tor-browser

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

task-attribution.html (5850B)


      1 <!doctype html>
      2 <html>
      3  <head>
      4    <meta charset="utf-8" />
      5    <title>Soft Navigation Detection: Task Attribution.</title>
      6    <script src="/resources/testharness.js"></script>
      7    <script src="/resources/testharnessreport.js"></script>
      8    <script src="/resources/testdriver.js"></script>
      9    <script src="/resources/testdriver-vendor.js"></script>
     10    <script>
     11      // Appends a new div with a greeting to the document body.
     12      function updateUI() {
     13        const greeting = document.createElement("div");
     14        greeting.textContent = "Hello, World.";
     15        document.body.appendChild(greeting);
     16      }
     17 
     18      // Basic soft navigation (see basic.html) which directly does its work
     19      // in the click handler. This is our baseline - the methods below
     20      // differ in that they require propagating the soft navigation attribution
     21      // to a different task.
     22      function noSchedulingHop() {
     23        updateUI();
     24        history.pushState({}, "", "/no-scheduling-hop");
     25      }
     26 
     27      // A soft navigation where the click handler schedules its work with
     28      // setTimeout, 0ms delay.
     29      // https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
     30      function withSetTimeout0() {
     31        setTimeout(() => {
     32          updateUI();
     33          history.pushState({}, "", "/with-set-timeout-0");
     34        }, 0);
     35      }
     36 
     37      // A soft navigation where the click handler schedules its work with
     38      // setTimeout, 10ms delay.
     39      // https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
     40      function withSetTimeout10() {
     41        setTimeout(() => {
     42          updateUI();
     43          history.pushState({}, "", "/with-set-timeout-10");
     44        }, 10);
     45      }
     46 
     47      // A soft navigation where the click handler schedules its work with
     48      // two setTimeouts.
     49      // https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
     50      function twoSetTimeouts() {
     51        setTimeout(updateUI, 20);
     52        setTimeout(() => {
     53          history.pushState({}, "", "/two-set-timeouts");
     54        }, 10);
     55      }
     56 
     57      // A soft navigation where the click handler schedules its UI work with
     58      // setTimeout and the URL update with a sync history.pushState call.
     59      // https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
     60      function setTimeoutAndSyncUrlUpdate() {
     61        setTimeout(updateUI, 10);
     62        history.pushState({}, "", "/set-timeout-and-sync-url-update");
     63      }
     64 
     65      // A soft navigation where the click handler schedules its work with
     66      // scheduler.postTask.
     67      // https://developer.mozilla.org/en-US/docs/Web/API/Scheduler/postTask
     68      function withSchedulerPostTask() {
     69        scheduler.postTask(() => {
     70          updateUI();
     71          history.pushState({}, "", "/with-scheduler-post-task");
     72        });
     73      }
     74 
     75      // A soft navigation where the click handler yields
     76      // (using scheduler.yield) between URL and UI update.
     77      async function withSchedulerYield() {
     78        history.pushState({}, "", "/with-scheduler-yield");
     79        await scheduler.yield();
     80        updateUI();
     81      }
     82 
     83      // A soft navigation where the click handler schedules its work with
     84      // requestAnimationFrame.
     85      // https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
     86      function withRequestAnimationFrame() {
     87        requestAnimationFrame(() => {
     88          updateUI();
     89          history.pushState({}, "", "/with-request-animation-frame");
     90        });
     91      }
     92    </script>
     93  </head>
     94  <body>
     95    <div id="no-scheduling-hop" onclick="noSchedulingHop()">Click here!</div>
     96    <div id="with-set-timeout-0" onclick="withSetTimeout0()">Click here!</div>
     97    <div id="with-set-timeout-10" onclick="withSetTimeout10()">Click here!</div>
     98    <div id="two-set-timeouts" onclick="twoSetTimeouts()">Click here!</div>
     99    <div id="set-timeout-and-sync-url-update" onclick="setTimeoutAndSyncUrlUpdate()">
    100      Click here!
    101    </div>
    102    <div id="with-scheduler-post-task" onclick="withSchedulerPostTask()">Click here!</div>
    103    <div id="with-scheduler-yield" onclick="withSchedulerYield()">Click here!</div>
    104    <div id="with-request-animation-frame" onclick="withRequestAnimationFrame()">Click here!</div>
    105 
    106    <script>
    107      function test_template(test_id, description) {
    108        promise_test(async (t) => {
    109          let entries;
    110          new PerformanceObserver((list, observer) => {
    111            entries = list.getEntries();
    112            observer.disconnect();
    113          }).observe({ type: "soft-navigation" });
    114          if (test_driver) {
    115            test_driver.click(document.getElementById(test_id));
    116          }
    117          await t.step_wait(() => entries !== undefined, "Soft navigation event not fired.");
    118 
    119          assert_equals(entries.length, 1, "Expected exactly one soft navigation.");
    120          assert_equals(
    121            entries[0].name.replace(/.*\//, ""),
    122            test_id,
    123            "URL should end with the test ID.",
    124          );
    125        }, description);
    126      }
    127 
    128      test_template("no-scheduling-hop", "No scheduling hop.");
    129      test_template("with-set-timeout-0", "With set_timeout, 0ms delay.");
    130      test_template("with-set-timeout-10", "With set_timeout, 10ms delay.");
    131      test_template("two-set-timeouts", "With two set_timeouts.");
    132      test_template("set-timeout-and-sync-url-update", "With set_timeout and sync URL update.");
    133      if (scheduler.postTask) {
    134        // Skip test if scheduler.postTask is not supported.
    135        test_template("with-scheduler-post-task", "With scheduler.postTask.");
    136      }
    137      if (scheduler.yield) {
    138        // Skip test if scheduler.yield is not supported.
    139        test_template("with-scheduler-yield", "With scheduler.yield.");
    140      }
    141      test_template("with-request-animation-frame", "With requestAnimationFrame.");
    142    </script>
    143  </body>
    144 </html>