summaryrefslogtreecommitdiff
path: root/components/jetpack/sdk/addon
diff options
context:
space:
mode:
Diffstat (limited to 'components/jetpack/sdk/addon')
-rw-r--r--components/jetpack/sdk/addon/bootstrap.js179
-rw-r--r--components/jetpack/sdk/addon/events.js56
-rw-r--r--components/jetpack/sdk/addon/host.js12
-rw-r--r--components/jetpack/sdk/addon/installer.js121
-rw-r--r--components/jetpack/sdk/addon/manager.js18
-rw-r--r--components/jetpack/sdk/addon/runner.js180
-rw-r--r--components/jetpack/sdk/addon/window.js66
7 files changed, 0 insertions, 632 deletions
diff --git a/components/jetpack/sdk/addon/bootstrap.js b/components/jetpack/sdk/addon/bootstrap.js
deleted file mode 100644
index a6055bd10..000000000
--- a/components/jetpack/sdk/addon/bootstrap.js
+++ /dev/null
@@ -1,179 +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";
-
-const { Cu } = require("chrome");
-const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-const { Task: { spawn } } = require("resource://gre/modules/Task.jsm");
-const { readURI } = require("sdk/net/url");
-const { mount, unmount } = require("sdk/uri/resource");
-const { setTimeout } = require("sdk/timers");
-const { Loader, Require, Module, main, unload } = require("toolkit/loader");
-const prefs = require("sdk/preferences/service");
-
-// load below now, so that it can be used by sdk/addon/runner
-// see bug https://bugzilla.mozilla.org/show_bug.cgi?id=1042239
-const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {});
-
-const REASON = [ "unknown", "startup", "shutdown", "enable", "disable",
- "install", "uninstall", "upgrade", "downgrade" ];
-
-const UUID_PATTERN = /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/;
-// Takes add-on ID and normalizes it to a domain name so that add-on
-// can be mapped to resource://domain/
-const readDomain = id =>
- // If only `@` character is the first one, than just substract it,
- // otherwise fallback to legacy normalization code path. Note: `.`
- // is valid character for resource substitutaiton & we intend to
- // make add-on URIs intuitive, so it's best to just stick to an
- // add-on author typed input.
- id.lastIndexOf("@") === 0 ? id.substr(1).toLowerCase() :
- id.toLowerCase().
- replace(/@/g, "-at-").
- replace(/\./g, "-dot-").
- replace(UUID_PATTERN, "$1");
-
-const readPaths = id => {
- const base = `extensions.modules.${id}.path.`;
- const domain = readDomain(id);
- return prefs.keys(base).reduce((paths, key) => {
- const value = prefs.get(key);
- const name = key.replace(base, "");
- const path = name.split(".").join("/");
- const prefix = path.length ? `${path}/` : path;
- const uri = value.endsWith("/") ? value : `${value}/`;
- const root = `extensions.modules.${domain}.commonjs.path.${name}`;
-
- mount(root, uri);
-
- paths[prefix] = `resource://${root}/`;
- return paths;
- }, {});
-};
-
-const Bootstrap = function(mountURI) {
- this.mountURI = mountURI;
- this.install = this.install.bind(this);
- this.uninstall = this.uninstall.bind(this);
- this.startup = this.startup.bind(this);
- this.shutdown = this.shutdown.bind(this);
-};
-Bootstrap.prototype = {
- constructor: Bootstrap,
- mount(domain, rootURI) {
- mount(domain, rootURI);
- this.domain = domain;
- },
- unmount() {
- if (this.domain) {
- unmount(this.domain);
- this.domain = null;
- }
- },
- install(addon, reason) {
- return new Promise(resolve => resolve());
- },
- uninstall(addon, reason) {
- return new Promise(resolve => {
- const {id} = addon;
-
- prefs.reset(`extensions.${id}.sdk.domain`);
- prefs.reset(`extensions.${id}.sdk.version`);
- prefs.reset(`extensions.${id}.sdk.rootURI`);
- prefs.reset(`extensions.${id}.sdk.baseURI`);
- prefs.reset(`extensions.${id}.sdk.load.reason`);
-
- resolve();
- });
- },
- startup(addon, reasonCode) {
- const { id, version, resourceURI: { spec: addonURI } } = addon;
- const rootURI = this.mountURI || addonURI;
- const reason = REASON[reasonCode];
- const self = this;
-
- return spawn(function*() {
- const metadata = JSON.parse(yield readURI(`${rootURI}package.json`));
- const domain = readDomain(id);
- const baseURI = `resource://${domain}/`;
-
- this.mount(domain, rootURI);
-
- prefs.set(`extensions.${id}.sdk.domain`, domain);
- prefs.set(`extensions.${id}.sdk.version`, version);
- prefs.set(`extensions.${id}.sdk.rootURI`, rootURI);
- prefs.set(`extensions.${id}.sdk.baseURI`, baseURI);
- prefs.set(`extensions.${id}.sdk.load.reason`, reason);
-
- const command = prefs.get(`extensions.${id}.sdk.load.command`);
-
- const loader = Loader({
- id,
- isNative: true,
- checkCompatibility: true,
- prefixURI: baseURI,
- rootURI: baseURI,
- name: metadata.name,
- paths: Object.assign({
- "": "resource://gre/modules/commonjs/",
- "devtools/": "resource://devtools/",
- "./": baseURI
- }, readPaths(id)),
- manifest: metadata,
- metadata: metadata,
- modules: {
- "@test/options": {},
- },
- noQuit: prefs.get(`extensions.${id}.sdk.test.no-quit`, false)
- });
- self.loader = loader;
-
- const module = Module("package.json", `${baseURI}package.json`);
- const require = Require(loader, module);
- const main = command === "test" ? "sdk/test/runner" : null;
- const prefsURI = `${baseURI}defaults/preferences/prefs.js`;
-
- const { startup } = require("sdk/addon/runner");
- startup(reason, {loader, main, prefsURI});
- }.bind(this)).catch(error => {
- console.error(`Failed to start ${id} addon`, error);
- throw error;
- });
- },
- shutdown(addon, code) {
- this.unmount();
- return this.unload(REASON[code]);
- },
- unload(reason) {
- return new Promise(resolve => {
- const { loader } = this;
- if (loader) {
- this.loader = null;
- unload(loader, reason);
-
- setTimeout(() => {
- for (let uri of Object.keys(loader.sandboxes)) {
- let sandbox = loader.sandboxes[uri];
- if (Cu.getClassName(sandbox, true) == "Sandbox")
- Cu.nukeSandbox(sandbox);
- delete loader.sandboxes[uri];
- delete loader.modules[uri];
- }
-
- try {
- Cu.nukeSandbox(loader.sharedGlobalSandbox);
- } catch (e) {
- Cu.reportError(e);
- }
-
- resolve();
- }, 1000);
- }
- else {
- resolve();
- }
- });
- }
-};
-exports.Bootstrap = Bootstrap;
diff --git a/components/jetpack/sdk/addon/events.js b/components/jetpack/sdk/addon/events.js
deleted file mode 100644
index 45bada6e1..000000000
--- a/components/jetpack/sdk/addon/events.js
+++ /dev/null
@@ -1,56 +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': 'experimental'
-};
-
-var { request: hostReq, response: hostRes } = require('./host');
-var { defer: async } = require('../lang/functional');
-var { defer } = require('../core/promise');
-var { emit: emitSync, on, off } = require('../event/core');
-var { uuid } = require('../util/uuid');
-var emit = async(emitSync);
-
-// Map of IDs to deferreds
-var requests = new Map();
-
-// May not be necessary to wrap this in `async`
-// once promises are async via bug 881047
-var receive = async(function ({data, id, error}) {
- let request = requests.get(id);
- if (request) {
- if (error) request.reject(error);
- else request.resolve(clone(data));
- requests.delete(id);
- }
-});
-on(hostRes, 'data', receive);
-
-/*
- * Send is a helper to be used in client APIs to send
- * a request to host
- */
-function send (eventName, data) {
- let id = uuid();
- let deferred = defer();
- requests.set(id, deferred);
- emit(hostReq, 'data', {
- id: id,
- data: clone(data),
- event: eventName
- });
- return deferred.promise;
-}
-exports.send = send;
-
-/*
- * Implement internal structured cloning algorithm in the future?
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#internal-structured-cloning-algorithm
- */
-function clone (obj) {
- return JSON.parse(JSON.stringify(obj || {}));
-}
diff --git a/components/jetpack/sdk/addon/host.js b/components/jetpack/sdk/addon/host.js
deleted file mode 100644
index 91aa0e869..000000000
--- a/components/jetpack/sdk/addon/host.js
+++ /dev/null
@@ -1,12 +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": "experimental"
-};
-
-exports.request = {};
-exports.response = {};
diff --git a/components/jetpack/sdk/addon/installer.js b/components/jetpack/sdk/addon/installer.js
deleted file mode 100644
index bb8cf8d16..000000000
--- a/components/jetpack/sdk/addon/installer.js
+++ /dev/null
@@ -1,121 +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/. */
-
-module.metadata = {
- "stability": "experimental"
-};
-
-const { Cc, Ci, Cu } = require("chrome");
-const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
-const { defer } = require("../core/promise");
-const { setTimeout } = require("../timers");
-
-/**
- * `install` method error codes:
- *
- * https://developer.mozilla.org/en/Addons/Add-on_Manager/AddonManager#AddonInstall_errors
- */
-exports.ERROR_NETWORK_FAILURE = AddonManager.ERROR_NETWORK_FAILURE;
-exports.ERROR_INCORRECT_HASH = AddonManager.ERROR_INCORRECT_HASH;
-exports.ERROR_CORRUPT_FILE = AddonManager.ERROR_CORRUPT_FILE;
-exports.ERROR_FILE_ACCESS = AddonManager.ERROR_FILE_ACCESS;
-
-/**
- * Immediatly install an addon.
- *
- * @param {String} xpiPath
- * file path to an xpi file to install
- * @return {Promise}
- * A promise resolved when the addon is finally installed.
- * Resolved with addon id as value or rejected with an error code.
- */
-exports.install = function install(xpiPath) {
- let { promise, resolve, reject } = defer();
-
- // Create nsIFile for the xpi file
- let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
- try {
- file.initWithPath(xpiPath);
- }
- catch(e) {
- reject(exports.ERROR_FILE_ACCESS);
- return promise;
- }
-
- // Listen for installation end
- let listener = {
- onInstallEnded: function(aInstall, aAddon) {
- aInstall.removeListener(listener);
- // Bug 749745: on FF14+, onInstallEnded is called just before `startup()`
- // is called, but we expect to resolve the promise only after it.
- // As startup is called synchronously just after onInstallEnded,
- // a simple setTimeout(0) is enough
- setTimeout(resolve, 0, aAddon.id);
- },
- onInstallFailed: function (aInstall) {
- aInstall.removeListener(listener);
- reject(aInstall.error);
- },
- onDownloadFailed: function(aInstall) {
- this.onInstallFailed(aInstall);
- }
- };
-
- // Order AddonManager to install the addon
- AddonManager.getInstallForFile(file, function(install) {
- if (install.error == 0) {
- install.addListener(listener);
- install.install();
- } else {
- reject(install.error);
- }
- });
-
- return promise;
-};
-
-exports.uninstall = function uninstall(addonId) {
- let { promise, resolve, reject } = defer();
-
- // Listen for uninstallation end
- let listener = {
- onUninstalled: function onUninstalled(aAddon) {
- if (aAddon.id != addonId)
- return;
- AddonManager.removeAddonListener(listener);
- resolve();
- }
- };
- AddonManager.addAddonListener(listener);
-
- // Order Addonmanager to uninstall the addon
- getAddon(addonId).then(addon => addon.uninstall(), reject);
-
- return promise;
-};
-
-exports.disable = function disable(addonId) {
- return getAddon(addonId).then(addon => {
- addon.userDisabled = true;
- return addonId;
- });
-};
-
-exports.enable = function enabled(addonId) {
- return getAddon(addonId).then(addon => {
- addon.userDisabled = false;
- return addonId;
- });
-};
-
-exports.isActive = function isActive(addonId) {
- return getAddon(addonId).then(addon => addon.isActive && !addon.appDisabled);
-};
-
-const getAddon = function getAddon (id) {
- let { promise, resolve, reject } = defer();
- AddonManager.getAddonByID(id, addon => addon ? resolve(addon) : reject());
- return promise;
-}
-exports.getAddon = getAddon;
diff --git a/components/jetpack/sdk/addon/manager.js b/components/jetpack/sdk/addon/manager.js
deleted file mode 100644
index 7ac0a7d6e..000000000
--- a/components/jetpack/sdk/addon/manager.js
+++ /dev/null
@@ -1,18 +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": "experimental"
-};
-
-const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
-const { defer } = require("../core/promise");
-
-function getAddonByID(id) {
- let { promise, resolve } = defer();
- AddonManager.getAddonByID(id, resolve);
- return promise;
-}
-exports.getAddonByID = getAddonByID;
diff --git a/components/jetpack/sdk/addon/runner.js b/components/jetpack/sdk/addon/runner.js
deleted file mode 100644
index 3977a04e4..000000000
--- a/components/jetpack/sdk/addon/runner.js
+++ /dev/null
@@ -1,180 +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/. */
-
-module.metadata = {
- "stability": "experimental"
-};
-
-const { Cc, Ci, Cu } = require('chrome');
-const { rootURI, metadata, isNative } = require('@loader/options');
-const { id, loadReason } = require('../self');
-const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
-const { once } = require('../system/events');
-const { exit, env, staticArgs } = require('../system');
-const { when: unload } = require('../system/unload');
-const globals = require('../system/globals');
-const xulApp = require('../system/xul-app');
-const { get } = require('../preferences/service');
-const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
- getService(Ci.nsIAppShellService);
-const { preferences } = metadata;
-
-const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function () {
- return Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", {}).
- BrowserToolboxProcess;
-});
-
-// Initializes default preferences
-function setDefaultPrefs(prefsURI) {
- const prefs = Cc['@mozilla.org/preferences-service;1'].
- getService(Ci.nsIPrefService).
- QueryInterface(Ci.nsIPrefBranch2);
- const branch = prefs.getDefaultBranch('');
- const sandbox = Sandbox({
- name: prefsURI,
- prototype: {
- pref: function(key, val) {
- switch (typeof val) {
- case 'boolean':
- branch.setBoolPref(key, val);
- break;
- case 'number':
- if (val % 1 == 0) // number must be a integer, otherwise ignore it
- branch.setIntPref(key, val);
- break;
- case 'string':
- branch.setCharPref(key, val);
- break;
- }
- }
- }
- });
- // load preferences.
- evaluate(sandbox, prefsURI);
-}
-
-function definePseudo(loader, id, exports) {
- let uri = resolveURI(id, loader.mapping);
- loader.modules[uri] = { exports: exports };
-}
-
-function startup(reason, options) {
- return Startup.onceInitialized.then(() => {
- // Inject globals ASAP in order to have console API working ASAP
- Object.defineProperties(options.loader.globals, descriptor(globals));
-
- // NOTE: Module is intentionally required only now because it relies
- // on existence of hidden window, which does not exists until startup.
- let { ready } = require('../addon/window');
- // Load localization manifest and .properties files.
- // Run the addon even in case of error (best effort approach)
- require('../l10n/loader').
- load(rootURI).
- then(null, function failure(error) {
- if (!isNative)
- console.info("Error while loading localization: " + error.message);
- }).
- then(function onLocalizationReady(data) {
- // Exports data to a pseudo module so that api-utils/l10n/core
- // can get access to it
- definePseudo(options.loader, '@l10n/data', data ? data : null);
- return ready;
- }).then(function() {
- run(options);
- }).then(null, console.exception);
- return void 0; // otherwise we raise a warning, see bug 910304
- });
-}
-
-function run(options) {
- try {
- // Try initializing HTML localization before running main module. Just print
- // an exception in case of error, instead of preventing addon to be run.
- try {
- // Do not enable HTML localization while running test as it is hard to
- // disable. Because unit tests are evaluated in a another Loader who
- // doesn't have access to this current loader.
- if (options.main !== 'sdk/test/runner') {
- require('../l10n/html').enable();
- }
- }
- catch(error) {
- console.exception(error);
- }
-
- // native-options does stuff directly with preferences key from package.json
- if (preferences && preferences.length > 0) {
- try {
- require('../preferences/native-options').
- enable({ preferences: preferences, id: id }).
- catch(console.exception);
- }
- catch (error) {
- console.exception(error);
- }
- }
- else {
- // keeping support for addons packaged with older SDK versions,
- // when cfx didn't include the 'preferences' key in @loader/options
-
- // Initialize inline options localization, without preventing addon to be
- // run in case of error
- try {
- require('../l10n/prefs').enable();
- }
- catch(error) {
- console.exception(error);
- }
-
- // TODO: When bug 564675 is implemented this will no longer be needed
- // Always set the default prefs, because they disappear on restart
- if (options.prefsURI) {
- // Only set if `prefsURI` specified
- try {
- setDefaultPrefs(options.prefsURI);
- }
- catch (err) {
- // cfx bootstrap always passes prefsURI, even in addons without prefs
- }
- }
- }
-
- // this is where the addon's main.js finally run.
- let program = main(options.loader, options.main);
-
- if (typeof(program.onUnload) === 'function')
- unload(program.onUnload);
-
- if (typeof(program.main) === 'function') {
- program.main({
- loadReason: loadReason,
- staticArgs: staticArgs
- }, {
- print: function print(_) { dump(_ + '\n') },
- quit: exit
- });
- }
-
- if (get("extensions." + id + ".sdk.debug.show", false)) {
- BrowserToolboxProcess.init({ addonID: id });
- }
- } catch (error) {
- console.exception(error);
- throw error;
- }
-}
-exports.startup = startup;
-
-// If add-on is lunched via `cfx run` we need to use `system.exit` to let
-// cfx know we're done (`cfx test` will take care of exit so we don't do
-// anything here).
-if (env.CFX_COMMAND === 'run') {
- unload(function(reason) {
- if (reason === 'shutdown')
- exit(0);
- });
-}
diff --git a/components/jetpack/sdk/addon/window.js b/components/jetpack/sdk/addon/window.js
deleted file mode 100644
index 93ed1d8dc..000000000
--- a/components/jetpack/sdk/addon/window.js
+++ /dev/null
@@ -1,66 +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": "experimental"
-};
-
-const { Ci, Cc } = require("chrome");
-const { make: makeWindow, getHiddenWindow } = require("../window/utils");
-const { create: makeFrame, getDocShell } = require("../frame/utils");
-const { defer } = require("../core/promise");
-const { when: unload } = require("../system/unload");
-const cfxArgs = require("../test/options");
-
-var addonPrincipal = Cc["@mozilla.org/systemprincipal;1"].
- createInstance(Ci.nsIPrincipal);
-
-var hiddenWindow = getHiddenWindow();
-
-if (cfxArgs.parseable) {
- console.info("hiddenWindow document.documentURI:" +
- hiddenWindow.document.documentURI);
- console.info("hiddenWindow document.readyState:" +
- hiddenWindow.document.readyState);
-}
-
-// Once Bug 565388 is fixed and shipped we'll be able to make invisible,
-// permanent docShells. Meanwhile we create hidden top level window and
-// use it's docShell.
-var frame = makeFrame(hiddenWindow.document, {
- nodeName: "iframe",
- namespaceURI: "http://www.w3.org/1999/xhtml",
- allowJavascript: true,
- allowPlugins: true
-})
-var docShell = getDocShell(frame);
-var eventTarget = docShell.chromeEventHandler;
-
-// We need to grant docShell system principals in order to load XUL document
-// from data URI into it.
-docShell.createAboutBlankContentViewer(addonPrincipal);
-
-// Get a reference to the DOM window of the given docShell and load
-// such document into that would allow us to create XUL iframes, that
-// are necessary for hidden frames etc..
-var window = docShell.contentViewer.DOMDocument.defaultView;
-window.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
-
-// Create a promise that is delivered once add-on window is interactive,
-// used by add-on runner to defer add-on loading until window is ready.
-var { promise, resolve } = defer();
-eventTarget.addEventListener("DOMContentLoaded", function handler(event) {
- eventTarget.removeEventListener("DOMContentLoaded", handler, false);
- resolve();
-}, false);
-
-exports.ready = promise;
-exports.window = window;
-
-// Still close window on unload to claim memory back early.
-unload(function() {
- window.close()
- frame.parentNode.removeChild(frame);
-});