Extension Versioning, Update and Compatibility

 

Add-on Versioning

Add-ons should specify their versions using the Toolkit version format. As a rough overview this is a version string split by periods, some examples:

  • 2.0
  • 1.0b1
  • 3.0pre1
  • 5.0.1.2
Note: Before Firefox 1.5 the more basic Firefox Version Format was used: major.minor.release.build[+] where only digits were allowed. The toolkit version format supports the Firefox version format but allows greater flexibility.

How Applications Determine Compatibility

When installing add-ons applications look at the targetApplication entries in the add-on's install.rdf. An entry must exist with an ID matching the ID of the application. Additionally the minVersion and maxVersion of this entry must be a range that includes the version of the running application.

If the application has a targetApplication entry but it is for an incompatible version then the application will retrieve updated compatibility information from the add-on's updateURL.

If the install.rdf contains any targetPlatform entries then the platform of the currently running application must be listed or the installation will be rejected.

Firefox 3 note

In applications based on Gecko 1.9 you can also use a targetApplication entry with an id toolkit@mozilla.org and minVersion and maxVersion that match the toolkit version of the running application. This allows you to say that your add-on will install into any toolkit based application.

Overriding Compatibility Checking

For testing purposes you can tell the application to somewhat ignore compatibility checks when installing add-ons. Simply create the boolean preference extensions.checkCompatibility and set it to false.

Note: Before Firefox 1.5 the preference app.extensions.version could be used to override the version that the application believed itself to be to allow normally incompatible extensions to install.

Choosing minVersion and maxVersion

minVersion and maxVersion should specify the range of versions of the application you have tested with. In particular you should never specify a maxVersion that is larger than the currently available version of the application since you do not know what API and UI changes are just around the corner. With compatibility updating it is not necessary to release a whole new version of the extension just to increase its maxVersion.

For the maxVersion it is generally permissible to use a * in place of the minor version of the application you support, for example 2.0.0.* would mean that you support any minor update to version 2 of the application. The application will usually suggest to extension authors which version part it is sensible to do this with.

Do not mistakenly think that * in a version represents any version. The * actually represents an infinitely high number and so is really only sensibly used in the maxVersion. Using it in a minVersion usually doesn't produce the effect you want.

Valid Application Versions

 

Automatic Add-on Update Checking

Applications will periodically check for updates to installed add-ons by retrieving the updateURL. The information returned can be used to notify the user of an updated version to the add-on as well as inform the application of new application versions that the add-on is compatible with.

Note: Starting in Gecko 2.0, the automatic add-on update process properly supports cases in which the add-on's GUID changes by uninstalling the old version and then installing the new one. Previously, it was possible to wind up with two copies of the same add-on installed.

Compatibility Updates

During the automatic update checks, applications look for both new versions and updated compatibility information about the currently installed version of an add-on. This means that if your update manifest contains an entry for the currently installed version of the add-on, and the entry's targetApplication entry specifies a larger maxVersion then the application will use this value instead of that specified in the add-on's install.rdf. This can cause add-ons that are disabled for being incompatible to become enabled and add-ons that would normally not install to be installed.

Update RDF Format

If you host your add-on's updateURL yourself then you will need to return the add-on version information in an RDF format. Below is an example update manifest. It lists information about 2 different versions of the extension with id foobar@developer.mozilla.org. The versions included are 2.2 and 2.5, both of which specify compatibility with Firefox versions 1.5 to 2.0.0.*. For version 2.2 an https update link is used while version 2.5 has a regular http link with a hash to verify the file retrieved.

It is important to get the initial RDF:Description's about attribute correct. It varies depending on what type of add-on you are providing information for:

  • For an extension or plugin bundle it must be urn:mozilla:extension:<id>
  • For a theme it must be urn:mozilla:theme:<id>
  • For any other type of add-on it must be urn:mozilla:item:<id>
