tor-browser

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

echo-prerender-page-client-hints-received.py (3418B)


      1 """ Handle the prerendering navigation request and insert the received client
      2 info to the returned page.
      3 """
      4 
      5 import textwrap
      6 
      7 html_template = """
      8 <!DOCTYPE html>
      9 <html>
     10 <head>
     11 <title>echo client hints on prerendering page</title>
     12 </head>
     13 <script src="/speculation-rules/prerender/resources/utils.js"></script>
     14 <body>
     15 <script>
     16 
     17 // Allow generator to add the received CH information into this script.
     18 %s
     19 
     20 const params = new URLSearchParams(location.search);
     21 const uid = params.get('uid');
     22 
     23 // Performs the following checks on prerendering pages:
     24 // 1. The client did not send server_received_full_version_list when fetching
     25 //    the prerendering main resource.
     26 // 2. The request initiated by the prerendering page is sent with
     27 //    sec-ch-ua-full-version-list attached, because the server asked the
     28 //    prerendering page to attach this hint for the following requests.
     29 // If any of the checks fails, it will ask the main test page to terminate
     30 // the test.
     31 // Otherwise, it asks the initiator page to perform activation, and informs
     32 // the main test page of the test success upon being activated. This is used
     33 // to verify that the initiator page's client hints cache is not modified by
     34 // the prerendering page, i.e., the initiator page does not attach
     35 // sec-ch-ua-full-version-list to the requests.
     36 async function load_as_prerendering_page() {
     37  // The first prerendering request should not contain the field of
     38  // sec-ch-ua-full-version-list, as prerender is initiated by the initial
     39  // page.
     40  if (!server_received_bitness || server_received_full_version_list) {
     41    failTest(
     42        `Prerender page saw unexpected request headers.
     43             bitness: ${server_received_bitness},
     44             full_version: ${server_received_full_version_list}`,
     45        uid);
     46  }
     47  const r =
     48      await fetch('../resources/echo-subresource-client-hints-received.py');
     49  if (r.status != 200 || r.headers.get('server_received_bitness') !== 'true' ||
     50      r.headers.get('server_received_full_version_list') !== 'true') {
     51    failTest(
     52        `Prerender page saw unexpected headers while fetching
     53             sub-resources.
     54             bitness: ${r.headers.get('server_received_bitness')},
     55             full_version: ${
     56            r.headers.get('server_received_full_version_list')}`,
     57        uid);
     58  } else {
     59    document.onprerenderingchange = () => {
     60      const bc = new PrerenderChannel('test-channel', uid);
     61      // Send the result to the test runner page.
     62      bc.postMessage({result: 'PASSED'});
     63    };
     64    const bc = new PrerenderChannel('prerender-channel', uid);
     65    bc.postMessage('ready for activation');
     66  }
     67 }
     68 
     69 load_as_prerendering_page();
     70 </script>
     71 </body>
     72 </html>
     73 """
     74 
     75 def translate_to_js(val: bool) -> str:
     76    if isinstance(val, bool):
     77        return "true" if val else "false"
     78    return ""
     79 
     80 def main(request, response):
     81    response.headers.set(b"Accept-CH", "sec-ch-ua-full-version-list")
     82    response.status = 200
     83 
     84    # Insert the received hints into script.
     85    content = html_template % (
     86        textwrap.dedent(
     87            f"""
     88            const server_received_bitness =
     89                {translate_to_js(b"sec-ch-ua-bitness" in request.headers)};
     90            const server_received_full_version_list =
     91                {translate_to_js(b"sec-ch-ua-full-version-list" in
     92                    request.headers)};
     93            """
     94        )
     95    )
     96    response.content = content.encode("utf-8")