tor-browser

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

history.sub.html (7216B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="/common/utils.js"></script>
      5 
      6 <meta http-equiv="Content-Security-Policy" content="img-src 'none'">
      7 
      8 <script>
      9  let message_from = (source_token, starts_with) => {
     10    return new Promise(resolve => {
     11      window.addEventListener('message', msg => {
     12        if (msg.data.token === source_token) {
     13          if (!starts_with || msg.data.msg.startsWith(starts_with))
     14            resolve(msg.data.msg);
     15        }
     16      });
     17    });
     18  };
     19 
     20  const img_url = window.origin + "/content-security-policy/support/fail.png";
     21 
     22  const function_addImage_string = img_token => `
     23    function addImage() {
     24      let img = document.createElement('img');
     25      img.src = '${img_url}';
     26      img.onload = () => opener.postMessage(
     27          {msg: 'img loaded', token: '${img_token}'}, '*');
     28      img.onerror = () => opener.postMessage(
     29          {msg: 'img blocked', token: '${img_token}'}, '*');
     30      document.body.appendChild(img);
     31    }
     32  `;
     33 
     34  const img_tag_string = img_token => `
     35    <img src="${img_url}"
     36         onload="opener.postMessage(
     37             {msg: 'img loaded', token: '${img_token}'}, '*');"
     38         onerror="opener.postMessage(
     39             {msg: 'img blocked', token: '${img_token}'}, '*');"
     40    >
     41  `;
     42 
     43  let write_img_to_popup = (popup, img_token) => {
     44    let div = popup.document.createElement('div');
     45    div.innerHTML = img_tag_string(img_token);
     46    popup.document.body.appendChild(div);
     47  };
     48 
     49  // A beforeunload event listener disables bfcache (Firefox only).
     50  //
     51  // Note: Chrome enables bfcache only on HTTP/HTTPS documents, so a blob will
     52  // never be put in the bfcache. Moreover with Chrome, bfcache needs a single
     53  // top-level browsing context in the browsing context group. Since we are
     54  // using window.open() below, the back-forward cache is not triggered.
     55  const disable_bfcache = `
     56    window.addEventListener('beforeunload', function(event) {
     57      eval('1+1');
     58    });
     59  `;
     60 
     61  const blob_payload = blob_token => `
     62    <!doctype html>
     63    <script>window.window_token = "${blob_token}";</scr`+`ipt>
     64    <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt>
     65    <body onpageshow="addImage();"></body>
     66  `;
     67  let blob_url = blob_token => URL.createObjectURL(
     68    new Blob([blob_payload(blob_token)], { type: 'text/html' }));
     69 
     70  const blob_payload_no_bfcache = blob_token => `
     71    <!doctype html>
     72    <script>window.window_token = "${blob_token}";</scr`+`ipt>
     73    <script>${disable_bfcache}</scr`+`ipt>
     74    <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt>
     75    <body onpageshow="addImage();"></body>
     76  `;
     77  let blob_url_no_bfcache = blob_token => URL.createObjectURL(
     78    new Blob([blob_payload_no_bfcache(blob_token)], { type: 'text/html' }));
     79 
     80  let testCases = [
     81    test_token => ({
     82      token: test_token,
     83      url: "about:blank",
     84      add_img_function: popup => write_img_to_popup(popup, test_token),
     85      other_origin: window.origin,
     86      name: '"about:blank" document is navigated back from history same-origin.',
     87    }),
     88    test_token => ({
     89      token: test_token,
     90      url: "about:blank",
     91      add_img_function: popup => write_img_to_popup(popup, test_token),
     92      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
     93      name: '"about:blank" document is navigated back from history cross-origin.',
     94    }),
     95    test_token => ({
     96      token: test_token,
     97      url: blob_url(test_token),
     98      other_origin: window.origin,
     99      name: 'blob URL document is navigated back from history same-origin.',
    100    }),
    101    test_token => ({
    102      token: test_token,
    103      url: blob_url(test_token),
    104      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
    105      name: 'blob URL document is navigated back from history cross-origin.',
    106    }),
    107    test_token => ({
    108      token: test_token,
    109      url: blob_url_no_bfcache(test_token),
    110      other_origin: window.origin,
    111      name: 'blob URL document is navigated back from history (without bfcache on Firefox) same-origin.',
    112    }),
    113    test_token => ({
    114      token: test_token,
    115      url: blob_url_no_bfcache(test_token),
    116      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
    117      name: 'blob URL document is navigated back from history (without bfcache on Firefox) cross-origin.',
    118    }),
    119  ].map(f => f(token()));
    120 
    121  let async_promise_test = (promise, description) => {
    122    async_test(test => {
    123      promise(test)
    124        .then(() => {test.done();})
    125        .catch(test.step_func(error => { throw error; }));
    126    }, description);
    127  };
    128 
    129  testCases.forEach(testCase => {
    130    async_promise_test(async t => {
    131      // Create a popup.
    132      let popup = window.open();
    133 
    134      // Closing fails sometimes on Firefox:
    135      // https://bugzilla.mozilla.org/show_bug.cgi?id=1698093
    136      t.add_cleanup(() => { popup.close(); });
    137 
    138      // Perform a real navigation in the popup. This is needed because the
    139      // initial empty document is not stored in history (so there is no way of
    140      // navigating back to it and test history inheritance).
    141      const token_1 = token();
    142      let loaded_1 = message_from(token_1);
    143      popup.location = testCase.other_origin +
    144        `/content-security-policy/inheritance/support` +
    145        `/postmessage-opener.html?token=${token_1}`;
    146      assert_equals(await loaded_1, "ready",
    147                    "Could not open and navigate popup.");
    148 
    149      // Navigate to the local scheme document. We need to wait for the
    150      // navigation to succeed.
    151      let wait = () => t.step_wait(
    152        condition = () => {
    153          try {
    154            return popup.location.href == testCase.url;
    155          } catch {}
    156          return false;
    157        },
    158        description = "Wait for the popup to navigate.",
    159        timeout=3000,
    160        interval=50);
    161 
    162      let message = message_from(testCase.token);
    163      popup.location = testCase.url;
    164      await wait();
    165      if (testCase.add_img_function) {
    166        testCase.add_img_function(popup);
    167      }
    168 
    169      // Check that the local scheme document inherits CSP from the initiator.
    170      assert_equals(await message, "img blocked",
    171                    "Image should be blocked by CSP inherited from navigation initiator.");
    172 
    173      const token_2 = token();
    174      let loaded_2 = message_from(token_2, "ready");
    175      let message_2 = message_from(testCase.token, "img");
    176      // Navigate to another page, which will navigate back.
    177      popup.location = testCase.other_origin +
    178        `/content-security-policy/inheritance/support` +
    179        `/message-opener-and-navigate-back.html?token=${token_2}`;
    180      assert_equals(await loaded_2, "ready",
    181                    "Could not navigate popup.");
    182 
    183      // We need to wait for the history navigation to be performed.
    184      await wait();
    185 
    186      // Check that the "about:blank" document reloaded from history has the
    187      // original CSPs.
    188      if (testCase.add_img_function) {
    189        testCase.add_img_function(popup);
    190      }
    191      assert_equals(await message_2, "img blocked",
    192                    "Image should be blocked by CSP reloaded from history.");
    193    }, "History navigation: " + testCase.name);
    194  });
    195 </script>