Getting started with extension development: Difference between revisions

From MozillaZine Knowledge Base
Jump to navigationJump to search
(→‎Planning your extension: table format changed)
Line 108: Line 108:
overlay.xul is a simple XUL overlay. You can read more about overlays at [http://xulplanet.com/tutorials/xultu/overlay.html XUL Planet], although that page describes using overlays for a different purpose.
overlay.xul is a simple XUL overlay. You can read more about overlays at [http://xulplanet.com/tutorials/xultu/overlay.html XUL Planet], although that page describes using overlays for a different purpose.


An simple overlay looks like this:
A simple overlay looks like this:


{| {{prettytable}}
{| {{prettytable}}

Revision as of 18:58, 7 February 2006

This page is part of the extension development documentation project.

Ask your questions in MozillaZine Forums. Also try browsing example code.

Note: development documentation is in process of being moved to Mozilla Development Center (MDC).

Two new major extension developers' features introduced in Firefox 1.5 are the greatly simplified chrome registration scheme and reworked Extension Manager. It is now even easier to start writing extensions than it was before.

This article describes steps needed to get started with extensions development. Last two sections have a few development tips and packaging information. Most of it is targeted at beginners in extension development, although the setup tips should be useful for everybody. This article is concise and doesn't go into discussing the technologies involved; it's more of a crash-course. Another, more detailed tutorial, is available at developer.mozilla.org.

It's a wiki page, so feel free to make improvements to this page and to add your feedback on the Talk page. However questions and requests for help are better suited for the forums.

Extensions created in this way will only work on Firefox/Thunderbird 1.5 and later, but you should be able to make changes to make your extension compatible with Firefox 1.0 quite easily later.

Again, this will work only in Firefox /Thunderbird1.5, not 1.0.x! Not 1.0.6, 1.0.7 or anything like that. Only 1.5 or later.

Setting up your environment

This article focuses on Firefox extensions, although it also applies to other Toolkit applications, such as Thunderbird.

The first thing you need to do is download a recent version of your application. You can get Firefox here. As it was mentioned above, you need Firefox 1.5 or later, setup tips from this article may not work in earlier versions.

For further instructions, see Setting up extension development environment. Do read that page, it will save you many hours when developing and debugging your extension. In particular, you must set the javascript.options.showInConsole pref to true.

What this Extension Does

This extension adds an item called 'Hello World!' to the Tools Menu in FireFox . It's a good example of creating an extension that pops up a new window when you activate it.

Planning your extension

You should plan what you need for your extension; we will use an example that provides a new menu option that creates a message in a window. The following files are required, choose your own names if you like, except for the folders and files 'chrome.manifest' and 'install.rdf'.

Filename Purpose
chrome.manifest Tells Firefox what to do with your files
install.rdf The description file for your extension
overlay.xul The highest level script file
overlay.js Lower level JavaScript code
overlay.dtd A translation for text string codes
hello.dtd A translation for the new window strings
overlay.css The display controls for your elements
hello.xul The script for the new window
helloworld@mozilla.doslash.org A pointer to your extension files

Creating stub extension files

As you should already know extensions usually modify application's UI ("chrome") and behavior by providing overlays to already existent windows/documents. Those overlays are a part of extension's content package (content provider). Most extensions also have one or more locales and skins. (If you didn't know that, we advise you to read XUL Structure chapter from XULPlanet's XUL Tutorial and Configurable Chrome document).

This section describes what directory structure and what files are needed in order to make Firefox register your extension's files.

You can download the ZIP file with all needed stub files and appropriate folder structure and skip to Registering your extension in the Extension Manager. It's recommended that you still read the subsections below though, as they contain explanations of what is the function of each file in the package and provide links to other resources.

Folder structure

Below is the folder structure we will use. You may use different structure, as long as you update your chrome.manifest (see below) accordingly. Create this in the folder where you intend to develop your project:

helloworld/
  chrome.manifest
  install.rdf
  content/
    overlay.js
    overlay.xul
    hello.xul
  locale/
    en-US/
      overlay.dtd
      hello.dtd
  skin/
      overlay.css

The folders are traditionally named "content", "locale" and "skin", and you should follow the tradition. You may call the files inside those folders whatever you want (except chrome.manifest and install.rdf).

Note: This folder structure is for development, you'll need different folder structure when packaging your extension.

Stub files

chrome.manifest

Recent versions of Firefox read simple plaintext chrome.manifest file (instead of old and confusing contents.rdf) to determine what packages and overlays your extension provides. The format of this file is described in the Chrome Registration document, we'll create an example chrome.manifest file for our folder structure.

It looks like this (assuming your extension's package name is "helloworld"):

1
2
3
4
5
6
7

content helloworld content/
overlay chrome://browser/content/browser.xul chrome://helloworld/content/overlay.xul

locale helloworld en-US locale/en-US/

skin helloworld classic/1.0 skin/
style chrome://global/content/customizeToolbar.xul chrome://helloworld/skin/overlay.css

What each line of the file does:

  • Line 1 registers a content provider: it maps contents of chrome://helloworld/content/ to the content folder.
  • Line 2 registers an overlay for chrome://browser/content/browser.xul location, allowing you to add to/modify Firefox main window UI from your overlay.xul file.
  • Line 4 registers a en-US locale provider.
  • Line 6 registers a default skin provider.
  • Line 7 applies your overlay.css style file to chrome://global/content/customizeToolbar.xul document (used, for example, when creating toolbar buttons). You could instead register an overlay and include the stylesheet in the overlay using the <?xml-stylesheet?> processing instruction.

Warning: Don't forget the end slash at the end of the paths : "content/" works, whereas "content" doesn't. Also note that the packagename ('helloworld' in this case) has to be in all lowercase.

Note: this file will be a bit different when you create an XPI for your extension, see the Packaging section below.

overlay.xul

overlay.xul is a simple XUL overlay. You can read more about overlays at XUL Planet, although that page describes using overlays for a different purpose.

A simple overlay looks like this:

1
2
3
4
5
6
7
8
9
10
11
12

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://helloworld/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://helloworld/locale/overlay.dtd">
<overlay id="helloworld-overlay"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script src="overlay.js"/>

  <menupopup id="menu_ToolsPopup">
  <menuitem id="helloworld-hello" label="&helloworld;"
    oncommand="HelloWorld.onMenuItemCommand(event);"/>
  </menupopup>
</overlay>

What each line of the file does:

  • Line 1 is the XML declaration, specifying the version of XML being used. It can also be used to specify file's encoding, but that should seldom be needed, as you should put localizable strings in the DTD file.
  • Line 2 is optional and can be used to apply a stylesheet to the base document.
  • Line 3 is also optional, but recommended if you include any user-visible strings in your overlay. It is used to make your overlay localizable.
  • Lines 4-5 define the root element of the overlay. It must be a XUL <overlay> element.
  • Line 6 is optional and can be used to attach a JavaScript file to the base document. See next section for more information.
  • Lines 8-10 add a menu item to the Tools menu in Firefox main window. See Adding items to menus for more information.

overlay.js

As you may know, JavaScript files are used to define application's behavior. Please refer to the list of JavaScript development resources for information on JavaScript in general.

An important issue you should be aware of is that all scripts that are loaded for a given document (the scripts used by the window itself, and scripts loaded from overlays to that document) share the same scope. This means you should use unique names for global identifiers in your extensions to avoid clashing with other extensions. It's usually accomplished by prefixing all global identifiers with the name of your extension or by putting most/all of your variables and functions in an object with an unique name.

Typical JavaScript file for an overlay looks like this:

var HelloWorld = {
  onLoad: function() {
    // initialization code
    this.initialized = true;
  },

  onMenuItemCommand: function() {
    window.open("chrome://helloworld/content/hello.xul", "", "chrome");
  }
};

window.addEventListener("load", function(e) { HelloWorld.onLoad(e); }, false); 

overlay.dtd

DTD files are used to make XUL/XBL/XHTML and other XML files in Mozilla chrome localizable. Basically, instead of hard-coding the strings in your XUL file, you use XML entities, which expand to the values declared in the DTD file referenced at the top of the XUL file.

It makes your extension localizable, because there may be a few different locale providers for your extension, and Mozilla is able to choose between them at run-time.

DTD files used for localization purposes consist of entity declarations like the one below:

<!ENTITY helloworld "Hello World!">

hello.dtd

This is the file for the new window.

<!ENTITY title.label "Hello World">
<!ENTITY separate.label "This is a separate window!">
<!ENTITY close.label "Close">

hello.xul

In addition to modifying existing windows, you can create new windows for your extensions. The UI of your own windows is also described in XUL files, but unlike overlays, the root element is a <window> or a <dialog>, and not <overlay>. Another difference from overlays is that you don't have to register each of new windows in chrome.manifest.

The example package includes file hello.xul, which is used to describe a simple window.

 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin/global.css"  type="text/css"?>
 <!DOCTYPE window SYSTEM "chrome://helloworld/locale/hello.dtd">
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 
         title="&title.label;">
 
 <hbox align="center">
   <description flex="1">&separate.label;</description>
   <button label="&close.label;" oncommand="close();"/>
 </hbox>
 
 </window>

install.rdf

install.rdf file is used by the Extension Manager when installing an XPI file and when registering an extension at specified location. In Firefox 1.5 and later it's only used to provide EM metadata, such as extension's ID, version, description, author etc. For more information, see install.rdf article.

 <?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>helloworld@mozilla.doslash.org</em:id>
     <em:name>Hello World (Firefox 1.5 edition)</em:name>
     <em:version>1.0</em:version>
     <em:description>Classic first extension from MozillaZine KB</em:description>
     <em:creator>Nickolay Ponomarev</em:creator>
     <!-- optional items -->
     <em:contributor>A person who helped you</em:contributor>
     <em:contributor>Another one</em:contributor>
    
 <em:homepageURL>http://kb.mozillazine.org/Getting_started_with_extension_development</em:homepageURL>
     <!-- em:optionsURL>chrome://sampleext/content/settings.xul</em:optionsURL>
     <em:aboutURL>chrome://sampleext/content/about.xul</em:aboutURL>
     <em:iconURL>chrome://sampleext/skin/mainicon.png</em:iconURL>
     
  <em:updateURL>http://sampleextension.mozdev.org/update.rdf</em:updateURL-->
 
     <!-- Firefox -->
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>1.5</em:minVersion>
         <em:maxVersion>1.5.0.*</em:maxVersion>
       </Description>
     </em:targetApplication>
 
   </Description>
 
 </RDF>

Registering your extension in the Extension Manager

Before you set your extension loose on the world you must test it. To avoid problems it is advisable to create and use a new profile for testing it.

Once you created the files described above and put them in the appropriate folder structure, registering them in the Extension Manager is trivial. With Firefox closed, create a "pointer" file with the same name as your extension's ID in profile folder/extensions/, edit it so that it contains the path to your folder containing install.rdf and chrome.manifest files.

E.g. helloworld's ID is helloworld@mozilla.doslash.org and we would like to register it in X:\Dev\helloworld\ (i.e. there is X:\Dev\helloworld\install.rdf file etc.). Just put a single line into the file at this path: profile folder/extensions/helloworld@mozilla.doslash.org

X:\Dev\helloworld

Start Firefox and check your extension is installed. Then test it.

Development cycle

Once you have registered your extension following the steps above, developing your extension is quite easy. If you've set the development preferences, your development cycle will be like this:

  1. Edit your extension files.
  2. Reopen the window(s), that modified files apply to, or use Reload chrome feature of Extension Developer Extension.
    • If you changed chrome.manifest, you'll have to restart.
    • If you changed install.rdf, you need to touch the extension folder specified in your "pointer" file (update its Last modified time) and restart.
(i.e. If you update c:\dev\helloworld\install.rdf you need to make sure the folder c:\dev\helloworld has a different timestamp.
A quick way to do this on windows is to rename c:\dev\helloworld to c:\dev\helloworld-tmp, make a new helloworld folder, then copy the contents of the helloworld-tmp folder into the new helloworld folder. Alternatively, display the folder in Explorer, right click on the right hand side pane, and select New>Folder - then just delete the New Folder.
On linux you could just use the touch command.)


It's much more convenient compared to the edit-rezip-restart cycle many extension authors were using or the pleasure of editing chrome.rdf file or similar setup tricks.

Packaging

As it was mentioned, the folder structure and chrome.manifest file must be changed before packaging. Cf.:

DevelopingPackaging
Folder structure
helloworld/
  chrome.manifest
  install.rdf
  components/
  defaults/
    preferences/
      mydefaults.js
  content/
    overlay.js
    overlay.xul
  locale/
    en-US/
      overlay.dtd
  skin/
    overlay.css
helloworld.xpi/
  chrome.manifest
  install.rdf
  components/
  defaults/
    preferences/
      mydefaults.js
  chrome/
    helloworld.jar
      content/
        overlay.js
        overlay.xul
      locale/
        en-US/
          overlay.dtd
      skin/
        overlay.css
chrome.manifest (note extra "jar:chrome/helloworld.jar!/" in the right column)
content	helloworld content/
overlay	chrome://browser/content/browser.xul	chrome://helloworld/content/overlay.xul

locale	helloworld	en-US	locale/en-US/

skin	helloworld	classic/1.0	skin/
style	chrome://global/content/customizeToolbar.xul	chrome://helloworld/skin/overlay.css
content	helloworld jar:chrome/helloworld.jar!/content/
overlay	chrome://browser/content/browser.xul	chrome://helloworld/content/overlay.xul

locale	helloworld	en-US	jar:chrome/helloworld.jar!/locale/en-US/

skin	helloworld	classic/1.0	jar:chrome/helloworld.jar!/skin/
style	chrome://global/content/customizeToolbar.xul	chrome://helloworld/skin/overlay.css

You don't have to put your chrome files in a JAR when packaging, but it is strongly recommended to do so, as it results in better startup performance.

Some links and tools are available at Packaging extensions.

Resources