<!
DOCTYPE html>
<
html lang=
"en">
<
head>
<
meta charset=
"utf-8">
<
title>Bug 1326251</
title>
<
script>
var bc = new BroadcastChannel(
"file_bug1326251");
bc.onmessage = function(event) {
if (
"nextTest" in event.data) {
testSteps[event.data.nextTest]();
}
}
function is(val1, val2, msg) {
bc.postMessage({type:
"is", value1: val1, value2: val2, message: msg});
}
function ok(val, msg) {
bc.postMessage({type:
"ok", value: val, message: msg});
}
const BASE_URL =
"http://mochi.test:8888/tests/docshell/test/navigation/";
let testSteps = [
async function() {
// Test 1: Create dynamic
iframe with bfcache enabled.
// Navigate static / dynamic iframes, then navigate top level window
// and navigate back. Both iframes should still exist with history
// entries preserved.
window.onunload = null; // enable bfcache
await createDynamicFrame(document);
await loadUriInFrame(document.getElementById(
"staticFrame"),
"frame1.html");
await loadUriInFrame(document.getElementById(
"dynamicFrame"),
"frame1.html");
await loadUriInFrame(document.getElementById(
"staticFrame"),
"frame2.html");
await loadUriInFrame(document.getElementById(
"dynamicFrame"),
"frame2.html");
is(history.length, 5,
"history.length");
window.location =
"goback.html";
},
async function() {
let webNav = SpecialPowers.wrap(window)
.docShell
.QueryInterface(SpecialPowers.Ci.nsIWebNavigation);
let shistory = webNav.sessionHistory;
is(webNav.canGoForward, true,
"canGoForward");
is(shistory.index, 4,
"shistory.index");
is(history.length, 6,
"history.length");
is(document.getElementById(
"staticFrame").contentWindow.location.href, BASE_URL +
"frame2.html",
"staticFrame location");
is(document.getElementById(
"dynamicFrame").contentWindow.location.href, BASE_URL +
"frame2.html",
"dynamicFrame location");
// Test 2: Load another page in dynamic
iframe, canGoForward should be
// false.
await loadUriInFrame(document.getElementById(
"dynamicFrame"),
"frame3.html");
is(webNav.canGoForward, false,
"canGoForward");
is(shistory.index, 5,
"shistory.index");
is(history.length, 6,
"history.length");
// Test 3: Navigate to antoher page with bfcache disabled, all dynamic
//
iframe entries should be removed.
window.onunload = function() {}; // disable bfcache
window.location =
"goback.html";
},
async function() {
let windowWrap = SpecialPowers.wrap(window);
let docShell = windowWrap.docShell;
let shistory = docShell.QueryInterface(SpecialPowers.Ci.nsIWebNavigation)
.sessionHistory;
// Now staticFrame has frame0 -> frame1 -> frame2.
if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) {
// *EntryIndex attributes aren
't meaningful when the session history
// lives in the parent process.
is(docShell.previousEntryIndex, 3,
"docShell.previousEntryIndex");
is(docShell.loadedEntryIndex, 2,
"docShell.loadedEntryIndex");
}
is(shistory.index, 2,
"shistory.index");
is(history.length, 4,
"history.length");
is(document.getElementById(
"staticFrame").contentWindow.location.href, BASE_URL +
"frame2.html",
"staticFrame location");
ok(!document.getElementById(
"dynamicFrame"),
"dynamicFrame should not exist");
// Test 4: Load a nested
frame in the static
frame, navigate the inner
// static
frame, add a inner dynamic
frame and navigate the dynamic
//
frame. Then navigate the outer static
frame and go back. The inner
//
iframe should show the last entry of inner static
frame.
let staticFrame = document.getElementById(
"staticFrame");
staticFrame.width =
"320px";
staticFrame.height =
"360px";
await loadUriInFrame(staticFrame,
"iframe_static.html");
let innerStaticFrame = staticFrame.contentDocument.getElementById(
"staticFrame");
await loadUriInFrame(innerStaticFrame,
"frame1.html");
let innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument,
"frame2.html");
await loadUriInFrame(innerDynamicFrame,
"frame3.html");
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static
// innerStaticFrame: frame0 -> frame1
// innerDynamicFrame: frame2 -> frame3
is(shistory.index, 5,
"shistory.index");
is(history.length, 6,
"history.length");
// Wait for 2 load events - navigation and goback.
let onloadPromise = awaitOnload(staticFrame, 2);
await loadUriInFrame(staticFrame,
"goback.html");
await onloadPromise;
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static -> goback
// innerStaticFrame: frame0 -> frame1
is(shistory.index, 4,
"shistory.index");
is(history.length, 6,
"history.length");
innerStaticFrame = staticFrame.contentDocument.getElementById(
"staticFrame");
is(innerStaticFrame.contentDocument.location.href, BASE_URL +
"frame1.html",
"innerStaticFrame location");
ok(!staticFrame.contentDocument.getElementById(
"dynamicFrame"),
"innerDynamicFrame should not exist");
// Test 5: Insert and navigate inner dynamic
frame again with bfcache
// enabled, and navigate top level window to a special page which will
// evict bfcache then goback. Verify that dynamic entries are correctly
// removed in this case.
window.onunload = null; // enable bfcache
staticFrame.width =
"320px";
staticFrame.height =
"360px";
innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument,
"frame2.html");
await loadUriInFrame(innerDynamicFrame,
"frame3.html");
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static
// innerStaticFrame: frame0 -> frame1
// innerDynamicFrame: frame2 -> frame3
is(shistory.index, 5,
"shistory.index");
is(history.length, 6,
"history.length");
window.location =
"file_bug1326251_evict_cache.html";
},
async function() {
let windowWrap = SpecialPowers.wrap(window);
let docShell = windowWrap.docShell;
let shistory = docShell.QueryInterface(SpecialPowers.Ci.nsIWebNavigation)
.sessionHistory;
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static
// innerStaticFrame: frame0 -> frame1
if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) {
// *EntryIndex attributes aren
't meaningful when the session history
// lives in the parent process.
is(docShell.previousEntryIndex, 5,
"docShell.previousEntryIndex");
is(docShell.loadedEntryIndex, 4,
"docShell.loadedEntryIndex");
}
is(shistory.index, 4,
"shistory.index");
is(history.length, 6,
"history.length");
let staticFrame = document.getElementById(
"staticFrame");
let innerStaticFrame = staticFrame.contentDocument.getElementById(
"staticFrame");
is(innerStaticFrame.contentDocument.location.href, BASE_URL +
"frame1.html",
"innerStaticFrame location");
ok(!staticFrame.contentDocument.getElementById(
"dynamicFrame"),
"innerDynamicFrame should not exist");
// Test 6: Insert and navigate inner dynamic
frame and then reload outer
//
frame. Verify that inner dynamic
frame entries are all removed.
staticFrame.width =
"320px";
staticFrame.height =
"360px";
let innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument,
"frame2.html");
await loadUriInFrame(innerDynamicFrame,
"frame3.html");
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static
// innerStaticFrame: frame0 -> frame1
// innerDynamicFrame: frame2 -> frame3
is(shistory.index, 5,
"shistory.index");
is(history.length, 6,
"history.length");
let staticFrameLoadPromise = new Promise(resolve => {
staticFrame.onload = resolve;
});
staticFrame.contentWindow.location.reload();
await staticFrameLoadPromise;
// staticFrame: frame0 -> frame1 -> frame2 -> iframe_static
// innerStaticFrame: frame0 -> frame1
is(shistory.index, 4,
"shistory.index");
is(history.length, 5,
"history.length");
innerStaticFrame = staticFrame.contentDocument.getElementById(
"staticFrame");
is(innerStaticFrame.contentDocument.location.href, BASE_URL +
"frame1.html",
"innerStaticFrame location");
ok(!staticFrame.contentDocument.getElementById(
"dynamicFrame"),
"innerDynamicFrame should not exist");
bc.postMessage(
"finishTest");
bc.close();
window.close();
},
];
function awaitOnload(
frame, occurances = 1) {
return new Promise(function(resolve) {
let count = 0;
frame.addEventListener(
"load", function listener() {
if (++count == occurances) {
frame.removeEventListener(
"load", listener);
setTimeout(resolve, 0);
}
});
});
}
async function createDynamicFrame(targetDocument, frameSrc =
"frame0.html") {
let dynamicFrame = targetDocument.createElement(
"iframe");
let onloadPromise = awaitOnload(dynamicFrame);
dynamicFrame.id =
"dynamicFrame";
dynamicFrame.src = frameSrc;
let container = targetDocument.getElementById(
"frameContainer");
container.appendChild(dynamicFrame);
await onloadPromise;
return dynamicFrame;
}
async function loadUriInFrame(
frame, uri) {
let onloadPromise = awaitOnload(
frame);
frame.src = uri;
return onloadPromise;
}
function test() {
bc.postMessage(
"requestNextTest");
}
</
script>
</
head>
<
body onpageshow=
"test();">
<
div id=
"frameContainer">
<
iframe id=
"staticFrame" src=
"frame0.html"></
iframe>
</
div>
</
body>
</
html>