Automatic Firefox Extension Updates

Firefox extension developers probably already know that by providing an extension at the official Firefox Add-ons website, you get automatic updates for free. But suppose you want to host your extension on your own website? How does one go about adding automatic update support? This article aims to answer that question.

Signing Your Extension

Beginning with Firefox 3, all extension updates are required to be provided on a secure channel. Since we want to host our extension on our own website, we have two options:

  1. Provide updates on a secure (https) connection
  2. Digitally sign the extension

We’re going to ignore the first option since, in most cases, it costs money (you usually have to purchase an SSL certificate and have a static IP address). Digitally signing an extension is free, fairly easy, and quick to do. So let’s learn how to do that!

Creating a Public-Private Key Pair

The first step in signing our extension is to create a public-private key pair. Mozilla provides the McCoy tool to do just this. It’s not the most straightforward tool in the world, so here’s a walkthrough of how to get it up and running:

  1. Visit the McCoy website, and download the appropriate package (they provide downloads for Windows, Linux, and Mac OS X).
  2. Extract the package to a folder of your choice.
  3. Run the McCoy executable. The first time you run this tool, it will ask you to create a master password to protect your keys. Creating a master password is highly recommended! Each subsequent time you run McCoy, it will ask you to enter this password.
  4. Once the McCoy application is running, select the Keys » Create New Key menu item. Provide a descriptive name for your key and click OK. Note that if you plan on providing multiple extensions on your website, you only need one key.

Now that we have created our key pair, we need to update our extension’s installer manifest.

Updating the Install Manifest

It is assumed that you are already familiar with installer manifests, so we will not spend time on explaining their contents (if you aren’t familiar with them, read up on the subject). I will use the installer manifest created in my Toolbar Tutorial as an example for this article. The original manifest is shown below:

<?xml version="1.0"?>

<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>tuttoolbar@borngeek.com</em:id>
        <em:name>Tutorial Toolbar</em:name>
        <em:type>2</em:type>
        <em:version>1.0</em:version>

        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>4.0</em:minVersion>
                <em:maxVersion>30.*</em:maxVersion>
            </Description>
        </em:targetApplication>

        <em:creator>Jonah Bishop</em:creator>
        <em:description>An example toolbar extension.</em:description>
        <em:homepageURL>http://www.borngeek.com/firefox/</em:homepageURL>

    </Description>
</RDF>

We need to add two elements to this manifest: the em:updateURL and em:updateKey elements. The em:updateURL element simply provides a URL to your update manifest file. It looks like the following:

<em:updateURL>http://www.example.com/update.rdf</em:updateURL>

Also note that the official Firefox add-ons website will not accept extensions with an em:updateURL element in the installer manifest.

Next up is the em:updateKey element. It simply contains the public key portion of your public-private key pair. To obtain your public key pair, simply open McCoy, right click on the key you created earlier, and select the Copy Public Key menu item. Then place the copied value between an open and close em:updateKey element tag. Here’s an example:

<em:updateKey>
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb
KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP
z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc
G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB
</em:updateKey>

Looks like a bunch of gobbledygook, huh? Thankfully, Firefox is smart and allows you to put white space in your em:updateKey elements to make it look a little cleaner in your install manifest (as I’ve done above). By default, the copied value from McCoy will just be one long string. After adding these two elements, our resulting installer manifest will look like this (I’ve highlighted the added portions below):

<?xml version="1.0"?>

<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>tuttoolbar@borngeek.com</em:id>
        <em:name>Tutorial Toolbar</em:name>
        <em:type>2</em:type>
        <em:version>1.0</em:version>

        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>4.0</em:minVersion>
                <em:maxVersion>30.*</em:maxVersion>
            </Description>
        </em:targetApplication>

        <em:creator>Jonah Bishop</em:creator>
        <em:description>An example toolbar extension.</em:description>
        <em:homepageURL>http://www.borngeek.com/firefox/</em:homepageURL>

        <em:updateURL>http://www.example.com/update.rdf</em:updateURL>

        <em:updateKey>
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW8qxAeURIMLnHjb
        KrjR/uqnRsiomahNArMh3KqRLDDmRGCoO21fyHyh5kdgiEL+2Q+sNP
        z+j5maIG4qePXp7BVp90QMqiGLvl+z4baDOqcNvErN0l8scd8EegXc
        G7Ofa5Gc5oEU/gItIVR4k9AICyW2pJhe51UPa3UKXDS0v3TwIDAQAB
        </em:updateKey>

    </Description>
</RDF>

We’re done updating our extension’s installer manifest! Note that the steps we’ve just taken only need to be done once. Once you’ve added these items, you won’t need to change them again (unless your update manifest URL changes or you decide to use a new key). You can now package up your extension for distribution, just like you’ve always done.

Creating an Update Manifest

Now that we’ve changed things on the extension side, it’s time to create our update manifest. This file will live on our web server, and is how people who use your extension ‘check in’ to see if there’s a new version available. Let’s start by looking at the final product we’ll be creating (all of the highlighted sections are things you will need to edit):

<?xml version="1.0"?>
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns="http://www.mozilla.org/2004/em-rdf#">