Note: Prior to Gecko 2.0 (Firefox 4.0), the ordering of the versions within the <RDF:Seq> is significant.  For later versions, the compatible add-on version with the greatest version string will be used by the client for automatic updates.  The behavior depends on the version of the client application, of course.
<?xml version="1.0" encoding="UTF-8"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <!-- This Description resource includes all the update and compatibility information for
       a single add-on with the id foobar@developer.mozilla.org. You can list multiple
       add-ons information in the same RDF file. -->
  <RDF:Description about="urn:mozilla:extension:foobar@developer.mozilla.org">
    <em:updates>
      <RDF:Seq>
        <!-- Each li is a different version of the same add-on -->
        <RDF:li>
          <RDF:Description>
            <em:version>2.2</em:version> <!-- This is the version number of the add-on -->
            <!-- One targetApplication for each application the add-on is compatible with -->
            <em:targetApplication>
              <RDF:Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>1.5</em:minVersion>
                <em:maxVersion>2.0.0.*</em:maxVersion>
                <!-- This is where this version of the add-on will be downloaded from -->
                <em:updateLink>https://www.mysite.com/foobar2.2.xpi</em:updateLink>
                <!-- A page describing what is new in this updated version -->
                <em:updateInfoURL>http://www.mysite.com/updateinfo2.2.xhtml</em:updateInfoURL>
              </RDF:Description>
            </em:targetApplication>
          </RDF:Description>
        </RDF:li>
        <RDF:li>
          <RDF:Description>
            <em:version>2.5</em:version>
            <em:targetApplication>
              <RDF:Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>1.5</em:minVersion>
                <em:maxVersion>2.0.0.*</em:maxVersion>
                <em:updateLink>http://www.mysite.com/foobar2.5.xpi</em:updateLink>
                <em:updateHash>sha256:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e64ad2e3a0b60120ca271ce6e6</em:updateHash>
              </RDF:Description>
            </em:targetApplication>
          </RDF:Description>
        </RDF:li>
      </RDF:Seq>
    </em:updates>
    <!-- A signature is only necessary if your add-on includes an updateKey
         in its install.rdf. -->
    <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAMO1O2gwSCCth1GwYMgscfaNakpN40PJfOWt
                  ub2HVdg8+OXMciF8d/9eVWm8eH/IxuxyZlmRZTs3O5tv9eWAY5uBCtqDf1WgTsGk
                  jrgZow1fITkZI7w0//C8eKdMLAtGueGfNs2IlTd5P/0KH/hf1rPc1wUqEqKCd4+L
                  BcVq13ad</em:signature>
  </RDF:Description>
</RDF:RDF>

Some people prefer this alternate format (note that much of the information has been trimmed from this example for brevity in order to show the basic structure):

<?xml version="1.0" encoding="UTF-8"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
  <!-- This Description resource includes all the update and compatibility information for
       a single add-on with the id foobar@developer.mozilla.org. You can list multiple
       add-ons information in the same RDF file. -->
  <RDF:Description about="urn:mozilla:extension:foobar@developer.mozilla.org">
    <em:updates>
      <RDF:Seq>
        <!-- The resource attribute points to an RDF:Description entry below with
             a matching about attribute. The actual uri can be whatever you like -->
        <RDF:li resource="urn:mozilla:extension:foobar@developer.mozilla.org:2.2"/>
        <RDF:li resource="urn:mozilla:extension:foobar@developer.mozilla.org:2.5"/>
      </RDF:Seq>
    </em:updates>
    <em:signature>MIGTMA0GCSqGSIb3DQEBBQUAA4GBAMO1O2gwSCCth1GwYMgscfaNakpN40PJfOWt
                  ub2HVdg8+OXMciF8d/9eVWm8eH/IxuxyZlmRZTs3O5tv9eWAY5uBCtqDf1WgTsGk
                  jrgZow1fITkZI7w0//C8eKdMLAtGueGfNs2IlTd5P/0KH/hf1rPc1wUqEqKCd4+L
                  BcVq13ad</em:signature>
  </RDF:Description>
  <!-- This represents the same Description within the li from the previous example -->
  <RDF:Description about="urn:mozilla:extension:foobar@developer.mozilla.org:2.2">
    <em:version>2.2</em:version>
    <!-- Trimmed the rest of the contents here -->
  </RDF:Description>
  <RDF:Description about="urn:mozilla:extension:foobar@developer.mozilla.org:2.5">
    <em:version>2.5</em:version>
    <!-- Trimmed the rest of the contents here -->
  </RDF:Description>
</RDF:RDF>
Note: It is possible to change the id of add-on through add-on update. To do this, just provide new em:id in install.rdf within new xpi file, and put its url in em:updateLink in update.rdf.

Providing Details about Updates

General

It is possible to provide the user some details about what is new in an updated version of your add-on. This is visible when the user gets an add-on update notification and should be used to give a quick overview of what new features have been added and any security issues that have been resolved.

In order to do this you must add an updateInfoURL entry to the update manifest (see the example above). The page at this URL will be retrieved and displayed to the user. Since it is being displayed outside of a normal webpage context it is heavily sanitized, which means there are few formatting options available and scripting and images aren't allowed.

The information page retrieved must currently be totally valid XHTML, including being delivered with the MIME type application/xhtml+xml (Important: see Problems section)

You may include %APP_LOCALE% in your updateInfoURL if you want to have locale information included in the URL -- this allows you to customize the text based on the user's locale. You may also use the other substitution strings supported by updateURL, although those may be less useful.

Formatting Prior to Firefox 4

Prior to Firefox 4 you could only use the following tags, any other tags have themselves and their contents completely stripped:

  • h1, h2 and h3 for general headings
  • p for paragraphs
  • ul and ol for lists.

Within lists use the usual li tag for each list item.

Within h1, h2, h3, p and li tags you may use:

  • b or strong for bolder text
  • i or em for italicized text

Formatting in Firefox 4 and later

From Firefox 4 the restrictions are relaxed somewhat. The following tags are interpreted normally:

  • h1, h2 and h3 for general headings
  • p, div, pre and blockquote for block formatting
  • ul, ol, li, dl, dt and dd for lists
  • b, i, em, strong, u, q, sub, sup and code for text formatting
  • br and hr for line breaking

