index.js (5486B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 // List of all command modules 8 // (please try to keep the list alphabetically sorted) 9 /* eslint sort-keys: "error" */ 10 /* eslint-enable sort-keys */ 11 const Commands = { 12 inspectedWindowCommand: 13 "devtools/shared/commands/inspected-window/inspected-window-command", 14 inspectorCommand: "devtools/shared/commands/inspector/inspector-command", 15 networkCommand: "devtools/shared/commands/network/network-command", 16 objectCommand: "devtools/shared/commands/object/object-command", 17 resourceCommand: "devtools/shared/commands/resource/resource-command", 18 responsiveCommand: "devtools/shared/commands/responsive/responsive-command", 19 rootResourceCommand: 20 "devtools/shared/commands/root-resource/root-resource-command", 21 scriptCommand: "devtools/shared/commands/script/script-command", 22 targetCommand: "devtools/shared/commands/target/target-command", 23 targetConfigurationCommand: 24 "devtools/shared/commands/target-configuration/target-configuration-command", 25 threadConfigurationCommand: 26 "devtools/shared/commands/thread-configuration/thread-configuration-command", 27 tracerCommand: "devtools/shared/commands/tracer/tracer-command", 28 }; 29 /* eslint-disable sort-keys */ 30 31 /** 32 * For a given descriptor and its related Targets, already initialized, 33 * return the dictionary with all command instances. 34 * This dictionary is lazy and commands will be loaded and instanciated on-demand. 35 * 36 * @param {DescriptorFront} descriptorFront 37 * @param {boolean} enableWindowGlobalThreadActors: Used by one test. 38 */ 39 async function createCommandsDictionary( 40 descriptorFront, 41 enableWindowGlobalThreadActors 42 ) { 43 // Bug 1675763: Watcher actor is not available in all situations yet. 44 let watcherFront; 45 const supportsWatcher = descriptorFront.traits?.watcher; 46 if (supportsWatcher) { 47 watcherFront = await descriptorFront.getWatcher({ 48 enableWindowGlobalThreadActors, 49 }); 50 } 51 const { client } = descriptorFront; 52 53 const allInstantiatedCommands = new Set(); 54 55 const dictionary = { 56 // Expose both client and descriptor for legacy codebases, or tests. 57 // But ideally only commands should interact with these two objects 58 client, 59 descriptorFront, 60 watcherFront, 61 62 // Expose for tests 63 waitForRequestsToSettle(options) { 64 return descriptorFront.client.waitForRequestsToSettle(options); 65 }, 66 67 // Boolean flag to know if the DevtoolsClient should be closed 68 // when this commands happens to be destroyed. 69 // This is set by: 70 // * commands-from-url in case we are opening a toolbox 71 // with a dedicated DevToolsClient (mostly from about:debugging, when the client isn't "cached"). 72 // * CommandsFactory, when we are connecting to a local tab and expect 73 // the client, toolbox and descriptor to all follow the same lifecycle. 74 shouldCloseClient: true, 75 76 /** 77 * Destroy the commands which will destroy: 78 * - all inner commands, 79 * - the related descriptor, 80 * - the related DevToolsClient (not always) 81 */ 82 async destroy() { 83 descriptorFront.off("descriptor-destroyed", this.destroy); 84 85 // Destroy all inner command modules 86 for (const command of allInstantiatedCommands) { 87 if (typeof command.destroy == "function") { 88 command.destroy(); 89 } 90 } 91 allInstantiatedCommands.clear(); 92 93 // Destroy the descriptor front, and all its children fronts. 94 // Watcher, targets,... 95 // 96 // Note that DescriptorFront.destroy will be null because of Pool.destroy 97 // when this function is called while the descriptor front itself is being 98 // destroyed. 99 if (!descriptorFront.isDestroyed()) { 100 await descriptorFront.destroy(); 101 } 102 103 // Close the DevToolsClient. Shutting down the connection 104 // to the debuggable context and its DevToolsServer. 105 // 106 // See shouldCloseClient jsdoc about this condition. 107 if (this.shouldCloseClient) { 108 await client.close(); 109 } 110 }, 111 }; 112 dictionary.destroy = dictionary.destroy.bind(dictionary); 113 114 // Automatically destroy the commands object if the descriptor 115 // happens to be destroyed. Which means that the debuggable context 116 // is no longer debuggable. 117 descriptorFront.on("descriptor-destroyed", dictionary.destroy); 118 119 for (const name in Commands) { 120 loader.lazyGetter(dictionary, name, () => { 121 const Constructor = require(Commands[name]); 122 const command = new Constructor({ 123 // Commands can use other commands 124 commands: dictionary, 125 126 // The context to inspect identified by this descriptor 127 descriptorFront, 128 129 // The front for the Watcher Actor, related to the given descriptor 130 // This is a key actor to watch for targets and resources and pull global actors running in the parent process 131 watcherFront, 132 133 // From here, we could pass DevToolsClient, or any useful protocol classes... 134 // so that we abstract where and how to fetch all necessary interfaces 135 // and avoid having to know that you might pull the client via descriptorFront.client 136 }); 137 allInstantiatedCommands.add(command); 138 return command; 139 }); 140 } 141 142 return dictionary; 143 } 144 exports.createCommandsDictionary = createCommandsDictionary;