tor-browser

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

echo-client-hints-received.py (2640B)


      1 """ Handle the initiator navigation request and attach the received client info
      2 to the returned page.
      3 """
      4 
      5 
      6 import textwrap
      7 
      8 html_template = """
      9 <!DOCTYPE html>
     10 <html>
     11 <head>
     12 <title>echo client hints on prerendering page</title>
     13 </head>
     14 <script src="/speculation-rules/prerender/resources/utils.js"></script>
     15 <body>
     16 <script>
     17 
     18 // Allow generator to add the received CH information into this script.
     19 %s
     20 const params = new URLSearchParams(location.search);
     21 const uid = params.get('uid');
     22 
     23 // Performs the check below on initiator pages:
     24 // 1. The client did not send server_received_full_version_list when fetching
     25 //    the initiator page.
     26 // If the check fails, it will ask the main test page to terminate the test.
     27 // Otherwise, it will:
     28 // 1. Initiate a prerendering action. And the prerendering page will perform
     29 //    some checks.
     30 // 2. Wait for the prerendering page to pass all checks and send a signal back.
     31 // 3. Activate the prerendered page.
     32 async function load_as_initiator_page() {
     33  if (!server_received_bitness || server_received_full_version_list) {
     34    // The initial headers are not as expected. Terminate the test.
     35    failTest(
     36        `unexpected initial headers.
     37             bitness: ${server_received_bitness},
     38             full_version: ${server_received_full_version_list}`,
     39        uid);
     40    return;
     41  }
     42  const prerendering_url =
     43      `./echo-prerender-page-client-hints-received.py?uid=${uid}`;
     44  // Wait for the prerendered page to be ready for activation.
     45  const bc = new PrerenderChannel('prerender-channel', uid);
     46  const gotMessage = new Promise(resolve => {
     47    bc.addEventListener('message', e => {
     48      resolve(e.data);
     49    }, {once: true});
     50  });
     51  startPrerendering(prerendering_url);
     52 
     53  data = await gotMessage;
     54  if (data == 'ready for activation') {
     55    window.location = prerendering_url;
     56  } else {
     57    failTest(`Initial page received unexpected result: ${data}`, uid);
     58  }
     59 }
     60 
     61 load_as_initiator_page();
     62 
     63 </script>
     64 </body>
     65 </html>
     66 """
     67 
     68 def translate_to_js(val: bool) -> str:
     69    if isinstance(val, bool):
     70        return "true" if val else "false"
     71    return ""
     72 
     73 def main(request, response):
     74    response.status = 200
     75 
     76    # Insert the received hints into script.
     77    content = html_template % (
     78        textwrap.dedent(
     79            f"""
     80            const server_received_bitness =
     81                {translate_to_js(b"sec-ch-ua-bitness" in request.headers)};
     82            const server_received_full_version_list =
     83                {translate_to_js(b"sec-ch-ua-full-version-list" in
     84                    request.headers)};
     85            """
     86        )
     87    )
     88    response.content = content.encode("utf-8")