tor-browser

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

automatic-beacon-helper.js (5051B)


      1 // This is a helper file used for the automatic-beacon-*.https.html tests.
      2 // To use this, make sure you import these scripts:
      3 // <script src="/resources/testharness.js"></script>
      4 // <script src="/resources/testharnessreport.js"></script>
      5 // <script src="/common/utils.js"></script>
      6 // <script src="/common/dispatcher/dispatcher.js"></script>
      7 // <script src="resources/utils.js"></script>
      8 // <script src="/resources/testdriver.js"></script>
      9 // <script src="/resources/testdriver-actions.js"></script>
     10 // <script src="/resources/testdriver-vendor.js"></script>
     11 // <script src="/common/get-host-info.sub.js"></script>
     12 
     13 const NavigationTrigger = {
     14  Click: 0,
     15  ClickOnce: 1,
     16  CrossOriginClick: 2,
     17  CrossOriginClickNoOptIn: 3
     18 };
     19 
     20 // Registers an automatic beacon in a given remote context frame, and registers
     21 // the navigation handler for the frame that will trigger the beacon.
     22 //     remote_context: The context for the fenced frame or URN iframe.
     23 //      beacon_events: An array of FenceEvents to register with the frame.
     24 //     navigation_url: The URL the frame will navigate to.
     25 // navigation_trigger: How the navigation will be performed. Either through a
     26 //                     click, a click with a `once` event, a click in a
     27 //                     cross-origin subframe, or a click in a cross-origin
     28 //                     subframe with no opt-in header.
     29 //             target: the target of the navigation. Either '_blank' or
     30 //                     '_unfencedTop'.
     31 async function setupAutomaticBeacon(
     32    remote_context, beacon_events, navigation_url = 'resources/dummy.html',
     33    navigation_trigger = NavigationTrigger.Click, target = '_blank') {
     34  const full_url = new URL(navigation_url, location.href);
     35  await remote_context.execute(
     36      async (
     37          NavigationTrigger, beacon_events, navigation_trigger, full_url,
     38          target) => {
     39        switch (navigation_trigger) {
     40          case NavigationTrigger.Click:
     41            addEventListener('click', (event) => {
     42              beacon_events.forEach((beacon_event) => {
     43                window.fence.setReportEventDataForAutomaticBeacons(
     44                    beacon_event);
     45              });
     46              window.open(full_url, target);
     47            });
     48            break;
     49          case NavigationTrigger.ClickOnce:
     50            beacon_events.forEach((beacon_event) => {
     51              window.fence.setReportEventDataForAutomaticBeacons(beacon_event);
     52            });
     53            addEventListener('click', (event) => {
     54              window.open(full_url, target);
     55            });
     56            break;
     57          case NavigationTrigger.CrossOriginClick:
     58          case NavigationTrigger.CrossOriginClickNoOptIn:
     59            beacon_events.forEach((beacon_event) => {
     60              window.fence.setReportEventDataForAutomaticBeacons(beacon_event);
     61            });
     62            // Add a cross-origin iframe that will perform the top-level
     63            // navigation.
     64            const iframe = await attachIFrameContext({
     65              origin: get_host_info().HTTPS_REMOTE_ORIGIN,
     66              headers: [[
     67                'Allow-Fenced-Frame-Automatic-Beacons',
     68                navigation_trigger == NavigationTrigger.CrossOriginClick ?
     69                    'true' :
     70                    'false'
     71              ]]
     72            });
     73            await iframe.execute(async (full_url, target) => {
     74              addEventListener('click', (event) => {
     75                window.open(full_url, target);
     76              });
     77            }, [full_url, target]);
     78            break;
     79        }
     80      },
     81      [NavigationTrigger, beacon_events, navigation_trigger, full_url, target]);
     82 }
     83 
     84 // Checks if an automatic beacon of type `event_type` with contents `event_data`
     85 // was sent out or not.
     86 //        event_type: The automatic beacon type to check.
     87 //        event_data: The automatic beacon data to check.
     88 // expected_referrer: The expected referrer header, if different from origin.
     89 //  expected_success: Whether we expect the automatic beacon to be sent.
     90 //                 t: The WPT's test object. Only required if
     91 //                   expected_success = false.
     92 async function verifyBeaconData(
     93    event_type, event_data, expected_referrer = null, expected_success = true,
     94    t) {
     95  if (expected_success) {
     96    const data = await nextBeacon(event_type, event_data);
     97    const [beacon_initiator_origin, beacon_referrer] =
     98        data.split(",");
     99    assert_equals(beacon_initiator_origin, get_host_info().HTTPS_ORIGIN,
    100        "The initiator origin should be set as expected.");
    101    // The Referer header has a trailing '/' appended to the URL.
    102    assert_equals(beacon_referrer,
    103        (expected_referrer ? expected_referrer :
    104        get_host_info().HTTPS_ORIGIN) + "/",
    105        "The beacon referrer should be set as expected.");
    106  } else {
    107    const timeout = new Promise(r => t.step_timeout(r, 1000));
    108    const result =
    109        await Promise.race([nextBeacon(event_type, event_data), timeout]);
    110    assert_true(typeof result === 'undefined',
    111        "The beacon should not have sent.");
    112  }
    113 }