/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; // Test that the ResourceCommand clears its pending events for resources emitted from // target destroyed when devtools.browsertoolbox.scope is updated. 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()) { ok(true, "Don't go further is both Fission and EFT are disabled"); 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); // Start 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 onAvailable = async ({ targetFront }) => { targets.add(targetFront); }; const onDestroyed = () => {}; await targetCommand.watchTargets({ types: [TYPES.PROCESS, TYPES.FRAME], onAvailable, onDestroyed, }); info("Open a tab in a new content process"); const firstTab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: TEST_URL, forceNewProcess: true, }); const newTabInnerWindowId = firstTab.linkedBrowser.browsingContext.currentWindowGlobal.innerWindowId; info("Wait for the tab window global target"); const windowGlobalTarget = await waitFor(() => [...targets].find( target => target.targetType == TYPES.FRAME && target.innerWindowId == newTabInnerWindowId ) ); let gotTabResource = false; const onResourceAvailable = resources => { for (const resource of resources) { if (resource.targetFront == windowGlobalTarget) { gotTabResource = true; if (resource.targetFront.isDestroyed()) { ok( false, "we shouldn't get resources for the target that was destroyed when switching mode" ); } } } }; info("Start listening for resources"); await commands.resourceCommand.watchResources( [commands.resourceCommand.TYPES.CONSOLE_MESSAGE], { onAvailable: onResourceAvailable, ignoreExistingResources: true, } ); // Emit logs every ms to fill up the resourceCommand resource queue (pendingEvents) const intervalId = await SpecialPowers.spawn( firstTab.linkedBrowser, [], () => { let counter = 0; return content.wrappedJSObject.setInterval(() => { counter++; content.wrappedJSObject.console.log("STREAM_" + counter); }, 1); } ); info("Wait until we get the first resource"); await waitFor(() => gotTabResource); info("Disable multiprocess debugging"); await pushPref("devtools.browsertoolbox.scope", "parent-process"); info("Wait for the tab target to be destroyed"); await waitFor(() => windowGlobalTarget.isDestroyed()); info("Wait for a bit so any throttled action would have the time to occur"); await wait(1000); // Stop listening for resources await commands.resourceCommand.unwatchResources( [commands.resourceCommand.TYPES.CONSOLE_MESSAGE], { onAvailable: onResourceAvailable, } ); // And stop the interval await SpecialPowers.spawn(firstTab.linkedBrowser, [intervalId], id => { content.wrappedJSObject.clearInterval(id); }); targetCommand.destroy(); await commands.destroy(); });