2 November 2012

Browser plugin development using Firebreath

FireBreath is a framework that allows easy creation of powerful browser plugins. A plugin built on FireBreath works as an NPAPI plugin or as an ActiveX control (windows only) and support could be added for other plugin types built in C++ as well. Check out the complete firebreath features here.

First download firebreath either by downloading the stable version or by cloning recent project from git repository. Check out the firebreath download link for more details.

After downloading/extracting into a folder, you are ready to develop browser plugin.Firebreath provides a plugin generator python script called fbgen.py. This scripts requires Python 2.5, 2.6, 2.7 or 3.2.3. Now you can generate your new plugin project by executing this script by -
> python2.7 fbgen.py
This will ask for the details of your plugin and then generate a project based on that. The details asked are -
  • Plugin Name [] : This is the human readable name of your plugin that will be used in the strings.
  • Plugin Identifier [] : This is the code friendly identifier that will be used to name classes, project directory etc. 
  • Plugin Prefix [] : The plugin prefix is used to generate project names in visual studio. 
  • Plugin Mime Type [] : The mime type that you'll use with the object tag to embed your plugin into the web page. 
  • Plugin Description [] :  A human readable description of the plugin that will go in the strings resource that is compiled into the plugin; It will be visible in the plugin navigator on NPAPI based browsers. 
  • Plugin has no UI [false] : Set to true if you do not plan to do any drawing with your plugin.
  • Company Name [] : This is used for copyright notices in the resource strings. 
  • CompanyIdentifier [] : This is used to generate ActiveX PROGID and a few other things in the plugin config.
  • Company Domain [] : This is needed to create a unique id for the mozilla plugin, which is of the form "@[company domain]/[plugin id]". The default is generated from the company id.
 fbgen.py takes the provided information and generates a project in the <firebreath>/projects directory. You can copy this project folder to any other required place. The important files which were created are as follows:
  • PluginConfig.cmake - Configuration options from this file are used to generate other files that are critical to your plugin configuration.
  • CMakeLists.txt - It is the main config file for generating the project. 
  • Factory.cpp - This contains a subclass of FactoryBase for your plugin. The method that is called by Firebreath to create the main plugin object is in here, as are the global init and deinit functions. The default behaviour is to create a [YourProjectID] object and call plugins StaticInitialize() and StaticDeinitialize() for the global init and deinit.
  • <PluginIdentifier>(.cpp | .h) - This is essentially the main entry-point for the project. Any time someone puts an object tag on a page with your plugin, this object gets initialized. It has a window from which it gets events and which can draw for it and it has an API which handles javascript calls. createJSAPI method creates the JSAPI that will be seen by javascript when it accesses the object.
  • <PluginIdentifier>API(.cpp | .h) - This is the default "API" class. Think of it as a javascript object when you access your plugin from javascript. You can add methods and functions, deal with and return arrays and javascript objects, and even return other API objects with their own methods and properties.
  • Win/projectDef.cmake -  This is the other half of the project definition started in 'CMakeLists.txt', which deals specifically with windows. Similarly, there are files for Mac and X11.
  • Win/np_winmain.cpp - This provides the main entrypoints for NPAPI. 
  • Win/dllmain.cpp - This provides the dllmain entrypoint of your DLL.
After generating your project, move the project folder to a desired location and create a build folder for the project. Now you can use the platform specific project generation script, to generate the project in build folder.
Firebreath provides automatic project development scripts for most platforms. These are prep scripts and some them are as follows - 
  • prep20xx.cmd - Generates visual studio projects (prep2010.cmd for visual studio 2010)
  • prep2010x64.cmd - Generates visual studio projects for a 64 bit build.
  • prepmac.sh  - Generates XCode project on Mac.
  • prepcodeblocks.sh - Generates CodeBlocks Project.
  • prepeclipse.sh - Generates Eclipse project.
  • prepmake.sh - Make based build.
