browser_scrollPositions.js (7908B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const BASE = "http://example.com/browser/browser/components/sessionstore/test/"; 7 const URL2 = BASE + "browser_scrollPositions_sample2.html"; 8 const URL_FRAMESET = BASE + "browser_scrollPositions_sample_frameset.html"; 9 10 // Randomized set of scroll positions we will use in this test. 11 const SCROLL_X = Math.round(100 * (1 + Math.random())); 12 const SCROLL_Y = Math.round(200 * (1 + Math.random())); 13 const SCROLL_STR = SCROLL_X + "," + SCROLL_Y; 14 15 const SCROLL2_X = Math.round(300 * (1 + Math.random())); 16 const SCROLL2_Y = Math.round(400 * (1 + Math.random())); 17 const SCROLL2_STR = SCROLL2_X + "," + SCROLL2_Y; 18 19 requestLongerTimeout(10); 20 21 add_task(test_scroll_nested); 22 23 if (gFissionBrowser) { 24 addCoopTask("browser_scrollPositions_sample.html", test_scroll, HTTPSROOT); 25 } 26 addNonCoopTask("browser_scrollPositions_sample.html", test_scroll, HTTPROOT); 27 addNonCoopTask("browser_scrollPositions_sample.html", test_scroll, HTTPSROOT); 28 29 addCoopTask( 30 "browser_scrollPositions_sample.html", 31 test_scroll_background_tabs, 32 HTTPSROOT 33 ); 34 addNonCoopTask( 35 "browser_scrollPositions_sample.html", 36 test_scroll_background_tabs, 37 HTTPROOT 38 ); 39 40 addNonCoopTask( 41 "browser_scrollPositions_sample.html", 42 test_scroll_background_tabs, 43 HTTPSROOT 44 ); 45 46 function getScrollPosition(bc) { 47 return SpecialPowers.spawn(bc, [], () => { 48 let x = {}, 49 y = {}; 50 content.windowUtils.getVisualViewportOffset(x, y); 51 return { x: x.value, y: y.value }; 52 }); 53 } 54 55 /** 56 * This test ensures that we properly serialize and restore scroll positions 57 * for an average page without any frames. 58 */ 59 async function test_scroll(aURL) { 60 let tab = BrowserTestUtils.addTab(gBrowser, aURL); 61 let browser = tab.linkedBrowser; 62 await promiseBrowserLoaded(browser); 63 64 // Scroll down a little. 65 await setScrollPosition(browser, SCROLL_X, SCROLL_Y); 66 await checkScroll(tab, { scroll: SCROLL_STR }, "scroll is fine"); 67 68 // Duplicate and check that the scroll position is restored. 69 let tab2 = ss.duplicateTab(window, tab); 70 let browser2 = tab2.linkedBrowser; 71 await promiseTabRestored(tab2); 72 73 let scroll = await getScrollPosition(browser2); 74 is( 75 JSON.stringify(scroll), 76 JSON.stringify({ x: SCROLL_X, y: SCROLL_Y }), 77 "scroll position has been duplicated correctly" 78 ); 79 80 // Check that reloading retains the scroll positions. 81 browser2.reload(); 82 await promiseBrowserLoaded(browser2); 83 await checkScroll( 84 tab2, 85 { scroll: SCROLL_STR }, 86 "reloading retains scroll positions" 87 ); 88 89 // Check that a force-reload resets scroll positions. 90 browser2.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); 91 await promiseBrowserLoaded(browser2); 92 await checkScroll(tab2, null, "force-reload resets scroll positions"); 93 94 // Scroll back to the top and check that the position has been reset. We 95 // expect the scroll position to be "null" here because there is no data to 96 // be stored if the frame is in its default scroll position. 97 await setScrollPosition(browser, 0, 0); 98 await checkScroll(tab, null, "no scroll stored"); 99 100 // Cleanup. 101 BrowserTestUtils.removeTab(tab); 102 BrowserTestUtils.removeTab(tab2); 103 } 104 105 /** 106 * This tests ensures that we properly serialize and restore scroll positions 107 * for multiple frames of pages with framesets. 108 */ 109 async function test_scroll_nested() { 110 let tab = BrowserTestUtils.addTab(gBrowser, URL_FRAMESET); 111 let browser = tab.linkedBrowser; 112 await promiseBrowserLoaded(browser); 113 114 // Scroll the first child frame down a little. 115 await setScrollPosition( 116 browser.browsingContext.children[0], 117 SCROLL_X, 118 SCROLL_Y 119 ); 120 await checkScroll( 121 tab, 122 { children: [{ scroll: SCROLL_STR }] }, 123 "scroll is fine" 124 ); 125 126 // Scroll the second child frame down a little. 127 await setScrollPosition( 128 browser.browsingContext.children[1], 129 SCROLL2_X, 130 SCROLL2_Y 131 ); 132 await checkScroll( 133 tab, 134 { children: [{ scroll: SCROLL_STR }, { scroll: SCROLL2_STR }] }, 135 "scroll is fine" 136 ); 137 138 // Duplicate and check that the scroll position is restored. 139 let tab2 = ss.duplicateTab(window, tab); 140 let browser2 = tab2.linkedBrowser; 141 await promiseTabRestored(tab2); 142 143 let scroll = await getScrollPosition(browser2.browsingContext.children[0]); 144 is( 145 JSON.stringify(scroll), 146 JSON.stringify({ x: SCROLL_X, y: SCROLL_Y }), 147 "scroll position #1 has been duplicated correctly" 148 ); 149 150 scroll = await getScrollPosition(browser2.browsingContext.children[1]); 151 is( 152 JSON.stringify(scroll), 153 JSON.stringify({ x: SCROLL2_X, y: SCROLL2_Y }), 154 "scroll position #2 has been duplicated correctly" 155 ); 156 157 // Check that resetting one frame's scroll position removes it from the 158 // serialized value. 159 await setScrollPosition(browser.browsingContext.children[0], 0, 0); 160 await checkScroll( 161 tab, 162 { children: [null, { scroll: SCROLL2_STR }] }, 163 "scroll is fine" 164 ); 165 166 // Check the resetting all frames' scroll positions nulls the stored value. 167 await setScrollPosition(browser.browsingContext.children[1], 0, 0); 168 await checkScroll(tab, null, "no scroll stored"); 169 170 // Cleanup. 171 BrowserTestUtils.removeTab(tab); 172 BrowserTestUtils.removeTab(tab2); 173 } 174 175 /** 176 * Test that scroll positions persist after restoring background tabs in 177 * a restored window (bug 1228518). 178 * Also test that scroll positions for previous session history entries 179 * are preserved as well (bug 1265818). 180 */ 181 async function test_scroll_background_tabs(aURL) { 182 await pushPrefs(["browser.sessionstore.restore_on_demand", true]); 183 184 let newWin = await BrowserTestUtils.openNewBrowserWindow(); 185 let tab = BrowserTestUtils.addTab(newWin.gBrowser, aURL); 186 let browser = tab.linkedBrowser; 187 await BrowserTestUtils.browserLoaded(browser); 188 189 // Add user interaction to the first entry. 190 await SpecialPowers.spawn(browser, [], () => { 191 content.document.notifyUserGestureActivation(); 192 }); 193 194 // Scroll down a little. 195 await setScrollPosition(browser, SCROLL_X, SCROLL_Y); 196 await checkScroll( 197 tab, 198 { scroll: SCROLL_STR }, 199 "scroll on first page is fine" 200 ); 201 202 // Navigate to a different page and scroll there as well. 203 let browser2loaded = BrowserTestUtils.browserLoaded(browser, false, URL2); 204 BrowserTestUtils.startLoadingURIString(browser, URL2); 205 await browser2loaded; 206 207 // Scroll down a little. 208 await setScrollPosition(browser, SCROLL2_X, SCROLL2_Y); 209 await checkScroll( 210 tab, 211 { scroll: SCROLL2_STR }, 212 "scroll on second page is fine" 213 ); 214 215 // Close the window 216 await BrowserTestUtils.closeWindow(newWin); 217 218 await forceSaveState(); 219 220 // Now restore the window 221 newWin = ss.undoCloseWindow(0); 222 223 // Make sure to wait for the window to be restored. 224 await BrowserTestUtils.waitForEvent(newWin, "SSWindowStateReady"); 225 226 is(newWin.gBrowser.tabs.length, 2, "There should be two tabs"); 227 228 // The second tab should be the one we loaded aURL at still 229 tab = newWin.gBrowser.tabs[1]; 230 231 ok(tab.hasAttribute("pending"), "Tab should be pending"); 232 browser = tab.linkedBrowser; 233 234 // Ensure there are no pending queued messages in the child. 235 await TabStateFlusher.flush(browser); 236 237 // Now check to see if the background tab remembers where it 238 // should be scrolled to. 239 newWin.gBrowser.selectedTab = tab; 240 await promiseTabRestored(tab); 241 242 await checkScroll( 243 tab, 244 { scroll: SCROLL2_STR }, 245 "scroll is correct for restored tab" 246 ); 247 248 // Now go back in history and check that the scroll position 249 // is restored there as well. 250 is(browser.canGoBack, true, "can go back"); 251 browser.goBack(); 252 253 await BrowserTestUtils.browserLoaded(browser); 254 await TabStateFlusher.flush(browser); 255 256 await checkScroll( 257 tab, 258 { scroll: SCROLL_STR }, 259 "scroll is correct after navigating back within the restored tab" 260 ); 261 262 await BrowserTestUtils.closeWindow(newWin); 263 }