diff options
Diffstat (limited to '')
-rw-r--r-- | remote/test/browser/page/browser_frameDetached.js | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/remote/test/browser/page/browser_frameDetached.js b/remote/test/browser/page/browser_frameDetached.js new file mode 100644 index 0000000000..659898c283 --- /dev/null +++ b/remote/test/browser/page/browser_frameDetached.js @@ -0,0 +1,180 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const DOC = toDataURL("<div>foo</div>"); +const DOC_IFRAME_MULTI = toDataURL(` + <iframe src='data:text/html,foo'></iframe> + <iframe src='data:text/html,bar'></iframe> +`); +const DOC_IFRAME_NESTED = toDataURL(` + <iframe src="${DOC_IFRAME_MULTI}"></iframe> +`); + +// Disable bfcache to force documents to be destroyed on navigation +Services.prefs.setIntPref("browser.sessionhistory.max_total_viewers", 0); +registerCleanupFunction(() => { + Services.prefs.clearUserPref("browser.sessionhistory.max_total_viewers"); +}); + +add_task(async function noEventWhenPageDomainDisabled({ client }) { + info("Navigate to a page with nested iframes"); + await loadURL(DOC_IFRAME_NESTED); + + await runFrameDetachedTest(client, 0, async () => { + info("Navigate away from a page with an iframe"); + await loadURL(DOC); + }); +}); + +add_task(async function noEventAfterPageDomainDisabled({ client }) { + const { Page } = client; + + info("Navigate to a page with nested iframes"); + await loadURL(DOC_IFRAME_NESTED); + + await Page.enable(); + await Page.disable(); + + await runFrameDetachedTest(client, 0, async () => { + info("Navigate away to a page with no iframes"); + await loadURL(DOC); + }); +}); + +add_task(async function noEventWhenNavigatingWithNoFrames({ client }) { + const { Page } = client; + + await Page.enable(); + + info("Navigate to a page with no iframes"); + await loadURL(DOC); + + await runFrameDetachedTest(client, 0, async () => { + info("Navigate away to a page with no iframes"); + await loadURL(DOC); + }); +}); + +add_task(async function eventWhenNavigatingWithFrames({ client }) { + const { Page } = client; + + info("Navigate to a page with iframes"); + await loadURL(DOC_IFRAME_MULTI); + + await Page.enable(); + + await runFrameDetachedTest(client, 2, async () => { + info("Navigate away to a page with no iframes"); + await loadURL(DOC); + }); +}); + +add_task(async function eventWhenNavigatingWithNestedFrames({ client }) { + const { Page } = client; + + info("Navigate to a page with nested iframes"); + await loadURL(DOC_IFRAME_NESTED); + + await Page.enable(); + + await runFrameDetachedTest(client, 3, async () => { + info("Navigate away to a page with no iframes"); + await loadURL(DOC); + }); +}); + +add_task(async function eventWhenDetachingFrame({ client }) { + const { Page } = client; + + info("Navigate to a page with iframes"); + await loadURL(DOC_IFRAME_MULTI); + + await Page.enable(); + + await runFrameDetachedTest(client, 1, async () => { + // Remove the single frame from the page + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + const frame = content.document.getElementsByTagName("iframe")[0]; + frame.remove(); + }); + }); +}); + +add_task(async function eventWhenDetachingNestedFrames({ client }) { + const { Page, Runtime } = client; + + info("Navigate to a page with nested iframes"); + await loadURL(DOC_IFRAME_NESTED); + + await Page.enable(); + await Runtime.enable(); + + const { context } = await Runtime.executionContextCreated(); + + await runFrameDetachedTest(client, 3, async () => { + // Remove top-frame, which also removes any nested frames + await evaluate(client, context.id, async () => { + const frame = document.getElementsByTagName("iframe")[0]; + frame.remove(); + }); + }); +}); + +async function runFrameDetachedTest(client, expectedEventCount, callback) { + const { Page } = client; + + const DETACHED = "Page.frameDetached"; + + const history = new RecordEvents(expectedEventCount); + history.addRecorder({ + event: Page.frameDetached, + eventName: DETACHED, + messageFn: payload => { + return `Received ${DETACHED} for frame id ${payload.frameId}`; + }, + }); + + const framesBefore = await getFlattenedFrameTree(client); + await callback(); + const framesAfter = await getFlattenedFrameTree(client); + + const frameDetachedEvents = await history.record(); + + if (expectedEventCount == 0) { + is(frameDetachedEvents.length, 0, "Got no frame detached event"); + return; + } + + // check how many frames were attached or detached + const count = Math.abs(framesBefore.size - framesAfter.size); + + is(count, expectedEventCount, "Expected amount of frames detached"); + is( + frameDetachedEvents.length, + count, + "Received the expected amount of frameDetached events" + ); + + // extract the new or removed frames + const framesAll = new Map([...framesBefore, ...framesAfter]); + const expectedFrames = new Map( + [...framesAll].filter(([key, _value]) => { + return framesBefore.has(key) && !framesAfter.has(key); + }) + ); + + frameDetachedEvents.forEach(({ payload }) => { + const { frameId } = payload; + + info(`Check frame id ${frameId}`); + const expectedFrame = expectedFrames.get(frameId); + + is( + frameId, + expectedFrame.id, + "Got expected frame id for frameDetached event" + ); + }); +} |