Usage: prepXXX <project dir> <build dir> [params]

This project will generate a project of desired type in specified build directory. You can build this project to generate a browser plugin. You can proceed plugin development on this project.

After compilation of the project, it will generate the plugin in "<Build Dir>/bin/<ProjectName>/<Debug/Release>". You can register this plugin in browser by copying it in default browser plugin folder. To test your plugin, you can use the htm file generated in "<Build-Dir>/projects/<ProjectName>/gen/FBControl.htm".

Firebreath comes with a few 3dparty libraries which can be attached to the project as when needed. Boost is used by default in the project. If you want to add logging to your project, you can use log4cplus library into your project. To add it to your project. Go to the PluginConfig.cmake file of your project and add this line  -

To add any boost library to the firebreath project, you can add following line to the PluginConfig.cmake file -
E.g. - add_boost_library(filesystem), add_boost_library(thread), add_boost_library(signals)

To use some other version of boost library apart from the one which comes with firebreath, you can build the boost library externally and add it with the prep command.
 C:\>prepxxx.cmd <project-location> <build-location> "-DWITH_SYSTEM_BOOST=ON" "-DBoost_USE_STATIC_LIBS=ON" "-DBOOST_ROOT='<Boost-Library-Location>'" "-DBoost_DEBUG=OFF" "-DCMAKE_BUILD_TYPE=Debug"

Note - Make sure that your build location doesn't contain any previous project build before executing the above command.

 After this, run the prepXXX <project dir> <build dir> command again.
Now add following lines to the Factory.cpp class -
void getLoggingMethods( FB::Log::LogMethodList& outMethods )
        // The next line will enable logging to the console (think: printf).
        outMethods.push_back(std::make_pair(FB::Log::LogMethod_Console, std::string()));

        // The next line will enable logging to a logfile.
        outMethods.push_back(std::make_pair(FB::Log::LogMethod_File, "C:\\log.txt"));

        // Obviously, if you use both lines, you will get output on both sinks.

This function specifies the log file location. Now you can log to your file by using macros FBLOG_INFO(src, msg), FBLOG_TRACE(src, msg), FBLOG_DEBUG(src, msg), FBLOG_WARN(src, msg), FBLOG_ERROR(src, msg), FBLOG_FATAL(src, msg)

The most difficult part of plugin development is debugging. Its not as simple as application development. As you can take a look at firebreath's link for debugging http://www.firebreath.org/display/documentation/Debugging+Plugins, it requires a bit of setup before you can start with full fledged debugging. For simple break point debugging, I use google chrome with plugin startup dialog. This helps me to attach process to the plugin while it waits for the plugin to start. Follow the given steps to add breakpoints and debug your plugin on windows using visual studio.
1. Build your plugin in visual studio.
2. Now go to the command promt in windows and start google chrome executable with the flag --plugin-startup-dialog. Google chrome executable is mostly present in your "<Home-Folder>/AppData/Local/Google/Chrome/Application/chrome.exe". With the command also give the url to open as your plugin testing html page e.g. FBControl.htm. So your command would look something like this -
C:\> <Home-Folder>/AppData/Local/Google/Chrome/Application/chrome.exe --plugin-startup-dialog <Html-Location>/FBControl.htm 
 3. This command will start chrome and popup a process id for your plugin(Don't press ok button in the process id dialog). Go to visual studio and click on Debug>Attach to process...
4. Now a dialog will appear with list of processes. Attach your process to the process id provided by chrome.
5. After attaching the process, go to chrome and click Ok button of the process id dialog. This will start the plugin process and your execution will stop at the breakpoint provided in visual studio.

This debugging process might not work directly on all browsers. You just have to configure them as specified in this link - http://www.firebreath.org/display/documentation/Debugging+Plugins.

1 comment:

  1. For newer versions of chrome if just "--plugin-startup-dialog" does not work use

    " --plugin-startup-dialog --wait-for-debugger"