Skip to content

Commit

Permalink
Reland "Cross-origin support for window.fence.reportEvent()." (#45554)
Browse files Browse the repository at this point in the history
This is a reland of commit 280fe80c08b919b9cb7ba8228b1b0323ce5bceea.

There is a known flakiness issue with tests that involve loading
cross-origin subframes with remote context executors. The way we
historically have fixed that is by splitting up each promise_test into a
separate file. This CL attempts to fix that flakiness by doing just
that.

Original change's description:
> Cross-origin support for window.fence.reportEvent().
>
> Third-party ad serving (3PAS) lets advertisers manage ads across
> different bidding platforms. However, the event-level reporting API
> (reportEvent()) currently prevents direct reporting from documents
> that are cross-origin to the root ad frame's fenced frame config's
> mapped URL, limiting this functionality for the 3PAS use case. This CL
> extends the reportEvent() API to support this use case.
>
> To allow cross-origin reporting while still preserving privacy, both
> the ad frame and the 3PAS subframe must explicitly opt in. The ad
> frame opts in using a new `Allow-Cross-Origin-Event-Reporting`
> response header, while the 3PAS subframe opts in by calling
> reportEvent() with `crossOriginExposed=true`. If both opt-ins are
> present, then the reportEvent() call from the 3PAS document will
> succeed.
>
> This CL adds histograms to track how many beacons are sent from
> documents that are same-origin and cross-origin to the fenced frame
> config's mapped url.
>
> This CL also expands the fenced frame WPT system to support
> content-initiated navigations of fenced frame contexts to cross-origin
> URLs.
>
> Change-Id: I4e895bec4cb77604e2017cfc67b496d59863a30b
> Bug: 331844131

Bug: 331844131
Change-Id: Iacf17786ba5471faff15252c87e1924698ab4583
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5425335
Reviewed-by: Dominic Farolino <[email protected]>
Reviewed-by: Arthur Sonzogni <[email protected]>
Reviewed-by: Garrett Tanzer <[email protected]>
Reviewed-by: Tarun Bansal <[email protected]>
Commit-Queue: Liam Brady <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1283165}

Co-authored-by: Liam Brady <[email protected]>
  • Loading branch information
