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
|
/*
* This file is provided by the addon-developer-support repository at
* https://github.com/thundernest/addon-developer-support
*
* Version 1.1
* - added startup event, to make sure API is ready as soon as the add-on is starting
* NOTE: This requires to add the startup event to the manifest, see:
* https://github.com/thundernest/addon-developer-support/tree/master/auxiliary-apis/NotifyTools#usage
*
* 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/.
*/
// Get various parts of the WebExtension framework that we need.
var { ExtensionCommon } = ChromeUtils.import ? ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm")
: ChromeUtils.importESModule(
"resource://gre/modules/ExtensionCommon.sys.mjs"
);
var { ExtensionSupport } = ChromeUtils.import ? ChromeUtils.import("resource:///modules/ExtensionSupport.jsm")
: ChromeUtils.importESModule(
"resource:///modules/ExtensionSupport.sys.mjs"
);
//var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
//var Services = globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services;
var NotifyTools = class extends ExtensionCommon.ExtensionAPI {
getAPI(context) {
var self = this;
this.onNotifyBackgroundObserver = {
observe: async function (aSubject, aTopic, aData) {
if (
Object.keys(self.observerTracker).length > 0 &&
aData == self.extension.id
) {
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 listener of Object.values(self.observerTracker)) {
observerTrackerPromises.push(listener(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 onNotifyBackground 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 and the notifyTools script to at least v1.5");
for (let listener of Object.values(self.observerTracker)) {
listener(payload.data);
}
}
}
},
};
this.observerTracker = {};
this.observerTrackerNext = 1;
// Add observer for notifyTools.js
Services.obs.addObserver(
this.onNotifyBackgroundObserver,
"NotifyBackgroundObserver",
false
);
return {
NotifyTools: {
notifyExperiment(data) {
return new Promise(resolve => {
Services.obs.notifyObservers(
{ data, resolve },
"NotifyExperimentObserver",
self.extension.id
);
});
},
onNotifyBackground: new ExtensionCommon.EventManager({
context,
name: "NotifyTools.onNotifyBackground",
register: (fire) => {
let trackerId = self.observerTrackerNext++;
self.observerTracker[trackerId] = fire.sync;
return () => {
delete self.observerTracker[trackerId];
};
},
}).api(),
}
};
}
// Force API to run at startup, otherwise event listeners might not be added at the requested time. Also needs
// "events": ["startup"] in the experiment manifest
onStartup() { }
onShutdown(isAppShutdown) {
if (isAppShutdown) {
return; // the application gets unloaded anyway
}
// Remove observer for notifyTools.js
Services.obs.removeObserver(
this.onNotifyBackgroundObserver,
"NotifyBackgroundObserver"
);
// Flush all caches
Services.obs.notifyObservers(null, "startupcache-invalidate");
}
};
|