tor-browser

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

browser_sessionHistory.js (9167B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 requestLongerTimeout(2);
      7 
      8 /**
      9 * Ensure that starting a load invalidates shistory.
     10 */
     11 add_task(async function test_load_start() {
     12  // Create a new tab.
     13  let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
     14  let browser = tab.linkedBrowser;
     15  await BrowserTestUtils.browserLoaded(browser, { wantLoad: "about:blank" });
     16 
     17  const PAGE = "http://example.com/";
     18 
     19  // Load a new URI.
     20  let historyReplacePromise = promiseOnHistoryReplaceEntry(browser);
     21  BrowserTestUtils.startLoadingURIString(browser, PAGE);
     22 
     23  // Remove the tab before it has finished loading.
     24  await historyReplacePromise;
     25  await promiseRemoveTabAndSessionState(tab);
     26 
     27  // Undo close the tab.
     28  tab = ss.undoCloseTab(window, 0);
     29  browser = tab.linkedBrowser;
     30  await promiseTabRestored(tab);
     31 
     32  // Check that the correct URL was restored.
     33  is(browser.currentURI.spec, PAGE, "url is correct");
     34 
     35  // Cleanup.
     36  gBrowser.removeTab(tab);
     37 });
     38 
     39 /**
     40 * Ensure that anchor navigation invalidates shistory.
     41 */
     42 add_task(async function test_hashchange() {
     43  const PATH = getRootDirectory(gTestPath).replace(
     44    "chrome://mochitests/content/",
     45    "http://example.com/"
     46  );
     47  const URL = PATH + "file_sessionHistory_hashchange.html";
     48  // Create a new tab.
     49  let tab = BrowserTestUtils.addTab(gBrowser, URL);
     50  let browser = tab.linkedBrowser;
     51  await promiseBrowserLoaded(browser);
     52 
     53  // Check that we start with a single shistory entry.
     54  await TabStateFlusher.flush(browser);
     55  let { entries } = JSON.parse(ss.getTabState(tab));
     56  is(entries.length, 1, "there is one shistory entry");
     57 
     58  // Click the link and wait for a hashchange event.
     59  let eventPromise = BrowserTestUtils.waitForContentEvent(
     60    browser,
     61    "hashchange",
     62    true
     63  );
     64  await SpecialPowers.spawn(browser, [], async function () {
     65    content.document.querySelector("#a").click();
     66  });
     67  info("About to watch for a hash change event");
     68  await eventPromise;
     69  info("Got a hash change event");
     70 
     71  // Check that we now have two shistory entries.
     72  await TabStateFlusher.flush(browser);
     73  ({ entries } = JSON.parse(ss.getTabState(tab)));
     74  is(entries.length, 2, "there are two shistory entries");
     75 
     76  // Cleanup.
     77  gBrowser.removeTab(tab);
     78 });
     79 
     80 /**
     81 * Ensure that loading pages from the bfcache invalidates shistory.
     82 */
     83 add_task(async function test_pageshow() {
     84  const URL = "data:text/html;charset=utf-8,<h1>first</h1>";
     85  const URL2 = "data:text/html;charset=utf-8,<h1>second</h1>";
     86 
     87  // Create a new tab.
     88  let tab = BrowserTestUtils.addTab(gBrowser, URL);
     89  let browser = tab.linkedBrowser;
     90  await promiseBrowserLoaded(browser);
     91 
     92  // Create a second shistory entry.
     93  BrowserTestUtils.startLoadingURIString(browser, URL2);
     94  await promiseBrowserLoaded(browser);
     95 
     96  // Wait until shistory changes.
     97  let pageShowPromise = BrowserTestUtils.waitForContentEvent(
     98    browser,
     99    "pageshow",
    100    true
    101  );
    102 
    103  // Go back to the previous url which is loaded from the bfcache.
    104  browser.goBack();
    105  await pageShowPromise;
    106  is(browser.currentURI.spec, URL, "correct url after going back");
    107 
    108  // Check that loading from bfcache did invalidate shistory.
    109  await TabStateFlusher.flush(browser);
    110  let { index } = JSON.parse(ss.getTabState(tab));
    111  is(index, 1, "first history entry is selected");
    112 
    113  // Cleanup.
    114  gBrowser.removeTab(tab);
    115 });
    116 
    117 /**
    118 * Ensure that subframe navigation invalidates shistory.
    119 */
    120 add_task(async function test_subframes() {
    121  const URL =
    122    "data:text/html;charset=utf-8," +
    123    "<iframe src=http%3A//example.com/ name=t></iframe>" +
    124    "<a id=a1 href=http%3A//example.com/1 target=t>clickme</a>" +
    125    "<a id=a2 href=http%3A//example.com/%23section target=t>clickme</a>";
    126 
    127  // Create a new tab.
    128  let tab = BrowserTestUtils.addTab(gBrowser, URL);
    129  let browser = tab.linkedBrowser;
    130  await promiseBrowserLoaded(browser);
    131 
    132  // Check that we have a single shistory entry.
    133  await TabStateFlusher.flush(browser);
    134  let { entries } = JSON.parse(ss.getTabState(tab));
    135  is(entries.length, 1, "there is one shistory entry");
    136  is(entries[0].children.length, 1, "the entry has one child");
    137 
    138  // Navigate the subframe.
    139  await SpecialPowers.spawn(browser, [], async function () {
    140    content.document.notifyUserGestureActivation();
    141    content.document.querySelector("#a1").click();
    142  });
    143  await promiseBrowserLoaded(
    144    browser,
    145    false /* wait for subframe load only */,
    146    "http://example.com/1"
    147  );
    148 
    149  // Check shistory.
    150  await TabStateFlusher.flush(browser);
    151  ({ entries } = JSON.parse(ss.getTabState(tab)));
    152  is(entries.length, 2, "there now are two shistory entries");
    153  is(entries[1].children.length, 1, "the second entry has one child");
    154 
    155  // Go back in history.
    156  let goneBack = promiseBrowserLoaded(
    157    browser,
    158    false /* wait for subframe load only */,
    159    "http://example.com/"
    160  );
    161  info("About to go back in history");
    162  browser.goBack();
    163  await goneBack;
    164 
    165  // Navigate the subframe again.
    166  let eventPromise = BrowserTestUtils.waitForContentEvent(
    167    browser,
    168    "hashchange",
    169    true
    170  );
    171  await SpecialPowers.spawn(browser, [], async function () {
    172    content.document.querySelector("#a2").click();
    173  });
    174  await eventPromise;
    175 
    176  // Check shistory.
    177  await TabStateFlusher.flush(browser);
    178  ({ entries } = JSON.parse(ss.getTabState(tab)));
    179  is(entries.length, 2, "there now are two shistory entries");
    180  is(entries[1].children.length, 1, "the second entry has one child");
    181 
    182  // Cleanup.
    183  gBrowser.removeTab(tab);
    184 });
    185 
    186 /**
    187 * Ensure that navigating from an about page invalidates shistory.
    188 */
    189 add_task(async function test_about_page_navigate() {
    190  // Create a new tab.
    191  let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
    192  let browser = tab.linkedBrowser;
    193  await BrowserTestUtils.browserLoaded(browser, { wantLoad: "about:blank" });
    194 
    195  // Check that we have a single shistory entry.
    196  await TabStateFlusher.flush(browser);
    197  let { entries } = JSON.parse(ss.getTabState(tab));
    198  is(entries.length, 1, "there is one shistory entry");
    199  is(entries[0].url, "about:blank", "url is correct");
    200 
    201  // Verify that the title is also recorded.
    202  is(entries[0].title, "about:blank", "title is correct");
    203 
    204  BrowserTestUtils.startLoadingURIString(browser, "about:robots");
    205  await promiseBrowserLoaded(browser);
    206 
    207  // Check that we have changed the history entry.
    208  await TabStateFlusher.flush(browser);
    209  ({ entries } = JSON.parse(ss.getTabState(tab)));
    210  is(entries.length, 1, "there is one shistory entry");
    211  is(entries[0].url, "about:robots", "url is correct");
    212 
    213  // Cleanup.
    214  gBrowser.removeTab(tab);
    215 });
    216 
    217 /**
    218 * Ensure that history.pushState and history.replaceState invalidate shistory.
    219 */
    220 add_task(async function test_pushstate_replacestate() {
    221  // Create a new tab.
    222  let tab = BrowserTestUtils.addTab(gBrowser, "http://example.com/1");
    223  let browser = tab.linkedBrowser;
    224  await promiseBrowserLoaded(browser);
    225 
    226  // Check that we have a single shistory entry.
    227  await TabStateFlusher.flush(browser);
    228  let { entries } = JSON.parse(ss.getTabState(tab));
    229  is(entries.length, 1, "there is one shistory entry");
    230  is(entries[0].url, "http://example.com/1", "url is correct");
    231 
    232  await SpecialPowers.spawn(browser, [], async function () {
    233    content.window.history.pushState({}, "", "test-entry/");
    234  });
    235 
    236  // Check that we have added the history entry.
    237  await TabStateFlusher.flush(browser);
    238  ({ entries } = JSON.parse(ss.getTabState(tab)));
    239  is(entries.length, 2, "there is another shistory entry");
    240  is(entries[1].url, "http://example.com/test-entry/", "url is correct");
    241 
    242  await SpecialPowers.spawn(browser, [], async function () {
    243    content.window.history.replaceState({}, "", "test-entry2/");
    244  });
    245 
    246  // Check that we have modified the history entry.
    247  await TabStateFlusher.flush(browser);
    248  ({ entries } = JSON.parse(ss.getTabState(tab)));
    249  is(entries.length, 2, "there is still two shistory entries");
    250  is(
    251    entries[1].url,
    252    "http://example.com/test-entry/test-entry2/",
    253    "url is correct"
    254  );
    255 
    256  // Cleanup.
    257  gBrowser.removeTab(tab);
    258 });
    259 
    260 /**
    261 * Ensure that slow loading subframes will invalidate shistory.
    262 */
    263 add_task(async function test_slow_subframe_load() {
    264  const SLOW_URL =
    265    "http://mochi.test:8888/browser/browser/components/" +
    266    "sessionstore/test/browser_sessionHistory_slow.sjs";
    267 
    268  const URL =
    269    "data:text/html;charset=utf-8," +
    270    "<frameset cols=50%25,50%25>" +
    271    "<frame src='" +
    272    SLOW_URL +
    273    "'>" +
    274    "</frameset>";
    275 
    276  // Add a new tab with a slow loading subframe
    277  let tab = BrowserTestUtils.addTab(gBrowser, URL);
    278  let browser = tab.linkedBrowser;
    279  await promiseBrowserLoaded(browser);
    280 
    281  await TabStateFlusher.flush(browser);
    282  let { entries } = JSON.parse(ss.getTabState(tab));
    283 
    284  // Check the number of children.
    285  is(entries.length, 1, "there is one root entry ...");
    286  is(entries[0].children.length, 1, "... with one child entries");
    287 
    288  // Check URLs.
    289  ok(entries[0].url.startsWith("data:text/html"), "correct root url");
    290  is(entries[0].children[0].url, SLOW_URL, "correct url for subframe");
    291 
    292  // Cleanup.
    293  gBrowser.removeTab(tab);
    294 });