summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/ExtensionActivityLog.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/components/extensions/ExtensionActivityLog.sys.mjs120
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)
+ );
+ }
+ },
+};