1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
// Set this to the ID of your add-on, or call notifyTools.setAddonID().
const ADDON_ID = "{8845E3B3-E8FB-40E2-95E9-EC40294818C4}";
/*
* This file is provided by the addon-developer-support repository at
* https://github.com/thundernest/addon-developer-support
*
* For usage descriptions, please check:
* https://github.com/thundernest/addon-developer-support/tree/master/scripts/notifyTools
*
* Version 1.6
* - adjusted to Thunderbird Supernova (Services is now in globalThis)
*
* Version 1.5
* - deprecate enable(), disable() and registerListener()
* - add setAddOnId()
*
* Version 1.4
* - auto enable/disable
*
* Version 1.3
* - registered listeners for notifyExperiment can return a value
* - remove WindowListener from name of observer
*
* Author: John Bieling (john@thunderbird.net)
*
* 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/.
*/
var notifyTools = {
registeredCallbacks: {},
registeredCallbacksNextId: 1,
addOnId: ADDON_ID,
setAddOnId: function (addOnId) {
this.addOnId = addOnId;
},
onNotifyExperimentObserver: {
observe: async function (aSubject, aTopic, aData) {
if (notifyTools.addOnId == "") {
throw new Error("notifyTools: ADDON_ID is empty!");
}
if (aData != notifyTools.addOnId) {
return;
}
let payload = aSubject.wrappedJSObject;
// Make sure payload has a resolve function, which we use to resolve the
// observer notification.
if (payload.resolve) {
let observerTrackerPromises = [];
// Push listener into promise array, so they can run in parallel
for (let registeredCallback of Object.values(
notifyTools.registeredCallbacks
)) {
observerTrackerPromises.push(registeredCallback(payload.data));
}
// We still have to await all of them but wait time is just the time needed
// for the slowest one.
let results = [];
for (let observerTrackerPromise of observerTrackerPromises) {
let rv = await observerTrackerPromise;
if (rv != null) results.push(rv);
}
if (results.length == 0) {
payload.resolve();
} else {
if (results.length > 1) {
console.warn(
"Received multiple results from onNotifyExperiment listeners. Using the first one, which can lead to inconsistent behavior.",
results
);
}
payload.resolve(results[0]);
}
} else {
// Older version of NotifyTools, which is not sending a resolve function, deprecated.
console.log("Please update the notifyTools API to at least v1.5");
for (let registeredCallback of Object.values(
notifyTools.registeredCallbacks
)) {
registeredCallback(payload.data);
}
}
},
},
addListener: function (listener) {
if (Object.values(this.registeredCallbacks).length == 0) {
Services.obs.addObserver(
this.onNotifyExperimentObserver,
"NotifyExperimentObserver",
false
);
}
let id = this.registeredCallbacksNextId++;
this.registeredCallbacks[id] = listener;
return id;
},
removeListener: function (id) {
delete this.registeredCallbacks[id];
if (Object.values(this.registeredCallbacks).length == 0) {
Services.obs.removeObserver(
this.onNotifyExperimentObserver,
"NotifyExperimentObserver"
);
}
},
removeAllListeners: function () {
if (Object.values(this.registeredCallbacks).length != 0) {
Services.obs.removeObserver(
this.onNotifyExperimentObserver,
"NotifyExperimentObserver"
);
}
this.registeredCallbacks = {};
},
notifyBackground: function (data) {
if (this.addOnId == "") {
throw new Error("notifyTools: ADDON_ID is empty!");
}
return new Promise((resolve) => {
Services.obs.notifyObservers(
{ data, resolve },
"NotifyBackgroundObserver",
this.addOnId
);
});
},
// Deprecated.
enable: function () {
console.log("Manually calling notifyTools.enable() is no longer needed.");
},
disable: function () {
console.log("notifyTools.disable() has been deprecated, use notifyTools.removeAllListeners() instead.");
this.removeAllListeners();
},
registerListener: function (listener) {
console.log("notifyTools.registerListener() has been deprecated, use notifyTools.addListener() instead.");
this.addListener(listener);
},
};
if (typeof window != "undefined" && window) {
window.addEventListener(
"unload",
function (event) {
notifyTools.removeAllListeners();
},
false
);
}
|