From ac46df8daea09899ce30dc8fd70986e258c746bf Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 9 Feb 2018 06:46:43 -0500 Subject: Move Add-on SDK source to toolkit/jetpack --- toolkit/jetpack/sdk/core/observer.js | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 toolkit/jetpack/sdk/core/observer.js (limited to 'toolkit/jetpack/sdk/core/observer.js') diff --git a/toolkit/jetpack/sdk/core/observer.js b/toolkit/jetpack/sdk/core/observer.js new file mode 100644 index 000000000..7e11bf8f9 --- /dev/null +++ b/toolkit/jetpack/sdk/core/observer.js @@ -0,0 +1,89 @@ +/* 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": "experimental" +}; + + +const { Cc, Ci, Cr, Cu } = require("chrome"); +const { Class } = require("./heritage"); +const { isWeak } = require("./reference"); +const method = require("../../method/core"); + +const 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"); + +// This is a method that will be invoked when notification observer +// subscribed to occurs. +const observe = method("observer/observe"); +exports.observe = observe; + +// Method to subscribe to the observer notification. +const subscribe = method("observe/subscribe"); +exports.subscribe = subscribe; + + +// Method to unsubscribe from the observer notifications. +const unsubscribe = method("observer/unsubscribe"); +exports.unsubscribe = unsubscribe; + + +// This is wrapper class that takes a `delegate` and produces +// instance of `nsIObserver` which will delegate to a given +// object when observer notification occurs. +const ObserverDelegee = Class({ + initialize: function(delegate) { + this.delegate = delegate; + }, + QueryInterface: function(iid) { + if (!iid.equals(Ci.nsIObserver) && + !iid.equals(Ci.nsISupportsWeakReference) && + !iid.equals(Ci.nsISupports)) + throw Cr.NS_ERROR_NO_INTERFACE; + + return this; + }, + observe: function(subject, topic, data) { + observe(this.delegate, subject, topic, data); + } +}); + + +// Class that can be either mixed in or inherited from in +// order to subscribe / unsubscribe for observer notifications. +const Observer = Class({}); +exports.Observer = Observer; + +// Weak maps that associates instance of `ObserverDelegee` with +// an actual observer. It ensures that `ObserverDelegee` instance +// won't be GC-ed until given `observer` is. +const subscribers = new WeakMap(); + +// Implementation of `subscribe` for `Observer` type just registers +// observer for an observer service. If `isWeak(observer)` is `true` +// observer service won't hold strong reference to a given `observer`. +subscribe.define(Observer, (observer, topic) => { + if (!subscribers.has(observer)) { + const delegee = new ObserverDelegee(observer); + subscribers.set(observer, delegee); + addObserver(delegee, topic, isWeak(observer)); + } +}); + +// Unsubscribes `observer` from observer notifications for the +// given `topic`. +unsubscribe.define(Observer, (observer, topic) => { + const delegee = subscribers.get(observer); + if (delegee) { + subscribers.delete(observer); + removeObserver(delegee, topic); + } +}); -- cgit v1.2.3