tor-browser

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

loaf-source-location-redirect.html (3417B)


      1 <!DOCTYPE HTML>
      2 <meta charset=utf-8>
      3 <title>Long Animation Frame Timing: source location should not expose cross-origin redirects</title>
      4 <meta name="timeout" content="long">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/common/utils.js"></script>
      8 <script src="/common/get-host-info.sub.js"></script>
      9 <script src="resources/utils.js"></script>
     10 
     11 <body>
     12 <h1>Long Animation Frame: source location with cross-origin redirects</h1>
     13 <div id="log"></div>
     14 <script>
     15 
     16 const {REMOTE_ORIGIN} = get_host_info();
     17 
     18 function corsify(url, cors) {
     19  if (!cors)
     20    return url.href;
     21  url.searchParams.set("pipe", "header(Access-Control-Allow-Origin, *)");
     22  return url.href;
     23 }
     24 
     25 const targetURL = (path, cors) =>
     26  corsify(new URL(path, REMOTE_ORIGIN), cors);
     27 
     28 function crossOriginRedirectURL(path, cors) {
     29  const url = new URL(`/common/redirect.py`, REMOTE_ORIGIN);
     30  url.searchParams.set("location", targetURL(path, cors));
     31  return corsify(url, cors);
     32 }
     33 
     34 function test_source_location_with_redirect({path, type, name}) {
     35  for (let scriptType of ["classic-opaque", "classic-cors", "module"]) {
     36    const cors = scriptType !== "classic-opaque";
     37    promise_test(async t => {
     38      const VERY_LONG_FRAME_DURATION = 360;
     39      const preRedirectURL = crossOriginRedirectURL(path, cors);
     40      const postRedirectURL = targetURL(path, cors);
     41      let [entry, script] = await expect_long_frame_with_script((t, busy_wait) => {
     42        const script = document.createElement("script");
     43        script.src = preRedirectURL;
     44        if (scriptType === "module")
     45          script.type = "module";
     46        else if (cors)
     47          script.crossOrigin = "anonymous";
     48        document.body.appendChild(script);
     49        t.add_cleanup(() => script.remove());
     50      }, script => script.duration >= VERY_LONG_FRAME_DURATION - 5, t);
     51 
     52      const result =
     53        script.sourceURL.startsWith(postRedirectURL) ? "post-redirect" :
     54        script.sourceURL.startsWith(preRedirectURL) ? "pre-redirect" :
     55        script.sourceURL === "" ?
     56        "empty" : "other";
     57 
     58      assert_not_equals(result, "other", `Unexpected source location ${script.sourceURL}`);
     59      if (!cors)
     60        assert_equals(script.executionStart, script.startTime, "Opaque scripts should hide execution start time");
     61 
     62      if (cors) {
     63        assert_not_equals(result, "empty", "CORS-ok scripts should expose sourceLocation");
     64      } else {
     65        assert_equals(result, "pre-redirect", "No-CORS classic scripts should expose pre-redirect URL");
     66        assert_equals(script.sourceCharPosition, type === "script-block" || type === "resolve-promise" ? 0 : -1, "No-CORS classic scripts should not expose character index");
     67      }
     68    }, `Test ${type} with ${scriptType}`);
     69  }
     70 }
     71 
     72 test_source_location_with_redirect({
     73  path: "/long-animation-frame/resources/busy.js",
     74  type: "script-block"
     75 });
     76 
     77 test_source_location_with_redirect({
     78  path: "/long-animation-frame/resources/raf-generates-loaf.js",
     79  name: "FrameRequestCallback",
     80  type: "user-callback"
     81 });
     82 test_source_location_with_redirect({
     83  path: "/long-animation-frame/resources/event-generates-loaf.js",
     84  type: "event-listener",
     85  name: "XMLHttpRequest.onload"
     86 });
     87 
     88 test_source_location_with_redirect({
     89  path: "/long-animation-frame/resources/promise-generates-loaf.js",
     90  type: "resolve-promise",
     91  name: "Window.fetch.then"
     92 });
     93 
     94 </script>
     95 </body>