If you're making a new add-on from scratch, it's strongly recommended that you use the new SDK, which comes with a command-line build tool called cfx. I found this a real breeze to use, and in my opinion the files that make up your add-on are arranged in a much simpler, more intuitive structure. Another big advantage of these types of add-ons is that they are all 'restartless' extensions, which means that there's no need for the user to restart their browser after installing your add-on in order to activate it.
Getting Set up
First thing to do is get the Add-ons SDK. This includes a JavaScript library that lets your add-on interact with browser components such as tabs, menus etc. It also provides tools for add-on development (Jetpack) and packaging (cuddlefish). These tools require python 2 (version 2.7 or lower on Linux and Mac, 2.6 or lower on Windows).Once you've downloaded and unpacked the SDK, open a terminal at the root directory of where you just extracted the SDK to, and start the environment. Linux & Apple users do this by running source bin/activate, Windows people just type bin\activate. You can now create a directory for your add-on anywhere you like and initialise it with cfx init (as long as you do it from the same terminal window where you ran activate).
Note: if you're running on Arch Linux like I am, you will be on the latest version of python 3 by default which is not supported by the SDK. You will need to install python 2 from the extra repo, and then make the SDK run under it by changing the first line of bin/cfx from
#! /usr/bin/env python
to#! /usr/bin/env python2
Making A Simple Add-on
Let's build a simple Firefox add-on that will automatically reload a tab every 5 minutes. Running cfx init from your add-on directory creates the structure required by an add-on. The main code is located in the JavaScript file lib/main.js, and it should currently be empty. Open it up in your preferred text editor or IDE, and add the following code:var tabs = require("sdk/tabs");
var contextMenu = require("sdk/context-menu");
var timer = require('sdk/timers');
var menuItem = contextMenu.Item({
label: "Refresh every 5 min",
contentScript: 'self.on("click", function () { self.postMessage(); });',
onMessage: function() {
var tab = tabs.activeTab;
timer.setInterval(function() { tab.reload(); }, 300000);
}
});
The first three lines import the SDK libraries that the add-on uses: tabs and context-menu obviously allow us to interact with tabs and context menus, and timers lets us set up code that runs after a delay or repeatedly at regular intervals.Next we create a context menu item that will appear on the main context menu when the user right-clicks a web page. All we need to do is create this as a global variable, and it will automatically be added to the context menu without having to explicitly do so.
You can see that the menu item is configured by a JavaScript object passed to contextMenu.Item(). The contentScript property is where we can place code that is executed when the user selects the menu item. Here all it does is send itself an empty message, which is handled by the code in the onMessage property. Here, we get hold of the currently active tab, and set a repeating timer to reload the tab every 300000 milliseconds, ie five minutes.
We can now test this add-on in Firefox, by saving the file and running cfx run from the add-on directory. This starts up a new instance of Firefox with our add-in installed.
Once we have tested the add-on and are happy with it, we run cfx xpi to package it up as a .xpi add-on, ready for distribution through the Mozilla Add-on site or any other means. The add-on can be installed manually by choosing File > Open from the Firefox menu and browsing to the .xpi file.
Adding Items on Other Context Menus
To add items to a different context menu, such as the one you see when right clicking on text that has been selected, you need to add a context property to the object passed to contextMenu.Item() like so:var menuItem = contextMenu.Item({
context: contextMenu.SelectionContext(),
label: "This item appears on the selected text context menu",
contentScript: 'doStuff();'
});
Refer to the SDK context menu API documentation for information on the other contexts available.