diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/components/extensions/ExtensionActivityLog.sys.mjs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/toolkit/components/extensions/ExtensionActivityLog.sys.mjs b/toolkit/components/extensions/ExtensionActivityLog.sys.mjs new file mode 100644 index 0000000000..6e7bbec5a4 --- /dev/null +++ b/toolkit/components/extensions/ExtensionActivityLog.sys.mjs @@ -0,0 +1,120 @@ +/* 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/. */ + +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + +import { ExtensionUtils } from "resource://gre/modules/ExtensionUtils.sys.mjs"; + +const lazy = {}; +ChromeUtils.defineESModuleGetters(lazy, { + ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs", +}); +XPCOMUtils.defineLazyGetter(lazy, "tabTracker", () => { + return lazy.ExtensionParent.apiManager.global.tabTracker; +}); + +var { DefaultMap } = ExtensionUtils; + +const MSG_SET_ENABLED = "Extension:ActivityLog:SetEnabled"; +const MSG_LOG = "Extension:ActivityLog:DoLog"; + +export const ExtensionActivityLog = { + initialized: false, + + // id => Set(callbacks) + listeners: new DefaultMap(() => new Set()), + watchedIds: new Set(), + + init() { + if (this.initialized) { + return; + } + + this.initialized = true; + + Services.ppmm.sharedData.set("extensions/logging", this.watchedIds); + + Services.ppmm.addMessageListener(MSG_LOG, this); + }, + + /** + * Notify all listeners of an extension activity. + * + * @param {string} id The ID of the extension that caused the activity. + * @param {string} viewType The view type the activity is in. + * @param {string} type The type of the activity. + * @param {string} name The API name or path. + * @param {object} data Activity specific data. + * @param {string} timeStamp The timestamp for the activity. + */ + log(id, viewType, type, name, data, timeStamp) { + if (!this.initialized) { + return; + } + let callbacks = this.listeners.get(id); + if (callbacks) { + if (!timeStamp) { + timeStamp = new Date(); + } + + for (let callback of callbacks) { + try { + callback({ id, viewType, timeStamp, type, name, data }); + } catch (e) { + Cu.reportError(e); + } + } + } + }, + + addListener(id, callback) { + this.init(); + let callbacks = this.listeners.get(id); + if (callbacks.size === 0) { + this.watchedIds.add(id); + Services.ppmm.sharedData.set("extensions/logging", this.watchedIds); + Services.ppmm.sharedData.flush(); + Services.ppmm.broadcastAsyncMessage(MSG_SET_ENABLED, { id, value: true }); + } + callbacks.add(callback); + }, + + removeListener(id, callback) { + let callbacks = this.listeners.get(id); + if (callbacks.size > 0) { + callbacks.delete(callback); + if (callbacks.size === 0) { + this.watchedIds.delete(id); + Services.ppmm.sharedData.set("extensions/logging", this.watchedIds); + Services.ppmm.sharedData.flush(); + Services.ppmm.broadcastAsyncMessage(MSG_SET_ENABLED, { + id, + value: false, + }); + } + } + }, + + receiveMessage({ name, data }) { + if (name === MSG_LOG) { + let { viewType, browsingContextId } = data; + if (browsingContextId && (!viewType || viewType == "tab")) { + let browser = + BrowsingContext.get(browsingContextId).top.embedderElement; + let browserData = lazy.tabTracker.getBrowserData(browser); + if (browserData && browserData.tabId !== undefined) { + data.data.tabId = browserData.tabId; + } + } + this.log( + data.id, + data.viewType, + data.type, + data.name, + data.data, + new Date(data.timeStamp) + ); + } + }, +}; |