Packaging Firefox/Thunderbird Extensions

Ben Goodger, 05/17/2004

Introduction

This document describes how to create extensions for Firefox 0.9 and newer, and Thunderbird 0.7 and newer.

Pre-requisites

You must know XUL, JavaScript and other languages/technologies that are required to put your extension together. There are plenty of resources that describe this, and much sample code. This document focuses on how to package XUL, JS and other components together into an extension.

Extension File Layout

New Firefox/Thunderbird extensions are laid out like so:

extension.xpi:
              install.rdf
              chrome/extension.jar
              components/extension.dll
              components/extension.js
              defaults/extension.something
              defaults/preferences/extension.js
       

install.js scripts are no longer used for Firefox and Thunderbird extensions. If you provide an install.js script, it will not be read. The new Extension Manager uses the install.rdf manifest at the top of your extension XPI to handle the installation automatically. You can provide an install.js if your extension also targets another application such as Mozilla 1.x. Those applications will ignore the install.rdf manifests and use the script instead.

The layout of your files within the XPI is now enforced. You must place jar files you want to register chrome for in the chrome subdirectory, XPCOM components in components, defaults files other than default preferences files in defaults and default preferences files in defaults/preferences. The Extension Manager checks these various locations during startup, installation and uninstallation to perform various operations such as chrome registration automatically, loading of default prefs and so on.

install.rdf

Your install.rdf manifest will look something like this:

<?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">
    <-- properties -->
  </Description>      
</RDF>

Compulsory install.rdf Properties

Your install.rdf file must have these properties:

em:id
The string GUID of the extension - you can create these by using guidgen (Windows), uuidgen (Unix) or "botbot uuid" on IRC. e.g.

<em:id>{daf44bf7-a45e-4450-979c-91cf07434c3d}</em:id>

em:version
A Firefox Version Format (FVF) string identifying the version that is being supplied by this package. e.g.

<em:version>4.6</em:version>

em:targetApplication
A object specifying an application targeted by this extension. This means that the extension will work with the application identified by the GUID (em:id), from the min version (em:minVersion) up to and including the max version (em:maxVersion). An extension manifest must specify at least one of these properties, and may specify more if the extension targets multiple apps that support this extension system (e.g. Firefox and Thunderbird). e.g.

  <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>


em:name
The name of the extension - intended for display in the UI. e.g.

<em:name>My Extension</em:name>

em:file
A chrome .jar file that requires chrome registration. The em:file arcs lead to resources with URIs of the format: urn:mozilla:extension:file:<fileName>.jar. Each of these child resources has a set of em:package, em:locale and em:skin properties that specify the path within the jar file where there is a chrome item that needs to be registered. e.g.

<em:file>
  <Description about="urn:mozilla:extension:file:myext.jar">
    <em:package>content/myext/</em:package>
    <em:locale>locale/en-US/myext/</em:locale>
    <em:skin>skin/classic/myext/</em:skin>
  </Description>
</em:file>
em:requires
A object specifying another extension that is required by this extension. em:id specifies the GUID of the extension that is required, em:minVersion specifies the minimum required version and em:maxVersion - much as for em:targetApplication. An Extension's manifest can specify 0 or more of these em:requires objects.

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


Note: This field does not do anything in Firefox 0.9 but will in the future be used to disable chains of incompatible extensions. Please begin using it now.

Optional install.rdf Properties

Your install.rdf file may have these properties in addition to the ones above:

em:description
A short description of the extension - intended for display in the UI. Should fit on one short line of text. e.g.

<em:description>Advanced foo tools.</em:description>

em:creator
The name of the creator/principal developer - intended for display in the UI. e.g.

<em:creator>John Doe</em:creator>

em:contributor
The name(s) of contributors to the extension - intended for display in the UI. Your manifest can specify 0 or more of these properties. e.g.

<em:contributor>Jane Doe</em:contributor>

em:homepageURL
A link to the extension's home page - intended for display in the UI. e.g.

<em:homepageURL>http://www.foo.com/</em:homepageURL>

