browser_target_command_various_descriptors.js (8445B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test the TargetCommand API with all possible descriptors 7 8 const TEST_URL = "https://example.org/document-builder.sjs?html=org"; 9 const SECOND_TEST_URL = "https://example.com/document-builder.sjs?html=org"; 10 const CHROME_WORKER_URL = CHROME_URL_ROOT + "test_worker.js"; 11 12 const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js"); 13 14 add_task(async function () { 15 // Enabled fission prefs 16 await pushPref("devtools.browsertoolbox.scope", "everything"); 17 // Disable the preloaded process as it gets created lazily and may interfere 18 // with process count assertions 19 await pushPref("dom.ipc.processPrelaunch.enabled", false); 20 // This preference helps destroying the content process when we close the tab 21 await pushPref("dom.ipc.keepProcessesAlive.web", 1); 22 23 await testLocalTab(); 24 await testRemoteTab(); 25 await testParentProcess(); 26 await testWorker(); 27 await testWebExtension(); 28 }); 29 30 async function testParentProcess() { 31 info("Test TargetCommand against parent process descriptor"); 32 33 const commands = await CommandsFactory.forMainProcess(); 34 const { descriptorFront } = commands; 35 36 is( 37 descriptorFront.descriptorType, 38 DESCRIPTOR_TYPES.PROCESS, 39 "The descriptor type is correct" 40 ); 41 is( 42 descriptorFront.isParentProcessDescriptor, 43 true, 44 "Descriptor front isParentProcessDescriptor is correct" 45 ); 46 is( 47 descriptorFront.isProcessDescriptor, 48 true, 49 "Descriptor front isProcessDescriptor is correct" 50 ); 51 52 const targetCommand = commands.targetCommand; 53 await targetCommand.startListening(); 54 55 const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES); 56 Assert.greater( 57 targets.length, 58 1, 59 "We get many targets when debugging the parent process" 60 ); 61 const targetFront = targets[0]; 62 is(targetFront, targetCommand.targetFront, "The first is the top level one"); 63 is( 64 targetFront.targetType, 65 targetCommand.TYPES.FRAME, 66 "the parent process target is of frame type, because it inherits from WindowGlobalTargetActor" 67 ); 68 is(targetFront.isTopLevel, true, "This is flagged as top level"); 69 70 targetCommand.destroy(); 71 await waitForAllTargetsToBeAttached(targetCommand); 72 73 await commands.destroy(); 74 } 75 76 async function testLocalTab() { 77 info("Test TargetCommand against local tab descriptor (via getTab({ tab }))"); 78 79 const tab = await addTab(TEST_URL); 80 const commands = await CommandsFactory.forTab(tab); 81 const { descriptorFront } = commands; 82 is( 83 descriptorFront.descriptorType, 84 DESCRIPTOR_TYPES.TAB, 85 "The descriptor type is correct" 86 ); 87 is( 88 descriptorFront.isTabDescriptor, 89 true, 90 "Descriptor front isTabDescriptor is correct" 91 ); 92 93 const targetCommand = commands.targetCommand; 94 await targetCommand.startListening(); 95 96 const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES); 97 is(targets.length, 1, "Got a unique target"); 98 const targetFront = targets[0]; 99 is(targetFront, targetCommand.targetFront, "The first is the top level one"); 100 is( 101 targetFront.targetType, 102 targetCommand.TYPES.FRAME, 103 "the tab target is of frame type" 104 ); 105 is(targetFront.isTopLevel, true, "This is flagged as top level"); 106 107 targetCommand.destroy(); 108 109 BrowserTestUtils.removeTab(tab); 110 111 await commands.destroy(); 112 } 113 114 async function testRemoteTab() { 115 info( 116 "Test TargetCommand against remote tab descriptor (via getTab({ browserId }))" 117 ); 118 119 const tab = await addTab(TEST_URL); 120 const commands = await CommandsFactory.forRemoteTab( 121 tab.linkedBrowser.browserId 122 ); 123 const { descriptorFront } = commands; 124 is( 125 descriptorFront.descriptorType, 126 DESCRIPTOR_TYPES.TAB, 127 "The descriptor type is correct" 128 ); 129 is( 130 descriptorFront.isTabDescriptor, 131 true, 132 "Descriptor front isTabDescriptor is correct" 133 ); 134 135 const targetCommand = commands.targetCommand; 136 await targetCommand.startListening(); 137 138 const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES); 139 is(targets.length, 1, "Got a unique target"); 140 const targetFront = targets[0]; 141 is( 142 targetFront, 143 targetCommand.targetFront, 144 "TargetCommand top target is the same as the first target" 145 ); 146 is( 147 targetFront.targetType, 148 targetCommand.TYPES.FRAME, 149 "the tab target is of frame type" 150 ); 151 is(targetFront.isTopLevel, true, "This is flagged as top level"); 152 153 const browser = tab.linkedBrowser; 154 const onLoaded = BrowserTestUtils.browserLoaded(browser); 155 BrowserTestUtils.startLoadingURIString(browser, SECOND_TEST_URL); 156 await onLoaded; 157 158 info("Wait for the new target"); 159 await waitFor(() => targetCommand.targetFront != targetFront); 160 isnot( 161 targetCommand.targetFront, 162 targetFront, 163 "The top level target changes on navigation" 164 ); 165 ok( 166 !targetCommand.targetFront.isDestroyed(), 167 "The new target isn't destroyed" 168 ); 169 ok(targetFront.isDestroyed(), "While the previous target is destroyed"); 170 171 targetCommand.destroy(); 172 173 BrowserTestUtils.removeTab(tab); 174 175 await commands.destroy(); 176 } 177 178 async function testWebExtension() { 179 info("Test TargetCommand against webextension descriptor"); 180 181 const extension = ExtensionTestUtils.loadExtension({ 182 useAddonManager: "temporary", 183 manifest: { 184 name: "Sample extension", 185 }, 186 }); 187 188 await extension.startup(); 189 190 const commands = await CommandsFactory.forAddon(extension.id); 191 const { descriptorFront } = commands; 192 is( 193 descriptorFront.descriptorType, 194 DESCRIPTOR_TYPES.EXTENSION, 195 "The descriptor type is correct" 196 ); 197 is( 198 descriptorFront.isWebExtensionDescriptor, 199 true, 200 "Descriptor front isWebExtensionDescriptor is correct" 201 ); 202 203 const targetCommand = commands.targetCommand; 204 await targetCommand.startListening(); 205 206 const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES); 207 is(targets.length, 1, "Got a unique target"); 208 const targetFront = targets[0]; 209 is(targetFront, targetCommand.targetFront, "The first is the top level one"); 210 is( 211 targetFront.targetType, 212 targetCommand.TYPES.FRAME, 213 "the web extension target is of frame type, because it inherits from WindowGlobalTargetActor" 214 ); 215 is(targetFront.isTopLevel, true, "This is flagged as top level"); 216 is(targetFront.addonId, extension.id, "The addonId attribute is correct"); 217 218 targetCommand.destroy(); 219 220 await extension.unload(); 221 222 await commands.destroy(); 223 } 224 225 // CommandsFactory expect the worker id, which is computed from the nsIWorkerDebugger.id attribute 226 function getNextWorkerDebuggerId() { 227 return new Promise(resolve => { 228 const wdm = Cc[ 229 "@mozilla.org/dom/workers/workerdebuggermanager;1" 230 ].createInstance(Ci.nsIWorkerDebuggerManager); 231 const listener = { 232 onRegister(dbg) { 233 wdm.removeListener(listener); 234 resolve(dbg.id); 235 }, 236 }; 237 wdm.addListener(listener); 238 }); 239 } 240 async function testWorker() { 241 info("Test TargetCommand against worker descriptor"); 242 243 const workerUrl = CHROME_WORKER_URL + "#descriptor"; 244 const onNextWorker = getNextWorkerDebuggerId(); 245 const worker = new Worker(workerUrl); 246 const workerId = await onNextWorker; 247 ok(workerId, "Found the worker Debugger ID"); 248 249 const commands = await CommandsFactory.forWorker(workerId); 250 const { descriptorFront } = commands; 251 is( 252 descriptorFront.descriptorType, 253 DESCRIPTOR_TYPES.WORKER, 254 "The descriptor type is correct" 255 ); 256 is( 257 descriptorFront.isWorkerDescriptor, 258 true, 259 "Descriptor front isWorkerDescriptor is correct" 260 ); 261 262 const targetCommand = commands.targetCommand; 263 await targetCommand.startListening(); 264 265 const targets = await targetCommand.getAllTargets(targetCommand.ALL_TYPES); 266 is(targets.length, 1, "Got a unique target"); 267 const targetFront = targets[0]; 268 is(targetFront, targetCommand.targetFront, "The first is the top level one"); 269 is( 270 targetFront.targetType, 271 targetCommand.TYPES.WORKER, 272 "the worker target is of worker type" 273 ); 274 is(targetFront.isTopLevel, true, "This is flagged as top level"); 275 276 targetCommand.destroy(); 277 278 // Calling CommandsFactory.forWorker, will call RootFront.getWorker 279 // which will spawn lots of worker legacy code, firing lots of requests, 280 // which may still be pending 281 await commands.waitForRequestsToSettle(); 282 283 await commands.destroy(); 284 worker.terminate(); 285 }