| 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); |
| |
| // TODO(jbroman): this should probably be plumbed in from elsewhere |
| if (!location.pathname.includes('/speculationrules.')) { |
| 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}; |
| } |