tor-browser

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

browser_500328.js (5253B)


      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 async function checkState(browser) {
      6  await SpecialPowers.spawn(browser, [], () => {
      7    // Go back and then forward, and make sure that the state objects received
      8    // from the popState event are as we expect them to be.
      9    //
     10    // We also add a node to the document's body when after going back and make
     11    // sure it's still there after we go forward -- this is to test that the two
     12    // history entries correspond to the same document.
     13 
     14    // Set some state in the page's window.  When we go back(), the page should
     15    // be retrieved from bfcache, and this state should still be there.
     16    content.testState = "foo";
     17  });
     18 
     19  // Now go back.  This should trigger the popstate event handler.
     20  let popstatePromise = SpecialPowers.spawn(browser, [], async () => {
     21    let event = await ContentTaskUtils.waitForEvent(content, "popstate", true);
     22    ok(event.state, "Event should have a state property.");
     23 
     24    is(content.testState, "foo", "testState after going back");
     25    is(
     26      JSON.stringify(content.history.state),
     27      JSON.stringify({ obj1: 1 }),
     28      "first popstate object."
     29    );
     30 
     31    // Add a node with id "new-elem" to the document.
     32    let doc = content.document;
     33    ok(
     34      !doc.getElementById("new-elem"),
     35      "doc shouldn't contain new-elem before we add it."
     36    );
     37    let elem = doc.createElement("div");
     38    elem.id = "new-elem";
     39    doc.body.appendChild(elem);
     40  });
     41 
     42  // Ensure that the message manager has processed the previous task before
     43  // going back to prevent racing with it in non-e10s mode.
     44  await SpecialPowers.spawn(browser, [], () => {});
     45  browser.goBack();
     46 
     47  await popstatePromise;
     48 
     49  popstatePromise = SpecialPowers.spawn(browser, [], async () => {
     50    let event = await ContentTaskUtils.waitForEvent(content, "popstate", true);
     51 
     52    // When content fires a PopStateEvent and we observe it from a chrome event
     53    // listener (as we do here, and, thankfully, nowhere else in the tree), the
     54    // state object will be a cross-compartment wrapper to an object that was
     55    // deserialized in the content scope. And in this case, since RegExps are
     56    // not currently Xrayable (see bug 1014991), trying to pull |obj3| (a RegExp)
     57    // off of an Xrayed Object won't work. So we need to waive.
     58    Assert.equal(
     59      Cu.waiveXrays(event.state).obj3.toString(),
     60      "/^a$/",
     61      "second popstate object."
     62    );
     63 
     64    // Make sure that the new-elem node is present in the document.  If it's
     65    // not, then this history entry has a different doc identifier than the
     66    // previous entry, which is bad.
     67    let doc = content.document;
     68    let newElem = doc.getElementById("new-elem");
     69    ok(newElem, "doc should contain new-elem.");
     70    newElem.remove();
     71    ok(!doc.getElementById("new-elem"), "new-elem should be removed.");
     72  });
     73 
     74  // Ensure that the message manager has processed the previous task before
     75  // going forward to prevent racing with it in non-e10s mode.
     76  await SpecialPowers.spawn(browser, [], () => {});
     77  browser.goForward();
     78  await popstatePromise;
     79 }
     80 
     81 add_task(async function test() {
     82  await SpecialPowers.pushPrefEnv({
     83    set: [["browser.navigation.requireUserInteraction", false]],
     84  });
     85 
     86  // Tests session restore functionality of history.pushState and
     87  // history.replaceState().  (Bug 500328)
     88 
     89  // We open a new blank window, let it load, and then load in
     90  // http://example.com.  We need to load the blank window first, otherwise the
     91  // docshell gets confused and doesn't have a current history entry.
     92  let state;
     93  await BrowserTestUtils.withNewTab(
     94    { gBrowser, url: "about:blank" },
     95    async function (browser) {
     96      BrowserTestUtils.startLoadingURIString(browser, "http://example.com");
     97      await BrowserTestUtils.browserLoaded(browser);
     98 
     99      // After these push/replaceState calls, the window should have three
    100      // history entries:
    101      //   testURL        (state object: null)          <-- oldest
    102      //   testURL        (state object: {obj1:1})
    103      //   testURL?page2  (state object: {obj3:/^a$/})  <-- newest
    104      function contentTest() {
    105        let history = content.window.history;
    106        history.pushState({ obj1: 1 }, "title-obj1");
    107        history.pushState({ obj2: 2 }, "title-obj2", "?page2");
    108        history.replaceState({ obj3: /^a$/ }, "title-obj3");
    109      }
    110      await SpecialPowers.spawn(browser, [], contentTest);
    111      await TabStateFlusher.flush(browser);
    112 
    113      state = ss.getTabState(gBrowser.getTabForBrowser(browser));
    114    }
    115  );
    116 
    117  // Restore the state into a new tab.  Things don't work well when we
    118  // restore into the old tab, but that's not a real use case anyway.
    119  await BrowserTestUtils.withNewTab(
    120    { gBrowser, url: "about:blank" },
    121    async function (browser) {
    122      let tab2 = gBrowser.getTabForBrowser(browser);
    123 
    124      let tabRestoredPromise = promiseTabRestored(tab2);
    125      ss.setTabState(tab2, state, true);
    126 
    127      // Run checkState() once the tab finishes loading its restored state.
    128      await tabRestoredPromise;
    129      await checkState(browser);
    130    }
    131  );
    132 });