6.3. Installing Mozilla Applications

Once your application is packaged, the next step is to create a cross-platform installation, or XPI. A XPI is a special file archive that contains your Mozilla package(s) and its own installation instructions. The relationship of the various parts of the installation process -- the XPI itself, the internal installation script, the trigger script that begins the installation, and the Mozilla browser -- can be visualized in Figure 6-4.

Figure 6-4. Installation process overview

6.3.1. The XPI File Format

Mozilla cross-platform installations use XPIs as the file format in which to organize, compress, and automate software installations and software updates. A XPI is a PKZIP-compressed archive (like ZIP and JAR files) with a special script at the highest level that manages the installation. A quick scan of the contents of a XPI file (which you can open using with any unzip utility) reveals the high-level directory structure shown in Example 6-8.

Note that the high-level structure in Example 6-8 parallels the installed browser's directory structure very closely. The bin directory at the highest level of the archive corresponds to the Mozilla application directory. On Unix, this directory is actually called bin, where all of the resources are stored. On other platforms, the installation puts these resources in the application directory itself.

In the case of the Mozilla browser, the XPIs manage the transfer and registry of all components -- the chrome files in the JARs, the executables, the default user information, and the libraries. As you will see in the installation script, the contents of the archive are installed onto the filesystem in much the same way as they are stored in the archive itself, although it's possible to rearrange things arbitrarily upon installation -- to create new directories, install files in system folders and other areas, or execute software that handles other aspects of the installation, such as third-party installers.

6.3.1.1. XPI example

When the items to be installed are very simple, XPIs may contain nothing more than a single executable and the install script itself, as shown in Figure 6-5. In this figure, the WinZip utility has been used to display the contents of a XPI that installs a text editor on a Win32 system.

This example uses XPInstall technology to install something that may or may not be a Mozilla application. The install.js script in Example 6-8 would look like this. In Mozilla application development, however, XPIs often contain JAR files that are installed as new packages in the Mozilla distribution. To make a XPI for your package, use any zip software (applications or extensions that will be part of the main Mozilla distribution are required to use the free zip utility from InfoTools so that they can be run as part of the build process) to archive your files.

6.3.1.2. JARs versus XPIs

Technically, only the internal installation script distinguishes JARs and XPIs. However, Mozilla treats them differently. Since JARs do not include this installation script, they cannot install full content or applications by themselves. In this case, "content" means XUL, XBL, or JavaScript files that have script access to XPCOM. Files of this kind that are in JARs are denied access to XPConnect and are not registered as content in the chrome registry. JARs are used primarily to install locales, or language packs, and skins.

Skins that contain scripts and bindings (see the section Section 4.5.3 and the Evil Skins sidebar, both in Chapter 4) are seen more as chrome content and must be installed in XPIs if they are to be fully functional. Like executables that are fetched from the Web, XPIs can cause trouble when downloaded by unprepared users since the software in XPIs are given the same privileges on the Mozilla platform that the browser chrome itself has.

The characteristics and usage of an XPI are:

  • Has an install.js file

  • Can install anything via XPInstall API

  • PKZip-compressed

  • May contain one or more JAR packages

  • Mozilla installation

  • Used for new packages

The characteristics and usage of a JAR are:

  • Contains only the resources themselves

  • Installed with an external script

  • May be installed inside a XPI

  • PKZip-compressed

  • Themes

  • Languages packs

  • Storage archive for installed components

Mozilla uses the presence of this internal installation script and not the file suffix (which can be changed easily enough) to determine what type of archive it is. Accordingly, JARs are most often used to install new themes and new language packs, which can be done by using just a brief trigger script on a web page loaded into Mozilla. When they contain new chrome -- new XUL and JavaScript that will access the Mozilla objects via XPConnect -- JAR files must be put within a XPI that can register them properly.

6.3.2. Installation Scripts

