1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// META: timeout=long
// META: script=/common/get-host-info.sub.js
// META: script=./resources/common.js
const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
const COEP = '|header(cross-origin-embedder-policy,credentialless)';
const COEP_RO =
'|header(cross-origin-embedder-policy-report-only,credentialless)';
const CORP_CROSS_ORIGIN =
'|header(cross-origin-resource-policy,cross-origin)';
const FRAME_URL = `${ORIGIN}/common/blank.html?pipe=`;
const REMOTE_FRAME_URL = `${REMOTE_ORIGIN}/common/blank.html?pipe=`;
function checkCorpReport(report, contextUrl, blockedUrl, disposition) {
assert_equals(report.type, 'coep');
assert_equals(report.url, contextUrl);
assert_equals(report.body.type, 'corp');
assert_equals(report.body.blockedURL, blockedUrl);
assert_equals(report.body.disposition, disposition);
assert_equals(report.body.destination, 'iframe');
}
function checkCoepMismatchReport(report, contextUrl, blockedUrl, disposition) {
assert_equals(report.type, 'coep');
assert_equals(report.url, contextUrl);
assert_equals(report.body.type, 'navigation');
assert_equals(report.body.blockedURL, blockedUrl);
assert_equals(report.body.disposition, disposition);
}
function loadFrame(document, url) {
return new Promise((resolve, reject) => {
const frame = document.createElement('iframe');
frame.src = url;
frame.onload = () => resolve(frame);
frame.onerror = reject;
document.body.appendChild(frame);
});
}
// |parentSuffix| is a suffix for the parent frame URL.
// |targetUrl| is a URL for the target frame.
async function loadFrames(test, parentSuffix, targetUrl) {
const frame = await loadFrame(document, FRAME_URL + parentSuffix);
test.add_cleanup(() => frame.remove());
// Here we don't need "await". This loading may or may not succeed, and
// we're not interested in the result.
loadFrame(frame.contentDocument, targetUrl);
return frame;
}
async function observeReports(global, expected_count) {
const reports = [];
const receivedEveryReports = new Promise(resolve => {
if (expected_count == 0)
resolve();
const observer = new global.ReportingObserver((rs) => {
for (const r of rs) {
reports.push(r.toJSON());
}
if (expected_count <= reports.length)
resolve();
});
observer.observe();
});
// Wait 500ms more to catch additionnal unexpected reports.
await receivedEveryReports;
await new Promise(r => step_timeout(r, 500));
return reports;
}
function desc(headers) {
return headers === '' ? '(none)' : headers;
}
// CASES is a list of test case. Each test case consists of:
// parent_headers: the suffix of the URL of the parent frame.
// target_headers: the suffix of the URL of the target frame.
// expected_reports: one of:
// 'CORP': CORP violation
// 'CORP-RO': CORP violation (report only)
// 'NAV': COEP mismatch between the frames.
// 'NAV-RO': COEP mismatch between the frames (report only).
const reportingTest = function(
parent_headers, target_headers, expected_reports) {
// These tests are very slow, so they must be run in parallel using
// async_test.
promise_test_parallel(async t => {
const targetUrl = REMOTE_FRAME_URL + target_headers;
const parent = await loadFrames(t, parent_headers, targetUrl);
const contextUrl = parent.src ? parent.src : 'about:blank';
const reports = await observeReports(
parent.contentWindow,
expected_reports.length
);
assert_equals(reports.length, expected_reports.length);
for (let i = 0; i < reports.length; i += 1) {
const report = reports[i];
switch (expected_reports[i]) {
case 'CORP':
checkCorpReport(report, contextUrl, targetUrl, 'enforce');
break;
case 'CORP-RO':
checkCorpReport(report, contextUrl, targetUrl, 'reporting');
break;
case 'NAV':
checkCoepMismatchReport(report, contextUrl, targetUrl, 'enforce');
break;
case 'NAV-RO':
checkCoepMismatchReport(report, contextUrl, targetUrl, 'reporting');
break;
default:
assert_unreached(
'Unexpected report exception: ' + expected_reports[i]);
}
}
}, `parent: ${desc(parent_headers)}, target: ${desc(target_headers)}, `);
}
reportingTest('', '', []);
reportingTest('', COEP, []);
reportingTest(COEP, COEP, ['CORP']);
reportingTest(COEP, '', ['CORP']);
reportingTest('', CORP_CROSS_ORIGIN, []);
reportingTest(COEP, CORP_CROSS_ORIGIN, ['NAV']);
reportingTest('', COEP + CORP_CROSS_ORIGIN, []);
reportingTest(COEP, COEP + CORP_CROSS_ORIGIN, []);
reportingTest(COEP_RO, COEP, ['CORP-RO']);
reportingTest(COEP_RO, '', ['CORP-RO', 'NAV-RO']);
reportingTest(COEP_RO, CORP_CROSS_ORIGIN, ['NAV-RO']);
reportingTest(COEP_RO, COEP + CORP_CROSS_ORIGIN, []);
reportingTest(COEP, COEP_RO + CORP_CROSS_ORIGIN, ['NAV']);
|