1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * This module enables consumers to register callbacks on every
7 * current and future browser window.
9 * Usage: EveryWindow.registerCallback(id, init, uninit);
10 * EveryWindow.unregisterCallback(id);
12 * id is expected to be a unique value that identifies the
13 * consumer, to be used for unregistration. If the id is already
14 * in use, registerCallback returns false without doing anything.
16 * Each callback will receive the window for which it is presently
17 * being called as the first argument.
19 * init is called on every existing window at the time of registration,
20 * and on all future windows at browser-delayed-startup-finished.
22 * uninit is called on every existing window if requested at the time
23 * of unregistration, and at the time of domwindowclosed.
24 * If the window is closing, a second argument is passed with value `true`.
27 var initialized = false;
28 var callbacks = new Map();
30 function callForEveryWindow(callback) {
31 let windowList = Services.wm.getEnumerator("navigator:browser");
32 for (let win of windowList) {
33 win.delayedStartupPromise.then(() => {
39 export const EveryWindow = {
41 * Registers init and uninit functions to be called on every window.
43 * @param {string} id A unique identifier for the consumer, to be
44 * used for unregistration.
45 * @param {function} init The function to be called on every currently
46 * existing window and every future window after delayed startup.
47 * @param {function} uninit The function to be called on every window
48 * at the time of callback unregistration or after domwindowclosed.
49 * @returns {boolean} Returns false if the id was taken, else true.
51 registerCallback: function EW_registerCallback(id, init, uninit) {
52 if (callbacks.has(id)) {
57 let addUnloadListener = win => {
58 function observer(subject, topic, data) {
59 if (topic == "domwindowclosed" && subject === win) {
60 Services.ww.unregisterNotification(observer);
61 for (let c of callbacks.values()) {
66 Services.ww.registerNotification(observer);
69 Services.obs.addObserver(win => {
70 for (let c of callbacks.values()) {
73 addUnloadListener(win);
74 }, "browser-delayed-startup-finished");
76 callForEveryWindow(addUnloadListener);
81 callForEveryWindow(init);
82 callbacks.set(id, { id, init, uninit });
88 * Unregisters a previously registered consumer.
90 * @param {string} id The id to unregister.
91 * @param {boolean} [callUninit=true] Whether to call the registered uninit
92 * function on every window.
94 unregisterCallback: function EW_unregisterCallback(id, callUninit = true) {
95 if (!callbacks.has(id)) {
100 callForEveryWindow(callbacks.get(id).uninit);
103 callbacks.delete(id);