<r:Description about="urn:mozilla:extension:tuttoolbar@borngeek.com">
    <updates>
    <r:Seq>
    <r:li>
    <r:Description>
        <version>1.0.2</version>
        <targetApplication>
            <r:Description>
            <id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</id>
            <minVersion>4.0</minVersion>
            <maxVersion>30.*</maxVersion>
            <updateLink>http://www.example.com/downloads/tuttoolbar_1_0_2.xpi</updateLink>
            <updateHash>
            sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502
            </updateHash>
            </r:Description>
        </targetApplication>
    </r:Description>
    </r:li>
    </r:Seq>
    </updates>
</r:Description>

</r:RDF>

Let’s quickly go line by line and discuss what’s going on. First we have the standard XML boiler plate, followed by an r:RDF element, specifying that this is an RDF (Resource Description Framework) file. The main item of interest is the r:Description element. You will have one of these, along with all its sub-elements, for each extension you plan on listing in your update manifest. The first custom value we must provide happens to occur in this element’s about attribute. The urn:mozilla:extension portion is boilerplate, but it’s followed by our extension’s GUID (globally unique identifier). In this example, the GUID is tuttoolbar@borngeek.com. Note that if your GUID does not use the email-style formatting, (e.g. it looks something like d4373b50-43b3-11de-8a39-0800200c9a66), you will need to wrap it in curly braces ‘{}’.

Following a bunch of child elements (updates, r:Seq, r:li, and another r:Description), we come to the next element of interest: version. This is the version of your extension which, in our example, is 1.0.2.

Next up is some information about our target application (Firefox). We have a targetApplication element, followed by yet another r:Description element, and then the all-important id element. The value within the id element is the GUID for Firefox. This value will always be the same. This is followed by the familiar looking minVersion and maxVersion elements, which specify the minimum and maximum versions of Firefox that this extension supports. It’s very important that these values match the values in your extension’s installer manifest.

The updateLink element is next, and is where you specify the URL to your extension. Make sure the URL you provide here points to the appropriate file, especially if you also provide downloads for older versions of your extensions.

Finally, comes the updateHash element. This element holds either a sha1, sha256, sha384, or sha512 hash of your extension’s XPI file. I personally use sha256, since there were initially some backwards-compatibility issues with sha384 and sha512 (see bug 383390 for more info). If you’re on a Linux box, you should have the tools necessary to create these hashes. On a Windows box, you can get the appropriate programs (sha256sum is the name of the executable I use) via Cygwin. To get the hash value, you issue a command like the following from the directory where your XPI file lives:

sha256sum tuttoolbar_1_0_2.xpi

The output looks like the following:

c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502 *tuttoolbar.xpi

The hex string (everything before the space) is what you insert into your updateHash element, preceded by the type of SHA hash you used and a colon. Again, from our example:

<updateHash>
sha256:c22ad513c1243959a6d8e6b3cfad18a2a9141306f0165da6b05b008b2042e502
</updateHash>

To wrap things up, we close all our open elements, and we’re done. Save this file as your development manifest! I personally use the filename update.rdf.dev. Why save a development version? Because when we sign our update manifest, the contents of this file will be blown away (actually, things are substantially rearranged)! Saving a development version of this file will save you a lot of frustration in the long run. You always update your development version first, and sign a copy of it second.

Signing the Update Manifest

To sign your update manifest, follow these easy steps:

  1. Copy your development version of your update manifest, and name this copy update.rdf. This is the file we will be signing.
  2. If it’s not already open, start up McCoy.
  3. Once McCoy is open, select the key you created earlier, and select the Update » Sign Update Manifest menu item.
  4. Select the update.rdf file that we just created from the file chooser dialog, and click the “Open” button.

It will appear that nothing happened, but something did! This is one beef I have with McCoy; it doesn’t tell you that anything has been done. But if you open your update manifest, you’ll notice that it’s been modified. At this point, all our work is done. It’s now time to upload our files to our web server.

Hosting an Update Manifest

Before we get to uploading files, we need to make sure our web site is set up to serve XPI and RDF files. On Apache servers, this can be done through some rules in a .htaccess file (I don’t know off the top of my head how it works on IIS or TomCat servers; so be warned that the following information applies to Apache servers only). I typically put these rules in the .htaccess file at the root of my site, in case I ever move my XPI or RDF files around. Here are the rules to add:

AddType application/x-xpinstall .xpi
AddType text/xml .rdf

These rules essentially specify the MIME types to serve for these file extensions. This is an important step! Otherwise, your extensions won’t install properly, and automatic updates won’t work either. Also note that if your website is using a content management system like WordPress, you’ll want to place these rules at the top of the .htaccess file, just as a precaution.

Now that we have those rules set up, we can upload the extension XPI file and our update manifest to their appropriate locations. The update manifest must be placed in the location you specified in your extension’s installer manifest, and the extension must be uploaded to the location specified in your update manifest. Otherwise, automatic updates won’t work as expected.

And that’s all there is to it! Although there are some hoops you have to jump through, this process is fairly easy to implement. Happy extending!