Home > Writing Themes > Writing Themes Part Two: Theme Packaging and Installation

Writing Themes Part Two: Theme Packaging and Installation

This page discusses theme packaging and installation, providing both an introduction and details.

Overview of Theme Packaging and Installation

Theme packaging and installation is the part of making a theme that begins with a finished theme sitting on your hard drive in the form of several hundred individual files and directories, and takes you to the point where your theme is installed and running in Firefox.

Packaging itself is fairly simple -- use your zip program to pack all the individual files into a single .zip file having a .jar extension -- as is installation, which can be as simple as dragging and dropping the jar file onto the Firefox Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0) window. The only complexity is in making sure that the correct files are in the correct locations in a specific directory structure within the jar file, and in supplying the files that Firefox reads to know how to install the theme. These files are install.rdf, contents.rdf, and chrome.manifest.

Here is the short and simple checklist to use in packaging and installing your theme. Each topic is discussed in more detail in the sections that follow.

  1. Make sure that your theme is arranged within the proper directory structure.
  2. Make sure that your theme contains all mandatory files.
  3. Complete any editing of the theme itself, such as changing icons or CSS rules.
  4. Provide an install.rdf in the top directory of your theme.
  5. Provide a contents.rdf in the top directory of your theme.
  6. Use a zip program to zip up your theme into a .zip file having the extension .jar.
  7. Drag and drop the jar file onto the open Firefox Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0) window.
You might also want to look at this tutorial walk through the process of creating, editing, and installing a very simple theme.

There is a second method of packaging a theme that uses a file called chrome.manifest instead of contents.rdf. The checklist for packaging a theme with chrome.manifest is somewhat different from the list just given, and the directory structure of the resulting jar file is different as well. This second method has its pluses and minuses; you can read about packaging with chrome.manifest in detail here.

How to Install a Theme

It's easy to install a theme, assuming that it was correctly built and packaged as a jar file. There are three ways:

  1. by clicking on a specially programmed hyperlink on a web page (such as the "Install Now" link on this page) if you're using Firefox
  2. by dragging and dropping from a web page's link to a theme's jar file onto the open Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0)
  3. by dragging and dropping a theme's jar file onto the open Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0)

A Sample Script to Zip Up Your Theme

I use two zip programs as part of theme development: ALZip, which is good both for opening and creating jar files, and 7Zip, which is good at creating jar files under control of a script. I like using a script because it saves typing and prevents errors.

Here's the batch file that contains the script which takes my unpacked theme from its location on the hard drive and packages it as a jar file, ready for installation as a theme. In this particular script, it actually creates two jar files, one with a version number as part of the name -- I change the _NNN to something like _0.7.7 by renaming the jar by hand, after the script completes -- and one without. The one without is posted on my web site -- I leave off the version number because I don't want to have to update all my links to it each time I release a new version -- and the one with a version number is saved for future reference, along with all the jar files from previous releases of the theme.

001:   d:  
002:   cd d:\MCD\dvl\moztheme\NASA_Normal\unpacked  
003:   d:\app\7-Zip\7z a -tzip -mx0 ..\packed\NASA_Normal.jar @..\scripts\7ZipBackupFileList.txt  
004:   copy ..\packed\NASA_Normal.jar ..\packed\NASA_Normal_NNN.jar /Y  

The script refers to the file 7ZipBackupFileList.txt, which contains the list of files and directories to include in the jar. Here's a listing of 7ZipBackupFileList.txt.

001:   install.rdf  
002:   contents.rdf  
003:   icon.png  
004:   preview.png  
005:   browser  
006:   communicator  
007:   global  
008:   help  
009:   local_install  
010:   mozapps  
011:   xpi_skins  

You can find 7-Zip here, and ALZip here.

install.rdf and contents.rdf

Two of the important files in an add-on theme are install.rdf and contents.rdf. Together, these two files tell Firefox how to install and use your theme. These two files are not found in the default theme (no need to install a theme that comes preinstalled); they are only used in add-on themes. These two files are located in the root directory of jar files for themes, and must be present for the theme to be installable with Firefox.

install.rdf is the file that identifies your theme to the Firefox Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0). This is the file that Firefox reads when you install the theme to gather information identifying the name of the theme, the version number, the author of the theme, and where to automatically check for theme updates. Additionally, it identifies which software the theme works with, whether that be Firefox, Thunderbird, Seamonkey, or other compatible applications. You can read more about install.rdf below.

contents.rdf is the file that tells Firefox how to locate needed items within the theme's jar file. As implied by the name, it serves as a table of contents, telling Firefox how to map from chrome URLs to locations within the jar. install.rdf and contents.rdf are linked by the use of a single internal name for the theme which occurs in both install.rdf and contents.rdf. You can read more about contents.rdf below.

Beginning with Firefox 1.5, the use of contents.rdf is deprecated in favor of using a chrome.manifest instead. It will still work to use contents.rdf, and you'll need to use contents.rdf for your theme to work with versions of Firefox older than 1.5, but one can assume that at some point contents.rdf will no longer be supported by newer versions of Firefox.

install.rdf in Detail

install.rdf is the file that identifies your theme to the Firefox Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0). This is the file that Firefox reads when you install the theme to gather information identifying the name of the theme, the version number, the author, and the location to check for theme updates. Additionally, install.rdf identifies which software the theme works with, whether that be Firefox, Thunderbird, Seamonkey, or other compatible applications.

Let's take a look at a typical install.rdf. In this listing, the highlighted areas show values that are supplied by the theme developer; the rest of the file can be copied and reused verbatim.

