Commit c329c459 authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

COEP: Add tests about CacheStorage.

Add new WPT tests case about retrieving a resource from the
CacheStorage.

The covers the following combinaison:

  1) The document with and without COEP: require-corp.
  2) The request in "cors" or "non-cors" mode.
  3) The request cross-origin or same-origin.
  4) The response with:
     - CORP: undefined
     - CORP: same-origin
     - CORP: cross-origin
  5) The response with: "Access-Control-Allow-Origin" being "*" or not
     defined.

Bug: 1031542
Change-Id: I1800c0c2e48645a8f4bccf56c4ff586522bb6aa2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1955724
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#724598}
parent 743c65a4
<!doctype html>
<html>
<title> Retrieve resources from CacheStorage with Cross-Origin-Embedder-Policy: require-corp</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>
/*
This document does NOT define the Cross-Origin-Embedder-Policy header.
Cross-Origin Embedder Policy Editor's draft: https://mikewest.github.io/corpp/
This test is retrieving same-origin and cross-origin resources from the
CacheStorage. The resources are generated from the ServiceWorker or from the
network with the header Cross-Origin-Resource-Policy being one of:
- 'same-origin'
- 'cross-origin'
- <undefined>
*/
promise_test(async (t) => {
const SCOPE = new URL(location.href).pathname;
const SCRIPT =
'resources/sw-store-to-cache-storage.js?' +
`pipe=header(service-worker-allowed,${SCOPE})`;
await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
await new Promise(resolve => {
navigator.serviceWorker.addEventListener('controllerchange', resolve);
});
}, 'setting up');
function remote(path) {
const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
return new URL(path, REMOTE_ORIGIN);
}
function local(path) {
return new URL(path, location.origin);
}
// Send a message to the currently active ServiceWorker and wait for its
// response.
function executeCommandInServiceWorker(command) {
return new Promise(resolve => {
navigator.serviceWorker.addEventListener('message', e => resolve(e.data));
navigator.serviceWorker.controller.postMessage(command);
});
}
// Try loading an image from a |response|. Return a Promise resolving or
// rejecting depending on the image loading result.
function readImageFromResponse(response) {
return new Promise((resolve, reject) => {
const img = document.createElement("img");
img.onload = resolve.bind(this, "");
img.onerror = reject.bind(this, {name: "Image.onerror"});
response.blob().then(blob => {
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);
})
})
}
const image_path = "/images/blue.png?pipe=";
const corp_header = {
"":"",
"corp-undefined": "",
"corp-same-origin": "|header(Cross-Origin-Resource-Policy,same-origin)",
"corp-cross-origin": "|header(Cross-Origin-Resource-Policy,cross-origin)",
}
const cors_header = {
"":"",
"cors-disabled": "",
"cors-enabled": "|header(Access-Control-Allow-Origin,*)",
}
function test(
// Test parameters:
request_source, request_origin, request_mode, response_cors, response_corp,
// Test expectations:
response_stored, response_type) {
promise_test(async (t) => {
// 0. Start from an empty CacheStorage.
await caches.delete("v1");
// 1. Make the ServiceWorker to request the ressource and store it into the
// CacheStorage.
const path = image_path +
corp_header[response_corp] +
cors_header[response_cors];
const url = (request_origin === "same-origin" ? local : remote)(path);
const command = {
url: url.href,
mode: request_mode,
source: request_source,
};
assert_equals(await executeCommandInServiceWorker(command), response_stored);
if (response_stored === "not-stored") {
return;
}
// 2. Make this document to retrieve it from the CacheStorage.
const cache = await caches.open('v1');
const response = await cache.match(url);
assert_equals(response.type, response_type);
if (request_source === "service-worker") {
assert_equals("foo", await response.text());
return;
}
// Opaque response are not readable.
if (response_type === "opaque") {
await promise_rejects(t, {name: "Image.onerror"}, readImageFromResponse(response));
return;
}
await readImageFromResponse(response);
}, `Fetch ${request_origin} ${request_mode} ${response_cors} ${response_corp} from ${request_source} and CacheStorage.`)
}
// Responses generated from the ServiceWorker.
{
test("service-worker", "cross-origin", "cors", "", "", "stored", "default");
test("service-worker", "cross-origin", "no-cors", "", "", "stored", "default");
test("service-worker", "same-origin", "cors", "", "", "stored", "default");
test("service-worker", "same-origin", "no-cors", "", "", "stored", "default");
}
// Responses generated from a same-origin server.
{
const t = test.bind(this, "network", "same-origin");
t("cors", "cors-disabled", "corp-cross-origin", "stored", "basic");
t("cors", "cors-disabled", "corp-same-origin", "stored", "basic");
t("cors", "cors-disabled", "corp-undefined", "stored", "basic");
t("cors", "cors-enabled", "corp-cross-origin", "stored", "basic");
t("cors", "cors-enabled", "corp-same-origin", "stored", "basic");
t("cors", "cors-enabled", "corp-undefined", "stored", "basic");
t("no-cors", "cors-disabled", "corp-cross-origin", "stored", "basic");
t("no-cors", "cors-disabled", "corp-same-origin", "stored", "basic");
t("no-cors", "cors-disabled", "corp-undefined", "stored", "basic");
t("no-cors", "cors-enabled", "corp-cross-origin", "stored", "basic");
t("no-cors", "cors-enabled", "corp-same-origin", "stored", "basic");
t("no-cors", "cors-enabled", "corp-undefined", "stored", "basic");
}
// Responses generated from a cross-origin server.
{
const t = test.bind(this, "network", "cross-origin");
t("cors", "cors-disabled", "corp-cross-origin", "not-stored");
t("cors", "cors-disabled", "corp-same-origin", "not-stored");
t("cors", "cors-disabled", "corp-undefined", "not-stored");
t("cors", "cors-enabled", "corp-cross-origin", "stored", "cors");
t("cors", "cors-enabled", "corp-same-origin", "stored", "cors");
t("cors", "cors-enabled", "corp-undefined", "stored", "cors");
t("no-cors", "cors-disabled", "corp-cross-origin", "stored", "opaque");
t("no-cors", "cors-disabled", "corp-same-origin", "not-stored");
t("no-cors", "cors-disabled", "corp-undefined", "stored", "opaque");
t("no-cors", "cors-enabled", "corp-cross-origin", "stored", "opaque");
t("no-cors", "cors-enabled", "corp-same-origin", "not-stored");
t("no-cors", "cors-enabled", "corp-undefined", "stored", "opaque");
}
</script>
</html>
This is a testharness.js-based test.
PASS setting up
PASS Fetch cross-origin cors from service-worker and CacheStorage.
PASS Fetch cross-origin no-cors from service-worker and CacheStorage.
PASS Fetch same-origin cors from service-worker and CacheStorage.
PASS Fetch same-origin no-cors from service-worker and CacheStorage.
PASS Fetch same-origin cors cors-disabled corp-cross-origin from network and CacheStorage.
PASS Fetch same-origin cors cors-disabled corp-same-origin from network and CacheStorage.
PASS Fetch same-origin cors cors-disabled corp-undefined from network and CacheStorage.
PASS Fetch same-origin cors cors-enabled corp-cross-origin from network and CacheStorage.
PASS Fetch same-origin cors cors-enabled corp-same-origin from network and CacheStorage.
PASS Fetch same-origin cors cors-enabled corp-undefined from network and CacheStorage.
PASS Fetch same-origin no-cors cors-disabled corp-cross-origin from network and CacheStorage.
PASS Fetch same-origin no-cors cors-disabled corp-same-origin from network and CacheStorage.
PASS Fetch same-origin no-cors cors-disabled corp-undefined from network and CacheStorage.
PASS Fetch same-origin no-cors cors-enabled corp-cross-origin from network and CacheStorage.
PASS Fetch same-origin no-cors cors-enabled corp-same-origin from network and CacheStorage.
PASS Fetch same-origin no-cors cors-enabled corp-undefined from network and CacheStorage.
PASS Fetch cross-origin cors cors-disabled corp-cross-origin from network and CacheStorage.
PASS Fetch cross-origin cors cors-disabled corp-same-origin from network and CacheStorage.
PASS Fetch cross-origin cors cors-disabled corp-undefined from network and CacheStorage.
PASS Fetch cross-origin cors cors-enabled corp-cross-origin from network and CacheStorage.
PASS Fetch cross-origin cors cors-enabled corp-same-origin from network and CacheStorage.
PASS Fetch cross-origin cors cors-enabled corp-undefined from network and CacheStorage.
PASS Fetch cross-origin no-cors cors-disabled corp-cross-origin from network and CacheStorage.
PASS Fetch cross-origin no-cors cors-disabled corp-same-origin from network and CacheStorage.
FAIL Fetch cross-origin no-cors cors-disabled corp-undefined from network and CacheStorage. assert_unreached: Should have rejected: undefined Reached unreachable code
PASS Fetch cross-origin no-cors cors-enabled corp-cross-origin from network and CacheStorage.
PASS Fetch cross-origin no-cors cors-enabled corp-same-origin from network and CacheStorage.
FAIL Fetch cross-origin no-cors cors-enabled corp-undefined from network and CacheStorage. assert_unreached: Should have rejected: undefined Reached unreachable code
Harness: the test ran to completion.
<!doctype html>
<html>
<title> Retrieve resources from CacheStorage with Cross-Origin-Embedder-Policy: require-corp</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>
/*
This document has the header Cross-Origin-Embedder-Policy: require-corp.
Cross-Origin Embedder Policy Editor's draft: https://mikewest.github.io/corpp/
This test is retrieving same-origin and cross-origin resources from the
CacheStorage. The resources are generated from the ServiceWorker or from the
network with the header Cross-Origin-Resource-Policy being one of:
- 'same-origin'
- 'cross-origin'
- <undefined>
*/
promise_test(async (t) => {
const SCOPE = new URL(location.href).pathname;
const SCRIPT =
'resources/sw-store-to-cache-storage.js?' +
`pipe=header(service-worker-allowed,${SCOPE})`;
await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
await new Promise(resolve => {
navigator.serviceWorker.addEventListener('controllerchange', resolve);
});
}, 'setting up');
function remote(path) {
const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
return new URL(path, REMOTE_ORIGIN);
}
function local(path) {
return new URL(path, location.origin);
}
// Send a message to the currently active ServiceWorker and wait for its
// response.
function executeCommandInServiceWorker(command) {
return new Promise(resolve => {
navigator.serviceWorker.addEventListener('message', e => resolve(e.data));
navigator.serviceWorker.controller.postMessage(command);
});
}
// Try loading an image from a |response|. Return a Promise resolving or
// rejecting depending on the image loading result.
function readImageFromResponse(response) {
return new Promise((resolve, reject) => {
const img = document.createElement("img");
img.onload = resolve.bind(this, "");
img.onerror = reject.bind(this, {name: "Image.onerror"});
response.blob().then(blob => {
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);
})
})
}
const image_path = "/images/blue.png?pipe=";
const corp_header = {
"":"",
"corp-undefined": "",
"corp-same-origin": "|header(Cross-Origin-Resource-Policy,same-origin)",
"corp-cross-origin": "|header(Cross-Origin-Resource-Policy,cross-origin)",
}
const cors_header = {
"":"",
"cors-disabled": "",
"cors-enabled": "|header(Access-Control-Allow-Origin,*)",
}
function test(
// Test parameters:
request_source, request_origin, request_mode, response_cors, response_corp,
// Test expectations:
response_stored, response_type) {
promise_test(async (t) => {
// 0. Start from an empty CacheStorage.
await caches.delete("v1");
// 1. Store a cross-origin no-cors response generated from the SW into the
// CacheStorage.
const path = image_path +
corp_header[response_corp] +
cors_header[response_cors];
const url = (request_origin === "same-origin" ? local : remote)(path);
const command = {
url: url.href,
mode: request_mode,
source: request_source,
};
assert_equals(await executeCommandInServiceWorker(command), response_stored);
if (response_stored === "not-stored") {
return;
}
// 2. Retrieve it from the CacheStorage.
const cache = await caches.open('v1');
if (response_type === 'error') {
await promise_rejects(t, new TypeError(), cache.match(url));
return;
}
const response = await cache.match(url);
assert_equals(response.type, response_type);
if (request_source === "service-worker") {
assert_equals("foo", await response.text());
return;
}
// Opaque response can't be read from the document.
if (response_type === "opaque") {
await promise_rejects(t, {name: "Image.onerror"}, readImageFromResponse(response));
return;
}
await readImageFromResponse(response);
}, `Fetch ${request_origin} ${request_mode} ${response_cors} ${response_corp} from ${request_source} and CacheStorage.`)
}
// Responses generated from the ServiceWorker.
{
test("service-worker", "cross-origin", "cors", "", "", "stored", "default");
test("service-worker", "cross-origin", "no-cors", "", "", "stored", "default");
test("service-worker", "same-origin", "cors", "", "", "stored", "default");
test("service-worker", "same-origin", "no-cors", "", "", "stored", "default");
}
// Responses generated from a same-origin server.
{
const t = test.bind(this, "network", "same-origin");
t("cors", "cors-disabled", "corp-cross-origin", "stored", "basic");
t("cors", "cors-disabled", "corp-same-origin", "stored", "basic");
t("cors", "cors-disabled", "corp-undefined", "stored", "basic");
t("cors", "cors-enabled", "corp-cross-origin", "stored", "basic");
t("cors", "cors-enabled", "corp-same-origin", "stored", "basic");
t("cors", "cors-enabled", "corp-undefined", "stored", "basic");
t("no-cors", "cors-disabled", "corp-cross-origin", "stored", "basic");
t("no-cors", "cors-disabled", "corp-same-origin", "stored", "basic");
t("no-cors", "cors-disabled", "corp-undefined", "stored", "basic");
t("no-cors", "cors-enabled", "corp-cross-origin", "stored", "basic");
t("no-cors", "cors-enabled", "corp-same-origin", "stored", "basic");
t("no-cors", "cors-enabled", "corp-undefined", "stored", "basic");
}
// Responses generated from a cross-origin server.
{
const t = test.bind(this, "network", "cross-origin");
t("cors", "cors-disabled", "corp-cross-origin", "not-stored");
t("cors", "cors-disabled", "corp-same-origin", "not-stored");
t("cors", "cors-disabled", "corp-undefined", "not-stored");
t("cors", "cors-enabled", "corp-cross-origin", "stored", "cors");
t("cors", "cors-enabled", "corp-same-origin", "stored", "cors");
t("cors", "cors-enabled", "corp-undefined", "stored", "cors");
t("no-cors", "cors-disabled", "corp-cross-origin", "stored", "opaque");
t("no-cors", "cors-disabled", "corp-same-origin", "not-stored");
t("no-cors", "cors-disabled", "corp-undefined", "stored", "error");
t("no-cors", "cors-enabled", "corp-cross-origin", "stored", "opaque");
t("no-cors", "cors-enabled", "corp-same-origin", "not-stored");
t("no-cors", "cors-enabled", "corp-undefined", "stored", "error");
}
</script>
</html>
self.addEventListener('activate', (e) => {
e.waitUntil(clients.claim());
});
self.addEventListener('message', (e) => {
e.waitUntil((async () => {
const url = new URL(e.data.url);
const request = new Request(url, {mode: e.data.mode});
const cache = await caches.open('v1');
let response;
switch(e.data.source) {
case "service-worker":
response = new Response('foo');
break;
case "network":
try {
response = await fetch(request);
} catch(error) {
e.source.postMessage('not-stored');
return;
}
break;
}
await cache.put(request, response);
e.source.postMessage('stored');
})());
})
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment