tor-browser

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

browser_restore_container_tabs_oa.js (8188B)


      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 
      5 "use strict";
      6 
      7 const { UrlbarProviderOpenTabs } = ChromeUtils.importESModule(
      8  "moz-src:///browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs"
      9 );
     10 
     11 const PATH = "browser/browser/components/sessionstore/test/empty.html";
     12 
     13 /* import-globals-from ../../tabbrowser/test/browser/tabs/helper_origin_attrs_testing.js */
     14 loadTestSubscript(
     15  "../../tabbrowser/test/browser/tabs/helper_origin_attrs_testing.js"
     16 );
     17 
     18 var TEST_CASES = [
     19  "https://example.com/" + PATH,
     20  "https://example.org/" + PATH,
     21  "about:preferences",
     22  "about:config",
     23 ];
     24 
     25 var remoteTypes;
     26 
     27 var xulFrameLoaderCreatedCounter = {};
     28 
     29 function handleEventLocal(aEvent) {
     30  if (aEvent.type != "XULFrameLoaderCreated") {
     31    return;
     32  }
     33  // Ignore <browser> element in about:preferences and any other special pages
     34  if ("gBrowser" in aEvent.target.ownerGlobal) {
     35    xulFrameLoaderCreatedCounter.numCalledSoFar++;
     36  }
     37 }
     38 
     39 var NUM_DIFF_TAB_MODES = NUM_USER_CONTEXTS + 1; /** regular tab */
     40 
     41 add_setup(async function () {
     42  await SpecialPowers.pushPrefEnv({
     43    set: [
     44      // Set the pref to true so we know exactly how many tabs should be restoring at
     45      // any given time. This guarantees that a finishing load won't start another.
     46      ["browser.sessionstore.restore_on_demand", true],
     47      // Don't restore tabs lazily.
     48      ["browser.sessionstore.restore_tabs_lazily", true],
     49      // don't preload tabs so we don't have extra XULFrameLoaderCreated events
     50      // firing
     51      ["browser.newtab.preload", false],
     52    ],
     53  });
     54 
     55  requestLongerTimeout(7);
     56 });
     57 
     58 function setupRemoteTypes() {
     59  if (gFissionBrowser) {
     60    remoteTypes = [
     61      "webIsolated=https://example.com",
     62      "webIsolated=https://example.com^userContextId=1",
     63      "webIsolated=https://example.com^userContextId=2",
     64      "webIsolated=https://example.com^userContextId=3",
     65      "webIsolated=https://example.org",
     66      "webIsolated=https://example.org^userContextId=1",
     67      "webIsolated=https://example.org^userContextId=2",
     68      "webIsolated=https://example.org^userContextId=3",
     69    ];
     70  } else {
     71    remoteTypes = Array(
     72      NUM_DIFF_TAB_MODES * 2 /** 2 is the number of non parent uris */
     73    ).fill("web");
     74  }
     75  remoteTypes.push(...Array(NUM_DIFF_TAB_MODES * 2).fill(null)); // remote types for about: pages
     76 
     77  forgetClosedWindows();
     78  is(SessionStore.getClosedWindowCount(), 0, "starting with no closed windows");
     79 }
     80 /*
     81 * 1. Open several tabs in different containers and in regular tabs
     82 [page1, page2, page3] [ [(page1 - work) (page1 - home)] [(page2 - work) (page2 - home)] ]
     83 * 2. Close the window
     84 * 3. Restore session, window will have the following tabs
     85 * [initial blank page, page1, page1-work, page1-home, page2, page2-work, page2-home] 
     86 * 4. Verify correct remote types and that XULFrameLoaderCreated gets fired correct number of times
     87 */
     88 add_task(async function testRestore() {
     89  setupRemoteTypes();
     90  let newWin = await promiseNewWindowLoaded();
     91  var regularPages = [];
     92  var containerPages = {};
     93  // Go through all the test cases and open same set of urls in regular tabs and in container tabs
     94  for (const uri of TEST_CASES) {
     95    // Open a url in a regular tab
     96    let regularPage = await openURIInRegularTab(uri, newWin);
     97    regularPages.push(regularPage);
     98 
     99    // Open the same url in different user contexts
    100    for (
    101      var user_context_id = 1;
    102      user_context_id <= NUM_USER_CONTEXTS;
    103      user_context_id++
    104    ) {
    105      let containerPage = await openURIInContainer(
    106        uri,
    107        newWin,
    108        user_context_id
    109      );
    110      containerPages[uri] = containerPage;
    111    }
    112  }
    113  await TabStateFlusher.flushWindow(newWin);
    114 
    115  // Close the window
    116  await BrowserTestUtils.closeWindow(newWin);
    117  await forceSaveState();
    118 
    119  is(
    120    SessionStore.getClosedWindowCount(),
    121    1,
    122    "Should have restore data for the closed window"
    123  );
    124 
    125  Assert.equal(
    126    0,
    127    (await UrlbarProviderOpenTabs.getDatabaseRegisteredOpenTabsForTests())
    128      .length,
    129    "No registered open pages should be left"
    130  );
    131 
    132  // Now restore the window
    133  newWin = SessionStore.undoCloseWindow(0);
    134 
    135  // Make sure to wait for the window to be restored.
    136  await Promise.all([
    137    BrowserTestUtils.waitForEvent(newWin, "SSWindowStateReady"),
    138  ]);
    139  await BrowserTestUtils.waitForEvent(
    140    newWin.gBrowser.tabContainer,
    141    "SSTabRestored"
    142  );
    143 
    144  var nonblank_pages_len =
    145    TEST_CASES.length + NUM_USER_CONTEXTS * TEST_CASES.length;
    146  is(
    147    newWin.gBrowser.tabs.length,
    148    nonblank_pages_len + 1 /* initial page */,
    149    "Correct number of tabs restored"
    150  );
    151 
    152  // Now we have pages opened in the following manner
    153  // [blank page, page1, page1-work, page1-home, page2, page2-work, page2-home]
    154 
    155  info(`Number of tabs restored: ${newWin.gBrowser.tabs.length}`);
    156  var currRemoteType, expectedRemoteType;
    157  let loaded;
    158  for (var tab_idx = 1; tab_idx < nonblank_pages_len; ) {
    159    info(`Accessing regular tab at index ${tab_idx}`);
    160    var test_page_data = regularPages.shift();
    161    let regular_tab = newWin.gBrowser.tabs[tab_idx];
    162    let regular_browser = regular_tab.linkedBrowser;
    163 
    164    // I would have used browserLoaded but for about:config it doesn't work
    165    let ready = BrowserTestUtils.waitForCondition(async () => {
    166      // Catch an error because the browser might change remoteness in between
    167      // calls, so we will just wait for the document to finish loadig.
    168      return SpecialPowers.spawn(regular_browser, [], () => {
    169        return content.document.readyState == "complete";
    170      }).catch(console.error);
    171    });
    172    newWin.gBrowser.selectedTab = regular_tab;
    173    await TabStateFlusher.flush(regular_browser);
    174    await ready;
    175 
    176    currRemoteType = regular_browser.remoteType;
    177    expectedRemoteType = remoteTypes.shift();
    178    is(
    179      currRemoteType,
    180      expectedRemoteType,
    181      `correct remote type for regular tab with uri ${test_page_data.uri}`
    182    );
    183 
    184    let page_uri = regular_browser.currentURI.spec;
    185    info(`Current uri = ${page_uri}`);
    186 
    187    // Iterate over container pages, starting after the regular page and ending before the next regular page
    188    var userContextId = 1;
    189    for (
    190      var container_tab_idx = tab_idx + 1;
    191      container_tab_idx < tab_idx + 1 + NUM_USER_CONTEXTS;
    192      container_tab_idx++, userContextId++
    193    ) {
    194      info(`Accessing container tab at index ${container_tab_idx}`);
    195      let container_tab = newWin.gBrowser.tabs[container_tab_idx];
    196 
    197      initXulFrameLoaderCreatedCounter(xulFrameLoaderCreatedCounter);
    198      container_tab.ownerGlobal.gBrowser.addEventListener(
    199        "XULFrameLoaderCreated",
    200        handleEventLocal
    201      );
    202 
    203      loaded = BrowserTestUtils.browserLoaded(
    204        container_tab.linkedBrowser,
    205        false,
    206        test_page_data.uri
    207      );
    208 
    209      newWin.gBrowser.selectedTab = container_tab;
    210      await TabStateFlusher.flush(container_tab.linkedBrowser);
    211      await loaded;
    212      let uri = container_tab.linkedBrowser.currentURI.spec;
    213 
    214      // Verify XULFrameLoaderCreated was fired once
    215      is(
    216        xulFrameLoaderCreatedCounter.numCalledSoFar,
    217        1,
    218        `XULFrameLoaderCreated was fired once, when restoring ${uri} in container ${userContextId} `
    219      );
    220      container_tab.ownerGlobal.gBrowser.removeEventListener(
    221        "XULFrameLoaderCreated",
    222        handleEventLocal
    223      );
    224 
    225      // Verify correct remote type for container tab
    226      currRemoteType = container_tab.linkedBrowser.remoteType;
    227      expectedRemoteType = remoteTypes.shift();
    228      info(
    229        `Remote type for container tab ${userContextId} is ${currRemoteType}`
    230      );
    231      is(
    232        currRemoteType,
    233        expectedRemoteType,
    234        "correct remote type for container tab"
    235      );
    236    }
    237    // Advance to the next regular page in our tabs list
    238    tab_idx = container_tab_idx;
    239  }
    240 
    241  await BrowserTestUtils.closeWindow(newWin);
    242 
    243  Assert.equal(
    244    0,
    245    (await UrlbarProviderOpenTabs.getDatabaseRegisteredOpenTabsForTests())
    246      .length,
    247    "No registered open pages should be left"
    248  );
    249 });