Most new packages in Mozilla are installed by means of installation scripts. These scripts are written in JavaScript. Unlike regular web page JavaScript, however, which uses window as the top-level object, installation scripts have a special install object context. As you will see in the following examples, the Install object -- even when it's implicit and not prefixed to the object methods -- is the top-level object upon which most methods are called.

6.3.2.4. Platform-dependent installation

Though the XPI format is by definition cross-platform, the files you distribute within it may need to be installed on a per-platform basis. The platform can be retrieved using the platform property of the Install object or the getFolder function. Example 6-14 shows a JavaScript function for install.js for returning the platform that the script is running on.

It's often necessary to check the platform when you install new language packs. At the time of this writing, issues related to write access to the chrome folder on Unix systems require some forking in the install script. There are also certain JAR files that are installed on a per-platform basis in language packs. Example 6-14 covers the three major platforms (Windows, Mac, and *nix). Here is how you use it:

platformNode = getPlatform( );
if (platformNode != 'unix') {
  // do Unix script and files
}
else if (platformNode != 'win') {
  // do Windows script and files
}
else {  // mac
  // do Mac script and files
}

6.3.2.5. The install log

When you are testing your XPI or need a way to troubleshoot installation problems, one of the best methods is to consult the installation log file. This file is called install.log and lives in the bin directory.

The install.log file is generated the first time you try to install software in Mozilla and appended to for each subsequent installation. The format of the file -- in which the URL and date of the installation appear as a heading -- makes it easy to find the installation you are checking on in the install log.

Example 6-15 shows the output in install.log after a single successful installation.

In your install.js file, you can use the method logComment to create output other than these standard logging messages. This can be very useful for debugging your install scripts or providing extra feedback:

logComment( "Installation started ..." );

The output for this call will appear in install.log formatted like this:

** Installation started ...

When installation is not smooth, Mozilla outputs an error code to track down what is happening. For example, if you declare a constant variable twice in your install script, you will receive notification of an script error in the UI, and this error will be logged in install.log:

** Line: 4    redeclaration of const X_JAR_FILE
Install **FAILED** with error -229  --  07/01/2002 11:47:53

A full list of error codes can be found at http://lxr.mozilla.org/seamonkey/source/xpinstall/src/nsInstall.h or in the XPInstall API Reference at http://developer.netscape.com/docs/manuals/xpinstall/err.html.

user_pref("xpinstall.enabled", false);

6.3.3. XPInstall

XPInstall is a technology used for cross-platform installation. Mozilla uses it extensively to install new packages, but as a general-purpose technology, it can be used to install anything on your computer. The XPI file format we described in the section Section 6.3.1 earlier in this chapter is the basic unit of exchange in an XPInstall and the installation script manages the installation.

Installation scripts -- whether they appear within the XPI, on a web page as an external "trigger script," or elsewhere in JavaScript -- use the XPInstall API to do all the heavy lifting. The XPInstall API includes installation functions (Example 6-16) organized into such high-level objects as the Install object, the InstallTrigger object, and the File object, which you can use to install new Mozilla packages.

In addition to the XPInstall API installation functions, installation scripts often call methods on the chrome registry itself. As described earlier in this chapter in the Section 6.2.4 section, the chrome registry handles the registration of new files and packages on the local system, the maintenance of user configurable data (such as what skin or theme you currently selected), and several utility functions used to make installations easier and more successful.

6.3.3.1. The Install object

The Install object is the main object in the XPInstall API. It provides most of the methods and properties used in installation scripts.

initInstall(displayName, name, version, flags)

