diff options
Diffstat (limited to 'toolkit/components/extensions/ExtensionChildDevToolsUtils.sys.mjs')
-rw-r--r-- | toolkit/components/extensions/ExtensionChildDevToolsUtils.sys.mjs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/toolkit/components/extensions/ExtensionChildDevToolsUtils.sys.mjs b/toolkit/components/extensions/ExtensionChildDevToolsUtils.sys.mjs new file mode 100644 index 0000000000..084fe8f940 --- /dev/null +++ b/toolkit/components/extensions/ExtensionChildDevToolsUtils.sys.mjs @@ -0,0 +1,111 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +/* 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/. */ + +/** + * @file + * This module contains utilities for interacting with DevTools + * from the child process. + */ + +import { EventEmitter } from "resource://gre/modules/EventEmitter.sys.mjs"; + +// Create a variable to hold the cached ThemeChangeObserver which does not +// get created until a devtools context has been created. +let themeChangeObserver; + +/** + * An observer that watches for changes to the devtools theme and provides + * that information to the devtools.panels.themeName API property, as well as + * emits events for the devtools.panels.onThemeChanged event. It also caches + * the current value of devtools.themeName. + */ +class ThemeChangeObserver extends EventEmitter { + constructor(themeName, onDestroyed) { + super(); + this.themeName = themeName; + this.onDestroyed = onDestroyed; + this.contexts = new Set(); + + Services.cpmm.addMessageListener("Extension:DevToolsThemeChanged", this); + } + + addContext(context) { + if (this.contexts.has(context)) { + throw new Error( + "addContext on the ThemeChangeObserver was called more than once" + + " for the context." + ); + } + + context.callOnClose({ + close: () => this.onContextClosed(context), + }); + + this.contexts.add(context); + } + + onContextClosed(context) { + this.contexts.delete(context); + + if (this.contexts.size === 0) { + this.destroy(); + } + } + + onThemeChanged(themeName) { + // Update the cached themeName and emit an event for the API. + this.themeName = themeName; + this.emit("themeChanged", themeName); + } + + receiveMessage({ name, data }) { + if (name === "Extension:DevToolsThemeChanged") { + this.onThemeChanged(data.themeName); + } + } + + destroy() { + Services.cpmm.removeMessageListener("Extension:DevToolsThemeChanged", this); + this.onDestroyed(); + this.onDestroyed = null; + this.contexts.clear(); + this.contexts = null; + } +} + +export var ExtensionChildDevToolsUtils = { + /** + * Creates an cached instance of the ThemeChangeObserver class and + * initializes it with the current themeName. This cached instance is + * destroyed when all of the contexts added to it are closed. + * + * @param {string} themeName The name of the current devtools theme. + * @param {import("ExtensionPageChild.sys.mjs").DevToolsContextChild} context + * The newly created devtools page context. + */ + initThemeChangeObserver(themeName, context) { + if (!themeChangeObserver) { + themeChangeObserver = new ThemeChangeObserver(themeName, function () { + themeChangeObserver = null; + }); + } + themeChangeObserver.addContext(context); + }, + + /** + * Returns the cached instance of ThemeChangeObserver. + * + * @returns {ThemeChangeObserver} The cached instance of ThemeChangeObserver. + */ + getThemeChangeObserver() { + if (!themeChangeObserver) { + throw new Error( + "A ThemeChangeObserver must be created before being retrieved." + ); + } + return themeChangeObserver; + }, +}; |