File:  [mozdev] / books / www / chapters / ch06.html
Revision 1.15: download - view: text, annotated - select for diffs - revision graph
Fri Apr 4 16:27:40 2003 UTC (16 years, 7 months ago) by cdn
Branches: MAIN
CVS tags: HEAD
ahem

    1:     <link rel="prev" href="http://books.mozdev.org/chapters/ch05.html" />
    2:     <link rel="next" href="http://books.mozdev.org/chapters/ch07.html" />
    3: 
    4:     <style type="text/css">
    5:       div.c17 {font-weight: bold; text-align: center}
    6:       div.c16 {text-align: center}
    7:     </style>
    8: 
    9:     <h2>Chapter 6</h2>
   10:     <h1><a name="77063"></a> Packaging and Installing
   11:     Applications</h1>
   12:     <p>The previous chapters covered the basic parts of building an
   13:     application. Now that you've seen how to create an application
   14:     with XUL, CSS, and JavaScript that can be used on your local
   15:     computer, we will show you how to turn your program into
   16:     something that can be installed by other users. This chapter
   17:     discusses the technologies Mozilla provides for packaging and
   18:     installing applications.</p>
   19:     <p>Until your project is packaged for distribution, it can't be
   20:     fully considered a finished application (unless it was designed
   21:     to work only on the computer where it was created). Making your
   22:     application distributable, installable, and registrable allows
   23:     others to use what you have created.</p>
   24:     <p>This chapter is divided into four main sections. It starts
   25:     with a quick overview of the basics of packaging and installing
   26:     applications. The second section provides details about how to
   27:     get your application packaged and described so that Mozilla
   28:     recognizes what it is. The next section specifies how to put
   29:     your package into a cross-platform installation file that can
   30:     be installed over the Web onto other machines. The last section
   31:     provides tips for customizing how your application will look
   32:     once it is installed.</p>
   33:     <h2><a name="77064"></a> Packaging and Installing Overview</h2>
   34:     <p>Several different pieces comprise 
   35:     <!--INDEX STARTRANGE==packaging:overview;installation:overview -->
   36:     Mozilla's distribution technology. In fact, Mozilla may have a
   37:     few more moving parts than other packaging systems because it
   38:     needs a way to package and install new software uniformly
   39:     across several different platforms. <a href="#77002">Figure
   40:     6-1</a> shows the major components of Mozilla's packaging
   41:     system outlined in black.</p>
   42:     <div class="c16">
   43:       <img src="foo.gif">
   44:     </div>
   45:     <p><i>Figure 6-1: <a name="77002"></a></i> <i>Mozilla packaging
   46:     components</i></p>
   47:     <p>As you can see in <a href="#77002">Figure 6-1</a>, the 
   48:     <!--INDEX XPI (Cross-Platform Installer);distribution:XPI -->
   49:     Cross-Platform Installer (XPI), pronounced zippy or X-P-I, is
   50:     the archive format used to distribute Mozilla applications. The
   51:     XPI file contains a script that downloads and installs the
   52:     application. The package inside the XPI has a manifest that is
   53:     used to register the new Mozilla-based software with the
   54:     Mozilla chrome registry.</p>
   55:     <p>When a XPI contains a 
   56:     <!--INDEX packages:installation script;XPI (Cross-Platform Installer):package installation script -->
   57:     Mozilla-based package such as the xFly sample discussed in <a
   58:     href="ch02.html#77048">Chapter 2</a> and the following
   59:     chapters, the installation script also takes care of the
   60:     package registration process, described in the <a href=
   61:     "#77070">"Registering Packages</a>" section later in this
   62:     chapter. <a href="#77020">Example 6-1</a> shows a simple
   63:     installation script and the kind of information it contains.
   64:     The <a href="#77085">"Installation Scripts</a>" section, also
   65:     later in this chapter, discusses other scripts that may need to
   66:     be used in the installation process, such as trigger
   67:     scripts.</p>
   68:     <p><i>Example 6-1: <a name="77020"></a></i> <i>Package
   69:     installation script</i></p>
   70: <pre>
   71:  var myFile = "xFly.jar";
   72:  initInstall(                      // initialize the installation
   73:    "Install xFly",                 // display name of installation
   74:    "xFly",                         // package name
   75:    "0.0.1",                        // version of install
   76:    1);                             // flags - an optional argument, 
   77:                                    // reserved for future use
   78:  f = getFolder("Chrome"); // specify a target directory
   79:  setPackageFolder(f);
   80:  addFile(myFile);         // add software to the installation
   81:  registerChrome(
   82:    PACKAGE | DELAYED_CHROME,       // chrome switch (i.e., type)
   83:    getFolder("Chrome","xFly.jar"), // destination of package
   84:    "content/xFly/");               // location of manifest in package
   85:  if (0 == getLastError( ))   // if there have been no errors:
   86:    performInstall( );        // install "xfly.jar"
   87:  else                       // otherwise
   88:    cancelInstall( );         // cancel the installation.
   89: </pre>
   90:     <p>The installation process requires a few different steps.
   91:     First an installation must be initialized. Then the software to
   92:     be installed is added to the specified target directory.
   93:     Finally, packages in the installation 
   94:     <!--INDEX registration:packages;packages:registration;installation:packages:registration -->
   95:     are registered. At this point, the application is installed on
   96:     a user's computer.</p>
   97:     <p>When you install new packages or 
   98:     <!--INDEX chrome:registry, package installation -->
   99:     Mozilla-based software, the chrome registry on the Mozilla side
  100:     brokers the deal-reading the manifest, executing the
  101:     installation script(s), and updating the package information
  102:     that it maintains internally (storing this information using
  103:     RDF).</p>
  104:     <p>The relationship of the packaging, installation, and
  105:     registration-and all pieces involved-may seem a little complex
  106:     and idiosyncratic at first, but bear with it. The upshot of
  107:     this powerful but somewhat diffuse packaging technology is that
  108:     you can bundle your software, put it on a server, and have
  109:     users install it by simply clicking a link on a web page when
  110:     using Mozilla.</p>
  111:     <p>It is possible to use this 
  112:     <!--INDEX bundling, packaging and;packages:bundling and -->
  113:     packaging system to bundle any sort of application or extension
  114:     to an existing Mozilla application. You can install a XPI that
  115:     adds functionality to the Mozilla browser, such 
  116:     <!--INDEX XPI (Cross-Platform Installer):Mouse Gestures;Mouser Gestures -->
  117:     as Mouse Gestures (<i><a href=
  118:     "http://optimoz.mozdev.org/gestures/">http://optimoz.mozdev.org/gestures/</a></i>
  119:     ), which enables the execution of common browser commands with
  120:     mouse movements. You can package new Mozilla development tools
  121:     and libraries like JSLib (see <a href="ch05.html#77037">Chapter
  122:     5</a>). You can also 
  123:     <!--INDEX ENDRANGE==packaging:overview;installation:overview -->
  124:     create installations for entirely new Mozilla applications.</p>
  125:     <h2><a name="77065"></a> Packaging Mozilla Applications</h2>
  126:     <p><i>Packaging</i> simply 
  127:     <!--INDEX packaging:Mozilla applications;applications:packaging -->
  128:     means organizing your files into a Mozilla application
  129:     structure. Packaging your application is required to make it
  130:     installable and to make it something that Mozilla recognizes as
  131:     one of its own. Whether your Mozilla-based becomes a part of an
  132:     existing Mozilla application, like Mouse Gestures, or will
  133:     exist as a standalone application, like JabberZilla, you will
  134:     need to package it.</p>
  135:     <p>When you are done with this packaging section, package your
  136:     Mozilla-based applications in the same way that we packaged the
  137:     xFly example in <a href="ch02.html#77048">Chapter 2</a>. This
  138:     chapter describes the manifests and other necessary files. Then
  139:     the Installation section shows how you can put your package in
  140:     a XPI file and create installation script(s) so it can be
  141:     distributed and installed.</p>
  142:     <h3><a name="77066"></a> Package Manifests</h3>
  143:     <p>All new packages 
  144:     <!--INDEX packages:manifests;manifests:packages --> must have
  145:     manifests describing their contents, skin information, and
  146:     locale information. These manifests are formatted in RDF, which
  147:     makes them easy to combine with the RDF data that makes up the
  148:     chrome registry and makes it easy to fit the package into the
  149:     Mozilla software. There is some flexibility about where in the
  150:     package the manifest must appear, but the registration process
  151:     must find and read it regardless of where it is.</p>
  152:     <p>The installation script points out the manifest locations so
  153:     the package can be registered properly. Note that 
  154:     <!--INDEX JAR (Java Archive) files:manifests --> manifests
  155:     appear in JARs, but they do not appear in XPIs, since the
  156:     latter is a temporary file that gets deleted once the files it
  157:     contains, including JARs, are installed (see the <a href=
  158:     "#77081">"Installing Mozilla Applications</a>" section later in
  159:     this chapter for more information about XPI install files).</p>
  160:     <h4><a name="77067"></a> Theme package manifests</h4>
  161:     <p><a href="#77022">Example 6-2</a> shows 
  162:     <!--INDEX themes:package manifests;manifests:packages:themes and;packages:manifests:themes -->
  163:     a manifest for a new theme to be installed in Mozilla. It is
  164:     simple because it describes only one type of package, the "fly
  165:     skin," and the existing component it interacts with, the
  166:     communicator-the default Mozilla browser (the syntax and
  167:     structure is the same for all manifests, however). The manifest
  168:     says, in effect, this is what I have here (the metadata about
  169:     the theme-its name, a description, etc.), and this is what it
  170:     affects (the list of <tt>chrome:packages</tt> to which the
  171:     theme should be applied).</p>
  172:     <p><i>Example 6-2: <a name="77022"></a></i> <i>Simple theme
  173:     package manifest</i></p>
  174: <pre>
  175:  &lt;?xml version="1.0"?&gt;
  176:  &lt;RDF:RDF xmlns:RDF="<a href=
  177: "http://www.w3.org/1999/02/22-rdf-syntax-ns">http://www.w3.org/1999/02/22-rdf-syntax-ns</a>#"
  178:    xmlns:chrome="<a href=
  179: "http://www.mozilla.org/rdf/chrome">http://www.mozilla.org/rdf/chrome</a>#"&gt;
  180:    &lt;!-- List all the skins being supplied by this theme --&gt;
  181:    &lt;RDF:Seq about="urn:mozilla:skin:root"&gt;
  182:      &lt;RDF:li resource="urn:mozilla:skin:flyskin/1.0" /&gt;
  183:    &lt;/RDF:Seq&gt;
  184:    &lt;!-- Fly Skin Information --&gt;
  185:    &lt;RDF:Description about="urn:mozilla:skin:flyskin/1.0"
  186:      chrome:displayName="Fly Skin"
  187:      chrome:author="frillies"
  188:      chrome:description="shimmering, purple/black, hairy"&gt;
  189:     &lt;chrome:packages&gt;
  190:       &lt;RDF:Seq about="urn:mozilla:skin:classic/1.0:packages"&gt;
  191:         &lt;RDF:li resource="urn:mozilla:skin:classic/1.0:communicator"/&gt;
  192:       &lt;/RDF:Seq&gt;
  193:     &lt;/chrome:packages&gt;
  194:    &lt;/RDF:Description&gt;
  195:  &lt;/RDF:RDF&gt;
  196: </pre>
  197:     <h4><a name="77068"></a> Language pack manifests</h4>
  198:     <p>When you look at 
  199:     <!--INDEX language pack manifests;manifests:language pack manifests;packages:manifests:language pack manifests -->
  200:     a package manifest that describes a new locale, as shown in <a
  201:     href="#77024">Example 6-3</a> (which is for a 
  202:     <!--INDEX German language pack manifest --> German language
  203:     pack in Mozilla), you see a similar structure. Again, the
  204:     manifest describes the new package first and then lists the
  205:     existing components to which this new package applies.</p>
  206:     <p><i>Example 6-3: <a name="77024"></a></i> <i>Locale package
  207:     manifest</i></p>
  208: <pre>
  209:  &lt;?xml version="1.0"?&gt;
  210:  &lt;RDF:RDF xmlns:RDF="<a href=
  211: "http://www.w3.org/1999/02/22-rdf-syntax-ns">http://www.w3.org/1999/02/22-rdf-syntax-ns</a>#"
  212:   xmlns:chrome="<a href=
  213: "http://www.mozilla.org/rdf/chrome">http://www.mozilla.org/rdf/chrome</a>#"&gt;
  214:   &lt;!-- list all the skins being supplied by this package --&gt;
  215:   &lt;RDF:Seq about="urn:mozilla:locale:root"&gt;
  216:   &lt;RDF:li resource="urn:mozilla:locale:en-DE"/&gt;
  217:   &lt;/RDF:Seq&gt;
  218:   &lt;!-- locale information --&gt;
  219:   &lt;RDF:Description about="urn:mozilla:locale:en-DE"
  220:    chrome:displayName="English (German)"
  221:    chrome:author="mozilla.org"
  222:    chrome:name="en-DE"
  223:    chrome:previewURL="<a href=
  224: "http://www.mozilla.org/locales/en-DE.gif">http://www.mozilla.org/locales/en-DE.gif</a>"&gt;
  225:    &lt;chrome:packages&gt;
  226:     &lt;RDF:Seq about="urn:mozilla:locale:en-DE:packages"&gt;
  227:       &lt;RDF:li resource="urn:mozilla:locale:en-DE:communicator"/&gt;
  228:       &lt;RDF:li resource="urn:mozilla:locale:en-DE:editor"/&gt;
  229:       &lt;RDF:li resource="urn:mozilla:locale:en-DE:global"/&gt;
  230:       &lt;RDF:li resource="urn:mozilla:locale:en-DE:messenger"/&gt;
  231:       &lt;RDF:li resource="urn:mozilla:locale:en-DE:navigator"/&gt;
  232:     &lt;/RDF:Seq&gt;
  233:    &lt;/chrome:packages&gt;
  234:   &lt;/RDF:Description&gt;
  235:  &lt;/RDF:RDF&gt;
  236: </pre>
  237:     <p>Note that in <a href="#77024">Example 6-3</a>'s package
  238:     manifest, all major components are affected by this new locale
  239:     package. When the package is installed and the manifest is
  240:     read, the chrome registry is made aware of a German language
  241:     pack that it can use to display German in the interface of each
  242:     Mozilla component.</p>
  243:     <blockquote>
  244:       <hr>
  245:       <b>contents.rdf Type Manifests</b> 
  246:       <p>Package manifests are an area where Mozilla browser itself
  247:       may not be the best model for learning about the best
  248:       application development practice. Mozilla is such a large and
  249:       modular application that it uses several manifests instead of
  250:       one application-wide <i>manifest.rdf</i> file.</p>
  251:       <p>Although they have the same format, these distributed
  252:       manifests are found in several <i>contents.rdf</i> files. In
  253:       a single theme (e.g., the <i>modern.jar</i>), you can see as
  254:       many as eight manifests (for major component to which the
  255:       theme applies).</p>
  256:       <p>These two types of manifests-the <i>contents.rdf</i> file,
  257:       which typically describes a single package-component
  258:       relationship; and the <i>manifest.rdf</i> file, which
  259:       describes the package's relationship to all affected
  260:       components-are functionally equivalent. In both cases, the
  261:       chrome registry reads all RDF/XML data and registers the
  262:       package.</p>
  263:       <p>Because the manifest data format is RDF/XML, you can use
  264:       either type of manifest in your own package development,
  265:       although using a single <i>manifest.rdf</i> is generally much
  266:       easier, especially if you want to change the list of affected
  267:       components of any other metadata later.</p>
  268:       <hr>
  269:     </blockquote>
  270:     <p>The package manifests for content and new applications-which
  271:     may include new content, skin, and locale information-have an
  272:     identical syntax and a very similar structure, as you will see
  273:     in the following sections. The manifest for a full
  274:     Mozilla-based application like xFly describes the content, the
  275:     skin, and the locale in a single file that sits at the top of
  276:     that package.</p>
  277:     <h4><a name="77069"></a> Application manifests</h4>
  278:     <p>When you create new 
  279:     <!--INDEX application manifests;manifests:application manifests;packages:manifests:application manifests -->
  280:     applications on top of Mozilla, you will often create new
  281:     content, new skins, and your own localizable language elements,
  282:     such as DTDs. For applications, the manifest must describe
  283:     these parts of your application if Mozilla is to find and
  284:     register them properly.</p>
  285:     <p><a href="#77026">Example 6-4</a>, the package 
  286:     <!--INDEX XMLTerm extension, package manifest --> manifest from
  287:     the XMLTerm Mozilla extension, describes the contents, skin,
  288:     and locale in a single file, which is most common for
  289:     Mozilla-based applications.</p>
  290:     <p><i>Example 6-4: <a name="77026"></a></i> <i>manifest.rdf
  291:     describing the XMLTerm extension</i></p>
  292: <pre>
  293:  &lt;?xml version="1.0"?&gt;
  294:  &lt;RDF:RDF xmlns:RDF="<a href=
  295: "http://www.w3.org/1999/02/22-rdf-syntax-ns">http://www.w3.org/1999/02/22-rdf-syntax-ns</a>#"
  296:           xmlns:chrome="<a href=
  297: "http://www.mozilla.org/rdf/chrome">http://www.mozilla.org/rdf/chrome</a>#"&gt;
  298:    &lt;!-- list all the packages being supplied by this jar --&gt;
  299:    &lt;RDF:Seq about="urn:mozilla:package:root"&gt;
  300:      &lt;RDF:li resource="urn:mozilla:package:xmlterm"/&gt;
  301:    &lt;/RDF:Seq&gt;
  302:    &lt;RDF:Seq about="urn:mozilla:skin:root"&gt;
  303:      &lt;RDF:li resource="urn:mozilla:skin:modern/1.0" /&gt;
  304:    &lt;/RDF:Seq&gt;
  305:    &lt;RDF:Seq about="urn:mozilla:locale:root"&gt;
  306:      &lt;RDF:li resource="urn:mozilla:locale:en-US"/&gt;
  307:    &lt;/RDF:Seq&gt;
  308:    &lt;!-- xmlterm package information --&gt;
  309:    &lt;RDF:Description about="urn:mozilla:package:xmlterm"
  310:          chrome:displayName="XMLterm"
  311:          chrome:author="xmlterm.org"
  312:          chrome:name="xmlterm"&gt;
  313:    &lt;/RDF:Description&gt;
  314:    &lt;!-- xmlterm overlay information --&gt;
  315:    &lt;RDF:Seq about="urn:mozilla:overlays"&gt;
  316:      &lt;RDF:li resource="chrome://communicator/content/tasksOverlay.xul"/&gt;
  317:    &lt;/RDF:Seq&gt;
  318:    &lt;RDF:Seq about="chrome://communicator/content/tasksOverlay.xul"&gt;
  319:      &lt;RDF:li&gt;chrome://xmlterm/content/xmltermOverlay.xul&lt;/RDF:li&gt;
  320:    &lt;/RDF:Seq&gt;
  321:    &lt;!-- locale information --&gt;
  322:    &lt;RDF:Description about="urn:mozilla:locale:en-US"
  323:          chrome:displayName="English(US)"
  324:          chrome:author="mozilla.org"
  325:          chrome:name="en-US"
  326:          chrome:previewURL="<a href=
  327: "http://www.mozilla.org/locales/en-US.gif">http://www.mozilla.org/locales/en-US.gif</a>"&gt;
  328:      &lt;chrome:packages&gt;
  329:        &lt;RDF:Seq about="urn:mozilla:locale:en-US:packages"&gt;
  330:          &lt;RDF:li resource="urn:mozilla:locale:en-US:xmlterm"/&gt;
  331:        &lt;/RDF:Seq&gt;
  332:      &lt;/chrome:packages&gt;
  333:    &lt;/RDF:Description&gt;
  334:    &lt;!-- xmlterm skin information --&gt;
  335:    &lt;RDF:Description about="urn:mozilla:skin:modern/1.0"
  336:          chrome:displayName="Modern"
  337:          chrome:author="mozilla.org"
  338:          chrome:name="modern/1.0"&gt;
  339:      &lt;chrome:packages&gt;
  340:        &lt;RDF:Seq about="urn:mozilla:skin:modern/1.0:packages"&gt;
  341:          &lt;RDF:li resource="urn:mozilla:skin:modern/1.0:xmlterm"/&gt;
  342:        &lt;/RDF:Seq&gt;
  343:      &lt;/chrome:packages&gt;
  344:    &lt;/RDF:Description&gt;
  345:  &lt;/RDF:RDF&gt;
  346: </pre>
  347:     <p>The structure in <a href="#77026">Example 6-4</a> is exactly
  348:     the same as that in more focused manifests (<a href=
  349:     "#77022">Example 6-2</a> and <a href="#77024">Example 6-3</a>),
  350:     but all of the skin, content, and locale structures sit
  351:     together in a single <i>manifest.rdf</i> file. This manifest
  352:     follows the Mozilla convention of introducing the package
  353:     contents at the top and then expanding upon the basic listing
  354:     of each separate sections, providing the necessary metadata
  355:     about the items in the middle, and then listing the components
  356:     that are affected by the items at the end. However, the
  357:     flexibility of the RDF format means you could just as easily
  358:     order this information differently-which is why RDF is
  359:     sometimes described as creating a "soup" of statements about
  360:     resources.</p>
  361:     <p>Note that the overlay section in the middle of the example
  362:     is part of the content description. It tells the chrome
  363:     registry that the contents of the file
  364:     <i>xmltermOverlay.xul</i> should be overlaid into the
  365:     <i>tasksOverlay.xul</i> file in Mozilla, in which much of the
  366:     Tools menu is defined. The package manifest for the xFly sample
  367:     application that we discuss here, also a single file, is very
  368:     similar to the manifest in <a href="#77026">Example
  369:     6-4</a>.</p>
  370:     <h3><a name="77070"></a> Registering Packages</h3>
  371:     <p>Typically, registration occurs 
  372:     <!--INDEX packages:registration;registration:packages -->
  373:     during installation, which is why the <a href=
  374:     "#77081">"Installing Mozilla Applications</a>" section of this
  375:     chapter goes into more detail about the specific methods and
  376:     objects available for package registration. The registration
  377:     process deals with packages and package manifests, however, so
  378:     the following two sections describe the two types of package
  379:     registration that are possible in Mozilla. The first provides
  380:     an overview of how to register a package on installation, as is
  381:     typically done, and the second describes how to use a special
  382:     file to register your work with Mozilla as you develop it so
  383:     that you can view your work as it progresses.</p>
  384:     <h4><a name="77071"></a> Registering packages on
  385:     installation</h4>
  386:     <p>Generally, the registration process 
  387:     <!--INDEX registration:packages:on installation[registration:packages:installation] -->
  388:     <!--INDEX packages:registration:on installation[packages:registration:installation] -->
  389:     <!--INDEX installation:packages:registration and --> is a
  390:     transaction that takes place between your installation scripts,
  391:     the chrome registry, and the manifests that describe the
  392:     package. Usually, registration happens upon installation. You
  393:     can approach this transaction in many ways, but the general
  394:     relationship is shown in <a href="#77004">Figure 6-2</a>.</p>
  395:     <div class="c16">
  396:       <img src="foo.gif">
  397:     </div>
  398:     <p><i>Figure 6-2: <a name="77004"></a></i> <i>Package
  399:     interaction overview</i></p>
  400:     <p>In this relationship, the install script is responsible for
  401:     managing the transfer of files to a specified location on the
  402:     local disk and alerting the chrome registry to the new files
  403:     and their manifests. The chrome registry then finds and reads
  404:     those manifests. If the information there is formatted
  405:     correctly, then that information is added to the sum of package
  406:     information that the chrome registry manages-a single,
  407:     overarching datasource of all packages in Mozilla, including
  408:     skins, locales, overlays, and other software. In this way, the
  409:     package is added to Mozilla. The major players in this
  410:     interaction between the packages, the package descriptions, and
  411:     the chrome registry are shown in the following list.</p>
  412:     <ul>
  413:       <li>Manifests in the archives themselves</li>
  414:       <li>XPInstall, the technology that performs the downloading
  415:       and resource installation</li>
  416:       <li>The chrome registry, the database of packages, and user
  417:       information that is read and written to when new software is
  418:       installed</li>
  419:     </ul>
  420:     <h4><a name="77072"></a> Registering packages as you develop
  421:     them (installed-chrome.txt)</h4>
  422:     <p>The file <i>installed-chrome.txt</i> is a 
  423:     <!--INDEX registration:packages:at development[registration:packages:development] -->
  424:     <!--INDEX packages:registration:at development[packages:registration:development] -->
  425:     convenience for developers who want to create and test new
  426:     packages without <!--INDEX installed-chrome.txt file --> having
  427:     to install them with installation scripts and manifests. Some
  428:     earlier xFly examples in this book already used this method.
  429:     The <i>installed-chrome.txt</i> file is a list of entries that
  430:     point to package manifests. Each line provides the chrome
  431:     registry with a pointer to a manifest in which new software is
  432:     described: new skin information, new packages, and new
  433:     locales.</p>
  434:     <p>In the following snippet from the
  435:     <i>installed-chrome.txt</i> file in the Mozilla <i>chrome</i>
  436:     directory, five entries point to <i>contents.rdf</i> type
  437:     manifests that describe the modern skin resources particular to
  438:     the application's major components. The first line in this
  439:     list, for example, tells the chrome registry to find a
  440:     <i>contents.rdf</i> file in the subdirectory
  441:     <i>skin/modern/communicator</i> contained in the
  442:     <i>modern.jar</i> file, which describes the resources present
  443:     there to skin the communicator component. When the chrome
  444:     registry reads this line, it uses those resources to skin the
  445:     communicator component, shown here:</p>
  446: <pre>
  447: skin,install,url,jar:resource:/chrome/modern.jar!/skin/modern/communicator/
  448: skin,install,url,jar:resource:/chrome/modern.jar!/skin/modern/editor/
  449: skin,install,url,jar:resource:/chrome/modern.jar!/skin/modern/global/
  450: skin,install,url,jar:resource:/chrome/modern.jar!/skin/modern/messenger/
  451: skin,install,url,jar:resource:/chrome/modern.jar!/skin/modern/navigator/
  452: </pre>
  453:     <p>Instead of installing your package with installation
  454:     scripts, you can add the appropriate entries to this file, as
  455:     seen in the following examples. Adding these entries only
  456:     registers local content on your machine. When you use the
  457:     <i>installed-chrome.txt</i> file, you neither install a new
  458:     package nor make that package installable by others. Editing
  459:     the <i>installed-chrome.txt</i> file directly is a shortcut for
  460:     making Mozilla aware of packages so that you can check your
  461:     progress as you develop. You probably need to create an
  462:     installer for packages you want to distribute and install on
  463:     other systems.</p>
  464:     <p>To register a local copy of 
  465:     <!--INDEX registration:xFly application, chrome directory;xFly:registration, chrome directory -->
  466:     the xFly application with the Mozilla <i>chrome</i> directory,
  467:     you would add the following three entries, where the
  468:     <i>xFly</i> directory and the appropriate subdirectories sit
  469:     directly under the <i>chrome</i> directory:</p>
  470: <pre>
  471: content,install,url,resource:/chrome/xfly/content/
  472: skin,install,url,resource:/chrome/xfly/skin/
  473: locale,install,url,resource:/chrome/xfly/locale/en-US/
  474: </pre>
  475:     <p>The first line tells the chrome registry that the content is
  476:     found in the directory <i>chrome/xfly/content</i>. The next
  477:     line points to the skin resources at <i>chrome/xfly/skin</i>,
  478:     and so on. Note that creating a single entry for the xFly skin
  479:     and locating its resources underneath the xFly application
  480:     directory (as opposed to a subdirectory in the modern and/or
  481:     classic JARs) means that the xFly skin will not change when the
  482:     user changes skins.</p>
  483:     <p>If we had the same structure archived in a JAR file called
  484:     <i>xfly.jar</i> rather than in a directory, the
  485:     <i>installed-chrome.txt</i> entries would look like this:</p>
  486: <pre>
  487: content,install,url,jar:resource:/chrome/xfly.jar!/content/
  488: skin,install,url,jar:resource:/chrome/xfly.jar!/skin/
  489: locale,install,url,jar:resource:/chrome/xfly.jar!/locale/en-US/
  490: </pre>
  491:     <p>This code tells the chrome registry to look in the
  492:     <i>content</i>, <i>skin</i>, and <i>locale/en-US</i>
  493:     directories in the JAR file to locate the manifests.</p>
  494:     <p>This skin entry seems to indicate that only one set of skin
  495:     information is available for the xFly sample, and that it
  496:     always applies. If the xFly skin inherits, as many skins do,
  497:     from one or another of the preinstalled theme (e.g., Modern),
  498:     it may look very bad or even break when that theme is not
  499:     selected. See the section <a href="ch04.html#77088">"Skin
  500:     inheritance and skin modularization</a>" in <a href=
  501:     "ch04.html#77060">Chapter 4</a> for a discussion of skin
  502:     inheritance and tips on how to make sure your skin is
  503:     structured to best take advantage of it.</p>
  504:     <p>When you make these additions to the
  505:     <i>installed-chrome.txt</i> file and restart Mozilla, the
  506:     chrome registry looks for manifests in the directories you
  507:     specify and registers the packages described there. The
  508:     <i>installed-chrome.txt</i> entries in this section do not
  509:     necessarily need to be included on your final XPI resource, but
  510:     you will see them in some XPIs bundled in their own
  511:     <i>installed-chrome.txt</i> file separate form the main one.
  512:     See the section <a href="#77078">"The Chrome Registry</a>" for
  513:     more information about this process.</p>
  514:     <h3><a name="77073"></a> Creating a Package</h3>
  515:     <p>The xFly sample package 
  516:     <!--INDEX packages:xFly;xFly package --> is a relatively
  517:     straightforward arrangement of content, skin, and locale. You
  518:     have already seen how to set up most preliminaries you need to
  519:     make it a package in <a href="ch02.html#77048">Chapter 2</a>,
  520:     but this section will discuss the process in detail.</p>
  521:     <h4><a name="77074"></a> Setting up xFly</h4>
  522:     <p>To start working immediately 
  523:     <!--INDEX xFly package:setup;packages:xFly:setup --> with tools
  524:     like XUL and CSS, you can move some things around and hack one
  525:     of the chrome registry files, as you have already seen. This
  526:     section reviews those important preliminary application
  527:     development steps in more detail.</p>
  528:     <p>Because it has its own interface and is not worried (for
  529:     now) about being made available in languages other than
  530:     English, the only one for which it has a language pack, the
  531:     xFly package is self-contained:</p>
  532: <pre>
  533: chrome
  534: xfly
  535: content
  536: skin
  537: locale
  538: </pre>
  539:     <p>All parts of the package can be held in a single JAR file or
  540:     a single <i>chrome</i> subdirectory. Contrast this with a large
  541:     component-like communicator that, when you include its content,
  542:     skin, localized information, and the Mozilla services it uses
  543:     via XPConnect, is spread out into all of the main JAR files
  544:     that make up the distribution:</p>
  545: <pre>
  546: chrome/modern.jar!/skins/modern/communicator/
  547: chrome/comm.jar!/content/communicator/
  548: chrome/en-US.jar!/locale/en-US/communicator/
  549: </pre>
  550:     <blockquote>
  551:       <div class="c17">
  552:         NOTE
  553:       </div>
  554:       <p>When you develop your application, it's typical to work
  555:       within a regular directory. As you finish the application and
  556:       make it available for distribution and installation, however,
  557:       you may want to use one of the installation archive formats
  558:       to package your work, such as a JAR file. See the section <a
  559:       href="#77082">"The XPI File Format</a>" later in this chapter
  560:       for more details.</p>
  561:     </blockquote>
  562:     <p>When your application is large and distributed in this way,
  563:     the RDF-based manifests "compose" all of the metadata and treat
  564:     all files as a single component.</p>
  565:     <h4><a name="77075"></a> Hacking the installed-chrome.txt
  566:     file</h4>
  567:     <p>The entries you made 
  568:     <!--INDEX installed-chrome.txt file:xFly and;xFly:installed-chrome.txt file -->
  569:     to the <i>installed-chrome.txt</i> in <a href=
  570:     "ch02.html#77048">Chapter 2</a> tell the chrome registry that a
  571:     new package must be registered:</p>
  572: <pre>
  573: content,install,url,resource:/chrome/xfly/content/
  574: skin,install,url,resource:/chrome/xfly/skin/
  575: locale,install,url,resource:/chrome/xfly/locale/en-US/
  576: </pre>
  577:     <p>These entries tell the chrome registry that, in addition to
  578:     all of the packages that make up the main Mozilla browser
  579:     (e.g., the communicator skin in the Modern theme, the en-US
  580:     locale, and the content that makes up the navigator), the xFly
  581:     <tt>content</tt>, <tt>skin</tt>, and <tt>locale</tt> should be
  582:     registered as components of a new package. When the chrome
  583:     registry reads these entries, it tries to find the manifests
  584:     for these parts of the xFly package. When it finds them, it
  585:     registers the package, overlays any files it finds in that
  586:     package (see the next section), and makes it accessible via the
  587:     special <i>chrome://</i> URLs given in the manifests.</p>
  588:     <h4><a name="77076"></a> Adding the xFly application to the
  589:     Mozilla Tools menu</h4>
  590:     <p>Adding your application <!--INDEX xFly:Tools menu --> to one
  591:     of the Mozilla browser menus (so users can easily launch your
  592:     application once it is installed) makes your application feel
  593:     official. <a href="#77006">Figure 6-3</a> shows the presence of
  594:     the xFly item in the Tools menu. The Tools menu lists various
  595:     extra components in Mozilla, including the DOM Inspector and
  596:     the JavaScript Debugger (if they are installed).</p>
  597:     <div class="c16">
  598:       <img src="foo.gif">
  599:     </div>
  600:     <p><i>Figure 6-3: <a name="77006"></a></i> <i>xFly item in
  601:     Tools menu</i></p>
  602:     <p>It is also possible to add an item to the Window menu that
  603:     includes links to Navigator (the default browser), the Mail and
  604:     Newsgroup client, the Chatzilla IRC client, Composer, and the
  605:     Address Book (which only show up if they were added as part of
  606:     the Mozilla installation process or if they were added
  607:     separately afterwards).</p>
  608:     <p>Here we describe how you can use special constructions in
  609:     your package's manifest to tell the chrome registry about files
  610:     from your package that should be overlaid into the main
  611:     browser. Overlaying these files lets you add interface items,
  612:     such as this link to xFly, in an existing application. <a href=
  613:     "#77028">Example 6-5</a> shows the simple overlay file that
  614:     puts xFly in the Tools menu.</p>
  615:     <p>The top-level element is an <tt>&lt;overlay/&gt;</tt> rather
  616:     than a <tt>&lt;window/&gt;</tt>. Direct children of the overlay
  617:     are associated with certain elements in the main browser (in
  618:     this case, the <tt>&lt;menupopup/&gt;</tt> of the Tools menu)
  619:     and their contents are interpolated into the list of children
  620:     there. This file overlays an extra <tt>&lt;menuitem/&gt;</tt>
  621:     into the Tools menu. In this case, the <tt>menuitem</tt> has an
  622:     <tt>oncommand</tt> event handler that calls
  623:     <tt>toOpenWindowByType-</tt>a function for opening new chrome
  624:     defined in the <i>tasksOverlay.js</i> that much of the chrome
  625:     in the Mozilla UI imports.</p>
  626:     <p><i>Example 6-5: <a name="77028"></a></i> <i>The xFly
  627:     overlay</i></p>
  628: <pre>
  629:  &lt;?xml version="1.0"?&gt;
  630:  &lt;overlay id="xflyTasksOverlay"
  631:     xmlns="<a href=
  632: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</a>"&gt;
  633:    &lt;menupopup id="taskPopup"&gt;
  634:      &lt;menuitem label="xFly"
  635:          oncommand="toOpenWindowByType(`xfly:main', `chrome://xfly/content/');" /&gt;
  636:    &lt;/menupopup&gt;
  637:  &lt;/overlay&gt;
  638: </pre>
  639:     <p>But how does the overlay know where to overlay itself? The
  640:     IDs of the overlay children and the original XUL are matched to
  641:     find the target within the files, but the manifest that
  642:     accompanies the overlay in your package tells Mozilla which
  643:     overlays are associated with which XUL files. The part of the
  644:     manifest that deals with an overlay looks like the code in <a
  645:     href="#77030">Example 6-6</a>. This code is put in the
  646:     <i>contents.rdf</i> file in the <i>content</i> directory of the
  647:     xFly package.</p>
  648:     <p><i>Example 6-6: <a name="77030"></a></i> <i>Overlay
  649:     information in the manifest</i></p>
  650: <pre>
  651:  &lt;!-- overlay information --&gt;
  652:    &lt;RDF:Seq about="urn:mozilla:overlays"&gt;
  653:      &lt;RDF:li resource="chrome://communicator/content/tasksOverlay.xul" /&gt;
  654:    &lt;/RDF:Seq&gt;
  655:    &lt;RDF:Seq about="chrome://communicator/content/tasksOverlay.xul"&gt;
  656:      &lt;RDF:li&gt;chrome://xfly/content/xflyOverlay.xul&lt;/RDF:li&gt;
  657:    &lt;/RDF:Seq&gt;
  658: </pre>
  659:     <p>The first RDF element in the manifest is a list of affected
  660:     target files and the second is a list of files that should be
  661:     overlayed into those targets. Do not be confused by the names
  662:     of the files in this case: the <i>tasksOverlay.xul</i> file is
  663:     a target-though it is an overlay, as described in the following
  664:     section-and <i>xflyOverlay.xul</i> is the overlay with the xFly
  665:     menu item.</p>
  666:     <h4><a name="77077"></a> Overlaying Mozilla files into your
  667:     application</h4>
  668:     <p>In the previous section, we 
  669:     <!--INDEX files:overlaying into application;applications:overlaying files to;overlays:overlaying files into application -->
  670:     described how to use the XUL overlay technology to put
  671:     information from your application into the Mozilla browser.
  672:     When developers use overlays in this way, they usually add a
  673:     <tt>menuitem</tt> or a new UI to the browser that provides
  674:     access to the application.</p>
  675:     <p>But overlays can also add interface elements and other data
  676:     from Mozilla into the application itself. In fact, each
  677:     component in Mozilla imports a lot of its own user interface
  678:     from such XUL overlay mainstays as <i>globalOverlay.xul</i>,
  679:     <i>tasksOverlay.xul</i> (the file into which the xFly
  680:     <tt>menuitem</tt> is overlaid), and
  681:     <i>navigatorOverlay.xul</i>. As you can see when you look at
  682:     the main browser file, <i>navigator.xul</i>, shown in <a href=
  683:     "#77032">Example 6-7</a>, most user interface is actually
  684:     brought in from these reusable overlays. A relatively small
  685:     percentage of all that appears in the browser is defined within
  686:     that particular <i>navigator.xul</i> file.</p>
  687:     <p><i>Example 6-7: <a name="77032"></a></i> <i>Overlays in
  688:     navigator.xul</i></p>
  689: <pre>
  690:  &lt;?xul-overlay href="chrome://navigator/content/navigatorOverlay.xul"?&gt;
  691:  &lt;?xul-overlay href="chrome://navigator/content/navExtraOverlay.xul"?&gt;
  692:  &lt;?xul-overlay href="chrome://navigator/content/linkToolbarOverlay.xul"?&gt;
  693:  &lt;?xul-overlay href="chrome://communicator/content/sidebar/sidebarOverlay.xul"?&gt;
  694:  &lt;?xul-overlay href="chrome://communicator/content/securityOverlay.xul"?&gt;
  695:  &lt;?xul-overlay href="chrome://communicator/content/communicatorOverlay.xul"?&gt;
  696:  &lt;?xul-overlay href="chrome://communicator/content/bookmarks/bookmarksOverlay.xul"?&gt;
  697: </pre>
  698:     <p>Of these overlays, those with 
  699:     <!--INDEX communicatorOverlay.xul file;overlays:communicatorOverlay.xul file -->
  700:     the most value for application developers are the
  701:     <i>communicatorOverlay.xul</i>, which defines many of browser
  702:     menus; the <i>tasksOverlay.xul</i>, which adds the Tools menu 
  703:     <!--INDEX tasksOverlay.xul file;overlays:tasksOverlay.xul file -->
  704:     and brings in all of its application <tt>menuitems</tt> as well
  705:     as a lot of important browser functions like
  706:     <tt>toOpenWindowByType</tt> and <tt>toNavigator</tt> (for
  707:     returning to the main browser window); and the
  708:     <tt>globalOverlay</tt> (which is overlaid into
  709:     <i>navigatorOverlay.xul</i>, so it gets loaded there), which
  710:     defines even more general and low-level features like pop ups
  711:     and functions for quitting the application or setting tooltip
  712:     text.</p>
  713:     <p>Once files are divided into subdirectories and the manifests
  714:     for each subdirectory, your application is technically a
  715:     package-although until you compress it and create an install
  716:     script, it's a package only for your computer and the
  717:     environment in which it was created. See the section <a href=
  718:     "#77096">"Finishing Things Up</a>" later in this chapter to see
  719:     how you can use the file format and installation information to
  720:     make the xFly something you can put on a web server and have
  721:     users install with a single click on a web page.</p>
  722:     <h3><a name="77078"></a> The Chrome Registry</h3>
  723:     <p>The chrome registry was briefly 
  724:     <!--INDEX chrome:registry;registration:chrome registry -->
  725:     mentioned several times in this book. It plays an important
  726:     (but sometimes invisible) role in the way Mozilla applications,
  727:     including the Mozilla browser itself, deal with user
  728:     information, new components, skins, and other resources.</p>
  729:     <p>At the beginning of the book, you had to create RDF files
  730:     that would describe your application to Mozilla. Special
  731:     entries also needed to be made to the
  732:     <i>installed-chrome.txt</i> file in the <i>chrome</i>
  733:     application directory. These entries are just two of the most
  734:     common ways to address the chrome registry, which is what
  735:     Mozilla uses to persist configurable aspects of the browser and
  736:     its other applications.</p>
  737:     <h4><a name="77079"></a> Where is the chrome registry?</h4>
  738:     <p>The chrome registry is not a single file and it's not stored
  739:     in a single place. Rather, it is a distributed collection of
  740:     data and interfaces for data manipulation. The data itself
  741:     generally lives in RDF files, many of which are in the
  742:     <i>chrome</i> application directory. The chrome registry
  743:     APIs-principally <tt>nsIChromeRegistry-</tt>are used by
  744:     installation scripts when they register new 
  745:     <!--INDEX nsIChromeRegistry --> software, by the skin-switching
  746:     UI, and by the language selection facility. The chrome registry
  747:     is the means through which packages are registered.</p>
  748:     <p>In some cases, especially when you create and debug your
  749:     Mozilla application, you may want to edit the RDF files that
  750:     make up the chrome registry directly. But more often, you can
  751:     use external scripts, inline JavaScript, or the
  752:     <i>installed-chrome.txt</i> file to get what you need from the
  753:     registry. Procedures for doing so are described in the section
  754:     <a href="#77070">"Registering Packages</a>" earlier in this
  755:     chapter, and in the section <a href="#77085">"Installation
  756:     Scripts</a>" later in this chapter.</p>
  757:     <h4><a name="77080"></a> Accessing the chrome registry in
  758:     installation scripts</h4>
  759:     <p>An install script is a 
  760:     <!--INDEX installation scripts:chrome registry access;chrome:registry:installation scripts;scripts:installation scripts:chrome registry -->
  761:     required part of a software package like the xFly. The two main
  762:     functions of an installation script are the physical download
  763:     and installation of files in the package and registration of
  764:     that software with the chrome registry. Install scripts use
  765:     functions from the XPInstall API to install the files and
  766:     functions from the chrome registry interface to handle the
  767:     latter, as seen in this snippet:</p>
  768: <pre>
  769: registerChrome(PACKAGE | DELAYED_CHROME, getFolder("Chrome", "help"), "content/");
  770: </pre>
  771:     <p>The registration process is typically something that happens
  772:     between the install initialization and the actual execution of
  773:     the install:</p>
  774: <pre>
  775: initInstall( ) // initialize the overall installation
  776: // add items to installed using:
  777: // addFolder, addDirectory, getFolder, and others
  778: registerChrome(TYPE, dir, subdir)
  779: performInstall( );
  780: </pre>
  781:     <p>Scripts and the installation process, including the
  782:     registration of installed packages, are detailed in the next
  783:     section.</p>
  784:     <h2><a name="77081"></a> Installing Mozilla Applications</h2>
  785:     <p>Once your application 
  786:     <!--INDEX applications:installation;installation:applications -->
  787:     is packaged, the next step is to create a cross-platform
  788:     installation, or XPI. A XPI is a special file archive that
  789:     contains your Mozilla package(s) and its own installation
  790:     instructions. The relationship of the various parts of the
  791:     installation process-the XPI itself, the internal installation
  792:     script, the trigger script that begins the installation, and
  793:     the Mozilla browser-can be visualized in <a href=
  794:     "#77008">Figure 6-4</a>.</p>
  795:     <div class="c16">
  796:       <img src="foo.gif">
  797:     </div>
  798:     <p><i>Figure 6-4: <a name="77008"></a></i> <i>Installation
  799:     process overview</i></p>
  800:     <h3><a name="77082"></a> The XPI File Format</h3>
  801:     <p>Mozilla cross-platform installations 
  802:     <!--INDEX XPI files:formats;installation:applications:XPI file formats;applications:installation:XPI file formats -->
  803:     use XPIs as the file format in which to organize, compress, and
  804:     automate software installations and software updates. A XPI is
  805:     a PKZIP-compressed archive (like ZIP and JAR files) with a
  806:     special script at the highest level that manages the
  807:     installation. A quick scan of the contents of a XPI file (which
  808:     you can open using with any unzip utility) reveals the
  809:     high-level directory structure shown in <a href=
  810:     "#77034">Example 6-8</a>.</p>
  811:     <p><i>Example 6-8: <a name="77034"></a></i> <i>Top level of the
  812:     browser.xpi archive</i></p>
  813: <pre>
  814:  install.js
  815:  bin\
  816:    chrome\
  817:    components
  818:    defaults\
  819:    icons\
  820:    plugins\
  821:    res\
  822: </pre>
  823:     <p>Note that the high-level structure in <a href=
  824:     "#77034">Example 6-8</a> parallels the installed browser's
  825:     directory structure very closely. The <i>bin</i> directory at
  826:     the highest level of the archive corresponds to the Mozilla
  827:     application directory. On Unix, this directory is actually
  828:     called bin, where all of the resources are stored. On other
  829:     platforms, the installation puts these resources in the
  830:     application directory itself.</p>
  831:     <p>In the case of the Mozilla browser, the XPIs manage the
  832:     transfer and registry of all components-the chrome files in the
  833:     JARs, the executables, the default user information, and the
  834:     libraries. As you will see in the installation script, the
  835:     contents of the archive are installed onto the filesystem in
  836:     much the same way as they are stored in the archive itself,
  837:     although it's possible to rearrange things arbitrarily upon
  838:     installation-to create new directories, install files in system
  839:     folders and other areas, or execute software that handles other
  840:     aspects of the installation, such as third-party
  841:     installers.</p>
  842:     <h4><a name="77083"></a> XPI example</h4>
  843:     <p>When the items to be installed are very simple, XPIs may
  844:     contain nothing more than a single executable and the install
  845:     script itself, as shown in <a href="#77010">Figure 6-5</a>. In
  846:     this figure, the WinZip utility has been used to display the
  847:     contents of a XPI that installs a text editor on a Win32
  848:     system.</p>
  849:     <div class="c16">
  850:       <img src="foo.gif">
  851:     </div>
  852:     <p><i>Figure 6-5: <a name="77010"></a></i> <i>Simplest XPI
  853:     archive</i></p>
  854:     <p>This example uses XPInstall technology to install something
  855:     that may or may not be a Mozilla application. The
  856:     <i>install.js</i> script in <a href="#77034">Example 6-8</a>
  857:     would look like this. In Mozilla application development,
  858:     however, XPIs often contain JAR files that are installed as new
  859:     packages in the Mozilla distribution. To make a XPI for your
  860:     package, use any zip software (applications or extensions that
  861:     will be part of the main Mozilla distribution are required to
  862:     use the free <i>zip</i> utility from InfoTools so that they can
  863:     be run as part of the build process) to archive your files.</p>
  864:     <h4><a name="77084"></a> JARs versus XPIs</h4>
  865:     <p>Technically, only the internal 
  866:     <!--INDEX JAR (Java Archive) files:XPIs and;XPIs, JARs and -->
  867:     installation script distinguishes JARs and XPIs. However,
  868:     Mozilla treats them differently. Since JARs do not include this
  869:     installation script, they cannot install full content or
  870:     applications by themselves. In this case, "content" means XUL,
  871:     XBL, or JavaScript files that have script access to XPCOM.
  872:     Files of this kind that are in JARs are denied access to
  873:     XPConnect and are not registered as content in the chrome
  874:     registry. JARs are used primarily to install locales, or
  875:     language packs, and skins.</p>
  876:     <p>Skins that contain scripts 
  877:     <!--INDEX skins:scripts and;skins:bindings and;bindings:skins;scripts:skins -->
  878:     and bindings (see the section <a href="ch04.html#77103">"Theme
  879:     Security Restrictions</a>" and the <a href=
  880:     "ch04.html#62192">"Evil Skins</a>" sidebar, both in <a href=
  881:     "ch04.html#77060">Chapter 4</a>) are seen more as chrome
  882:     content and must be installed in XPIs if they are to be fully
  883:     functional. Like executables that are fetched from the Web,
  884:     XPIs can cause trouble when downloaded by unprepared users
  885:     since the software in XPIs are given the same privileges on the
  886:     Mozilla platform that the browser chrome itself has.</p>
  887:     <p>The characteristics and usage 
  888:     <!--INDEX XPI files:characteristics;JAR (Java Archive) files:characteristics -->
  889:     of an XPI are:</p>
  890:     <ul>
  891:       <li>Has an <i>install.js</i> file</li>
  892:       <li>Can install anything via XPInstall API</li>
  893:       <li>PKZip-compressed</li>
  894:       <li>May contain one or more JAR packages</li>
  895:       <li>Mozilla installation</li>
  896:       <li>Used for new packages</li>
  897:     </ul>
  898:     <p>The characteristics and usage of a JAR are:</p>
  899:     <ul>
  900:       <li>Contains only the resources themselves</li>
  901:       <li>Installed with an external script</li>
  902:       <li>May be installed inside a XPI</li>
  903:       <li>PKZip-compressed</li>
  904:       <li>Themes</li>
  905:       <li>Languages packs</li>
  906:       <li>Storage archive for installed components</li>
  907:     </ul>
  908:     <p>Mozilla uses the presence of this internal installation
  909:     script and not the file suffix (which can be changed easily
  910:     enough) to determine what type of archive it is. Accordingly,
  911:     JARs are most often used to install new themes and new language
  912:     packs, which can be done by using just a brief trigger script
  913:     on a web page loaded into Mozilla. When they contain new
  914:     chrome-new XUL and JavaScript that will access the Mozilla
  915:     objects via XPConnect-JAR files must be put within a XPI that
  916:     can register them properly.</p>
  917:     <h3><a name="77085"></a> Installation Scripts</h3>
  918:     <p>Most new packages in 
  919:     <!--INDEX installation scripts;scripts;installation scripts -->
  920:     Mozilla are <!--INDEX JavaScript:installation scripts -->
  921:     installed by means of installation scripts. These scripts are
  922:     written in JavaScript. Unlike regular web page JavaScript,
  923:     however, which uses <tt>window</tt> as the top-level object,
  924:     installation scripts have a special install object context. As
  925:     you will see in the following examples, the <tt>Install</tt>
  926:     object-even when it's implicit and not prefixed to the object
  927:     methods-is the top-level object upon which most methods are
  928:     called.</p>
  929:     <h4><a name="77086"></a> Script examples</h4>
  930:     <p>At their very simplest, installation scripts look something
  931:     like <a href="#77036">Example 6-9</a>.</p>
  932:     <p><i>Example 6-9: <a name="77036"></a></i> <i>Simple install
  933:     script</i></p>
  934: <pre>
  935:  // initialize the installation first
  936:  initInstall("My Package Install", "package_name", "1.0", 1);
  937:  // add files to the installation
  938:  f = getFolder("Program");
  939:  setPackageFolder(f);
  940:  addFile("package.xpi")
  941:  // perform the installation
  942:  performInstall( );
  943: </pre>
  944:     <p>These methods are being called on the <tt>Install</tt>
  945:     object, which is implicit in an installation script. <a href=
  946:     "#77038">Example 6-10</a> is an equivalent (and still very
  947:     compact) installation script. The <tt>Install</tt> object is
  948:     prefixed explicitly to the install functions. Example 6-10<a
  949:     name="77038"></a> <i>Script that explicitly prefixes the
  950:     Install object</i></p>
  951: <pre>
  952:  Install.initInstall("My Package Install", "package_name", "1.0", 1);
  953:  f = Install.getFolder("Program");
  954:  Install.setPackageFolder(f);
  955:  Install.addFile("package.xpi")
  956:  Install.performInstall( );
  957: </pre>
  958:     <p>As they become more complicated, install scripts may set up
  959:     and arrange target directories in more specific ways, do more
  960:     error checking, and include variables to make the code more
  961:     readable and reusable, as seen in the longer install script in
  962:     <a href="#77040">Example 6-11</a>. Example 6-11<a name=
  963:     "77040"></a> <i>A more complicated install script</i></p>
  964: <pre>
  965:  var vi = "10.10.10.10";
  966:  var xpiSrc = "adddir1";
  967:  initInstall("addFileNoVers1", "adddir_1", vi, 1);
  968:  f = getFolder("Program");
  969:  setPackageFolder(f);
  970:  err = addDirectory(xpiSrc);
  971:  logComment("the error = " + err);
  972:  if (0 == getLastError( ))
  973:    performInstall( );
  974:  else
  975:    cancelInstall( );
  976: </pre>
  977:     <h4><a name="77087"></a> Web page installations</h4>
  978:     <p>XPInstall technology makes software installation 
  979:     <!--INDEX installation:from web page[installation:web page];XPInstall:installation from web page -->
  980:     from a web page very easy. When a link on a web page kicks off
  981:     the installation of new software, "trigger" code on the web
  982:     page starts the process and gets the XPI onto the local system.
  983:     Once this is done, the <i>install.js</i> file in the XPI can
  984:     take up the full installation and registration of new
  985:     files.</p>
  986:     <p>In <a href="#77042">Example 6-12</a>, the trigger
  987:     script-placed in an <tt>onclick</tt> event handler on the
  988:     page-starts the installation of a new theme on the local
  989:     machine, where the XPI can be unpacked and its installation
  990:     script executed in full. Example 6-12<a name="77042"></a>
  991:     <i>Trigger script on a web page</i></p>
  992: <pre>
  993:  &lt;a href="#"
  994:     onclick="InstallTrigger.installChrome(
  995:     InstallTrigger.SKIN,
  996:     '<a href=
  997: "http://wildskins/newblue.xpi">http://wildskins/newblue.xpi</a>',
  998:     'newblue/1.0');"&gt;
  999:     Install the New Blue theme&lt;/a&gt;
 1000: </pre>
 1001:     <p>Later, we discuss in more detail the <tt>Install</tt>
 1002:     object, whose methods are typically called in installation
 1003:     scripts.</p>
 1004:     <h4><a name="77088"></a> Scriptless installations</h4>
 1005:     <p>When you have a simple Mozilla package like a 
 1006:     <!--INDEX installation:scriptless;scriptless installations -->
 1007:     theme, which does not need special security privileges and
 1008:     which is always installed in a particular location, you can
 1009:     leave out the XPI and its internal installation script
 1010:     altogether and use a trigger script like <a href=
 1011:     "#77044">Example 6-13</a> and a regular JAR file to download
 1012:     and register the new package. Example 6-13<a name="77044"></a>
 1013:     <i>Scriptless install of a JAR</i></p>
 1014: <pre>
 1015:  &lt;a href="#"
 1016:     onclick="InstallTrigger.installChrome(
 1017:     InstallTrigger.SKIN,
 1018:     '<a href=
 1019: "http://wildskins/newblue.jar">http://wildskins/newblue.jar</a>',
 1020:     'newblue/1.0');"&gt;
 1021:     Install the New Blue theme&lt;/a&gt;
 1022: </pre>
 1023:     <p>The only difference here is that the item to be installed is
 1024:     a JAR and not a XPI file. Also, no internal installation script
 1025:     is present (since of the two, only XPIs carry their own
 1026:     <i>install.js</i> file). When the <tt>InstallTrigger</tt>
 1027:     object gets a JAR with a package manifest it can read and a
 1028:     package type that doesn't break the security boundary for
 1029:     applications (i.e., a new theme, a new language pack, or new
 1030:     content that doesn't use XPConnect), it can download and
 1031:     register that package with the chrome registry and make it
 1032:     available to users. The JAR and a trigger script like the one
 1033:     just shown are all you need in this case. See the earlier
 1034:     section, <a href="#77084">"JARs versus XPIs</a>" for more
 1035:     detail on the limitations of scriptless installs.</p>
 1036:     <blockquote>
 1037:       <div class="c17">
 1038:         NOTE
 1039:       </div>
 1040:       <p>The xFly application accesses XPCOM objects in Mozilla,
 1041:       which makes it a full-blown XPConnected application. Thus, it
 1042:       needs to be installed in a XPI file that has its own internal
 1043:       installation script.</p>
 1044:     </blockquote>
 1045:     <h4><a name="77089"></a> Platform-dependent installation</h4>
 1046:     <p>Though the XPI format is by definition cross-platform, 
 1047:     <!--INDEX installation:platform-dependent;platform-dependent installation -->
 1048:     the files you distribute within it may need to be installed on
 1049:     a per-platform basis. The platform can be retrieved using the
 1050:     <tt>platform</tt> property of the <tt>Install</tt> object or
 1051:     the <tt>getFolder</tt> function. <a href="#77046">Example
 1052:     6-14</a> shows a JavaScript function for <i>install.js</i> for
 1053:     returning the platform that the script is running on. Example
 1054:     6-14<a name="77046"></a> <i>Getting the operating system in an
 1055:     install script</i></p>
 1056: <pre>
 1057:  function getPlatform( )
 1058:  {
 1059:      var platformStr;
 1060:      var platformNode;
 1061:      if('platform' in Install)
 1062:      {
 1063:          platformStr = new String(Install.platform);
 1064:          if (!platformStr.search(/^Macintosh/))
 1065:              platformNode = 'mac';
 1066:          else if (!platformStr.search(/^Win/))
 1067:              platformNode = 'win';
 1068:          else
 1069:              platformNode = 'unix';
 1070:      }
 1071:      else
 1072:      {
 1073:          var fOSMac  = getFolder("Mac System");
 1074:          var fOSWin  = getFolder("Win System");
 1075:          logComment("fOSMac: "  + fOSMac);
 1076:          logComment("fOSWin: "  + fOSWin);
 1077:          if(fOSMac != null)
 1078:              platformNode = 'mac';
 1079:          else if(fOSWin != null)
 1080:              platformNode = 'win';
 1081:          else
 1082:              platformNode = 'unix';
 1083:      }
 1084:      return platformNode;
 1085:  }
 1086: </pre>
 1087:     <p>It's often necessary to check the platform when you install
 1088:     new language packs. At the time of this writing, issues related
 1089:     to write access to the chrome folder on Unix systems require
 1090:     some forking in the install script. There are also certain JAR
 1091:     files that are installed on a per-platform basis in language
 1092:     packs. <a href="#77046">Example 6-14</a> covers the three major
 1093:     platforms (Windows, Mac, and *nix). Here is how you use it:</p>
 1094: <pre>
 1095: platformNode = getPlatform( );
 1096: if (platformNode != 'unix') {
 1097: // do Unix script and files
 1098: }
 1099: else if (platformNode != 'win') {
 1100: // do Windows script and files
 1101: }
 1102: else {  // mac
 1103: // do Mac script and files
 1104: }
 1105: </pre>
 1106:     <h4><a name="77090"></a> The install log</h4>
 1107:     <p>When you are testing your XPI or need a way 
 1108:     <!--INDEX installation:logs;logging installation --> to
 1109:     troubleshoot installation problems, one of the best methods is
 1110:     to consult <!--INDEX install.log file --> the installation log
 1111:     file. This file is called <i>install.log</i> and lives in the
 1112:     <i>bin</i> directory.</p>
 1113:     <p>The <i>install.log</i> file is generated the first time you
 1114:     try to install software in Mozilla and appended to for each
 1115:     subsequent installation. The format of the file-in which the
 1116:     URL and date of the installation appear as a heading-makes it
 1117:     easy to find the installation you are checking on in the
 1118:     install log.</p>
 1119:     <p><a href="#77048">Example 6-15</a> shows the output in
 1120:     <i>install.log</i> after a single successful installation.
 1121:     Example 6-15<a name="77048"></a> <i>install.log</i></p>
 1122: <pre>
 1123:  -------------------------------------------------------------------------------
 1124:  <a href=
 1125: "http://books.mozdev.org/examples/xfly.xpi">http://books.mozdev.org/examples/xfly.xpi</a>  --  06/28/2002 19:12:59
 1126:  -------------------------------------------------------------------------------
 1127:       Install xFly (version 0.0.1)
 1128:       ------------
 1129:       &lt;/td&gt;[1/4]    Installing: C:\MOZILLA\BIN\chrome\xfly.jar
 1130:       [2/4]    Register Content: jar:resource:/chrome/xfly.jar!/content/
 1131:       [3/4]    Register Skin: jar:resource:/chrome/xfly.jar!/skin/
 1132:       [4/4]    Register Locale: jar:resource:/chrome/xfly.jar!/locale/en-US/
 1133:       Install completed successfully  --  06/28/2002 19:13:03
 1134: </pre>
 1135:     <p>In your <i>install.js</i> file, you can use 
 1136:     <!--INDEX logComment( ) method;methods:logComment( ) --> the
 1137:     method <tt>logComment</tt> to create output other than these
 1138:     standard logging messages. This can be very useful for
 1139:     debugging your install scripts or providing extra feedback:</p>
 1140: <pre>
 1141: logComment( "Installation started ..." );
 1142: </pre>
 1143:     <p>The output for this call will appear in <i>install.log</i>
 1144:     formatted like this:</p>
 1145: <pre>
 1146: ** Installation started ...
 1147: </pre>
 1148:     <p>When installation is not smooth, Mozilla 
 1149:     <!--INDEX errors, installation and;installation:error codes -->
 1150:     outputs an error code to track down what is happening. For
 1151:     example, if you declare a constant variable twice in your
 1152:     install script, you will receive notification of an script
 1153:     error in the UI, and this error will be logged in
 1154:     <i>install.log</i>:</p>
 1155: <pre>
 1156: ** Line: 4    redeclaration of const X_JAR_FILE
 1157: Install **FAILED** with error -229  --  07/01/2002 11:47:53
 1158: </pre>
 1159:     <p>A full list of error codes can be found at <i><a href=
 1160:     "http://lxr.mozilla.org/seamonkey/source/xpinstall/src/nsInstall.h">
 1161:     http://lxr.mozilla.org/seamonkey/source/xpinstall/src/nsInstall.h</a></i>
 1162:     or in the <i>XPInstall API Reference</i> at <i><a href=
 1163:     "http://developer.netscape.com/docs/manuals/xpinstall/err.html">
 1164:     http://developer.netscape.com/docs/manuals/xpinstall/err.html</a></i>.</p>
 1165:     <blockquote>
 1166:       <div class="c17">
 1167:         NOTE
 1168:       </div>
 1169:       <p>Though XPInstall is enabled by default, there is
 1170:       preference to turn it on and off in the user profile
 1171:       preferences file (<i>prefs.js</i>). To disable XPInstall, set
 1172:       the preference like this:</p>
 1173:     </blockquote>
 1174:     user_pref("xpinstall.enabled", false); 
 1175:     <blockquote>
 1176:       <p>And be aware that target installation platforms may have
 1177:       this preference turned off, which prevents you from
 1178:       installing any new software in Mozilla.</p>
 1179:     </blockquote>
 1180:     <h3><a name="77091"></a> XPInstall</h3>
 1181:     <p>XPInstall is a technology used for <!--INDEX XPInstall --> 
 1182:     <!--INDEX installation:(see also XPInstall)[installation:zz(see also XPInstall)] -->
 1183:     cross-platform installation. Mozilla uses it extensively to
 1184:     install new packages, but as a general-purpose technology, it
 1185:     can be used to install anything on your computer. The XPI file
 1186:     format we described in the section <a href="#77082">"The XPI
 1187:     File Format</a>" earlier in this chapter is the basic unit of
 1188:     exchange in an XPInstall and the installation script manages
 1189:     the installation.</p>
 1190:     <p>Installation scripts-whether they appear within the XPI, on
 1191:     a web page as an external "trigger script," or elsewhere in
 1192:     JavaScript-use the XPInstall API to do all the heavy lifting.
 1193:     The XPInstall API includes installation functions (<a href=
 1194:     "#77050">Example 6-16</a>) organized into such high-level
 1195:     objects as the <tt>Install</tt> object, the
 1196:     <tt>InstallTrigger</tt> object, and the <tt>File</tt> object,
 1197:     which you can use to install new Mozilla 
 1198:     <!--INDEX XPInstall:functions;functions:XPInstall --> packages.
 1199:     Example 6-16<a name="77050"></a> <i>Common XPInstall
 1200:     functions</i></p>
 1201: <pre>
 1202:  initInstall( )      // initializes every installation
 1203:  getFolder( )        // creates a new folder on the target system
 1204:  addFile( )          // adds files and directories to the install
 1205:  performInstall( )   // executes the installation
 1206:  cancelInstall( )    // cancels installation if there are errors
 1207: </pre>
 1208:     <p>In addition to the XPInstall API installation functions,
 1209:     installation scripts often call methods on the chrome registry
 1210:     itself. As described earlier in this chapter in the <a href=
 1211:     "#77078">"The Chrome Registry</a>" section, the chrome registry
 1212:     handles the registration of new files and packages on the local
 1213:     system, the maintenance of user configurable data (such as what
 1214:     skin or theme you currently selected), and several utility
 1215:     functions used to make installations easier and more
 1216:     successful.</p>
 1217:     <h4><a name="77092"></a> The Install object</h4>
 1218:     <p>The <tt>Install</tt> object is the main object 
 1219:     <!--INDEX Install object, XPInstall;objects:Install (XPInstall);XPInstall:Install object -->
 1220:     in the XPInstall API. It provides most of the methods and
 1221:     properties used in installation scripts.</p>
 1222: <pre>
 1223: initInstall(displayName, name, version, flags)
 1224: </pre>
 1225:     <p>The <tt>initInstall( )</tt> method that 
 1226:     <!--INDEX initInstall( ) method, XPInstall;XPInstall:iniInstall( ) method -->
 1227:     initializes the installation process takes the following
 1228:     parameters: <i>displayName</i> is the name you give to the
 1229:     installation itself; <i>name</i> is the name of the package to
 1230:     be installed (which must match the name given to the package in
 1231:     the manifests); <i>version</i> is the version of the package
 1232:     being installed (also specified in the manifest); and
 1233:     <i>flags</i> is an optional parameter reserved for future use
 1234:     (which is set to "0" by default and about which you don't have
 1235:     to worry).</p>
 1236: <pre>
 1237: Example: initInstall("Example Installation", "xfly", "0.9", 0);
 1238: addFile(file)
 1239: </pre>
 1240:     <p>The <tt>addFile( )</tt> method adds a 
 1241:     <!--INDEX addFile( ) method, XPInstall;methods:addFile( ), XPInstall;XPInstall:addFile( ) method -->
 1242:     single file to the initialized installation. <tt>file</tt> is a
 1243:     pointer to the file in the XPI that will be installed.</p>
 1244: <pre>
 1245: Example: addFile("simple.exe");
 1246: err = performInstall( )
 1247: </pre>
 1248:     <p>The <tt>performInstall( )</tt> method starts 
 1249:     <!--INDEX performInstall( ) method, XPInstall;XPInstall:performInstall( ) method;methods:XPInstall:performInstall( ) -->
 1250:     the installation that you set up.</p>
 1251: <pre>
 1252: Example: performInstall( );
 1253: </pre>
 1254:     <p>The <tt>Install</tt> object exposes the methods listed in <a
 1255:     href="#77016">Table 6-1</a>.</p>
 1256:     <p><i>Table 6-1: <a name="77016"></a></i> <i>Install object
 1257:     methods</i></p>
 1258:     <tt>addFile</tt>method.<i>.ini</i>file.
 1259:     <table width="100%" border="1">
 1260:       <tr>
 1261:         <td><b>Method</b></td>
 1262:         <td><b>Description</b></td>
 1263:       </tr>
 1264:       <tr>
 1265:         <td>AddDirectory</td>
 1266:         <td>Unpacks an entire subdirectory.</td>
 1267:       </tr>
 1268:       <tr>
 1269:         <td>AddFile</td>
 1270:         <td>Unpacks a single file.</td>
 1271:       </tr>
 1272:       <tr>
 1273:         <td>Alert</td>
 1274:         <td>Displays an Alert dialog box with a message and an OK
 1275:         button.</td>
 1276:       </tr>
 1277:       <tr>
 1278:         <td>CancelInstall</td>
 1279:         <td>Aborts the installation of the software.</td>
 1280:       </tr>
 1281:       <tr>
 1282:         <td>Confirm</td>
 1283:         <td>Displays a Confirm dialog box with the specified
 1284:         message and OK and Cancel buttons.</td>
 1285:       </tr>
 1286:       <tr>
 1287:         <td>deleteRegisteredFile</td>
 1288:         <td>Deletes the specified file and its entry in the Client
 1289:         Version Registry.</td>
 1290:       </tr>
 1291:       <tr>
 1292:         <td>Execute</td>
 1293:         <td>Extracts a file from the XPI file to a temporary
 1294:         location and schedules it for later execution.</td>
 1295:       </tr>
 1296:       <tr>
 1297:         <td>Gestalt</td>
 1298:         <td>Retrieves information about the operating environment
 1299:         (Mac OS only).</td>
 1300:       </tr>
 1301:       <tr>
 1302:         <td>GetComponentFolder</td>
 1303:         <td>Returns an object representing the directory in which a
 1304:         component is installed.</td>
 1305:       </tr>
 1306:       <tr>
 1307:         <td>GetFolder</td>
 1308:         <td>Returns an object representing a directory, for use
 1309:         with the</td>
 1310:       </tr>
 1311:       <tr>
 1312:         <td>GetLastError</td>
 1313:         <td>Returns the most recent nonzero error code.</td>
 1314:       </tr>
 1315:       <tr>
 1316:         <td>getWinProfile</td>
 1317:         <td>Constructs an object for working with a Windows</td>
 1318:       </tr>
 1319:       <tr>
 1320:         <td>getWinRegistry</td>
 1321:         <td>Constructs an object for working with the Windows
 1322:         registry.</td>
 1323:       </tr>
 1324:       <tr>
 1325:         <td>InitInstall</td>
 1326:         <td>Initializes installation for the given software and
 1327:         version.</td>
 1328:       </tr>
 1329:       <tr>
 1330:         <td>LoadResources</td>
 1331:         <td>Returns an object whose properties are localized
 1332:         strings loaded from the specified property file.</td>
 1333:       </tr>
 1334:       <tr>
 1335:         <td>LogComment</td>
 1336:         <td>Adds a comment line to the install log.</td>
 1337:       </tr>
 1338:       <tr>
 1339:         <td>Patch</td>
 1340:         <td>Applies a set of differences between two versions.</td>
 1341:       </tr>
 1342:       <tr>
 1343:         <td>PerformInstall</td>
 1344:         <td>Finalizes the installation of software.</td>
 1345:       </tr>
 1346:       <tr>
 1347:         <td>RegisterChrome</td>
 1348:         <td>Registers chrome with the chrome registry.</td>
 1349:       </tr>
 1350:       <tr>
 1351:         <td>ResetError</td>
 1352:         <td>Resets a saved error code to zero.</td>
 1353:       </tr>
 1354:       <tr>
 1355:         <td>setPackageFolder</td>
 1356:         <td>Sets the default package folder that is saved with the
 1357:         root node.</td>
 1358:       </tr>
 1359:     </table>
 1360:     <h4><a name="77093"></a> The InstallTrigger object</h4>
 1361:     <p>When you have very simple 
 1362:     <!--INDEX InstallTrigger object, XPInstall;XPInstall:InstallTrigger object -->
 1363:     installations-such as when you want to install a new skin-you
 1364:     may not need to use the services from the <tt>Install</tt>
 1365:     object. Besides providing the services necessary for
 1366:     "triggering" the downloading of a package from a web site, the
 1367:     <tt>InstallTrigger</tt> object offers some simple methods for
 1368:     installing when you do not need to rearrange of the disk,
 1369:     register complications, or do other install-type preparation
 1370:     (see <a href="#77018">Table 6-2</a>).</p>
 1371:     <p><i>Table 6-2: <a name="77018"></a></i> <i>InstallTrigger
 1372:     interface showing the role of the InstallTrigger object in the
 1373:     overall installation process</i></p>
 1374:     <tt>InstallVersion</tt>object representing the version number
 1375:     from the Client Version Registry for the specified software or
 1376:     component.
 1377:     <table width="100%" border="1">
 1378:       <tr>
 1379:         <td><b>Method</b></td>
 1380:         <td><b>Description</b></td>
 1381:       </tr>
 1382:       <tr>
 1383:         <td>compareVersion</td>
 1384:         <td>Compares the version of a file or package with the
 1385:         version of an existing file or package.</td>
 1386:       </tr>
 1387:       <tr>
 1388:         <td>Enabled</td>
 1389:         <td>Indicates whether the Software Installation is enabled
 1390:         for this client machine.</td>
 1391:       </tr>
 1392:       <tr>
 1393:         <td>getVersionInfo</td>
 1394:         <td>Returns an</td>
 1395:       </tr>
 1396:       <tr>
 1397:         <td>Install</td>
 1398:         <td>Installs one or more XPI files on the local
 1399:         machine.</td>
 1400:       </tr>
 1401:       <tr>
 1402:         <td>installChrome</td>
 1403:         <td>Installs new skin or locale packages in Netscape 6 and
 1404:         Mozilla.</td>
 1405:       </tr>
 1406:       <tr>
 1407:         <td>startSoftwareUpdate</td>
 1408:         <td>Initiates the download and installation of specified
 1409:         software. Note: deprecated in favor of install.</td>
 1410:       </tr>
 1411:     </table>
 1412:     <p>This web page installation script defines its own
 1413:     <tt>install</tt> method in which a callback parameter on the
 1414:     <tt>InstallTrigger</tt>'s own <tt>install( )</tt> method checks
 1415:     the success of the installation and displays a relevant alert
 1416:     for the user (as shown in <a href="#77052">Example 6-17</a>).
 1417:     Example 6-17<a name="77052"></a> <i>Install script
 1418:     callback</i></p>
 1419: <pre>
 1420:  function doneFn (name, result)
 1421:  {
 1422:     if (result != 0 &amp;&amp; result != 999)
 1423:       alert("The install didn't seem to work, you could maybe try " +
 1424:             "a manual install instead.\nFailure code was " + result + ".");
 1425:     else
 1426:       alert("Installation complete, please restart your browser.");
 1427:  }
 1428:  function install(packageName, fileName)
 1429:  {
 1430:     var xpi = new Object( );
 1431:     xpi&lt;/td&gt;[packageName] = fileName;
 1432:     InstallTrigger.install(xpi, doneFn);
 1433:  }
 1434:  &lt;a href="javascript:install('xFly','xfly.xpi');"&gt;install&lt;/a&gt;
 1435: </pre>
 1436:     <h4><a name="77094"></a> Installing non-Mozilla software</h4>
 1437:     <p>The XPInstall technology downloads 
 1438:     <!--INDEX installation:non-Mozilla software;software installation, non-Mozilla software -->
 1439:     and installs any software on any machine using Mozilla or
 1440:     Netscape 6/7. The same <tt>Install</tt> object methods that
 1441:     download, register, and install new Mozilla packages (e.g., new
 1442:     themes or new Mozilla applications like xFly) can be used to
 1443:     download other executables and software into any location on
 1444:     the local machine.</p>
 1445:     <p>As with Mozilla application installs, you use an
 1446:     installation script within a XPI to initialize the
 1447:     installation, add the files you want to the installation, and
 1448:     then perform the install and put the software in the designated
 1449:     locations. Note that non-Mozilla software installations do not
 1450:     include a registration step, since the chrome registry does not
 1451:     track non-Mozilla software or any more general additions to the
 1452:     operating system. <a href="#77054">Example 6-18</a> shows a
 1453:     simple and typical non-Mozilla installation. Example 6-18<a
 1454:     name="77054"></a> <i>Non-Mozilla software installation
 1455:     script</i></p>
 1456: <pre>
 1457:  var xpiSrc = "file.txt";
 1458:  initInstall(
 1459:    "Adding A File",
 1460:    "testFile",
 1461:    "1.0.1.7",
 1462:    1);
 1463:  f = getFolder("Program"); // keyword for the main program
 1464:                            // directory on the target platform
 1465:                            // (e.g., the "Program Files" dir on win32)
 1466:  setPackageFolder(f);
 1467:  addFile(xpiSrc);
 1468:  if (0 == getLastError( ))
 1469:      performInstall( );
 1470:  else
 1471:      cancelInstall( );
 1472: </pre>
 1473:     <p>Refer to the "XPInstall API Reference" on <i><a href=
 1474:     "http://developer.netscape.com">http://developer.netscape.com</a></i>
 1475:     for more detailed information about the XPInstall API and how
 1476:     it can be used in more complex installations.</p>
 1477:     <h3><a name="77095"></a> Uninstalling Applications</h3>
 1478:     <p>You may have noticed an <tt>uninstall( )</tt> 
 1479:     <!--INDEX applications:installation:uninstalling;installation:applications:unstalling;unstalling applications -->
 1480:     <!--INDEX uninstall( ) method, XPInstall;XPInstall:uninstall( ) methods;methods:XPInstall:uninstall( ) -->
 1481:     method on the <tt>Install</tt> object in the XPInstall API.
 1482:     This method does some of the work you need to do to uninstall
 1483:     packages from Mozilla, but it's a buggy process and doesn't
 1484:     finish the job.<a name="b279"></a><a href="#279">[*]</a> Beyond
 1485:     the physical removal of the package resources during the
 1486:     uninstall, several RDF files in the chrome registry need to be
 1487:     updated, and the XPInstall <tt>uninstall( )</tt> does not get
 1488:     to some of these files.</p>
 1489:     <p>Fortunately, the JSLib JavaScript developer's library has a
 1490:     well-implemented uninstall function, which you can use by
 1491:     importing the <i>uninstall.js</i> file and calling uninstall on
 1492:     the package you want uninstalled. <i>uninstall.js</i> is one of
 1493:     the JS file collections that comprise the JSLib.</p>
 1494:     <p>Once you install JSLib, using the uninstall method is
 1495:     simple:</p>
 1496: <pre>
 1497: include("chrome://jslib/install/uninstall.js");
 1498: var p = new Uninstall('myPackageName');
 1499: p.removePkg( );
 1500: </pre>
 1501:     <p>You might want to put this uninstall routine in a function
 1502:     so you can reuse it.</p>
 1503: <pre>
 1504: function unInstall(pkg) {
 1505: var p = new Uninstall(pkg);
 1506: p.removePkg( );
 1507: }
 1508: </pre>
 1509:     <p>This method removes the resources themselves and deletes all
 1510:     references to the package in the chrome registry. The
 1511:     <tt>pkg</tt> parameter is the name of the package as defined in
 1512:     the manifest for that package. The xFly package manifest, for
 1513:     example, defines "xfly" as the name of the package, as shown in
 1514:     <a href="#77056">Example 6-19</a>. Example 6-19<a name=
 1515:     "77056"></a> <i>Package metadata in the xFly manifest</i></p>
 1516: <pre>
 1517:  &lt;!-- xFly package information --&gt;
 1518:    &lt;RDF:Description about="urn:mozilla:package:xfly"
 1519:          chrome:displayName="xFly"
 1520:          chrome:author="frillies"
 1521:          chrome:name="xfly"&gt;
 1522:    &lt;/RDF:Description&gt;
 1523: </pre>
 1524:     <p><a href="#77036">Example 6-9</a> comes from the content
 1525:     package manifest for xFly, which is similar to the full content
 1526:     manifest for the XMLTerm application you saw in <a href=
 1527:     "#77026">Example 6-4</a>.</p>
 1528:     <p>To uninstall the xFly package, 
 1529:     <!--INDEX xFly package:uninstalling;packages:xFly:uninstalling -->
 1530:     then-as you should do to the working version you have as you
 1531:     develop before installing the final version-hook up a menuitem
 1532:     to call the uninstall routine:</p>
 1533: <pre>
 1534: &lt;menuitem id="uninstall-item" label="Uninstall xFly" oncommand="unInstall("xfly")" /&gt;
 1535: </pre>
 1536:     <p>This menuitem should have access to a JavaScript file and
 1537:     contains the following code:</p>
 1538: <pre>
 1539: include("chrome://jslib/install/uninstall.js");
 1540: function unInstall(pkg) {
 1541: var p = new Uninstall(pkg);
 1542: p.removePkg( );
 1543: }
 1544: </pre>
 1545:     <h2><a name="77096"></a> Finishing Things Up</h2>
 1546:     <p>We dealt with the xFly example earlier in this chapter and
 1547:     then discussed general information about file formats,
 1548:     installation scripts, and xpinstall. You now have everything
 1549:     you need to make the xFly package an installable application.
 1550:     Borrowing liberally from the examples in the earlier sections
 1551:     <a href="#77082">"The XPI File Format</a>" and <a href=
 1552:     "#77085">"Installation Scripts</a>," you can bundle a JAR file
 1553:     or the entire subdirectory structure you already created for
 1554:     xFly in the <i>chrome</i> directory:</p>
 1555: <pre>
 1556: chrome
 1557: xfly      content
 1558: skin
 1559: locale
 1560: </pre>
 1561:     <p>Bundle the JAR file into a ZIP file, add an installation
 1562:     script to that ZIP file (and a web trigger script to the
 1563:     application's web page), and make your application available to
 1564:     Mozilla users everywhere.</p>
 1565:     <h3><a name="77097"></a> Creating the xFly XPI</h3>
 1566:     <p>An XPI file is nothing more <!--INDEX xFly API:creating -->
 1567:     than a ZIP file with its own installation script. Using a ZIP
 1568:     utility, you can archive the <i>xfly</i> directory and preserve
 1569:     the subdirectory structure so it's installed in the user's
 1570:     <i>chrome</i> directory as it is in your own. Make sure that
 1571:     the ZIP file, whatever it's called, contains the top-level
 1572:     <i>xfly</i> subdirectory as part of this structure. If it is a
 1573:     JAR file you are distributing for your package, make the JAR
 1574:     file (<i>xfly.jar</i>) the top level, with the <i>content</i>,
 1575:     <i>skin</i>, and <i>locale</i> directories contained
 1576:     within:</p>
 1577: <pre>
 1578: xfly.jar
 1579: content
 1580: skin
 1581: locale
 1582: </pre>
 1583:     <p>The URLs you used to refer to various parts of your xFly
 1584:     application (e.g., <i>chrome://xfly/content/xfly.js</i> as part
 1585:     of the command that imports the external script file into the
 1586:     main XUL file) will be registered during the installation
 1587:     process with that <i>xfly</i> directory or JAR file directly
 1588:     underneath the Mozilla <i>chrome</i> directory.</p>
 1589:     <h3><a name="77098"></a> Adding the Installation Script</h3>
 1590:     <p>Once you understand the <a href="#77085">"Installation
 1591:     Scripts</a>" section (earlier in this chapter), creating an
 1592:     installation script for 
 1593:     <!--INDEX installation scripts:xFly API;xFly API:installation scripts;scripts:installation scripts:xFly API -->
 1594:     the xFly application is straightforward, as <a href=
 1595:     "#77058">Example 6-20</a> shows. In this case, we bundled all
 1596:     the xFly subdirectories in a single JAR file, <i>xfly.jar</i>.
 1597:     Example 6-20<a name="77058"></a> <i>xFly installation
 1598:     script</i></p>
 1599: <pre>
 1600:  const X_MSG             = "Install xFly";
 1601:  const X_NAME            = "xFly";
 1602:  const X_VER             = "0.0.1";
 1603:  const X_JAR_FILE        = "xfly.jar";
 1604:  const X_CONTENT         = "content/";
 1605:  const X_SKIN            = "skin/";
 1606:  const X_LOCALE          = "locale/en-US/";
 1607:  const X_CHROME          = "chrome";
 1608:  var err = initInstall(X_MSG, X_NAME, X_VER);
 1609:  logComment("initInstall: " + err);
 1610:  logComment( "Installation started ..." );
 1611:  addFile("We're on our way ...", X_JAR_FILE, getFolder(X_CHROME), "");
 1612:  registerChrome(CONTENT|DELAYED_CHROME, getFolder(X_CHROME, X_JAR_FILE), X_CONTENT);
 1613:  registerChrome(SKIN|DELAYED_CHROME, getFolder(X_CHROME, X_JAR_FILE), X_SKIN);
 1614:  registerChrome(LOCALE|DELAYED_CHROME, getFolder(X_CHROME, X_JAR_FILE), X_LOCALE);
 1615:  err = getLastError( );
 1616:  if ( err == SUCCESS )  {      // if there have been no errors:
 1617:    performInstall( );           // install "xfly.jar"
 1618:    alert("Please restart Mozilla");
 1619:  }
 1620:  else  {                       // otherwise
 1621:    cancelInstall( );            // cancel the installation.
 1622:  }
 1623: </pre>
 1624:     <p>Save the installation code in <a href="#77058">Example
 1625:     6-20</a> as <i>install.js</i> and add it to the ZIP file you
 1626:     created out of the <i>xfly</i> subdirectory. Name this zip file
 1627:     <i>xfly.xpi</i>. The installation script should be archived at
 1628:     the top level of the XPI file and appear next to the
 1629:     <i>xfly</i> subdirectory or JAR file. Another feature of this
 1630:     script is the declaration of constant variables at the top, for
 1631:     various values used in the script. This feature is good for
 1632:     re-use and organizing your script.</p>
 1633:     <h3><a name="77099"></a> Web Page Installer</h3>
 1634:     <p>The XPI file you created 
 1635:     <!--INDEX installation:web page installer;web page installer;XPInstall:web page installer -->
 1636:     in the last two sections, with its internal <i>install.js</i>
 1637:     file, is all you need to make your Mozilla application portable
 1638:     and installable. The final step creates a link on a regular web
 1639:     page that tells Mozilla where this file is, as shown in <a
 1640:     href="#77060">Example 6-21</a>. Example 6-21<a name=
 1641:     "77060"></a> <i>Web page trigger</i></p>
 1642: <pre>
 1643:  &lt;a href="#"
 1644:     onclick="InstallTrigger.install(
 1645:     {`xfly' :
 1646:     'xfly.xpi'});"&gt;
 1647:     Install my cool xFly Application&lt;/a&gt;
 1648: </pre>
 1649:     <p>When the user browses the application web page and clicks
 1650:     the "Install my cool xFly Application" link shown above,
 1651:     Mozilla finds and downloads <i>xfly.xpi</i> in the same
 1652:     directory. It then opens the archive, reads the install script,
 1653:     creates the <i>xfly</i> subdirectory on the local machine or
 1654:     moves the JAR file onto the local machine, and registers it
 1655:     with the chrome registry. When the user restarts the browser,
 1656:     the xFly application is integrated into Mozilla and ready for
 1657:     use. The user can access it with any overlays that put it into
 1658:     the browser's interface (e.g., as an item in the Tools menu) or
 1659:     invoke it directly by using the special chrome option for
 1660:     pointing to a registered chrome:</p>
 1661: <pre>
 1662: mozilla -chrome chrome://xfly/content
 1663: </pre>
 1664:     <blockquote>
 1665:       <div class="c17">
 1666:         NOTE
 1667:       </div>
 1668:       <p>You don't need to have an install page to install a XPI in
 1669:       Mozilla. If, instead of a web page, you provide a URL that
 1670:       points directly to a XPI, Mozilla displays a dialog that asks
 1671:       the user whether they want to initiate the installation of
 1672:       that XPI. As with any new software installation, however, a
 1673:       page that describes the package and what it does can help
 1674:       allay fears and promote use.</p>
 1675:     </blockquote>
 1676:     <h2><a name="77100"></a> Extra Tricks for Customizing an
 1677:     Application</h2>
 1678:     <p>If the Mozilla application 
 1679:     <!--INDEX applications:customizing;customizing applications -->
 1680:     you are working on is more autonomous than a package that sits
 1681:     up on a Mozilla installation, you may want to add extra
 1682:     customization. Here are two common features: the program icon
 1683:     and the splash screen. Some features require that you build the
 1684:     source code yourself, even just a particular module instead of
 1685:     the whole tree. Refer to <a href="appa.html#90096">Appendix
 1686:     A</a> for more details on obtaining and building the source
 1687:     code.</p>
 1688:     <h3><a name="77101"></a> Icons</h3>
 1689:     <p>Program icons are important 
 1690:     <!--INDEX icons, application customization;applications:customizing:icons -->
 1691:     for several reasons. Primarily, however, they are a visual
 1692:     representation of your application on the system that it runs
 1693:     on, whether it runs in a file explorer, a taskbar, or an
 1694:     application selector. This section tells you where to locate
 1695:     the current icons in the Mozilla application and what files or
 1696:     resources need to be changed to make your icon the default for
 1697:     Mozilla.</p>
 1698:     <h4><a name="77102"></a> Windows</h4>
 1699:     <p>In Windows, create your own icon 
 1700:     <!--INDEX icons, application customization:Windows;applications:customizing:icons;Windows:icons -->
 1701:     and then follow these steps:</p>
 1702:     <ol>
 1703:       <li>Go to the <i>mozilla/xpfe/bootstrap</i> folder in the
 1704:       source tree.</li>
 1705:       <li>Open the <i>splash.rc</i> resource file. This can be done
 1706:       in the text editor of your choice or in any program with
 1707:       special handling for Windows resource files.</li>
 1708:       <li>Change the icon resource to the file of your choice.</li>
 1709:     </ol>
 1710:     // Program icon. IDI_APPLICATION ICON "mozdev.ico" 
 1711:     <ol>
 1712:       <li>Recompile the bootstrap module. This recompilation
 1713:       regenerates the <i>mozilla.exe</i> executable file.</li>
 1714:     </ol>
 1715:     C:\mozilla\src&gt;cd mozilla\xpfe\bootstrap
 1716:     C:\mozilla\src\mozilla\xpfe\bootstrap&gt;nmake -f makefile.win 
 1717:     <p>An alternative to Steps 2 and 3 is to give your icon the
 1718:     same name as the Mozilla icon (<i>mozilla.ico</i>) and just
 1719:     drop it into the tree, replacing the existing one shown in <a
 1720:     href="#77012">Figure 6-6</a>.</p>
 1721:     <div class="c16">
 1722:       <img src="foo.gif">
 1723:     </div>
 1724:     <p><i>Figure 6-6: <a name="77012"></a></i> <i>Windows taskbar
 1725:     with Mozilla icon</i></p>
 1726:     <h4><a name="77103"></a> Unix</h4>
 1727:     <p>X Windows uses the 
 1728:     <!--INDEX icons, application customization:Unix;applications:customizing:icons;Unix:icons -->
 1729:     common X Pixmap (XPM) format for icons. XPM files are C source
 1730:     code files, with each pixmap defined as a static character
 1731:     array. The window manager expects to find two XPM files for
 1732:     each icon specified in the configuration files as <i>ICON</i>.
 1733:     Mozilla has two files for icons located in
 1734:     <i>mozilla/src/gtk</i>: <i>mozicon16.xpm</i> and
 1735:     <i>mozicon50.xpm</i>. Many utilities, such as the GIMP,
 1736:     PaintShopPro, and Xview, can transform images from other common
 1737:     formats.</p>
 1738:     <h4><a name="77104"></a> Macintosh</h4>
 1739:     <p>The Macintosh BNDL 
 1740:     <!--INDEX icons, application customization:Macintosh;applications:customizing:icons;Macintosh:icons -->
 1741:     resource (OS icons for files and applications) and related
 1742:     resource types (4bit, 8bit, large, small icons, masks, and
 1743:     FREF) are contained in <i>nsMacBundle.rsrc,</i> located at
 1744:     <i>mozilla/xpfe/bootstrap</i>. It also contains a <tt>MOZZ</tt>
 1745:     resource that references the Mozilla software license. All
 1746:     Macintosh software have this set of resources.</p>
 1747:     <blockquote>
 1748:       <div class="c17">
 1749:         NOTE
 1750:       </div>
 1751:       <p>If you want to change icons on a window-by-window basis,
 1752:       do it only in Mozilla on the Windows platform. In the chrome
 1753:       root, there exists a directory <i>\icons\default\</i>. Within
 1754:       this directory, you can place any number of icons for windows
 1755:       in your application. The filename has to be the same as the
 1756:       XUL window ID: <tt>&lt;window_id&gt;.ico</tt>. One example of
 1757:       an icon being used in this way is the DOM Inspector window in
 1758:       Mozilla. In the <i>\icons\default\</i> directory you will
 1759:       find the file <i>winInspectorMain.ico</i> on Windows. This
 1760:       option is good for package authors who add windows to the
 1761:       Mozilla application and do not want to hijack this resource
 1762:       completely. Icons can be installed as part of an XPI.</p>
 1763:     </blockquote>
 1764:     <h3><a name="77105"></a> Splash Screen</h3>
 1765:     <p>Are splash screens a 
 1766:     <!--INDEX splash screen, application customization;applications:customizing:splash screen -->
 1767:     necessary startup feature for a program or a shameless plug?
 1768:     The answer is probably somewhere in between, leaning toward the
 1769:     necessary in the case of Mozilla (<a href="#77014">Figure
 1770:     6-7</a> shows Mozilla's splash screen).</p>
 1771:     <div class="c16">
 1772:       <img src="foo.gif">
 1773:     </div>
 1774:     <p><i>Figure 6-7: <a name="77014"></a></i> <i>Mozilla's splash
 1775:     screen</i></p>
 1776:     <p>Because Mozilla is a large application and needs to process
 1777:     so much (including profiles, initialization code, and
 1778:     theme/locale selection from the chrome registry) before you
 1779:     actually see the first window appear, users need a visual clue
 1780:     that something is happening when Mozilla starts up.</p>
 1781:     <p>If your application also requires a lot of processing at
 1782:     startup or if you would like to customize your application,
 1783:     then creating and using your own unique splash screen is
 1784:     essential.</p>
 1785:     <h4><a name="77106"></a> Windows</h4>
 1786:     <p>The splash screen file 
 1787:     <!--INDEX splash screen, application customization:Windows;applications:customizing:splash screen;Windows:splash screen -->
 1788:     is a bitmap image that also lives in the same <i>splash.rc</i>
 1789:     file that houses the icon file, perhaps more appropriately
 1790:     named in this case.</p>
 1791: <pre>
 1792: // Splash screen bitmap.
 1793: IDB_SPLASH BITMAP
 1794: "splash.bmp"
 1795: </pre>
 1796:     <p>Again, you have the option of changing the resource file or
 1797:     calling the image file the same name as the Mozilla splash
 1798:     (<i>splash.bmp</i>) and dropping it into the tree. Both of
 1799:     options require recompilation of the bootstrap module.</p>
 1800:     <h4><a name="77107"></a> Unix</h4>
 1801:     <p>The splash screen uses 
 1802:     <!--INDEX splash screen, application customization:Unix;applications:customizing:splash screen;Unix:splash screen -->
 1803:     the same XPM format as is used for the icons. The file is
 1804:     called <i>splash.xpm</i> and is located in
 1805:     <i>mozilla/xpfe/bootstrap</i>. Note that the splash display is
 1806:     turned off by default on this platform and can be displayed by
 1807:     using the <tt>-splash</tt> switch in a command shell.</p>
 1808: <pre>
 1809: /mozilla -splash
 1810: </pre>
 1811:     <h4><a name="77108"></a> Macintosh</h4>
 1812:     <p>The file <i>Splash.rsrc</i> (located 
 1813:     <!--INDEX splash screen, application customization:Macintosh;applications:customizing:splash screen;Macintosh:splash screen -->
 1814:     in the source tree at <i>mozilla/xpfe/bootstrap</i>) contains
 1815:     Macintosh resources to display the splash screen (native DLOG,
 1816:     DITL, PICT) during startup while the shared libraries are
 1817:     loaded and before the profile manager is shown.</p>
 1818:     <hr>
 1819:     <hr>
 1820:     <a name="279"></a><a href="#b279">[Back]</a> <a name=
 1821:     "77062"></a> Currently, some open bugs in Bugzilla are tracking
 1822:     the progress of this method and its improvement. 
 1823:     <hr>
 1824:     <br>
 1825:     <br>
 1826:     File a <a href=
 1827:     "http://mozdev.org/bugs/enter_bug.cgi?product=books">Bug</a>
 1828:     for chapter 6. 
 1829:     <?php $hide_text_control=1; $post_to_list=NO; $author='reviewers@mozdev.org'; // require(NOTES); ?>

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>