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.
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.
Firefox 7 supports a new syntax for defining extensions' preferences for both bootstrapped and traditional extensions. The user interface for the preferences defined with this new syntax appears in the extension's detail view in the Add-on Manager. This functionality originally appeared in Firefox mobile and is now available in Firefox on the desktop as well.
The XUL allowed for the inline options is limited to a few new tags. Here is an example of an options.xul
file:
<?xml version="1.0"?> <!DOCTYPE mydialog SYSTEM "chrome://myaddon/locale/mydialog.dtd"> <vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <setting type="bool" pref="extensions.myaddon.bool" title="Boolean" desc="Stored as a boolean preference" /> </vbox>
Note that it's limited to <setting>
tags. The root <vbox>
just acts as a container, it isn't merged into the main window. If you need script support, see the display notifications section.
There are several types of <setting>
s, each with a different type
attribute:
type attribute | displayed as | preference stored as |
bool |
checkbox |
boolean |
boolint |
checkbox |
integer (use the attributes on and off to specify what values to store) |
integer |
textbox |
integer |
string |
textbox |
string |
color |
colorpicker |
string (in the #123456 format) |
file |
browse button and label | string |
directory |
browse button and label | string |
menulist |
menulist |
dependent on the menu item values |
radio |
radio buttons |
dependent on the radio values |
control |
button |
no pref stored |
The pref
attribute should have the full name of the preference to be stored. The title
attribute is used as a label for the controls. To set a description, either use the desc
attribute, or a text node as a child of the <setting>
tag.
Settings are tied to actual preferences, except the button setting, which is designed more for actions.
Some examples:
<!-- Boolean examples --> <setting pref="extensions.myaddon.bool1" type="bool" title="Boolean 1"/> <setting pref="extensions.myaddon.bool2" type="bool" title="Boolean 2"> Description of Boolean 2 </setting> <!-- Boolean stored as an integer --> <setting pref="extensions.myaddon.boolInt" type="boolint" title="Boolean 3" on="1" off="2"/> <!-- Integer example --> <setting pref="extensions.myaddon.int" type="integer" title="Integer"/> <!-- String examples --> <setting pref="extensions.myaddon.text" type="string" title="Text"/> <setting pref="extensions.myaddon.password" type="string" title="Password" inputtype="password"/> <!-- Color example --> <setting pref="extensions.myaddon.color" type="color" title="Color"/> <!-- File and directory examples --> <setting pref="extensions.myaddon.file" type="file" title="File"/> <setting pref="extensions.myaddon.directory" type="directory" title="Directory"/> <!-- List example (this example would be stored as an integer) --> <setting pref="extensions.myaddon.options1" type="menulist" title="Options 1"> <menulist> <menupopup> <menuitem value="500" label="small"/> <menuitem value="800" label="medium"/> <menuitem value="1200" label="large"/> </menupopup> </menulist> </setting> <!-- Radio Button example (this example would be stored as a boolean) --> <setting pref="extensions.myaddon.options2" type="radio" title="Options 2"> <radiogroup> <radio value="false" label="disabled"/> <radio value="true" label="enabled"/> </radiogroup> </setting> <!-- Button example - not tied to a preference, but attached to a command --> <setting title="Do Something" type="control"> <button id="myaddon-button" label="Click Me" oncommand="alert('Thank you!');"/> </setting>
Most of the setting elements (it might be all I havent really looked), support oninputchanged
attribute. So like for the type="file"
, once a user browses and picks a file, when it updates the label it will trigger the oninputchanged
attribute. So if you would like to do some changes to the XUL on the inline options page you can do so. The this
value is the setting XUL element. See MXR for what all this holds: http://mxr.mozilla.org/mozilla-release/source/toolkit/mozapps/extensions/content/setting.xml for example you can fire this.inputChanged()
etc etc.
<setting pref="extensions.ThrobberRestored.showTxtOnToolbar" title="Show Text on Toolbar Button" type="bool" oninputchanged="alert('New value is = ' + this.value); this.style.backgroundColor='red';"> If labels on other toolbar buttons are visible (like by using add-on "Classic Theme Restorer") then show label on throbber toolbar button </setting>
NOTE In order for the oninputchanged
to execute, the setting MUST have a pref
attribute, otherwise the oninputchanged
will not trigger.
Some discussion on the subject at StackOverflow: How to use addEventListener on inputChanged of inline options
If you want to use the settings UI for anything more than storing preferences, then you will probably need to initialize them when they first appear. You can't do this until your options XUL has been loaded into the Add-on Manager window, so you should listen for the addon-options-displayed
notification to initialize your settings. For example:
var observer = { observe: function(aSubject, aTopic, aData) { if (aTopic == "addon-options-displayed" && aData == "MY_ADDON@MY_DOMAIN") { var doc = aSubject; var control = doc.getElementById("myaddon-pref-control"); control.value = "test"; } } }; Services.obs.addObserver(observer, "addon-options-displayed", false); // Don't forget to remove your observer when your add-on is shut down.
This code should be in bootstrap.js
(within the startup()
function) for restartless extensions or in an XPCOM component or a JavaScript code module (not an overlay!) for traditional extensions.
Note: Starting in Gecko 13.0, you can also listen for the addon-options-hidden
notification, which has the same subject and data as above, to find out when the UI is about to be removed. Use this notification to remove event listeners, or any other references that might otherwise be leaked.
There are two ways to let the Add-on Manager find your options file:
options.xul
and put it in the extension's root folder (alongside install.rdf
). This method does not require you to create a chrome.manifest
and set it's path. This method does not require you to specify optionsType
in install.rdf.
install.rdf
to identify the XUL file used for displaying the options. This requires that you register a content
path in the chrome.manifest
. You must also specify the optionsType
as 2
:
<em:optionsURL>chrome://myaddon/content/name_of_my_file_to_use_for_inline_opts.xul</em:optionsURL>
<em:optionsType>2</em:optionsType>
Your chrome.manifest
file should contain the following, otherwise the path chrome://myaddon/content/name_of_my_file_to_use_for_inline_opts.xul
will not exist
content myaddon ./This method allows you to maintain compatibility with previous versions of Firefox by adding an override to your
chrome.manifest
:
override chrome://myaddon/content/name_of_my_file_to_use_for_inline_opts.xul chrome://myaddon/content/oldOptions.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<=6.*
If you would like to programatcially open up the add-on manager with your options displayed you can do so by using BrowserOpenAddonsMgr function which is available on "navigator:browser" type windows. For example:
Components.utils.import('resource://gre/modules/Services.jsm
');
Services.wm.getMostRecentWindow('navigator:browser').BrowserOpenAddonsMgr();
To open up the add-on manager with your inline options shown do so by passing the URL to your add-ons preferences page which is "addons://detail/" followed by your add-on id followed by "/preferences". Seen in snippet here:
Components.utils.import('resource://gre/modules/Services.jsm
');
Services.wm.getMostRecentWindow('navigator:browser').BrowserOpenAddonsMgr('addons://detail/YOUR_ADDON_ID_HERE/preferences'
);
Read more about it at this topic here on Mozilla Add-ons Forum :: How to open an add-on's preference panel?. Shown on this page are tricks, like you can pass the link to any page in the add-on manager to load that page such as the services page like: BrowserOpenAddonsMgr('addons://list/service')
.