browser_document_devtools_basics.js (4570B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /** 5 * Document the basics of DevTools backend via Fronts in a test. 6 */ 7 8 "use strict"; 9 10 const TEST_URL = "data:text/html,new-tab"; 11 12 add_task(async () => { 13 // Allow logging all RDP packets 14 await pushPref("devtools.debugger.log", true); 15 // Really all of them 16 await pushPref("devtools.debugger.log.verbose", true); 17 18 // Instantiate a DevTools server 19 DevToolsServer.init(); 20 DevToolsServer.registerAllActors(); 21 22 // Instantiate a client connected to this server 23 const transport = DevToolsServer.connectPipe(); 24 const client = new DevToolsClient(transport); 25 26 // This will trigger some handshake with the server 27 await client.connect(); 28 29 // You need to call listTabs once to retrieve the existing list of Tab Descriptor actors... 30 const tabs = await client.mainRoot.listTabs(); 31 32 // ... which will let you receive the 'tabListChanged' event. 33 // This is an empty RDP packet, you need to re-call listTabs to get the full new updated list of actors. 34 const onTabListUpdated = client.mainRoot.once("tabListChanged"); 35 36 // Open a new tab. 37 await BrowserTestUtils.openNewForegroundTab({ 38 gBrowser, 39 url: TEST_URL, 40 }); 41 42 await onTabListUpdated; 43 44 // The new list of Tab descriptors should contain the newly opened tab 45 const newTabs = await client.mainRoot.listTabs(); 46 is(newTabs.length, tabs.length + 1); 47 48 const tabDescriptorActor = newTabs.pop(); 49 is(tabDescriptorActor.url, TEST_URL); 50 51 // Query the Tab Descriptor actor to retrieve its related Watcher actor. 52 // Each Descriptor actor has a dedicated watcher which will be scoped to the context of the descriptor. 53 // Here the watcher will focus on the related tab. 54 const watcherActor = await tabDescriptorActor.getWatcher(); 55 56 // The call to Watcher Actor's watchTargets will emit target-available-form RDP events. 57 // One per available target. It will emit one for each immediatly available target, 58 // but also for any available later. That, until you call unwatchTarget method. 59 // 60 // Here I'm listening to "target-available" to get a Front instance, which helps call RDP methods. 61 // But this isn't an RDP event. This is a frontend-only thing. 62 const onTopTargetAvailable = watcherActor.once("target-available"); 63 64 // watchTargets accepts "frame", "process" and "worker" 65 // When debugging a web page you want to listen to frame and worker targets. 66 // "frame" would better be named "WindowGlobal" as it will notify you about all the WindowGlobal of the page. 67 // Each top level documents and any iframe documents will have a related WindowGlobal, 68 // if any of these documents navigate, a new WindowGlobal will be instantiated. 69 // If you care about workers, listen to worker targets as well. 70 await watcherActor.watchTargets("frame"); 71 72 // This is a trivial example so we have a unique WindowGlobal target for the top level document 73 const topTarget = await onTopTargetAvailable; 74 is(topTarget.url, TEST_URL); 75 76 // Similarly to watchTarget, the next call to watchResources will emit new resources right away as well as later. 77 const onConsoleMessages = topTarget.once("resources-available-array"); 78 79 // If you want to observe anything, you have to use Watcher Actor's watchrResources API. 80 // The list of all available resources is here: 81 // https://searchfox.org/mozilla-central/source/devtools/server/actors/resources/index.js#9 82 // And you might have a look at each ResourceWatcher subclass to learn more about the fields exposed by each resource type: 83 // https://searchfox.org/mozilla-central/source/devtools/server/actors/resources 84 await watcherActor.watchResources(["console-message"]); 85 86 // You may use many useful actors on each target actor, like console, thread, ... 87 // You can get the full list of available actors in: 88 // https://searchfox.org/mozilla-central/source/devtools/server/actors/utils/actor-registry.js#176 89 // And then look into the mentioned path for implementation. 90 const webConsoleActor = await topTarget.getFront("console"); 91 92 // Call the Console API in order to force emitting a console-message resource 93 await webConsoleActor.evaluateJSAsync({ text: "console.log('42')" }); 94 95 // Wait for the related console-message resource 96 const [[, resources]] = await onConsoleMessages; 97 98 // Note that resources-available-array comes with a "array" attribute which is an array of resources 99 // which may contain various resource types. 100 is(resources[0].arguments[0], "42"); 101 102 await client.close(); 103 });