Installing Extensions and Themes From Web Pages

There are a variety of ways you can install extensions and themes from web pages, including direct linking to the XPI files and using the InstallTrigger object.

Extension and web authors are encouraged to use the method described below to install XPIs, as it provides the best experience to users.

Web Script Example

<script type="application/javascript">
function install (aEvent)
  for (var a =; a.href === undefined;) a = a.parentNode;
  var params = {
    "Foo": { URL:,
             toString: function () { return this.URL; }

  return false;

<a href=""
  onclick="return install(event);">Install Extension!</a>

Let's go through this piece by piece. The HTML <a> is the install link. The href attribute contains a direct link to the extension XPI file, this is what will show in the location bar when the link is moused over. Users can save the XPI file to disk easily by right clicking on the link and choosing "Save Link As..."

When the link is clicked it calls the function install passing the event object as the parameter.

The install first creates a parameter block:

var params = {
  "Foo": { URL:,
           toString: function () { return this.URL; }

This specifies the display name (Foo) for use in the confirmation dialog, the URL to the extension (which is the link href, recall), the Icon URL to display in the confirmation dialog, a hash of the xpi file contents (to protect against corrupted downloads), and a toString function which will allow this code to work with versions of Firefox 0.8 and earlier. You could also use the old style parameter block ({ "Foo": }) if you wanted - and didn't have an Icon to use for the confirmation dialog.

InstallTrigger.install is then called to install the item with the parameter block.

return false;

This last part is the most important - the install function must return false so that when the link is clicked, only the script is run, and the link href is not navigated to. If you omit this step, the user may see two installation dialogs—since you've effectively invoked two install requests, one from the InstallTrigger, one from trying to load the XPI file directly.

Available Parameters for the install object

The InstallTrigger.install method accepts a JavaScript object as a parameter, with several properties on that object used to affect the install.


The URL property specifies the URL of the XPI to install. This property is required.


The IconURL property specifies an icon to be displayed in the installation dialog. This property is optional. If you do not specify an icon, the default icon will be used, usually a green puzzle piece. The icon can be any image format supported by Firefox, and should be 32x32 pixels in size.


The Hash property specifies a cryptographic hash of the XPI file contents. This is used to verify the downloaded file, to protect against a corrupted file being served by a mirror download server, for example. You can use any hash function supported by nsICryptoHash. The hash is specified as hash function:hash value, for example, sha1:28857e60d043447c5f4550853f2d40770b326a13.


The toString() property should return the XPI URL, for compatibility with Firefox browsers older than version 1.0, and other applications such as Seamonkey.


Pretty much everything I've described applies to themes too, except you'll use the installChrome function. Because so many sites installed extensions by direct-linking the XPI file and relying on content handling to invoke the confirmation UI, many sites are (incorrectly) doing so for theme JAR files too and wondering why they aren't auto-detected and installed. Well, XPI is a Mozilla-specific extension and so we can have special handling for it, but JAR is not - not all .jar files are Firefox themes, so if you click on a .jar link you'll be shown the Save As decision dialog. For this reason you should always use the InstallTrigger API to install themes.

A Note on updateEnabled()

InstallTrigger exposes a function called updateEnabled that some of you may be calling before you call InstallTrigger.install. This is not necessary as install calls updateEnabled itself internally. Furthermore, calling updateEnabled may lead to problems if your distribution site is not in the user's whitelist, because Firefox only displays the "Installation Blocked" message when install or installChrome are called, or when a XPI file is loaded. So, if you have code that looks like this:

if (InstallTrigger.updateEnabled())
  InstallTrigger.install({"Foo": "foo.xpi"});

... and your site is not in the whitelist, when the user invokes that code, updateEnabled will return false because your site isn't whitelisted, and since it was updateEnabled that discovered this, not a call to install, there will be no notification to the user.

Thus you should only use updateEnabled to display content in the page to alert the user that software installation is disabled, or your site is not in the whitelist—do not place it in the install code path.

(* by all means don't let this stop you from developing more ambitious install systems, I am providing this documentation only as a guide that I hope most extension distributors will use since it handles most cases well)