Creating a Firefox sidebar

J.C. Wesdorp

jcwesdorp . at . occidopagus.nl

May 30, 2005

Abstract

This document show how to create and register a sidebar for the Firefox browser.


Table of Contents

1. Introduction
2. Pre-requisites
3. Packages
4. Deployment
5. Resources

This article descripes how to create a registered sidebar for the Firefox browser.

1. Introduction

This article is a quick start for the creation of a new sidebar for Firefox. What we will do is creating a sidebar and register it so it will be availible in the menu. The goal is creating an empty sidebar that can be used as start for new sidebar applications.

Creating a sidebar requires some GUI creation and registration in the destination application. First a simple XUL page is created. Then the registration files are made and finally the sidebar is packed into an installable XPI file.

2. Pre-requisites

This article is a quick start, it won't explain all elements of XUL, packaging and XPI's. It's preferable you have some basic knowledge of how XUL works and how Firefox handles extensions.

3. Packages

Additions to Firefox are installed with packages. A packages exists of the XUL and application logics. Optionally locales and skins can be included. Most additions are provided with a default tree structure, although not required it is recommended to use this structure. Here the package for the sidebar is created, the files included are listed below.

Example 1. Package structure

emptysidebar
\- chrome
   |- content
   |- locale
   |  \- en-US
   \- skin

Create all folders, except for skin. It is not used for this tutorial.

The locale holds the locale, only the en-US locale is created. It is listed in Example 2. The locale includes the name and shortcut keys for the sidebar.

Example 2. chrome/locale/en-US/emptysidebar.dtd"

<!ENTITY emptysidebar.title		"EmptySidebar">

<!ENTITY openEmptySidebar.commandkey	"E">
<!ENTITY openEmptySidebar.modifierskey	"shift accel">

The content folder includes our sidebar, the emptysidebar.xul is printed in Example 3. It creates a page holding one label. Other elements can be included, please read the XUL tutorials for more information.

Example 3. chrome/content/emptysidebar.xul

<?xml version="1.0"?>

<?xml-stylesheet href="chrome://global/skin/" type"text/css" ?>
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css" ?>

<!DOCTYPE page SYSTEM "chrome://emptysidebar/locale/emptysidebar.dtd">
<page id="sbEmptySidebar" title="&emptysidebar.title;"
	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >

<vbox flex="1">
	<label id="atest" value="&emptysidebar.title;" />
</vbox>

</page>

New extensions can be registered in the menus or popups, Firefox uses an overlays for extending menus. This is an separate XUL file that specifies the location of menu items. The sidebar here is added to the View | Sidebar menu. The overlay file is listed in Example 4.

Example 4. chrome/contents/emptysidebar-overlay.xul

<?xml version="1.0"?>

<!DOCTYPE overlay SYSTEM "chrome://emptysidebar/locale/emptysidebar.dtd">
<overlay id="emptySidebarOverlay"
	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

	<menupopup id="viewSidebarMenu">
		<menuitem key="key_openEmptySidebar" observes="viewEmptySidebar"  />
	</menupopup>

	<keyset id="mainKeyset">
		<key id="key_openEmptySidebar" command="viewEmptySidebar"
			key="&openEmptySidebar.commandkey;" 
			modifiers="&openEmptySidebar.modifierskey;" />
	</keyset>

	<broadcasterset id="mainBroadcasterSet"> 
		<broadcaster id="viewEmptySidebar" 
			label="&emptysidebar.title;"
			autoCheck="false"
			type="checkbox"
			group="sidebar"
			sidebarurl="chrome://emptysidebar/content/emptysidebar.xul"
			sidebarTitle="&emptysidebar.title;"
			oncommand="toggleSidebar('viewEmptySidebar');" />
	</broadcasterset>

</overlay>

The overlay file consists of three entries, the menu definition, shortcut keys and the event handler for UI elements. The broadcaster is linked to an UI element with the observes attribute. The broadcaster viewEmptySidebar defines how a click on the menu is handled or the shortcut keys are pressed.

Finally, the contents file are created. We create a contents.rdf for the folders content and locale/en-US folder. The files are listed in Example 5 and Example 6.

Example 5. chrome/content/contents.rdf

<?xml version="1.0"?>

<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

	<!-- list all packages -->
	<RDF:Seq about="urn:mozilla:package:root">
		<RDF:li resource="urn:mozilla:package:emptysidebar"/>
	</RDF:Seq>

	<!-- package information -->
	<RDF:Description about="urn:mozilla:package:emptysidebar"
		chrome:displayName="emptysidebar"
		chrome:author="www.occidopagus.nl"
		chrome:authorURL="http://www.occidopagus.nl"
		chrome:name="emptysidebar"
		chrome:extension="true"
		chrome:description="An example project"
		>
	</RDF:Description>

	<!-- Overlay information -->
	<RDF:Seq about="urn:mozilla:overlays">
		<RDF:li resource="chrome://browser/content/browser.xul" />
	</RDF:Seq>

	<RDF:Seq about="chrome://browser/content/browser.xul">
		<RDF:li>chrome://emptysidebar/content/emptysidebar-overlay.xul</RDF:li>
	</RDF:Seq>

