You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



Firefox Extension System

Latest Extension System Notes

(02-19-2004)

What is an Extension

An extension contains these pieces:

  • Chrome (XUL, JavaScript, Themes, Locale components in JAR files)
  • XPCOM components (Compiled C++ code, JavaScript components)
  • Default preferences files
  • Other default resources (for profile)

Where Extensions Live

Extensions can live in one of the following two places:

  • bin/extensions/<extension_name>/ for extensions available to all users on a system and because administrator privileges are required to install these there is no front end for installing extensions in this way.
  • <profile_dir>/extensions/<extension_name> for per profile extensions - especially useful on multiuser systems. These extensions are preserved across application and is the default install mode when installing by the user through the front-end.

Anatomy of an Extension

An extension's directory structure looks something like this:

myExtension/chrome/myPackage1.jar
myExtension/chrome/myPackage2.jar
...
myExtension/components/myComponent1.dll
myExtension/components/myComponent2.js
...
myExtension/defaults/pref/myExtension.js <- default prefs go here
...
myExtension/defaults/myExtensionDefault.rdf <- other defaults files go here

Managing Extensions

Extensions are installed, uninstalled and tracked through an Extension Manager. The behavior of this Extension Manager is described more fully here and here.

The extension manager uses a RDF datasource to track extensions, their component parts and dependencies, and to build a UI for managing extensions.

Installing an Extension

More detail on how extensions are registered with the extension manager now via XPInstall. The emphasis here is on maximum compatibility and reuse with existing XPInstall APIs... a couple of new methods are added to specifically support the new extension system file hierarchy:

    // Tell the XPInstall system we're about to install an extension. This creates a
    // folder under the applicable extensions folder (bin or profile - all user/fe
    // generated install actions are profile, command line extension installation
    // can be profile or bin dir)
    initExtensionInstall("myExtension");
    
    // Used to generate log entries in extensions/<myExtension>/install.log
    var err = initInstall("My Extension 1.0 for Firefox 1.0", "My Extension", "1.0");
    ...
    
    // getTargetFolder(aFlag, subfile) returns:
    // aFlag      returns
    // 0          [<profile>|bin]/extensions/<myExtension>/
    //              root extension directory
    // CHROME     [<profile>|bin]/extensions/<myExtension>/chrome/
    //              extension's chrome packages, themes, locale packages
    // COMPONENTS [<profile>|bin]/extensions/<myExtension>/components/
    //              extension's components
    // DEFAULS    [<profile>|bin]/extensions/<myExtension>/defaults/
    //              extension's generic defaults
    // PREFS      [<profile>|bin]/extensions/<myExtension>/defaults/prefs/
    //              extension's default preferences files (all files in this directory are read)
    // This function returns the profile or bin version of the extensions folder depending
    // on how the install operation was invoked (see above). 
    // This function is meant to provide a shortcut to allow extension authors to install
    // into the right place. 
    if (verifyDiskSpace(getTargetFolder(0), spaceRequired)) {
      addFile("My Extension Chrome",              // Registry Name
              "chrome/myExtension.jar",           // Source File (in XPI)
              getFolder(getTargetFolder(CHROME)), // Target Folder 
              "");                                // Target subdir
      addFile("My Extension Component",               // Registry Name
              "components/myExtension.dll",           // Source File (in XPI)
              getFolder(getTargetFolder(COMPONENTS)), // Target Folder 
              "");                                    // Target subdir
      addFile("My Extension Default Prefs",      // Registry Name
              "chrome/myExtension.js",           // Source File (in JAR)
              getFolder(getTargetFolder(PREFS)), // Target Folder 
              "");                               // Target subdir
      
      var file = getTargetFolder(CHROME, "myExtension.jar");     
      registerChrome(PACKAGE | DELAYED_CHROME, file, "content/myExtension");
      registerChrome(LOCALE | DELAYED_CHROME, file, "locale/en-US/myExtension");
      registerChrome(SKIN | DELAYED_CHROME, file, "skin/classic/myExtension");
      
      // Tidy up 
      finalizeExtensionInstall();
    }
    ...
    

As you can see this script looks very similar to current XPInstall scripts which should make migration of existing extensions easier. The main modifications have been function calls to invoke the extension manager, create and reference the appropriate directories in bin|profile/extensions.

XPI files must look like this:

myextension.xpi/install.js <- install script
myextension.xpi/extension.rdf <- extension manifest (metadata about this extension, dependencies etc)
myextension.xpi/* <- other files

extension.rdf is a manifest containing information about the package as a whole, its author(s) and dependencies if any. A vocabulary for this could follow that suggested by Benjamin Smedberg here. (I suggest not using actual RDF containers where order is not important to avoid overhead, and rather just using multiple assertions of each property)

finalizeExtensionInstall results in nsIExtensionManager's installExtension method being called which adds the new extension to the extension database (using the extension.rdf database to help it do so).

Encouraging extension authors to follow this scheme will be easy, as the new extension UI will use the extension manager's RDF datasource to populate it rather than the chrome registry. The metadata cruft in the chrome registry that at present exists only to support the extension/theme FE is relocated to the extension manager where it makes more sense.

My belief is that this proposal uses existing, well-tested code/systems such as the chrome registry and xpinstall to best benefit.

Uninstalling an Extension

See my older extensions document for discussion of this.

Documentation and References