diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/page-mod.js')
-rw-r--r-- | addon-sdk/source/lib/sdk/page-mod.js | 190 |
1 files changed, 0 insertions, 190 deletions
diff --git a/addon-sdk/source/lib/sdk/page-mod.js b/addon-sdk/source/lib/sdk/page-mod.js deleted file mode 100644 index 538be2732..000000000 --- a/addon-sdk/source/lib/sdk/page-mod.js +++ /dev/null @@ -1,190 +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": "stable" -}; - -const { contract: loaderContract } = require('./content/loader'); -const { contract } = require('./util/contract'); -const { WorkerHost, connect } = require('./content/utils'); -const { Class } = require('./core/heritage'); -const { Disposable } = require('./core/disposable'); -const { Worker } = require('./content/worker'); -const { EventTarget } = require('./event/target'); -const { on, emit, once, setListeners } = require('./event/core'); -const { isRegExp, isUndefined } = require('./lang/type'); -const { merge, omit } = require('./util/object'); -const { remove, has, hasAny } = require("./util/array"); -const { Rules } = require("./util/rules"); -const { processes, frames, remoteRequire } = require('./remote/parent'); -remoteRequire('sdk/content/page-mod'); - -const pagemods = new Map(); -const workers = new Map(); -const models = new WeakMap(); -var modelFor = (mod) => models.get(mod); -var workerFor = (mod) => workers.get(mod)[0]; - -// Helper functions -var isRegExpOrString = (v) => isRegExp(v) || typeof v === 'string'; - -var PAGEMOD_ID = 0; - -// Validation Contracts -const modOptions = { - // contentStyle* / contentScript* are sharing the same validation constraints, - // so they can be mostly reused, except for the messages. - contentStyle: merge(Object.create(loaderContract.rules.contentScript), { - msg: 'The `contentStyle` option must be a string or an array of strings.' - }), - contentStyleFile: merge(Object.create(loaderContract.rules.contentScriptFile), { - msg: 'The `contentStyleFile` option must be a local URL or an array of URLs' - }), - include: { - is: ['string', 'array', 'regexp'], - ok: (rule) => { - if (isRegExpOrString(rule)) - return true; - if (Array.isArray(rule) && rule.length > 0) - return rule.every(isRegExpOrString); - return false; - }, - msg: 'The `include` option must always contain atleast one rule as a string, regular expression, or an array of strings and regular expressions.' - }, - exclude: { - is: ['string', 'array', 'regexp', 'undefined'], - ok: (rule) => { - if (isRegExpOrString(rule) || isUndefined(rule)) - return true; - if (Array.isArray(rule) && rule.length > 0) - return rule.every(isRegExpOrString); - return false; - }, - msg: 'If set, the `exclude` option must always contain at least one ' + - 'rule as a string, regular expression, or an array of strings and ' + - 'regular expressions.' - }, - attachTo: { - is: ['string', 'array', 'undefined'], - map: function (attachTo) { - if (!attachTo) return ['top', 'frame']; - if (typeof attachTo === 'string') return [attachTo]; - return attachTo; - }, - ok: function (attachTo) { - return hasAny(attachTo, ['top', 'frame']) && - attachTo.every(has.bind(null, ['top', 'frame', 'existing'])); - }, - msg: 'The `attachTo` option must be a string or an array of strings. ' + - 'The only valid options are "existing", "top" and "frame", and must ' + - 'contain at least "top" or "frame" values.' - }, -}; - -const modContract = contract(merge({}, loaderContract.rules, modOptions)); - -/** - * PageMod constructor (exported below). - * @constructor - */ -const PageMod = Class({ - implements: [ - modContract.properties(modelFor), - EventTarget, - Disposable, - ], - extends: WorkerHost(workerFor), - setup: function PageMod(options) { - let mod = this; - let model = modContract(options); - models.set(this, model); - model.id = PAGEMOD_ID++; - - let include = model.include; - model.include = Rules(); - model.include.add.apply(model.include, [].concat(include)); - - let exclude = isUndefined(model.exclude) ? [] : model.exclude; - model.exclude = Rules(); - model.exclude.add.apply(model.exclude, [].concat(exclude)); - - // Set listeners on {PageMod} itself, not the underlying worker, - // like `onMessage`, as it'll get piped. - setListeners(this, options); - - pagemods.set(model.id, this); - workers.set(this, []); - - function serializeRules(rules) { - for (let rule of rules) { - yield isRegExp(rule) ? { type: "regexp", pattern: rule.source, flags: rule.flags } - : { type: "string", value: rule }; - } - } - - model.childOptions = omit(model, ["include", "exclude", "contentScriptOptions"]); - model.childOptions.include = [...serializeRules(model.include)]; - model.childOptions.exclude = [...serializeRules(model.exclude)]; - model.childOptions.contentScriptOptions = model.contentScriptOptions ? - JSON.stringify(model.contentScriptOptions) : - null; - - processes.port.emit('sdk/page-mod/create', model.childOptions); - }, - - dispose: function(reason) { - processes.port.emit('sdk/page-mod/destroy', modelFor(this).id); - pagemods.delete(modelFor(this).id); - workers.delete(this); - }, - - destroy: function(reason) { - // Explicit destroy call, i.e. not via unload so destroy the workers - let list = workers.get(this); - if (!list) - return; - - // Triggers dispose which will cause the child page-mod to be destroyed - Disposable.prototype.destroy.call(this, reason); - - // Destroy any active workers - for (let worker of list) - worker.destroy(reason); - } -}); -exports.PageMod = PageMod; - -// Whenever a new process starts send over the list of page-mods -processes.forEvery(process => { - for (let mod of pagemods.values()) - process.port.emit('sdk/page-mod/create', modelFor(mod).childOptions); -}); - -frames.port.on('sdk/page-mod/worker-create', (frame, modId, workerOptions) => { - let mod = pagemods.get(modId); - if (!mod) - return; - - // Attach the parent side of the worker to the child - let worker = Worker(); - - workers.get(mod).unshift(worker); - worker.on('*', (event, ...args) => { - // page-mod's "attach" event needs to be passed a worker - if (event === 'attach') - emit(mod, event, worker) - else - emit(mod, event, ...args); - }); - - worker.on('detach', () => { - let array = workers.get(mod); - if (array) - remove(array, worker); - }); - - connect(worker, frame, workerOptions); -}); |