/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; // Test the TargetCommand API with changes made to devtools.browsertoolbox.scope const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(`
`); add_task(async function () { // Do not run this test when both fission and EFT is disabled as it changes // the number of targets if (!isFissionEnabled() && !isEveryFrameTargetEnabled()) { return; } // Disable the preloaded process as it gets created lazily and may interfere // with process count assertions await pushPref("dom.ipc.processPrelaunch.enabled", false); // This preference helps destroying the content process when we close the tab await pushPref("dom.ipc.keepProcessesAlive.web", 1); // First test with multiprocess debugging enabled await pushPref("devtools.browsertoolbox.scope", "everything"); const commands = await CommandsFactory.forMainProcess(); const targetCommand = commands.targetCommand; await targetCommand.startListening(); const { TYPES } = targetCommand; const targets = new Set(); const destroyedTargetIsModeSwitchingMap = new Map(); const onAvailable = async ({ targetFront }) => { targets.add(targetFront); }; const onDestroyed = ({ targetFront, isModeSwitching }) => { destroyedTargetIsModeSwitchingMap.set(targetFront, isModeSwitching); targets.delete(targetFront); }; await targetCommand.watchTargets({ types: [TYPES.PROCESS, TYPES.FRAME], onAvailable, onDestroyed, }); Assert.greater(targets.size, 1, "We get many targets"); info("Open a tab in a new content process"); await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: TEST_URL, forceNewProcess: true, }); const newTabProcessID = gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal .osPid; const newTabInnerWindowId = gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal .innerWindowId; info("Wait for the tab content process target"); const processTarget = await waitFor(() => [...targets].find( target => target.targetType == TYPES.PROCESS && target.processID == newTabProcessID ) ); info("Wait for the tab window global target"); const windowGlobalTarget = await waitFor(() => [...targets].find( target => target.targetType == TYPES.FRAME && target.innerWindowId == newTabInnerWindowId ) ); let multiprocessTargetCount = targets.size; info("Disable multiprocess debugging"); await pushPref("devtools.browsertoolbox.scope", "parent-process"); info("Wait for all targets but top level and workers to be destroyed"); await waitFor(() => [...targets].every( target => target == targetCommand.targetFront || target.targetType == TYPES.WORKER ) ); ok(processTarget.isDestroyed(), "The process target is destroyed"); ok( destroyedTargetIsModeSwitchingMap.get(processTarget), "isModeSwitching was passed to onTargetDestroyed and is true for the process target" ); ok(windowGlobalTarget.isDestroyed(), "The window global target is destroyed"); ok( destroyedTargetIsModeSwitchingMap.get(windowGlobalTarget), "isModeSwitching was passed to onTargetDestroyed and is true for the window global target" ); info("Open a second tab in a new content process"); const parentProcessTargetCount = targets.size; await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: TEST_URL, forceNewProcess: true, }); await wait(1000); is( parentProcessTargetCount, targets.size, "The new tab process should be ignored and no target be created" ); info("Re-enable multiprocess debugging"); await pushPref("devtools.browsertoolbox.scope", "everything"); // The second tab relates to one content process target and one window global target multiprocessTargetCount += 2; await waitFor( () => targets.size == multiprocessTargetCount, "Wait for all targets we used to have before disable multiprocess debugging" ); info("Wait for the tab content process target to be available again"); ok( [...targets].some( target => target.targetType == TYPES.PROCESS && target.processID == newTabProcessID ), "We have the tab content process target" ); info("Wait for the tab window global target to be available again"); ok( [...targets].some( target => target.targetType == TYPES.FRAME && target.innerWindowId == newTabInnerWindowId ), "We have the tab window global target" ); info("Open a third tab in a new content process"); await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: TEST_URL, forceNewProcess: true, }); const thirdTabProcessID = gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal .osPid; const thirdTabInnerWindowId = gBrowser.selectedTab.linkedBrowser.browsingContext.currentWindowGlobal .innerWindowId; info("Wait for the third tab content process target"); await waitFor(() => [...targets].find( target => target.targetType == TYPES.PROCESS && target.processID == thirdTabProcessID ) ); info("Wait for the third tab window global target"); await waitFor(() => [...targets].find( target => target.targetType == TYPES.FRAME && target.innerWindowId == thirdTabInnerWindowId ) ); targetCommand.destroy(); // Wait for all the targets to be fully attached so we don't have pending requests. await Promise.all( targetCommand.getAllTargets(targetCommand.ALL_TYPES).map(t => t.initialized) ); await commands.destroy(); });