tor-browser

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

cross-partition-navigation.https.html (10210B)


      1 <!DOCTYPE html>
      2 <meta charset=utf-8>
      3 <meta name="timeout" content="long">
      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>
      8 <script src="/common/dispatcher/dispatcher.js"></script>
      9 <!-- Pull in executor_path needed by newPopup / newIframe -->
     10 <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"></script>
     11 <!-- Pull in importScript / newPopup / newIframe -->
     12 <script src="/html/anonymous-iframe/resources/common.js"></script>
     13 <script src="resources/common.js"></script>
     14 <body>
     15 <script>
     16 
     17 const navigation_handle_null = "Navigation handle returns null";
     18 const navigation_handle_not_null = "Navigation handle returns not null";
     19 const opener_null_response = "Window.opener is null";
     20 const opener_not_null_response = "Window.opener isn't null";
     21 
     22 const does_blob_url_open_return_handle = (blob_url, response_queue_name) => `
     23  async function test() {
     24    const handle = window.open("${blob_url}")
     25    if (!handle) {
     26      return send("${response_queue_name}", "${navigation_handle_null}");
     27    }
     28 
     29    return send("${response_queue_name}", "${navigation_handle_not_null}");
     30  }
     31  await test();
     32 `;
     33 
     34 const opener_check_frame_html = (noopener_response_queue) => `
     35  <!doctype html>
     36  <!-- dispatcher.js requires the baseURI to be set in order to compute
     37    the server path correctly in the blob URL page. -->
     38  <base href="${window.location.href}">
     39  <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"><\/script>
     40  <script src="/html/anonymous-iframe/resources/common.js"><\/script>
     41  <script src="/common/utils.js"><\/script>
     42  <script src="/common/dispatcher/dispatcher.js"><\/script>
     43  <script>
     44    if (window.opener === null) {
     45      send("${noopener_response_queue}", "${opener_null_response}")
     46    } else {
     47      send("${noopener_response_queue}", "${opener_not_null_response}")
     48    }
     49  <\/script>
     50 `;
     51 
     52 // Tests blob URL window.open for same and cross partition iframes.
     53 promise_test(t => {
     54  return new Promise(async (resolve, reject) => {
     55    try {
     56      // Creates same and cross partition iframes.
     57      const response_queue_uuid = token();
     58      const noopener_response_queue = token();
     59 
     60      const [cross_site_iframe_uuid, same_site_iframe_uuid] =
     61        await create_test_iframes(t, response_queue_uuid);
     62 
     63      const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"});
     64      const blob_url = URL.createObjectURL(blob);
     65 
     66      // Attempt to open blob URL in cross partition iframe.
     67      await send(cross_site_iframe_uuid, does_blob_url_open_return_handle(blob_url, response_queue_uuid));
     68      const response_1 = await receive(response_queue_uuid);
     69      if (response_1 !== navigation_handle_null) {
     70        reject(`Blob URL handle wasn't null in not-same-top-level-site iframe: ${response_1}`);
     71      }
     72      const noopener_response_1 = await receive(noopener_response_queue);
     73      if (noopener_response_1 !== opener_null_response) {
     74        reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`);
     75      }
     76 
     77      // Attempt to open blob URL in same partition iframe.
     78      await send(same_site_iframe_uuid, does_blob_url_open_return_handle(blob_url, response_queue_uuid));
     79      const response_2 = await receive(response_queue_uuid);
     80      if (response_2 !== navigation_handle_not_null) {
     81        reject(`Blob URL wasn't opened in same-top-level-site iframe: ${response_2}`);
     82      }
     83      const noopener_response_2 = await receive(noopener_response_queue);
     84      if (noopener_response_2 !== opener_not_null_response) {
     85        reject(`Blob URL page opener was null in same-top-level-site iframe`);
     86      }
     87      resolve();
     88    } catch (e) {
     89      reject(e);
     90    }
     91  });
     92 }, "Blob URL window.open should enforce noopener for a cross-top-level-site navigation");
     93 
     94 const blob_url_iframe_html = (response_queue_uuid, message) => `
     95  <!doctype html>
     96  <!-- dispatcher.js requires the baseURI to be set in order to compute
     97    the server path correctly in the blob URL page. -->
     98  <base href="${window.location.href}">
     99  <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"><\/script>
    100  <script src="/html/anonymous-iframe/resources/common.js"><\/script>
    101  <script src="/common/utils.js"><\/script>
    102  <script src="/common/dispatcher/dispatcher.js"><\/script>
    103  <script>
    104      send("${response_queue_uuid}", "${message}");
    105  <\/script>
    106 `;
    107 
    108 const create_iframe_with_blob_url = (blob_url, response_queue_uuid) => `
    109  const iframe = document.createElement('iframe');
    110  iframe.src = "${blob_url}";
    111  iframe.onload = () => {
    112    const same_site_message = "same_partition_loaded";
    113    const blob_url_iframe_html = ${blob_url_iframe_html};
    114    const same_top_level_site_blob = new Blob([blob_url_iframe_html("${response_queue_uuid}", same_site_message)], {type : "text/html"});
    115    const same_top_level_site_blob_url = URL.createObjectURL(same_top_level_site_blob);
    116    const iframe2 = document.createElement('iframe');
    117    iframe2.src = same_top_level_site_blob_url;
    118    document.body.appendChild(iframe2);
    119  };
    120  document.body.appendChild(iframe);
    121 `;
    122 
    123 // Tests blob URL subframe navigations for same and cross partition iframes.
    124 promise_test(t => {
    125  return new Promise(async (resolve, reject) => {
    126    try {
    127      // Creates same and cross partition iframes.
    128      const response_queue_uuid = token();
    129      const cross_site_message = "cross_partition_loaded";
    130 
    131      const [cross_site_iframe_uuid, same_site_iframe_uuid] =
    132        await create_test_iframes(t, response_queue_uuid);
    133 
    134      // Create blob URL for the cross-site test.
    135      const cross_site_blob = new Blob([blob_url_iframe_html(response_queue_uuid, cross_site_message)], {type: "text/html"});
    136      const cross_site_blob_url = URL.createObjectURL(cross_site_blob);
    137 
    138      // Attempt to open blob URL in cross partition iframe.
    139      await send(cross_site_iframe_uuid, create_iframe_with_blob_url(cross_site_blob_url, response_queue_uuid));
    140 
    141      const response = await receive(response_queue_uuid);
    142      if (response === cross_site_message) {
    143        reject(`Blob URL subframe navigation succeeded in not-same-top-level-site iframe.`);
    144      }
    145      resolve();
    146    } catch (e) {
    147      reject(e);
    148    }
    149  });
    150 }, "Blob URL should partition subframe navigation.");
    151 
    152 const open_blob_url_window_via_a_click = (blob_url) => `
    153  const link = document.createElement("a");
    154  link.href = "${blob_url}";
    155  link.target = "_blank";
    156  link.rel = "opener";
    157  document.body.appendChild(link);
    158  link.click();
    159 `;
    160 
    161 // Tests blob URL `<a target="_blank" rel="opener">` click for same and cross partition iframes.
    162 promise_test(t => {
    163  return new Promise(async (resolve, reject) => {
    164    try {
    165      // Creates same and cross partition iframes.
    166      const noopener_response_queue = token();
    167 
    168      const [cross_site_iframe_uuid, same_site_iframe_uuid] = await create_test_iframes(t, token());
    169 
    170      const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"});
    171      const blob_url = URL.createObjectURL(blob);
    172 
    173      // Attempt to click blob URL in cross partition iframe.
    174      await send(cross_site_iframe_uuid, open_blob_url_window_via_a_click(blob_url));
    175      const noopener_response_1 = await receive(noopener_response_queue);
    176      if (noopener_response_1 !== opener_null_response) {
    177        reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`);
    178      }
    179 
    180      // Attempt to click blob URL in same partition iframe.
    181      await send(same_site_iframe_uuid, open_blob_url_window_via_a_click(blob_url));
    182      const noopener_response_2 = await receive(noopener_response_queue);
    183      if (noopener_response_2 !== opener_not_null_response) {
    184        reject(`Blob URL page opener was null in same-top-level-site iframe`);
    185      }
    186      resolve();
    187    } catch (e) {
    188      reject(e);
    189    }
    190  });
    191 }, "Blob URL link click should enforce noopener for a cross-top-level-site navigation");
    192 
    193 const open_blob_url_window_via_area_click = (blob_url) => `
    194  const canvas = document.createElement("canvas");
    195  canvas.height = 1;
    196  canvas.width = 1;
    197  const dataURL = canvas.toDataURL();
    198 
    199  const image = document.createElement("img");
    200  image.src = dataURL;
    201  document.body.appendChild(image);
    202 
    203  const map = document.createElement("map");
    204  map.name = "map";
    205  image.useMap = "#map";
    206  document.body.appendChild(map);
    207 
    208  const area = document.createElement("area");
    209  area.shape = "rect";
    210  area.coords = "0,0,1,1";
    211  area.href = "${blob_url}";
    212  area.target = "_blank";
    213  area.rel = "opener";
    214  map.appendChild(area);
    215  area.click();
    216 `;
    217 
    218 // Tests blob URL `<area target="_blank" rel="opener">` click for same and cross partition iframes.
    219 promise_test(t => {
    220  return new Promise(async (resolve, reject) => {
    221    try {
    222      // Creates same and cross partition iframes.
    223      const noopener_response_queue = token();
    224 
    225      const [cross_site_iframe_uuid, same_site_iframe_uuid] = await create_test_iframes(t, token());
    226 
    227      const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"});
    228      const blob_url = URL.createObjectURL(blob);
    229 
    230      // Attempt to click blob URL in cross partition iframe.
    231      await send(cross_site_iframe_uuid, open_blob_url_window_via_area_click(blob_url));
    232      const noopener_response_1 = await receive(noopener_response_queue);
    233      if (noopener_response_1 !== opener_null_response) {
    234        reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`);
    235      }
    236 
    237      // Attempt to click blob URL in same partition iframe.
    238      await send(same_site_iframe_uuid, open_blob_url_window_via_area_click(blob_url));
    239      const noopener_response_2 = await receive(noopener_response_queue);
    240      if (noopener_response_2 !== opener_not_null_response) {
    241        reject(`Blob URL page opener was null in same-top-level-site iframe`);
    242      }
    243      resolve();
    244    } catch (e) {
    245      reject(e);
    246    }
    247  });
    248 }, "Blob URL area element click should enforce noopener for a cross-top-level-site navigation");
    249 
    250 </script>
    251 </body>