browser_target_command_scope_flag.js (6962B)
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 changes made to devtools.browsertoolbox.scope 7 8 const TEST_URL = 9 "data:text/html;charset=utf-8," + encodeURIComponent(`<div id="test"></div>`); 10 11 add_task(async function () { 12 // Disable the preloaded process as it gets created lazily and may interfere 13 // with process count assertions 14 await pushPref("dom.ipc.processPrelaunch.enabled", false); 15 // This preference helps destroying the content process when we close the tab 16 await pushPref("dom.ipc.keepProcessesAlive.web", 1); 17 18 // First test with multiprocess debugging enabled 19 await pushPref("devtools.browsertoolbox.scope", "everything"); 20 21 const commands = await CommandsFactory.forMainProcess(); 22 const targetCommand = commands.targetCommand; 23 await targetCommand.startListening(); 24 25 // Pass any configuration, in order to ensure attaching all the thread actors 26 await commands.threadConfigurationCommand.updateConfiguration({ 27 skipBreakpoints: false, 28 }); 29 30 const { TYPES } = targetCommand; 31 32 const targets = new Set(); 33 const destroyedTargetIsModeSwitchingMap = new Map(); 34 const onAvailable = async ({ targetFront }) => { 35 targets.add(targetFront); 36 }; 37 const onDestroyed = ({ targetFront, isModeSwitching }) => { 38 destroyedTargetIsModeSwitchingMap.set(targetFront, isModeSwitching); 39 targets.delete(targetFront); 40 }; 41 await targetCommand.watchTargets({ 42 types: [TYPES.PROCESS, TYPES.FRAME], 43 onAvailable, 44 onDestroyed, 45 }); 46 Assert.greater(targets.size, 1, "We get many targets"); 47 48 info("Open a tab in a new content process"); 49 await BrowserTestUtils.openNewForegroundTab({ 50 gBrowser, 51 url: TEST_URL, 52 forceNewProcess: true, 53 }); 54 55 // Verify that only PROCESS and top target have their thread actor attached. 56 // We especially care about having the FRAME targets to not be attached, 57 // otherwise we would have two thread actor debugging the same thread 58 // with the PROCESS target already debugging all FRAME documents. 59 for (const target of targets) { 60 const threadFront = await target.getFront("thread"); 61 const isAttached = await threadFront.isAttached(); 62 if (target.targetType == TYPES.PROCESS) { 63 ok(isAttached, "All process targets are attached"); 64 } else if (target.isTopLevel) { 65 ok(isAttached, "The top level target is attached"); 66 } else { 67 ok( 68 !isAttached, 69 "The frame targets should not be attached in multiprocess mode" 70 ); 71 } 72 } 73 74 const firstTabProcessID = 75 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 76 .osPid; 77 const firstTabInnerWindowId = 78 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 79 .innerWindowId; 80 81 info("Wait for the tab content process target"); 82 const processTarget = await waitFor(() => 83 [...targets].find( 84 target => 85 target.targetType == TYPES.PROCESS && 86 target.processID == firstTabProcessID 87 ) 88 ); 89 90 info("Wait for the tab window global target"); 91 const windowGlobalTarget = await waitFor(() => 92 [...targets].find( 93 target => 94 target.targetType == TYPES.FRAME && 95 target.innerWindowId == firstTabInnerWindowId 96 ) 97 ); 98 99 info("Disable multiprocess debugging"); 100 await pushPref("devtools.browsertoolbox.scope", "parent-process"); 101 102 info("Wait for all targets but top level and workers to be destroyed"); 103 await waitFor(() => 104 [...targets].every( 105 target => 106 target == targetCommand.targetFront || target.targetType == TYPES.WORKER 107 ) 108 ); 109 110 ok(processTarget.isDestroyed(), "The process target is destroyed"); 111 ok( 112 destroyedTargetIsModeSwitchingMap.get(processTarget), 113 "isModeSwitching was passed to onTargetDestroyed and is true for the process target" 114 ); 115 ok(windowGlobalTarget.isDestroyed(), "The window global target is destroyed"); 116 ok( 117 destroyedTargetIsModeSwitchingMap.get(windowGlobalTarget), 118 "isModeSwitching was passed to onTargetDestroyed and is true for the window global target" 119 ); 120 121 info("Open a second tab in a new content process"); 122 const parentProcessTargetCount = targets.size; 123 await BrowserTestUtils.openNewForegroundTab({ 124 gBrowser, 125 url: TEST_URL, 126 forceNewProcess: true, 127 }); 128 const secondTabProcessID = 129 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 130 .osPid; 131 const secondTabInnerWindowId = 132 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 133 .innerWindowId; 134 135 await wait(1000); 136 is( 137 parentProcessTargetCount, 138 targets.size, 139 "The new tab process should be ignored and no target be created" 140 ); 141 142 info("Re-enable multiprocess debugging"); 143 await pushPref("devtools.browsertoolbox.scope", "everything"); 144 145 await waitFor(() => { 146 return [...targets].some( 147 target => 148 target.targetType == TYPES.PROCESS && 149 target.processID == firstTabProcessID 150 ); 151 }, "Wait for the first tab content process target to be available again"); 152 153 await waitFor(() => { 154 return [...targets].some( 155 target => 156 target.targetType == TYPES.FRAME && 157 target.innerWindowId == firstTabInnerWindowId 158 ); 159 }, "Wait for the first tab frame target to be available again"); 160 161 await waitFor(() => { 162 return [...targets].some( 163 target => 164 target.targetType == TYPES.PROCESS && 165 target.processID == secondTabProcessID 166 ); 167 }, "Wait for the second tab content process target to be available again"); 168 169 await waitFor(() => { 170 return [...targets].some( 171 target => 172 target.targetType == TYPES.FRAME && 173 target.innerWindowId == secondTabInnerWindowId 174 ); 175 }, "Wait for the second tab frame target to be available again"); 176 177 info("Open a third tab in a new content process"); 178 await BrowserTestUtils.openNewForegroundTab({ 179 gBrowser, 180 url: TEST_URL, 181 forceNewProcess: true, 182 }); 183 184 const thirdTabProcessID = 185 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 186 .osPid; 187 const thirdTabInnerWindowId = 188 gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal 189 .innerWindowId; 190 191 info("Wait for the third tab content process target"); 192 await waitFor(() => 193 [...targets].find( 194 target => 195 target.targetType == TYPES.PROCESS && 196 target.processID == thirdTabProcessID 197 ) 198 ); 199 200 info("Wait for the third tab window global target"); 201 await waitFor(() => 202 [...targets].find( 203 target => 204 target.targetType == TYPES.FRAME && 205 target.innerWindowId == thirdTabInnerWindowId 206 ) 207 ); 208 209 targetCommand.destroy(); 210 211 // Wait for all the targets to be fully attached so we don't have pending requests. 212 await Promise.all( 213 targetCommand.getAllTargets(targetCommand.ALL_TYPES).map(t => t.initialized) 214 ); 215 216 await commands.destroy(); 217 });