From ac46df8daea09899ce30dc8fd70986e258c746bf Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 9 Feb 2018 06:46:43 -0500 Subject: Move Add-on SDK source to toolkit/jetpack --- toolkit/jetpack/sdk/loader/cuddlefish.js | 102 +++++++++++++++++++++++++++++++ toolkit/jetpack/sdk/loader/sandbox.js | 74 ++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 toolkit/jetpack/sdk/loader/cuddlefish.js create mode 100644 toolkit/jetpack/sdk/loader/sandbox.js (limited to 'toolkit/jetpack/sdk/loader') diff --git a/toolkit/jetpack/sdk/loader/cuddlefish.js b/toolkit/jetpack/sdk/loader/cuddlefish.js new file mode 100644 index 000000000..6ba19157b --- /dev/null +++ b/toolkit/jetpack/sdk/loader/cuddlefish.js @@ -0,0 +1,102 @@ +/* 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" +}; + +// This module is manually loaded by bootstrap.js in a sandbox and immediatly +// put in module cache so that it is never loaded in any other way. + +/* Workarounds to include dependencies in the manifest +require('chrome') // Otherwise CFX will complain about Components +require('toolkit/loader') // Otherwise CFX will stip out loader.js +require('sdk/addon/runner') // Otherwise CFX will stip out addon/runner.js +*/ + +const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components; + +// `loadSandbox` is exposed by bootstrap.js +const loaderURI = module.uri.replace("sdk/loader/cuddlefish.js", + "toolkit/loader.js"); +const xulappURI = module.uri.replace("loader/cuddlefish.js", + "system/xul-app.jsm"); +// We need to keep a reference to the sandbox in order to unload it in +// bootstrap.js + +var loaderSandbox = loadSandbox(loaderURI); +const loaderModule = loaderSandbox.exports; + +const { incompatibility } = Cu.import(xulappURI, {}).XulApp; + +const { override, load } = loaderModule; + +function CuddlefishLoader(options) { + let { manifest } = options; + + options = override(options, { + // Put `api-utils/loader` and `api-utils/cuddlefish` loaded as JSM to module + // cache to avoid subsequent loads via `require`. + modules: override({ + 'toolkit/loader': loaderModule, + 'sdk/loader/cuddlefish': exports + }, options.modules), + resolve: function resolve(id, requirer) { + let entry = requirer && requirer in manifest && manifest[requirer]; + let uri = null; + + // If manifest entry for this requirement is present we follow manifest. + // Note: Standard library modules like 'panel' will be present in + // manifest unless they were moved to platform. + if (entry) { + let requirement = entry.requirements[id]; + // If requirer entry is in manifest and it's requirement is not, than + // it has no authority to load since linker was not able to find it. + if (!requirement) + throw Error('Module: ' + requirer + ' has no authority to load: ' + + id, requirer); + + uri = requirement; + } else { + // If requirer is off manifest than it's a system module and we allow it + // to go off manifest by resolving a relative path. + uri = loaderModule.resolve(id, requirer); + } + return uri; + }, + load: function(loader, module) { + let result; + let error; + + // In order to get the module's metadata, we need to load the module. + // if an exception is raised here, it could be that is due to application + // incompatibility. Therefore the exception is stored, and thrown again + // only if the module seems be compatible with the application currently + // running. Otherwise the incompatibility message takes the precedence. + try { + result = load(loader, module); + } + catch (e) { + error = e; + } + + error = incompatibility(module) || error; + + if (error) + throw error; + + return result; + } + }); + + let loader = loaderModule.Loader(options); + // Hack to allow loading from `toolkit/loader`. + loader.modules[loaderURI] = loaderSandbox; + return loader; +} + +exports = override(loaderModule, { + Loader: CuddlefishLoader +}); diff --git a/toolkit/jetpack/sdk/loader/sandbox.js b/toolkit/jetpack/sdk/loader/sandbox.js new file mode 100644 index 000000000..791dbc086 --- /dev/null +++ b/toolkit/jetpack/sdk/loader/sandbox.js @@ -0,0 +1,74 @@ +/* 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 { Cc, Ci, CC, Cu } = require('chrome'); +const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(); +const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']. + getService(Ci.mozIJSSubScriptLoader); +const self = require('sdk/self'); +const { getTabId } = require('../tabs/utils'); +const { getInnerId } = require('../window/utils'); + +const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {}); +const { require: devtoolsRequire } = devtools; +const { addContentGlobal, removeContentGlobal } = devtoolsRequire("devtools/server/content-globals"); + +/** + * Make a new sandbox that inherits given `source`'s principals. Source can be + * URI string, DOMWindow or `null` for system principals. + */ +function sandbox(target, options) { + options = options || {}; + options.metadata = options.metadata ? options.metadata : {}; + options.metadata.addonID = options.metadata.addonID ? + options.metadata.addonID : self.id; + + let sandbox = Cu.Sandbox(target || systemPrincipal, options); + Cu.setSandboxMetadata(sandbox, options.metadata); + let innerWindowID = options.metadata['inner-window-id'] + if (innerWindowID) { + addContentGlobal({ + global: sandbox, + 'inner-window-id': innerWindowID + }); + } + return sandbox; +} +exports.sandbox = sandbox; + +/** + * Evaluates given `source` in a given `sandbox` and returns result. + */ +function evaluate(sandbox, code, uri, line, version) { + return Cu.evalInSandbox(code, sandbox, version || '1.8', uri || '', line || 1); +} +exports.evaluate = evaluate; + +/** + * Evaluates code under the given `uri` in the given `sandbox`. + * + * @param {String} uri + * The URL pointing to the script to load. + * It must be a local chrome:, resource:, file: or data: URL. + */ +function load(sandbox, uri) { + if (uri.indexOf('data:') === 0) { + let source = uri.substr(uri.indexOf(',') + 1); + + return evaluate(sandbox, decodeURIComponent(source), '1.8', uri, 0); + } else { + return scriptLoader.loadSubScript(uri, sandbox, 'UTF-8'); + } +} +exports.load = load; + +/** + * Forces the given `sandbox` to be freed immediately. + */ +exports.nuke = Cu.nukeSandbox -- cgit v1.2.3