browser_frame_history.js (7607B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 5 6 /** 7 Ensure that frameset history works properly when restoring a tab, 8 provided that the frameset is static. 9 */ 10 11 // Loading a toplevel frameset 12 add_task(async function () { 13 await SpecialPowers.pushPrefEnv({ 14 set: [ 15 ["browser.navigation.requireUserInteraction", false], 16 ["dom.navigation.webidl.enabled", true], 17 ], 18 }); 19 20 let testURL = 21 getRootDirectory(gTestPath) + "browser_frame_history_index.html"; 22 let tab = BrowserTestUtils.addTab(gBrowser, testURL); 23 gBrowser.selectedTab = tab; 24 25 info("Opening a page with three frames, 4 loads should take place"); 26 await waitForLoadsInBrowser(tab.linkedBrowser, 4); 27 28 let browser_b = 29 tab.linkedBrowser.contentDocument.getElementsByTagName("frame")[1]; 30 let document_b = browser_b.contentDocument; 31 let links = document_b.getElementsByTagName("a"); 32 33 // We're going to click on the first link, so listen for another load event 34 info("Clicking on link 1, 1 load should take place"); 35 let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 36 EventUtils.sendMouseEvent( 37 { type: "click" }, 38 links[0], 39 browser_b.contentWindow 40 ); 41 await promise; 42 43 info("Clicking on link 2, 1 load should take place"); 44 promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 45 EventUtils.sendMouseEvent( 46 { type: "click" }, 47 links[1], 48 browser_b.contentWindow 49 ); 50 await promise; 51 52 info("Close then un-close page, 4 loads should take place"); 53 await promiseRemoveTabAndSessionState(tab); 54 let newTab = ss.undoCloseTab(window, 0); 55 await waitForLoadsInBrowser(newTab.linkedBrowser, 4); 56 57 info("Go back in time, 1 load should take place"); 58 gBrowser.goBack(); 59 await waitForLoadsInBrowser(newTab.linkedBrowser, 1); 60 61 let expectedURLEnds = ["a.html", "b.html", "c1.html"]; 62 let frames = 63 newTab.linkedBrowser.contentDocument.getElementsByTagName("frame"); 64 for (let i = 0; i < frames.length; i++) { 65 is( 66 frames[i].contentDocument.location.href, 67 getRootDirectory(gTestPath) + 68 "browser_frame_history_" + 69 expectedURLEnds[i], 70 "frame " + i + " has the right url" 71 ); 72 } 73 74 let expectedUrls = ["c", "c1", "c2"].map( 75 url => `${getRootDirectory(gTestPath)}browser_frame_history_${url}.html` 76 ); 77 let entryUrls = frames[2].contentWindow.navigation 78 .entries() 79 .map(entry => entry.url); 80 for (const [entryUrl, expectedUrl] of expectedUrls.map((url, i) => [ 81 entryUrls[i], 82 url, 83 ])) { 84 is(entryUrl, expectedUrl, "frame 2 NHE has correct url"); 85 } 86 87 gBrowser.removeTab(newTab); 88 }); 89 90 // Loading the frameset inside an iframe 91 add_task(async function () { 92 let testURL = 93 getRootDirectory(gTestPath) + "browser_frame_history_index2.html"; 94 let tab = BrowserTestUtils.addTab(gBrowser, testURL); 95 gBrowser.selectedTab = tab; 96 97 info( 98 "iframe: Opening a page with an iframe containing three frames, 5 loads should take place" 99 ); 100 await waitForLoadsInBrowser(tab.linkedBrowser, 5); 101 102 let browser_b = tab.linkedBrowser.contentDocument 103 .getElementById("iframe") 104 .contentDocument.getElementsByTagName("frame")[1]; 105 let document_b = browser_b.contentDocument; 106 let links = document_b.getElementsByTagName("a"); 107 108 // We're going to click on the first link, so listen for another load event 109 info("iframe: Clicking on link 1, 1 load should take place"); 110 let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 111 EventUtils.sendMouseEvent( 112 { type: "click" }, 113 links[0], 114 browser_b.contentWindow 115 ); 116 await promise; 117 118 info("iframe: Clicking on link 2, 1 load should take place"); 119 promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 120 EventUtils.sendMouseEvent( 121 { type: "click" }, 122 links[1], 123 browser_b.contentWindow 124 ); 125 await promise; 126 127 info("iframe: Close then un-close page, 5 loads should take place"); 128 await promiseRemoveTabAndSessionState(tab); 129 let newTab = ss.undoCloseTab(window, 0); 130 await waitForLoadsInBrowser(newTab.linkedBrowser, 5); 131 132 info("iframe: Go back in time, 1 load should take place"); 133 gBrowser.goBack(); 134 await waitForLoadsInBrowser(newTab.linkedBrowser, 1); 135 136 let expectedURLEnds = ["a.html", "b.html", "c1.html"]; 137 let frames = newTab.linkedBrowser.contentDocument 138 .getElementById("iframe") 139 .contentDocument.getElementsByTagName("frame"); 140 for (let i = 0; i < frames.length; i++) { 141 is( 142 frames[i].contentDocument.location.href, 143 getRootDirectory(gTestPath) + 144 "browser_frame_history_" + 145 expectedURLEnds[i], 146 "frame " + i + " has the right url" 147 ); 148 } 149 gBrowser.removeTab(newTab); 150 }); 151 152 // Now, test that we don't record history if the iframe is added dynamically 153 add_task(async function () { 154 // Start with an empty history 155 let blankState = JSON.stringify({ 156 windows: [ 157 { 158 tabs: [ 159 { entries: [{ url: "about:blank", triggeringPrincipal_base64 }] }, 160 ], 161 _closedTabs: [], 162 }, 163 ], 164 _closedWindows: [], 165 }); 166 await setBrowserState(blankState); 167 168 let testURL = 169 getRootDirectory(gTestPath) + "browser_frame_history_index_blank.html"; 170 let tab = BrowserTestUtils.addTab(gBrowser, testURL); 171 gBrowser.selectedTab = tab; 172 await waitForLoadsInBrowser(tab.linkedBrowser, 1); 173 174 info( 175 "dynamic: Opening a page with an iframe containing three frames, 4 dynamic loads should take place" 176 ); 177 let doc = tab.linkedBrowser.contentDocument; 178 let iframe = doc.createElement("iframe"); 179 iframe.id = "iframe"; 180 iframe.src = "browser_frame_history_index.html"; 181 doc.body.appendChild(iframe); 182 await waitForLoadsInBrowser(tab.linkedBrowser, 4); 183 184 let browser_b = tab.linkedBrowser.contentDocument 185 .getElementById("iframe") 186 .contentDocument.getElementsByTagName("frame")[1]; 187 let document_b = browser_b.contentDocument; 188 let links = document_b.getElementsByTagName("a"); 189 190 // We're going to click on the first link, so listen for another load event 191 info("dynamic: Clicking on link 1, 1 load should take place"); 192 let promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 193 EventUtils.sendMouseEvent( 194 { type: "click" }, 195 links[0], 196 browser_b.contentWindow 197 ); 198 await promise; 199 200 info("dynamic: Clicking on link 2, 1 load should take place"); 201 promise = waitForLoadsInBrowser(tab.linkedBrowser, 1); 202 EventUtils.sendMouseEvent( 203 { type: "click" }, 204 links[1], 205 browser_b.contentWindow 206 ); 207 await promise; 208 209 info("Check in the state that we have not stored this history"); 210 let state = ss.getBrowserState(); 211 info(JSON.stringify(JSON.parse(state), null, "\t")); 212 is( 213 state.indexOf("c1.html"), 214 -1, 215 "History entry was not stored in the session state" 216 ); 217 gBrowser.removeTab(tab); 218 }); 219 220 // helper functions 221 function waitForLoadsInBrowser(aBrowser, aLoadCount) { 222 return new Promise(resolve => { 223 let loadCount = 0; 224 aBrowser.addEventListener( 225 "load", 226 function listener() { 227 if (++loadCount < aLoadCount) { 228 info( 229 "Got " + loadCount + " loads, waiting until we have " + aLoadCount 230 ); 231 return; 232 } 233 234 aBrowser.removeEventListener("load", listener, true); 235 resolve(); 236 }, 237 true 238 ); 239 }); 240 } 241 242 function timeout(delay, task) { 243 return new Promise((resolve, reject) => { 244 setTimeout(() => resolve(true), delay); 245 task.then(() => resolve(false), reject); 246 }); 247 }