tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }