Bug 1719139 [wpt PR 29575] - Reland "[COEP] Fix flaky reporting tests for COEP:require-corp.", a=testonly

Automatic update from web-platform-tests
Reland "[COEP] Fix flaky reporting tests for COEP:require-corp."

This is a reland of 93e7378c0b1270c5973d9b63af77caa8a7fb41d5

Original change's description:
> [COEP] Fix flaky reporting tests for COEP:require-corp.
>
> Fixed reporting-navigation and reporting-subresource-corp tests.
>
> Bug: 1218825, 1091665
> Change-Id: I7aaf7e1436373a5a6cd0a8f1d947957b31822cbc
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980597
> Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
> Commit-Queue: Yifan Luo <lyf@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#898086}

Bug: 1218825, 1091665
Change-Id: I580b13b18b6f14d909dd6fa9fbaa20a7e803e9f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3005344
Reviewed-by: Yifan Luo <lyf@chromium.org>
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Commit-Queue: Yifan Luo <lyf@chromium.org>
Cr-Commit-Position: refs/heads/master@{#900404}

--

wpt-commits: 2160b7ee5fb13d5bd76b180d54b8a3f6322c8ea9
wpt-pr: 29575
This commit is contained in:
Yifan Luo 2021-07-17 09:48:36 +00:00 коммит произвёл moz-wptsync-bot
Родитель 161ecf6d40
Коммит 6fc17e4536
2 изменённых файлов: 85 добавлений и 71 удалений

Просмотреть файл

@ -5,6 +5,7 @@
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script> <script src="/common/get-host-info.sub.js"></script>
<script src="./credentialless/resources/common.js"></script>
<script> <script>
const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
const COEP = '|header(cross-origin-embedder-policy,require-corp)'; const COEP = '|header(cross-origin-embedder-policy,require-corp)';
@ -67,16 +68,25 @@ async function loadFrames(test, parentSuffix, withEmptyFrame, targetUrl) {
return parent; return parent;
} }
async function observeReports(global) { async function observeReports(global, expected_count) {
const reports = []; const reports = [];
const observer = new global.ReportingObserver((rs) => { const receivedEveryReports = new Promise(resolve => {
for (const r of rs) { if (expected_count == 0)
reports.push(r.toJSON()); resolve();
}
});
observer.observe();
// Wait 5000ms for reports to settle. const observer = new global.ReportingObserver((rs) => {
for (const r of rs) {
reports.push(r.toJSON());
}
if (expected_count <= reports.length)
resolve();
});
observer.observe();
});
// Wait 5000 ms more to catch additionnal unexpected reports.
await receivedEveryReports;
await new Promise(r => step_timeout(r, 5000)); await new Promise(r => step_timeout(r, 5000));
return reports; return reports;
} }
@ -125,30 +135,31 @@ for (const testcase of CASES) {
loadFrames(t, testcase.parent, withEmptyFrame, targetUrl) loadFrames(t, testcase.parent, withEmptyFrame, targetUrl)
.then(t.step_func(parent => { .then(t.step_func(parent => {
const contextUrl = parent.src ? parent.src : 'about:blank'; const contextUrl = parent.src ? parent.src : 'about:blank';
observeReports(parent.contentWindow).then(t.step_func(reports => { observeReports(parent.contentWindow, testcase.reports.length)
assert_equals(reports.length, testcase.reports.length); .then(t.step_func(reports => {
for (let i = 0; i < reports.length; i += 1) { assert_equals(reports.length, testcase.reports.length);
const report = reports[i]; for (let i = 0; i < reports.length; i += 1) {
switch (testcase.reports[i]) { const report = reports[i];
case 'CORP': switch (testcase.reports[i]) {
checkCorpReport(report, contextUrl, targetUrl, 'enforce'); case 'CORP':
break; checkCorpReport(report, contextUrl, targetUrl, 'enforce');
case 'CORP-RO': break;
checkCorpReport(report, contextUrl, targetUrl, 'reporting'); case 'CORP-RO':
break; checkCorpReport(report, contextUrl, targetUrl, 'reporting');
case 'NAV': break;
checkCoepMismatchReport(report, contextUrl, targetUrl, 'enforce'); case 'NAV':
break; checkCoepMismatchReport(report, contextUrl, targetUrl, 'enforce');
case 'NAV-RO': break;
checkCoepMismatchReport(report, contextUrl, targetUrl, 'reporting'); case 'NAV-RO':
break; checkCoepMismatchReport(report, contextUrl, targetUrl, 'reporting');
default: break;
assert_unreached( default:
'Unexpected report expeaction: ' + testcase.reports[i]); assert_unreached(
'Unexpected report expeaction: ' + testcase.reports[i]);
}
} }
} t.done();
t.done(); })).catch(t.step_func(e => { throw e; }));
})).catch(t.step_func(e => { throw e; }));
})).catch(t.step_func(e => { throw e; })); })).catch(t.step_func(e => { throw e; }));
}, `parent: ${desc(testcase.parent)}, target: ${desc(testcase.target)}, ` + }, `parent: ${desc(testcase.parent)}, target: ${desc(testcase.target)}, ` +
`with empty frame: ${withEmptyFrame}`); `with empty frame: ${withEmptyFrame}`);

Просмотреть файл

@ -20,8 +20,27 @@ const REPORTING_FRAME_URL = `${ORIGIN}${BASE}/reporting-empty-frame.html` +
'?pipe=header(cross-origin-embedder-policy,require-corp)' + '?pipe=header(cross-origin-embedder-policy,require-corp)' +
`|header(cross-origin-embedder-policy-report-only,require-corp)`; `|header(cross-origin-embedder-policy-report-only,require-corp)`;
function wait(ms) { async function observeReports(global, expected_count) {
return new Promise(resolve => step_timeout(resolve, ms)); 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();
});
await receivedEveryReports;
// Wait 500ms more to catch additionnal unexpected reports.
await new Promise(r => step_timeout(r, 500));
return reports;
} }
function checkReport(report, contextUrl, blockedUrl, disposition, destination) { function checkReport(report, contextUrl, blockedUrl, disposition, destination) {
@ -33,23 +52,15 @@ function checkReport(report, contextUrl, blockedUrl, disposition, destination) {
assert_equals(report.body.destination, destination); assert_equals(report.body.destination, destination);
} }
async function fetchInFrame(t, frameUrl, url) { async function fetchInFrame(t, frameUrl, url, expected_count) {
const reports = [];
const frame = await with_iframe(frameUrl); const frame = await with_iframe(frameUrl);
t.add_cleanup(() => frame.remove()); t.add_cleanup(() => frame.remove());
const observer = new frame.contentWindow.ReportingObserver((rs) => {
for (const report of rs) {
reports.push(report.toJSON());
}
});
observer.observe();
const init = { mode: 'no-cors', cache: 'no-store' }; const init = { mode: 'no-cors', cache: 'no-store' };
let future_reports = observeReports(frame.contentWindow, expected_count);
await frame.contentWindow.fetch(url, init).catch(() => {}); await frame.contentWindow.fetch(url, init).catch(() => {});
// Wait 200ms for reports to settle. return await future_reports;
await wait(200);
return reports;
} }
async function fetchInWorker(workerOrPort, url) { async function fetchInWorker(workerOrPort, url) {
@ -84,13 +95,13 @@ async function fetchInWorker(workerOrPort, url) {
const ENVIRONMENTS = [{ const ENVIRONMENTS = [{
tag: 'document', tag: 'document',
contextUrl: FRAME_URL, contextUrl: FRAME_URL,
run: async (test, url) => { run: async (test, url, expected_count) => {
return await fetchInFrame(test, FRAME_URL, url); return await fetchInFrame(test, FRAME_URL, url, expected_count);
}, },
}, { }, {
tag: 'dedicated worker', tag: 'dedicated worker',
contextUrl: WORKER_URL, contextUrl: WORKER_URL,
run: async (test, url) => { run: async (test, url, expected_count) => {
const worker = new Worker(WORKER_URL); const worker = new Worker(WORKER_URL);
worker.addEventListener('error', test.unreached_func('Worker.onerror')); worker.addEventListener('error', test.unreached_func('Worker.onerror'));
test.add_cleanup(() => worker.terminate()); test.add_cleanup(() => worker.terminate());
@ -99,7 +110,7 @@ const ENVIRONMENTS = [{
}, { }, {
tag: 'shared worker', tag: 'shared worker',
contextUrl: WORKER_URL, contextUrl: WORKER_URL,
run: async (test, url) => { run: async (test, url, expected_count) => {
const worker = new SharedWorker(WORKER_URL); const worker = new SharedWorker(WORKER_URL);
worker.addEventListener('error', test.unreached_func('Worker.onerror')); worker.addEventListener('error', test.unreached_func('Worker.onerror'));
return await fetchInWorker(worker.port, url); return await fetchInWorker(worker.port, url);
@ -107,7 +118,7 @@ const ENVIRONMENTS = [{
}, { }, {
tag: 'service worker', tag: 'service worker',
contextUrl: WORKER_URL, contextUrl: WORKER_URL,
run: async (test, url) => { run: async (test, url, expected_count) => {
// As we don't want the service worker to control any page, generate a // As we don't want the service worker to control any page, generate a
// one-time scope. // one-time scope.
const SCOPE = new URL(`resources/${token()}.html`, location).pathname; const SCOPE = new URL(`resources/${token()}.html`, location).pathname;
@ -121,7 +132,7 @@ const ENVIRONMENTS = [{
}, { }, {
tag: 'between service worker and page', tag: 'between service worker and page',
contextUrl: REPORTING_FRAME_URL, contextUrl: REPORTING_FRAME_URL,
run: async (test, url) => { run: async (test, url, expected_count) => {
// Here we use a Service Worker without COEP. // Here we use a Service Worker without COEP.
const WORKER_URL = `${ORIGIN}${BASE}/sw.js`; const WORKER_URL = `${ORIGIN}${BASE}/sw.js`;
const reg = await service_worker_unregister_and_register( const reg = await service_worker_unregister_and_register(
@ -130,36 +141,34 @@ const ENVIRONMENTS = [{
const worker = reg.installing || reg.waiting || reg.active; const worker = reg.installing || reg.waiting || reg.active;
worker.addEventListener('error', test.unreached_func('Worker.onerror')); worker.addEventListener('error', test.unreached_func('Worker.onerror'));
return await fetchInFrame( return await fetchInFrame(
test, REPORTING_FRAME_URL, url); test, REPORTING_FRAME_URL, url, expected_count);
}, },
}]; }];
const CASES = [{ const CASES = [{
name: 'same-origin', name: 'same-origin',
url: '/common/text-plain.txt', url: '/common/text-plain.txt',
check: (reports, url, contextUrl) => { expected_count: 0,
assert_equals(reports.length, 0); check: (reports, url, contextUrl) => {}
}
}, { }, {
name: 'blocked by CORP: same-origin', name: 'blocked by CORP: same-origin',
url: `${REMOTE_ORIGIN}${BASE}/nothing-same-origin-corp.txt`, url: `${REMOTE_ORIGIN}${BASE}/nothing-same-origin-corp.txt`,
check: (reports, url, contextUrl) => { expected_count: 0,
assert_equals(reports.length, 0); check: (reports, url, contextUrl) => {}
}
}, { }, {
name: 'blocked due to COEP', name: 'blocked due to COEP',
url: `${REMOTE_ORIGIN}/common/text-plain.txt`, url: `${REMOTE_ORIGIN}/common/text-plain.txt`,
expected_count: 2,
check: (reports, contextUrl, url) => { check: (reports, contextUrl, url) => {
assert_equals(reports.length, 2);
checkReport(reports[0], contextUrl, url, 'reporting', ''); checkReport(reports[0], contextUrl, url, 'reporting', '');
checkReport(reports[1], contextUrl, url, 'enforce', ''); checkReport(reports[1], contextUrl, url, 'enforce', '');
} }
}, { }, {
name: 'blocked during redirect', name: 'blocked during redirect',
url: `${ORIGIN}/common/redirect.py?location=` + url: `${ORIGIN}/common/redirect.py?location=` +
encodeURIComponent(`${REMOTE_ORIGIN}/common/text-plain.txt`), encodeURIComponent(`${REMOTE_ORIGIN}/common/text-plain.txt`),
expected_count: 2,
check: (reports, contextUrl, url) => { check: (reports, contextUrl, url) => {
assert_equals(reports.length, 2);
checkReport(reports[0], contextUrl, url, 'reporting', ''); checkReport(reports[0], contextUrl, url, 'reporting', '');
checkReport(reports[1], contextUrl, url, 'enforce', ''); checkReport(reports[1], contextUrl, url, 'enforce', '');
}, },
@ -168,8 +177,10 @@ const CASES = [{
for (const env of ENVIRONMENTS) { for (const env of ENVIRONMENTS) {
for (const testcase of CASES) { for (const testcase of CASES) {
promise_test(async (t) => { promise_test(async (t) => {
const reports = await env.run(t, testcase.url); const reports = await env.run(
t, testcase.url, testcase.expected_count);
assert_equals(reports.length, testcase.expected_count);
testcase.check(reports, env.contextUrl, testcase.url); testcase.check(reports, env.contextUrl, testcase.url);
}, `[${env.tag}] ${testcase.name}`); }, `[${env.tag}] ${testcase.name}`);
} }
@ -177,24 +188,16 @@ for (const env of ENVIRONMENTS) {
// A test for a non-empty destination. // A test for a non-empty destination.
promise_test(async (t) => { promise_test(async (t) => {
const reports = [];
const frame = await with_iframe(FRAME_URL); const frame = await with_iframe(FRAME_URL);
t.add_cleanup(() => frame.remove()); t.add_cleanup(() => frame.remove());
const observer = new frame.contentWindow.ReportingObserver((rs) => {
for (const report of rs) {
reports.push(report.toJSON());
}
});
observer.observe();
const url = `${REMOTE_ORIGIN}/common/utils.js`; const url = `${REMOTE_ORIGIN}/common/utils.js`;
const script = frame.contentDocument.createElement('script'); const script = frame.contentDocument.createElement('script');
script.src = url; script.src = url;
const future_reports = observeReports(frame.contentWindow, 2);
frame.contentDocument.body.appendChild(script); frame.contentDocument.body.appendChild(script);
// Wait 200ms for reports to settle. const reports = await future_reports;
await wait(200);
assert_equals(reports.length, 2); assert_equals(reports.length, 2);
checkReport(reports[0], FRAME_URL, url, 'reporting', 'script'); checkReport(reports[0], FRAME_URL, url, 'reporting', 'script');
checkReport(reports[1], FRAME_URL, url, 'enforce', 'script'); checkReport(reports[1], FRAME_URL, url, 'enforce', 'script');