We'll begin by looking at how the XUL is handled in Mozilla.
In Mozilla, XUL is handled in much the same way as HTML or other types of content are 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. Style sheets (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, from a web page, or from an extension or standalone XULRunner application.
Content from remote sources (e.g. http://localhost/~username/ )
, regardless of whether they are HTML or XUL or another document type, are limited in the type of operations they can perform, for security reasons. For this reason, Mozilla provides a method of installing content locally and registering the installed files as part of its chrome system. This allows a special URL form, called a chrome://
URL, to be used. By accessing a file using a chrome URL, the files receive elevated privileges to access local files, access preferences and bookmarks and perform other privileged operations. Obviously, web pages do not get these privileges, unless they are signed with a digital certificate and the user has granted permission to perform these operations.
This chrome package registration is the way Firefox extensions are able to add features to the browser. The extensions are small packages of XUL files, JavaScript, style sheets and images packed together into a single file. These packaged files can be created by using a ZIP utility. When the user downloads the zipped file, the packaged files will be installed onto the user's machine. The extension will hook into the browser using a XUL specific feature called an overlay which allows the XUL from the extension to mesh with the XUL in the browser. To the user, it may seem like the extension has modified the browser, but in reality, the code is all separate, and the extension may be easily uninstalled. 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 the chrome URL, if you know what it is.
Standalone XUL applications may include XUL code in a similar way, but, of course, the XUL for the application will be included as part of the installation, instead of having to be installed separately as an extension. However, this XUL code will be registered in the chrome system such that the application can display the UI.
It is worth noting that the Mozilla browser itself is actually just a set of packages containing XUL files, JavaScript and style sheets. These files are accessed via a chrome URL and have enhanced privileges and work just like any other package. Of course, the browser is much larger and more sophisticated than most extensions. Firefox and Thunderbird, as well as number of other components are all written in XUL and are all accessible via chrome URLs. You can examine these packages by looking in the chrome directory where Firefox or another XUL application is built.
The chrome URL always begins with 'chrome://'. In much the same way as an 'http://' URL always refers to remote web sites accessed using HTTP, 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 with the same access privileges as the installed extension.
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.
Remote XUL was disabled in Firefox 8, so the following is of historic interest only.
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 http://localhost/xul.php. Ensure that your web server is configured to send XUL files with the content type of application/vnd.mozilla.xul+xml
(eg with PHP header('Content-type: 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.
Mozilla uses a distinctly different kind of document object (DOM) for HTML and XUL, although they share much of the same functionality. 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. Likewise, 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 specific; 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:
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 Creating a Window and save this section for later.
Mozilla is organized such that you can have as many components as you want pre-installed. Each extension is something of a standalone component with a separate chrome URL. Mozilla also has one component for each installed theme 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 has 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 is in the directory where you built Mozilla. The chrome directory is where you find all the files that describe the user interface used by the Mozilla browser, mail client, and other applications. Typically, you put all the XUL files for an application in this directory, although extensions are installed in the extensions directory for a particular user. Just copying a XUL file into the chrome
directory doesn't give the file any extra permissions, nor can it be accessed via a chrome URL. To gain the extra privileges, you will need to create a manifest file and put that in the chrome directory. This file is easy to create, as it is typically only a couple of lines long. It is used to map a chrome URL to a file or directory path on the disk where the XUL files are located. Details of how to create this file will be discussed in a later section.
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' probably because it seemed like a convenient name to use in keeping with the chrome packages that are included with Mozilla.
To further the confusion, there are two other places where the word "chrome" might appear. These are 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 the browser UI to exist around your dialog boxes.
The files for a package are usually combined into a single JAR file. A JAR file may be created and examined using a ZIP utility. For instance, you can open 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 into a directory. Although you don't normally distribute a package this way, it is handy during development since you can edit the file directly and then reload the XUL file without having to repackage or reinstall the files.
By default, Mozilla applications parse XUL files and scripts, and store a pre-compiled version in memory for the remainder of the application session. This improves performance. However, because of this, the XUL will be not be reloaded even when the source files are changed. To disable this mechanism, it is necessary to change the preference nglayout.debug.disable_xul_cache
. In Firefox, this preference may be added to the user preferences by typing "about:config" in the address field, and setting this value to true. Or, just manually edit your user.js
preferences file and add the following line:
pref("nglayout.debug.disable_xul_cache", true);
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, which are all 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.
The three types of chrome packages are:
.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.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 browser package included with Firefox as an example. If you extract the files in browser.jar
, you will find that it contains a directory structure much like the following:
content browser browser.xul browser.js -- other browser XUL and JS files goes here -- bookmarks -- bookmarks files go here -- preferences -- preferences 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
. 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.
The content/browser
directory contains a number of files with .xul
and .js
extensions. The XUL files are the ones with the .xul
extension. The files with .js
extensions are JavaScript files containing scripts that handle the functionality of a window. Many XUL files have a script file associated with them, and some may have more than one.
In the listing above, two files have been shown. There are of course others, but for simplicity they aren't shown. The file browser.xul
is the XUL file that describes the main browser window. 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 "browser" so we expect to find browser.xul
. Some of the other XUL files describe separate windows. For example, the file pageInfo.xul
describes the page info dialog.
Many packages will include a contents.rdf
file, which describes the package, its author, and the overlays it uses. However, this file is obsolete and has been replaced with a simpler mechanism. This newer method is the manifest file mentioned earlier, and you will find these as files with the .manifest
extension in the chrome directory. For instance, browser.manifest
describes the browser package.
Several subdirectories, such as bookmarks
and preferences
, describe additional sections of the browser component. They are placed in different directories only to keep the files more organized.
Although the underlying code for Mozilla calls them skins and the user interface calls them themes, they're both referring to the same thing. The classic.jar
file describes the default theme provided with Firefox. The structure is similar to the content packages. For example, examining classic.jar
:
skin classic browser browser.css -- other browser skin files go here -- global -- global skin files go here -- . . .
Again, this directory structure isn't necessary and is used for convenience. You can actually put all the files in one directory at the top level and not use subdirectories. However, for larger applications, subdirectories are used to separate the different components. In the example above, a directory exists for theme related files for the browser and another for global theme related files. The global directory contains skin files that are general to all packages. These files will apply to all components and will be included with your own standalone applications. 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. Firefox includes both the global and browser theme files in one archive, but they can be included separately.
A skin is made up of CSS files and a number of images used to define the look of an interface. The file browser.css
is used by browser.xul
and contains styles that define the appearance of various parts of the browser interface. Again, note how the file browser.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 file contains files that specify text used by the package for a specific language. The locale structure is similar to the others, so it won't be listed 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 browser.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 browser.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 code at all. 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.
There is a special package called toolkit (or global). We saw the global directory earlier for skins. The file 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 XUL 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. The toolkit package is used by all XUL applications.
Mozilla places the packages that are included with the installation in the chrome
directory. However, they do not need to be placed there. When installing another package, you can place it anywhere on the disk, as long as a manifest file points to it. It is common to place 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.
There are two chrome
directories used for XUL applications: one is in the same place where the application is built, while the other is part of user's profile. The former allows packages that are shared by all users while the latter allows packages to be created only for a specific user or users. Extensions, while installed in a separate extensions directory, are also usually user specific. Any manifest files located in either chrome directory will be examined to see which packages are installed.
In the next section, we'll look at how to refer to chrome packages using the chrome URL.