diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/shared/commands/index.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/devtools/shared/commands/index.js b/devtools/shared/commands/index.js new file mode 100644 index 0000000000..94cf7717cb --- /dev/null +++ b/devtools/shared/commands/index.js @@ -0,0 +1,133 @@ +/* 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/. */ + +"use strict"; + +// List of all command modules +// (please try to keep the list alphabetically sorted) +/* eslint sort-keys: "error" */ +/* eslint-enable sort-keys */ +const Commands = { + inspectedWindowCommand: + "devtools/shared/commands/inspected-window/inspected-window-command", + inspectorCommand: "devtools/shared/commands/inspector/inspector-command", + networkCommand: "devtools/shared/commands/network/network-command", + resourceCommand: "devtools/shared/commands/resource/resource-command", + rootResourceCommand: + "devtools/shared/commands/root-resource/root-resource-command", + scriptCommand: "devtools/shared/commands/script/script-command", + targetCommand: "devtools/shared/commands/target/target-command", + targetConfigurationCommand: + "devtools/shared/commands/target-configuration/target-configuration-command", + threadConfigurationCommand: + "devtools/shared/commands/thread-configuration/thread-configuration-command", +}; +/* eslint-disable sort-keys */ + +/** + * For a given descriptor and its related Targets, already initialized, + * return the dictionary with all command instances. + * This dictionary is lazy and commands will be loaded and instanciated on-demand. + */ +async function createCommandsDictionary(descriptorFront) { + // Bug 1675763: Watcher actor is not available in all situations yet. + let watcherFront; + const supportsWatcher = descriptorFront.traits?.watcher; + if (supportsWatcher) { + watcherFront = await descriptorFront.getWatcher(); + } + const { client } = descriptorFront; + + const allInstantiatedCommands = new Set(); + + const dictionary = { + // Expose both client and descriptor for legacy codebases, or tests. + // But ideally only commands should interact with these two objects + client, + descriptorFront, + watcherFront, + + // Expose for tests + waitForRequestsToSettle() { + return descriptorFront.client.waitForRequestsToSettle(); + }, + + // Boolean flag to know if the DevtoolsClient should be closed + // when this commands happens to be destroyed. + // This is set by: + // * commands-from-url in case we are opening a toolbox + // with a dedicated DevToolsClient (mostly from about:debugging, when the client isn't "cached"). + // * CommandsFactory, when we are connecting to a local tab and expect + // the client, toolbox and descriptor to all follow the same lifecycle. + shouldCloseClient: true, + + /** + * Destroy the commands which will destroy: + * - all inner commands, + * - the related descriptor, + * - the related DevToolsClient (not always) + */ + async destroy() { + descriptorFront.off("descriptor-destroyed", this.destroy); + + // Destroy all inner command modules + for (const command of allInstantiatedCommands) { + if (typeof command.destroy == "function") { + command.destroy(); + } + } + allInstantiatedCommands.clear(); + + // Destroy the descriptor front, and all its children fronts. + // Watcher, targets,... + // + // Note that DescriptorFront.destroy will be null because of Pool.destroy + // when this function is called while the descriptor front itself is being + // destroyed. + if (!descriptorFront.isDestroyed()) { + await descriptorFront.destroy(); + } + + // Close the DevToolsClient. Shutting down the connection + // to the debuggable context and its DevToolsServer. + // + // See shouldCloseClient jsdoc about this condition. + if (this.shouldCloseClient) { + await client.close(); + } + }, + }; + dictionary.destroy = dictionary.destroy.bind(dictionary); + + // Automatically destroy the commands object if the descriptor + // happens to be destroyed. Which means that the debuggable context + // is no longer debuggable. + descriptorFront.on("descriptor-destroyed", dictionary.destroy); + + for (const name in Commands) { + loader.lazyGetter(dictionary, name, () => { + const Constructor = require(Commands[name]); + const command = new Constructor({ + // Commands can use other commands + commands: dictionary, + + // The context to inspect identified by this descriptor + descriptorFront, + + // The front for the Watcher Actor, related to the given descriptor + // This is a key actor to watch for targets and resources and pull global actors running in the parent process + watcherFront, + + // From here, we could pass DevToolsClient, or any useful protocol classes... + // so that we abstract where and how to fetch all necessary interfaces + // and avoid having to know that you might pull the client via descriptorFront.client + }); + allInstantiatedCommands.add(command); + return command; + }); + } + + return dictionary; +} +exports.createCommandsDictionary = createCommandsDictionary; |