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.



Extension Installation

Introduction

Prerequisites

Please read The Structure of an Extension and Extension Manifests before reading this document.

This document covers automated install of extension XPIs laid out as discussed in Extension Structure using only a manifest. For details on the installation of an extension using a custom install script, see Custom Extension Installation.

From Web Page to Install

There are two kinds of clients - XPInstall Enabled clients and non-XPInstall enabled. XPInstall Enabled clients are Firefox with Software Installation enabled, non-XPInstall Enabled clients are other browsers like Internet Explorer, and Firefox with Software Installation Disabled. XPInstall Enabled clients are referred to from now on as "XPI+" and non-XPInstall Enabled clients are referred to as "XPI-"

There are also two classes of target applications. One is the XPInstall Enabled browser (Firefox), the other is any other XUL application that supports Extensions. You can install directly into the former category from the web using XPInstall APIs, in the latter case you must install by using the content type handling facilties provided by the host environment. For more information on this see Target Applications. The former category is referred to TA+, the latter is TA-.

Consider two extensions. Extension A is fairly simple and depends on no others. It is packaged in a single XPI. Extension B depends on a third extension, Extension C v3.2-3.5. This is a common case - many extensions rely on JSLib. This dependency chain can be recursive (in that C could theoretically depend on D), and there may be multiple dependencies. But in this case we will assume we have just A, and B->C.

Determining Packages to Download

Client Target Extension Content Generated
XPI+ TA+ A InstallTrigger.install({ "A": "a.xpi"});
XPI- TA+ A <a href="a.xpi">A</a>
XPI+ TA- A <a href="a.xpi">A</a>
XPI- TA- A <a href="a.xpi">A</a>
XPI+ TA+ B
  if (versionExists("C", "3.2", "3.5")) 
    InstallTrigger.install({ "B": "b.xpi" });
  else
    InstallTrigger.install({ "C": "c.xpi", "B": "b.xpi" });
    
            
XPI- TA+ B <a href="c35.xpi">C v3.5</a>
<a href="b.xpi">B</a>
XPI+ TA- B <a href="c35.xpi">C v3.5</a>
<a href="b.xpi">B</a>
XPI- TA- B <a href="c35.xpi">C v3.5</a>
<a href="b.xpi">B</a>

Basically for XPInstall enabled browser clients, we are able to determine dependencies directly from the browser (see "versionExists" function below) and perform batch installs. Otherwise we need to serve up a list of xpis and have the user install them one by one. In the future we can improve this process perhaps by having a XRE registry.

  function versionExists(aInstallRegKey, aMinVersion, aMaxVersion)
  {
    var minRV = InstallTrigger.compareVersion(aInstallRegKey, aMinVersion);
    var maxRV = InstallTrigger.compareVersion(aInstallRegKey, aMaxVersion);
    return (minRV >= 0 && maxRV <= 0);
  }   
    

Installing the File

Either via the InstallTrigger or by being invoked by the host environment content handling system, the XPInstall system in the target application is invoked.

The XPInstall system checks for an install.js file at the top level of the XPI file. If one is present, then Custom Extension Installation is invoked. If none is found, it opens a stream to the extension manifest RDF file at the top level of the XPI file, and passes this to the Extension Manager.

The extension manager reads from the stream into a RDF DataSource and then performs the following actions:

  • The chrome:targetApplication arcs are verified - so that we don't end up installing an extension targeted at another application, or installing an extension that requires a version range of target application that does not intersect with the target application (e.g. requires Firefox 1.0-1.5, but Firefox 0.9 is installed).
  • The chrome:requires arcs are verified - so that we don't install an extension before all its dependencies are installed. This prevents problems arising from script incompatibilities, version incompatibilities etc.
  • Each of the following actions is logged in an install.log file under the extension's folder.
  • A folder for the extension with a unique id generated from the extension's id in the manifest is created in the extension folder.
  • The contents of the archive excluding the top level manifest are now extracted to the target extension folder.
  • The chrome:file arcs are now enumerated, and registerChrome is called for each package/skin/locale supplied by each package.
  • If all of the above succeeds, the contents of the manifest datasource is merged into the application extensions datasource.
  • The chrome:toBeEnabled arc is set to true for the given extension(s). This will cause the extension's overlays to be enabled and default preferences files loaded at the next start.
  • An .autoreg file is placed in the profile directory, which will cause a component re-registration on the next start to register any extension components.

For details on uninstallation of extensions installed through the standard mechanism described here and the Custom Extension Installation, see Extension Uninstallation.