Support for extensions using XUL/XPCOM or the Add-on SDK was removed in Firefox 57, released November 2017. As there is no supported version of Firefox enabling these technologies, this page will be removed by December 2020.
Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.
Starting from Firefox 53, no new legacy add-ons will be accepted on addons.mozilla.org (AMO) for desktop Firefox and Firefox for Android.
Starting from Firefox 57, only extensions developed using WebExtensions APIs will be supported on Desktop Firefox and Firefox for Android.
Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to use WebExtensions APIs if they can. See the "Compatibility Milestones" document for more information.
A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.
This article describes best practices when making extensions, including how to be kind to your users. It assumes that you are already familiar with Building an Extension.
Using the Tool menu option gives the author the maximum amount of choices. Whether the extensions should go at the top, bottom, or somewhere in between on the Tools menu, the author always has a choice. Ideally, the location would be below the Add-ons item, grouped with the other extension-related commands (
In general, toolbar items are very useful to end users because they can be removed or added to various toolbars as necessary. Status bar items should only be added for extensions that need constant monitoring, such as ad blocking, page ranking, or cookie management. Likewise, use context menu items sparingly — only for tasks that are done frequently or on specific elements of a web page.
Don't steal focus. It's not your extension's job to take focus from the web content. If the user loads a website and they ask for focus, they should get it. Overriding their request isn't very nice.
There is a default popup About dialog that is created from install.rdf data; creating a new XUL About box is usually unnecessary. You can decrease download size by omitting a customized About box. Make one only if you have a special feature that needs to be included — for example, a custom updater.
If you have XUL buttons in your extension that do functions similar to ones that already exist in a browser — for example, a feed reader that reloads and stops — use icons from the browser's theme. The icons makes the extension lighter, while providing more consistency, especially for users using different themes.
Unique icons are usually worth their download weight. They allow for easy identification among other extensions in the Extensions manager.
There are many namespaces which extensions often must share with other consumers, be they other add-ons, web code, or the browser itself. These often include areas such as:
- Object prototypes, such as
String.prototype, which are often extended to add methods to native objects.
- Global variables, such as top-level declarations on scripts loaded into shared windows or web pages.
- Expando properties of shared objects, such as
documentobjects, or DOM nodes.
- IDs and class names in HTML and XUL documents, when extensions add elements to web pages or browser windows.
resource:packages, which are often defined in
- XPCOM contract IDs, which are often registered in
While these are among the most common examples of namespaces in which conflicts can occur, there are many others. In general, care must be taken whenever defining a name anywhere that other code might do likewise. Strategies to avoid such conflicts include:
- Avoid shared namespaces where possible
- Prefix names in shared namespaces
When shared namespaces can't be avoided, the simplest solution to prevent conflicts is to use a distinct prefix for all of your names. Class names for HTML elements created by the Cool Beans extension, for instance, might all be prefixed with
cool-beans-. Global variables might all be defined as properties of the
Some namespaces have specific conflict prevention conventions, which should be followed as appropriate. XPCOM contract IDs, for instance, should always begin with an
@, followed by a domain name that the author controls, e.g.,
It is important that the prefix that you use be unlikely to conflict with other code, and that it be indicative of the name of your add-on. Generic prefixes such as
myextension-, or short prefixes such as
ffx-, are likely to be used elsewhere, and therefore unsuitable to the purpose.
Many common libraries which create global variables provide a method called
noConflict, or similar, which revert any global variables they've declared, and return the object itself. For instance, calling
jQuery.noConflict(true)will remove the
window.$variables, and return the
jQueryobject itself, for future use by the caller.
When available, these methods should always be used to prevent conflicts with third-party code.
Be creative! Don't be redundant and include "extension," "Mozilla/Firefox/Thunderbird," or the version number in the name. Be original!
Use something that is descriptive, but that would fit in the default add-on manager width. The Mozilla extensions (Inspector/Reporter/Talkback) believe starting with a verb is the best way. For example, "Does an action in the browser."
Assume that the vast majority of your users don't have inner working knowledge of Mozilla. Make sure your extension's homepage states the "obvious," including the purpose of your extension. Users also appreciate when your extension is shipped with a simple how-to document.
Firefox/Thunderbird 1.5 or later are much more strict about the IDs of extensions than their 1.0 counterparts. Make sure they're valid.
Please follow the Mozilla pattern: major version dot current incarnation dot security/bugfix release (like 1.0.7).
Always use locale DTDs and property files, even if providing your extension in one language. It will make translation of your extension to another language easier. It occurs more often than you would think.
Firefox users like options. Lots of options. Try to include everything a user could ever want to customize in your extension, remembering more can be added later. For a large number of options for your extension, break the options window into multiple pages (tabs) that are well labeled. Don't hesitate to give long descriptions for each preference, as long as they are easy to understand, even for non-computer-savvy users. However, please make sure the default set of preferences is adequate — don't require people to tweak options in order to get your extension's core functionality.
Internal Firefox preference names for extensions or to be clear, the name of the preference as it appears in the about:config, should start with "
extensions.," then the name of the extension, with a dot, then the name of the preference. For instance, a boolean for the Reporter extension's option for hiding the privacy statement is "
Requiring a user to download another extension in order to use yours isn't nice. Avoid the dependency on other extensions, especially extensions that you didn't develop.