98 lines
3.8 KiB
JavaScript
98 lines
3.8 KiB
JavaScript
function TestCase(scenarios, sanityChecker) {
|
|
function runTest(scenario) {
|
|
sanityChecker.checkScenario(scenario, subresourceMap);
|
|
|
|
const urls = getRequestURLs(scenario.subresource,
|
|
scenario.origin,
|
|
scenario.redirection);
|
|
|
|
/** @type {Subresource} */
|
|
const subresource = {
|
|
subresourceType: scenario.subresource,
|
|
url: urls.testUrl,
|
|
policyDeliveries: scenario.subresource_policy_deliveries,
|
|
};
|
|
|
|
let violationEventResolve;
|
|
// Resolved with an array of securitypolicyviolation events.
|
|
const violationEventPromise = new Promise(resolve => {
|
|
violationEventResolve = resolve;
|
|
});
|
|
|
|
promise_test(async t => {
|
|
await xhrRequest(urls.announceUrl);
|
|
|
|
// Currently only requests from top-level Documents are tested
|
|
// (specified by `spec.src.json`) and thus securitypolicyviolation
|
|
// events are assumed to be fired on the top-level Document here.
|
|
// When adding non-top-level Document tests, securitypolicyviolation
|
|
// events should be caught in appropriate contexts.
|
|
const violationEvents = [];
|
|
const listener = e => { violationEvents.push(e); };
|
|
document.addEventListener('securitypolicyviolation', listener);
|
|
|
|
try {
|
|
// Send out the real resource request.
|
|
// This should tear down the key if it's not blocked.
|
|
const mainPromise = invokeRequest(subresource, scenario.source_context_list);
|
|
if (scenario.expectation === 'allowed') {
|
|
await mainPromise;
|
|
} else {
|
|
await mainPromise
|
|
.then(t.unreached_func('main promise resolved unexpectedly'))
|
|
.catch(_ => {});
|
|
}
|
|
} finally {
|
|
// Always perform post-processing/clean up for
|
|
// 'securitypolicyviolation' events and resolve
|
|
// `violationEventPromise`, to prevent timeout of the
|
|
// promise_test() below.
|
|
|
|
// securitypolicyviolation events are fired in a queued task in
|
|
// https://w3c.github.io/webappsec-csp/#report-violation
|
|
// so wait for queued tasks to run using setTimeout().
|
|
let timeout = 0;
|
|
if (scenario.subresource.startsWith('worklet-') &&
|
|
navigator.userAgent.includes("Firefox/")) {
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1808911
|
|
// In Firefox sometimes violations from Worklets are delayed.
|
|
timeout = 10;
|
|
}
|
|
await new Promise(resolve => setTimeout(resolve, timeout));
|
|
|
|
// Pass violation events to `violationEventPromise` (which will be tested
|
|
// in the subsequent promise_test()) and clean up the listener.
|
|
violationEventResolve(violationEvents);
|
|
document.removeEventListener('securitypolicyviolation', listener);
|
|
}
|
|
|
|
// Send request to check if the key has been torn down.
|
|
const assertResult = await xhrRequest(urls.assertUrl);
|
|
|
|
// Now check if the value has been torn down. If it's still there,
|
|
// we have blocked the request by content security policy.
|
|
assert_equals(assertResult.status, scenario.expectation,
|
|
"The resource request should be '" + scenario.expectation + "'.");
|
|
|
|
}, scenario.test_description);
|
|
|
|
promise_test(async _ => {
|
|
const violationEvents = await violationEventPromise;
|
|
if (scenario.expectation === 'allowed') {
|
|
assert_array_equals(violationEvents, [],
|
|
'no violation events should be fired');
|
|
} else {
|
|
assert_equals(violationEvents.length, 1,
|
|
'One violation event should be fired');
|
|
}
|
|
}, scenario.test_description + ": securitypolicyviolation");
|
|
} // runTest
|
|
|
|
function runTests() {
|
|
for (const scenario of scenarios) {
|
|
runTest(scenario);
|
|
}
|
|
}
|
|
|
|
return {start: runTests};
|
|
}
|