示例#1
0
class MessageServer:
    """
    parent class of all the servers with messenger
    """
    def __init__(self, messenger_name):
        self.server_messenger = Messenger(messenger_name)

    def get_message(self):
        return self.server_messenger.get_message()

    def put_message(self, msg):
        self.server_messenger.put_message(msg)

    def send_message_content(self, content, target_message_server):
        self.server_messenger.send_message_content(
            content, target_message_server.server_messenger)

    def handle_message(self, msg):
        raise NotImplementedError('please implement function "handle_message"')
示例#2
0
class Daemon:
    """
    Application entry point. Initializes the application.

    :param python_version str: the current major python version
    """
    def __init__(self, python_version):
        self.python_version = python_version
        self.set_chrome_path()
        self.set_actions()
        self.messenger = Messenger(self.python_version)
        self.is_running = False

    def set_actions(self):
        """Defines the different messages from the addon that will be handled."""
        self.actions = {}
        self.actions[ACTIONS['VERSION']] = self.send_version
        self.actions[ACTIONS['COLORS']] = self.send_colorscheme
        self.actions[ACTIONS['CSS_ENABLE']] = self.send_enable_css_response
        self.actions[ACTIONS['CSS_DISABLE']] = self.send_disable_css_response

    def set_chrome_path(self):
        """Tries to set the path to the chrome directory."""
        self.chrome_path = custom_css.get_firefox_chrome_path()

    def check_chrome_path(self, action):
        """
        Checks if the path to the 'chrome' directory was found and sends a message if it was not.

        :return: if chrome_path is set
        :rType: bool
        """
        if not self.chrome_path:
            self.messenger.send_message(
                Message(action,
                        'Could not find path to chrome folder',
                        success=False))
            return False
        else:
            return True

    def check_target(self, message):
        """
        Checks if the message received specifies a target, or the message is invalid.

        :param message object: the decoded message
        :return: if message has key 'target' with a valid value
        :rType: bool
        """
        if 'target' in message and len(message['target']) > 0:
            return message['target']

        logging.error('%s: target was not specified' % message['action'])
        self.send_invalid_action()
        return False

    def send_version(self, message):
        """Sends the current daemon version to the addon."""
        self.messenger.send_message(Message(ACTIONS['VERSION'],
                                            DAEMON_VERSION))

    def send_colorscheme(self, message):
        """Sends the current colorscheme to the addon."""
        (success, data) = fetcher.get_colorscheme(PYWAL_COLORS_PATH,
                                                  BG_LIGHT_MODIFIER)
        self.messenger.send_message(
            Message(ACTIONS['COLORS'], data, success=success))

    def send_invalid_action(self):
        """Sends an action to the addon indicating that the action sent was invalid"""
        self.messenger.send_message(
            Message(ACTIONS['INVALID_ACTION'], {}, success=False))

    def send_output(self, message):
        """
        Sends an output message to the addon that will be displayed in the 'Debugging output' area.

        :param message str: the message to send to the addon
        """
        self.messenger.send_message(Message(ACTIONS['OUTPUT'], message))

    def send_enable_css_response(self, message):
        """
        Tries to enable a custom CSS file and sends the result to the addon.

        :param target string: the name of the CSS file to enable/disable
        """
        action = ACTIONS['CSS_ENABLE']
        target = self.check_target(message)
        if target is not False:
            if self.check_chrome_path(action):
                (success, message) = custom_css.enable_custom_css(
                    self.chrome_path, target)
                self.messenger.send_message(
                    Message(action, message, success=success))

    def send_disable_css_response(self, message):
        """
        Tries to disable a custom CSS file and sends the result to the addon.

        :param target string: the name of the CSS file to enable/disable
        """
        action = ACTIONS['CSS_DISABLE']
        target = self.check_target(message)
        if target is not False:
            if self.check_chrome_path(action):
                (success, message) = custom_css.disable_custom_css(
                    self.chrome_path, target)
                self.messenger.send_message(
                    Message(action, message, success=success))

    def handle_message(self, message):
        """
        Handles the incoming messages and does the appropriate action.

        :param message object: the decoded message
        """
        try:
            action = message['action']
            if action in self.actions:
                self.actions[action](message)
            else:
                logging.debug('%s: no such action' % action)
                self.send_invalid_action()
        except KeyError:
            logging.error('action was not defined')
            self.send_invalid_action()

    def socket_thread_worker(self):
        """The socket server thread worker."""
        while True:
            message = self.socket_server.get_message()
            if message == 'update':
                logging.debug('Update triggered from external script')
                self.send_colorscheme()

    def start_socket_server(self):
        """Starts the socket server and creates the socket thread."""
        success = self.socket_server.start()
        if success == True:
            if self.python_version == 3:
                # We use daemon=True so that the thread will exit when the daemon exits.
                # https://docs.python.org/2/library/threading.html#threading.Thread.daemon
                self.socket_thread = Thread(target=self.socket_thread_worker,
                                            daemon=True)
            else:
                self.socket_thread = Thread(target=self.socket_thread_worker)

            self.socket_thread.start()

    def start(self):
        """Starts the daemon and listens for incoming messages."""
        self.is_running = True
        try:
            while True:
                message = self.messenger.get_message()
                logging.debug('Received message from addon: %s' % message)
                self.handle_message(message)
        except KeyboardInterrupt:
            return

    def close(self):
        """Application cleanup."""
        self.socket_server.close()
        self.is_running = False
        logging.debug('Cleanup')