tor-browser

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

cross-document-traversal-cross-document-traversal.html (6429B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Cross-document traversals during cross-document traversals</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 
      7 <!--
      8  In the spec, all traversals are queued, and that includes computing what
      9  "back" and "forward" mean, based on the "current session history step". The
     10  "current session history step" is updated at the end of "apply the history
     11  step", at which point the queued steps in "traverse history by a delta" get to
     12  run and compute what is back/forward. So the basic structure is:
     13 
     14  - back(), back(): go back once, then again.
     15  - back(), forward(): go back once, then go forward.
     16 
     17  However, note that these observable effects (e.g., actually loading an
     18  intermediate document) are done via queued tasks. Those tasks will end up not
     19  running, once we switch the active document due to the second traversal. So
     20  the end observable result looks like:
     21 
     22  - back(), back(): go back -2.
     23  - back(), forward(): go nowhere.
     24 -->
     25 
     26 <body>
     27 <script type="module">
     28 import { createIframe, waitForLoad, delay, waitForPotentialNetworkLoads } from "./resources/helpers.mjs";
     29 
     30 promise_test(async t => {
     31  const iframe = await createIframe(t);
     32 
     33  // Setup
     34  // Extra delay()s are necessary because if we navigate "inside" the load
     35  // handler (i.e. in a promise reaction for the load handler) then it will
     36  // be a replace navigation.
     37  iframe.contentWindow.location.search = "?1";
     38  await waitForLoad(iframe);
     39  await delay(t, 0);
     40  iframe.contentWindow.location.search = "?2";
     41  await waitForLoad(iframe);
     42  await delay(t, 0);
     43  iframe.contentWindow.location.search = "?3";
     44  await waitForLoad(iframe);
     45  await delay(t, 0);
     46  iframe.contentWindow.history.back();
     47  await waitForLoad(iframe);
     48  await delay(t, 0);
     49  assert_equals(iframe.contentWindow.location.search, "?2", "we made our way to ?2 for setup");
     50 
     51  iframe.contentWindow.history.back();
     52  assert_equals(iframe.contentWindow.location.search, "?2", "must not go back synchronously");
     53 
     54  iframe.contentWindow.history.forward();
     55  assert_equals(iframe.contentWindow.location.search, "?2", "must not go forward synchronously");
     56 
     57  iframe.onload = t.unreached_func("second load event");
     58 
     59  await waitForPotentialNetworkLoads(t);
     60  assert_equals(iframe.contentWindow.location.search, "?2", "must stay on ?2");
     61 }, "cross-document traversals in opposite directions: the result is going nowhere");
     62 
     63 promise_test(async t => {
     64  const iframe = await createIframe(t);
     65 
     66  // Setup
     67  // Extra delay()s are necessary because if we navigate "inside" the load
     68  // handler (i.e. in a promise reaction for the load handler) then it will
     69  // be a replace navigation.
     70  iframe.contentWindow.location.search = "?1";
     71  await waitForLoad(iframe);
     72  await delay(t, 0);
     73  iframe.contentWindow.location.search = "?2";
     74  await waitForLoad(iframe);
     75  await delay(t, 0);
     76 
     77  iframe.contentWindow.history.back();
     78  assert_equals(iframe.contentWindow.location.search, "?2", "must not go back synchronously");
     79 
     80  iframe.contentWindow.history.forward();
     81  assert_equals(iframe.contentWindow.location.search, "?2", "must not go forward synchronously");
     82 
     83  iframe.onload = t.unreached_func("second load event");
     84 
     85  await waitForPotentialNetworkLoads(t);
     86  assert_equals(iframe.contentWindow.location.search, "?2", "must stay on ?2");
     87 }, "cross-document traversals in opposite directions, second traversal invalid at queuing time but valid at the time it is run: the result is going nowhere");
     88 
     89 promise_test(async t => {
     90  const iframe = await createIframe(t);
     91 
     92  // Setup
     93  // Extra delay()s are necessary because if we navigate "inside" the load
     94  // handler (i.e. in a promise reaction for the load handler) then it will
     95  // be a replace navigation.
     96  iframe.contentWindow.location.search = "?1";
     97  await waitForLoad(iframe);
     98  await delay(t, 0);
     99  iframe.contentWindow.location.search = "?2";
    100  await waitForLoad(iframe);
    101  await delay(t, 0);
    102  iframe.contentWindow.location.search = "?3";
    103  await waitForLoad(iframe);
    104  await delay(t, 0);
    105 
    106  iframe.contentWindow.history.back();
    107  assert_equals(iframe.contentWindow.location.search, "?3", "must not go back synchronously (1)");
    108 
    109  iframe.contentWindow.history.back();
    110  assert_equals(iframe.contentWindow.location.search, "?3", "must not go back synchronously (2)");
    111 
    112  await waitForLoad(iframe);
    113  assert_equals(iframe.contentWindow.location.search, "?1", "first load event must be going back");
    114 
    115  iframe.onload = t.unreached_func("second load event");
    116 
    117  await waitForPotentialNetworkLoads(t);
    118  assert_equals(iframe.contentWindow.location.search, "?1", "must stay on ?1");
    119 }, "cross-document traversals in the same (back) direction: the result is going -2 with only one load event");
    120 
    121 promise_test(async t => {
    122  const iframe = await createIframe(t);
    123 
    124  // Setup
    125  // Extra delay()s are necessary because if we navigate "inside" the load
    126  // handler (i.e. in a promise reaction for the load handler) then it will
    127  // be a replace navigation.
    128  iframe.contentWindow.location.search = "?1";
    129  await waitForLoad(iframe);
    130  await delay(t, 0);
    131  iframe.contentWindow.location.search = "?2";
    132  await waitForLoad(iframe);
    133  await delay(t, 0);
    134  iframe.contentWindow.location.search = "?3";
    135  await waitForLoad(iframe);
    136  await delay(t, 0);
    137  iframe.contentWindow.history.back();
    138  await waitForLoad(iframe);
    139  await delay(t, 0);
    140  assert_equals(iframe.contentWindow.location.search, "?2", "we made our way to ?2 for setup");
    141  iframe.contentWindow.history.back();
    142  await waitForLoad(iframe);
    143  await delay(t, 0);
    144  assert_equals(iframe.contentWindow.location.search, "?1", "we made our way to ?1 for setup");
    145 
    146  iframe.contentWindow.history.forward();
    147  assert_equals(iframe.contentWindow.location.search, "?1", "must not go forward synchronously (1)");
    148 
    149  iframe.contentWindow.history.forward();
    150  assert_equals(iframe.contentWindow.location.search, "?1", "must not go forward synchronously (2)");
    151 
    152  await waitForLoad(iframe);
    153  assert_equals(iframe.contentWindow.location.search, "?3", "first load event must be going forward");
    154 
    155  iframe.onload = t.unreached_func("second load event");
    156 
    157  await waitForPotentialNetworkLoads(t);
    158  assert_equals(iframe.contentWindow.location.search, "?3", "must stay on ?3");
    159 }, "cross-document traversals in the same (forward) direction: the result is going +2 with only one load event");
    160 </script>