diff options
Diffstat (limited to 'devtools/server/tests/browser/browser_watcher-watchTargets-frames.js')
-rw-r--r-- | devtools/server/tests/browser/browser_watcher-watchTargets-frames.js | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js b/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js new file mode 100644 index 0000000000..1e7f502f2c --- /dev/null +++ b/devtools/server/tests/browser/browser_watcher-watchTargets-frames.js @@ -0,0 +1,260 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test Watcher actor against frames. + */ + +"use strict"; + +const TEST_DOC_URL = MAIN_DOMAIN + "doc_iframe.html"; + +// URL of the <iframe> already loaded in doc_iframe.html (the top level test document) +const TEST_DOC_URL1 = + MAIN_DOMAIN.replace("test1.example.org", "example.com") + + "doc_iframe_content.html"; + +// URL of an <iframe> dynamically inserted during the test +const TEST_DOC_URL2 = + MAIN_DOMAIN.replace("test1.example.org", "example.net") + "doc_iframe2.html"; + +add_task(async function() { + const tabTarget = await addTabTarget(TEST_DOC_URL); + const { mainRoot } = tabTarget.client; + + // First test watching all frames. Really all of them. + // From all top level windows, tabs, and any inner remoted iframe. + await testWatchAllFrames(mainRoot); + + // Then use the Watcher to watch only frames of a given tab. + await testWatchOneTabFrames(tabTarget); +}); + +async function testWatchAllFrames(mainRoot) { + info("Assert watchTargets against the whole browser"); + const targets = []; + + const processDescriptor = await mainRoot.getMainProcess(); + const watcher = await processDescriptor.getWatcher(); + + const onNewTarget = target => { + dump( + " (+) target: " + target.url + " -- " + target.browsingContextID + "\n" + ); + targets.push(target); + }; + watcher.on("target-available", onNewTarget); + await watcher.watchTargets("frame"); + + // As it retrieve the whole browser browsing contexts, it is hard to know how many it will fetch + ok(targets.length > 0, "Got multiple frame targets"); + + // Assert that we get a target for the top level tab document + const tabTarget = targets.find(f => f.url == TEST_DOC_URL); + ok(tabTarget, "We get the target for the tab document"); + const tabId = gBrowser.selectedTab.linkedBrowser.browsingContext.id; + is( + tabTarget.browsingContextID, + tabId, + "The tab frame target BrowsingContextID is correct" + ); + + const parentProcessTarget = await processDescriptor.getTarget(); + is( + await parentProcessTarget.getWatcherFront(), + watcher, + "Parent process target getWatcher returns the same watcher" + ); + + const parentTarget = await tabTarget.getParentTarget(); + is( + parentTarget, + parentProcessTarget, + "Tab parent target is the main process target" + ); + + const tabTarget2 = await watcher.getBrowsingContextTarget(tabId); + is(tabTarget, tabTarget2, "getBrowsingContextTarget returns the same target"); + + // Assert that we also fetch the iframe targets + await assertTabIFrames(watcher, targets, tabTarget); + + await watcher.unwatchTargets("frame"); + watcher.off("target-available", onNewTarget); +} + +async function testWatchOneTabFrames(tabTarget) { + info("Assert watchTargets against a given Tab"); + const targets = []; + + const tabDescriptor = tabTarget.descriptorFront; + const watcher = await tabDescriptor.getWatcher(); + + is( + await tabTarget.getWatcherFront(), + watcher, + "Tab target getWatcher returns the same watcher" + ); + + const onNewTarget = target => { + dump( + " (+) target: " + target.url + " -- " + target.browsingContextID + "\n" + ); + targets.push(target); + }; + watcher.on("target-available", onNewTarget); + + await watcher.watchTargets("frame"); + + if (SpecialPowers.useRemoteSubframes) { + is(targets.length, 1, "With fission, one additional target is reported"); + } else { + is(targets.length, 0, "Without fission no additional target is reported"); + } + + await assertTabIFrames(watcher, targets, tabTarget); + + await watcher.unwatchTargets("frame"); + watcher.off("target-available", onNewTarget); +} + +async function assertTabIFrames(watcher, targets, tabTarget) { + // - The existing <iframe> + const existingIframeTarget = targets.find(f => f.url === TEST_DOC_URL1); + const existingIframeId = await ContentTask.spawn( + gBrowser.selectedBrowser, + null, + url => { + const iframe = content.document.querySelector("#remote-frame"); + return iframe.frameLoader.browsingContext.id; + } + ); + + if (SpecialPowers.useRemoteSubframes) { + ok(existingIframeTarget, "And its remote child iframe"); + is( + existingIframeTarget.browsingContextID, + existingIframeId, + "The iframe target BrowsingContextID is correct" + ); + is( + await existingIframeTarget.getWatcherFront(), + watcher, + "Iframe target getWatcher returns the same watcher" + ); + const sameTarget = await watcher.getBrowsingContextTarget(existingIframeId); + is( + sameTarget, + existingIframeTarget, + "getBrowsingContextTarget returns the same target" + ); + const sameTabTarget = await watcher.getParentBrowsingContextTarget( + existingIframeId + ); + is( + tabTarget, + sameTabTarget, + "getParentBrowsingContextTarget returned the tab target" + ); + const existingIframeParentTarget = await existingIframeTarget.getParentTarget(); + is( + existingIframeParentTarget, + tabTarget, + "The iframe parent target is the tab target" + ); + } else { + ok( + !existingIframeTarget, + "Without fission, the iframes are not spawning additional targets" + ); + } + + const originalFrameCount = targets.length; + + if (SpecialPowers.useRemoteSubframes) { + // Assert that the frame target get destroyed and re-created on reload + // This only happens with Fission, as otherwise, the iframe doesn't get a Descriptor/Target anyway. + const onReloadedCreated = watcher.once("target-available"); + const onReloadedDestroyed = watcher.once("target-destroyed"); + SpecialPowers.spawn(BrowsingContext.get(existingIframeId), [], () => { + content.location.reload(); + }); + info("Waiting for previous target destruction"); + const destroyedIframeTarget = await onReloadedDestroyed; + info("Waiting for new target creation"); + const createdIframeTarget = await onReloadedCreated; + is( + destroyedIframeTarget, + existingIframeTarget, + "the destroyed target is the expected one, i.e. the previous one" + ); + isnot( + createdIframeTarget, + existingIframeTarget, + "the created target is the expected one, i.e. a new one" + ); + is( + createdIframeTarget.browsingContextID, + existingIframeId, + "The new iframe target BrowsingContextID is the same" + ); + const createdIframeParentTarget = await createdIframeTarget.getParentTarget(); + is( + createdIframeParentTarget, + tabTarget, + "The created iframe parent target is also the tab target" + ); + } + + // Assert that we also get an event for iframes added after the call to watchTargets + const onCreated = watcher.once("target-available"); + const newIframeId = await ContentTask.spawn( + gBrowser.selectedBrowser, + TEST_DOC_URL2, + url => { + const iframe = content.document.createElement("iframe"); + iframe.src = url; + content.document.body.appendChild(iframe); + return iframe.frameLoader.browsingContext.id; + } + ); + + if (SpecialPowers.useRemoteSubframes) { + await onCreated; + is(targets.length, originalFrameCount + 2, "Got the additional frame"); + + // Match against the BrowsingContext ID as the target is created very early + // and the url isn't set yet when the target is created. + const newIframeTarget = targets.find( + f => f.browsingContextID === newIframeId + ); + ok(newIframeTarget, "We got the target for the new iframe"); + + const newIframeParentTarget = await newIframeTarget.getParentTarget(); + is( + newIframeParentTarget, + tabTarget, + "The new iframe parent target is also the tab target" + ); + + // Assert that we also get notified about destroyed frames + const onDestroyed = watcher.once("target-destroyed"); + await ContentTask.spawn(gBrowser.selectedBrowser, newIframeId, id => { + const browsingContext = BrowsingContext.get(id); + const iframe = browsingContext.embedderElement; + iframe.remove(); + }); + const destroyedTarget = await onDestroyed; + is( + destroyedTarget, + newIframeTarget, + "We got notified about the iframe destruction" + ); + } else { + is( + targets.length, + originalFrameCount, + "Without fission, the iframes are not spawning additional targets" + ); + } +} |