diff --git a/devtools/client/framework/test/browser_tab_descriptor_fission.js b/devtools/client/framework/test/browser_tab_descriptor_fission.js index b9b93b329708..c88c58e49f5e 100644 --- a/devtools/client/framework/test/browser_tab_descriptor_fission.js +++ b/devtools/client/framework/test/browser_tab_descriptor_fission.js @@ -26,15 +26,6 @@ add_task(async function() { ); ok(tabDescriptor, "Should have a descriptor actor for the tab"); - const firstCommands = await tabDescriptor.getCommands(); - ok(firstCommands, "Got commands"); - const secondCommands = await tabDescriptor.getCommands(); - is( - firstCommands, - secondCommands, - "Multiple calls to getCommands return the same commands object" - ); - is( target.descriptorFront, tabDescriptor, diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js index 4799ac17e36b..69ad42530209 100644 --- a/devtools/client/framework/toolbox.js +++ b/devtools/client/framework/toolbox.js @@ -39,6 +39,7 @@ var Startup = Cc["@mozilla.org/devtools/startup-clh;1"].getService( const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); +const { createCommandsDictionary } = require("devtools/shared/commands/index"); const { BrowserLoader } = ChromeUtils.import( "resource://devtools/client/shared/browser-loader.js" @@ -778,7 +779,8 @@ Toolbox.prototype = { // It exposes commands modules listed in devtools/shared/commands/index.js // which are an abstraction on top of RDP methods. // See devtools/shared/commands/README.md - this.commands = await this.descriptorFront.getCommands(); + // Bug 1700909 will make the commands be instantiated by gDevTools instead of the Toolbox. + this.commands = await createCommandsDictionary(this.descriptorFront); //TODO: complete the renaming of targetList everywhere // But for now, still expose this name on Toolbox diff --git a/devtools/client/fronts/descriptors/descriptor-mixin.js b/devtools/client/fronts/descriptors/descriptor-mixin.js index 8128192600ee..26af5d8a42d3 100644 --- a/devtools/client/fronts/descriptors/descriptor-mixin.js +++ b/devtools/client/fronts/descriptors/descriptor-mixin.js @@ -4,8 +4,6 @@ "use strict"; -const { createCommandsDictionary } = require("devtools/shared/commands/index"); - /** * A Descriptor represents a debuggable context. It can be a browser tab, a tab on * a remote device, like a tab on Firefox for Android. But it can also be an add-on, @@ -33,13 +31,6 @@ function DescriptorMixin(parentClass) { get client() { return this._client; } - - async getCommands() { - if (!this._commands) { - this._commands = createCommandsDictionary(this); - } - return this._commands; - } } return Descriptor; } diff --git a/devtools/client/responsive/test/browser/head.js b/devtools/client/responsive/test/browser/head.js index 1c55b89fbc09..619a14049734 100644 --- a/devtools/client/responsive/test/browser/head.js +++ b/devtools/client/responsive/test/browser/head.js @@ -626,7 +626,7 @@ function addDeviceForTest(device) { async function waitForClientClose(ui) { info("Waiting for RDM devtools client to close"); - await ui.client.once("closed"); + await ui.commands.client.once("closed"); info("RDM's devtools client is now closed"); } diff --git a/devtools/client/responsive/ui.js b/devtools/client/responsive/ui.js index fb1852762592..10d977dd5d48 100644 --- a/devtools/client/responsive/ui.js +++ b/devtools/client/responsive/ui.js @@ -14,19 +14,10 @@ const Constants = require("devtools/client/responsive/constants"); const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); +const { + CommandsFactory, +} = require("devtools/shared/commands/commands-factory"); -loader.lazyRequireGetter( - this, - "DevToolsClient", - "devtools/client/devtools-client", - true -); -loader.lazyRequireGetter( - this, - "DevToolsServer", - "devtools/server/devtools-server", - true -); loader.lazyRequireGetter( this, "throttlingProfiles", @@ -364,34 +355,22 @@ class ResponsiveUI { this.resizeHandleY = null; this.resizeToolbarObserver = null; - // Close the devtools client used to speak with responsive emulation actor. + // Destroying the commands will close the devtools client used to speak with responsive emulation actor. // The actor handles clearing any overrides itself, so it's not necessary to clear // anything on shutdown client side. - const clientClosed = this.client.close(); + const commandsDestroyed = this.commands.destroy(); if (!isTabContentDestroying) { - await clientClosed; + await commandsDestroyed; } - this.client = this.responsiveFront = null; + this.commands = this.responsiveFront = null; this.destroyed = true; return true; } async connectToServer() { - // The client being instantiated here is separate from the toolbox. It is being used - // separately and has a life cycle that doesn't correspond to the toolbox. - DevToolsServer.init(); - DevToolsServer.registerAllActors(); - this.client = new DevToolsClient(DevToolsServer.connectPipe()); - await this.client.connect(); - - // Pass a proper `tab` filter option to getTab in order to create a - // "local" TabDescriptor, which handles target switching autonomously with - // its corresponding target-list. - const descriptor = await this.client.mainRoot.getTab({ tab: this.tab }); - - const commands = await descriptor.getCommands(); - this.targetList = commands.targetCommand; + this.commands = await CommandsFactory.forTab(this.tab); + this.targetList = this.commands.targetCommand; this.resourceWatcher = new ResourceWatcher(this.targetList); await this.targetList.startListening(); diff --git a/devtools/client/shared/test/shared-head.js b/devtools/client/shared/test/shared-head.js index 14027621c653..7ca284e44ecf 100644 --- a/devtools/client/shared/test/shared-head.js +++ b/devtools/client/shared/test/shared-head.js @@ -51,6 +51,9 @@ const { gDevTools } = require("devtools/client/framework/devtools"); const { TabDescriptorFactory, } = require("devtools/client/framework/tab-descriptor-factory"); +const { + CommandsFactory, +} = require("devtools/shared/commands/commands-factory"); const DevToolsUtils = require("devtools/shared/DevToolsUtils"); // This is overridden in files that load shared-head via loadSubScript. @@ -534,8 +537,13 @@ async function navigateTo(uri, { isErrorPage = false } = {}) { async function createAndAttachTargetForTab(tab) { info("Creating and attaching to a local tab target"); - const descriptor = await TabDescriptorFactory.createDescriptorForTab(tab); - const target = await descriptor.getTarget(); + const commands = await CommandsFactory.forTab(tab); + + // Initialize the TargetCommands which require some async stuff to be done + // before being fully ready. This will define the `targetCommand.targetFront` attribute. + await commands.targetCommand.startListening(); + + const target = commands.targetCommand.targetFront; await target.attach(); return target; } diff --git a/devtools/client/webconsole/browser-console-manager.js b/devtools/client/webconsole/browser-console-manager.js index 138158f61bdf..7aa9b573dcd9 100644 --- a/devtools/client/webconsole/browser-console-manager.js +++ b/devtools/client/webconsole/browser-console-manager.js @@ -5,18 +5,11 @@ "use strict"; var Services = require("Services"); -const ChromeUtils = require("ChromeUtils"); -const { DevToolsLoader } = ChromeUtils.import( - "resource://devtools/shared/Loader.jsm" -); +const { + CommandsFactory, +} = require("devtools/shared/commands/commands-factory"); loader.lazyRequireGetter(this, "Tools", "devtools/client/definitions", true); -loader.lazyRequireGetter( - this, - "DevToolsClient", - "devtools/client/devtools-client", - true -); loader.lazyRequireGetter(this, "l10n", "devtools/client/webconsole/utils/l10n"); loader.lazyRequireGetter( this, @@ -38,7 +31,6 @@ class BrowserConsoleManager { this._browserConsole = null; this._browserConsoleInitializing = null; this._browerConsoleSessionState = false; - this._devToolsClient = null; } storeBrowserConsoleSessionState() { @@ -50,17 +42,15 @@ class BrowserConsoleManager { } /** - * Open a Browser Console for the given commands context. + * Open a Browser Console for the current commands context. * - * @param object commands - * The commands object with all interfaces defined from devtools/shared/commands/ * @param nsIDOMWindow iframeWindow * The window where the browser console UI is already loaded. * @return object * A promise object for the opening of the new BrowserConsole instance. */ - async openBrowserConsole(commands, win) { - const hud = new BrowserConsole(commands, win, win); + async openBrowserConsole(win) { + const hud = new BrowserConsole(this.commands, win, win); this._browserConsole = hud; await hud.init(); return hud; @@ -77,8 +67,8 @@ class BrowserConsoleManager { await this._browserConsole.destroy(); this._browserConsole = null; - await this._devToolsClient.close(); - this._devToolsClient = null; + await this.commands.destroy(); + this.commands = null; } /** @@ -96,9 +86,9 @@ class BrowserConsoleManager { // Temporarily cache the async startup sequence so that if toggleBrowserConsole // gets called again we can return this console instead of opening another one. this._browserConsoleInitializing = (async () => { - const commands = await this.connect(); + this.commands = await CommandsFactory.forBrowserConsole(); const win = await this.openWindow(); - const browserConsole = await this.openBrowserConsole(commands, win); + const browserConsole = await this.openBrowserConsole(win); return browserConsole; })(); @@ -107,51 +97,6 @@ class BrowserConsoleManager { return browserConsole; } - /** - * One method to handle the whole setup sequence to connect to RDP backend. - * - * This will instantiate a special DevTools module loader for the DevToolsServer. - * Then spawn a DevToolsClient to connect to it. - * Get a Main Process Descriptor from it. - * Finally spawn a commands object for this descriptor. - */ - async connect() { - // The Browser console ends up using the debugger in autocomplete. - // Because the debugger can't be running in the same compartment than its debuggee, - // we have to load the server in a dedicated Loader, flagged with - // `freshCompartment`, which will force it to be loaded in another compartment. - // We aren't using `invisibleToDebugger` in order to allow the Browser toolbox to - // debug the Browser console. This is fine as they will spawn distinct Loaders and - // so distinct `DevToolsServer` and actor modules. - const loader = new DevToolsLoader({ - freshCompartment: true, - }); - const { DevToolsServer } = loader.require( - "devtools/server/devtools-server" - ); - - DevToolsServer.init(); - - // We want all the actors (root, browser and target-scoped) to be registered on the - // DevToolsServer. This is needed so the Browser Console can retrieve: - // - the console actors, which are target-scoped (See Bug 1416105) - // - the screenshotActor, which is browser-scoped (for the `:screenshot` command) - DevToolsServer.registerAllActors(); - - DevToolsServer.allowChromeProcess = true; - - this._devToolsClient = new DevToolsClient(DevToolsServer.connectPipe()); - await this._devToolsClient.connect(); - - const descriptor = await this._devToolsClient.mainRoot.getMainProcess(); - - // Hack something in order to help TargetMixinFront to distinguish the BrowserConsole - descriptor.createdForBrowserConsole = true; - - const commands = await descriptor.getCommands(); - return commands; - } - async openWindow() { const win = Services.ww.openWindow( null, diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js index a150ce17bc9b..c15c0547ba21 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_console_api.js @@ -5,7 +5,8 @@ const { STUBS_UPDATE_ENV, - createResourceWatcherForTab, + createCommandsForTab, + createResourceWatcherForCommands, getStubFile, getCleanedPacket, getSerializedPacket, @@ -55,15 +56,14 @@ add_task(async function() { } else { ok(true, "Stubs are up to date"); } - - await closeTabAndToolbox().catch(() => {}); }); async function generateConsoleApiStubs() { const stubs = new Map(); const tab = await addTab(TEST_URI); - const resourceWatcher = await createResourceWatcherForTab(tab); + const commands = await createCommandsForTab(tab); + const resourceWatcher = await createResourceWatcherForCommands(commands); // The resource-watcher only supports a single call to watch/unwatch per // instance, so we attach a unique watch callback, which will forward the @@ -115,6 +115,8 @@ async function generateConsoleApiStubs() { onAvailable: onConsoleMessage, }); + await commands.destroy(); + return stubs; } diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_css_message.js b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_css_message.js index c5119502802e..c85ed900e8f4 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_css_message.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_css_message.js @@ -5,7 +5,8 @@ const { STUBS_UPDATE_ENV, - createResourceWatcherForTab, + createCommandsForTab, + createResourceWatcherForCommands, getCleanedPacket, getStubFile, writeStubsToFile, @@ -61,7 +62,8 @@ async function generateCssMessageStubs() { const stubs = new Map(); const tab = await addTab(TEST_URI); - const resourceWatcher = await createResourceWatcherForTab(tab); + const commands = await createCommandsForTab(tab); + const resourceWatcher = await createResourceWatcherForCommands(commands); // The resource-watcher only supports a single call to watch/unwatch per // instance, so we attach a unique watch callback, which will forward the @@ -103,7 +105,7 @@ async function generateCssMessageStubs() { onAvailable: onCSSMessageAvailable, }); - await closeTabAndToolbox().catch(() => {}); + await commands.destroy(); return stubs; } diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_network_event.js b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_network_event.js index 8eeea50d23a3..aed3b64ce8aa 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_network_event.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_network_event.js @@ -4,7 +4,8 @@ "use strict"; const { - createResourceWatcherForTab, + createCommandsForTab, + createResourceWatcherForCommands, STUBS_UPDATE_ENV, getStubFile, getCleanedPacket, @@ -57,7 +58,8 @@ add_task(async function() { async function generateNetworkEventStubs() { const stubs = new Map(); const tab = await addTab(TEST_URI); - const resourceWatcher = await createResourceWatcherForTab(tab); + const commands = await createCommandsForTab(tab); + const resourceWatcher = await createResourceWatcherForCommands(commands); const stacktraces = new Map(); let addNetworkStub = function() {}; let addNetworkUpdateStub = function() {}; @@ -145,6 +147,9 @@ async function generateNetworkEventStubs() { onUpdated, } ); + + await commands.destroy(); + return stubs; } // Ensures the order of the resource properties diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_page_error.js b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_page_error.js index 6b13a9c5eba2..2e61097ba1ae 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_page_error.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_page_error.js @@ -5,7 +5,8 @@ const { STUBS_UPDATE_ENV, - createResourceWatcherForTab, + createCommandsForTab, + createResourceWatcherForCommands, getCleanedPacket, getSerializedPacket, getStubFile, @@ -57,15 +58,14 @@ add_task(async function() { } else { ok(true, "Stubs are up to date"); } - - await closeTabAndToolbox(); }); async function generatePageErrorStubs() { const stubs = new Map(); const tab = await addTab(TEST_URI); - const resourceWatcher = await createResourceWatcherForTab(tab); + const commands = await createCommandsForTab(tab); + const resourceWatcher = await createResourceWatcherForCommands(commands); // The resource-watcher only supports a single call to watch/unwatch per // instance, so we attach a unique watch callback, which will forward the diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_platform_messages.js b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_platform_messages.js index ae9a0a510f62..53f218898081 100644 --- a/devtools/client/webconsole/test/browser/browser_webconsole_stubs_platform_messages.js +++ b/devtools/client/webconsole/test/browser/browser_webconsole_stubs_platform_messages.js @@ -5,7 +5,8 @@ const { STUBS_UPDATE_ENV, - createResourceWatcherForDescriptor, + createCommandsForMainProcess, + createResourceWatcherForCommands, getCleanedPacket, getSerializedPacket, getStubFile, @@ -59,22 +60,8 @@ add_task(async function() { async function generatePlatformMessagesStubs() { const stubs = new Map(); - // Instantiate a minimal server - const { DevToolsClient } = require("devtools/client/devtools-client"); - const { DevToolsServer } = require("devtools/server/devtools-server"); - DevToolsServer.init(); - DevToolsServer.allowChromeProcess = true; - if (!DevToolsServer.createRootActor) { - DevToolsServer.registerAllActors(); - } - const transport = DevToolsServer.connectPipe(); - const client = new DevToolsClient(transport); - await client.connect(); - const mainProcessDescriptor = await client.mainRoot.getMainProcess(); - - const resourceWatcher = await createResourceWatcherForDescriptor( - mainProcessDescriptor - ); + const commands = await createCommandsForMainProcess(); + const resourceWatcher = await createResourceWatcherForCommands(commands); // The resource-watcher only supports a single call to watch/unwatch per // instance, so we attach a unique watch callback, which will forward the @@ -105,7 +92,7 @@ async function generatePlatformMessagesStubs() { } resourceWatcher.targetList.destroy(); - await client.close(); + await commands.destroy(); return stubs; } diff --git a/devtools/client/webconsole/test/browser/stub-generator-helpers.js b/devtools/client/webconsole/test/browser/stub-generator-helpers.js index 10edfc1bf219..477f7e73d93a 100644 --- a/devtools/client/webconsole/test/browser/stub-generator-helpers.js +++ b/devtools/client/webconsole/test/browser/stub-generator-helpers.js @@ -14,25 +14,28 @@ const CHROME_PREFIX = "chrome://mochitests/content/browser/"; const STUBS_FOLDER = "devtools/client/webconsole/test/node/fixtures/stubs/"; const STUBS_UPDATE_ENV = "WEBCONSOLE_STUBS_UPDATE"; -async function createResourceWatcherForTab(tab) { +async function createCommandsForTab(tab) { const { - TabDescriptorFactory, - } = require("devtools/client/framework/tab-descriptor-factory"); - const descriptor = await TabDescriptorFactory.createDescriptorForTab(tab); - const target = await descriptor.getTarget(); - const resourceWatcher = await createResourceWatcherForDescriptor( - target.descriptorFront - ); - return resourceWatcher; + CommandsFactory, + } = require("devtools/shared/commands/commands-factory"); + const commands = await CommandsFactory.forTab(tab); + return commands; } -async function createResourceWatcherForDescriptor(descriptor) { +async function createCommandsForMainProcess() { + const { + CommandsFactory, + } = require("devtools/shared/commands/commands-factory"); + const commands = await CommandsFactory.forMainProcess(); + return commands; +} + +async function createResourceWatcherForCommands(commands) { // Avoid mocha to try to load these module and fail while doing it when running node tests const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); - const commands = await descriptor.getCommands(); const targetList = commands.targetCommand; await targetList.startListening(); return new ResourceWatcher(targetList); @@ -542,8 +545,9 @@ function parsePacketAndCreateFronts(packet) { module.exports = { STUBS_UPDATE_ENV, - createResourceWatcherForTab, - createResourceWatcherForDescriptor, + createCommandsForTab, + createCommandsForMainProcess, + createResourceWatcherForCommands, getStubFile, getCleanedPacket, getSerializedPacket, diff --git a/devtools/server/connectors/content-process-connector.js b/devtools/server/connectors/content-process-connector.js index 7c5c0de0e116..4f159acc3526 100644 --- a/devtools/server/connectors/content-process-connector.js +++ b/devtools/server/connectors/content-process-connector.js @@ -104,7 +104,11 @@ function connectToContentProcess(connection, mm, onDestroy) { if (subject == mm) { // Send the "tabDetached" event before closing the connection which // will destroy fronts on the client. - connection.send({ from: actor.actor, type: "tabDetached" }); + // Note that the content process may be destroyed before the actor is created. + // Avoid trying to send any tabDetached in such situation. + if (actor) { + connection.send({ from: actor.actor, type: "tabDetached" }); + } onClose(); } } diff --git a/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js b/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js index 2047add8905c..3ba196a9e111 100644 --- a/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js +++ b/devtools/server/tests/browser/browser_stylesheets_getTextEmpty.js @@ -11,15 +11,17 @@ const TEST_URI = `data:text/html;charset=utf-8,`; add_task(async function() { - const target = await addTabTarget(TEST_URI); + const browser = await addTab(TEST_URI); + const tab = gBrowser.getTabForBrowser(browser); const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); - const commands = await target.descriptorFront.getCommands(); + const commands = await CommandsFactory.forTab(tab); const targetList = commands.targetCommand; await targetList.startListening(); + const target = targetList.targetFront; const resourceWatcher = new ResourceWatcher(targetList); const styleSheetsFront = await target.getFront("stylesheets"); diff --git a/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js b/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js index 1e7f502f2cc8..c7e968e1306a 100644 --- a/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js +++ b/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js @@ -8,6 +8,9 @@ "use strict"; const TEST_DOC_URL = MAIN_DOMAIN + "doc_iframe.html"; +const { + createLocalClientForTests, +} = require("devtools/shared/commands/commands-factory"); // URL of the ` ); - const firstDescriptor = await mainRoot.getTab({ tab: gBrowser.selectedTab }); - const firstTarget = await firstDescriptor.getTarget(); - const commands = await firstDescriptor.getCommands(); const targetList = commands.targetCommand; const { TYPES } = targetList; - await targetList.startListening(); - is( - targetList.targetFront, - firstTarget, - "The target list top level target is the main process one" - ); - // Create a second target to switch to, a new tab with an iframe const secondTab = await addTab( `data:text/html,` ); - const secondDescriptor = await mainRoot.getTab({ tab: gBrowser.selectedTab }); + const secondDescriptor = await commands.client.mainRoot.getTab({ + tab: gBrowser.selectedTab, + }); const secondTarget = await secondDescriptor.getTarget(); const frameTargets = []; - let currentTarget = firstTarget; + const firstTarget = targetList.targetFront; + let currentTarget = targetList.targetFront; const onFrameAvailable = ({ targetFront, isTargetSwitching }) => { is( targetFront.targetType, @@ -142,6 +134,8 @@ async function testSwitchToTarget(client) { targetList.destroy(); + await commands.destroy(); + BrowserTestUtils.removeTab(firstTab); BrowserTestUtils.removeTab(secondTab); } diff --git a/devtools/shared/commands/target/tests/browser_target_list_tab_workers.js b/devtools/shared/commands/target/tests/browser_target_list_tab_workers.js index 9095a788076f..9063a8581f98 100644 --- a/devtools/shared/commands/target/tests/browser_target_list_tab_workers.js +++ b/devtools/shared/commands/target/tests/browser_target_list_tab_workers.js @@ -18,9 +18,6 @@ add_task(async function() { // which forces the emission of RDP requests we aren't correctly waiting for. await pushPref("dom.ipc.processPrelaunch.enabled", false); - const client = await createLocalClient(); - const mainRoot = client.mainRoot; - // The WorkerDebuggerManager#getWorkerDebuggerEnumerator method we're using to retrieve // workers loops through _all_ the workers in the process, which means it goes over workers // from other tabs as well. Here we add a few tabs that are not going to be used in the @@ -32,16 +29,15 @@ add_task(async function() { const tab = await addTab(`${FISSION_TEST_URL}?&noServiceWorker`); // Create a TargetCommand for the tab - const descriptor = await mainRoot.getTab({ tab }); - const target = await descriptor.getTarget(); - + const commands = await CommandsFactory.forTab(tab); + await commands.targetCommand.startListening(); // Ensure attaching the target as BrowsingContextTargetActor.listWorkers // assert that the target actor is attached. // It isn't clear if this assertion is meaningful? + const target = commands.targetCommand.targetFront; await target.attach(); - - const commands = await descriptor.getCommands(); const targetList = commands.targetCommand; + const { TYPES } = targetList; // Workaround to allow listening for workers in the content toolbox @@ -322,8 +318,8 @@ add_task(async function() { targetList.destroy(); info("Unregister service workers so they don't appear in other tests."); - await unregisterAllServiceWorkers(client); + await unregisterAllServiceWorkers(commands.client); BrowserTestUtils.removeTab(tab); - await client.close(); + await commands.destroy(); }); diff --git a/devtools/shared/commands/target/tests/browser_target_list_various_descriptors.js b/devtools/shared/commands/target/tests/browser_target_list_various_descriptors.js index b2203381a785..0870411fdbad 100644 --- a/devtools/shared/commands/target/tests/browser_target_list_various_descriptors.js +++ b/devtools/shared/commands/target/tests/browser_target_list_various_descriptors.js @@ -18,24 +18,18 @@ add_task(async function() { // This preference helps destroying the content process when we close the tab await pushPref("dom.ipc.keepProcessesAlive.web", 1); - const client = await createLocalClient(); - const mainRoot = client.mainRoot; - - await testLocalTab(mainRoot); - await testRemoteTab(mainRoot); - await testParentProcess(mainRoot); - await testContentProcess(mainRoot); - await testWorker(mainRoot); - await testWebExtension(mainRoot); - - await client.close(); + await testLocalTab(); + await testRemoteTab(); + await testParentProcess(); + await testContentProcess(); + await testWorker(); + await testWebExtension(); }); -async function testParentProcess(rootFront) { +async function testParentProcess() { info("Test TargetCommand against parent process descriptor"); - const descriptor = await rootFront.getMainProcess(); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forMainProcess(); const targetList = commands.targetCommand; await targetList.startListening(); @@ -55,14 +49,15 @@ async function testParentProcess(rootFront) { targetList.destroy(); await waitForAllTargetsToBeAttached(targetList); + + await commands.destroy(); } -async function testLocalTab(rootFront) { +async function testLocalTab() { info("Test TargetCommand against local tab descriptor (via getTab({ tab }))"); const tab = await addTab(TEST_URL); - const descriptor = await rootFront.getTab({ tab }); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forTab(tab); const targetList = commands.targetCommand; await targetList.startListening(); // Avoid the target to close the client when we destroy the target list and the target @@ -82,18 +77,19 @@ async function testLocalTab(rootFront) { targetList.destroy(); BrowserTestUtils.removeTab(tab); + + await commands.destroy(); } -async function testRemoteTab(rootFront) { +async function testRemoteTab() { info( "Test TargetCommand against remote tab descriptor (via getTab({ outerWindowID }))" ); const tab = await addTab(TEST_URL); - const descriptor = await rootFront.getTab({ + const commands = await CommandsFactory.forRemoteTabInTest({ outerWindowID: tab.linkedBrowser.outerWindowID, }); - const commands = await descriptor.getCommands(); const targetList = commands.targetCommand; await targetList.startListening(); @@ -120,7 +116,7 @@ async function testRemoteTab(rootFront) { if (isFissionEnabled()) { info("With fission, cross process switching destroy everything"); ok(targetFront.isDestroyed(), "Top level target is destroyed"); - ok(descriptor.isDestroyed(), "Descriptor is also destroyed"); + ok(commands.descriptorFront.isDestroyed(), "Descriptor is also destroyed"); } else { is( targetList.targetFront, @@ -132,9 +128,11 @@ async function testRemoteTab(rootFront) { targetList.destroy(); BrowserTestUtils.removeTab(tab); + + await commands.destroy(); } -async function testWebExtension(rootFront) { +async function testWebExtension() { info("Test TargetCommand against webextension descriptor"); const extension = ExtensionTestUtils.loadExtension({ @@ -146,8 +144,7 @@ async function testWebExtension(rootFront) { await extension.startup(); - const descriptor = await rootFront.getAddon({ id: extension.id }); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forAddon(extension.id); const targetList = commands.targetCommand; await targetList.startListening(); @@ -165,9 +162,11 @@ async function testWebExtension(rootFront) { targetList.destroy(); await extension.unload(); + + await commands.destroy(); } -async function testContentProcess(rootFront) { +async function testContentProcess() { info("Test TargetCommand against content process descriptor"); const tab = await BrowserTestUtils.openNewForegroundTab({ @@ -178,8 +177,7 @@ async function testContentProcess(rootFront) { const { osPid } = tab.linkedBrowser.browsingContext.currentWindowGlobal; - const descriptor = await rootFront.getProcess(osPid); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forProcess(osPid); const targetList = commands.targetCommand; await targetList.startListening(); @@ -197,17 +195,35 @@ async function testContentProcess(rootFront) { targetList.destroy(); BrowserTestUtils.removeTab(tab); + + await commands.destroy(); } -async function testWorker(rootFront) { +// CommandsFactory expect the worker id, which is computed from the nsIWorkerDebugger.id attribute +function getWorkerDebuggerId(url) { + const wdm = Cc[ + "@mozilla.org/dom/workers/workerdebuggermanager;1" + ].createInstance(Ci.nsIWorkerDebuggerManager); + const workers = wdm.getWorkerDebuggerEnumerator(); + while (workers.hasMoreElements()) { + const worker = workers.getNext(); + worker.QueryInterface(Ci.nsIWorkerDebugger); + if (worker.url == url) { + return worker.id; + } + } + return null; +} + +async function testWorker() { info("Test TargetCommand against worker descriptor"); const workerUrl = CHROME_WORKER_URL + "#descriptor"; new Worker(workerUrl); - const { workers } = await rootFront.listWorkers(); - const descriptor = workers.find(w => w.url == workerUrl); - const commands = await descriptor.getCommands(); + const workerId = getWorkerDebuggerId(workerUrl); + ok(workerId, "Found the worker Debugger ID"); + const commands = await CommandsFactory.forWorker(workerId); const targetList = commands.targetCommand; await targetList.startListening(); @@ -223,4 +239,11 @@ async function testWorker(rootFront) { is(targetFront.isTopLevel, true, "This is flagged as top level"); targetList.destroy(); + + // Calling CommandsFactory.forWorker, will call RootFront.getWorker + // which will spawn lots of worker legacy code, firing lots of requests, + // which may still be pending + await commands.waitForRequestsToSettle(); + + await commands.destroy(); } diff --git a/devtools/shared/commands/target/tests/browser_target_list_watchTargets.js b/devtools/shared/commands/target/tests/browser_target_list_watchTargets.js index 649147ac7ae6..748ce6e1890a 100644 --- a/devtools/shared/commands/target/tests/browser_target_list_watchTargets.js +++ b/devtools/shared/commands/target/tests/browser_target_list_watchTargets.js @@ -17,21 +17,15 @@ add_task(async function() { // This preference helps destroying the content process when we close the tab await pushPref("dom.ipc.keepProcessesAlive.web", 1); - const client = await createLocalClient(); - const mainRoot = client.mainRoot; - - await testWatchTargets(mainRoot); - await testContentProcessTarget(mainRoot); - await testThrowingInOnAvailable(mainRoot); - - await client.close(); + await testWatchTargets(); + await testContentProcessTarget(); + await testThrowingInOnAvailable(); }); -async function testWatchTargets(mainRoot) { +async function testWatchTargets() { info("Test TargetCommand watchTargets function"); - const targetDescriptor = await mainRoot.getMainProcess(); - const commands = await targetDescriptor.getCommands(); + const commands = await CommandsFactory.forMainProcess(); const targetList = commands.targetCommand; const { TYPES } = targetList; @@ -44,7 +38,7 @@ async function testWatchTargets(mainRoot) { "Check that onAvailable is called for processes already created *before* the call to watchTargets" ); const targets = new Set(); - const topLevelTarget = await targetDescriptor.getTarget(); + const topLevelTarget = targetList.targetFront; const onAvailable = ({ targetFront }) => { if (targets.has(targetFront)) { ok(false, "The same target is notified multiple times via onAvailable"); @@ -157,16 +151,16 @@ async function testWatchTargets(mainRoot) { targetList.destroy(); - // Also destroy the descriptor so that testThrowingInOnAvailable can get a fresh - // commands object and also a fresh TargetList instance - targetDescriptor.destroy(); + await commands.destroy(); } -async function testContentProcessTarget(mainRoot) { +async function testContentProcessTarget() { info("Test TargetCommand watchTargets with a content process target"); - const processes = await mainRoot.listProcesses(); - const commands = await processes[1].getCommands(); + const { + osPid, + } = gBrowser.selectedBrowser.browsingContext.currentWindowGlobal; + const commands = await CommandsFactory.forProcess(osPid); const targetList = commands.targetCommand; const { TYPES } = targetList; @@ -176,7 +170,7 @@ async function testContentProcessTarget(mainRoot) { // as listening for additional target is only enable for the parent process target. // See bug 1593928. const targets = new Set(); - const topLevelTarget = await processes[1].getTarget(); + const topLevelTarget = targetList.targetFront; const onAvailable = ({ targetFront }) => { if (targets.has(targetFront)) { // This may fail if the top level target is reported by LegacyImplementation @@ -206,15 +200,16 @@ async function testContentProcessTarget(mainRoot) { targetList.unwatchTargets([TYPES.PROCESS], onAvailable, onDestroyed); targetList.destroy(); + + await commands.destroy(); } -async function testThrowingInOnAvailable(mainRoot) { +async function testThrowingInOnAvailable() { info( "Test TargetCommand watchTargets function when an exception is thrown in onAvailable callback" ); - const targetDescriptor = await mainRoot.getMainProcess(); - const commands = await targetDescriptor.getCommands(); + const commands = await CommandsFactory.forMainProcess(); const targetList = commands.targetCommand; const { TYPES } = targetList; @@ -243,4 +238,6 @@ async function testThrowingInOnAvailable(mainRoot) { ); targetList.destroy(); + + await commands.destroy(); } diff --git a/devtools/shared/commands/target/tests/browser_watcher_actor_getter_caching.js b/devtools/shared/commands/target/tests/browser_watcher_actor_getter_caching.js index 65a40ab124f6..45db3807190b 100644 --- a/devtools/shared/commands/target/tests/browser_watcher_actor_getter_caching.js +++ b/devtools/shared/commands/target/tests/browser_watcher_actor_getter_caching.js @@ -9,12 +9,10 @@ const TEST_URL = "data:text/html;charset=utf-8,Actor caching test"; add_task(async function() { info("Setup the test page with workers of all types"); - const client = await createLocalClient(); const tab = await addTab(TEST_URL); info("Create a target list for a tab target"); - const descriptor = await client.mainRoot.getTab({ tab }); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forTab(tab); const targetList = commands.targetCommand; await targetList.startListening(); @@ -54,8 +52,8 @@ add_task(async function() { ); targetList.destroy(); - await client.waitForRequestsToSettle(); - await client.close(); + await commands.waitForRequestsToSettle(); + await commands.destroy(); }); /** diff --git a/devtools/shared/commands/target/tests/browser_watcher_target_configuration.js b/devtools/shared/commands/target/tests/browser_watcher_target_configuration.js index 69c6c057e898..fa7c4c230431 100644 --- a/devtools/shared/commands/target/tests/browser_watcher_target_configuration.js +++ b/devtools/shared/commands/target/tests/browser_watcher_target_configuration.js @@ -7,13 +7,10 @@ add_task(async function() { info("Setup the test page with workers of all types"); - const client = await createLocalClient(); - const mainRoot = client.mainRoot; const tab = await addTab("data:text/html;charset=utf-8,Configuration actor"); info("Create a target list for a tab target"); - const descriptor = await mainRoot.getTab({ tab }); - const commands = await descriptor.getCommands(); + const commands = await CommandsFactory.forTab(tab); const targetList = commands.targetCommand; await targetList.startListening(); @@ -68,7 +65,7 @@ add_task(async function() { ); targetList.destroy(); - await client.close(); + await commands.destroy(); }); function compareOptions(options, expected, message) { diff --git a/devtools/shared/resources/tests/head.js b/devtools/shared/resources/tests/head.js index 30fbde157bc4..06207794c43f 100644 --- a/devtools/shared/resources/tests/head.js +++ b/devtools/shared/resources/tests/head.js @@ -15,29 +15,14 @@ Services.scriptloader.loadSubScript( const { DevToolsClient } = require("devtools/client/devtools-client"); const { DevToolsServer } = require("devtools/server/devtools-server"); -async function createLocalClient() { - // Instantiate a minimal server - DevToolsServer.init(); - DevToolsServer.allowChromeProcess = true; - if (!DevToolsServer.createRootActor) { - DevToolsServer.registerAllActors(); - } - const transport = DevToolsServer.connectPipe(); - const client = new DevToolsClient(transport); - await client.connect(); - return client; -} - -async function _initResourceWatcherFromDescriptor( - client, - descriptor, +async function _initResourceWatcherFromCommands( + commands, { listenForWorkers = false } = {} ) { const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); - const commands = await descriptor.getCommands(); const targetList = commands.targetCommand; if (listenForWorkers) { targetList.listenForWorkers = true; @@ -47,7 +32,7 @@ async function _initResourceWatcherFromDescriptor( // Now create a ResourceWatcher const resourceWatcher = new ResourceWatcher(targetList); - return { client, resourceWatcher, targetList }; + return { client: commands.client, commands, resourceWatcher, targetList }; } /** @@ -58,34 +43,36 @@ async function _initResourceWatcherFromDescriptor( * @param {Object} options * @param {Boolean} options.listenForWorkers * @return {Object} object - * @return {ResourceWatcher} object.client - * The underlying client instance. + * @return {ResourceWatcher} object.resourceWatcher + * The underlying resource watcher interface. + * @return {Object} object.commands + * The commands object defined by modules from devtools/shared/commands. * @return {DevToolsClient} object.client * The underlying client instance. * @return {DevToolsClient} object.targetList * The underlying target list instance. */ async function initResourceWatcher(tab, options) { - const client = await createLocalClient(); - const descriptor = await client.mainRoot.getTab({ tab }); - return _initResourceWatcherFromDescriptor(client, descriptor, options); + const commands = await CommandsFactory.forTab(tab); + return _initResourceWatcherFromCommands(commands, options); } /** * Instantiate a multi-process ResourceWatcher, watching all type of targets. * * @return {Object} object - * @return {ResourceWatcher} object.client - * The underlying client instance. + * @return {ResourceWatcher} object.resourceWatcher + * The underlying resource watcher interface. + * @return {Object} object.commands + * The commands object defined by modules from devtools/shared/commands. * @return {DevToolsClient} object.client * The underlying client instance. * @return {DevToolsClient} object.targetList * The underlying target list instance. */ async function initMultiProcessResourceWatcher() { - const client = await createLocalClient(); - const descriptor = await client.mainRoot.getMainProcess(); - return _initResourceWatcherFromDescriptor(client, descriptor); + const commands = await CommandsFactory.forMainProcess(); + return _initResourceWatcherFromCommands(commands); } // Copied from devtools/shared/webconsole/test/chrome/common.js diff --git a/devtools/shared/webconsole/test/browser/browser_network_longstring.js b/devtools/shared/webconsole/test/browser/browser_network_longstring.js index 6870bb797165..1225cb0cffc4 100644 --- a/devtools/shared/webconsole/test/browser/browser_network_longstring.js +++ b/devtools/shared/webconsole/test/browser/browser_network_longstring.js @@ -13,16 +13,15 @@ let ORIGINAL_LONG_STRING_LENGTH, ORIGINAL_LONG_STRING_INITIAL_LENGTH; add_task(async function() { const tab = await addTab(URL_ROOT + "network_requests_iframe.html"); - const target = await createAndAttachTargetForTab(tab); - // Avoid mocha to try to load these module and fail while doing it when running node tests const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); - const commands = await target.descriptorFront.getCommands(); + const commands = await CommandsFactory.forTab(tab); const targetList = commands.targetCommand; await targetList.startListening(); + const target = commands.targetCommand.targetFront; const resourceWatcher = new ResourceWatcher(targetList); // Override the default long string settings to lower values. diff --git a/devtools/shared/webconsole/test/chrome/common.js b/devtools/shared/webconsole/test/chrome/common.js index bf7dcb55fd6a..506648573c3b 100644 --- a/devtools/shared/webconsole/test/chrome/common.js +++ b/devtools/shared/webconsole/test/chrome/common.js @@ -12,6 +12,9 @@ const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm"); const { DevToolsServer } = require("devtools/server/devtools-server"); // eslint-disable-next-line mozilla/reject-some-requires const { DevToolsClient } = require("devtools/client/devtools-client"); +const { + CommandsFactory, +} = require("devtools/shared/commands/commands-factory"); const Services = require("Services"); @@ -113,18 +116,15 @@ var _attachConsole = async function(listeners, attachToTab, attachToWorker) { }; async function createResourceWatcherForTab() { - const client = await connectToDebugger(); - const targetDescriptor = await client.mainRoot.getMainProcess(); - const target = await targetDescriptor.getTarget(); - // Avoid mocha to try to load these module and fail while doing it when running node tests const { ResourceWatcher, } = require("devtools/shared/resources/resource-watcher"); - const commands = await targetDescriptor.getCommands(); + const commands = await CommandsFactory.forMainProcess(); const targetList = commands.targetCommand; await targetList.startListening(); + const target = commands.targetCommand.targetFront; const resourceWatcher = new ResourceWatcher(targetList); return { resourceWatcher, target };