<!doctype html>
<html>
<title> Check enforcement of COEP in a ServiceWorker using CacheStorage. </title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<script>
// See also: ./dedicated-worker-cache-storage.https.html
function remote(path) {
const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
return new URL(path, REMOTE_ORIGIN);
}
const iframe_path = "./resources/iframe.html?pipe=";
const service_worker_path = "./resources/universal-worker.js?pipe=";
const ressource_path = "/images/blue.png?pipe=";
const coep_header= {
"coep-none" : "",
"coep-require-corp" : "|header(Cross-Origin-Embedder-Policy,require-corp)",
}
const corp_header = {
"corp-undefined" : "",
"corp-cross-origin" : "|header(Cross-Origin-Resource-Policy,cross-origin)",
}
// Send a message to the |worker| and wait for its response.
function executeCommandInServiceWorker(worker, command) {
const channel = new MessageChannel();
const response = new Promise(resolve => channel.port1.onmessage = resolve);
worker.postMessage(command, [ channel.port2 ]);
return response;
}
// Check enforcement of COEP in a ServiceWorker using CacheStorage.
//
// 1) Fetch a response from a document with COEP:none. Store it in the
// CacheStorage. The response is cross-origin without any CORS header.
// 2) From a ServiceWorker, retrieve the response from the CacheStorage.
//
// Test parameters:
// - |worker_coep| the COEP header of the ServiceWorker's script response.
// - |response_corp| the CORP header of the response.
//
// Test expectations:
// |loaded| is true whenever the worker is able to fetch the response from
// the CacheStorage. According to the specification:
// https://mikewest.github.io/corpp/#initialize-embedder-policy-for-global
// it must be false when:
// - |worker_coep| is 'coep-require-corp' and
// - |response-corp| is 'corp-undefined'.
function check(
// Test parameters:
worker_coep,
response_corp,
// Test expectations:
loaded) {
promise_test(async (t) => {
// 1) Fetch a response from a document with COEP:none. Store it in the
// CacheStorage. The response is cross-origin without any CORS header.
const resource_path = ressource_path + corp_header[response_corp];
const resource_url = remote(resource_path);
const fetch_request = new Request(resource_url, {mode: 'no-cors'});
const cache = await caches.open('v1');
const fetch_response = await fetch(fetch_request);
await cache.put(fetch_request, fetch_response);
// 2) Start a ServiceWorker.
const SCOPE= new URL(location.href).pathname;
const service_worker_allowed = `|header(service-worker-allowed,${SCOPE})`;
const SCRIPT =
service_worker_path +
coep_header[worker_coep] +
service_worker_allowed;
const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
add_completion_callback(() => reg.unregister());
// Start talking to the ServiceWorker, no matter its state.
const worker = reg.installing || reg.waiting || reg.active;
// 3) From the service worker, try to retrieve the response from the
// CacheStorage.
const response = executeCommandInServiceWorker(worker, `
(async function() {
const cache = await caches.open('v1');
const request = new Request('${resource_url}', {
mode: 'no-cors'
});
try {
const response = await cache.match(request);
message.ports[0].postMessage('success');
} catch(error) {
message.ports[0].postMessage('error');
}
})()
`);
const {data} = await response;
assert_equals(data === "success", loaded);
}, `A ServiceWorker with ${worker_coep} use CacheStorage to get a ${response_corp} response.`)
}
// ------------------------------------------------------
// worker_coep , response_corp , loaded
// ------------------------------------------------------
check("coep-none" , "corp-undefined" , true);
check("coep-none" , "corp-cross-origin" , true);
check("coep-require-corp" , "corp-undefined" , false);
check("coep-require-corp" , "corp-cross-origin" , true);
</script>
</html>