diff --git a/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html b/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html
new file mode 100644
index 000000000000000..7bfdab133070e95
--- /dev/null
+++ b/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html
@@ -0,0 +1,86 @@
+
+
+
A test with both COOP and COOP report only setup using Reporting-Endpoints header
+
+
+
+
+
+
+
+
+
diff --git a/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers b/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers
new file mode 100644
index 000000000000000..de48445f38fafc0
--- /dev/null
+++ b/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers
@@ -0,0 +1,6 @@
+Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint"
+Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop-report-only-endpoint"
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Embedder-Policy-Report-Only: require-corp
+Referrer-Policy: origin
+Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=2aee31d2-cd11-43bd-b34d-5f081ca3b2b4", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=d18f1779-e2ab-4a7a-8b1c-44e3a6f440f5"
diff --git a/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html b/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html
new file mode 100644
index 000000000000000..43da4b79b30243b
--- /dev/null
+++ b/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html
@@ -0,0 +1,129 @@
+
+ Both the openee and the opener have a COOP reporter. The report are sent to
+ both side.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html b/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html
new file mode 100644
index 000000000000000..764b4128ff773ce
--- /dev/null
+++ b/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html
@@ -0,0 +1,116 @@
+
+ Tests the redirect interaction with COOP same-origin-allow-popups.
+
+
+
+
+
+
+
+
+
+
diff --git a/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html b/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html
new file mode 100644
index 000000000000000..ae94d6871a77c63
--- /dev/null
+++ b/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html
@@ -0,0 +1,135 @@
+
+ Tests the redirect interaction with COOP unsafe-none.
+
+
+
+
+
+
+
+
+
+
diff --git a/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html b/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html
index 68ecd913756fa25..ae91e7dc04b1cb6 100644
--- a/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html
+++ b/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html
@@ -21,11 +21,11 @@
const coopToken= token();
await reportingTest(async resolve => {
const noCOOPUrl = executor_path +
- `|header(report-to,${encodeURIComponent(getReportEndpoints(location.origin))})` +
+ convertToWPTHeaderPipe(getReportToHeader(location.origin)) +
`|header(Cross-Origin-Opener-Policy,${encodeURIComponent(`unsafe-none; report-to="${popupReportEndpoint.name}"`)})` +
`&uuid=${noCoopToken}`;
const coopUrl = executor_path +
- `|header(report-to,${encodeURIComponent(getReportEndpoints(location.origin))})` +
+ convertToWPTHeaderPipe(getReportToHeader(location.origin)) +
`|header(Cross-Origin-Opener-Policy,${encodeURIComponent(`same-origin; report-to="${redirectReportEndpoint.name}"`)})` +
`&uuid=${coopToken}`;
diff --git a/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html b/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html
index d337541dfff01e8..b19cdd5a9c1e131 100644
--- a/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html
+++ b/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html
@@ -22,7 +22,7 @@
// Tests the redirect interaction with COOP same-origin-allow-popups and
// reporting:
-// 1 - open the opener document on origin same_origin wit COOP
+// 1 - open the opener document on origin same_origin with COOP
// same-origin-allow-popups.
// 2 - opener opens popup with document on origin popup_origin, no COOP and a
// redirect header (HTTP 302, location).
diff --git a/html/cross-origin-opener-policy/reporting/resources/reporting-common.js b/html/cross-origin-opener-policy/reporting/resources/reporting-common.js
index 246c9224a3aed46..48d48aa3884710e 100644
--- a/html/cross-origin-opener-policy/reporting/resources/reporting-common.js
+++ b/html/cross-origin-opener-policy/reporting/resources/reporting-common.js
@@ -190,50 +190,68 @@ async function reportingTest(testFunction, executorToken, expectedReports) {
await Promise.all(Array.from(expectedReports, checkForExpectedReport));
}
-function getReportEndpoints(host) {
- result = "";
- reportEndpoints.forEach(
- reportEndpoint => {
- let reportToJSON = {
- 'group': `${reportEndpoint.name}`,
- 'max_age': 3600,
- 'endpoints': [
- {
- 'url': `${host}/reporting/resources/report.py?reportID=${reportEndpoint.reportID}`
- },
- ]
- };
- result += JSON.stringify(reportToJSON)
- .replace(/,/g, '\\,')
- .replace(/\(/g, '\\\(')
- .replace(/\)/g, '\\\)=')
- + "\\,";
- }
- );
- return result.slice(0, -2);
+function convertToWPTHeaderPipe([name, value]) {
+ return `header(${name}, ${encodeURIComponent(value)})`;
+}
+
+function getReportToHeader(host) {
+ return [
+ "Report-To",
+ reportEndpoints.map(
+ reportEndpoint => {
+ const reportToJSON = {
+ 'group': `${reportEndpoint.name}`,
+ 'max_age': 3600,
+ 'endpoints': [{
+ 'url': `${host}${getReportEndpointURL(reportEndpoint.reportID)}`
+ }]
+ };
+ // Escape comma as required by wpt pipes.
+ return JSON.stringify(reportToJSON)
+ .replace(/,/g, '\\,')
+ .replace(/\(/g, '\\\(')
+ .replace(/\)/g, '\\\)=');
+ }
+ ).join("\\, ")];
+}
+
+function getReportingEndpointsHeader(host) {
+ return [
+ "Reporting-Endpoints",
+ reportEndpoints.map(reportEndpoint => {
+ return `${reportEndpoint.name}="${host}${getReportEndpointURL(reportEndpoint.reportID)}"`;
+ }).join("\\, ")];
+}
+
+// Return Report and Report-Only policy headers.
+function getPolicyHeaders(coop, coep, coopRo, coepRo) {
+ return [
+ [`Cross-Origin-Opener-Policy`, coop],
+ [`Cross-Origin-Embedder-Policy`, coep],
+ [`Cross-Origin-Opener-Policy-Report-Only`, coopRo],
+ [`Cross-Origin-Embedder-Policy-Report-Only`, coepRo]];
}
function navigationReportingTest(testName, host, coop, coep, coopRo, coepRo,
- expectedReports ){
+ expectedReports) {
const executorToken = token();
const callbackToken = token();
promise_test(async t => {
- await reportingTest( async resolve => {
+ await reportingTest(async resolve => {
+ const openee_headers = [
+ getReportToHeader(host.origin),
+ ...getPolicyHeaders(coop, coep, coopRo, coepRo)
+ ].map(convertToWPTHeaderPipe);
const openee_url = host.origin + executor_path +
- `|header(report-to,${encodeURIComponent(getReportEndpoints(host.origin))})` +
- `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(coop)})` +
- `|header(Cross-Origin-Embedder-Policy,${encodeURIComponent(coep)})` +
- `|header(Cross-Origin-Opener-Policy-Report-Only,${encodeURIComponent(coopRo)})` +
- `|header(Cross-Origin-Embedder-Policy-Report-Only,${encodeURIComponent(coepRo)})`+
- `&uuid=${executorToken}`;
+ openee_headers.join('|') + `&uuid=${executorToken}`;
const openee = window.open(openee_url);
const uuid = token();
t.add_cleanup(() => send(uuid, "window.close()"));
// 1. Make sure the new document is loaded.
send(executorToken, `
- send("${callbackToken}", "Ready");
- `);
+ send("${callbackToken}", "Ready");
+ `);
let reply = await receive(callbackToken);
assert_equals(reply, "Ready");
resolve();
@@ -241,6 +259,43 @@ function navigationReportingTest(testName, host, coop, coep, coopRo, coepRo,
}, `coop reporting test ${testName} to ${host.name} with ${coop}, ${coep}, ${coopRo}, ${coepRo}`);
}
+function navigationDocumentReportingTest(testName, host, coop, coep, coopRo,
+ coepRo, expectedReports) {
+ const executorToken = token();
+ const callbackToken = token();
+ promise_test(async t => {
+ const openee_headers = [
+ getReportingEndpointsHeader(host.origin),
+ ...getPolicyHeaders(coop, coep, coopRo, coepRo)
+ ].map(convertToWPTHeaderPipe);
+ const openee_url = host.origin + executor_path +
+ openee_headers.join('|') + `&uuid=${executorToken}`;
+ window.open(openee_url);
+ t.add_cleanup(() => send(executorToken, "window.close()"));
+ // Have openee window send a message through dispatcher, once we receive
+ // the Ready message from dispatcher it means the openee is fully loaded.
+ send(executorToken, `
+ send("${callbackToken}", "Ready");
+ `);
+ let reply = await receive(callbackToken);
+ assert_equals(reply, "Ready");
+
+ await wait(1000);
+
+ expectedReports = expectedReports.map(
+ (report) => replaceValuesInExpectedReport(report, executorToken));
+ return Promise.all(expectedReports.map(
+ async ({ endpoint, report: expectedReport }) => {
+ await pollReports(endpoint);
+ for (let report of endpoint.reports) {
+ assert_true(isObjectAsExpected(report, expectedReport),
+ `report received for endpoint: ${endpoint.name} ${JSON.stringify(report)} should match ${JSON.stringify(expectedReport)}`);
+ }
+ assert_equals(endpoint.reports.length, 1, `has exactly one report for ${endpoint.name}`)
+ }));
+ }, `coop document reporting test ${testName} to ${host.name} with ${coop}, ${coep}, ${coopRo}, ${coepRo}`);
+}
+
// Run an array of reporting tests then verify there's no reports that were not
// expected.
// Tests' elements contain: host, coop, coep, coop-report-only,
@@ -254,6 +309,17 @@ async function runNavigationReportingTests(testName, tests) {
verifyRemainingReports();
}
+// Run an array of reporting tests using Reporting-Endpoints header then
+// verify there's no reports that were not expected.
+// Tests' elements contain: host, coop, coep, coop-report-only,
+// coep-report-only, expectedReports.
+// See isObjectAsExpected for explanations regarding the matching behavior.
+function runNavigationDocumentReportingTests(testName, tests) {
+ clearReportsOnServer();
+ tests.forEach(test => {
+ navigationDocumentReportingTest(testName, ...test);
+ });
+}
function verifyRemainingReports() {
promise_test(t => {
@@ -275,7 +341,6 @@ const receiveReport = async function(uuid, type) {
if (reports == "timeout")
return "timeout";
reports = JSON.parse(reports);
-
for(report of reports) {
if (report?.body?.type == type)
return report;
@@ -283,6 +348,17 @@ const receiveReport = async function(uuid, type) {
}
}
+// Build a set of 'Cross-Origin-Opener-Policy' and
+// 'Cross-Origin-Opener-Policy-Report-Only' headers.
+const coopHeaders = function (uuid) {
+ return {
+ coopSameOriginHeader: `|header(Cross-Origin-Opener-Policy,same-origin%3Breport-to="${uuid}")`,
+ coopSameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy,same-origin-allow-popups%3Breport-to="${uuid}")`,
+ coopReportOnlySameOriginHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin%3Breport-to="${uuid}")`,
+ coopReportOnlySameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin-allow-popups%3Breport-to="${uuid}")`
+ };
+}
+
// Build a set of headers to tests the reporting API. This defines a set of
// matching 'Report-To', 'Cross-Origin-Opener-Policy' and
// 'Cross-Origin-Opener-Policy-Report-Only' headers.
@@ -302,9 +378,19 @@ const reportToHeaders = function(uuid) {
return {
header: `|header(report-to,${reportToJSON})`,
- coopSameOriginHeader: `|header(Cross-Origin-Opener-Policy,same-origin%3Breport-to="${uuid}")`,
- coopSameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy,same-origin-allow-popups%3Breport-to="${uuid}")`,
- coopReportOnlySameOriginHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin%3Breport-to="${uuid}")`,
- coopReportOnlySameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin-allow-popups%3Breport-to="${uuid}")`,
+ ...coopHeaders(uuid)
+ };
+};
+
+// Build a set of headers to tests the reporting API. This defines a set of
+// matching 'Reporting-Endpoints', 'Cross-Origin-Opener-Policy' and
+// 'Cross-Origin-Opener-Policy-Report-Only' headers.
+const reportingEndpointsHeaders = function (uuid) {
+ const report_endpoint_url = dispatcher_path + `?uuid=${uuid}`;
+ const reporting_endpoints_header = `${uuid}="${report_endpoint_url}"`;
+
+ return {
+ header: `|header(Reporting-Endpoints,${reporting_endpoints_header})`,
+ ...coopHeaders(uuid)
};
};