There are multitude amount of Firefox extensions downloadable over the internet right now targeting day to day website visitors and developers as their primary audience. ….. This being said, have you ever wondered what would it take to make such amazing software tools? Let me walk you through the fundamental steps in making a very basic Firefox extension.
Let's begin by creating a folder that would contain your extension definition. For illustration purposes we will name this “demo@bambitinc.com”. Inside the demo@bambitinc.com folder create another folder named content. Inside the content folder create an empty javascript file named bambit.js. On the same level as the bambit.js file create an empty XML User Interface Language file named bambit.xul. Now lets step back to the previous directory and create another two empty files named chrome.manifest and install.rdf. You should end up with a directory structure like this:
demo@bambitinc.com/
content/
bambit.js
bambit.xul
chrome.manifest
install.rdf
Using your favorite text editor, open up the bambit.xul. Inside we would want to add an overlay. In general, Firefox's interface is written in XUL defined at http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul and javascript. The XUL document defines the widgets such as the buttons, toolbars, etc. While the javascript handles the user actions. For us to extend the browser, we partially modify the browser UI by inserting, removing, or modifying the widgets defined in the master XUL. This can be accomplished using overlays. XUL overlay is a way of attaching UI widget to the XUL document at runtime.
First we would import the bambit.js that will handle user actions and modify a merge point. In this case the browser's status bar.
<?xml version="1.0"?>
<overlay id="bambit:" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript" src="chrome://bambit/content/bambit.js" />
<statusbar id="status-bar">
<statusbarpanel id="bambit"
label="Bambit"
insertbefore="statusbar-display"
onclick="bambit();"
/>
</statusbar>
</overlay>
We import the javascript file just as a child of the overlay. Take note that the path of the file is not called by the file URI nor was it a fixed path. It is invoked using the chrome URI. This is a bundled package that defines scheme, package name, type of data, and finally the file to load.
Next we defined a new child of statusbar named statusbarpanel. Statusbar serves as the merge point where the modifications would take place. The child statusbarpanel creates a new panel on the left of the statusbar-display with a text “Bambit”. The next attribute “onclick” defines the javascript function to be used when user clicked on that panel. This will be defined on the bambit.js file.
After saving open up the bambit.js file and make the function “bambit”. As a proof on concept we will only redirect the whole window to the bambit website.
function bambit(){
window.location = “http://www.bambitinc.com”;
}
Now we need to create the manifest that will be used on the chrome package. Inside the chrome.manifest file we'll define the type of material, name of the chrome package, and the location of the files. Also we need to merge our overlay with the browser during runtime. All these can be accomplished by this code.
content bambit content/
overlay chrome://browser/content/browser.xul chrome://bambit/content/bambit.xul
Finally, open up the install.rdf file. Inside place the following code.
<?xml version="1.0"?>
<RDF
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:bambit="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<bambit:id>hello-world@bambitinc.com</bambit:id>
<bambit:name>Bambit Hello World</bambit:name>
<bambit:version>1.0</bambit:version>
<bambit:type>2</bambit:type>
<bambit:targetApplication>
<Description>
<bambit:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</bambit:id>
<bambit:minVersion>1.5</bambit:minVersion>
<bambit:maxVersion>3.0.*</bambit:maxVersion>
</Description>
</bambit:targetApplication>
</Description>
</RDF>
These are the minimum elements required in the installation manifest. For the complete list of the install properties click here: (https://developer.mozilla.org/en/Install_Manifests)
- id: This is the id that makes your extension unique. On Firefox versions prior to 1.5 this can only be in a GUID format and nothing else. For 1.5 onwards it can accept GUID and email address format though it is not necessary to be a valid email address.
- name: This is the name your resource will be known universally.
- version: This represents the version of your resource.
- type: This indicate what kind of resource you are installing. Since we will install an extension that value would be 2. If we would like it to be a theme or a locale we should use 4 and 8 respectively.
- targetApplication: This defines the application you're resource is applicable to. Since we are making an extension for Firefox the id should be equal to the Firefox application id (ec8030f7-c20a-464f-9b0e-13a3a9e97384). If you notice that the mini-version is set to 1.5, that is because I used something that is not applicable to earlier versions, specifically the id of the application. Earlier versions only support GUID. For the max-version we set it to 3.0.x to ensure that the resource is compatible with Firefox's security and stability updates.
(Link to compressed file)
Test
We are now ready to test our extension. First, we need to setup a development environment. We don't want to ruin the Firefox version we are currently working on even though it is easily repairable. We do this by creating another Firefox profile. For this example “dev” is the name of the new profile.
On linux:
/usr/local/bin/firefox -no-remote -P dev
On MAC:
/Applications/Firefox.app/Contents/MacOS/firefox-bin -no-remote -P dev &
On Windows:
start "" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev
The first time you run the command it will display the profile list screen. There create the new profile named “dev”.
Now we our environment ready. What we'll do is copy the entire demo@bambitinc.com folder within the Firefox's (dev profile) extensions folder. In Vista you can go to <% Users %>\AppData\Roaming\Mozilla\Firefox\Profiles and browse through the extensions folder and paste the entire folder there. Open an instance of the development profile. You are supposed to see that a new extension named Bambit Demo is installed and you'll notice the text “Bambit” at the lower left of your status bar. Click on it and it will take the whole window to the Bambit website.
Package
Now that we got the extension working on our environment we'll need a way to publish it. Firefox's extensions are packaged as XPI files. In essence XPI files are just zipped files that have an extension of XPI. Using your favorite archive tool zipped the contents (not the folder) of the demo@bambitinc.com folder. Now delete the demo@bambitinc.com folder inside the extensions folder of your development environment. Close all instance of your Firefox development profile. You'll notice that the Bambit is no longer installed. Now using Firefox, open the XPI file you created earlier. This will go through the installation process. Viola! Your Firefox extension is made!!!