Vous êtes sur la page 1sur 11

Building a Thunderbird extension

Introduction
Thunderbird is Mozilla's open-source email application. It shares many of the technologies used by
Firefox, including JavaScript, the Gecko layout engine, the XUL XML User Interface Language and
the XPCOM Cross-Platform Component Object Model. Similar to Firefox, Thunderbird functionality
can be enhanced and customized via extensions.
This tutorial will introduce you to the components of a Thunderbird extension and will show you how
to build your own. The tutorial has the following pages:
1. Introduction (this page)
2. The extension filesystem (setting up your local system)
3. Install manifest (the install.rdf file that contains meta-information about the extension)
4. Chrome manifest (list of packages and overlays)
5. XUL (the XML user interface language that is used to modify the Thunderbird user interface)
6. Installing locally (enabling the extension on your local Thunderbird instance)
7. Packaging (making a distribution package that contains the extension)
8. Distributing (from your own site or from http://addons.mozilla.org/)
This tutorial is compatible with Thunderbird versions 2 and 3. All Thunderbird builds are available
from the ftp site.

References and resources


Tools and helper extensions
There are many tools available that help with developing Thunderbird extensions. At a minimum you
will need:
• Text editor: Any editor that is capable of writing plain text can be used to write extensions.
However, most developers use an editing program optimized for writing code (also known as an
Integrated Development Environment). These provide features like syntax highlighting and
code coloration, indentation, autocomplete, etc.
• File archive utility: Any utility that is capable of creating archive files can be used. Linux and
Mac include the zip utility by default.
There are also a number of extension and applications that are useful for testing and debugging
Thunderbird extensions, such as JavaScript consoles and XPCOM inspectors. These are described on
the page "Setting up an extension development environment".
To automatically generate a Firefox or Thunderbird extension framework, try the Add-on Builder on
the Add-on Developer hub.

Documentation
• Thunderbird extension documentation
• General information on developing extensions for Mozilla applications
• XUL reference
• Firefox addons developer guide (many topics are applicable to Thunderbird)
• Mozilla cross-reference source code browser ("comm-central" contains the Thunderbird code
repository)

Extension filesystem
Extensions are packaged and distributed in archive files (also known as Bundles), with the XPI
(pronounced “zippy”) file extension. An XPI file might look something like this:
exampleExt.xpi:
/install.rdf
/components/*
/components/cmdline.js
/defaults/
/defaults/preferences/*.js
/plugins/*
/chrome.manifest
/chrome/icons/default/*
/chrome/
/chrome/content/

Extensions must adhere to a particular file and directory structure. Therefore, to start, we will create
this directory structure on the local drive.
Note: Rather than manually creating the files and directory structure as explained below, you can use
the Firefox / Thunderbird Extension Wizard. This creates an archive package that contains an extension
framework, including the required files and directories. Unzip the archive into a directory called
'tutorial_ext' off the root or home directory and then edit the files to follow along with the tutorial.
First, create a top-level directory to store extensions (such as C:\tutorial_ext\ (Windows) or
~/tutorial_ext/ (Linux / Mac). Inside the new extension directory, create another directory
called content.
Inside the root directory of the extension directory, create two new empty text files, one called
chrome.manifest and the other called install.rdf. You should end up with this file and
directory structure:
tutorial_ext\
install.rdf
chrome.manifest
content\
Install manifest
Open the file called install.rdf that you created at the top of your extension's directory hierarchy
and paste the following text into the file:
<?xml version="1.0"?>

<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>myfirstext@jen.zed</em:id>
<em:name>My First Extension</em:name>
<em:version>1.0</em:version>
<em:creator>jenzed</em:creator>

<em:targetApplication>
<Description>
<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>3.0.*</em:maxVersion>
</Description>
</em:targetApplication>

</Description>
</RDF>

This file is an XML file that provides general information about the extension. The following items
(shown in bold) should be customized for your application:
• <em:id>myfirstext@jen.zed</em:id>: This is the ID of the extension. The first
portion is the short name of the extension and must be in lowercase; the last portion is a two-
part period-delimited value such as your first and last name or the top-level domain of your
website. While this value is in email address format, it is not an email address. It should,
however, be a unique value so that it does not conflict with other extensions.
• <em:name>My First Extension</em:name>: The extension name is displayed in the
Thunderbird add-on Manager.
• <em:version>1.0</em:version>: This is the version number of your extension. It must
be updated each time you release a new version of your extension. It is not the Thunderbird
version number (which is stored in the minVersion and maxVersion fields).
• <em:creator>My name</em:creator>: This optional value is used to store the
extension author's name.
• <em:minVersion>1.5</em:minVersion>: This element indicates the earliest version
of Thunderbird for which the extension is intended to work. Do not use a wildcard (such as "*").
See Valid Application Versions for a list of the supported version numbers and formats.
• <em:maxVersion>3.0.*</em:maxVersion>: This element indicates the most recent
version of Thunderbird for which the extension is intended to work. This cannot be higher than
the currently available version. "3.0.*" indicates that the extension works with Thunderbird 3.0
and any subsequent 3.0.x releases. See Valid Application Versions for a list of the supported
version numbers and formats.
There are more optional elements that can be specified in install.rdf. These are described on the
Install Manifests page. Note that elements can be specified in any order, as long as they are children of
the <Description> node.
Note: If you used the Firefox / Thunderbird Extension Wizard as described in the previous step, open
the install.rdf file that was in the archive package in a text editor. The values in the elements described
above were inserted based on the values you supplied on the form. The file also some additional,
optional elements that you can ignore.

Chrome manifest
The file called chrome.manifest tells Thunderbird what packages and overlays are provided by
the extension. Open the file called chrome.manifest that you created and add this code:
content myfirstext content/

• content specifies the type of material in the package


• myfirstext is the name of the chrome package (specified in the first segment of <em:id>
in the install.rdf file
• content/ is the location of the package's files within the chrome namespace
So, this line says that for a chrome package myfirstext, we can find its content files in the
directory content/ (which is a path relative to the location of chrome.manifest).
To change the Thunderbird user interface to support the extension, you create an overlay and then
merge it with the default Thunderbird interface. Later in the tutorial we will create a XUL overlay file
that will merge with the default messenger.xul file. At this point we are going to specify in
chrome.manifest the existence of the overlay (which we will create later).
Add this line at the end of chrome.manifest:
overlay chrome://messenger/content/messenger.xul
chrome://myfirstext/content/myhelloworld.xul

This tells Thunderbird to merge myhelloworld.xul into messenger.xul when


messenger.xul loads. For more information on chrome manifests and the properties they support,
see the Chrome Manifest Reference.
Note: If you used the Firefox / Thunderbird Extension Wizard as described in the previous step, open
the chrome.manifest file that was in the archive package in a text editor. You will see the content line at
the top of the file. Add the overlay line at the bottom of the file. It doesn't matter if there are other
overlay lines in the file.
XUL
Thunderbird's user interface is written in XUL and JavaScript. XUL is an XML grammar that provides
user interface widgets like buttons, menus, toolbars, trees etc. We add widgets by inserting new XUL
DOM elements into the application window and modify them using scripts and attaching event
handlers. While XUL provides the elements of the user interface, actions are written in JavaScript.
For our first extension, we will add some text to the Thunderbird status bar. The status bar is
implemented in a XUL file called messenger.xul. In messenger.xul we find the status bar,
which looks something like this:
<statusbar id="status-bar">
... <statusbarpanel>s ...
</statusbar>

<statusbar id="status-bar"> is a "merge point" for a XUL overlay. XUL Overlays are a
way of attaching other UI widgets to a XUL document at run time. A XUL Overlay is a .xul file that
specifies XUL fragments to insert at specific merge points within a "master" document. These
fragments can specify widgets to be inserted, removed or modified.
In this example you are adding a line to the indented statusbar. Therefore it becomes an item owned by
the id called "statusbar". This shows how the Thunderbird architecture allows extensions to modify
the user experience without modifying the installation files. This also enables version independence
between Thunderbird and Thunderbird extensions.
Example XUL Overlay Document
<?xml version="1.0"?>
<overlay id="sample"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<statusbar id="status-bar">
<statusbarpanel id="my-panel" label="Hello, World"/>
</statusbar>
</overlay>

The statusbar widget named status-bar specifies the merge point within the browser window
that we want to attach to. We want to add our item to that widget. The statusbarpanel child is a
new widget that we want to insert at the merge point. The statusbarpanel widget already exists in
the application. We are saying: "Create an instance of statusbarpanel that can be referred to as
my-panel".
Take the code for the sample.xul file above and save it into a new file called
myhelloworld.xul within the content folder you created earlier.
Installing locally
To install our extension locally, we first need to tell Thunderbird where to find it.
1. Locate your profile folder. This directory contain subdirectories for each of the defined profiles.
To ensure that your current mail and settings don't get messed up, use a test profile rather than
your standard profile when developing extensions. For example, on a Mac, your profile is
probably located in ~/Library/Thunderbird/Profiles/<Profile name>/.
Change to this directory.
2. There may already be an extensions/ directory in this directory. If not, create it. Change to
the extensions/ directory.
3. Create a new text file and put the full path to your development directory inside (for example
C:\tut_ext\ or ~/tut_ext/). Be sure to use the correct slash direction for the operating
system, include a closing slash and remove any trailing spaces.
4. Use the id of your extension (as specified in install.rdf) as the name of the file (for
example myfirstext@jen.zed).
Start Thunderbird. Thunderbird will detect the extension and automatically use it. When the message
window appears you should see the text "Hello, World!" on the right side of the status bar panel. See
Setting up extension development environment for how to set up a developer profile and enable
debugging features.
You can now go back and make changes to the .xul file. When you close and restart Thunderbird they
should appear.

Packaging
When you are satisfied with how your extension works, package it for deployment and installation.
Zip the contents of your extension's folder (not the extension folder itself), and rename the zip file to
have a .xpi extension. In Windows XP, you can do this by selecting all the files and subfolders in your
extension folder, right click and choose "Send To -> Compressed (Zipped) Folder". A .zip file will be
created for you. Just rename it and you're done!
On Mac OS X, you can right-click on the contents of the extension's folder and choose "Create Archive
of..." to make the zip file. However, since Mac OS X adds hidden files to folders in order to track file
metadata, you should instead use the Terminal, delete the hidden files (whose names begin with a
period), and then use the zip command on the command line to create the zip file.
On Linux, you would likewise use the command-line Zip tool.
cd ~/extensions/my_extensions
zip -r ../sample.xpi *

When placed in the (user's profile)/extension directory, Thunderbird will open the xpi, check the id in
the install.rdf and create that directory for your package. It will then cd to that directory and
unzip the files, thereby creating a mirror of your ~/extensions/my_extension directory
structure and files.
Distributing
Using addons.mozilla.org
The addons.mozilla.org site is a distribution site where you can host your extension for free. Your
extension will be hosted on Mozilla's mirror network. Mozilla's site also provides users with easier
installation and will automatically make new versions available to users of your existing versions when
you upload them. In addition Mozilla Update allows users to comment and provide feedback on your
extension. It is highly recommended that you use AMO to distribute your extensions.
Visit http://addons.mozilla.org/developers/ to create an account and begin distributing your extensions.
Note that your extension will be approved more quickly and downloaded more frequently if you have a
good description and screenshots of the extension in action.

Installing from a web page


There are a variety of ways you can install extensions from web pages, including direct linking to the
XPI files and using the InstallTrigger object. Extension and web authors are encouraged to use the
InstallTrigger method to install XPIs, as it provides the best experience to users.

Registering Extensions in the Windows Registry


On Windows, information about extensions can be added to the registry, and the extensions will
automatically be picked up the next time the applications starts. This allows application installers to
easily add integration hooks as extensions. See Adding Extensions using the Windows Registry for
more information.

Setting up an extension development


environment
This article gives suggestions on how to set up your Mozilla application for extension development.
Unless otherwise specified, these suggestions apply to both Firefox and Thunderbird as well as
SeaMonkey version 2.0 and above.

Overview
• Create a development user profile to run your development firefox session; with special
development preferences in about:config.
• Install some Firefox development extensions to your dev profile.
• Edit files in the extensions folder of your profile and restart the application with the dev profile.

Development profile
To avoid performance degradation from development-related prefs and extensions, and to avoid losing
your personal data, you can use a separate profile for development work.
You can run two instances of Thunderbird or Firefox at the same time by using separate profiles and
starting the application with the -no-remote parameter. For example, the following command will
start Firefox with a profile called "dev" whether an instance of Firefox is already running or not.
On Ubuntu (and many other Linux distributions):
/usr/bin/firefox -no-remote -P dev

On some other distributions of Linux/Unix:


/usr/local/bin/firefox -no-remote -P dev

On Mac:
/Applications/Firefox.app/Contents/MacOS/firefox-bin -no-remote -P dev &

On Windows:
Start -> Run "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev

On Windows 64 bit:
Start -> Run "%ProgramFiles(x86)%\Mozilla Firefox\firefox.exe" -no-remote -P dev

To start Thunderbird or SeaMonkey instead of Firefox, substitute "thunderbird" or "seamonkey" for


"firefox" in the examples above.
If the profile specified does not exist (or if no profile is specified), Thunderbird or Firefox will display
the Profile Manager. To run with the default profile, specify "default" as the profile (or omit the "-P"
switch).
(There is a thread in the Mozillazine forums that explains how to use both stable and development
versions of Firefox to check extension compatibility. See Installing Firefox 3 or Minefield while
keeping Firefox 2.)
To make the numerous restarts easier, you can make one for reading documentation / for regular use,
and the other one for extensions' testing, and run them at the same time using the no-remote
command switch as described at http://kb.mozillazine.org/Command_line_arguments . The first one
often needs lots of restarts, and you can launch both of them at the same time, like these two shortcuts
on Windows:
...firefox.exe -no-remote -p "profile1"
...firefox.exe -no-remote -p "profile2"
These are Windows-specific lines. If you find the same instructions for Linux / Mac OS / etc please
place them here too.
replace "..." with some real path. It is simple - just two shortcuts on the desktop - and lets you keep one
of the profiles always open.

Development command flags


As of Gecko 2 (Firefox 4), JavaScript files are cached ("fastload"). The -purgecaches command-
line flag disables this behavior. Alternatively, you can set the MOZ_PURGE_CACHES environment
variable. See this bug for more information.
Development preferences
There is a set of development preferences that, when enabled, allows you to view more information
about application activity, thus making debugging easier. However, these preferences can degrade
performance, so you may want to use a separate development profile when you enable these
preferences. For more information about Mozilla preferences, refer to the mozillaZine article on
"about:config".
Not all preferences are defined by default, and are therefore not listed in about:config by default.
You will have to create new (boolean) entries for them.
• javascript.options.showInConsole = true. Logs errors in chrome files to the Error Console.
• nglayout.debug.disable_xul_cache = true. Disables the XUL cache so that changes to
windows and dialogs do not require a restart. This assumes you're using directories rather than
JARs. Changes to XUL overlays will still require reloading of the document overlaid.
• browser.dom.window.dump.enabled = true. Enables the use of the dump() statement to
print to the standard console. See window.dump for more info. You can use
nsIConsoleService instead of dump() from a privileged script.
• javascript.options.strict = true. Enables strict JavaScript warnings in the Error Console. Note
that since many people have this setting turned off when developing, you will see lots of
warnings for problems with their code in addition to warnings for your own extension. You can
filter those with Console2.
• extensions.logging.enabled = true. This will send more detailed information about installation
and update problems to the Error Console. (Note that the extension manager automatically
restarts the application at startup sometimes, which may mean you won't have time to see the
messages logged before the automatic restart happens. To see them, prevent the automatic
restart by setting the environment NO_EM_RESTART to 1 before starting the application.)
• nglayout.debug.disable_xul_fastload = true. For Gecko 2.0+ (Firefox 4.0+). See this bug for
more information.
• You might also want to set dom.report_all_js_exceptions = true. See Exception logging in
JavaScript for details.
Gecko 2.0 note
(Firefox 4)

The Error Console is disabled by default starting in Firefox 4. You can re-enable it by changing the
devtools.errorconsole.enabled preference to true and restarting the browser. With this,
javascript.options.showInConsole is also set to true by default.

Accessing Firefox development preferences


To change preference settings in Firefox or SeaMonkey, type about:config in the Location Bar.
Alternatively, use the Extension Developer's Extension, which provides a menu interface for Firefox
settings.

Accessing Thunderbird development preferences


To change preference settings in Thunderbird, open the "Preferences" (Unix) or "Options" (Windows)
interface. On the "Advanced" page, select the "General" tab then click the "Config Editor" button.
Development extensions
These extensions may help you with your development.
• DOM Inspector, used to inspect and edit the live DOM of any web document or XUL
application (Firefox and Thunderbird)
• Venkman, a JavaScript Debugger (Firefox version, Thunderbird version)
• Extension Developer's Extension a suite of tools for extension development (Firefox)
• Console² enhanced JavaScript console (Firefox version, Thunderbird version)
• Javascript Command for writing/testing javascript on Firefox windows
• Chrome List navigate and view files in chrome:// (Firefox version, Thunderbird version)
• Chrome Edit Plus a user file editor (Firefox and Thunderbird)
• Add-on Builder a web-based application that generates an extension skeleton (Firefox,
Thunderbird, and others)
• Firebug a variety of development tools (Firefox)
• Chromebug combines elements of a JavaScript debugger and DOM (Firefox, "kinda works for
Thunderbird")
• MozRepl explore and modify Firefox and other Mozilla apps while they run (Firefox and
Thunderbird)
• ExecuteJS an enhanced JavaScript console (Firefox version, Thunderbird version)
• XPCOMViewer an XPCOM inspector (Firefox and Thunderbird)
• JavaScript shells to test snippets of JavaScript (Firefox and Thunderbird)
• SQLite Manager to manage the SQLite database (Firefox and Thunderbird)
• ViewAbout enables access to various about: dialogs from the View menu (Firefox version,
Thunderbird version)
• Crash Me Now! useful for testing debug symbols and the crash reporting system (Firefox and
Thunderbird)

Firefox extension proxy file


Extension files are normally installed in the user profile. However, it is usually easier to place
extension files in a temporary location, which also protects source files from accidental deletion. This
section explains how to create a proxy file that points to an extension that is installed in a location other
than the user profile.
1. Get the extension ID from the extension's install.rdf file.
2. Create a file in the "extensions" directory under your profile directory with the extension's ID as
the file name (for example "your_profile_directory/extensions/{46D1B3C0-DB7A-4b1a-863A-
6EE6F77ECB58}"). (How to find your profile directory) Alternatively, rather than using a
GUID, create a unique ID using the format "name@youremail" (for example
chromebug@mydomain.com).
3. The contents of this file should be the path to the directory that contains your install.rdf file. (eg.
"/full/path/to/yourExtension/". Windows users should use the drive name (CAPS)
and backslashes instead of frontslashes (for example
"C:\full\path\to\yourExtension\" or
"C:\sam\workspace\toolbar\helloWorldtoolbar\"). Remember to include the
closing slash and remove any trailing whitespace.
• Important: In Firefox 3, if you already installed the extension via XPI, you might need to
delete one or all of the extensions.* files in the profile folder. Backup first, but these files
will be regenerated. (I don't know what the original author had in mind here, but the files
extensions.cache, extensions.ini, extensions.rdf, are all
regenerated by Firefox if deleted. You need to delete them if you mess with
'components', no harm done. If you do not initially delete these files the first time you try
to load your extension, then the extension will silently not load. Firefox will disconnect
from its parent process when it regens these files, so you may have to exit once and
restart if you use the OS console.)
4. Place the file in the extensions folder of your profile and restart the application.

Using directories rather than JARs


Regardless of whether you choose to eventually package your extension's chrome in a JAR or in
directories, developing in directories is simpler. If you choose a JARed structure for releasing, you can
still develop with a directory structure by editing your chrome.manifest. For example, rather than
having
content myExtension jar:chrome/myExtension.jar!/content/

use
content myExtension chrome/content/

Vous aimerez peut-être aussi