tor-browser

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

history-iframe.sub.html (6545B)


      1 <!DOCTYPE html>
      2 <meta name="timeout" content="long">
      3 
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="/common/utils.js"></script>
      7 
      8 <meta http-equiv="Content-Security-Policy" content="img-src 'none'">
      9 <body>
     10 <script>
     11  let message_from = (source_token, starts_with) => {
     12    return new Promise(resolve => {
     13      window.addEventListener('message', msg => {
     14        if (msg.data.token === source_token) {
     15          if (!starts_with || msg.data.msg.startsWith(starts_with))
     16            resolve(msg.data.msg);
     17        }
     18      });
     19    });
     20  };
     21 
     22  const img_url = window.origin + "/content-security-policy/support/fail.png";
     23 
     24  const img_tag_string = img_token => `
     25    <img src="${img_url}"
     26         onload="top.postMessage(
     27             {msg: 'img loaded', token: '${img_token}'}, '*');"
     28         onerror="top.postMessage(
     29             {msg: 'img blocked', token: '${img_token}'}, '*');"
     30    >
     31   `;
     32 
     33  const html_test_payload = img_token => `
     34    <!doctype html>
     35    <script>
     36      function add_image() {
     37        let img = document.createElement('img');
     38        img.onload = () => top.postMessage(
     39            {msg: 'img loaded', token: '${img_token}'}, '*');
     40        img.onerror = () => top.postMessage(
     41            {msg: 'img blocked', token: '${img_token}'}, '*');
     42        img.src = '${img_url}';
     43        document.body.appendChild(img);
     44      }
     45    </scr`+`ipt>
     46    <body onpageshow="add_image();"></body>
     47  `;
     48  let blob_url = blob_token => URL.createObjectURL(
     49    new Blob([html_test_payload(blob_token)], { type: 'text/html' }));
     50 
     51  let write_img_to_about_blank = async (t, iframe, img_token) => {
     52    await t.step_wait(
     53      condition = () => {
     54        try {
     55          return iframe.contentWindow.location.href == "about:blank";
     56        } catch {}
     57        return false;
     58      },
     59      description = "Wait for the iframe to navigate.",
     60      timeout=6000,
     61      interval=50);
     62 
     63    let div = iframe.contentDocument.createElement('div');
     64    div.innerHTML = img_tag_string(img_token);
     65    iframe.contentDocument.body.appendChild(div);
     66  };
     67 
     68  let testCases = [
     69    test_token => ({
     70      token: test_token,
     71      url: "about:blank",
     72      add_img_function: (t, iframe) =>
     73          write_img_to_about_blank(t, iframe, test_token),
     74      other_origin: window.origin,
     75      name: '"about:blank" document is navigated back from history same-origin.',
     76    }),
     77    test_token => ({
     78      token: test_token,
     79      url: "about:blank",
     80      add_img_function: (t, iframe) =>
     81          write_img_to_about_blank(t, iframe, test_token),
     82      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
     83      name: '"about:blank" document is navigated back from history cross-origin.',
     84    }),
     85    test_token => ({
     86      token: test_token,
     87      url: blob_url(test_token),
     88      other_origin: window.origin,
     89      name: 'blob URL document is navigated back from history same-origin.',
     90    }),
     91    test_token => ({
     92      token: test_token,
     93      url: blob_url(test_token),
     94      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
     95      name: 'blob URL document is navigated back from history cross-origin.',
     96    }),
     97    test_token => ({
     98      token: test_token,
     99      url: `data:text/html,${html_test_payload(test_token)}`,
    100      other_origin: window.origin,
    101      name: 'data URL document is navigated back from history same-origin.',
    102    }),
    103    test_token => ({
    104      token: test_token,
    105      url: `data:text/html,${html_test_payload(test_token)}`,
    106      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
    107      name: 'data URL document is navigated back from history cross-origin.',
    108    }),
    109    test_token => ({
    110      token: test_token,
    111      srcdoc: `${html_test_payload(test_token)}`,
    112      other_origin: window.origin,
    113      name: 'srcdoc iframe is navigated back from history same-origin.',
    114    }),
    115    test_token => ({
    116      token: test_token,
    117      srcdoc: `${html_test_payload(test_token)}`,
    118      other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}",
    119      name: 'srcdoc iframe is navigated back from history cross-origin.',
    120    }),
    121  ].map(f => f(token()));
    122 
    123  testCases.forEach(testCase => {
    124    promise_test(async t => {
    125      // Create an iframe.
    126      let iframe = document.createElement('iframe');
    127      document.body.appendChild(iframe);
    128 
    129      // Perform a real navigation in the iframe. This is needed because the
    130      // initial empty document is not stored in history (so there is no way of
    131      // navigating back to it and test history inheritance).
    132      const token_1 = token();
    133      let loaded_1 = message_from(token_1);
    134      iframe.contentWindow.location = testCase.other_origin +
    135        "/content-security-policy/inheritance/support" +
    136        `/postmessage-top.html?token=${token_1}`;
    137      assert_equals(await loaded_1, "ready",
    138                    "Could not navigate iframe.");
    139 
    140      // Navigate to the local scheme document.
    141      let message = message_from(testCase.token);
    142      if (testCase.url)
    143        iframe.contentWindow.location = testCase.url;
    144      else
    145        iframe.srcdoc = testCase.srcdoc;
    146 
    147      // If the local scheme document is "about:blank", we need to write its
    148      // content now.
    149      if (testCase.add_img_function) {
    150        testCase.add_img_function(t, iframe);
    151      }
    152 
    153      // Check that the local scheme document inherits CSP from the initiator.
    154      assert_equals(await message, "img blocked",
    155                    "Image should be blocked by CSP inherited from navigation initiator.");
    156 
    157      // Navigate to another page, which will navigate back.
    158      const token_2 = token();
    159      let loaded_2 = message_from(token_2, "ready");
    160      let message_2 = message_from(testCase.token, "img");
    161      iframe.contentWindow.location = testCase.other_origin +
    162        "/content-security-policy/inheritance/support" +
    163        `/message-top-and-navigate-back.html?token=${token_2}`;
    164      assert_equals(await loaded_2, "ready",
    165                    "Could not navigate iframe.");
    166 
    167      // If the local scheme document is "about:blank", we need to write its
    168      // content again.
    169      if (testCase.add_img_function) {
    170        testCase.add_img_function(t, iframe);
    171      }
    172 
    173      // Check that the local scheme document reloaded from history still has
    174      // the original CSPs.
    175      assert_equals(await message_2, "img blocked",
    176                    "Image should be blocked by CSP reloaded from history.");
    177    }, "History navigation in iframe: " + testCase.name);
    178  });
    179 </script>
    180 </body>