diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/deprecated/sync-worker.js')
-rw-r--r-- | addon-sdk/source/lib/sdk/deprecated/sync-worker.js | 288 |
1 files changed, 0 insertions, 288 deletions
diff --git a/addon-sdk/source/lib/sdk/deprecated/sync-worker.js b/addon-sdk/source/lib/sdk/deprecated/sync-worker.js deleted file mode 100644 index 71cadac36..000000000 --- a/addon-sdk/source/lib/sdk/deprecated/sync-worker.js +++ /dev/null @@ -1,288 +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/. */ - -/** - * - * `deprecated/sync-worker` was previously `content/worker`, that was - * incompatible with e10s. we are in the process of switching to the new - * asynchronous `Worker`, which behaves slightly differently in some edge - * cases, so we are keeping this one around for a short period. - * try to switch to the new one as soon as possible.. - * - */ - -"use strict"; - -module.metadata = { - "stability": "unstable" -}; - -const { Class } = require('../core/heritage'); -const { EventTarget } = require('../event/target'); -const { on, off, emit, setListeners } = require('../event/core'); -const { - attach, detach, destroy -} = require('../content/utils'); -const { method } = require('../lang/functional'); -const { Ci, Cu, Cc } = require('chrome'); -const unload = require('../system/unload'); -const events = require('../system/events'); -const { getInnerId } = require("../window/utils"); -const { WorkerSandbox } = require('../content/sandbox'); -const { isPrivate } = require('../private-browsing/utils'); - -// A weak map of workers to hold private attributes that -// should not be exposed -const workers = new WeakMap(); - -var modelFor = (worker) => workers.get(worker); - -const ERR_DESTROYED = - "Couldn't find the worker to receive this message. " + - "The script may not be initialized yet, or may already have been unloaded."; - -const ERR_FROZEN = "The page is currently hidden and can no longer be used " + - "until it is visible again."; - -/** - * Message-passing facility for communication between code running - * in the content and add-on process. - * @see https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker - */ -const Worker = Class({ - implements: [EventTarget], - initialize: function WorkerConstructor (options) { - // Save model in weak map to not expose properties - let model = createModel(); - workers.set(this, model); - - options = options || {}; - - if ('contentScriptFile' in options) - this.contentScriptFile = options.contentScriptFile; - if ('contentScriptOptions' in options) - this.contentScriptOptions = options.contentScriptOptions; - if ('contentScript' in options) - this.contentScript = options.contentScript; - if ('injectInDocument' in options) - this.injectInDocument = !!options.injectInDocument; - - setListeners(this, options); - - unload.ensure(this, "destroy"); - - // Ensure that worker.port is initialized for contentWorker to be able - // to send events during worker initialization. - this.port = createPort(this); - - model.documentUnload = documentUnload.bind(this); - model.pageShow = pageShow.bind(this); - model.pageHide = pageHide.bind(this); - - if ('window' in options) - attach(this, options.window); - }, - - /** - * Sends a message to the worker's global scope. Method takes single - * argument, which represents data to be sent to the worker. The data may - * be any primitive type value or `JSON`. Call of this method asynchronously - * emits `message` event with data value in the global scope of this - * worker. - * - * `message` event listeners can be set either by calling - * `self.on` with a first argument string `"message"` or by - * implementing `onMessage` function in the global scope of this worker. - * @param {Number|String|JSON} data - */ - postMessage: function (...data) { - let model = modelFor(this); - let args = ['message'].concat(data); - if (!model.inited) { - model.earlyEvents.push(args); - return; - } - processMessage.apply(null, [this].concat(args)); - }, - - get url () { - let model = modelFor(this); - // model.window will be null after detach - return model.window ? model.window.document.location.href : null; - }, - - get contentURL () { - let model = modelFor(this); - return model.window ? model.window.document.URL : null; - }, - - // Implemented to provide some of the previous features of exposing sandbox - // so that Worker can be extended - getSandbox: function () { - return modelFor(this).contentWorker; - }, - - toString: function () { return '[object Worker]'; }, - attach: method(attach), - detach: method(detach), - destroy: method(destroy) -}); -exports.Worker = Worker; - -attach.define(Worker, function (worker, window) { - let model = modelFor(worker); - model.window = window; - // Track document unload to destroy this worker. - // We can't watch for unload event on page's window object as it - // prevents bfcache from working: - // https://developer.mozilla.org/En/Working_with_BFCache - model.windowID = getInnerId(model.window); - events.on("inner-window-destroyed", model.documentUnload); - - // will set model.contentWorker pointing to the private API: - model.contentWorker = WorkerSandbox(worker, model.window); - - // Listen to pagehide event in order to freeze the content script - // while the document is frozen in bfcache: - model.window.addEventListener("pageshow", model.pageShow, true); - model.window.addEventListener("pagehide", model.pageHide, true); - - // Mainly enable worker.port.emit to send event to the content worker - model.inited = true; - model.frozen = false; - - // Fire off `attach` event - emit(worker, 'attach', window); - - // Process all events and messages that were fired before the - // worker was initialized. - model.earlyEvents.forEach(args => processMessage.apply(null, [worker].concat(args))); -}); - -/** - * Remove all internal references to the attached document - * Tells _port to unload itself and removes all the references from itself. - */ -detach.define(Worker, function (worker, reason) { - let model = modelFor(worker); - - // maybe unloaded before content side is created - if (model.contentWorker) { - model.contentWorker.destroy(reason); - } - - model.contentWorker = null; - if (model.window) { - model.window.removeEventListener("pageshow", model.pageShow, true); - model.window.removeEventListener("pagehide", model.pageHide, true); - } - model.window = null; - // This method may be called multiple times, - // avoid dispatching `detach` event more than once - if (model.windowID) { - model.windowID = null; - events.off("inner-window-destroyed", model.documentUnload); - model.earlyEvents.length = 0; - emit(worker, 'detach'); - } - model.inited = false; -}); - -isPrivate.define(Worker, ({ tab }) => isPrivate(tab)); - -/** - * Tells content worker to unload itself and - * removes all the references from itself. - */ -destroy.define(Worker, function (worker, reason) { - detach(worker, reason); - modelFor(worker).inited = true; - // Specifying no type or listener removes all listeners - // from target - off(worker); - off(worker.port); -}); - -/** - * Events fired by workers - */ -function documentUnload ({ subject, data }) { - let model = modelFor(this); - let innerWinID = subject.QueryInterface(Ci.nsISupportsPRUint64).data; - if (innerWinID != model.windowID) return false; - detach(this); - return true; -} - -function pageShow () { - let model = modelFor(this); - model.contentWorker.emitSync('pageshow'); - emit(this, 'pageshow'); - model.frozen = false; -} - -function pageHide () { - let model = modelFor(this); - model.contentWorker.emitSync('pagehide'); - emit(this, 'pagehide'); - model.frozen = true; -} - -/** - * Fired from postMessage and emitEventToContent, or from the earlyMessage - * queue when fired before the content is loaded. Sends arguments to - * contentWorker if able - */ - -function processMessage (worker, ...args) { - let model = modelFor(worker) || {}; - if (!model.contentWorker) - throw new Error(ERR_DESTROYED); - if (model.frozen) - throw new Error(ERR_FROZEN); - model.contentWorker.emit.apply(null, args); -} - -function createModel () { - return { - // List of messages fired before worker is initialized - earlyEvents: [], - // Is worker connected to the content worker sandbox ? - inited: false, - // Is worker being frozen? i.e related document is frozen in bfcache. - // Content script should not be reachable if frozen. - frozen: true, - /** - * Reference to the content side of the worker. - * @type {WorkerGlobalScope} - */ - contentWorker: null, - /** - * Reference to the window that is accessible from - * the content scripts. - * @type {Object} - */ - window: null - }; -} - -function createPort (worker) { - let port = EventTarget(); - port.emit = emitEventToContent.bind(null, worker); - return port; -} - -/** - * Emit a custom event to the content script, - * i.e. emit this event on `self.port` - */ -function emitEventToContent (worker, ...eventArgs) { - let model = modelFor(worker); - let args = ['event'].concat(eventArgs); - if (!model.inited) { - model.earlyEvents.push(args); - return; - } - processMessage.apply(null, [worker].concat(args)); -} |