em:updateURL
A link to a custom RDF file that specifies available updates to the extension. The format is described below. If enabled, the extension system periodically checks with this RDF file to determine if newer versions are available. It is recommended you do not supply this field if you are listing your extension with a host such as update.mozilla.org and just use the default update service provided by that host. Your server must send this file as text/rdf or the update checker will not work. Firefox will substitute the following values into this URL in case you wish to generate the response RDF dynamically, such as using PHP or CGI:

%ITEM_ID%The GUID of the extension being updated
%ITEM_VERSION%The version of the extension being updated
%APP_ID%The GUID of the current application
%APP_VERSION%The version of the current application

e.g.

<em:updateURL>http://www.foo.com/update.cgi?id=%ITEM_ID%&version=%ITEM_VERSION%</em:updateURL>

em:optionsURL
The chrome:// URL of the extension's options FE. e.g.

<em:optionsURL>chrome://myext/content/options.xul</em:optionsURL>

em:aboutURL
The chrome:// URL of the extension's about FE. e.g.

<em:aboutURL>chrome://myext/content/about.xul</em:aboutURL>

em:iconURL
A chrome:// URL to a 32x32 icon to display in the Extension Manager UI. e.g.

<em:iconURL>chrome://myext/skin/icon.png</em:iconURL>

Sample install.rdf File

<?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>{daf44bf7-a45e-4450-979c-91cf07434c3d}</em:id>
    <em:version>4.6</em:version>
    
    <!-- Target Application this extension can install into, 
        with minimum and maximum supported versions. --> 
    <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>
    
    <!-- Front End MetaData -->
    <em:name>NewExt2</em:name>
    <em:description>A test extension</em:description>
    <em:creator>Joe Creator</em:creator>
    <em:homepageURL>http://www.bengoodger.com/</em:homepageURL>
    <em:updateURL>http://www.bengoodger.com/software/mb/umo/update.rdf</em:updateURL>

    <!-- Front End Integration Hooks (used by Extension Manager)-->
    <em:optionsURL>chrome://newext2/content/options.xul</em:optionsURL>
    <em:aboutURL>chrome://newext2/content/options.xul</em:aboutURL>
    <em:iconURL>chrome://newext2/skin/newext2.png</em:iconURL>
    
    <!-- Packages, Skins and Locales that this extension registers -->
    <em:file>
      <Description about="urn:mozilla:extension:file:newext2.jar">
        <em:package>content/newext2/</em:package>
        <em:locale>locale/en-US/newext2/</em:locale>
        <em:skin>skin/classic/newext2/</em:skin>
      </Description>
    </em:file>
  </Description>      
</RDF>

Firefox Version Format

All extensions must use the Firefox Version Format to describe their versioning. The FVF looks like this:

major.minor.sub[+]

e.g. 1.2.1 and 0.8+. "+" indicates that the item is from the "development" period between releases.

Not all fields are necessary, e.g. 1.2 is as valid as 1.2.0

Application IDs

The following are some common target application GUIDs that you can use in your targetApplication properties:

Firefox{ec8030f7-c20a-464f-9b0e-13a3a9e97384}
Thunderbird{3550f703-e582-4d05-9a08-453d09bdfdc6}

Custom Update RDF

As described above, an Extension can provide its own custom update URL which takes the form of a RDF file. Presently this file must be served as text/rdf. See em:updateURL above for details of the URL format. The RDF file must be formatted like so:

  <RDF:Description about="urn:mozilla:extension:{EXTENSION GUID}">
    <em:version><Version Number Being Offered></em:version>
    <em:updateLink><XPI URL></em:updateLink>
  </RDF:Description>

e.g.

  <RDF:Description about="urn:mozilla:extension:{EXTENSION GUID}">
    <em:version>5.0</em:version>
    <em:updateLink>http://www.foo.com/bar-5.0.xpi</em:updateLink>
  </RDF:Description>

 

Tips & Tricks

Not all of the flexibility offered by the old install.js install mechanism is preserved. Specifically: