Skip to content

Commit bf413b3

Browse files
committed
Add tests for new CSP behavior for resource hints (prefetch)
Instead of relying on `prefetch-src`, we rely on the least restrictive directive in the policy. Tests w3c/webappsec-csp#582
1 parent 4530a81 commit bf413b3

6 files changed

+116
-15
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src='/resources/testharness.js'></script>
5+
<script src='/resources/testharnessreport.js'></script>
6+
<script src='/common/utils.js'></script>
7+
<script src='/common/get-host-info.sub.js'></script>
8+
<script src='/content-security-policy/support/testharness-helper.js'></script>
9+
<script src='/content-security-policy/support/prefetch-helper.js'></script>
10+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'unsafe-inline'; img-src 'http://{{domains[www2]}}:{{ports[http][0]}}'">
11+
<script>
12+
const {OTHER_ORIGIN, REMOTE_ORIGIN} = get_host_info();
13+
promise_test(async t => {
14+
assert_true(await try_to_prefetch("/common/dummy.xml", t));
15+
}, 'Prefetch should succeed when restricted by default-src but allowed by other directive');
16+
promise_test(async t => {
17+
assert_false(await try_to_prefetch(new URL("/common/dummy.xml", REMOTE_ORIGIN).toString(), t));
18+
}, 'Prefetch should fail when restricted by default-src and different origin allowed by other directive');
19+
promise_test(async t => {
20+
assert_true(await try_to_prefetch(new URL("/common/dummy.xml", OTHER_ORIGIN).toString(), t));
21+
}, 'Prefetch should succeed when restricted by default-src but origin allowed by other directive');
22+
</script>
23+
</head>
24+
<body>
25+
</body>
26+
</html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'">
5+
<script src='/resources/testharness.js'></script>
6+
<script src='/resources/testharnessreport.js'></script>
7+
<script src='/common/utils.js'></script>
8+
<script src='/content-security-policy/support/testharness-helper.js'></script>
9+
<script src='/content-security-policy/support/prefetch-helper.js'></script>
10+
<script>
11+
promise_test(async t => {
12+
assert_true(await try_to_prefetch("/common/dummy.xml", t));
13+
}, 'Prefetch should fail when allowed by default-src');
14+
</script>
15+
</head>
16+
<body>
17+
</body>
18+
</html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' img-src 'self' 'unsafe-inline' connect-src 'self' 'unsafe-inline' object-src 'self' 'unsafe-inline' font-src 'self' 'unsafe-inline' child-src 'self' 'unsafe-inline'">
5+
<script src='/resources/testharness.js'></script>
6+
<script src='/resources/testharnessreport.js'></script>
7+
<script src='/common/utils.js'></script>
8+
<script src='/content-security-policy/support/testharness-helper.js'></script>
9+
<script src='/content-security-policy/support/prefetch-helper.js'></script>
10+
<script>
11+
promise_test(async t => {
12+
assert_true(await try_to_prefetch("/common/dummy.xml", t));
13+
}, 'Prefetch should succeed when there is no default-src');
14+
</script>
15+
</head>
16+
<body>
17+
</body>
18+
</html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src='/resources/testharness.js'></script>
5+
<script src='/resources/testharnessreport.js'></script>
6+
<script src='/common/utils.js'></script>
7+
<script src='/content-security-policy/support/testharness-helper.js'></script>
8+
<script src='/content-security-policy/support/prefetch-helper.js'></script>
9+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'">
10+
<script>
11+
promise_test(async t => {
12+
assert_false(await try_to_prefetch("/common/dummy.xml", t));
13+
}, 'Prefetch should fail when restricted by default-src');
14+
</script>
15+
</head>
16+
<body>
17+
</body>
18+
</html>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src='/resources/testharness.js'></script>
5+
<script src='/resources/testharnessreport.js'></script>
6+
<script src='/common/utils.js'></script>
7+
<script src='/content-security-policy/support/testharness-helper.js'></script>
8+
<script src='/content-security-policy/support/prefetch-helper.js'></script>
9+
<script>
10+
promise_test(async t => {
11+
assert_true(await try_to_prefetch("/common/dummy.xml", t));
12+
}, 'Prefetch succeeds when no CSP');
13+
</script>
14+
</head>
15+
<body>
16+
</body>
17+
</html>

content-security-policy/support/prefetch-helper.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,6 @@ setup(_ => {
77
"Browser supports performance APIs.");
88
});
99

10-
async function waitUntilResourceDownloaded(url) {
11-
await new Promise((resolve, reject) => {
12-
if (performance.getEntriesByName(url).length >= 1)
13-
resolve();
14-
15-
let observer = new PerformanceObserver(list => {
16-
list.getEntries().forEach(entry => {
17-
if (entry.name == url) {
18-
resolve();
19-
}
20-
});
21-
});
22-
});
23-
}
24-
2510
function assert_resource_not_downloaded(test, url) {
2611
// CSP failures generate resource timing entries, so let's make sure that
2712
// download sizes are 0.
@@ -69,3 +54,22 @@ function assert_link_does_not_prefetch(test, link) {
6954

7055
document.head.appendChild(link);
7156
}
57+
58+
async function try_to_prefetch(href, t) {
59+
const url = new URL(href, location.href);
60+
url.searchParams.set("pipe", "header(Cache-Control, max-age=604800)");
61+
url.searchParams.set("uuid", token());
62+
const link = document.createElement("link");
63+
link.rel = "prefetch";
64+
link.href = url.toString();
65+
link.crossOrigin = "anonymous";
66+
t.add_cleanup(() => link.remove());
67+
const didPrefetch = new Promise(resolve => new PerformanceObserver(list => {
68+
const entries = list.getEntriesByName(link.href);
69+
if (entries.length)
70+
resolve(entries[0]);
71+
}).observe({entryTypes: ["resource"]}));
72+
document.head.appendChild(link);
73+
const entry = await didPrefetch;
74+
return entry.requestStart > 0 && entry.decodedBodySize > 0;
75+
}

0 commit comments

Comments
 (0)