Beginner’s guide to writing a Firefox extension

Last week, I shared my hack for syncing my browsing between my computer and mobile. It’s built around a Firefox extension, so I thought I’d share my notes on how I got it to work.

screenshotThis post is a complete sample for creating a Firefox extension to add a button to the browser toolbar. When you click on the button, it grabs the URL from the Firefox address bar and does something with it.

I’ve gone through each file you need, explaining what it’s for and giving a sample ready for copy-and-pasting.

In my browser sync hack it sent the URL to my phone, but for this walkthrough I’m going with something simpler: opening the webpage in Internet Explorer. You can replace that bit of script with something more useful 🙂

I’m not an expert at this stuff by any means, and I found a lot of useful code snippets on mozilla.org to get me going. But this seems to work, and as people that I’ve shown my extension to so far seemed surprised at how easy it was, I thought it might be useful to share.

Apart from the Internet Explorer bit itself (which is a little Windows-specific), the rest of this should all work wherever Firefox does.

Step 1 – Prepare a development environment

Create a working directory where you will work on your extension.

Then create a text file in your Firefox extensions directory:
(e.g. C:\Documents and Settings\YourUserName\Application Data\Mozilla\Firefox\Profiles\YourFirefoxProfile\extensions\)

The file name should be named YourExtensionName@Your.Name
e.g. sendtoie@dale.lane

The file should contain the path where you put the working directory for your extension.

This is enough for Firefox to find your extension – although you will need to restart the browser every time you make a change.

Step 2 – chrome.manifest

Create a chrome.manifest file in your working directory where you will list the files we need for our extension

For example:

content sendtoie       content/
skin    sendtoie       classic/1.0      skin/
overlay chrome://browser/content/browser.xul    chrome://sendtoie/content/firefoxOverlay.xul
style   chrome://global/content/customizeToolbar.xul    chrome://sendtoie/skin/overlay.css

Step 3 – install.rdf

Create an install.rdf file in your working directory where you describe the extension – information that will be shown in the Firefox Add-ons dialog.

<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
 xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <Description about="urn:mozilla:install-manifest">
    <em:id>sendtoie@dale.lane</em:id>
    <em:name>Send to Internet Explorer</em:name>
    <em:version>0.1</em:version>
    <em:creator>Dale Lane</em:creator>
    <em:description>Send a webpage to Internet Explorer</em:description>
    <em:homepageURL>https://dalelane.co.uk/blog/</em:homepageURL>
    <em:iconURL>chrome://sendtoie/content/sendtoie.gif</em:iconURL>
    <em:targetApplication>
      <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
        <em:minVersion>2.0</em:minVersion>
        <em:maxVersion>3.0.*</em:maxVersion>
      </Description>
    </em:targetApplication>
  </Description>
</RDF>

Step 4 – content/firefoxOverlay.xul

Create a ‘content‘ sub-directory in your working directory and create a firefoxOverlay.xul file. This is where you specify that a button should be added to the toolbar and identify what function should be run when you click on it.

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://sendtoie/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://sendtoie/locale/sendtoie.dtd">
<overlay id="sendtoie-overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript" src="overlay.js"/>

  <toolbarpalette id="BrowserToolbarPalette">
     <toolbarbutton id="sendtoie-toolbar-button" 
        autoCheck="true"
        label="send page to IE"
        tooltiptext="Send current page to Internet Explorer"
        oncommand="SENDTOIE.onToolbarButtonCommand();"
        class="toolbarbutton-1 chromeclass-toolbar-additional"/>
  </toolbarpalette>
</overlay>

Step 5 – content/overlay.js

Still in the ‘content‘ sub-directory in your working directory, create an overlay.js file where you put the main Javascript implementation of your extension.

For this simple example, we use nsIProcess to invoke the Internet Explorer iexplore.exe process, passing it the URL from Firefox as an argument.

var SENDTOIE = {

    sendUrl : function() {

        var urlbar = document.getElementById('urlbar');

        if (urlbar) {
            // create an nsILocalFile for the executable
            var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
            file.initWithPath("C:\\Program Files\\Internet Explorer\\iexplore.exe");
            
            // create an nsIProcess
            var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
            process.init(file);
            
            // Run the process.
            // If first param is true, calling thread will be blocked until
            // called process terminates.
            // Second and third params are used to pass command-line arguments
            // to the process.
            var args = [urlbar.value];
            process.run(false, args, args.length);
        }
    },

    onToolbarButtonCommand : function(e) {
        SENDTOIE.sendUrl();
    },
};

Step 6 – skin/overlay.css

Create a ‘skin‘ sub-directory in your working directory and create an overlay.css file in there. This is where you specify the style for the button you are adding to the toolbar.

#sendtoie-toolbar-button
{
  list-style-image: url("chrome://sendtoie/skin/toolbar-button.png");
  -moz-image-region: rect(0px 24px 24px 0px);
}
#sendtoie-toolbar-button:hover
{
  -moz-image-region: rect(24px 24px 48px  0px);
}
[iconsize="small"] #sendtoie-toolbar-button
{
  -moz-image-region: rect( 0px 40px 16px 24px);
}
[iconsize="small"] #sendtoie-toolbar-button:hover
{
  -moz-image-region: rect(24px 40px 40px 24px);
}

Step 7 – skin/toolbar-button.png

Now for images. First, the icon that goes on the toolbar button goes in the ‘skin‘ directory.

You need at least four icons – one large icon, one large icon for when the mouse is hovering over it, one small icon, and one small icon for when the mouse is hovering over it.

You use one image file for all the images needed – the stylesheet in Step 6 identifies the coordinates of a section of the file to use for each image.

This is one of the images I created for a toolbar button in my syncing extension. (Sadly, drawing this is the bit that probably took me the longest of the whole hack!)

Step 8 – content/sendtoie.gif

The last quick step – you need an icon for the extension. This is the icon that will be shown the Firefox Add-ons dialog. I used this one, and put it in the ‘content‘ directory.

Step 9 – debug 🙂

Something probably went wrong, so you now get into a cycle of tweaking something, and restarting Firefox and retesting. You need to restart the browser to pick up any changes you make.

Once you are happy with it all, it’s time to package up your extension for sharing.

Delete the text file you added to the Firefox extensions directory in Step 1, and restart Firefox – you want a clean browser ready to test installing your real extension next.

Step 10 – preparing an xpi

Firefox extensions are distributed as .xpi files. This is just a zip file, renamed to have a xpi extension.

Zip up your working directory and give it a name that ends in .xpi. You can make this available as an installer for your extension for other Firefox users.

All done. 🙂

Tags: , ,

3 Responses to “Beginner’s guide to writing a Firefox extension”

  1. Kami says:

    Thanks! Very helpful guidance.

  2. SM says:

    I followed all the steps described by you. The extension get’s installed, but for some reason, the toolbar button does not show up in the “Customize Toolbar” dialog. Can you think of a reason why this is happening? I got the same results after reading https://developer.mozilla.org/en/Custom_Toolbar_Button.
    Thanks!

  3. dale says:

    @SM – Sorry, I can’t think of any reasons why this would happen. 🙁