| // This is a helper file used for the automatic-beacon-*.https.html tests. |
| // To use this, make sure you import these scripts: |
| // <script src="/resources/testharness.js"></script> |
| // <script src="/resources/testharnessreport.js"></script> |
| // <script src="/common/utils.js"></script> |
| // <script src="/common/dispatcher/dispatcher.js"></script> |
| // <script src="resources/utils.js"></script> |
| // <script src="/resources/testdriver.js"></script> |
| // <script src="/resources/testdriver-actions.js"></script> |
| // <script src="/resources/testdriver-vendor.js"></script> |
| // <script src="/common/get-host-info.sub.js"></script> |
| |
| const NavigationTrigger = { |
| Click: 0, |
| ClickOnce: 1, |
| CrossOriginClick: 2, |
| CrossOriginClickNoOptIn: 3 |
| }; |
| |
| // Registers an automatic beacon in a given remote context frame, and registers |
| // the navigation handler for the frame that will trigger the beacon. |
| // remote_context: The context for the fenced frame or URN iframe. |
| // beacon_events: An array of FenceEvents to register with the frame. |
| // navigation_url: The URL the frame will navigate to. |
| // navigation_trigger: How the navigation will be performed. Either through a |
| // click, a click with a `once` event, a click in a |
| // cross-origin subframe, or a click in a cross-origin |
| // subframe with no opt-in header. |
| // target: the target of the navigation. Either '_blank' or |
| // '_unfencedTop'. |
| async function setupAutomaticBeacon( |
| remote_context, beacon_events, navigation_url = 'resources/dummy.html', |
| navigation_trigger = NavigationTrigger.Click, target = '_blank') { |
| const full_url = new URL(navigation_url, location.href); |
| await remote_context.execute( |
| async ( |
| NavigationTrigger, beacon_events, navigation_trigger, full_url, |
| target) => { |
| switch (navigation_trigger) { |
| case NavigationTrigger.Click: |
| addEventListener('click', (event) => { |
| beacon_events.forEach((beacon_event) => { |
| window.fence.setReportEventDataForAutomaticBeacons( |
| beacon_event); |
| }); |
| window.open(full_url, target); |
| }); |
| break; |
| case NavigationTrigger.ClickOnce: |
| beacon_events.forEach((beacon_event) => { |
| window.fence.setReportEventDataForAutomaticBeacons(beacon_event); |
| }); |
| addEventListener('click', (event) => { |
| window.open(full_url, target); |
| }); |
| break; |
| case NavigationTrigger.CrossOriginClick: |
| case NavigationTrigger.CrossOriginClickNoOptIn: |
| beacon_events.forEach((beacon_event) => { |
| window.fence.setReportEventDataForAutomaticBeacons(beacon_event); |
| }); |
| // Add a cross-origin iframe that will perform the top-level |
| // navigation. |
| const iframe = await attachIFrameContext({ |
| origin: get_host_info().HTTPS_REMOTE_ORIGIN, |
| headers: [[ |
| 'Allow-Fenced-Frame-Automatic-Beacons', |
| navigation_trigger == NavigationTrigger.CrossOriginClick ? |
| 'true' : |
| 'false' |
| ]] |
| }); |
| await iframe.execute(async (full_url, target) => { |
| addEventListener('click', (event) => { |
| window.open(full_url, target); |
| }); |
| }, [full_url, target]); |
| break; |
| } |
| }, |
| [NavigationTrigger, beacon_events, navigation_trigger, full_url, target]); |
| } |
| |
| // Checks if an automatic beacon of type `event_type` with contents `event_data` |
| // was sent out or not. |
| // event_type: The automatic beacon type to check. |
| // event_data: The automatic beacon data to check. |
| // expected_referrer: The expected referrer header, if different from origin. |
| // expected_success: Whether we expect the automatic beacon to be sent. |
| // t: The WPT's test object. Only required if |
| // expected_success = false. |
| async function verifyBeaconData( |
| event_type, event_data, expected_referrer = null, expected_success = true, |
| t) { |
| if (expected_success) { |
| const data = await nextBeacon(event_type, event_data); |
| const [beacon_initiator_origin, beacon_referrer] = |
| data.split(","); |
| assert_equals(beacon_initiator_origin, get_host_info().HTTPS_ORIGIN, |
| "The initiator origin should be set as expected."); |
| // The Referer header has a trailing '/' appended to the URL. |
| assert_equals(beacon_referrer, |
| (expected_referrer ? expected_referrer : |
| get_host_info().HTTPS_ORIGIN) + "/", |
| "The beacon referrer should be set as expected."); |
| } else { |
| const timeout = new Promise(r => t.step_timeout(r, 1000)); |
| const result = |
| await Promise.race([nextBeacon(event_type, event_data), timeout]); |
| assert_true(typeof result === 'undefined', |
| "The beacon should not have sent."); |
| } |
| } |