.. _gui-plugins: Plugins ####### .. module:: bip.gui Bip has it own systems of plugins refered as :class:`BipPlugin`. All plugins should inherit of the :class:`BipPlugin` class. It is still possible to use bip in classic IDA plugin, however the gui part of Bip is mostly link to :class:`BipPlugin`. A plugin is made for being load by the :class:`~bip.gui.pluginmanager.BipPluginManager` and will be instantiated only once. Once loaded it is possible to get the plugin instance through the :class:`~bip.gui.pluginmanager.BipPluginManager` object: ``get_plugin_manager()["PLUGINNAME"]`` . A typicall implementation of a plugin will: * surcharge the :meth:`~BipPlugin.to_load` classmethod for checking if the plugin should be loaded. * surcharge the :meth:`~BipPlugin.load` method for making actions when it it loaded in IDA. * use some `activity decorators`_ for declaring actions. For example of a plugin you can check the :ref:`general-overview` or look at the printk plugin. .. _gui-plugin-internals: Implementation internals ======================== This part as the goal to describe the internal of the :class:`BipPlugin`: how are they loaded by the :class:`~bip.gui.pluginmanager.BipPluginManager` and how the interface with :class:`BipActivity`. It is not necessary to read it for using them or writing one. Loading of the plugins ---------------------- :class:`BipPlugin` are made for being loaded by the :class:`~bip.gui.pluginmanager.BipPluginManager`. :class:`BipPlugin` present in a particular directory (``bipplugin`` by default) will be loaded automatically by the :class:`~bip.gui.pluginmanager.BipPluginManager`. For doing this, the :class:`~bip.gui.pluginmanager.BipPluginManager` will search for all ``.py`` files present in the ``bipplugin`` directory and will search for classes which inherit from the :class:`BipPlugin` class. When the :class:`~bip.gui.pluginmanager.BipPluginManager` is loaded by IDA it will load all the plugins which has been found (this is done in the :meth:`~bip.gui.pluginmanager.BipPluginManager.init` method). It is also possible to load :class:`BipPlugin` "by hand" using the :meth:`~bip.gui.pluginmanager.BipPluginManager.addld_plugin` method. If this is done before the :class:`~bip.gui.pluginmanager.BipPluginManager` is loaded by IDA, it will load the plugin later: the same way it is done for the ones in the ``bipplugin`` directory. If the :class:`~bip.gui.pluginmanager.BipPluginManager` is already loaded, the plugin will be loaded immediately. When a :class:`BipPlugin` is loaded the following actions are made: 1. The attributes of the class are check for objects which inherit from the :class:`BipActivity` class and are stored in a ``_attributes`` list of the object (done by the :class:`BipPlugin` constructor, implemented in the :meth:`BipPlugin._init_activities` method). 2. The class method :meth:`BipPlugin.to_load` will be called: if it returns ``False`` the plugin will not be loaded, if it return ``True`` the manager continue its steps (done by :class:`~bip.gui.pluginmanager.BipPluginManager`). 3. The :class:`BipPlugin` object is then created and the constructor will try to register its :class:`BipActivity` (see `Registering activities`_). 4. The plugin is added in the list of instance maintain by the :class:`~bip.gui.pluginmanager.BipPluginManager`. 5. Finally the :meth:`BipPlugin.load` method will be called (done by the :class:`~bip.gui.pluginmanager.BipPluginManager`). It is important to note that if the :class:`~bip.gui.pluginmanager.BipPluginManager` has already been init by IDA this will all be made directly through the :meth:`~bip.gui.pluginmanager.BipPluginManager.addld_plugin` method, but if the :class:`~bip.gui.pluginmanager.BipPluginManager` has not yet been loaded the plugin will be loaded later. It is possible to use the :meth:`~bip.gui.pluginmanager.BipPluginManager.is_ready` to check if the :class:`BipPluginManager` has initialized and as loaded its plugins. .. note:: **Several loading of python scripts** :class:`BipPlugin` should be loaded only once, it is important for not having problems with activities (see `Registering activities`_) and to keep a unique reference to the actual object. However python files in the ``plugins`` directory are actually loaded twice by IDA which creates problem with the design explain before. Registering activities ---------------------- When a :class:`BipPlugin` is created the :class:`BipActivity` which are used must be registered. All :class:`BipPlugin` will be instantiated by the :class:`BipPluginManager` through the method :meth:`~BipPluginManager.load_all` or :meth:`~BipPluginManager.load_one`. Those methods will called the class method :class:`BipPlugin.to_load` of the :class:`BipPlugin` and if it returned true the constructor will be called follow by the :meth:`BipPlugin.load` method. When a plugin is instantiated, the :meth:`~BipPlugin.__init__` constructor will call the :meth:`~BipPlugin._init_activities` which will create a dict of all the :class:`BipActivity` objects define for the object and its class. Then the method :meth:`~BipPlugin._provide_plg_activities` will provide to the :class:`BipActivity` object the plugin in itself. Once the :class:`BipPlugin` is instantiated, the :meth:`BipPlugin.load` method will be called. This method will call :meth:`~BipPlugin._register_activities` which will take the dict of :class:`BipActivity` and for each one call its :meth:`~BipActivity.register` method. BipPlugin API ============= .. autoclass:: BipPlugin :members: :member-order: bysource :special-members: :private-members: .. _gui-plugin-activity-decorators: Activity decorators =================== Here is an overview of the currently available decorators, for more information on how they work see :ref:`gui-activity-actions`: =================== =================================================================== ========================================= Decorator Name Description Usage example =================== =================================================================== ========================================= :func:`shortcut` Register a "hot-key" which will call the function when triggered. ``@shortcut("Ctrl-H")`` :func:`menu` Register an entry in a menu in IDA. ``@menu("Edit/Plugins/", "PRINTNAME")`` =================== =================================================================== ========================================= .. autofunction:: shortcut .. autofunction:: menu