chromium-wpt-export-bot and Liam Brady authored Apr 10, 2024
1 parent 2c7c60f commit a57b6bd
Show file tree
Hide file tree
Showing 12 changed files with 570 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
const fencedframe = await attachFencedFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'true'
]],
register_beacon: true,
origin: get_host_info().HTTPS_ORIGIN
});
// Perform a cross-origin navigation. Since the navigation is
// content-initiated, the fenced frame reporting metadata will persist.
await navigateFrameContext(fencedframe, {
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await fencedframe.execute(() => {
// This page will call reportEvent() twice. Once for a destination enum
// event (i.e. an event with an eventType/eventData specified), and once for
// a destination URL event (i.e. an event with a destinationURL specified).
const destination_enum_event = {
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
}
window.fence.reportEvent(destination_enum_event);

const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
const destination_url_event = {
destinationURL: destination_url,
crossOriginExposed: true
}
window.fence.reportEvent(destination_url_event);
});
await nextBeacon("click", "enum");
await nextBeacon("url", "<No data>");
}, 'window.fence.reportEvent from a content-initiated cross-origin navigation');
</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from nested cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
// This test creates the following frame setup:
// ┌(test)─────────────────┐
// │┌(a.com)───[iframe]───┐│
// ││┌(b.com)──[iframe]──┐││
// │││┌(b.com)─[iframe]─┐│││
// ││││reportEvent(); ││││
// │││└─────────────────┘│││
// ││└───────────────────┘││
// │└─────────────────────┘│
// └───────────────────────┘
const fencedframe = await attachIFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'true'
]],
register_beacon: true
});
await fencedframe.execute(async () => {
const iframe = await attachIFrameContext({
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await iframe.execute(async () => {
const nested_iframe = await attachIFrameContext({
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await nested_iframe.execute(() => {
const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
window.fence.reportEvent({
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
});
window.fence.reportEvent({
destinationURL: destination_url,
crossOriginExposed: true
});
});
});
});
// Check that both the destination enum and destination URL events were
// reported.
await nextBeacon("click", "enum");
await nextBeacon("url", "<No data>");
}, 'window.fence.reportEvent from a nested cross-origin subframe of a URN ' +
'iframe');
</script>
</body>
61 changes: 61 additions & 0 deletions fenced-frame/fence-report-event-cross-origin-nested.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from nested cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
// This test creates the following frame setup:
// ┌(test)──────────────────────┐
// │┌(a.com)───[fencedframe]───┐│
// ││┌(b.com)──[iframe]───────┐││
// │││┌(b.com)─[iframe]──────┐│││
// ││││reportEvent(); ││││
// │││└──────────────────────┘│││
// ││└────────────────────────┘││
// │└──────────────────────────┘│
// └────────────────────────────┘
const fencedframe = await attachFencedFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'true'
]],
register_beacon: true
});
await fencedframe.execute(async () => {
const iframe = await attachIFrameContext({
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await iframe.execute(async () => {
const nested_iframe = await attachIFrameContext({
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await nested_iframe.execute(() => {
const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
window.fence.reportEvent({
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
});
window.fence.reportEvent({
destinationURL: destination_url,
crossOriginExposed: true
});
});
});
});
// Check that both the destination enum and destination URL events were
// reported.
await nextBeacon("click", "enum");
await nextBeacon("url", "<No data>");
}, 'window.fence.reportEvent from a nested cross-origin subframe');
</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
const fencedframe = await attachFencedFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'false'
]],
register_beacon: true
});
// Perform a cross-origin navigation. Since the navigation is
// content-initiated, the fenced frame reporting metadata will persist.
await navigateFrameContext(fencedframe, {
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await fencedframe.execute(() => {
// This page will call reportEvent() twice. Once for a destination enum
// event (i.e. an event with an eventType/eventData specified), and once for
// a destination URL event (i.e. an event with a destinationURL specified).
const destination_enum_event = {
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
}
window.fence.reportEvent(destination_enum_event);

const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
const destination_url_event = {
destinationURL: destination_url,
crossOriginExposed: true
}
window.fence.reportEvent(destination_url_event);
});
await verifyBeaconData("click", "enum", false, t);
await verifyBeaconData("url", "<No data>", false, t);
}, 'Cross-origin window.fence.reportEvent without embedder opt-in');
</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
const fencedframe = await attachFencedFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'true'
]],
register_beacon: true
});
await fencedframe.execute(async () => {
const iframe = await attachIFrameContext({
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await iframe.execute(() => {
const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
window.fence.reportEvent({
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: false
});
window.fence.reportEvent({
destinationURL: destination_url,
crossOriginExposed: false
});
});
});
// Check that both the destination enum and destination URL events were
// reported.
await verifyBeaconData("click", "enum", false, t);
await verifyBeaconData("url", "<No data>", false, t);
}, 'Cross-origin window.fence.reportEvent without subframe opt-in');
</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
const iframe = await attachIFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'true'
]],
register_beacon: true,
origin: get_host_info().HTTPS_ORIGIN
});
// Perform a cross-origin navigation. Since the navigation is
// content-initiated, the fenced frame reporting metadata will persist.
await navigateFrameContext(iframe, {
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await iframe.execute(() => {
// This page will call reportEvent() twice. Once for a destination enum
// event (i.e. an event with an eventType/eventData specified), and once for
// a destination URL event (i.e. an event with a destinationURL specified).
const destination_enum_event = {
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
}
window.fence.reportEvent(destination_enum_event);

const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
const destination_url_event = {
destinationURL: destination_url,
crossOriginExposed: true
}
window.fence.reportEvent(destination_url_event);
});
await nextBeacon("click", "enum");
await nextBeacon("url", "<No data>");
}, 'window.fence.reportEvent from a content-initiated cross-origin navigation');
</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<title>Test window.fence.reportEvent from cross-origin subframes.</title>
<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="/common/get-host-info.sub.js"></script>
<script src="resources/automatic-beacon-helper.js"></script>
<script src="resources/utils.js"></script>

<body>
<script>
promise_test(async(t) => {
const iframe = await attachIFrameContext({
generator_api: 'fledge',
headers: [[
'Allow-Cross-Origin-Event-Reporting', 'false'
]],
register_beacon: true
});
// Perform a cross-origin navigation. Since the navigation is
// content-initiated, the fenced frame reporting metadata will persist.
await navigateFrameContext(iframe, {
origin: get_host_info().HTTPS_REMOTE_ORIGIN,
});
await iframe.execute(() => {
// This page will call reportEvent() twice. Once for a destination enum
// event (i.e. an event with an eventType/eventData specified), and once for
// a destination URL event (i.e. an event with a destinationURL specified).
const destination_enum_event = {
eventType: "click",
eventData: "enum",
destination: ["buyer"],
crossOriginExposed: true
}
window.fence.reportEvent(destination_enum_event);

const destination_url = new URL(BEACON_URL + "?type=url",
get_host_info().HTTPS_ORIGIN);
const destination_url_event = {
destinationURL: destination_url,
crossOriginExposed: true
}
window.fence.reportEvent(destination_url_event);
});
await verifyBeaconData("click", "enum", false, t);
await verifyBeaconData("url", "<No data>", false, t);
}, 'Cross-origin window.fence.reportEvent without embedder opt-in');
</script>
</body>
Loading

1 comment on commit a57b6bd

@community-tc-integration
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh! Looks like an error! Details

HttpError: You have exceeded a secondary rate limit. Please wait a few minutes before you try again. If you reach out to GitHub Support for help, please include the request ID B2C2:3F42FC:120B6B2:1D29C1E:6616DC35.

Please sign in to comment.