--- a/addon-sdk/source/lib/sdk/preferences/native-options.js
+++ b/addon-sdk/source/lib/sdk/preferences/native-options.js
@@ -6,48 +6,67 @@
module.metadata = {
"stability": "unstable"
};
const { Cc, Ci, Cu } = require('chrome');
const { on } = require('../system/events');
const { id, preferencesBranch } = require('../self');
const { localizeInlineOptions } = require('../l10n/prefs');
+const { Services } = require("resource://gre/modules/Services.jsm");
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
const { defer } = require("sdk/core/promise");
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";;
const DEFAULT_OPTIONS_URL = 'data:text/xml,<placeholder/>';
const VALID_PREF_TYPES = ['bool', 'boolint', 'integer', 'string', 'color',
'file', 'directory', 'control', 'menulist', 'radio'];
+const isFennec = require("sdk/system/xul-app").is("Fennec");
+
function enable({ preferences, id }) {
let enabled = defer();
validate(preferences);
setDefaults(preferences, preferencesBranch);
// allow the use of custom options.xul
AddonManager.getAddonByID(id, (addon) => {
on('addon-options-displayed', onAddonOptionsDisplayed, true);
enabled.resolve({ id: id });
});
function onAddonOptionsDisplayed({ subject: doc, data }) {
if (data === id) {
- let parent = doc.getElementById('detail-downloads').parentNode;
- injectOptions({
- preferences: preferences,
- preferencesBranch: preferencesBranch,
- document: doc,
- parent: parent,
- id: id
- });
- localizeInlineOptions(doc);
+ let parent;
+
+ if (isFennec) {
+ parent = doc.querySelector('.options-box');
+
+ // NOTE: This disable the CSS rule that makes the options invisible
+ let item = doc.querySelector('#addons-details .addon-item');
+ item.removeAttribute("optionsURL");
+ } else {
+ parent = doc.getElementById('detail-downloads').parentNode;
+ }
+
+ if (parent) {
+ injectOptions({
+ preferences: preferences,
+ preferencesBranch: preferencesBranch,
+ document: doc,
+ parent: parent,
+ id: id
+ });
+ localizeInlineOptions(doc);
+ } else {
+ throw Error("Preferences parent node not found in Addon Details. The configured custom preferences will not be visible.");
+ }
}
}
return enabled.promise;
}
exports.enable = enable;
// centralized sanity checks
@@ -105,64 +124,67 @@ function setDefaults(preferences, prefer
branch.setComplexValue(name, Ci.nsISupportsString, str);
break;
}
}
}
exports.setDefaults = setDefaults;
// dynamically injects inline options into about:addons page at runtime
+// NOTE: on Firefox Desktop the about:addons page is a xul page document,
+// on Firefox for Android the about:addons page is an xhtml page, to support both
+// the XUL xml namespace have to be enforced.
function injectOptions({ preferences, preferencesBranch, document, parent, id }) {
for (let { name, type, hidden, title, description, label, options, on, off } of preferences) {
-
if (hidden) {
continue;
}
- let setting = document.createElement('setting');
+ let setting = document.createElementNS(XUL_NS, 'setting');
setting.setAttribute('pref-name', name);
setting.setAttribute('data-jetpack-id', id);
setting.setAttribute('pref', 'extensions.' + preferencesBranch + '.' + name);
setting.setAttribute('type', type);
setting.setAttribute('title', title);
if (description)
setting.setAttribute('desc', description);
if (type === 'file' || type === 'directory') {
setting.setAttribute('fullpath', 'true');
}
else if (type === 'control') {
- let button = document.createElement('button');
+ let button = document.createElementNS(XUL_NS, 'button');
button.setAttribute('pref-name', name);
button.setAttribute('data-jetpack-id', id);
button.setAttribute('label', label);
- button.setAttribute('oncommand', "Services.obs.notifyObservers(null, '" +
- id + "-cmdPressed', '" + name + "');");
+ button.addEventListener('command', function() {
+ Services.obs.notifyObservers(null, `${id}-cmdPressed`, name);
+ }, true);
setting.appendChild(button);
}
else if (type === 'boolint') {
setting.setAttribute('on', on);
setting.setAttribute('off', off);
}
else if (type === 'menulist') {
- let menulist = document.createElement('menulist');
- let menupopup = document.createElement('menupopup');
+ let menulist = document.createElementNS(XUL_NS, 'menulist');
+ let menupopup = document.createElementNS(XUL_NS, 'menupopup');
for (let { value, label } of options) {
- let menuitem = document.createElement('menuitem');
+ let menuitem = document.createElementNS(XUL_NS, 'menuitem');
menuitem.setAttribute('value', value);
menuitem.setAttribute('label', label);
menupopup.appendChild(menuitem);
}
menulist.appendChild(menupopup);
setting.appendChild(menulist);
}
else if (type === 'radio') {
- let radiogroup = document.createElement('radiogroup');
+ let radiogroup = document.createElementNS(XUL_NS, 'radiogroup');
for (let { value, label } of options) {
- let radio = document.createElement('radio');
+ let radio = document.createElementNS(XUL_NS, 'radio');
radio.setAttribute('value', value);
radio.setAttribute('label', label);
radiogroup.appendChild(radio);
}
setting.appendChild(radiogroup);
}
parent.appendChild(setting);