The head, style and script tags and any of their contents are completely stripped. Other tags aren't included in the result but do have their contents displayed, so the following snippet:

<span><q>Text</q></span>

Would be rendered exactly the same as:

<q>Text</q>

Sample File

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html lang="en-US" dir="ltr" xmlns="http://www.w3.org/1999/xhtml"> 
<h2>My Extension</h2> 
<ul> 
<li>This update fixes some stability related issues.</li>
</ul> 
</html>

What End-User Sees

The content of updateInfoURL will be displayed to user in the add-ons page, in a list of all available updates. The user then can click the Show Information button, and will see the information, on the right hand side. (note the button caption is changed to Hide Information)

Image:Example_updateInfoURL2.PNG

Problems

You may encounter a problem where the content will not be displayed. See image below. The problem is because of MIME type that should be set in the server for xhtml extension. If you are running Apache Server, you might consider adding AddType application/xhtml+xml .xhtml to the .htacess file. Unfortunately, I've encounter cases where adding the MIME type to the server didnt help either. So the solution I did, and which worked, was just to give the file a "xml" extension instead of "xhtml".

Image:Example_updateInfoURL_error1.png

Securing Updates

Gecko 1.9 has added additional requirements designed to protect users from man-in-the-middle attacks and the like during add-on updates. In the install.rdf of the already installed add-on updateURL must be specified in one of the following ways:

  • The updateURL uses https, or there is no updateURL at all (which defaults to addons.mozilla.org which is https)
  • The updateURL uses http and the updateKey entry is specified which will be used to verify the data in the update manifest.

When you specify an updateKey in the install.rdf, you must include a digital signature in the update manifest or the information will be rejected.

In the update manifest delivered from the updateURL the updateLink must be specified in one of the following ways:

  • The updateLink to the XPI file must use https
  • The updateLink can use http and you must include an updateHash for the XPI file using sha1, sha256, sha384 or sha512 hash algorithms.

Any entries in the update manifest that do not meet one of those two requirements will be ignored when checking for new versions.

Note that https links to sites with invalid certificates or that redirect to http sites will fail for both the update.rdf and updateLink cases.  updateLink using an https site with a non-builtin token CA signed certificate will fail regardless of whether or not updateHash is used.

Update Hashes

In order to verify the integrity of the downloaded XPI you may provide an updateHash entry alongside the updateLink. This should be a hash generated against the file data using one of the supported hashing algorithms (sha1, sha256, sha384 and sha512). In Firefox 3 if the updateLink is not https then the hash must be made using one of the sha family of algorithms. The hashing algorithm used is put at the start of the string and separated from the hash by a :.

  <em:updateHash>sha256:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e64ad2e3a0b60120ca271ce6e6</em:updateHash>

Note:  the value of updateHash, must start with the string of hashing algorithm, it is a common error to delete this prefix, when setting new value to updateHash:\nsha256:78fc1d2887eda35b4ad2e3a0b60120ca271ce6e64ad2e3a0b60120ca271ce6e6")

When a hash is specified the downloaded file is compared with the hash and an error shown if it does not match.

There are quite a few tools you may use to generate hashes:

Various Unix flavors include sha1sum, sha256sum and so on. Windows users should consider HashTab for interactive (non-build-script) use. There are also gnu ports for win (besides usual suspects like cygwin), which are good for non-interactive use:

sha256sum FILE

There is also md5deep, which is cross platform:

sha256deep FILE

OpenSSL also generates hashes for you:

openssl sha256 FILE

If you're on Windows, HashTab is a shell extension... simple right-click gives you hash values for any file.

There is also an enhancement bug about adding automatic hash generation of XPI files to mccoy.

And all popular (scripting) languages offer support, for examples: Python, Perl: CPAN Digest, PHP

Signing Update Manifests

If you wish to serve your update RDF over regular http, Gecko 1.9 based applications will require that you digitally sign the update manifest to ensure that it's information isn't tampered with between you creating it and applications retrieving it. The McCoy tool should be used to sign the update RDF.

The technical details of the signing mechanism are beyond the scope of this document however the basics are as follows:

Step 1 - Done once, before you publish your add-on

The target: Adding updateKey in install.rdf

The add-on author creates a public/private RSA cryptographic key pair.

The public part of the key is DER encoded and then base 64 encoded and added to the add-on's install.rdf as an updateKey entry.

Step 2 - Done every time you change your "update.rdf" file

The target: Setting value to signature in update.rdf

When the author creates the update rdf file a tool is used to sign it using the private part of the key. Roughly speaking the update information is converted to a string, then hashed using a sha512 hashing algorithm and this hash is signed using the private key. The resultant data is DER encoded then base 64 encoded for inclusion in the update.rdf as an signature entry.

Debugging and solving problems

The update mechanism logs information to the console, and display various information which can help you to find problem. To enable the log:

  1. Set the value of extensions.logging.enabled to true (using URL about:config)
  2. Run Firefox from command with option -console

If you encounter problems, search the output in console for your extension id, and see if failures were logged.