file_bug1326251.html (10618B)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <title>Bug 1326251</title> 6 <script> 7 var bc = new BroadcastChannel("file_bug1326251"); 8 bc.onmessage = function(event) { 9 if ("nextTest" in event.data) { 10 testSteps[event.data.nextTest](); 11 } 12 } 13 14 function is(val1, val2, msg) { 15 bc.postMessage({type: "is", value1: val1, value2: val2, message: msg}); 16 } 17 18 function ok(val, msg) { 19 bc.postMessage({type: "ok", value: val, message: msg}); 20 } 21 22 const BASE_URL = "http://mochi.test:8888/tests/docshell/test/navigation/"; 23 let testSteps = [ 24 async function() { 25 // Test 1: Create dynamic iframe with bfcache enabled. 26 // Navigate static / dynamic iframes, then navigate top level window 27 // and navigate back. Both iframes should still exist with history 28 // entries preserved. 29 window.onunload = null; // enable bfcache 30 await createDynamicFrame(document); 31 await loadUriInFrame(document.getElementById("staticFrame"), "frame1.html"); 32 await loadUriInFrame(document.getElementById("dynamicFrame"), "frame1.html"); 33 await loadUriInFrame(document.getElementById("staticFrame"), "frame2.html"); 34 await loadUriInFrame(document.getElementById("dynamicFrame"), "frame2.html"); 35 is(history.length, 5, "history.length"); 36 window.location = "goback.html"; 37 }, 38 async function() { 39 let webNav = SpecialPowers.wrap(window) 40 .docShell 41 .QueryInterface(SpecialPowers.Ci.nsIWebNavigation); 42 let shistory = webNav.sessionHistory; 43 is(webNav.canGoForward, true, "canGoForward"); 44 is(shistory.index, 4, "shistory.index"); 45 is(history.length, 6, "history.length"); 46 is(document.getElementById("staticFrame").contentWindow.location.href, BASE_URL + "frame2.html", "staticFrame location"); 47 is(document.getElementById("dynamicFrame").contentWindow.location.href, BASE_URL + "frame2.html", "dynamicFrame location"); 48 49 // Test 2: Load another page in dynamic iframe, canGoForward should be 50 // false. 51 await loadUriInFrame(document.getElementById("dynamicFrame"), "frame3.html"); 52 is(webNav.canGoForward, false, "canGoForward"); 53 is(shistory.index, 5, "shistory.index"); 54 is(history.length, 6, "history.length"); 55 56 // Test 3: Navigate to antoher page with bfcache disabled, all dynamic 57 // iframe entries should be removed. 58 window.onunload = function() {}; // disable bfcache 59 window.location = "goback.html"; 60 }, 61 async function() { 62 let windowWrap = SpecialPowers.wrap(window); 63 let docShell = windowWrap.docShell; 64 let shistory = docShell.QueryInterface(SpecialPowers.Ci.nsIWebNavigation) 65 .sessionHistory; 66 // Now staticFrame has frame0 -> frame1 -> frame2. 67 if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { 68 // *EntryIndex attributes aren't meaningful when the session history 69 // lives in the parent process. 70 is(docShell.previousEntryIndex, 3, "docShell.previousEntryIndex"); 71 is(docShell.loadedEntryIndex, 2, "docShell.loadedEntryIndex"); 72 } 73 is(shistory.index, 2, "shistory.index"); 74 is(history.length, 4, "history.length"); 75 is(document.getElementById("staticFrame").contentWindow.location.href, BASE_URL + "frame2.html", "staticFrame location"); 76 ok(!document.getElementById("dynamicFrame"), "dynamicFrame should not exist"); 77 78 // Test 4: Load a nested frame in the static frame, navigate the inner 79 // static frame, add a inner dynamic frame and navigate the dynamic 80 // frame. Then navigate the outer static frame and go back. The inner 81 // iframe should show the last entry of inner static frame. 82 let staticFrame = document.getElementById("staticFrame"); 83 staticFrame.width = "320px"; 84 staticFrame.height = "360px"; 85 await loadUriInFrame(staticFrame, "iframe_static.html"); 86 let innerStaticFrame = staticFrame.contentDocument.getElementById("staticFrame"); 87 await loadUriInFrame(innerStaticFrame, "frame1.html"); 88 let innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument, "frame2.html"); 89 await loadUriInFrame(innerDynamicFrame, "frame3.html"); 90 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static 91 // innerStaticFrame: frame0 -> frame1 92 // innerDynamicFrame: frame2 -> frame3 93 is(shistory.index, 5, "shistory.index"); 94 is(history.length, 6, "history.length"); 95 96 // Wait for 2 load events - navigation and goback. 97 let onloadPromise = awaitOnload(staticFrame, 2); 98 await loadUriInFrame(staticFrame, "goback.html"); 99 await onloadPromise; 100 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static -> goback 101 // innerStaticFrame: frame0 -> frame1 102 is(shistory.index, 4, "shistory.index"); 103 is(history.length, 6, "history.length"); 104 innerStaticFrame = staticFrame.contentDocument.getElementById("staticFrame"); 105 is(innerStaticFrame.contentDocument.location.href, BASE_URL + "frame1.html", "innerStaticFrame location"); 106 ok(!staticFrame.contentDocument.getElementById("dynamicFrame"), "innerDynamicFrame should not exist"); 107 108 // Test 5: Insert and navigate inner dynamic frame again with bfcache 109 // enabled, and navigate top level window to a special page which will 110 // evict bfcache then goback. Verify that dynamic entries are correctly 111 // removed in this case. 112 window.onunload = null; // enable bfcache 113 staticFrame.width = "320px"; 114 staticFrame.height = "360px"; 115 innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument, "frame2.html"); 116 await loadUriInFrame(innerDynamicFrame, "frame3.html"); 117 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static 118 // innerStaticFrame: frame0 -> frame1 119 // innerDynamicFrame: frame2 -> frame3 120 is(shistory.index, 5, "shistory.index"); 121 is(history.length, 6, "history.length"); 122 window.location = "file_bug1326251_evict_cache.html"; 123 }, 124 async function() { 125 let windowWrap = SpecialPowers.wrap(window); 126 let docShell = windowWrap.docShell; 127 let shistory = docShell.QueryInterface(SpecialPowers.Ci.nsIWebNavigation) 128 .sessionHistory; 129 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static 130 // innerStaticFrame: frame0 -> frame1 131 if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { 132 // *EntryIndex attributes aren't meaningful when the session history 133 // lives in the parent process. 134 is(docShell.previousEntryIndex, 5, "docShell.previousEntryIndex"); 135 is(docShell.loadedEntryIndex, 4, "docShell.loadedEntryIndex"); 136 } 137 is(shistory.index, 4, "shistory.index"); 138 is(history.length, 6, "history.length"); 139 let staticFrame = document.getElementById("staticFrame"); 140 let innerStaticFrame = staticFrame.contentDocument.getElementById("staticFrame"); 141 is(innerStaticFrame.contentDocument.location.href, BASE_URL + "frame1.html", "innerStaticFrame location"); 142 ok(!staticFrame.contentDocument.getElementById("dynamicFrame"), "innerDynamicFrame should not exist"); 143 144 // Test 6: Insert and navigate inner dynamic frame and then reload outer 145 // frame. Verify that inner dynamic frame entries are all removed. 146 staticFrame.width = "320px"; 147 staticFrame.height = "360px"; 148 let innerDynamicFrame = await createDynamicFrame(staticFrame.contentDocument, "frame2.html"); 149 await loadUriInFrame(innerDynamicFrame, "frame3.html"); 150 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static 151 // innerStaticFrame: frame0 -> frame1 152 // innerDynamicFrame: frame2 -> frame3 153 is(shistory.index, 5, "shistory.index"); 154 is(history.length, 6, "history.length"); 155 let staticFrameLoadPromise = new Promise(resolve => { 156 staticFrame.onload = resolve; 157 }); 158 staticFrame.contentWindow.location.reload(); 159 await staticFrameLoadPromise; 160 // staticFrame: frame0 -> frame1 -> frame2 -> iframe_static 161 // innerStaticFrame: frame0 -> frame1 162 is(shistory.index, 4, "shistory.index"); 163 is(history.length, 5, "history.length"); 164 innerStaticFrame = staticFrame.contentDocument.getElementById("staticFrame"); 165 is(innerStaticFrame.contentDocument.location.href, BASE_URL + "frame1.html", "innerStaticFrame location"); 166 ok(!staticFrame.contentDocument.getElementById("dynamicFrame"), "innerDynamicFrame should not exist"); 167 bc.postMessage("finishTest"); 168 bc.close(); 169 window.close(); 170 }, 171 ]; 172 173 function awaitOnload(frame, occurances = 1) { 174 return new Promise(function(resolve) { 175 let count = 0; 176 frame.addEventListener("load", function listener() { 177 if (++count == occurances) { 178 frame.removeEventListener("load", listener); 179 setTimeout(resolve, 0); 180 } 181 }); 182 }); 183 } 184 185 async function createDynamicFrame(targetDocument, frameSrc = "frame0.html") { 186 let dynamicFrame = targetDocument.createElement("iframe"); 187 let onloadPromise = awaitOnload(dynamicFrame); 188 dynamicFrame.id = "dynamicFrame"; 189 dynamicFrame.src = frameSrc; 190 let container = targetDocument.getElementById("frameContainer"); 191 container.appendChild(dynamicFrame); 192 await onloadPromise; 193 return dynamicFrame; 194 } 195 196 async function loadUriInFrame(frame, uri) { 197 let onloadPromise = awaitOnload(frame); 198 frame.src = uri; 199 return onloadPromise; 200 } 201 202 function test() { 203 bc.postMessage("requestNextTest"); 204 } 205 </script> 206 </head> 207 <body onpageshow="test();"> 208 <div id="frameContainer"> 209 <iframe id="staticFrame" src="frame0.html"></iframe> 210 </div> 211 </body> 212 </html>