browser_bug1303838.js (10095B)
1 /* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * Test for bug 1303838. 9 * Load a tab with some links, emulate link clicks and check if the 10 * browser would switch to the existing target tab opened by previous 11 * link click if loadDivertedInBackground is set to true. 12 */ 13 14 "use strict"; 15 16 const BASE_URL = "http://mochi.test:8888/browser/dom/base/test/"; 17 18 add_task(async function () { 19 // On Linux, in our test automation, the mouse cursor floats over 20 // the first tab, which causes it to be warmed up when tab warming 21 // is enabled. The TabSwitchDone event doesn't fire until the warmed 22 // tab is evicted, which is after a few seconds. That means that 23 // this test ends up taking longer than we'd like, since its waiting 24 // for the TabSwitchDone event between tab switches. 25 // 26 // So now we make sure that warmed tabs are evicted very shortly 27 // after warming to avoid the test running too long. 28 await SpecialPowers.pushPrefEnv({ 29 set: [ 30 ["browser.tabs.remote.warmup.unloadDelayMs", 50], 31 ["test.wait300msAfterTabSwitch", true], 32 ], 33 }); 34 await testLinkClick(false, false); 35 await testLinkClick(false, true); 36 await testLinkClick(true, false); 37 await testLinkClick(true, true); 38 }); 39 40 async function waitForTestReady(loadDivertedInBackground, tab) { 41 if (!loadDivertedInBackground) { 42 await BrowserTestUtils.switchTab(gBrowser, tab); 43 } else { 44 await new Promise(resolve => setTimeout(resolve, 0)); 45 } 46 } 47 48 async function testLinkClick(withFrame, loadDivertedInBackground) { 49 await SpecialPowers.pushPrefEnv({ 50 set: [["browser.tabs.loadDivertedInBackground", loadDivertedInBackground]], 51 }); 52 53 let tab = await BrowserTestUtils.openNewForegroundTab( 54 gBrowser, 55 BASE_URL + 56 (withFrame ? "file_bug1303838_with_iframe.html" : "file_bug1303838.html") 57 ); 58 is(gBrowser.tabs.length, 2, "check tabs.length"); 59 is(gBrowser.selectedTab, tab, "check selectedTab"); 60 61 info( 62 "Test normal links with loadDivertedInBackground=" + 63 loadDivertedInBackground + 64 ", withFrame=" + 65 withFrame 66 ); 67 68 let testTabPromise = BrowserTestUtils.waitForNewTab(gBrowser); 69 await clickLink(withFrame, "#link-1", tab.linkedBrowser); 70 let testTab = await testTabPromise; 71 is(gBrowser.tabs.length, 3, "check tabs.length"); 72 is( 73 gBrowser.selectedTab, 74 loadDivertedInBackground ? tab : testTab, 75 "check selectedTab" 76 ); 77 78 await waitForTestReady(loadDivertedInBackground, tab); 79 await clickLink( 80 withFrame, 81 "#link-2", 82 tab.linkedBrowser, 83 testTab.linkedBrowser, 84 !loadDivertedInBackground 85 ); 86 is(gBrowser.tabs.length, 3, "check tabs.length"); 87 is( 88 gBrowser.selectedTab, 89 loadDivertedInBackground ? tab : testTab, 90 "check selectedTab" 91 ); 92 93 await waitForTestReady(loadDivertedInBackground, tab); 94 await clickLink( 95 withFrame, 96 "#link-3", 97 tab.linkedBrowser, 98 testTab.linkedBrowser, 99 !loadDivertedInBackground 100 ); 101 is(gBrowser.tabs.length, 3, "check tabs.length"); 102 is( 103 gBrowser.selectedTab, 104 loadDivertedInBackground ? tab : testTab, 105 "check selectedTab" 106 ); 107 108 await waitForTestReady(loadDivertedInBackground, tab); 109 await clickLink( 110 withFrame, 111 "#link-4", 112 tab.linkedBrowser, 113 testTab.linkedBrowser, 114 !loadDivertedInBackground 115 ); 116 is(gBrowser.tabs.length, 3, "check tabs.length"); 117 is( 118 gBrowser.selectedTab, 119 loadDivertedInBackground ? tab : testTab, 120 "check selectedTab" 121 ); 122 123 // Location APIs shouldn't steal focus. 124 await waitForTestReady(loadDivertedInBackground, tab); 125 await clickLink( 126 withFrame, 127 "#link-5", 128 tab.linkedBrowser, 129 testTab.linkedBrowser, 130 /* awaitTabSwitch = */ false 131 ); 132 is(gBrowser.tabs.length, 3, "check tabs.length"); 133 is(gBrowser.selectedTab, tab, "check selectedTab"); 134 135 await waitForTestReady(/* diverted = */ true, tab); 136 await clickLink( 137 withFrame, 138 "#link-6", 139 tab.linkedBrowser, 140 testTab.linkedBrowser, 141 /* awaitTabSwitch = */ false 142 ); 143 is(gBrowser.tabs.length, 3, "check tabs.length"); 144 is(gBrowser.selectedTab, tab, "check selectedTab"); 145 146 await waitForTestReady(/* diverted = */ true, tab); 147 let loaded = BrowserTestUtils.browserLoaded( 148 testTab.linkedBrowser, 149 true, 150 "data:text/html;charset=utf-8,testFrame" 151 ); 152 await clickLink( 153 withFrame, 154 "#link-7", 155 tab.linkedBrowser, 156 testTab.linkedBrowser, 157 !loadDivertedInBackground, 158 false 159 ); 160 await loaded; 161 is(gBrowser.tabs.length, 3, "check tabs.length"); 162 is( 163 gBrowser.selectedTab, 164 loadDivertedInBackground ? tab : testTab, 165 "check selectedTab" 166 ); 167 168 info( 169 "Test anchor links with loadDivertedInBackground=" + 170 loadDivertedInBackground + 171 ", withFrame=" + 172 withFrame 173 ); 174 175 await waitForTestReady(loadDivertedInBackground, tab); 176 await clickLink( 177 withFrame, 178 "#anchor-link-1", 179 tab.linkedBrowser, 180 testTab.linkedBrowser, 181 !loadDivertedInBackground 182 ); 183 is(gBrowser.tabs.length, 3, "check tabs.length"); 184 is( 185 gBrowser.selectedTab, 186 loadDivertedInBackground ? tab : testTab, 187 "check selectedTab" 188 ); 189 190 await waitForTestReady(loadDivertedInBackground, tab); 191 await clickLink( 192 withFrame, 193 "#anchor-link-2", 194 tab.linkedBrowser, 195 testTab.linkedBrowser, 196 !loadDivertedInBackground 197 ); 198 is(gBrowser.tabs.length, 3, "check tabs.length"); 199 is( 200 gBrowser.selectedTab, 201 loadDivertedInBackground ? tab : testTab, 202 "check selectedTab" 203 ); 204 205 await waitForTestReady(loadDivertedInBackground, tab); 206 await clickLink( 207 withFrame, 208 "#anchor-link-3", 209 tab.linkedBrowser, 210 testTab.linkedBrowser, 211 !loadDivertedInBackground 212 ); 213 is(gBrowser.tabs.length, 3, "check tabs.length"); 214 is( 215 gBrowser.selectedTab, 216 loadDivertedInBackground ? tab : testTab, 217 "check selectedTab" 218 ); 219 220 info( 221 "Test iframe links with loadDivertedInBackground=" + 222 loadDivertedInBackground + 223 ", withFrame=" + 224 withFrame 225 ); 226 227 await waitForTestReady(loadDivertedInBackground, tab); 228 await clickLink( 229 withFrame, 230 "#frame-link-1", 231 tab.linkedBrowser, 232 testTab.linkedBrowser, 233 !loadDivertedInBackground, 234 true 235 ); 236 is(gBrowser.tabs.length, 3, "check tabs.length"); 237 is( 238 gBrowser.selectedTab, 239 loadDivertedInBackground ? tab : testTab, 240 "check selectedTab" 241 ); 242 243 await waitForTestReady(loadDivertedInBackground, tab); 244 await clickLink( 245 withFrame, 246 "#frame-link-2", 247 tab.linkedBrowser, 248 testTab.linkedBrowser, 249 !loadDivertedInBackground, 250 true 251 ); 252 is(gBrowser.tabs.length, 3, "check tabs.length"); 253 is( 254 gBrowser.selectedTab, 255 loadDivertedInBackground ? tab : testTab, 256 "check selectedTab" 257 ); 258 259 await waitForTestReady(loadDivertedInBackground, tab); 260 await clickLink( 261 withFrame, 262 "#frame-link-3", 263 tab.linkedBrowser, 264 testTab.linkedBrowser, 265 !loadDivertedInBackground, 266 true 267 ); 268 is(gBrowser.tabs.length, 3, "check tabs.length"); 269 is( 270 gBrowser.selectedTab, 271 loadDivertedInBackground ? tab : testTab, 272 "check selectedTab" 273 ); 274 275 BrowserTestUtils.removeTab(testTab); 276 BrowserTestUtils.removeTab(tab); 277 } 278 279 function clickLink( 280 isFrame, 281 linkId, 282 browser, 283 testBrowser, 284 awaitTabSwitch = false, 285 targetsFrame = false, 286 locationChangeNum = 1 287 ) { 288 let promises = []; 289 if (awaitTabSwitch) { 290 promises.push(waitForTabSwitch(gBrowser)); 291 } 292 if (testBrowser) { 293 promises.push( 294 waitForLocationChange(targetsFrame, testBrowser, locationChangeNum) 295 ); 296 } 297 298 info("BC children: " + browser.browsingContext.children.length); 299 promises.push( 300 BrowserTestUtils.synthesizeMouseAtCenter( 301 linkId, 302 {}, 303 isFrame ? browser.browsingContext.children[0] : browser 304 ) 305 ); 306 return Promise.all(promises); 307 } 308 309 function waitForTabSwitch(tabbrowser) { 310 info("Waiting for TabSwitch"); 311 return new Promise(resolve => { 312 tabbrowser.addEventListener("TabSwitchDone", function onSwitch() { 313 info("TabSwitch done"); 314 tabbrowser.removeEventListener("TabSwitchDone", onSwitch); 315 resolve(tabbrowser.selectedTab); 316 }); 317 }); 318 } 319 320 let locationChangeListener; 321 function waitForLocationChange(isFrame, browser, locationChangeNum) { 322 if (isFrame) { 323 return waitForFrameLocationChange(browser, locationChangeNum); 324 } 325 326 info("Waiting for " + locationChangeNum + " LocationChange"); 327 return new Promise(resolve => { 328 let seen = 0; 329 locationChangeListener = { 330 onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { 331 info("LocationChange: " + aLocation.spec); 332 if (++seen == locationChangeNum) { 333 browser.removeProgressListener(this); 334 resolve(); 335 } 336 }, 337 QueryInterface: ChromeUtils.generateQI([ 338 "nsIWebProgressListener", 339 "nsISupportsWeakReference", 340 ]), 341 }; 342 browser.addProgressListener(locationChangeListener); 343 }); 344 } 345 346 function waitForFrameLocationChange(browser, locationChangeNum) { 347 info("Waiting for " + locationChangeNum + " LocationChange in subframe"); 348 return SpecialPowers.spawn(browser, [locationChangeNum], async changeNum => { 349 let seen = 0; 350 let webprogress = content.docShell.QueryInterface(Ci.nsIWebProgress); 351 await new Promise(resolve => { 352 locationChangeListener = { 353 onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { 354 info("LocationChange: " + aLocation.spec); 355 if (++seen == changeNum) { 356 resolve(); 357 } 358 }, 359 QueryInterface: ChromeUtils.generateQI([ 360 "nsIWebProgressListener", 361 "nsISupportsWeakReference", 362 ]), 363 }; 364 webprogress.addProgressListener( 365 locationChangeListener, 366 Ci.nsIWebProgress.NOTIFY_LOCATION 367 ); 368 }); 369 webprogress.removeProgressListener(locationChangeListener); 370 }); 371 }