This tutorial is aimed at software engineers who have some familiarity with the Firefox browser and the Mozilla platform. I've tried to go into some detail ,where I can, about concepts and technologies that might be new to the reader. Ultimately my aim is to be able to guide a reader who merely has Firefox installed and wants to learn some programming to extend their browser. Which of course will mean providing links to such places that teach Javascript and XUL which is far beyond the scope of a simple tutorial such as this.
In order to complete this tutorial you will need to be able to zip, and unzip files and you will need to be able to edit text files. You won't need a full Mozilla development environment, but if you have one you have everything you'll need. I don't even think you will need a command prompt, although I use one quite a bit as it is generally quicker. (I use cygwin bash on winXP & win2K)
The extension registration architecture is about to undergo a
dramatic change in order to simplify the process for developers. In current
releases of Firefox (1.0.6) and Thunderbird (1.0.6) there are
more files needed and more complicated structures in those files.
For this reason I am going to focus solely on the new architecture
of extensions and will not support browsers of the 1.0.* branch.
If I have time I will try and post versions of the examples
here that will work in the old architecture. But since the
technology is drastically improved moving forward I
won't focus much on the old way. This means that the reader will
need to install a nightly build, or build from the Trunk. If
installing, check
here for a build. If building I will trust you know how
to get a trunk build (but instructions are
here just in case).
[NOTE: I have decided to not support the old architecture at all
after starting to and deciding it was too big of a pain. If you
HAVE to support browsers from the 1.0* realm than check out the
docs at the Mozilla Developer
Center. I believe they still have docs on how to support the
legacy interfaces.]
The "Hello, World!" example is the classic starting point when learning a new computer language. We'll start there. I've created a very simple extension to Firefox to get us started. I've packaged it up and it's ready for you to install: click here to install .
If nothing happens after clicking that link you need to tell Firefox it is okay to install software from my site. You can go into Tools->Options->Web Features and add www.jgaunt.com to the list of sites allowed to install software. Or you can right click the link and save the file to your computer and install it from there by going to File->Open and pointing to the downloaded XPI file. Either way, install the extension, restart your browser and then go to the tools menu. You should see a new menu item, "Hello World", at the bottom. Click on the menu item and see what happens.
Okay, well I said it was simple. You've now installed your first very basic extension into Firefox. In the next section we'll take a look at the files you installed and talk a bit about what each one does. Then we'll take a step forward and add localization and skin files.
Grab your favorite packaging utility (jar, zip, etc...) and open up the XPI file and take a look at what is inside (if you didn't download it earlier you can either download it now or go into your profile directory and find it in the extension folder of your Firefox Profile). The format for XPI can be opened by jar, unzip, or WinZip and probably others I'm not aware of. XPI is short for Cross Platform Install (the X really means cross). It is a file format recognized by the Mozilla Platform as an installation file. Inside this file is actually a bunch of other files that define the extra functionality. If you unzip that XPI file and take a look inside you will see the following directories and files:
The install.rdf file defines some basic information about the extension. Firefox uses this information to register the extension in its system and displays some to users so they know what is installed. Most important in this file is the <em:id> tag that defines a unique ID to identify the extension by and the <em:targetApplication> tag that defines Firefox (by GUID) as the application that this extension is developed for. The min and max versions define what versions the extension is compatable with. This is going to be very important as soon as the architecture changes go through. The pre-1.0+ architectre uses additional files (install.js and multiple contents.rdf files) to identify and register extensions. The version of the extension is important for purposes of updating.
This file defines the locations of content (and skins and locale files as we'll see later) and defines which overlays should be applied to which files. The special chrome:// URIs require a mapping be made for the content. That line in the manifest tells Firefox to look in the chrome directory for a helloWorld.jar and then to find the content files in the content folder. This may seem very straightforward, but it is possible to have content for multiple extensions in the same jar file and I'll demonstrate some different ways locating files later in the tutorial. The overlay line tells Firefox that it should take the helloWorldOverlay.xul file and apply it to the browser.xul file. For more information on how overlays work I suggest a visit to XULPlanet's Overlay Section.
This file defines the additional menu item UI element that we added to Firefox. The root tag defines this file as an overlay which tells Firefox how to handle the contents. The script tag read in our javascript so we have access to those methods. The menupopup tag has the same ID as the Tools menu in Firefox to tell Firefox that is the content we want to add to. The menuitem tag is the item the ultimately gets added. Again, for a more detailed discussion of overlays see the link above at XULPlanet.
Those are all the files you need to add functionality to the
Mozilla family of applications. As extensions have a lot to do with
XUL since most functionality has to be exposed to the user I can't
suggest strongly enough that the reader take some time at check
out the tutorials at
XULPlanet. At the very least check out the overlay discussion.
In the next section we'll add a locale file and a skin file so that
our extension can be localized into different languages and styled
for different skins. That will add some files and directories to
our XPI and expand the chrome.manifest file.
There is now a new example up in the staging area. click here to install . Functionally it is not different, but behind the scences things have changed. We are moving on to a file layout that will allow us to localize our applications with little hassle. We will also be able to style our application however we wont, including skinning it differently for different firefox themes.
If you open up the .xpi and take a look at the directory structure you will notice a couple of new directories. The chrome.manifest has a couple of new entries too. The new directories are locale/en-US/ and skin/. The locale directory contains folders that represent the different language localizations that can be applied. The default locale is en-US, for the US anyway, if you build ffox on a machine with a japanese or german locale that will probably be your default.
The files that go in the locale/<your-locale-here>/ folder are *.dtd and *.ent files and properties files. In particular these files define string entities that get pulled in and used by the XUL files. So instead of having a menu with a hard-coded "Hello World" string in it, which people who don't speak english will not be able to read (heck, some people who DO speak english won't be able to read it, but that is a different issue altogether). It seems it doesn't matter which type of file the entities are in (.dtd or .ent). I use a .dtd on the off chance I need to add something else and I've never heard of .ent files before (although I'll be looking into it). The properties files contain the equivalent of entities for javascript. One "entity" per line and you don't have to worry about spaces and quoting the string.
The files in the skin folder are generally images and css files. This is where you can define the look and layout of your UI. You'll see I merely added some color to the text on the menu item. Because the UI is defined in XML you can use CSS to style it. XUL has quite a bit of layout information in it already so generally the styling done in css tends to be the images, colors and such that make the UI pretty or blend in to the current environment.
So, having these new files that seperate the strings from the content is great and all, but how do you use them? I'm looking into easier ways, but for now the following works (and is used by lots of other extensions too). To pull in the properties file you need to use a string bundle object. Add this line to your js file:
For the dtd files just add this line to process your dtd: