We'll begin by looking at how the XUL is handled in Mozilla.
How XUL is Handled
In Mozilla, XUL is handled much in the same way that HTML is handled. When you type the URL of an HTML page into the browser's address field, the browser locates the web site and downloads the content. The Mozilla rendering engine takes the content in the form of HTML source and transforms it into a document tree. The tree is then converted into a set of objects that can be displayed on the screen. CSS, images and other technologies are used to control the presentation. XUL functions in much the same way.
In fact, in Mozilla, all document types, whether they are HTML or XUL, or even SVG are all handled by the same underlying code. This means that the same CSS properties may be used to style both HTML and XUL, and many of the features can be shared between both. However, there are some features that are specific to HTML such as forms, and others which are specific to XUL such as overlays.
Since XUL and HTML are handled in the same way, you can load both from either your local file system or from a web page. In addition, Mozilla provides a special way of installing and registering files as part of its chrome system. This involves creating an archive of the files which the user would download and install. These registered packages have enhanced privileges such as being able to read files, examine user preferences and bookmarks and access other system features. Obviously, web pages do not get these privileges, unless they are signed with a digital certificate and the user has granted these applications permission.
Registered packages are not required to use overlays, of course. If they don't, you won't be able to access them via the main browser interface, but you can still access them via a special kind of URL, designed specifically for accessing installed packages. This kind of URL is called a chrome URL and it always begins with 'chrome://'. Much like how the 'http://' URL always refers to remote web sites, and the 'file://' URL always refers to local files, the 'chrome://' URL always refers to installed packages and extensions. We'll look more at the syntax of a chrome URL in the next section.
It is important to note that when accessing content through a chrome URL, it gains the enhanced privileges described above that other kinds of URLs do not. For instance, an HTTP URL does not have any special privileges and an error will occur if a web page tries, for example, to read a local file. However, a file loaded via a chrome URL will be able to read files without restriction.
This distinction is important. This means that there are certain things that content of web pages cannot do, such as read the user's bookmarks. This distinction is not based on the kind of content being displayed; only on the type of URL used. Both HTML and XUL placed on a web site have no extra permissions; however both HTML and XUL loaded through a chrome URL have enhanced permissions.
If you are going to use XUL on a web site, you can just put the XUL file on the web site as you would an HTML file, and then load its URL in a browser. Ensure that your web server is configured to send XUL files with the content type of 'application/vnd.mozilla.xul+xml'. This content type is how Mozilla knows the difference between HTML and XUL. Mozilla does not use the file extension, unless reading files from the file system, but you should use the .xul extension for all XUL files. You can load XUL files from your own machine by opening them in the browser, or by double-clicking the file in your file manager. Remember that remote XUL will have significant restrictions on what it can do.
Currently, work is ongoing to allow XUL applications to be created as standalone applications which have their own installers and executables. While they will share Mozilla libraries, you will not need to have a browser installed in order to use XUL. It is actually somewhat possible to do this today, but the process is rather complicated and rarely done. The goal is to streamline this process.
While much of the functionality is shared between HTML and XUL, Mozilla uses a distinctly different kind of document object for each. There are three main types of document in Mozilla: HTML, XML and XUL. Naturally, the HTML document is used for HTML documents, the XUL document is used for XUL documents, and the XML document is used for other types of XML documents. Since XUL is also XML, the XUL document is a subtype of the more generic XML document. There are subtle differences in functionality. For example while the form controls on an HTML page are accessible via the 'document.forms' property, this property isn't available for XUL documents since XUL doesn't have forms in the HTML sense. On the other hand, XUL specific features such as overlays and templates are only available in XUL documents.
This distinction between documents is important. It is possible to use many XUL features in HTML or XML documents since they aren't document type specifc, however other features require the right kind of document. For instance, you can use the XUL layout types in other documents since they don't rely on the XUL document type to function.
To summarize the points made above:
- Mozilla renders both HTML and XUL using the same underlying engine and uses CSS to specify their presentation.
- XUL may be loaded from a remote site, the local file system, or installed as a package and accessed using a chrome URL. This is what browser extensions do.
- Chrome URLs may be used to access installed packages and open them with enhanced privileges.
- HTML, XML and XUL each have a different document type. Some features may be used in any document type whereas some features are specific to one kind of document.
The next few sections describe the basic structure of a chrome package which can be installed into Mozilla. However, if you just want to get started building a simple application, you may skip ahead to section 2 and save this section for later.
Mozilla is organized in such a way that you can have as many components as you want installed. A typical installation might have the navigator, messenger and editor components. It will also have one component for each installed skin and locale. Each of these components, or packages, is made up of a set of files that describe the user interface for it. For example, the messenger component will have descriptions of the mail messages list window, the composition window and the address book dialogs.
The packages that are provided with Mozilla are located within the chrome directory, which you will find in the directory where you installed Mozilla. The chrome directory is where you will find all the files that describe the user interface used by the Mozilla browser, mail client and other applications. Rather confusingly, the directory is called 'chrome' but is only marginally related to the chrome URL. Just copying a file into the 'chrome' directory doesn't give the file any extra permissions nor can it be accessed via a chrome URL. The only way to create content that can be accessed through a chrome URL is by creating a package as described in the next few sections. This directory is called 'chrome' likely because it seemed like a convenient name to use for the directory where the chrome packages that are included with Mozilla are kept.
To further the confusion, there are two other places where the word chrome might appear. The first is the '-chrome' command line argument, and the chrome modifier to the 'window.open' function. Neither of these features grant extra privileges; instead they are used to open a new top-level window without the browser UI such as the menu and toolbar. You will commonly use this feature in more complex XUL applications since you wouldn't want a browser to exist around your dialog boxes.
The files for a package are usually combined into a single JAR file. A JAR file may created and examined using a ZIP utility. For instance, open some of the JAR files in Mozilla's chrome directory to see the basic structure of a package. Although it's normal to combine the files into a JAR file, packages may also be accessed in expanded form as a set of directories. Although you don't normally distribute a package this way, it is handy during development since you can edit the file directory and then reload the XUL file without having to repackage or reinstall.
There are usually three different parts to a chrome package, although they are all optional. Each part is stored in a different directory. These three sets are the content, the skin and the locale, described below. A particular package might provide one or more skins and locales, but a user can replace them with their own. In addition, the package might include several different applications each accessible via different chrome URLs. The packaging system is flexible enough so that you can include whatever parts you need, and allow other parts, such as the text for different languages, to be downloaded separately.
- Content - Windows and scripts
The declarations of the windows and the user interface elements contained within them. These are stored in XUL files, which have a xul extension. A content package can have multiple XUL files, but the main window should have a filename that is the same as the package name. For example, the editor package will have a file within it called editor.xul. Scripts are placed in separate files alongside the XUL files.
- Skin - Style sheets, images and other theme specific files
Style sheets describe details of the appearance of a window. They are stored separately from XUL files to facilitate modifying the skin (theme) of an application. Any images used are stored here also.
- Locale - Locale specific files
All the text that is displayed within a window is stored separately. This way, a user can have a set for their own language.
Take a look at Mozilla's chrome directory. You should see a bunch of JAR files, one for each installed package. For example, the file messenger.jar describes the user interface for the Mail component. The file modern.jar describes the Modern skin.
Distinguishing a Package Type
The name of the JAR file might describe what it contains, but you can't be sure unless you view its contents. Let's use the messenger package as an example. If you extract the files in messenger.jar, you will find that it contains a directory structure much like the following:
content messenger contents.rdf messenger.xul -- other mail XUL and JS files goes here -- addressbook -- address book files go here -- messengercompose -- message composition files go here -- . . .
This is easily recognizable as a content package, as the top-level directory is called 'content'. For skins, this directory will usually be called 'skin' and for locales, it will usually be called 'locale'. Actually, this naming scheme isn't necessary but this is a common convention to make the parts of a package clearer. Some packages may include a content section, a skin and a locale. In this case, you will find a subdirectory for each type. For example, Chatzilla is distributed in this way.
In the listing above, two files have been shown. There are others of course, but for simplicity they aren't shown. The file messenger.xul is the XUL file that describes the main Mail window which displays the mail messages list. The mail window is fairly complex so it is actually made of several files each combined together using overlays. The main window for a content package should have the same name as the package with a xul extension. In this case, the package name is 'messenger', so we expect to find 'messenger.xul'. Some of the other XUL files describe separate windows. For example, the file subscribe.xul describes the dialog for subscribing to newsgroups.
The file contents.rdf is found in every package, one for each content, skin and locale in the package. This is an important file since it specifies the name of the package, its author and version. Mozilla will read this file and use its contents to register the package and assign a chrome URL to it, so that the files can be accessed through this chrome URL. Without this file, a chrome URL cannot be assigned to the package. The details of this file will be described in a later section.
Two subdirectories, addressbook and messengercompose, describe additional sections of the Mail component. They are placed in different directories only to separate them. They don't need 'contents.rdf' files because they can be accessed through the same chrome URLs.
The underlying code of Mozilla calls them skins, although the user interface calls them themes, but they both refer to the same thing. The modern.jar and classic.jar files in the Mozilla chrome directory describe the themes provided with Mozilla. Their structure is similar to the content packages. For example, examining modern.jar:
skin modern navigator contents.rdf -- navigator skin files go here -- messenger contents.rdf -- messenger skin files go here -- editor contents.rdf -- editor skin files go here -- communicator contents.rdf -- communicator skin files go here -- global contents.rdf -- global skin files go here -- . . .
This is a little more complicated, although the structure is similar to the content part. Instead of 'content' at the top level, 'skin' is used. Remember that this is purely convention, as you can actually put all the files in one directory at the top level and not use subdirectories. However, for larger applications like Mozilla itself, subdirectories are used to separate the different components. In the example above, five directories exist, one for each package that the skin is applied to. The global directory contains skin files that are general to all packages. These files will apply to all components and you will usually use this one yourself. The global part defines the appearance of all of the common XUL widgets, whereas the other directories have files that are specific to those applications. For example, the editor directory describes the skin for the editor component and contains, among other files, the images for the editor toolbar buttons.
You might notice that there are five contents.rdf files. This way, the skins are applied separately to each component. You could theoretically have a different skin for navigator as messenger, but most of the appearance is determined by the global part so you won't see much difference. Besides, Mozilla provides no capability to select a different theme for each application. They are also separate files so that new components can be added and existing components can be removed easily. For example, you could create a new theme for messenger and users could download it separately. By packaging the parts separately, the right pieces can be selected for use.
A skin is made up of CSS files and a number of images used to define the look of an interface. The file messenger.css is used by messenger.xul and contains styles which define the appearance of various parts of the mail interface. Again, note how the file messenger.css has the same name as the package. By changing the CSS files, you can adjust the appearance of a window without changing its function. This is how you can create a new theme. The XUL part remains the same but the skin part changes independently.
The file en-US.jar describes the language information for each component, in this case for US English. Like the skins, each language will contain files that specify text used by the package but for a specific language. As usual, a contents.rdf file is provided that lists the packages the locale provides text for. Subdirectories provide the text for each package. The locale structure is similar to the skin part, so we won't list it here.
The localized text is stored in two types of files, DTD files, and properties files. The DTD files have a dtd extension and contain entity declarations, one for each text string that is used in a window. For example, the file messenger.dtd contains entity declarations for each menu command. In addition, keyboard shortcuts for each command are also defined, because they may be different for each language. DTD files are used by XUL files so, in general, you will have one per XUL file. The locale part also contains properties files, which are similar, but are used by script files. The file messenger.properties contains a few such localized strings.
This structure allows you to translate Mozilla or a component into a different language by just adding a new locale for that language. You don't have to change the XUL part. In addition, another person could supply a separate package that applies a skin or locale to your content part, thus providing support for a new theme or language without having to change the original package.
Many of the packages in Mozilla are sub-packages of the communicator package. For example, you'll find the bookmarks window, the history viewer and the preferences dialogs within the communicator package. They are put there because they are general to a number of packages. There is nothing special about them.
There is a one special package called toolkit (or global). We saw the global directory earlier for skins. The toolkit.jar contains the corresponding content part for it. It contains some global dialogs and definitions. It also defines the default appearance and functionality of the various common widgets such as textboxes and buttons. The files located in the global part of a skin package contain the default look for all of the XUL interface elements. Most theme changes will involve variations of these files.
Adding a Package
Mozilla places the packages that are included with the installation in the chrome directory. However, they do not need to be placed there. If you have another package installed, it can be placed anywhere on the disk. The file chrome.rdf in the chrome directory stores the list of installed packages, skins and locales and where they are located. It is common to install new packages into the chrome directory simply because it is convenient, however they will work just as well from another directory or somewhere on your local network. You cannot store them on a remote site, unless the remote site is mounted through the local file system.
A user may have multiple skins and locales installed that modify the same package. Only one skin and locale per package is active at any given time. The file chrome/chrome.rdf in the user profile specifies which skins and locales are active. This file can also specify content packages. It works similarly to the chrome.rdf file in the main Mozilla installation, however packages specified in the profile are only installed for that user, whereas the Mozilla directory's chrome.rdf is used for packages that are available for all users.
(Next) In the next section, we'll look at how to refer to chrome packages using the chrome URL.
General information about extension development:
The new chrome architecture: