Commit 41f1c1c3 authored by Domenic Denicola's avatar Domenic Denicola Committed by Commit Bot

Origin isolation: add basic header-based WPTs

Bug: 1042415
Change-Id: I771434df7a4dbcf8b26ea0bceded1f3e7b136ada
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2116833
Commit-Queue: Domenic Denicola <domenic@chromium.org>
Reviewed-by: default avatarJames MacLean <wjmaclean@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758044}
parent 53107447
...@@ -220,6 +220,9 @@ crbug.com/974666 [ Mac10.13 ] http/tests/misc/object-embedding-svg-delayed-size- ...@@ -220,6 +220,9 @@ crbug.com/974666 [ Mac10.13 ] http/tests/misc/object-embedding-svg-delayed-size-
crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform-2.html [ Pass Crash ] crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform-2.html [ Pass Crash ]
crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform.html [ Pass Crash ] crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform.html [ Pass Crash ]
# This will likely be fixed as we finish off the origin isolation architecture work
crbug.com/1067389 external/wpt/origin-isolation/parent-no-child-yes-same.sub.https.html [ Pass Failure Crash ]
# Flakily timing out or failing. # Flakily timing out or failing.
# TODO(ccameron): Investigate this. # TODO(ccameron): Investigate this.
crbug.com/730267 virtual/gpu-rasterization/images/color-profile-group.html [ Pass Timeout Failure ] crbug.com/730267 virtual/gpu-rasterization/images/color-profile-group.html [ Pass Timeout Failure ]
......
spec: https://github.com/WICG/origin-isolation
suggested_reviewers:
- domenic
- annevk
- wjmaclean
# Origin isolation tests
These tests are for the proposal at [WICG/origin-isolation](https://github.com/WICG/origin-isolation). They should eventually move into a subdirectory of `html/` if/when that proposal merges into the HTML Standard.
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is not isolated, child is isolated, child is same-origin to the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][]}}", "?1");
});
// Since they're same-origin, and the parent loaded without isolation, the
// child's request for isolation gets ignored, and both end up site-keyed.
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "WebAssembly.Module message received");
}, "message event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
// Must not throw
frameWindow.document;
}, "setting document.domain must give sync access");
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is not isolated, child is isolated, child is a subdomain of the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][www]}}", "?1");
});
// Since they're different-origin, the child's isolation request is respected,
// so the parent ends up in the site-keyed agent cluster and the child in the
// origin-keyed one.
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "messageerror");
}, "messageerror event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
assert_throws_dom("SecurityError", DOMException, () => {
frameWindow.document;
});
}, "setting document.domain should no-op instead of giving sync access");
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is isolated, child is not isolated, child is same-origin to the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][]}}");
});
// Since they're same-origin, and the parent loaded with isolation, the
// child's non-request for isolation gets ignored, and both end up origin-keyed.
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "WebAssembly.Module message received");
}, "message event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
// Must not throw
frameWindow.document;
}, "setting document.domain must give sync access");
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is isolated, child is not isolated, child is a subdomain of the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][www]}}");
});
// Since they're different-origin, the parent's isolation request is respected,
// as is the child's non-request. So the parent ends up in the origin-keyed
// agent cluster and the child ends up in the site-keyed one.
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "messageerror");
}, "messageerror event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
assert_throws_dom("SecurityError", DOMException, () => {
frameWindow.document;
});
}, "setting document.domain must not give sync access");
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is isolated, child is not isolated, child is same-origin to the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][]}}", "?1");
});
// Both request isolation, and they're same-origin, so they both end up in the
// same origin-keyed agent cluster.
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "WebAssembly.Module message received");
}, "message event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
// Must not throw
frameWindow.document;
}, "setting document.domain must give sync access");
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<title>Parent is isolated, child is not isolated, child is a subdomain of the parent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import { insertIframe, sendWasmModule, setBothDocumentDomains } from "./resources/helpers.mjs";
let frameWindow;
promise_setup(async () => {
frameWindow = await insertIframe("{{hosts[][www]}}", "?1");
});
// Both request isolation, so the parent ends up in one origin-keyed agent
// cluster (the base domain's origin), and the child ends up in a different
// origin-keyed agent cluster (the www subdomain's origin).
promise_test(async () => {
const whatHappened = await sendWasmModule(frameWindow);
assert_equals(whatHappened, "messageerror");
}, "messageerror event must occur");
promise_test(async () => {
await setBothDocumentDomains(frameWindow);
assert_throws_dom("SecurityError", DOMException, () => {
frameWindow.document;
});
}, "setting document.domain must not give sync access");
</script>
export function insertIframe(hostname, header) {
const url = new URL("send-origin-isolation-header.py", import.meta.url);
url.hostname = hostname;
if (header !== undefined) {
url.searchParams.set("header", header);
}
const iframe = document.createElement("iframe");
iframe.src = url.href;
return new Promise((resolve, reject) => {
iframe.onload = () => resolve(iframe.contentWindow);
iframe.onerror = () => reject(new Error(`Could not load ${iframe.src}`));
document.body.append(iframe);
});
}
// This function is coupled to ./send-origin-isolation-header.py, which ensures
// that sending such a message will result in a message back.
export async function sendWasmModule(frameWindow) {
frameWindow.postMessage(await createWasmModule(), "*");
return waitForMessage();
}
// This function is coupled to ./send-origin-isolation-header.py, which ensures
// that sending such a message will result in a message back.
export async function setBothDocumentDomains(frameWindow) {
// By setting both this page's document.domain and the iframe's document.domain to the same
// value, we ensure that they can synchronously access each other, unless they are
// origin-isolated.
// NOTE: document.domain being unset is different than it being set to its current value.
// It is a terrible API.
document.domain = document.domain;
frameWindow.postMessage({ command: "set document.domain", newDocumentDomain: document.domain }, "*");
const whatHappened = await waitForMessage();
assert_equals(whatHappened, "document.domain is set");
}
function waitForMessage() {
return new Promise(resolve => {
window.addEventListener("message", e => resolve(e.data), { once: true });
});
}
// Any WebAssembly.Module will work fine for our tests; we just want to find out if it gives
// message or messageerror. So, we reuse one from the /wasm/ tests.
async function createWasmModule() {
const response = await fetch("/wasm/serialization/module/resources/incrementer.wasm");
const ab = await response.arrayBuffer();
return WebAssembly.compile(ab);
}
def main(request, response):
"""Send a response with the Origin-Isolation header given in the "header"
query parameter, or no header if that is not provided. In either case, the
response will listen for message and messageerror events and echo them back
to the parent. See ./helpers.mjs for how these handlers are used.
"""
if "header" in request.GET:
header = request.GET.first("header")
response.headers.set("Origin-Isolation", header)
response.headers.set("Content-Type", "text/html")
return """
<!DOCTYPE html>
<meta charset="utf-8">
<title>Helper page for origin isolation tests</title>
<script type="module">
window.onmessage = e => {
if (e.data.constructor === WebAssembly.Module) {
parent.postMessage("WebAssembly.Module message received", "*");
} else if (e.data.command === "set document.domain") {
document.domain = e.data.newDocumentDomain;
parent.postMessage("document.domain is set", "*");
}
};
window.onmessageerror = () => {
parent.postMessage("messageerror", "*");
};
</script>
"""
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