diff options
Diffstat (limited to 'tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js')
-rw-r--r-- | tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js new file mode 100644 index 0000000..6a25109 --- /dev/null +++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js @@ -0,0 +1,134 @@ +/* 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": "deprecated" +}; + +const { Cc, Ci } = require("chrome"); +const { when: unload } = require("../system/unload"); +const { ns } = require("../core/namespace"); +const { on, off, emit, once } = require("../system/events"); +const { id } = require("../self"); + +const subscribers = ns(); +const cache = []; + +/** + * Topics specifically available to Jetpack-generated extensions. + * + * Using these predefined consts instead of the platform strings is good: + * - allows us to scope topics specifically for Jetpacks + * - addons aren't dependent on strings nor behavior of core platform topics + * - the core platform topics are not clearly named + * + */ +exports.topics = { + /** + * A topic indicating that the application is in a state usable + * by add-ons. + */ + APPLICATION_READY: id + "_APPLICATION_READY" +}; + +function Listener(callback, target) { + return function listener({ subject, data }) { + callback.call(target || callback, subject, data); + } +} + +/** + * Register the given callback as an observer of the given topic. + * + * @param topic {String} + * the topic to observe + * + * @param callback {Object} + * the callback; an Object that implements nsIObserver or a Function + * that gets called when the notification occurs + * + * @param target {Object} [optional] + * the object to use as |this| when calling a Function callback + * + * @returns the observer + */ +function add(topic, callback, target) { + let listeners = subscribers(callback); + if (!(topic in listeners)) { + let listener = Listener(callback, target); + listeners[topic] = listener; + + // Cache callback unless it's already cached. + if (!~cache.indexOf(callback)) + cache.push(callback); + + on(topic, listener); + } +}; +exports.add = add; + +/** + * Unregister the given callback as an observer of the given topic. + * + * @param topic {String} + * the topic being observed + * + * @param callback {Object} + * the callback doing the observing + * + * @param target {Object} [optional] + * the object being used as |this| when calling a Function callback + */ +function remove(topic, callback, target) { + let listeners = subscribers(callback); + if (topic in listeners) { + let listener = listeners[topic]; + delete listeners[topic]; + + // If no more observers are registered and callback is still in cache + // then remove it. + let index = cache.indexOf(callback); + if (~index && !Object.keys(listeners).length) + cache.splice(index, 1) + + off(topic, listener); + } +}; +exports.remove = remove; + +/** + * Notify observers about something. + * + * @param topic {String} + * the topic to notify observers about + * + * @param subject {Object} [optional] + * some information about the topic; can be any JS object or primitive + * + * @param data {String} [optional] [deprecated] + * some more information about the topic; deprecated as the subject + * is sufficient to pass all needed information to the JS observers + * that this module targets; if you have multiple values to pass to + * the observer, wrap them in an object and pass them via the subject + * parameter (i.e.: { foo: 1, bar: "some string", baz: myObject }) + */ +function notify(topic, subject, data) { + emit(topic, { + subject: subject === undefined ? null : subject, + data: data === undefined ? null : data + }); +} +exports.notify = notify; + +unload(function() { + // Make a copy of cache first, since cache will be changing as we + // iterate through it. + cache.slice().forEach(function(callback) { + Object.keys(subscribers(callback)).forEach(function(topic) { + remove(topic, callback); + }); + }); +}) |