001:   <?xml version="1.0"?> 
002:    
003:   <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
004:        xmlns:em="http://www.mozilla.org/2004/em-rdf#"> 
005:    
006:     <Description about="urn:mozilla:install-manifest"> 
007:       <em:id>{13f5f0c0-2ad4-11db-a98b-0800200c9a66}</em:id> 
008:       <em:version>0.1</em:version> 
009:       
010:       <!-- Target Applications this theme can install into, 
011:            with minimum and maximum supported versions. --> 
012:             
013:       <!-- Firefox --> 
014:       <em:targetApplication> 
015:         <Description> 
016:           <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> 
017:           <em:minVersion>1.5</em:minVersion> 
018:           <em:maxVersion>3.0a1</em:maxVersion> 
019:         </Description> 
020:       </em:targetApplication> 
021:        
022:       <!-- Front End MetaData --> 
023:       <em:name>Test Theme</em:name> 
024:       <em:description>A simple test theme to demonstrate theme packaging and installation</em:description> 
025:       <em:creator>A very special person</em:creator> 
026:       <em:contributor>Contributors listed here.</em:contributor> 
027:       <em:homepageURL>http://www.yourhomepage.com</em:homepageURL> 
028:    
029:       <!-- Front End Integration Hooks (used by Theme Manager)--> 
030:       <em:internalName>Test_Theme</em:internalName> 
031:    
032:     </Description>      
033:    
034:   </RDF>  
035:    

