1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
<!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, reject) {
let count = 0;
frame.addEventListener("load", function listener(e) {
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>
|