Writing Browser Extensions - Comparing Firefox, Chrome and Opera

MediaPlus is a browser extension that gives users more control over media elements like video, images, games, flash, etc by allowing them to move, resize, download, magnify and perform other actions on them.
Writing an extension for browsers is very similar to writing web pages that work across browsers - similar concepts but interesting quirks along the way; hence this post.

1. Background
MediaPlus started as a browser bookmarklet that injected some javascript into the current web page. This javascript was responsible for identifying various media elements like flash, images, etc and mark them as actionable. When the user needs to interact with a specific media content, they move the mouse over the media content and a panel with various actions shows up. This is the core functionality of MediaPlus.
In addition to the above functionality, MediaPlus also needs to provide interaction points to start, suspend or stop the plugin. All these actions are folded into the bookmarklet button on the browser.
As an browser extension for Firefox, Opera and Chrome, MediaPlus provides these extension points. This post deals with the similarities and differences in the extension system of the three browsers.
The comparison boxes below are color coded to indicate the parts I felt was best/easiest against worst/hardest.
 
For Firefox, the jetpack way of writing extensions was used. A browser extension for Safari is under development and I am still learning to write extensions for Internet Explorer; these would be possibly covered in future posts.

2. Parts of an extension - Concepts
The basic concepts of building an extension as very similar. 

Chrome looks to be inspired by Greasemonkey way of building things - just making the thing better. Opera is heavily influenced by W3C WidgetsFirefox Heavily borrows from commonjs, specifically the modules part. 
 Note that all the three browsers support userscripts, thanks to their architecture. 

 
2.1 Manifest File
All extensions start with a manifest file. This is the file that defines the basic behavior of the extension.

They are called package.json, config.xml and manifest.json in Firefox, Opera and Chrome respectively that define the name, version, description, author, icons, permissions and other meta-data about the extension. Though they are similar, Opera interestingly chooses XML over JSON.

2.2 Additions to Browser Interface
The manifest file also defines the different controls that the extension will add to to the Browser UI. This include things like Context Menu Items, Toolbar buttons and other panels.
For chrome, these are usually included statically in the manifest. Interface elements include context menus, URL bar plugins, menu items, etc. Opera seems to be better as they provide flexibility of adding browser interface elements during run-time. The interface is defined in index.html along with its actions for clicking the button, etc. Firefox is also similar to Opera where the browser interaction elements are specified in the main module. This allows more actions to be specified by the extension based on the page.

2.3 Content Scripts
The core of MediaPlus rests in the script that is injected into the page. This is called a content script or injected script.
Chrome is the simplest as Javascript and CSS can be inserted at any point using an API call.
Opera does not have a direct way to inject script and hence, AJAX requests are made to the extension to read the script content and then inject it dynamically as HTML content.Opera includes all scripts in the includes folder as a part of the page. This however means that injecting scripts dynamically become hard. 
Firefox provides page-mod that includes scripts. Injecting scripts into specific tabs with similar URLs using a page-mod is hard that forced MediaPlus to use the same mechanism employed in Opera where scripts were read and written with HTML tags. 

In all three browsers, content scripts do not share the run time with the page for security reasons. Extensions usually can do more (like access local file system, cross domain ajax etc) than a script inside a webpage and hence the security boundary.
2.4 Background Processes and Message Passing
A background page is a singleton javascript loaded once in the browser that is responsible for background operations and other house keeping activities. All the three browsers have this concept with different ways to pass messages between content scripts, browser interaction parts and the background script.

Chrome again provides the simplest model of message passing using simple APIs. Messages can be relayed between content scripts, background process and browser UI (panels, popups, etc.).
Messages are handled using simple message listeners. There are also concepts of long and short lived connections.
Opera strictly follows the W3C message passing mechanism with Channels. Though complex, this is more powerful, providing events "onconnect", to actually start listening to a specific channel.  Firefox seemed to be the most powerful with message passing had both channels and events. The best past of Firefox was the ability to add an event listener ("onMyMsg") to specific messages and just act on it, thus avoiding switch case.

3. Coding
Any standard HTML and Javascript editor can be used for creating these extensions.

Chrome has a dedicated developer dashboard that can be used to point to the extension directory. Making changes to code requires hitting a reload button on the "Manage Extensions" to ensure that the latest code is running.In case of Opera, the config.xml can simply be dropped onto the Opera Window (in developer mode) and the entire directory structure is picked up. Hitting the reload button is require here too.  Setting up the development environment for Firefox is the hardest given that Jetpack extensions are actually compiled to XPI. This also means that any change would mean compiling and reloading the extension - something not native to web developers.

The issue with Firefox may be attributed to the fact that Jetpack extensions are actually compiled to the XPI that Firefox understands.

4. Debugging
Once the extension is written, the ability to trace through the code and see log messages helps a log in Debugging.

Chrome here steals the show with its web developer toolbar. With a single interface, all parts of the extension including the background process, content script and browser UI can be debugged. The simple console.log prints all messages in the console. Injected Scripts in Opera can be debugged with breakpoints using Dragonfly. However,  I have noticed that tracing through background index.html or browser UIs seems hard. The opera.postError is required to post messages to the Opera Error console - and it does not live well with JSON. Possibly a result of its development experience, debugging in Firefox can be hard. However, I ensured that I always pointed to a profile directory that had Venkman and Firebug. This way, I could actually debug all parts of the extension. 

5. Publishing
Once the extension is ready, it needs to be published to a place where users can discover and download the extension. All the three browser have a store like interface where users can discover and download the extensions. In case of all three stores, screenshots, icons and videos have to be provided in specific dimensions as required by the stores.
The extension simply needs to be zipped and uploaded to the store.

The Chrome store seems to be the most mature of them.
There is also support for a payment system.
You extension needs to get approved before it is actually visible on the store.
The store is also one single place for apps, themes, etc. 
The OEX file (zip of extension files needs to be uploaded)
The Opera Store has a great/quick approval process too.
I have not seen the support for payments in the store.

The packaged XPI file is uploaded to the store.
Given that Firefox had extensions even before some of the other browsers existed, it has a great eco-system of extensions. 
Though they are no "payments", donations are supported for developers.


Auto-updating the extension when a new version is available is also great in all three browsers. All the three also provide support for hosting the extensions at places other their store with support for auto-update URLs.

5. Analytics
Post publication, a mechanism is needed to monitor the traffic and downloads to the extension.

The store page for Chrome is can be integrated with Google Analytics, providing it with great analytics.
Apart from traffic sources, downloads and weekly installs, with user comments are also available.
Analytics in Opera store is pretty basic. Ratings, download count and user comments are the only available features.
Download per

Though firefox is not integrated with any powerful analytics, it does provide details like visits and downloads per time. It seems to be an in house version of an analytics system.

6. Conclusion
To conclude, all the three browsers strive to provide and most powerful yet simple platforms for developing extensions. Though there are not standards (like for web pages), each browser tries their best to infer from existing ways of doing things.
Note that this article derive from my experiences of building MediaPlus and I may not have touched upon all aspects of extension writing.

You can download MediaPlus for your browsers from the following links.

http://nparashuram.com/projects/flashresizer.html


Edit: As people pointed out, the article deals only with building extensions for Firefox using Jetpack. You can build extensions without Jetpack, but that cannot be compared to what Opera and Chrome offer.