Comments about this listing:

  • Line 1 says "This file is in XML format, and should be read according to the rules of XML version 1.0". This is how every install.rdf must begin.
  • Lines 3 and 4 say "This is an element of type RDF." This is standard code that theme developers can copy verbatim when creating a new install.rdf.
  • Lines 4 also defines a new namespace called "em", which is defined by the document located at "http://www.mozilla.org/2004/em-rdf". The "em" in this case refers to "extensions manager", the internal part of Firefox that handles eveything related to theme and extension installation. You don't need to know about namespaces as a theme developer, but if you want to know more you can read about namespaces here.
  • Line 6 creates an RDF element of type "description". This element contains everything from line 6 to the closing </Description> tag on line 32. This element exists because Firefox is written to expect it as part of the standard install.rdf.
  • Line 7 defines the GUID of your theme. GUID stands for "Globally Unique Identifier." This is a unique identifier, unlike any other in the world, specific to your theme. The GUID shown here is an example only; as a theme developer, you'll need to get your own, and in fact you'll need to get one for each theme (and each extension, were you to go that route) that you create. You can read more about GUIDs here.
  • Line 8 defines the version number of your theme. Version numbers are completely up to the theme developer.
  • Lines 13 through 20 define which programs and versions of programs your theme will work with. When Firefox installs a theme, it reads this part of install.rdf to decide whether the theme is compatible or not. In this particular example, these lines say that this theme will work with Firefox versions 1.5 through 3.0a1, and with no other programs or versions.
  • Line 16 defines the GUID of the program that your theme works with. It's important to note that the GUID shown on line 16 is the GUID of Firefox, and not the GUID of your theme. This install.rdf contains two GUIDs: one for your theme and one for each application supported by your theme, which in this case is only Firefox. If your theme worked with a program other than Firefox then you would use the appropriate GUID of the supported application as shown in this list. We'll come back to support for multiple applications in a moment.
  • Also note that Firefox is written so that only certain version numbers are allowed here. You can read more about version numbering here and here.
  • Line 23 lists the name of the theme. This is the "external name", displayed to end users in the Themes Manager/Add-ons Manager list of installed themes, and does not have to match up with any names used anywhere else.
  • Line 24 provides some descriptive text for the theme. This text is displayed to end users in the Themes Manager/Add-ons Manager list of installed themes. Again, this is arbitrary text, completely up to the theme developer.
  • Line 25: defines the name of the person, team, or organization responsible for this theme.
  • Line 26: lists any contributors to this theme that the theme developer wishes to credit.
  • Line 27: defines a web page to which Firefox end users are directed if they click "Visit Home Page" after right-clicking on the theme in the Themes Manager. This link is also displayed in the "About Theme" dialog box.
  • Line 30: defines an "internal name" for this theme. Unlike the "external name" defined on line 23, the internal name given here is intended to match an internal name used in contents.rdf and/or a chrome.manifest file. When the same internal name is found in both places, Firefox knows that both files are talking about the same theme. The internal name should not be broken up by any space or punctuation; instead, while I haven't seen this officially documented, it should probably consist of only letters, numerals, and the underscore.

    What if you wanted your theme to work with more programs than just Firefox? For each supported program, you would add another block of code just like lines 13 through 20. For example, if a theme supported Firefox, Thunderbird, and Flock, then its install.rdf would contain three targetApplication blocks, and would look like this.

    001:   <?xml version="1.0"?> 
    002:    
    003:   <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    004:        xmlns:em="http://www.mozilla.org/2004/em-rdf#"> 
    005:    
    006:     <Description about="urn:mozilla:install-manifest"> 
    007:       <em:id>{13f5f0c0-2ad4-11db-a98b-0800200c9a66}</em:id> 
    008:       <em:version>0.1</em:version> 
    009:       
    010:       <!-- Target Applications this theme can install into, 
    011:            with minimum and maximum supported versions. --> 
    012:             
    013:       <!-- Firefox --> 
    014:       <em:targetApplication> 
    015:         <Description> 
    016:           <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> 
    017:           <em:minVersion>1.5</em:minVersion> 
    018:           <em:maxVersion>3.0a1</em:maxVersion> 
    019:         </Description> 
    020:       </em:targetApplication> 
    021:        
    022:       <!-- Flock --> 
    023:       <em:targetApplication> 
    024:         <Description> 
    025:           <em:id>{a463f10c-3994-11da-9945-000d60ca027b}</em:id> 
    026:           <em:minVersion>0.7</em:minVersion> 
    027:           <em:maxVersion>1.0</em:maxVersion> 
    028:         </Description> 
    029:       </em:targetApplication> 
    030:        
    031:       <!-- Thunderbird --> 
    032:       <em:targetApplication> 
    033:         <Description> 
    034:           <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id> 
    035:           <em:minVersion>1.5</em:minVersion> 
    036:           <em:maxVersion>1.5.0.*</em:maxVersion> 
    037:         </Description> 
    038:       </em:targetApplication> 
    039:        
    040:       <!-- Front End MetaData --> 
    041:       <em:name>Test Theme</em:name> 
    042:       <em:description>A simple test theme to demonstrate theme packaging and installation</em:description> 
    043:       <em:creator>A very special person</em:creator> 
    044:       <em:contributor>Contributors listed here.</em:contributor> 
    045:       <em:homepageURL>http://www.yourhomepage.com</em:homepageURL> 
    046:    
    047:       <!-- Front End Integration Hooks (used by Theme Manager)--> 
    048:       <em:internalName>Test_Theme</em:internalName> 
    049:    
    050:     </Description>      
    051:    
    052:   </RDF>  
    053:    

    You can read about legal values for application IDs and version numbers on this page provided by AMO (addons.mozilla.org). (If you look at that page, you'll have to scroll down a little. There's a table of legal values.) AMO is involved because, when you submit a theme for publication through AMO, AMO software reads and checks your install.rdf to see which applications your theme works with. One of the several easy ways to get a theme submission rejected is to include illegal values for minimum and maximum version numbers. Update: 20070327 AMO has a new page listing valid version numbers.

    What is a minimally sufficient install.rdf? Which parts can you leave out, and which are absolutely required? It's safe to say that you wouldn't want to cut much from what's shown in the listing above. This MDC article documents the format of and elements in install.rdf, and states which are required and which are optional. It is assumed but not verified that the MDC article applies equally to themes and extensions.

    contents.rdf in Detail

    contents.rdf is the file that tells Firefox how to locate needed items within the theme's jar file. As implied by the name, it serves as a table of contents, telling Firefox how to map from chrome URLs to locations within the jar.

    Beginning with Firefox 1.5, the use of contents.rdf is deprecated in favor of using a chrome.manifest instead. None the less, there are good reasons for choosing to use contents.rdf, mainly for compatibility with older Firefox versions and with the Seamonkey version available as of Firefox 1.5.

    Let's take a look at a typical contents.rdf. In this listing, the highlighted areas show values that are supplied by the theme developer; the rest of the file can be copied and reused verbatim.

    001:   <?xml version="1.0"?> 
    002:    
    003:   <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    004:            xmlns:chrome="http://www.mozilla.org/rdf/chrome#"> 
    005:    
    006:     <!-- List all the skins being supplied by this theme --> 
    007:     <RDF:Seq about="urn:mozilla:skin:root"> 
    008:       <RDF:li resource="urn:mozilla:skin:Test_Theme" /> 
    009:     </RDF:Seq> 
    010:    
    011:     <!-- Test Theme Information --> 
    012:     <RDF:Description about="urn:mozilla:skin:Test_Theme
    013:           chrome:displayName="Test Theme
    014:           chrome:accessKey="N
    015:           chrome:author="A very special person
    016:           chrome:authorURL="http://www.yourhomepage.com
    017:           chrome:description="A simple test theme to demonstrate theme packaging and installation
    018:           chrome:name="Test_Theme
    019:           chrome:image="preview.png"> 
    020:       <chrome:packages> 
    021:         <RDF:Seq about="urn:mozilla:skin:Test_Theme:packages"> 
    022:           <RDF:li resource="urn:mozilla:skin:Test_Theme:browser"/> 
    023:           <RDF:li resource="urn:mozilla:skin:Test_Theme:communicator"/> 
    024:           <RDF:li resource="urn:mozilla:skin:Test_Theme:help"/> 
    025:           <RDF:li resource="urn:mozilla:skin:Test_Theme:global"/> 
    026:           <RDF:li resource="urn:mozilla:skin:Test_Theme:mozapps"/> 
    027:         </RDF:Seq> 
    028:       </chrome:packages> 
    029:     </RDF:Description> 
    030:    
    031:     <!-- Version Information.  State that we work only with major version 1 of this package. --> 
    032:     <RDF:Description about="urn:mozilla:skin:Test_Theme:browser"       chrome:skinVersion="1.5"/> 
    033:     <RDF:Description about="urn:mozilla:skin:Test_Theme:communicator"  chrome:skinVersion="1.5"/> 
    034:     <RDF:Description about="urn:mozilla:skin:Test_Theme:help"          chrome:skinVersion="1.5"/> 
    035:     <RDF:Description about="urn:mozilla:skin:Test_Theme:global"        chrome:skinVersion="1.5"/> 
    036:     <RDF:Description about="urn:mozilla:skin:Test_Theme:mozapps"       chrome:skinVersion="1.5"/> 
    037:   </RDF:RDF> 
    038:    

    Some comments about this listing:

    1. Line 1 says "This file is in XML format, and should be read according to the rules of XML version 1.0". This is how every contents.rdf must begin.
    2. Lines 3 and 4 say "This is an element of type RDF." This is standard code that theme developers can copy verbatim when creating a new contents.rdf.
    3. Lines 6, 11 and 31 are comments or remarks, intended to be read by other humans who may look at this file. They are ignored by Firefox when it reads this file.
    4. The "skinVersion" attribute shown in lines 32 through 36 seems to have no effect at all. There's some conjecture that this was used for application version compatibility checking with Firefox versions older than 1.0.
      magneto>    Hi, if my contents.rdf contains a line like this
                  <RDF:Description about="urn:mozilla:skin:Test_Theme:mozapps" chrome:skinVersion="1.5"/>
                  what is the chrome:skinVersion saying?
      Mossop>     magneto: Im not entirely sure it means anything as far as the app is concerned
      Mook>       thought it was supposed to serve as the app version, sorta
                  except that it only really worked for mozilla and stuff, while < 1 :p
      magneto>    Mossop: it doesn't seem to have any impact at all as far as i can tell
      Mossop>     Hmm. I never really got on with Contents.rdf files anyway ;)
    5. On lines 12, 18, 22 through 26, and 32 through 36, the string "Test_Theme" is the internal name for the theme, and must exactly match the internal name used in the theme's install.rdf, shown on line 30 of the install.rdf listing.
    6. Line 13 lists a displayName, but this is probably not used, since install.rdf already contains a displayName. This is likely to be a vestige left over from earlier Firefox versions. For safety's sake, just set this to the same value as used in install.rdf.
    7. Line 14 defines a value for accessKey, but it is an open question as to how this is used.
    8. Lines 15, 16 and 17 define values which can be set however the theme developer chooses. Since there are corresponding values set in install.rdf, the safest approach would be to use the same values for the same elements both here and in install.rdf.
    9. Line 19 appears to allow the developer to define a preview image separate from whatever is included in the root directory of the theme's jar file. It is an open question as to whether this works.
    10. Line 20 introduces the term "package". Packages are explained in more detail here. Each of the lines 22 through 26 defines a package. The five packages shown here are mandatory and must be defined for Firefox to work right (because part of Firefox will be looking for these packages). For now, all you need to know is that in contents.rdf, the package-defining lines 22 through 26 are mandatory, and the corresponding lines 32 through 36 are mandatory as well. For a basic theme, the only thing you should change in these lines is to replace the internal_name ("Test_Theme", in this example) with an internal_name of your own choosing. In a moment, we'll show how to add more packages.

    Overall, there is not a great deal of documentation available about the format of this file. This page at Mozilla Development Center shows a minimal contents.rdf.

    Adding Packages with contents.rdf

    This listing above shows contents.rdf for the case when your theme only includes the five standard packages (browser, global, communicator, help and mozapps). How is it handled when the theme contains additional packages, beyond the basic five? Doing so is a simple matter of adding two lines to the file for each additional package, with one line added to the upper group and one to the lower group for each additional package. The following listing shows contents.rdf modified to contain two additional packages.

    001:   <?xml version="1.0"?> 
    002:    
    003:   <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    004:            xmlns:chrome="http://www.mozilla.org/rdf/chrome#"> 
    005:    
    006:     <!-- List all the skins being supplied by this theme --> 
    007:     <RDF:Seq about="urn:mozilla:skin:root"> 
    008:       <RDF:li resource="urn:mozilla:skin:Test_Theme" /> 
    009:     </RDF:Seq> 
    010:    
    011:     <!-- Test Theme Information --> 
    012:     <RDF:Description about="urn:mozilla:skin:Test_Theme
    013:           chrome:displayName="Test Theme
    014:           chrome:accessKey="N
    015:           chrome:author="A very special person
    016:           chrome:authorURL="http://www.yourhomepage.com
    017:           chrome:description="A simple test theme to demonstrate theme packaging and installation
    018:           chrome:name="Test_Theme
    019:           chrome:image="preview.png"> 
    020:       <chrome:packages> 
    021:         <RDF:Seq about="urn:mozilla:skin:Test_Theme:packages"> 
    022:           <RDF:li resource="urn:mozilla:skin:Test_Theme:browser"/> 
    023:           <RDF:li resource="urn:mozilla:skin:Test_Theme:communicator"/> 
    024:           <RDF:li resource="urn:mozilla:skin:Test_Theme:help"/> 
    025:           <RDF:li resource="urn:mozilla:skin:Test_Theme:global"/> 
    026:           <RDF:li resource="urn:mozilla:skin:Test_Theme:mozapps"/> 
    027:           <RDF:li resource="urn:mozilla:skin:Test_Theme:xpi_skins"/> 
    028:           <RDF:li resource="urn:mozilla:skin:Test_Theme:local_install"/> 
    029:         </RDF:Seq> 
    030:       </chrome:packages> 
    031:     </RDF:Description> 
    032:    
    033:     <!-- Version Information.  State that we work only with major version 1 of this package. --> 
    034:     <RDF:Description about="urn:mozilla:skin:Test_Theme:browser"       chrome:skinVersion="1.5"/> 
    035:     <RDF:Description about="urn:mozilla:skin:Test_Theme:communicator"  chrome:skinVersion="1.5"/> 
    036:     <RDF:Description about="urn:mozilla:skin:Test_Theme:help"          chrome:skinVersion="1.5"/> 
    037:     <RDF:Description about="urn:mozilla:skin:Test_Theme:global"        chrome:skinVersion="1.5"/> 
    038:     <RDF:Description about="urn:mozilla:skin:Test_Theme:mozapps"       chrome:skinVersion="1.5"/> 
    039:     <RDF:Description about="urn:mozilla:skin:Test_Theme:xpi_skins"     chrome:skinVersion="1.5"/> 
    040:     <RDF:Description about="urn:mozilla:skin:Test_Theme:local_install" chrome:skinVersion="1.5"/> 
    041:   </RDF:RDF> 
    042:    

    The listing above shows how you would modify contents.rdf to add two packages. As for why, see this discussion of the package concept.

    GUIDs and UUIDs

    A Globally Unique Identifier, or GUID, is a number or name that is used to distinguish different software objects (like files and programs) from one another, and as a unique signifier for one object out of many objects in the same category. UUID, or Universally Unique Identifier, is another name for GUID, and they both refer to the same concept. Here's a sample GUID.

    ec8030f7-c20a-464f-9b0e-13a3a9e97384

    In the world of Firefox, and of all the Mozilla-related software, each theme should have its own GUID, and no theme should have the same GUID as any other theme. This allows Firefox to use GUIDs to uniquely identify each theme, and to distinguish each individual theme from all the other themes. As far as Firefox is concerned, if two themes have the same GUID, then they are the same theme.

    As a theme developer, you'll use the GUID in the file install.rdf to uniquely identify your theme. It is up to each theme developer to assign GUIDs to his or her themes. Once the theme developer has assigned the GUID by using it in install.rdf, that's all; there's no other place where the theme developer would use that GUID.

    Firefox uses GUIDs for both extensions and for themes. In light of this, it would be more accurate to say that no theme or extension should have the same GUID as any other theme or extension. As far as keeping track of GUIDs, Firefox treats both themes and extensions as if they were all just "add-ons", and the rule is that each add-on should have a GUID that is different from the GUIDs of all other add-ons.

    If you happen to go browsing through Firefox's extensions directory after you've installed your theme, you'll see the GUID of your theme and of any other installed extensions and themes, with the GUIDs used as subdirectory names. When Firefox installs a theme or extension, it creates a new subdirectory here, having the GUID of the theme or extension, and places related files in the subdirectory. Here's a screenshot of the extensions directory for one Firefox user.

    Figure: Contents of the extensions directory for one Firefox user

    How do theme developers get the GUID for their themes? They get them from what's called a GUID provider. A GUID provider is simply a piece of software that hands out GUIDs and promises never to hand out the same GUID twice. GUIDs and UUIDs have been around a lot longer than the commercial Internet, but these days GUID providers are available via the web, such as this one. The site displays a fresh UUID for you, and each time you refresh the web page, you'll get a new one, with the old one never, ever, seen again. UNIX users can also run programs like uuidgen, and Windows users have guidgen. You can read more about UUIDs and GUIDs in this Wikipedia article about UUIDs, especially as regards the question of whether they are truly unique.

    The system of GUIDs and GUID providers will work to keep GUIDs unique if you follow a few simple rules.

    1. Whenever you create a new theme or extension, get a new GUID.
    2. If you're modifying an existing theme or extension, then don't change its GUID.
    3. Whenever you get a new GUID, get it from a recognized GUID provider.
    There's nothing to guarantee that any GUID you may use in install.rdf is in fact unique. You can use any GUID you choose (as long as it is in the correct format), and there's nothing to stop you from picking one that's accidently the same as the GUID in another theme or even copying the GUID from another theme. Bad things would happen if you did that, so don't do it. Instead, go to a GUID provider and get a fresh GUID whenever you need a new one, such as when starting a new theme or extension.

    When does it matter what GUID a theme has? In two cases:

    1. when you install a theme, Firefox uses the GUID to decide whether that theme is already installed, in which case it's an update, or not already installed, in which case it's adding a new theme
    2. when you submit a theme to AMO (addons.mozilla.org), the AMO software checks to make sure that the theme you're submitting has a unique GUID, or, if you're submitting an update, that the updated version contains the same GUID as previous versions.
    Again, as far as Firefox and AMO are concerned, if it has the same GUID, then it's the same theme.

    This Mozilla Developer Center article provides more information and context about the use of GUIDs in install.rdf.

    Newer ID Format for Themes and Extensions

    GUIDs are used in many places in the world of software, and not just in Firefox. The example shown above is a generally-recognized format for GUIDs. Firefox supports a second, newer format of IDs for themes and extensions, specific to Firefox and Mozilla-related software, and in fact Mozilla has recommended that all themes and extensions start using this newer format if they are compatible with Firefox 1.5 or newer. For now, either format is accepted by Firefox. The newer id format is:

        extensionname@organization.tld    
    
    and here are three example IDs in the new format.
        cckwizard@extensions.mozilla.org
        firebug@software.joehewitt.com
        updatechannel@blueprintit.co.uk
    
    The new format results in unique IDs, just like the old format, but it's easier for humans to read and carries more information about the theme or extension. You can see some of this second form of ID in use in the screenshot of the extensions directory shown above.

    It's not clear how well older versions of Firefox support the "extensionname@organization.tld" form of ID.

    magneto>    hey, if i'm writing an extension and i want it to work with both Fx1.5 and Fx1.0, 
                can I use the "firebug@software.joehewitt.com" format for the extension ID in install.rdf, 
                or do I need to use the older numeric GUID format?
    Mook>       magneto: you need uuid, I think... not sure how strict the checking was though :p
    
    A little experimentation would quickly answer this question. Exercise is good for readers, and here's your chance to get a little more.

    This Mozilla Developer Center article provides more information and context about the use of GUIDs in install.rdf.

    chrome.manifest

    There is an alternative mechanism to contents.rdf. You can, instead, include in your theme a file called chrome.manifest. Like contents.rdf, chrome.manifest tells Firefox how to locate directories in your theme. Like contents.rdf, chrome.manifest resides at the top of the directory structure for your theme's jar file. Unlike contents.rdf, chrome.manifest excludes a lot of information that contents.rdf duplicates from install.rdf.

    If you use chrome.manifest instead of contents.rdf, then the jar file for the theme requires a particular directory structure, described below, which is different from the directory structure for themes using contents.rdf. Also, if you use chrome.manifest, you don't need to include a contents.rdf.

    We need to make a clear distinction between the terms "manifest file" and "chrome.manifest". Manifest files are used in general to define the default Firefox user interface, and are installed with Firefox as part of the default installation. chrome.manifest is the name of a file included in an add-on theme to tell Firefox how to load the theme. We've already discussed how the Firefox 1.5 user interface relies on seven manifest files to tell Firefox how to load the seven default jar files, but those are different from what we're talking about here. Here we're talking about a file having the exact name chrome.manifest, included in the jar file for an add-on theme, placed within the jar at the top of the jar's directory structure.

    The following listing shows a standard chrome.manifest suitable for use in the jar file for a theme. The highlighted values should be provided by the theme developer.

    001:   skin    browser         Test_Theme jar:chrome/chrome.jar!/browser/ 
    002:   skin    global          Test_Theme jar:chrome/chrome.jar!/global/ 
    003:   skin    mozapps         Test_Theme jar:chrome/chrome.jar!/mozapps/ 
    004:   skin    communicator    Test_Theme jar:chrome/chrome.jar!/communicator/ 
    005:   skin    help            Test_Theme jar:chrome/chrome.jar!/help/ 

    You can immediately see one benefit over contents.rdf: it's very very simple, with only five lines as compared to 38 lines in contents.rdf. It also eliminates the overlap between values specified in both install.rdf and contents.rdf.

    Here are the meanings of the fields in the first line.

    • The first field states the "manifest instruction type" of this line, which is "skin", meaning that this line is telling how to find part of a theme.
    • The second field, e.g. "browser", is the name of the package to which this line applies.
    • The third field, e.g. "Test_Theme", is the internal_name of the theme (or extension) which this package is part of. This internal_name must match the internal_name used in the corresponding install.rdf.
    • In the fourth field, the "jar:" says that the path to the package refers to a directory within a jar.
    • In the fourth field, the "chrome/" says that the jar is located is the chrome subdirectory of the location where the extension is installed.
    • In the fourth field, the "chrome.jar" is of course the name of the jar containing the related files.
    • In the fourth field, the /browser/ is a directory within the jar containing the files.

    The astute reader will notice the implications of the path which begins with "jar:" in the fourth field: the path is referring to a jar other than the jar containing chrome.manifest. It turns out that theme packaging and installation using chrome.manifest requires two jars, one to contain your theme overall, and a second jar embedded within the first jar, containing the actual images and CSS files of your theme. The end result for a theme packaged this way is a jar within a jar. This is discussed in more detail below.

    The chrome.manifest file for a theme is a special case of manifest files in general. In particular, the only manifest instruction types allowed in the chrome.manifest file for a theme are "skin", "comment", and "style", whereas manifest files in general support seven manifest instruction types. You can read more about manifest files in general here.

    Adding Packages with chrome.manifest

    For comparison, here's the chrome.manifest for a theme (FormalGnome) that includes some extra material in addition to handling the five required packages. This theme adds some files and directories for the package "tbx".

    001:   skin    global          FormalGnome jar:chrome/chrome.jar!/global/ 
    002:   skin    mozapps         FormalGnome jar:chrome/chrome.jar!/mozapps/ 
    003:   skin    browser         FormalGnome jar:chrome/chrome.jar!/browser/ 
    004:   skin    communicator    FormalGnome jar:chrome/chrome.jar!/communicator/ 
    005:   skin    tbx             FormalGnome jar:chrome/chrome.jar!/tbx/ 
    006:   skin    help            FormalGnome jar:chrome/chrome.jar!/help/ 
    Packages

    We've talked elsewhere about how the Firefox user interface is made up of hundreds of files -- XUL, CSS, and images, as well as other kinds -- that work together to build the part of Firefox that the end user sees. In the Firefox world, the terms "package" and "packaging" refer to the way that these files are grouped into reusable building blocks.

    The package concept is complex, and requires significant study to understand in detail. Fortunately, as a theme developer, there are only a few things that you need to understand about packages. You can read a more complete description of the package concept, but here are the basics.

    Where will you, as a theme developer, see packages used?

    • In the ten mandatory package-defining lines in contents.rdf in your theme, if you choose to use a contents.rdf
    • In the five mandatory package-defining lines in chrome.manifest in your theme, if you choose to use a chrome.manifest
    • In the chrome URLs in your theme, such as when you specify images or XBL bindings
    • In the chrome URLs used in the source code for the rest of the Firefox user interface, referring to mandatory files within your theme

    As a theme developer, what must you do to make sure your theme plays well with packages for Firefox 1.5 and Firefox 2.0?

    • If your theme uses a chrome.manifest, then your chrome.manifest must include the appropriate package-defining lines for the five default packages, as shown in lines 1 through 5 of the listing for chrome.manifest. If you follow the instructions for modifying chrome.manifest that accompany the listing, then you will have taken care of this.
    • If your theme uses a contents.rdf, then your contents.rdf must include the appropriate package-defining lines for the five default packages, as shown in lines 22 through 26 and 32 through 36 in the listing for contents.rdf. If you follow the instructions for modifying chrome.manifest that accompany the listing, then you will have taken care of this.
    • If you use any chrome URLs in your theme that reference packages other than the five default packages, then make sure you define those packages by adding a line to your theme's chrome.manifest or adding a pair of lines to your theme's contents.rdf, and point those packages to the right locations in the jar file for your theme, and make sure that the jar file for your theme contains the right directories and files at those locations. A sample contents.rdf modified in this way is shown here.
    • The chrome.manifest for a theme can only define the "skin" part of packages. For reasons of security (keeping themes safe and fun), a theme can't define either "content" or "locale" parts of packages in its chrome.manifest. Just be sure not to use any of the illegal manifest instruction types. This is not an issue if using contents.rdf, since the relevant lines are automatically translated into package "skin" definitions, and there's no way in contents.rdf to define either "content" or "locale" parts.

    For more detail about packages, see topic "The Package Concept". See also this comprehensive example showing how chrome jar files, manifest files, the chrome registry, chrome URLs, packages, and Firefox source code work together.

    Directory Structure of Jar Files for Themes Using chrome.manifest

    If you decide to use a chrome.manifest instead of a contents.rdf, then you must use a particular directory structure within the jar file for your theme which is very different from the structure you would use with contents.rdf. In particular, the five required theme directories (along with their contents and any other directories you might have in your theme) are first packaged into a jar file, which is then itself added to the jar file for the theme. The result is that you end up with a jar within a jar.

    This makes sense if you think that the point of theme installation is to end up with a chrome.manifest accompanying and outside of the jar file that it refers to, and to do it in the same way that the seven manifest files accompany but reside outside of the seven default jar files in the Firefox user interface.

    Here's the directory structure for the outer jar (the jar file containing the theme):

    /install.rdf
    /chrome.manifest
    /icon.png
    /preview.png
    /chrome/
        chrome.jar 
    and here's the directory structure of the inner jar
    /browser/
        ... files and directories
    /communicator/
        ... files and directories
    /global/
        ... files and directories
    /help/
        ... files and directories
    /mozapps/
        ... files and directories 
    You can see that the outer jar contains /chrome/chrome.jar, along with the files that Firefox needs to identify and install the theme. chrome.jar is the inner jar, and contains the five required theme directories.

    It's probably required, and certainly recommended, that you name the directory in the outer jar "chrome", and name the inner jar "chrome.jar". Official documentation on this point is nonexistent. At the very least, you would want to make sure that the path used in chrome.manifest (e.g., "jar:chrome/chrome.jar!/global/") matches the name of the inner jar file and of the directory containing it within the outer jar.

    magneto>    two ways of specifying the contents of a theme: 1) with contents.rdf 2) with chrome.manifest. 
                Does the chrome.manifest method require you to have a jar within a jar (which is all 
                I've seen so far) or can you have your directories browser/ global/ help/ communicator/ 
                and mozapps/ in the root of the outer jar, like they are when using contents.rdf?
    Mossop>     magneto: You can do whatever you like with chrome.manifest, manifests are far easier to 
                use and have more capabilities than rdf files. Though they do require Firefox/Thunderbird 1.5 or later
    magneto>    mossop: in my experiments so far when i try it without the jar within a jar the five 
                major directories don't get installed at all. is the theme installer written such that if 
                your theme has a chrome.manifest then the theme's jar also has to contain a chrome.jar? 
                or am i just doing it wrong?
    Mossop>     magneto: You changed the manifest entries to point to file: places rather than jar: yeah?
    magneto>    mossop: yes
    magneto>    mossop: e.g. skin global test_theme /global/
    Mossop>     magneto: That won't work
    Mossop>     magneto: Needs file:global/
    magneto>    ah! k thanks
    magneto>    Mossop: when a theme containing a chrome.manifest gets installed, does the chrome.manifest 
                simply get copied verbatim, or is it processed somehow?
    Mossop>     magneto: Copied verbatim. All the files in the jar are just extracted to a folder in the extensions directory
    magneto>    Mossop: k thx
    ...
    magneto>    mossop: for some reason when I install the theme, none of the subdirectories are being 
                created under the theme's installation directory. any idea what I should be looking at? 
                here's the content of the jar http://img167.imageshack.us/img167/2616/sp3220060821115107we5.jpg
    Mossop>     magneto: So in the future I highly recommend you ignore me. Looking at the source it appears 
                that while chrome.manifest will let you do that, the extension manager actually ignores 
                directories when it extracts from the theme's jar file. And I haven't got a clue why :s
    magneto>    so it sounds like jar within a jar is mandatory
    Mossop>     magneto: Unfortunately it does look that way. Thinking about it I reckon they dont let 
                you have directories because that might allow themes to have components and other 
                potentially dangerous bits of code included
    magneto>    mossop: you don't have an LXR link in front of you do you?
    Mossop>     magneto: For what?
    magneto>    mossop: for the source you were just looking at
    Mossop>     magneto: http://landfill.mozilla.org/mxr-test/seamonkey/source/toolkit/mozapps/extensions/src/nsExtensionManager.js.in#1568
    
    Manifest Instruction Types

    The first item on each line in a manifest file is the manifest instruction type. There are seven possible manifest instruction types:

    • content
    • overlay
    • locale
    • skin
    • comment
    • style
    • override

    Of the seven manifest instruction types, only three are allowed within the manifest file for a theme: skin, comment, and style. If you tried to use the others, they would be ignored, and would trigger error reports that show within the Javascript Console (Firefox 1.5) or Error Console (Firefox 2.0) window. These are the error messages you would see.

    Warning: Ignoring content registration in skin-only manifest.
    Source File: file:///E:/bonecho/profiles/bonecho/extensions/{B00df3690-c341-11da-a94d-0800200c9a66}/chrome.manifest
    Line: 8
    
    Warning: Ignoring overlay registration in skin-only manifest.
    Source File: file:///E:/bonecho/profiles/bonecho/extensions/{B00df3690-c341-11da-a94d-0800200c9a66}/chrome.manifest
    Line: 8
    
    Warning: Ignoring locale registration in skin-only manifest.
    Source File: file:///E:/bonecho/profiles/bonecho/extensions/{B00df3690-c341-11da-a94d-0800200c9a66%}/chrome.manifest
    Line: 8
    
    Warning: Ignoring override registration in skin-only manifest.
    Source File: file:///E:/bonecho/profiles/bonecho/extensions/{B00df3690-c341-11da-a94d-0800200c9a66%}/chrome.manifest
    Line: 8
    

    Here are examples of all seven manifest instruction types being used in sample lines. Note that, unlike the other manifest instruction types, comment lines begin with the symbol "#" rather than an actual word. The "#" symbol is commonly used in programming languages to mean "this line is a comment and should be ignored".

    content branding jar:browser.jar!/content/branding/ xpcnativewrappers=yes
    
    overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
    
    locale necko en-US jar:en-US.jar!/locale/en-US/necko/
    
    skin global classic/1.0 jar:classic.jar!/skin/classic/global/
    
    # this line is a comment - you can put whatever you want here
    
    style   chrome://browser/content/browser.xul    chrome://local_install/skin/local_install.css
    
    override    chrome://browser/content/searchDialog.xul chrome://tabmixplus/content/links/SearchDialog.xul
    

    Rather than duplicate documentation available elsewhere, we simply link you to official documentation about the format and function of each instruction type. One note about the official documentation: the description for manifest instruction type "skin" contains a somewhat cryptic reference to Firefox selecting "the best-fit skin", and isn't really clear what it means.

    magneto>    On this page http://developer.mozilla.org/en/docs/Chrome_Registration#Manifest_Instructions 
                it says "If more than one skin is registered for a package, the chrome registry will select
                the best-fit skin using the user's preferences." Is that really true, and if so how does 
                the crhome registry choose a best fit?
    Hannibal>   magneto: you have a theme selected
    Hannibal>   magneto: it picks that one if it can
    Hannibal>   if that theme doesn't provide that package, umm, I dunno. Undefined behaviour afaik
    magneto>    Hannibal: ok
    Hannibal>   well
    Hannibal>   it will try to find a theme that does support that package
    Hannibal>   but if there's more than one of such themes
    Hannibal>   then which it picks is undefined, afaik.
    magneto>    Hannibal: so that's basically saying, when all the installed themes register a package 
                "chrome://browser/skin", then it'll use the one from the currently selected theme?
    Hannibal>   right.
    
    So, with regard to themes at least, "selecting the best fit" would seem to mean "using the active theme".

    chrome.manifest vs. contents.rdf

    In brief: contents.rdf versus manifest file: one is old and deprecated, one is new and the way of the future. Manifest files are the new way. contents.rdf is the old way. They both do the same thing. They tell Firefox how to find files in the jar. The theme installation process causes contents.rdf to be converted into a manifest file.

    Theme developers currently have a choice in how they tell Firefox about the contents of their themes. The two methods are

    1. with a file called chrome.manifest and
    2. with a file called contents.rdf.
    For Firefox 1.5, the two methods are equivalent, and it is entirely up to the developer as to which method to use. You can see a sample of a contents.rdf here and the equivalent chrome.manifest here.

    In add-on themes, the chosen file, either contents.rdf of chrome.manifest, is placed in the root directory of the theme's jar. Neither file is included in classic.jar, the default Firefox theme, since the default Firefox installation provides a manifest as a separate file to accompany classic.jar.

    The use of contents.rdf is considered "the old way" and, while still supported, is deprecated in favor of using a chrome.manifest file. It's reasonable to assume that support for contents.rdf will end at some point in the future.

    Both contents.rdf and chrome.manifest files serve the same purpose, which is to tell Firefox how to map chrome URLs to the contents of the theme's jar. You could also say the purpose is to tell Firefox how to install the contents of the jar as packages, which amounts to the same thing.

    When Firefox installs a theme that contains a chrome.manifest, then that chrome.manifest is copied verbatim into the directory containing the installed theme. If, however, the theme contains a contents.rdf, then Firefox first creates the equivalent chrome.manifest, then writes the created chrome.manifest to the directory containing the installed theme. Either way, whether the jar for a theme includes a chrome.manifest or not, Firefox reads the resulting chrome.manifest during the Firefox start-up process to get information about how to load the theme and locate the items within the theme. You can see examples of the resulting chrome.manifest files here. Firefox really only needs to have a chrome.manifest, and only uses contents.rdf when no chrome.manifest is provided, as a convenience for theme developers who are still using the old method. If a theme developer instead chooses to provide a chrome.manifest, then contents.rdf need not be provided.

    These statements are true for extensions as well as for themes.

    At the time of this writing, Seamonkey supports only the contents.rdf method, as described in this quote from a Mozilla Development Center article:

    Before the plaintext manifests were introduced (which happened in Firefox 1.5, Toolkit 1.8), RDF manifests named "contents.rdf" were used to register chrome. This format is deprecated; however, the Mozilla Suite (SeaMonkey) does not support the plaintext manifest format yet, so contents.rdf manifests are required for extensions that wish to maintain backwards compatibility with Firefox 1.0 or the suite.

    See this complete example combining contents.rdf, manifest files, jar directories and chrome URLS.

    See also this and this Mozillazine Forum thread for more information.
    Firefox-Generated Manifest Files

    This is not something you need to know about as a theme developer. All you really need to know is that there are two methods of describing the contents of a jar (contents.rdf and/or chrome.manifest), that there are rules to follow with each method, and that your theme will be installable if you follow the rules for whichever method you choose. Still, you may be curious about what Firefox does with your theme when you install it. If so, you can read more here.

    Developing with an Unpacked Theme

    During development, you definitely don't want to have to zip up and install your theme every time you want to test a change. (You'll still need to zip up the theme to publish it to the world, but not necessarily to test your changes.) It's a lot more convenient to have your theme located at some place on your hard drive in a normal, open, unzipped directory structure so you can go in and look at and change its component files. See topic "Making Firefox Use Your Work Directory" for details.

    Theme Packaging and Installation: Conclusion

    This concludes the part of the article which focuses on theme packaging and installation. Armed with what you've learned in this section, this might be a good time to review the pitfalls of theme development discussed in topic "Hidden Traps of Theme Development", or read on for a discussion of Part Three: Theme Development.