From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- addon-sdk/source/lib/sdk/remote/parent.js | 338 ++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 addon-sdk/source/lib/sdk/remote/parent.js (limited to 'addon-sdk/source/lib/sdk/remote/parent.js') diff --git a/addon-sdk/source/lib/sdk/remote/parent.js b/addon-sdk/source/lib/sdk/remote/parent.js new file mode 100644 index 000000000..f110fe3f6 --- /dev/null +++ b/addon-sdk/source/lib/sdk/remote/parent.js @@ -0,0 +1,338 @@ +/* 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 { isChildLoader } = require('./core'); +if (isChildLoader) + throw new Error("Cannot load sdk/remote/parent in a child loader."); + +const { Cu, Ci, Cc } = require('chrome'); +const runtime = require('../system/runtime'); + +const MAIN_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + +if (runtime.processType != MAIN_PROCESS) { + throw new Error('Cannot use sdk/remote/parent in a child process.'); +} + +const { Class } = require('../core/heritage'); +const { Namespace } = require('../core/namespace'); +const { Disposable } = require('../core/disposable'); +const { omit } = require('../util/object'); +const { when } = require('../system/unload'); +const { EventTarget } = require('../event/target'); +const { emit } = require('../event/core'); +const system = require('../system/events'); +const { EventParent } = require('./utils'); +const options = require('@loader/options'); +const loaderModule = require('toolkit/loader'); +const { getTabForBrowser } = require('../tabs/utils'); + +const appInfo = Cc["@mozilla.org/xre/app-info;1"]. + getService(Ci.nsIXULRuntime); + +exports.useRemoteProcesses = appInfo.browserTabsRemoteAutostart; + +// Chose the right function for resolving relative a module id +var moduleResolve; +if (options.isNative) { + moduleResolve = (id, requirer) => loaderModule.nodeResolve(id, requirer, { rootURI: options.rootURI }); +} +else { + moduleResolve = loaderModule.resolve; +} +// Build the sorted path mapping structure that resolveURI requires +var pathMapping = Object.keys(options.paths) + .sort((a, b) => b.length - a.length) + .map(p => [p, options.paths[p]]); + +// Load the scripts in the child processes +var { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm'); +var PATH = options.paths['']; + +const childOptions = omit(options, ['modules', 'globals', 'resolve', 'load']); +childOptions.modules = {}; +// @l10n/data is just JSON data and can be safely sent across to the child loader +try { + childOptions.modules["@l10n/data"] = require("@l10n/data"); +} +catch (e) { + // There may be no l10n data +} +const loaderID = getNewLoaderID(); +childOptions.loaderID = loaderID; +childOptions.childLoader = true; + +const ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1']. + getService(Ci.nsIMessageBroadcaster); +const gmm = Cc['@mozilla.org/globalmessagemanager;1']. + getService(Ci.nsIMessageBroadcaster); + +const ns = Namespace(); + +var processMap = new Map(); + +function definePort(obj, name) { + obj.port.emitCPOW = (event, args, cpows = {}) => { + let manager = ns(obj).messageManager; + if (!manager) + return; + + let method = manager instanceof Ci.nsIMessageBroadcaster ? + "broadcastAsyncMessage" : "sendAsyncMessage"; + + manager[method](name, { loaderID, event, args }, cpows); + }; + + obj.port.emit = (event, ...args) => obj.port.emitCPOW(event, args); +} + +function messageReceived({ target, data }) { + // Ignore messages from other loaders + if (data.loaderID != loaderID) + return; + + emit(this.port, data.event, this, ...data.args); +} + +// Process represents a gecko process that can load webpages. Each process +// contains a number of Frames. This class is used to send and receive messages +// from a single process. +const Process = Class({ + implements: [ Disposable ], + extends: EventTarget, + setup: function(id, messageManager, isRemote) { + ns(this).id = id; + ns(this).isRemote = isRemote; + ns(this).messageManager = messageManager; + ns(this).messageReceived = messageReceived.bind(this); + this.destroy = this.destroy.bind(this); + ns(this).messageManager.addMessageListener('sdk/remote/process/message', ns(this).messageReceived); + ns(this).messageManager.addMessageListener('child-process-shutdown', this.destroy); + + this.port = new EventTarget(); + definePort(this, 'sdk/remote/process/message'); + + // Load any remote modules + for (let module of remoteModules.values()) + this.port.emit('sdk/remote/require', module); + + processMap.set(ns(this).id, this); + processes.attachItem(this); + }, + + dispose: function() { + emit(this, 'detach', this); + processMap.delete(ns(this).id); + ns(this).messageManager.removeMessageListener('sdk/remote/process/message', ns(this).messageReceived); + ns(this).messageManager.removeMessageListener('child-process-shutdown', this.destroy); + ns(this).messageManager = null; + }, + + // Returns true if this process is a child process + get isRemote() { + return ns(this).isRemote; + } +}); + +// Processes gives an API for enumerating an sending and receiving messages from +// all processes as well as detecting when a new process starts. +const Processes = Class({ + implements: [ EventParent ], + extends: EventTarget, + initialize: function() { + EventParent.prototype.initialize.call(this); + ns(this).messageManager = ppmm; + + this.port = new EventTarget(); + definePort(this, 'sdk/remote/process/message'); + }, + + getById: function(id) { + return processMap.get(id); + } +}); +var processes = exports.processes = new Processes(); + +var frameMap = new Map(); + +function setFrameProcess(frame, process) { + ns(frame).process = process; + frames.attachItem(frame); +} + +// Frames display webpages in a process. In the main process every Frame is +// linked with a or