Team LiB
Previous Section Next Section

Hack 95. Make Extensions Work Outside Firefox

Extensions are designed for Firefox, but sometimes you can use them elsewhere.

Individuals might move nimbly to Firefox, but organizations can take far longer. Some folks out there are still trying to escape Netscape 4.0 or Internet Explorer 5.0. A typical slow upgrade path is Netscape 4.xMozilla Application Suite 1.x (classic theme)Firefox. You don't have to wait for Firefox to start benefiting from extensions, though. A significant number of extensions also work with the Mozilla Application Suite (MAS) and possibly in other tools as well.

In principle, you can design an extension [Hack #84] to install on all Mozilla-based applications. In practice, the extra development effort required to provide portability discourages most extension creators.

9.6.1. Porting Extensions to Thunderbird and NVu

Thunderbird and NVu use the same extension-management system as Firefox. Because they are not browser products and because extensions typically integrate closely with Firefox's XUL interface, most extensions are unlikely to be portable. Extensions that hang off the Firefox Tools menu and extensions that act as independent mini-applications (such as calculators, games, and accessories) have some chance of successful integration. They might possibly hang off the Thunderbird Tasks menu.

9.6.1.1 Changing the target application

The first step required for that integration is to hack the install.rdf file that's supplied in the extensions installable .xpi file. In particular, Firefox extensions contain this RDF:

<em:targetApplication>
  <Description>
    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
    <em:minVersion>0.7</em:minVersion>
    <em:maxVersion>1.2</em:maxVersion>
  </Description>          
</em:targetApplication>

To modify this RDF for Thunderbird, change the targetApplication to this ID:

<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>

9.6.1.2 Changing overlay destinations

The XUL content that the extension adds to the application has to fit with the application's DOM structure. Usually, such extensions are bottom-up overlays [Hack #87], so finding the right integration point is critical.

For Thunderbird, the Tasks menu overlay target is ultimately located in the main window, which is called messageWindow.xul. The ID of the <menupopup> used for the Tasks menu is taskPopup. It's defined in mailWindowOverlay.xul.

To make this change, rip the contents.rdf file out of the extensions JAR archive that's inside the .xpi bundle. Add something like this:

<!-- overlay information -->
  <RDF:Seq about="urn:mozilla:overlays">
    <RDF:li resource="chrome://messenger/content/messenger.xul"/>
</RDF:Seq>

<!-- messenger items for Messenger -->
<RDF:Seq about="chrome://messenger/content/messenger.xul">
  <RDF:li>chrome://myexample/content/toolsOverlay.xul</RDF:li>
</RDF:Seq>

In this case, the myexample package is the basis of the extension.

9.6.1.3 Changing overlay content

Finally, edit the toolsOverlay.xul file and hack the <menupopup> ID to read taskPopup instead of menu_ToolsPopup (the Firefox alternative). Rebundle, install, and see what happens.

9.6.2. Back-Porting Extensions to the MAS

Back-porting extensions to the MAS is a far easier task than moving extensions between applications. The browser in the MAS and the Firefox browser have a degree of similarity in their internal structures. Furthermore, MAS has no extension registration mechanism (at least it has none in Versions 1.7 and earlier). That means it totally ignores the install.rdf file supplied inside an extension's .xpi. So, that part can be ignored, but there are other steps to which you must attend.

9.6.2.1 Making multiple-application overlays

Here's an example of the overlay information for the Diggler extension. This extension supports both MAS and Firefox, at least as recently as its 0.9 version (despite the creator's protestations). It works by duplicating overlay information, but relies on the fact that the overlay target (a tag id) is the same for both products:

<RDF:Seq about="urn:mozilla:overlays">
  <!-- Firefox -->
  <RDF:li resource="chrome://browser/content/browser.xul"/>
  <!-- Mozilla Application Suite -->
  <RDF:li resource="chrome://navigator/content/navigator.xul"/>
</RDF:Seq>

<!-- Firefox -->
<RDF:Seq about="chrome://browser/content/browser.xul">
  <RDF:li>chrome://diggler/content/digglerOverlay.xul</RDF:li>
</RDF:Seq>

<!-- Mozilla Application Suite -->
<RDF:Seq about="chrome://navigator/content/navigator.xul">
  <RDF:li>chrome://diggler/content/digglerOverlay.xul</RDF:li>
</RDF:Seq>

There are support files inside the extension for both MAS-style preference menus and for Firefox-style Options menus. Unzip the Diggler .xpi file and poke around inside to see how it's done.

9.6.2.2 Delivering backward compatibility for extensions

This piece of web page JavaScript is standard for recent versions of MAS and Firefox:

onclick="triggerURL('url');"

This special function, available only in recent Mozilla-based browsers, causes the XPInstall subsystem to fire up. It downloads the provided URL, expecting that it will be an installable .xpi file. Older versions of MAS (such as the stable 1.4 release) don't have this functionality. They use this instead:

onclick="InstallTrigger.install( { "myextension" : "url" } );

The most general solution is to get the server settings right [Hack #27] and to serve up the extension as a raw file:

<a href="http://www.example.com/myextension/myextension.xpi">Get it here</a>

If that's not possible, the web page must sniff the browser's exact version and use an XPInstall trigger call that matches it.

    Team LiB
    Previous Section Next Section