Hack 89. Build an Installable Theme![]() ![]() Firefox windows look.This hack describes how to make, bundle, and offer a new theme for installation. Firefox's theming system is not as comprehensive as some generic GUI skin engines. For example, it can't completely reorganize the Firefox user interface as flexibly as WinAMP's themes can. Firefox themes are restricted to effects that are possible within CSS. However, those effects are expanding in number as CSS becomes more popular. 8.7.1. Getting the Content TogetherBefore building the theme's bundle, make sure you have the content ready. 8.7.1.1 Do the creative bitNo one can give you a formula for creativity, and this hack isn't going to try. Before you can assemble the theme, you have to have a creative starting point, a plan, and a design. That should lead to a set of prepared images and some color scheme information. h5Your images and colors must be tied to CSS styles before they will have any effect. That means studying the CSS selector sites (tag names, attribute names, IDs, and classes) and structures (tag hierarchies) implicit in the XUL content to which your theme will apply. That, in turn, means studying the browser package as a bare minimum. Once that's done, you build the stylesheets that tie the images and colors to the content. Those stylesheets generally match the names of the sheets used in the windows to be styled. So, if this reference appears in an XUL document, you have the opportunity of supplying a stylesheet named special/decorations.css that will affect that window: <?xml-stylesheet href="/image/library/english/10055_decorations.css"?>This one-to-one match between theme sheets and referenced sheets can be distorted by two mechanisms. One mechanism is to use the contents.rdf file [Section 8.7.2, later in this hack]. The other way is to use the @import CSS directive. For example, most theme sheets start by importing the global theme: @import url("chrome://global/skin/");You can import whatever other sheets you see fit. You can, for example, leave the stylesheet empty except for an @import statement that includes some completely foreign sheet. In general terms, though, it makes sense to follow the pattern of sheet names implied by the XUL you're seeking to theme up. 8.7.1.3 Collect together skinsThe stylesheets and images must be collected together into skins. Each theme provides one skin per supported package. A skin is just a group of files in a common directory, possibly with some subdirectories. At a minimum, you should create skins for the browser, global, and mozapps packages. In an ideal world, you would also create skins for every package ever developedpast, present, and future. Since that's not feasible, there is a fallback mechanism.Nearly all XUL windows include the special global package's skin. The global skin is important, because it is the fallback resource for all packages that you don't explicitly write skins for. All well-written XUL documents know that the global skin is the first thing they should include. It's up to the theme designer to ensure that the global skin contains enough resources to support fallback. You should put all your generic images here and refer to these images from the other, more specialized skins that you create. 8.7.2. Building the Theme JAR FileThere are three different ways to deliver a theme:As a JAR file bundled with the Firefox installer and put in the install areaAs skin content that is part of a downloadable extensionAs a complete and separate downloadable theme Each approach requires different packaging of the skin information. 8.7.2.1 Build an install-bundled themeThis approach requires that the JAR file contain the skin information in the standard, inverted hierarchy [Hack #86] : skin/theme-name/package-name/skin-fileThe JAR file must also include a contents.rdf file for each skin: skin/theme-name/package-name/contents.rdfThis contents.rdf file should match this example exactly, also covered in [Hack #86] . We've just spaced it out a little more for discussion and included is a skin overlay [Hack #87] . <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"The skin overlay is the last chunk of code. Since this is package registration, not extension registration, only attributes that describe packages are understood. Almost identical copies of this file can be drawn from most skins, with just the names changed. Since the theme is bundled with the install, the install.js script at the top of the install bundle must also be updated so that it knows to register the additional skins. 8.7.2.2 Build skins into downloadable extensionsThis case is the same as the install-bundled case, except that the skin content is combined with locale and extension content in the one JAR file, which is then made into an extension XPI file [Hack #88] .To use this approach is to make a skin masquerade as a full extension. That's entirely possible, but the price is that Firefox expects that the extension's package will have content. Even if there are no content files, the package must still be registered using: <RDF:Seq about="urn:mozilla:package:root"> h5The format of the required JAR file in this case is different than in the previous two cases. It is a simplified format, and there is no need for an XPI file at any stage. The word skin and the theme name is redundant, since the theme bundle holds exactly one theme, so paths to skin files inside the JAR need only be constructed like this: package-name/skin-fileAt the top level, the JAR file must contain these additional files: contents.rdfThe two .png files and some information in the contents.rdf file are used in the Theme Manager dialog box to preview and describe the theme. See any downloadable theme for an example. The files can be any raster image format the Firefox understands. There is only one contents.rdf file in the JAR archive; it aggregates all the content of the various contents.rdf files that would otherwise appear one-per-skin in these locations: package-name/contents.rdfFinally, the install.rdf file contains the product registration information [Hack #88] for the theme. Some of this is also visible in the Theme Manager. 8.7.3. Installation SupportTo install a downloadable theme, use the same web page scripts that extensions require [Hack #88] . Because themes have a very regular and predictable format, there is no special install.js file requiredjust make sure the XPI file is delivered with the right content type. Firefox reads the downloaded theme, unpacks the JAR, and automatically deploys all of the pieces into the right spots. Alternatively, you can trigger XPInstall the old-fashioned way with a script and a raw JAR file: <script> |