Extension settings in a tab in Mozilla 7

In addition to settings in the Addon Manager, Firefox 7 also supports extension settings in a tab. Here's a quick bit of code you can use to provide backwards-compatibility.

Put this file at chrome://mynamespace/content/redirect.xul, point your optionsURL there, and set optionsType to 3.

<?xml version="1.0" ?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"><![CDATA[

const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import('resource://gre/modules/Services.jsm');

const FAKE_OPTIONS_URL = 'chrome://mynamespace/content/redirect.xul';
const REAL_OPTIONS_URL = 'chrome://mynamespace/content/settings.xul';

window.onload = function () {
var topWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);

if (topWindow.document.documentURI == FAKE_OPTIONS_URL) {
let recentWindow = Services.wm.getMostRecentWindow('navigator:browser');
if (recentWindow && 'switchToTabHavingURI' in recentWindow) {
recentWindow.switchToTabHavingURI(REAL_OPTIONS_URL, true);
} else {
window.openDialog(REAL_OPTIONS_URL, null, 'width=1000,height=600,centerscreen,chrome');
}
setTimeout(window.close, 0);
} else {
location.replace (REAL_OPTIONS_URL);
}
};

//]]></script>
</window>

The code will open REAL_OPTIONS_URL in a new tab in Firefox 4+ and SeaMonkey 2.1+, and a window in anything else.

New in-Addon-Manager extension settings in Mozilla 7

A new feature of the Mozilla 7 platform (soon to be on the Aurora channels) is the ability for extensions to have settings user-interface directly inside the Addon Manager. This will enable restartless extensions to easily have settings, and will also work for traditional extensions.

Here's how to use the new tools:

Create an options file

In most cases this will be a file called options.xul, and located inside the top-level directory of the extension (alongside install.rdf etc.). Alternatively, you can put this file elsewhere, and change install.rdf - em:optionsURL pointing to the file, and em:optionsType as 2.

Start with this:

<?xml version="1.0" ?>
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<!-- settings go here -->
</vbox>

The settings are represented as a list of <setting> elements of various types, for example:

<setting type="bool"
title="Boolean Setting"
desc="This is a description of the setting"
pref="extensions.settings.bool"/>

This node is represented with a checkbox. Clicking on the checkbox changes the value of the preference specified.

A description can be set with a desc attribute, or with text between the opening and closing <setting> tags. Other attributes can be use to alter the UI displayed. See the XUL documentation on MDC for control attributes.

Here's what this example looks like:

Settings Types

type attributedisplayed aspreference stored as
bool checkbox boolean
boolint checkbox integer (use the attributes on and off to specify what values to store)
integer
textbox with type="number"
integer
string textbox
string
color colorpicker with type="button"
string (in the #123456 format)
file browse button and label string
directory browse button and label
string

(NB: color, file and directory types haven't landed just yet, see this bug.)

There's also the control type, which allows you to have a button or menulist control:

<setting type="control" title="Button">
<button label="click me!" oncommand="alert('thanks!');"/>
</setting>
<setting type="control" title="Menulist">
<menulist sizetopopup="always" onchange="alert(this.value);">
<menupopup>
<menuitem label="alpha" value="1"/>
<menuitem label="beta" value="2"/>
<menuitem label="charlie" value="3"/>
<menuitem label="delta" value="4"/>
</menupopup>
</menulist>
</setting>

Note that neither of these controls have pref attributes, you'll have to control them yourself. See below for details.

Here's what all these controls look like:

Need script?

Each time the UI is loaded, the notification addon-options-displayed is sent. Here's how to use it:

var observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "addon-options-displayed" && aData == "my@addon.id") {
// your code here
// aSubject is the Addon Manager document, so you can use aSubject.getElementById etc.
}
}
};
Services.obs.addObserver(observer, "addon-options-displayed", false);

Do NOT forget to remove your observer when your extension is shut down.

Adding your own settings types

If you're mad enough you can create your own setting type. Create your own XBL binding, using chrome://mozapps/content/extensions/setting.xml for example code, and bind your setting with it like this:

<setting type="mytype"
style="display:-moz-grid-line; -moz-binding:url('chrome://mynamespace/content/mybindings.xml#binding-id');"/>

If you think your setting type will be useful to others and should become a built-in type, file a bug and CC me (geoff@darktrojan.net).

Add-on Overload

My apologies if you're trying to get my help with add-ons lately, I've had a lot of requests for features and fixes and I just can't deal with them all at once. I guess that's what happens when you get ~10000 new users in a month. On top of all this I've just discovered that all my new add-ons are broken on Firefox nightly builds. Oh, and I've had the flu for the last few weeks.

If you do need to ask me something, please do email, just don't expect an answer straight away. Slipping something into my paypal account will move you up the queue ;-)

My apologies also if you're an AMO reviewer and having to put up with new versions every few days.

Update: seems I've also run into an odd AMO bug affecting Open With 5.0.1. Get 5.0.2 instead.

Bootstrapped Add-On with Chrome - Proof of Concept

Warning: this is probably going to be complete geek nonsense to most people. Frankly if you made it this far you're doing well.

Various people in Add-Ons World have been posting ways to use bootstrapped add-ons with chrome, for locale and UI purposes. I've been working on my own answer, and I think it's a pretty tidy solution, although it does have its own problems.

The key in my solution is to give each version its own chrome namespace, so that there's no problems with cached files when the version changes.

[edit] To check whether the chrome namespace has been unregistered properly, disable the add-on and reload the test page. Error console will say "No chrome package registered for chrome://test-0.1/content/test.xul".

You can download my test addon here. I'd be interested to hear your thoughts, email me at geoff@darktrojan.net.

My new, new add-on - History Button

I seem to be in an add-on-making mood lately. Not really sure why. Perhaps it's because the things I want to see in Firefox probably aren't going to make it to Firefox 4. Anyway, here's my latest, which adds a history menu button to the toolbars, next to the existing bookmarks button.

https://addons.mozilla.org/firefox/addon/243489/

Incidentally, you may (or may not) wonder where the back/forward button's drop-down arrow has disappeared to. It's been removed, which I'm not all that happy about, but it's probably safe to say it isn't coming back.