diff options
Diffstat (limited to 'docshell/test/browser/browser_browsingContext-01.js')
-rw-r--r-- | docshell/test/browser/browser_browsingContext-01.js | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/docshell/test/browser/browser_browsingContext-01.js b/docshell/test/browser/browser_browsingContext-01.js new file mode 100644 index 0000000000..d1d6f947ef --- /dev/null +++ b/docshell/test/browser/browser_browsingContext-01.js @@ -0,0 +1,205 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const URL = "about:blank"; + +async function getBrowsingContextId(browser, id) { + return SpecialPowers.spawn(browser, [id], async function(id) { + let contextId = content.window.docShell.browsingContext.id; + + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(id); + if (target) { + contextId = target.docShell.browsingContext.id; + break; + } + + frames = frames.concat(Array.from(frame.frames)); + } + + return contextId; + }); +} + +async function addFrame(browser, id, parentId) { + return SpecialPowers.spawn(browser, [{ parentId, id }], async function({ + parentId, + id, + }) { + let parent = null; + if (parentId) { + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(parentId); + if (target) { + parent = target.contentWindow.document.body; + break; + } + frames = frames.concat(Array.from(frame.frames)); + } + } else { + parent = content.document.body; + } + + let frame = await new Promise(resolve => { + let frame = content.document.createElement("iframe"); + frame.id = id || ""; + frame.url = "about:blank"; + frame.onload = () => resolve(frame); + parent.appendChild(frame); + }); + + return frame.contentWindow.docShell.browsingContext.id; + }); +} + +async function removeFrame(browser, id) { + return SpecialPowers.spawn(browser, [id], async function(id) { + let frames = [content.window]; + while (frames.length) { + let frame = frames.pop(); + let target = frame.document.getElementById(id); + if (target) { + target.remove(); + break; + } + + frames = frames.concat(Array.from(frame.frames)); + } + }); +} + +function getBrowsingContextById(id) { + return BrowsingContext.get(id); +} + +add_task(async function() { + await BrowserTestUtils.withNewTab({ gBrowser, url: URL }, async function( + browser + ) { + let topId = await getBrowsingContextId(browser, ""); + let topContext = getBrowsingContextById(topId); + isnot(topContext, null); + is(topContext.parent, null); + is( + topId, + browser.browsingContext.id, + "<browser> has the correct browsingContext" + ); + is( + browser.browserId, + topContext.browserId, + "browsing context should have a correct <browser> id" + ); + + let id0 = await addFrame(browser, "frame0"); + let browsingContext0 = getBrowsingContextById(id0); + isnot(browsingContext0, null); + is(browsingContext0.parent, topContext); + + await removeFrame(browser, "frame0"); + + is(topContext.children.indexOf(browsingContext0), -1); + + // TODO(farre): Handle browsingContext removal [see Bug 1486719]. + todo_isnot(browsingContext0.parent, topContext); + }); +}); + +add_task(async function() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" + ) + "dummy_page.html", + }, + async function(browser) { + let path = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" + ); + await SpecialPowers.spawn(browser, [path], async function(path) { + function waitForMessage(command) { + let r; + let p = new Promise(resolve => { + content.window.addEventListener( + "message", + e => resolve({ result: r, event: e }), + { once: true } + ); + }); + r = command(); + return p; + } + + // Open a new window and wait for the message. + let { result: win, event: e1 } = await waitForMessage(_ => + content.window.open(path + "onpageshow_message.html") + ); + + is(e1.data, "pageshow"); + + { + // Create, attach and load an iframe into the window's document. + let frame = win.document.createElement("iframe"); + win.document.body.appendChild(frame); + frame.src = "dummy_page.html"; + await ContentTaskUtils.waitForEvent(frame, "load"); + } + + is(win.frames.length, 1, "Here we should have an iframe"); + + // The frame should have expected browsing context and docshell. + let frameBC = win.frames[0].docShell.browsingContext; + let winDocShell = win.frames[0].docShell; + + // Navigate the window and wait for the message. + let { event: e2 } = await waitForMessage( + _ => (win.location = path + "onload_message.html") + ); + + is(e2.data, "load"); + is(win.frames.length, 0, "Here there shouldn't be an iframe"); + + // Return to the previous document. N.B. we expect to trigger + // BFCache here, hence we wait for pageshow. + let { event: e3 } = await waitForMessage(_ => win.history.back()); + + is(e3.data, "pageshow"); + is(win.frames.length, 1, "And again there should be an iframe"); + + is(winDocShell, win.frames[0].docShell, "BF cache cached docshell"); + is( + frameBC, + win.frames[0].docShell.browsingContext, + "BF cache cached BC" + ); + is( + frameBC.id, + win.frames[0].docShell.browsingContext.id, + "BF cached BC's have same id" + ); + is( + win.docShell.browsingContext.children[0], + frameBC, + "BF cached BC's should still be a child of its parent" + ); + is( + win.docShell.browsingContext, + frameBC.parent, + "BF cached BC's should still be a connected to its parent" + ); + + win.close(); + }); + } + ); +}); |