summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/event/chrome.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/jetpack/sdk/event/chrome.js')
-rw-r--r--toolkit/jetpack/sdk/event/chrome.js65
1 files changed, 65 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/event/chrome.js b/toolkit/jetpack/sdk/event/chrome.js
new file mode 100644
index 000000000..9044fef99
--- /dev/null
+++ b/toolkit/jetpack/sdk/event/chrome.js
@@ -0,0 +1,65 @@
+/* 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": "unstable"
+};
+
+const { Cc, Ci, Cr, Cu } = require("chrome");
+const { emit, on, off } = require("./core");
+var observerService = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+
+const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
+const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
+const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
+
+const { when: unload } = require("../system/unload");
+
+// Simple class that can be used to instantiate event channel that
+// implements `nsIObserver` interface. It's will is used by `observe`
+// function as observer + event target. It basically proxies observer
+// notifications as to it's registered listeners.
+function ObserverChannel() {}
+Object.freeze(Object.defineProperties(ObserverChannel.prototype, {
+ QueryInterface: {
+ value: function(iid) {
+ if (!iid.equals(Ci.nsIObserver) &&
+ !iid.equals(Ci.nsISupportsWeakReference) &&
+ !iid.equals(Ci.nsISupports))
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+ },
+ observe: {
+ value: function(subject, topic, data) {
+ emit(this, "data", {
+ type: topic,
+ target: subject,
+ data: data
+ });
+ }
+ }
+}));
+
+function observe(topic) {
+ let observerChannel = new ObserverChannel();
+
+ // Note: `nsIObserverService` will not hold a weak reference to a
+ // observerChannel (since third argument is `true`). There for if it
+ // will be GC-ed with all it's event listeners once no other references
+ // will be held.
+ addObserver(observerChannel, topic, true);
+
+ // We need to remove any observer added once the add-on is unloaded;
+ // otherwise we'll get a "dead object" exception.
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1001833
+ unload(() => removeObserver(observerChannel, topic));
+
+ return observerChannel;
+}
+
+exports.observe = observe;