diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/preferences')
-rw-r--r-- | addon-sdk/source/lib/sdk/preferences/event-target.js | 61 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/preferences/native-options.js | 193 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/preferences/service.js | 137 | ||||
-rw-r--r-- | addon-sdk/source/lib/sdk/preferences/utils.js | 42 |
4 files changed, 0 insertions, 433 deletions
diff --git a/addon-sdk/source/lib/sdk/preferences/event-target.js b/addon-sdk/source/lib/sdk/preferences/event-target.js deleted file mode 100644 index b64ba303c..000000000 --- a/addon-sdk/source/lib/sdk/preferences/event-target.js +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -'use strict'; - -module.metadata = { - "stability": "unstable" -}; - -const { Cc, Ci } = require('chrome'); -const { Class } = require('../core/heritage'); -const { EventTarget } = require('../event/target'); -const { Branch } = require('./service'); -const { emit, off } = require('../event/core'); -const { when: unload } = require('../system/unload'); - -const prefTargetNS = require('../core/namespace').ns(); - -const PrefsTarget = Class({ - extends: EventTarget, - initialize: function(options) { - options = options || {}; - EventTarget.prototype.initialize.call(this, options); - - let branchName = options.branchName || ''; - let branch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefService). - getBranch(branchName). - QueryInterface(Ci.nsIPrefBranch2); - prefTargetNS(this).branch = branch; - - // provides easy access to preference values - this.prefs = Branch(branchName); - - // start listening to preference changes - let observer = prefTargetNS(this).observer = onChange.bind(this); - branch.addObserver('', observer, false); - - // Make sure to destroy this on unload - unload(destroy.bind(this)); - } -}); -exports.PrefsTarget = PrefsTarget; - -/* HELPERS */ - -function onChange(subject, topic, name) { - if (topic === 'nsPref:changed') { - emit(this, name, name); - emit(this, '', name); - } -} - -function destroy() { - off(this); - - // stop listening to preference changes - let branch = prefTargetNS(this).branch; - branch.removeObserver('', prefTargetNS(this).observer, false); - prefTargetNS(this).observer = null; -} diff --git a/addon-sdk/source/lib/sdk/preferences/native-options.js b/addon-sdk/source/lib/sdk/preferences/native-options.js deleted file mode 100644 index 840997df9..000000000 --- a/addon-sdk/source/lib/sdk/preferences/native-options.js +++ /dev/null @@ -1,193 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -'use strict'; - -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; - - 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 -function validate(preferences) { - for (let { name, title, type, label, options } of preferences) { - // make sure the title is set and non-empty - if (!title) - throw Error("The '" + name + "' pref requires a title"); - - // make sure that pref type is a valid inline option type - if (!~VALID_PREF_TYPES.indexOf(type)) - throw Error("The '" + name + "' pref must be of valid type"); - - // if it's a control, make sure it has a label - if (type === 'control' && !label) - throw Error("The '" + name + "' control requires a label"); - - // if it's a menulist or radio, make sure it has options - if (type === 'menulist' || type === 'radio') { - if (!options) - throw Error("The '" + name + "' pref requires options"); - - // make sure each option has a value and a label - for (let item of options) { - if (!('value' in item) || !('label' in item)) - throw Error("Each option requires both a value and a label"); - } - } - - // TODO: check that pref type matches default value type - } -} -exports.validate = validate; - -// initializes default preferences, emulates defaults/prefs.js -function setDefaults(preferences, preferencesBranch) { - const branch = Cc['@mozilla.org/preferences-service;1']. - getService(Ci.nsIPrefService). - getDefaultBranch('extensions.' + preferencesBranch + '.'); - for (let { name, value } of preferences) { - switch (typeof value) { - case 'boolean': - branch.setBoolPref(name, value); - break; - case 'number': - // must be integer, ignore otherwise - if (value % 1 === 0) { - branch.setIntPref(name, value); - } - break; - case 'string': - let str = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - str.data = value; - 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 }) { - preferences.forEach(({name, type, hidden, title, description, label, options, on, off}) => { - if (hidden) { - return; - } - - 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.createElementNS(XUL_NS, 'button'); - button.setAttribute('pref-name', name); - button.setAttribute('data-jetpack-id', id); - button.setAttribute('label', label); - 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.createElementNS(XUL_NS, 'menulist'); - let menupopup = document.createElementNS(XUL_NS, 'menupopup'); - for (let { value, label } of options) { - 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.createElementNS(XUL_NS, 'radiogroup'); - for (let { value, label } of options) { - let radio = document.createElementNS(XUL_NS, 'radio'); - radio.setAttribute('value', value); - radio.setAttribute('label', label); - radiogroup.appendChild(radio); - } - setting.appendChild(radiogroup); - } - - parent.appendChild(setting); - }); -} -exports.injectOptions = injectOptions; diff --git a/addon-sdk/source/lib/sdk/preferences/service.js b/addon-sdk/source/lib/sdk/preferences/service.js deleted file mode 100644 index 231cd8e14..000000000 --- a/addon-sdk/source/lib/sdk/preferences/service.js +++ /dev/null @@ -1,137 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -"use strict"; - -module.metadata = { - "stability": "unstable" -}; - -// The minimum and maximum integers that can be set as preferences. -// The range of valid values is narrower than the range of valid JS values -// because the native preferences code treats integers as NSPR PRInt32s, -// which are 32-bit signed integers on all platforms. -const MAX_INT = 0x7FFFFFFF; -const MIN_INT = -0x80000000; - -const {Cc,Ci,Cr} = require("chrome"); - -const prefService = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefService); -const prefSvc = prefService.getBranch(null); -const defaultBranch = prefService.getDefaultBranch(null); - -const { Preferences } = require("resource://gre/modules/Preferences.jsm"); -const prefs = new Preferences({}); - -const branchKeys = branchName => - keys(branchName).map($ => $.replace(branchName, "")); - -const Branch = function(branchName) { - return new Proxy(Branch.prototype, { - getOwnPropertyDescriptor(target, name, receiver) { - return { - configurable: true, - enumerable: true, - writable: false, - value: this.get(target, name, receiver) - }; - }, - ownKeys(target) { - return branchKeys(branchName); - }, - get(target, name, receiver) { - return get(`${branchName}${name}`); - }, - set(target, name, value, receiver) { - set(`${branchName}${name}`, value); - return true; - }, - has(target, name) { - return this.hasOwn(target, name); - }, - hasOwn(target, name) { - return has(`${branchName}${name}`); - }, - deleteProperty(target, name) { - reset(`${branchName}${name}`); - return true; - } - }); -} - - -function get(name, defaultValue) { - return prefs.get(name, defaultValue); -} -exports.get = get; - - -function set(name, value) { - var prefType; - if (typeof value != "undefined" && value != null) - prefType = value.constructor.name; - - switch (prefType) { - case "Number": - if (value % 1 != 0) - throw new Error("cannot store non-integer number: " + value); - } - - prefs.set(name, value); -} -exports.set = set; - -const has = prefs.has.bind(prefs) -exports.has = has; - -function keys(root) { - return prefSvc.getChildList(root); -} -exports.keys = keys; - -const isSet = prefs.isSet.bind(prefs); -exports.isSet = isSet; - -function reset(name) { - try { - prefSvc.clearUserPref(name); - } - catch (e) { - // The pref service throws NS_ERROR_UNEXPECTED when the caller tries - // to reset a pref that doesn't exist or is already set to its default - // value. This interface fails silently in those cases, so callers - // can unconditionally reset a pref without having to check if it needs - // resetting first or trap exceptions after the fact. It passes through - // other exceptions, however, so callers know about them, since we don't - // know what other exceptions might be thrown and what they might mean. - if (e.result != Cr.NS_ERROR_UNEXPECTED) { - throw e; - } - } -} -exports.reset = reset; - -function getLocalized(name, defaultValue) { - let value = null; - try { - value = prefSvc.getComplexValue(name, Ci.nsIPrefLocalizedString).data; - } - finally { - return value || defaultValue; - } -} -exports.getLocalized = getLocalized; - -function setLocalized(name, value) { - // We can't use `prefs.set` here as we have to use `getDefaultBranch` - // (instead of `getBranch`) in order to have `mIsDefault` set to true, here: - // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#233 - // Otherwise, we do not enter into this expected condition: - // http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/nsPrefBranch.cpp#244 - defaultBranch.setCharPref(name, value); -} -exports.setLocalized = setLocalized; - -exports.Branch = Branch; - diff --git a/addon-sdk/source/lib/sdk/preferences/utils.js b/addon-sdk/source/lib/sdk/preferences/utils.js deleted file mode 100644 index 1d5769c37..000000000 --- a/addon-sdk/source/lib/sdk/preferences/utils.js +++ /dev/null @@ -1,42 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -"use strict"; - -module.metadata = { - "stability": "unstable" -}; - -const { openTab, getBrowserForTab, getTabId } = require("sdk/tabs/utils"); -const { on, off } = require("sdk/system/events"); -const { getMostRecentBrowserWindow } = require('../window/utils'); - -// Opens about:addons in a new tab, then displays the inline -// preferences of the provided add-on -const open = ({ id }) => new Promise((resolve, reject) => { - // opening the about:addons page in a new tab - let tab = openTab(getMostRecentBrowserWindow(), "about:addons"); - let browser = getBrowserForTab(tab); - - // waiting for the about:addons page to load - browser.addEventListener("load", function onPageLoad() { - browser.removeEventListener("load", onPageLoad, true); - let window = browser.contentWindow; - - // wait for the add-on's "addon-options-displayed" - on("addon-options-displayed", function onPrefDisplayed({ subject: doc, data }) { - if (data === id) { - off("addon-options-displayed", onPrefDisplayed); - resolve({ - id: id, - tabId: getTabId(tab), - "document": doc - }); - } - }, true); - - // display the add-on inline preferences page - window.gViewController.commands.cmd_showItemDetails.doCommand({ id: id }, true); - }, true); -}); -exports.open = open; |