Skip to content

Commit 04ab86b

Browse files
xiaochen-zchromium-wpt-export-bot
authored andcommitted
[Connection-Allowlist] Enforce for cross-origin document prefetch
Enforce by passing the network restriction id to URLLoaderFactoryParamsHelper::CreateForPrefetch. The param is used by CrossOriginPrefetchLoaderFactory, which is for <link> prefetch that: - is cross-origin - having attribute `as="document"` Note: Browser test is not added for header triggered prefetch because crbug.com/40752428 makes the test flaky. The WPT that also uses header triggered prefetch somehow does not flake in try bots. Bug: 447954811, 507078585 Change-Id: I31b41b063c75026b52c28a1dbfb04f58deb10a90 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7832782 Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Commit-Queue: Xiaochen Zhou <xiaochenzh@chromium.org> Reviewed-by: Andrew Verge <averge@chromium.org> Cr-Commit-Position: refs/heads/main@{#1631576}
1 parent 6d630f5 commit 04ab86b

6 files changed

Lines changed: 98 additions & 0 deletions
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// META: script=/common/utils.js
2+
// META: script=resources/utils.js
3+
//
4+
// The test assumes the policy `Connection-Allowlist:
5+
// "*://:subdomain.{{hosts[alt][]}}:*"` has been set in the response. The
6+
// response also contains a link header that triggers a prefetch to the
7+
// cross-origin KV server at http://{{hosts[alt][www]}}:{{ports[http][0]}}.
8+
9+
promise_test(async () => {
10+
const result =
11+
await nextValueFromServer('d5c4b2a1-7e8d-4c60-91da-2a57191363c2');
12+
assert_equals(result, 'hello');
13+
}, 'Link header prefetch (as=document) to an allow-listed url succeeds.');
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Connection-Allowlist: (response-origin "*://:subdomain.{{hosts[alt][]}}:*" "*://*:*/*\\?*&ignore-allowlist=true*")
2+
Link: <http://{{hosts[alt][www]}}:{{ports[http][0]}}/connection-allowlist/tentative/resources/key-value-store.py?key=d5c4b2a1-7e8d-4c60-91da-2a57191363c2&value=hello>; rel=prefetch; as=document
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// META: script=/common/utils.js
2+
// META: script=resources/utils.js
3+
// META: timeout=long
4+
//
5+
// The test assumes the policy `Connection-Allowlist: (response-origin)` has
6+
// been set in the response. The response also contains a link header that
7+
// triggers a prefetch to the cross-origin KV server at
8+
// http://{{hosts[][www]}}:{{ports[http][0]}}.
9+
10+
promise_test(async (t) => {
11+
const result = await Promise.race([
12+
new Promise(r => t.step_timeout(r, 1000)),
13+
nextValueFromServer('a9853747-3a23-4802-a907-327ce0a888f0')
14+
]);
15+
assert_true(typeof result === 'undefined');
16+
}, 'Link header prefetch (as=document) to a not allow-listed url fails.');
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Connection-Allowlist: (response-origin "*://*:*/*\\?*&ignore-allowlist=true*")
2+
Link: <http://{{hosts[][www]}}:{{ports[http][0]}}/connection-allowlist/tentative/resources/key-value-store.py?key=a9853747-3a23-4802-a907-327ce0a888f0&value=hello>; rel=prefetch; as=document
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// META: script=/common/get-host-info.sub.js
2+
// META: script=/common/utils.js
3+
// META: script=resources/utils.js
4+
// META: timeout=long
5+
6+
const port = get_host_info().HTTP_PORT_ELIDED;
7+
const SUCCESS = true;
8+
const FAILURE = false;
9+
10+
function prefetch_test(origin, expectation) {
11+
promise_test(
12+
async t => {
13+
const key = token();
14+
const value = 'hello';
15+
const params = new URLSearchParams();
16+
params.set('key', key);
17+
params.set('value', value);
18+
19+
const link = document.createElement('link');
20+
link.rel = 'prefetch';
21+
link.as = 'document';
22+
link.href = `${origin}${STORE_URL}?${params.toString()}`;
23+
document.head.appendChild(link);
24+
t.add_cleanup(() => link.remove());
25+
26+
if (expectation === SUCCESS) {
27+
const result = await nextValueFromServer(key);
28+
assert_equals(result, value);
29+
} else {
30+
const result = await Promise.race([
31+
new Promise(r => t.step_timeout(r, 1000)), nextValueFromServer(key)
32+
]);
33+
assert_true(typeof result === 'undefined');
34+
}
35+
},
36+
`Prefetch (as=document) to ${origin} ${
37+
expectation === SUCCESS ? 'succeeds' : 'fails'}.`);
38+
}
39+
40+
const test_cases = [
41+
// Page loads originate from `http://hosts[][]`; prefetching this origin
42+
// succeeds, while subdomains fail as they are cross-origin but not
43+
// allow-listed.
44+
{origin: 'http://{{hosts[][]}}' + port, expectation: SUCCESS},
45+
{origin: 'http://{{hosts[][www]}}' + port, expectation: FAILURE},
46+
{origin: 'http://{{hosts[][www1]}}' + port, expectation: FAILURE},
47+
{origin: 'http://{{hosts[][www2]}}' + port, expectation: FAILURE},
48+
{origin: 'http://{{hosts[][天気の良い日]}}' + port, expectation: FAILURE},
49+
{origin: 'http://{{hosts[][élève]}}' + port, expectation: FAILURE},
50+
51+
// The pattern we've specified in the header ("*://*.hosts[alt]:*/") will
52+
// match any subdomain of `hosts[alt]` (though not, as it turns out,
53+
// `hosts[alt]` itself.
54+
{origin: 'http://{{hosts[alt][]}}' + port, expectation: FAILURE},
55+
{origin: 'http://{{hosts[alt][www]}}' + port, expectation: SUCCESS},
56+
{origin: 'http://{{hosts[alt][www1]}}' + port, expectation: SUCCESS},
57+
{origin: 'http://{{hosts[alt][www2]}}' + port, expectation: SUCCESS},
58+
{origin: 'http://{{hosts[alt][天気の良い日]}}' + port, expectation: SUCCESS},
59+
{origin: 'http://{{hosts[alt][élève]}}' + port, expectation: SUCCESS},
60+
];
61+
62+
for (let i = 0; i < test_cases.length; i++) {
63+
prefetch_test(test_cases[i].origin, test_cases[i].expectation);
64+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Connection-Allowlist: (response-origin "*://:subdomain.{{hosts[alt][]}}:*" "*://*:*/*\\?*&ignore-allowlist=true*")

0 commit comments

Comments
 (0)