test-case.sub.js (4176B)
1 function TestCase(scenarios, sanityChecker) { 2 function runTest(scenario) { 3 sanityChecker.checkScenario(scenario, subresourceMap); 4 5 const urls = getRequestURLs(scenario.subresource, 6 scenario.origin, 7 scenario.redirection); 8 9 /** @type {Subresource} */ 10 const subresource = { 11 subresourceType: scenario.subresource, 12 url: urls.testUrl, 13 policyDeliveries: scenario.subresource_policy_deliveries, 14 }; 15 16 let violationEventResolve; 17 // Resolved with an array of securitypolicyviolation events. 18 const violationEventPromise = new Promise(resolve => { 19 violationEventResolve = resolve; 20 }); 21 22 promise_test(async t => { 23 await xhrRequest(urls.announceUrl); 24 25 // Currently only requests from top-level Documents are tested 26 // (specified by `spec.src.json`) and thus securitypolicyviolation 27 // events are assumed to be fired on the top-level Document here. 28 // When adding non-top-level Document tests, securitypolicyviolation 29 // events should be caught in appropriate contexts. 30 const violationEvents = []; 31 const listener = e => { violationEvents.push(e); }; 32 document.addEventListener('securitypolicyviolation', listener); 33 34 try { 35 // Send out the real resource request. 36 // This should tear down the key if it's not blocked. 37 const mainPromise = invokeRequest(subresource, scenario.source_context_list); 38 if (scenario.expectation === 'allowed') { 39 await mainPromise; 40 } else { 41 await mainPromise 42 .then(t.unreached_func('main promise resolved unexpectedly')) 43 .catch(_ => {}); 44 } 45 } finally { 46 // Always perform post-processing/clean up for 47 // 'securitypolicyviolation' events and resolve 48 // `violationEventPromise`, to prevent timeout of the 49 // promise_test() below. 50 51 // securitypolicyviolation events are fired in a queued task in 52 // https://w3c.github.io/webappsec-csp/#report-violation 53 // so wait for queued tasks to run using setTimeout(). 54 let timeout = 0; 55 if (scenario.subresource.startsWith('worklet-') && 56 navigator.userAgent.includes("Firefox/")) { 57 // https://bugzilla.mozilla.org/show_bug.cgi?id=1808911 58 // In Firefox sometimes violations from Worklets are delayed. 59 timeout = 10; 60 } else if (scenario.subresource.startsWith('worker-') && 61 navigator.userAgent.includes("Servo/")) { 62 // In Servo, worker violations are also delayed, as they are 63 // sent via IPC. However, they typically arrive relatively 64 // quickly after that. 65 timeout = 1; 66 } 67 await new Promise(resolve => setTimeout(resolve, timeout)); 68 69 // Pass violation events to `violationEventPromise` (which will be tested 70 // in the subsequent promise_test()) and clean up the listener. 71 violationEventResolve(violationEvents); 72 document.removeEventListener('securitypolicyviolation', listener); 73 } 74 75 // Send request to check if the key has been torn down. 76 const assertResult = await xhrRequest(urls.assertUrl); 77 78 // Now check if the value has been torn down. If it's still there, 79 // we have blocked the request by content security policy. 80 assert_equals(assertResult.status, scenario.expectation, 81 "The resource request should be '" + scenario.expectation + "'."); 82 83 }, scenario.test_description); 84 85 promise_test(async _ => { 86 const violationEvents = await violationEventPromise; 87 if (scenario.expectation === 'allowed') { 88 assert_array_equals(violationEvents, [], 89 'no violation events should be fired'); 90 } else { 91 assert_equals(violationEvents.length, 1, 92 'One violation event should be fired'); 93 } 94 }, scenario.test_description + ": securitypolicyviolation"); 95 } // runTest 96 97 function runTests() { 98 for (const scenario of scenarios) { 99 runTest(scenario); 100 } 101 } 102 103 return {start: runTests}; 104 }