The initInstall( ) method that initializes the installation process takes the following parameters: displayName is the name you give to the installation itself; name is the name of the package to be installed (which must match the name given to the package in the manifests); version is the version of the package being installed (also specified in the manifest); and flags is an optional parameter reserved for future use (which is set to "0" by default and about which you don't have to worry).

Example: initInstall("Example Installation", "xfly", "0.9", 0);
addFile(file)

The addFile( ) method adds a single file to the initialized installation. file is a pointer to the file in the XPI that will be installed.

Example: addFile("simple.exe");
err = performInstall( )

The performInstall( ) method starts the installation that you set up.

Example: performInstall( );

The Install object exposes the methods listed in Table 6-1.

Table 6-1. Install object methods

Method

Description

AddDirectory

Unpacks an entire subdirectory.

AddFile

Unpacks a single file.

Alert

Displays an Alert dialog box with a message and an OK button.

CancelInstall

Aborts the installation of the software.

Confirm

Displays a Confirm dialog box with the specified message and OK and Cancel buttons.

deleteRegisteredFile

Deletes the specified file and its entry in the Client Version Registry.

Execute

Extracts a file from the XPI file to a temporary location and schedules it for later execution.

Gestalt

Retrieves information about the operating environment (Mac OS only).

GetComponentFolder

Returns an object representing the directory in which a component is installed.

GetFolder

Returns an object representing a directory, for use with the addFile method.

GetLastError

Returns the most recent nonzero error code.

getWinProfile

Constructs an object for working with a Windows .ini file.

getWinRegistry

Constructs an object for working with the Windows registry.

InitInstall

Initializes installation for the given software and version.

LoadResources

Returns an object whose properties are localized strings loaded from the specified property file.

LogComment

Adds a comment line to the install log.

Patch

Applies a set of differences between two versions.

PerformInstall

Finalizes the installation of software.

RegisterChrome

Registers chrome with the chrome registry.

ResetError

Resets a saved error code to zero.

setPackageFolder

Sets the default package folder that is saved with the root node.

6.3.3.2. The InstallTrigger object

When you have very simple installations -- such as when you want to install a new skin -- you may not need to use the services from the Install object. Besides providing the services necessary for "triggering" the downloading of a package from a web site, the InstallTrigger object offers some simple methods for installing when you do not need to rearrange of the disk, register complications, or do other install-type preparation (see Table 6-2).

This web page installation script defines its own install method in which a callback parameter on the InstallTrigger's own install( ) method checks the success of the installation and displays a relevant alert for the user (as shown in Example 6-17).

6.3.4. Uninstalling Applications

You may have noticed an uninstall( ) method on the Install object in the XPInstall API. This method does some of the work you need to do to uninstall packages from Mozilla, but it's a buggy process and doesn't finish the job.[1] Beyond the physical removal of the package resources during the uninstall, several RDF files in the chrome registry need to be updated, and the XPInstall uninstall( ) does not get to some of these files.

Fortunately, the JSLib JavaScript developer's library has a well-implemented uninstall function, which you can use by importing the uninstall.js file and calling uninstall on the package you want uninstalled. uninstall.js is one of the JS file collections that comprise the JSLib.

Once you install JSLib, using the uninstall method is simple:

include("chrome://jslib/install/uninstall.js");
var p = new Uninstall('myPackageName');
p.removePkg( );

You might want to put this uninstall routine in a function so you can reuse it.

function unInstall(pkg) {
   var p = new Uninstall(pkg);
   p.removePkg( );
}

This method removes the resources themselves and deletes all references to the package in the chrome registry. The pkg parameter is the name of the package as defined in the manifest for that package. The xFly package manifest, for example, defines "xfly" as the name of the package, as shown in Example 6-19.

Example 6-9 comes from the content package manifest for xFly, which is similar to the full content manifest for the XMLTerm application you saw in Example 6-4.

To uninstall the xFly package, then -- as you should do to the working version you have as you develop before installing the final version -- hook up a menuitem to call the uninstall routine:

<menuitem id="uninstall-item" label="Uninstall xFly" oncommand="unInstall("xfly")" />

This menuitem should have access to a JavaScript file and contains the following code:

include("chrome://jslib/install/uninstall.js");
function unInstall(pkg) {
   var p = new Uninstall(pkg);
   p.removePkg( );
}

Notes

[1]

Currently, some open bugs in Bugzilla are tracking the progress of this method and its improvement.