tor-browser

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

require-corp.https.html (9572B)


      1 <!doctype html>
      2 <meta name="timeout" content="long">
      3 <title>Cross-Origin-Embedder-Policy header and nested navigable resource without such header</title>
      4 <script src=/resources/testharness.js></script>
      5 <script src=/resources/testharnessreport.js></script>
      6 <script src="/common/get-host-info.sub.js"></script>
      7 <script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
      8 <div id=log></div>
      9 <script>
     10 const HOST = get_host_info();
     11 const BASE = new URL("resources", location).pathname;
     12 
     13 async_test(t => {
     14  const frame = document.createElement("iframe");
     15  t.add_cleanup(() => frame.remove());
     16  frame.src = "/common/blank.html";
     17  document.body.append(frame);
     18  // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
     19  // timeout is used here. Long term all network error handling should be similar and have a
     20  // reliable event.
     21  assert_equals(frame.contentDocument.body.localName, "body");
     22  t.step_wait_func_done(() => frame.contentDocument === null);
     23 }, `"require-corp" top-level: navigating a frame to "none" should fail`);
     24 
     25 async_test(t => {
     26  const frame = document.createElement("iframe");
     27  t.add_cleanup(() => frame.remove());
     28  const bc = new BroadcastChannel(token());
     29  bc.onmessage = t.step_func((event) => {
     30    let payload = event.data;
     31    assert_equals(payload, "loaded");
     32    t.step_wait_func_done(() => frame.contentDocument === null);
     33  });
     34  frame.src = `resources/navigate-require-corp.sub.html?channelName=${bc.name}&to=/common/blank.html`;
     35  document.body.append(frame);
     36  assert_equals(frame.contentDocument.body.localName, "body");
     37 }, `"require-corp" top-level: navigating a frame from "require-corp" to "none" should fail`);
     38 
     39 async_test(t => {
     40  let pageLoaded = false;
     41  const bc = new BroadcastChannel(token());
     42  let finished = false;
     43  bc.onmessage = t.step_func((event) => {
     44    let payload = event.data;
     45    assert_equals(payload, "loaded");
     46    pageLoaded = true;
     47  });
     48 
     49  const bc2 = new BroadcastChannel(token());
     50  bc2.onmessage = t.step_func_done((event) => {
     51    let payload = event.data;
     52    assert_equals(payload, "loaded");
     53    assert_equals(pageLoaded, true);
     54  });
     55 
     56  const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", "noopener");
     57  assert_equals(win, null);
     58 }, `"require-corp" top-level: creating a noopener "none" popup should succeed`);
     59 
     60 async_test(t => {
     61  let pageLoaded = false;
     62  const bc = new BroadcastChannel(token());
     63  bc.onmessage = t.step_func_done((event) => {
     64    pageLoaded = true;
     65    let payload = event.data;
     66    assert_equals(payload, "loaded");
     67  });
     68 
     69  const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=/common/blank.html`, "_blank");
     70  t.add_cleanup(() => win.close());
     71 }, `"require-corp" top-level: creating a "none" popup should succeed.`);
     72 
     73 [
     74  {
     75    "name": "",
     76    "title": "as popup"
     77  },
     78  {
     79    "name": "noopener",
     80    "title": "as noopener popup"
     81  },
     82  {
     83    "name": "clear opener",
     84    "title": "as popup with opener set to null"
     85  }
     86 ].forEach(({name, title}) => {
     87  async_test(t => {
     88    let pageLoaded = false;
     89    const bc = new BroadcastChannel(token());
     90    bc.onmessage = t.step_func(event => {
     91      pageLoaded = true;
     92      const payload = event.data;
     93      assert_equals(payload, "loaded");
     94    });
     95 
     96    const bc2 = new BroadcastChannel(token());
     97    bc2.onmessage = t.step_func_done(event => {
     98      const payload = event.data;
     99      assert_equals(payload, "loaded");
    100      assert_equals(pageLoaded, true);
    101    });
    102 
    103    let clearOpener = "";
    104    if (name === "clear opener") {
    105      clearOpener = "&clearOpener=true"
    106    }
    107 
    108    let noopener = undefined;
    109    if (name === "noopener") {
    110      noopener = "noopener"
    111    }
    112 
    113    const win = window.open(`resources/navigate-require-corp.sub.html?channelName=${bc.name}${clearOpener}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", noopener);
    114    if (name === "noopener") {
    115      assert_equals(win, null);
    116    } else {
    117      t.add_cleanup(() => win.close());
    118    }
    119  }, `"require-corp" top-level (${title}): navigating to "none" should succeed`);
    120 });
    121 
    122 promise_test(async t => {
    123  const response = await fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.js", {mode: "no-cors"});
    124  assert_equals(response.type, "opaque");
    125 }, `"require-corp" top-level: fetch() to CORP: cross-origin response should succeed`);
    126 
    127 promise_test(t => {
    128  return promise_rejects_js(t, TypeError, fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/common/blank.html", {mode: "no-cors"}));
    129 }, `"require-corp" top-level: fetch() to response without CORP should fail`);
    130 
    131 promise_test(t => {
    132  const w = window.open();
    133  return promise_rejects_js(t, w.TypeError, w.fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/common/blank.html", {mode: "no-cors"}));
    134 }, `"require-corp" top-level: fetch() to response without CORP through a WindowProxy should fail`);
    135 
    136 async_test(t => {
    137  let w = window.open();
    138  const frame = w.document.createElement("iframe");
    139  t.add_cleanup(() => {
    140    w.close();
    141    frame.remove();
    142  });
    143  frame.src = "/common/blank.html";
    144  document.body.append(frame);
    145  // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
    146  // timeout is used here. Long term all network error handling should be similar and have a
    147  // reliable event.
    148  assert_equals(frame.contentDocument.body.localName, "body");
    149  t.step_wait_func_done(() => frame.contentDocument === null);
    150 }, `"require-corp" top-level: navigating an iframe to a page without CORP, through a WindowProxy, should fail`);
    151 
    152 async_test(t => {
    153  const frame = document.createElement("iframe");
    154  const id = token();
    155  t.add_cleanup(() => frame.remove());
    156  window.addEventListener('message', t.step_func((e) => {
    157    if (e.data === id) {
    158      // Loaded!
    159      t.done();
    160    }
    161  }));
    162  // REMOTE_ORIGIN is cross-origin, same-site.
    163  frame.src = `${HOST.HTTPS_REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?token=${id}`;
    164  document.body.append(frame);
    165 }, 'CORP: same-site is checked and allowed.');
    166 
    167 async_test(t => {
    168  const frame = document.createElement("iframe");
    169  const id = token();
    170  t.add_cleanup(() => frame.remove());
    171  let loaded = false;
    172  window.addEventListener('message', t.step_func((e) => {
    173    if (e.data === id) {
    174      loaded = true;
    175    }
    176  }));
    177  t.step_timeout(() => {
    178    // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
    179    // timeout is used here. Long term all network error handling should be similar and have a
    180    // reliable event.
    181    assert_false(loaded);
    182    t.done();
    183  }, 2000);
    184 
    185  // NOTESAMESITE_ORIGIN is cross-origin, cross-site.
    186  frame.src = `${HOST.HTTPS_NOTSAMESITE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?token=${id}`;
    187  document.body.append(frame);
    188 }, 'CORP: same-site is checked and blocked.');
    189 
    190 async_test(t => {
    191  const frame = document.createElement("iframe");
    192  const bc = new BroadcastChannel(token());
    193  t.add_cleanup(() => frame.remove());
    194  bc.onmessage = t.step_func_done((event) => {
    195    const payload = event.data;
    196    assert_equals(payload, "loaded");
    197  });
    198 
    199  const dest = `${HOST.ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
    200  // REMOTE_ORIGIN is cross-origin, same-site.
    201  frame.src = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?to=${encodeURIComponent(dest)}`;
    202  document.body.append(frame);
    203 }, 'navigation CORP is checked with the parent frame, not the navigation source - to be allowed');
    204 
    205 async_test(t => {
    206  const frame = document.createElement("iframe");
    207  const bc = new BroadcastChannel(token());
    208  t.add_cleanup(() => frame.remove());
    209  let loaded = false;
    210  bc.onmessage = t.step_func((event) => {
    211    loaded = true;
    212  });
    213  t.step_timeout(() => {
    214    // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
    215    // timeout is used here. Long term all network error handling should be similar and have a
    216    // reliable event.
    217    assert_false(loaded);
    218    t.done();
    219  }, 2000);
    220 
    221  const dest = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
    222  // REMOTE_ORIGIN is cross-origin, same-site.
    223  frame.src = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?to=${encodeURIComponent(dest)}`;
    224  document.body.append(frame);
    225 }, 'navigation CORP is checked with the parent frame, not the navigation source - to be blocked');
    226 
    227 async_test(t => {
    228  const bc = new BroadcastChannel(token());
    229  let loaded = false;
    230  bc.onmessage = t.step_func((event) => {
    231    loaded = true;
    232  });
    233  t.step_timeout(() => {
    234    // Make sure the iframe didn't load. See
    235    // https://github.com/whatwg/html/issues/125 for why a timeout is used
    236    // here. Long term all network error handling should be similar and have a
    237    // reliable event.
    238    assert_false(loaded);
    239    t.done();
    240  }, 2000);
    241 
    242  const dest = `${HOST.ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
    243  const frame = document.createElement("iframe");
    244  t.add_cleanup(() => frame.remove());
    245  // |dest| is a same-origin URL and hence not blocked by CORP but reidirect.py
    246  // is a cross-origin (actually cross-site) URL, so blocked by CORP.
    247  frame.src = `${HOST.HTTPS_NOTSAMESITE_ORIGIN}/common/redirect.py?location=${encodeURIComponent(dest)}`;
    248  document.body.append(frame);
    249 }, 'navigation CORP is checked for each redirect');
    250 
    251 </script>