</RDF:RDF>

Example 6. chrome/locale/en-US/contents.rdf

<?xml version="1.0"?>

<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

	<RDF:Seq about="urn:mozilla:locale:root">
		<RDF:li resource="urn:mozilla:locale:en-US" />
	</RDF:Seq>

	<RDF:Description about="urn:mozilla:locale:en-US">
		<chrome:packages>
			<RDF:Seq about="urn:mozilla:locale:en-US:packages">
				<RDF:li resource="urn:mozilla:locale:en-US:emptysidebar" />
			</RDF:Seq>
		</chrome:packages>
	</RDF:Description>

</RDF:RDF>

Now that all files have been created the extension can be installed in Firefox. All installed packages are listed in the chrome.rdf but this file should not be changed manually. For developers the easiest way is using the installed-chrome.txt file for registration. When Firefox is started it reads this file to find out which packages are installed, if new packages are found they are added to the chrome.rdf file.

The installed-chrome.txt can be found in the Firefox chrome folder. Copy the emptysidebar folder to this folder and add the lines listed in Example 7 to installed-chrome.txt.

Example 7. installed-chrome.txt

content,install,url,resource:/chrome/emptysidebar/content/
locale,install,url,resource:/chrome/emptysidebar/locale/en-US/

Restart Firefox and the sidebar is included in the menu.

The firefix sidebar menu

4. Deployment

Now that we have a sidebar it is time to make it availible to the world. Installation requires the creation of an XPI file which is identified as extension in Firefox. The XPI is a ZIP file containing the content and locale files, an install script named install.js and a manifest called install.rdf.

Example 8. chrome/install.js

const APP_NAME			= "emptySidebar";
const CHROME_NAME		= "emptysidebar";
const APP_VERSION   		= "1.0";
const APP_FILE          	= "emptysidebar.jar";
const APP_CONTENT_PATH		= "content/";

initInstall(APP_NAME, APP_CHROME_NAME, APP_VERSION);

var chromeFolder = getFolder("Current User", "chrome");
setPackageFilder(chromFolder);
addFile(APP_NAME, "chrome/" + APP_FILE, chromeFolder, "");

var jarFoder = getFolder(chromeFolder, APP_FILE);
registerChrome(CONTENT | PROFILE_CHROME, jarFolder, APP_CONTENT_PATH);

var result = getLastError();
if (result == SUCCESS) {
	performInstall();
} else {
	cancelInstall(result);
}


Example 9. emptysidebar/install.rdf

<?xml version="1.0"?>

<!-- install.rdf template copied from http://kb.mozillazine.org/Install.rdf -->

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">

	<Description about="urn:mozilla:install-manifest">
	
		<em:id>{3B1B83AA-D06E-11D9-AF35-000D932E38A8}</em:id>
		<em:name>EmptySidebar Extension</em:name>
		<em:version>1.0</em:version>
		<em:description>Example extension for creation and registration of a sidebar.</em:description>
		<em:creator>J.C. Wesdorp</em:creator>
		<!-- optional items -->
		<em:homepageURL>http://occidopagus.nl/firefox/emptysidebar/</em:homepageURL>

                <!-- Firefox -->
		<em:targetApplication>
			<Description>
				<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
				<em:minVersion>0.9</em:minVersion>
				<em:maxVersion>1.0</em:maxVersion>
			</Description>
		</em:targetApplication>

                <!-- This is not needed for Firefox 1.1 and later. Only include this 
                     if you want to make your extension compatible with older versions -->
		<em:file>
			<Description about="urn:mozilla:extension:file:emptysidebar.jar">
				<em:package>content/</em:package>
				<!-- optional items -->
				<em:locale>locale/en-US/</em:locale>
			</Description>
		</em:file>
	</Description>

</RDF>

Each extension is identified by a GUID code. A GUID has to be created for each extension. Tools for GUID creation are GuidGen from Microsoft or uuidgen on Unix systems.

The content and locale files are packed into emptysidebar.jar, create this file in the chrome folder. On unix systems:

~/src/emptysidebar$ cd chrome
~/src/emptysidebar/chrome$ zip -r emptysidebar.jar content/ locale/

Finally, create the XPI file. This is an ZIP file containing the JAR file and the install scripts.

~/src/emptysidebar/chrome$ cd ..
~/src/emptysidebar$ zip emptysidebar.xpi install.* chrome/emptysidebar.jar

Open Firefox and browse to the folder containing emptysidebar.xpi. Click on the file and the Extension installation window pops up. After a restart of Firefox the sidebar is installed. Or click here for the XPI.

The EmptySidebar extension

5. Resources

Creating Applications with Mozilla
http://books.mozdev.org/html/index.html

Packaging Firefox/Thunderbird Extensions
http://www.bengoodger.com/software/mb/extensions/packaging/extensions.html

Mozillazine: Setting up extension development environment
http://kb.mozillazine.org/Setting_up_extension_development_environment

Mozillazine: Install.rdf
http://kb.mozillazine.org/Install.rdf