/* 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 { utils: Cu, classes: Cc, interfaces: Ci } = Components; const { Services } = Cu.import('resource://gre/modules/Services.jsm'); const cpmm = Cc['@mozilla.org/childprocessmessagemanager;1']. getService(Ci.nsISyncMessageSender); this.EXPORTED_SYMBOLS = ["registerContentFrame"]; // This may be an overriden version of the SDK so use the PATH as a key for the // initial messages before we have a loaderID. const PATH = __URI__.replace('framescript/content.jsm', ''); const { Loader } = Cu.import(PATH + 'toolkit/loader.js', {}); // one Loader instance per addon (per @loader/options to be precise) var addons = new Map(); // Tell the parent that a new process is ready cpmm.sendAsyncMessage('sdk/remote/process/start', { modulePath: PATH }); // Load a child process module loader with the given loader options cpmm.addMessageListener('sdk/remote/process/load', ({ data: { modulePath, loaderID, options, reason } }) => { if (modulePath != PATH) return; // During startup races can mean we get a second load message if (addons.has(loaderID)) return; options.waiveInterposition = true; let loader = Loader.Loader(options); let addon = { loader, require: Loader.Require(loader, { id: 'LoaderHelper' }), } addons.set(loaderID, addon); cpmm.sendAsyncMessage('sdk/remote/process/attach', { loaderID, processID: Services.appinfo.processID, isRemote: Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT }); addon.child = addon.require('sdk/remote/child'); for (let contentFrame of frames.values()) addon.child.registerContentFrame(contentFrame); }); // Unload a child process loader cpmm.addMessageListener('sdk/remote/process/unload', ({ data: { loaderID, reason } }) => { if (!addons.has(loaderID)) return; let addon = addons.get(loaderID); Loader.unload(addon.loader, reason); // We want to drop the reference to the loader but never allow creating a new // loader with the same ID addons.set(loaderID, {}); }) var frames = new Set(); this.registerContentFrame = contentFrame => { contentFrame.addEventListener("unload", () => { unregisterContentFrame(contentFrame); }, false); frames.add(contentFrame); for (let addon of addons.values()) { if ("child" in addon) addon.child.registerContentFrame(contentFrame); } }; function unregisterContentFrame(contentFrame) { frames.delete(contentFrame); for (let addon of addons.values()) { if ("child" in addon) addon.child.unregisterContentFrame(contentFrame); } }