summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/framescript/content.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/framescript/content.jsm')
-rw-r--r--addon-sdk/source/lib/framescript/content.jsm94
1 files changed, 94 insertions, 0 deletions
diff --git a/addon-sdk/source/lib/framescript/content.jsm b/addon-sdk/source/lib/framescript/content.jsm
new file mode 100644
index 000000000..eaee26be3
--- /dev/null
+++ b/addon-sdk/source/lib/framescript/content.jsm
@@ -0,0 +1,94 @@
+/* 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);
+ }
+}