Fix up wpt/preload
- Some tests in wpt/preload use Resource Timing entries to make sure
that no requests are made. We're changing that (Resource Timing
entries should be created even when blocked by CSP - see
https://github.com/whatwg/fetch/issues/1215). Stop using
Resource Timing entries and check that with server side scripts.
- http/tests/preload/preload-csp.html is covered by some WPTs. Let's
remove it.
Change-Id: I3c2cdfa2459d212657be7569c5290c48b39d6f05
Bug: 1275564
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3708287
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1019490}
diff --git a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
index 19e09472e..2a5bc1a 100644
--- a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
+++ b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
@@ -1,39 +1,50 @@
<!DOCTYPE html>
<script nonce="abc" src="/resources/testharness.js"></script>
<script nonce="abc" src="/resources/testharnessreport.js"></script>
+<script nonce="abc" src="/common/utils.js"></script>
<script nonce="abc" src="/preload/resources/preload_helper.js"></script>
<body>
<script nonce="abc">
-async_test(function(t) {
- verifyPreloadAndRTSupport();
- var link = document.createElement("link");
- link.as = "script";
- link.rel = "preload";
- link.href = "resources/dummy.js?with-nonce";
- link.nonce = "abc";
- link.onload = link.onerror = t.step_func(function() {
- t.step_timeout(function() {
- verifyNumberOfResourceTimingEntries("resources/dummy.js?with-nonce", 1);
- t.done();
- }, 0);
- });
- document.body.appendChild(link);
+promise_test(async (t) => {
+ verifyPreloadAndRTSupport();
+ const id = token();
+ const link = document.createElement("link");
+ link.as = "script";
+ link.rel = "preload";
+ link.href = stashPutUrl(id);
+ link.nonce = "abc";
+
+ const load = new Promise((resolve) => {
+ link.onload = resolve;
+ });
+ link.onerror = t.unreached_func("link.onerror");
+
+ document.body.appendChild(link);
+ await load;
+
+ const arrived = await hasArrivedAtServer(id);
+ assert_true(arrived, "The preload should've arrived at the server.");
}, "link preload with nonce attribute");
-async_test(function(t) {
- verifyPreloadAndRTSupport();
- var link = document.createElement("link");
- link.as = "script";
- link.rel = "preload";
- link.href = "resources/dummy.js?without-nonce";
- link.onload = link.onerror = t.step_func(function() {
- t.step_timeout(function() {
- verifyNumberOfResourceTimingEntries("resources/dummy.js?without-nonce", 0);
- t.done();
- }, 0);
- });
- document.body.appendChild(link);
+promise_test(async (t) => {
+ verifyPreloadAndRTSupport();
+ const id = token();
+ const link = document.createElement("link");
+ link.as = "script";
+ link.rel = "preload";
+ link.href = stashPutUrl(id);
+
+ const error = new Promise((resolve) => {
+ link.onerror = resolve;
+ });
+ link.onload = t.unreached_func("link.onload");
+
+ document.body.appendChild(link);
+ await error;
+
+ const arrived = await hasArrivedAtServer(id);
+ assert_false(arrived, "The preload should've arrived at the server.");
}, "link preload without nonce attribute");
</script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
index 74ea870..cd2d8fbb 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
@@ -1,33 +1,53 @@
<!DOCTYPE html>
-<title>Makes sure that Link headers preload resources with CSP nonce</title>
-<script nonce="abc" src="/resources/testharness.js"></script>
-<script nonce="abc" src="/resources/testharnessreport.js"></script>
-<script nonce="abc" src="/preload/resources/preload_helper.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/preload/resources/preload_helper.js"></script>
<body>
-<script nonce="abc">
- setup({single_test: true});
+<script>
- var iterations = 0;
+async_test(t => {
+ const id = token();
+ const pageUrl =
+ '/common/blank.html?pipe=' +
+ '|header(content-security-policy, script-src \'nonce-abc\')' +
+ `|header(link, <${encodedStashPutUrl(id)}>;rel=preload;as=script)`;
- function check_finished() {
- if (numberOfResourceTimingEntries("resources/dummy.js?from-header&without-nonce") == 0 &&
- numberOfResourceTimingEntries("resources/dummy.js?from-header&with-nonce") == 1) {
- done();
- }
- iterations++;
- if (iterations == 10) {
- // At least one is expected to fail, but this should give details to the exact failure(s).
- verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&without-nonce", 0);
- verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&with-nonce", 1);
- done();
- } else {
- step_timeout(check_finished, 500);
- }
+ const w = window.open(pageUrl);
+ t.add_cleanup(() => w.close());
+
+ step_timeout(async () => {
+ try {
+ const arrived = await hasArrivedAtServer(id);
+ assert_false(arrived, 'The preload should be blocked.');
+ t.done();
+ } catch (e) {
+ t.step(() => {throw e;});
}
+ }, 3000);
+}, 'without nonce');
- window.addEventListener("load", function() {
- verifyPreloadAndRTSupport();
- step_timeout(check_finished, 500);
- });
+async_test(t => {
+ const id = token();
+ const pageUrl =
+ '/common/blank.html?pipe=' +
+ '|header(content-security-policy, script-src \'nonce-az\')' +
+ `|header(link, <${encodedStashPutUrl(id)}>;rel=preload;as=script;nonce=az)`;
+ const w = window.open(pageUrl);
+ t.add_cleanup(() => w.close());
+
+ // TODO: Use step_wait after
+ // https://github.com/web-platform-tests/wpt/pull/34289 is merged.
+ step_timeout(async () => {
+ try {
+ const arrived = await hasArrivedAtServer(id);
+ assert_true(arrived, 'The preload should have arrived at the server.');
+ t.done();
+ } catch (e) {
+ t.step(() => {throw e;});
+ }
+ }, 3000);
+}, 'with nonce');
+
</script>
</body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html.headers b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html.headers
deleted file mode 100644
index a54b6937..0000000
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html.headers
+++ /dev/null
@@ -1,3 +0,0 @@
-Content-Security-Policy: script-src 'nonce-abc'
-Link: </preload/resources/dummy.js?from-header&without-nonce>;rel=preload;as=script
-Link: </preload/resources/dummy.js?from-header&with-nonce>;rel=preload;as=script;nonce=abc
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
index a11214e9..7d367bf 100644
--- a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
@@ -1,55 +1,35 @@
<!DOCTYPE html>
-<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; font-src 'none'; style-src 'none'; img-src 'none'; media-src 'none'; connect-src 'none'">
+<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; font-src 'none'; style-src 'none'; img-src 'none'; media-src 'none';">
<title>Makes sure that preload requests respect CSP</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
<script src="/preload/resources/preload_helper.js"></script>
-<link rel=preload href="{{host}}:{{ports[http][1]}}/preload/resources/dummy.js" as=style>
-<link rel=preload href="resources/dummy.css" as=style>
-<link rel=preload href="resources/square.png" as=image>
-<link rel=preload href="/fonts/CanvasTest.ttf" as=font crossorigin>
-<link rel=preload href="resources/white.mp4" as=video>
-<link rel=preload href="resources/sound_5.oga" as=audio>
-<link rel=preload href="resources/foo.vtt" as=track>
-<link rel=preload href="resources/dummy.xml?foo=bar" as=foobarxmlthing>
-<link rel=preload href="resources/dummy.xml">
+<link rel=preload href="http://{{host}}:{{ports[http][1]}}/preload/resources/stash-put.py?key={{uuid()}}" as=style>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=style>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=image>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=font crossorigin>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=video>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=audio>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=track>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=foobarxmlthing>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}">
<body>
<script>
- setup({single_test: true});
-
- var iterations = 0;
-
- function check_finished() {
- if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 &&
- numberOfResourceTimingEntries("resources/dummy.css") == 0 &&
- numberOfResourceTimingEntries("resources/square.png") == 0 &&
- numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 &&
- numberOfResourceTimingEntries("resources/white.mp4") == 0 &&
- numberOfResourceTimingEntries("resources/sound_5.oga") == 0 &&
- numberOfResourceTimingEntries("resources/foo.vtt") == 0 &&
- numberOfResourceTimingEntries("resources/dummy.xml") == 0) {
- done();
- }
- iterations++;
- if (iterations == 10) {
- // At least one is expected to fail, but this should give details to the exact failure(s).
- verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
- verifyNumberOfResourceTimingEntries("resources/dummy.css", 0);
- verifyNumberOfResourceTimingEntries("resources/square.png", 0);
- verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0);
- verifyNumberOfResourceTimingEntries("resources/white.mp4", 0);
- verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0);
- verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0);
- verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0);
- done();
- } else {
- step_timeout(check_finished, 500);
- }
+promise_test(async (t) => {
+ verifyPreloadAndRTSupport();
+ const keys = [];
+ const links = document.querySelectorAll('link');
+ for (const link of links) {
+ if (link.rel === 'preload') {
+ const r = /\?key=([a-zA-Z0-9\-]+)$/;
+ keys.push(link.href.match(r)[1]);
}
+ }
+ await new Promise((resolve) => step_timeout(resolve, 3000));
- window.addEventListener("load", function() {
- verifyPreloadAndRTSupport();
- step_timeout(check_finished, 500);
- });
+ for (const key of keys) {
+ assert_false(await hasArrivedAtServer(key));
+ }
+}, 'Preload requests are blocked by CSP.');
</script>
-
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
index c649a53f..8d280c4 100644
--- a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
@@ -1,55 +1,35 @@
<!DOCTYPE html>
-<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; default-src 'none'">
+<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; default-src 'none'; connect-src 'self';">
<title>Makes sure that preload requests respect CSP</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/preload/resources/preload_helper.js"></script>
-<link rel=preload href="{{host}}:{{ports[http][1]}}/preload/resources/dummy.js" as=style>
-<link rel=preload href="resources/dummy.css" as=style>
-<link rel=preload href="resources/square.png" as=image>
-<link rel=preload href="/fonts/CanvasTest.ttf" as=font crossorigin>
-<link rel=preload href="resources/white.mp4" as=video>
-<link rel=preload href="resources/sound_5.oga" as=audio>
-<link rel=preload href="resources/foo.vtt" as=track>
-<link rel=preload href="resources/dummy.xml?foo=bar" as=foobarxmlthing>
-<link rel=preload href="resources/dummy.xml">
+<link rel=preload href="http://{{host}}:{{ports[http][1]}}/preload/resources/stash-put.py?key={{uuid()}}" as=style>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=style>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=image>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=font crossorigin>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=video>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=audio>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=track>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}" as=foobarxmlthing>
+<link rel=preload href="/preload/resources/stash-put.py?key={{uuid()}}">
<body>
<script>
- setup({single_test: true});
-
- var iterations = 0;
-
- function check_finished() {
- if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 &&
- numberOfResourceTimingEntries("resources/dummy.css") == 0 &&
- numberOfResourceTimingEntries("resources/square.png") == 0 &&
- numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 &&
- numberOfResourceTimingEntries("resources/white.mp4") == 0 &&
- numberOfResourceTimingEntries("resources/sound_5.oga") == 0 &&
- numberOfResourceTimingEntries("resources/foo.vtt") == 0 &&
- numberOfResourceTimingEntries("resources/dummy.xml") == 0) {
- done();
- }
- iterations++;
- if (iterations == 10) {
- // At least one is expected to fail, but this should give details to the exact failure(s).
- verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
- verifyNumberOfResourceTimingEntries("resources/dummy.css", 0);
- verifyNumberOfResourceTimingEntries("resources/square.png", 0);
- verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0);
- verifyNumberOfResourceTimingEntries("resources/white.mp4", 0);
- verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0);
- verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0);
- verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0);
- done();
- } else {
- step_timeout(check_finished, 500);
- }
+promise_test(async (t) => {
+ verifyPreloadAndRTSupport();
+ const keys = [];
+ const links = document.querySelectorAll('link');
+ for (const link of links) {
+ if (link.rel === 'preload') {
+ const r = /\?key=([a-zA-Z0-9\-]+)$/;
+ keys.push(link.href.match(r)[1]);
}
+ }
+ await new Promise((resolve) => step_timeout(resolve, 3000));
- window.addEventListener("load", function() {
- verifyPreloadAndRTSupport();
- step_timeout(check_finished, 500);
- });
+ for (const key of keys) {
+ assert_false(await hasArrivedAtServer(key));
+ }
+}, 'Preload requests are blocked by CSP ("default-src \'none\').');
</script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.html b/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.html
deleted file mode 100644
index 7639565..0000000
--- a/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<head>
-<script src="/resources/testharness.js" nonce="123"></script>
-<script src="/resources/testharnessreport.js" nonce="123"></script>
-<title>CSP strict-dynamic + preload</title>
-<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-123' 'strict-dynamic'" />
-</head>
-<body>
-<link id="static-no-nonce" href="resources/dummy.js?static-no-nonce" rel=preload as=script>
-<link id="static-nonce" href="resources/dummy.js?static-nonce" rel=preload as=script nonce="123">
-<script nonce="123">
- let counter = 0;
- let cspViolation = false;
- let isLoaded = (url) => {
- let entries = performance.getEntriesByType("resource");
- for (let entry of entries) {
- if (entry.name.indexOf(url) != -1 ) {
- return true;
- }
- }
- return false;
- }
- window.addEventListener("securitypolicyviolation", (e) => {
- counter++;
- if (e.violatedDirective == "script-src-elem" && e.blockedURI.includes("static-no-nonce")) {
- cspViolation = true;
- }
- });
- let link = document.createElement("link");
- link.rel = "preload";
- link.href = "resources/dummy.js?dynamic-nonce";
- link.as = "script";
- link.onload = () => { ++counter; };
- document.head.appendChild(link);
- link = document.getElementById("static-no-nonce");
- link.addEventListener("error", () => { ++counter; });
- link = document.getElementById("static-nonce");
- link.addEventListener("load", () => { ++counter; });
- let t = async_test('preload from nonced script should work with strict-dynamic. preloaded script from markup should not.');
- let timerCounter = 0;
- setInterval(t.step_func(() => {
- if (counter >= 4 || timerCounter > 5) {
- assert_true(isLoaded("dynamic-nonce"), "dynamic inserted preload script should have been loaded");
- assert_true(isLoaded("static-nonce"), "preload tag with a nonce should have been loaded");
- assert_false(isLoaded("static-no-nonce"), "preload tag without a nonce should not have been loaded");
- assert_true(cspViolation, "CSP violation should have fired");
- t.done();
- }
- ++timerCounter;
- }), 100);
-
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.sub.html
new file mode 100644
index 0000000..bdd7a17
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-strict-dynamic.sub.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js" nonce="123"></script>
+<script src="/resources/testharnessreport.js" nonce="123"></script>
+<script src="/common/utils.js" nonce="123"></script>
+<script src="/preload/resources/preload_helper.js" nonce="123"></script>
+<title>CSP strict-dynamic + preload</title>
+<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-123' 'strict-dynamic'" />
+</head>
+<body>
+<script nonce="123">
+const PATTERN = /\?key=([a-zA-Z0-9\-]+)$/;
+
+// We use async_test instead of promise_test in this file because these
+// tests take long time to run and we want to run them in parallel.
+async_test((t) => {
+ Promise.resolve().then(async () => {
+ let sawViolation = false;
+ self.addEventListener('securitypolicyviolation', (e) => {
+ const link = document.querySelector('#static-no-nonce');
+ if (e.violatedDirective == 'script-src-elem' && e.blockedURI === link.href) {
+ sawViolation = true;
+ }
+ });
+
+ await new Promise((resolve) => step_timeout(resolve, 3000));
+
+ const link = document.querySelector('#static-no-nonce');
+ const key = link.href.match(PATTERN)[1]
+
+ assert_true(sawViolation, 'sawViolation');
+ assert_false(await hasArrivedAtServer(key), 'hasArrivedAtServer');
+ t.done();
+ }).catch(t.step_func((e) => {
+ throw e;
+ }));
+}, 'static-no-nonce');
+
+async_test((t) => {
+ Promise.resolve().then(async () => {
+ let sawViolation = false;
+ self.addEventListener('securitypolicyviolation', (e) => {
+ const link = document.querySelector('#static-nonce');
+ if (e.violatedDirective == 'script-src-elem' && e.blockedURI === link.href) {
+ sawViolation = true;
+ }
+ });
+
+ // TODO: Use step_wait after
+ // https://github.com/web-platform-tests/wpt/pull/34289 is merged.
+ await new Promise((resolve) => step_timeout(resolve, 3000));
+
+ const link = document.querySelector('#static-nonce');
+ const key = link.href.match(PATTERN)[1]
+
+ assert_false(sawViolation, 'sawViolation');
+ assert_true(await hasArrivedAtServer(key), 'hasArrivedAtServer');
+ t.done();
+ }).catch(t.step_func((e) => {
+ throw e;
+ }));
+}, 'static-nonce');
+
+async_test((t) => {
+ Promise.resolve().then(async () => {
+ const link = document.createElement('link');
+ link.rel = 'preload';
+ const id = token();
+ link.href = `/preload/resources/stash-put.py?key=${id}`;
+ link.as = 'script';
+
+ document.head.appendChild(link);
+ await new Promise((resolve, reject) => {
+ link.addEventListener('load', resolve, {once: true});
+ link.addEventListener('error', resolve, {once: true});
+ });
+ assert_true(await hasArrivedAtServer(id), 'hasArrivedAtServer');
+ t.done();
+ }).catch(t.step_func((e) => {
+ throw e;
+ }));
+}, 'dynamic');
+</script>
+
+<link id="static-no-nonce" href="/preload/resources/stash-put.py?key={{uuid()}}" rel=preload as=script>
+<link id="static-nonce" href="/preload/resources/stash-put.py?key={{uuid()}}" rel=preload as=script nonce="123">
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js b/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
index 1c7c1a27..5b7a6eb 100644
--- a/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
+++ b/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
@@ -1,3 +1,18 @@
+function stashPutUrl(token) {
+ return `/preload/resources/stash-put.py?key=${token}`;
+}
+
+function encodedStashPutUrl(token) {
+ return encodeURIComponent(stashPutUrl(token));
+}
+
+async function hasArrivedAtServer(token) {
+ const res = await fetch(`/preload/resources/stash-take.py?key=${token}`);
+ assert_true(res.status === 200 || res.status === 404,
+ 'status must be either 200 or 404');
+ return res.status === 200;
+}
+
function verifyPreloadAndRTSupport()
{
var link = window.document.createElement("link");
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/stash-put.py b/third_party/blink/web_tests/external/wpt/preload/resources/stash-put.py
new file mode 100644
index 0000000..f4bc8794
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/resources/stash-put.py
@@ -0,0 +1,20 @@
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ if request.method == u'OPTIONS':
+ # CORS preflight
+ response.headers.set(b'Access-Control-Allow-Origin', b'*')
+ response.headers.set(b'Access-Control-Allow-Methods', b'*')
+ response.headers.set(b'Access-Control-Allow-Headers', b'*')
+ return 'done'
+
+ url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
+ key = request.GET.first(b"key")
+ if b"value" in request.GET:
+ value = request.GET.first(b"value")
+ else:
+ value = b"value"
+ # value here must be a text string. It will be json.dump()'ed in stash-take.py.
+ request.server.stash.put(key, isomorphic_decode(value), url_dir)
+ response.headers.set(b'Access-Control-Allow-Origin', b'*')
+ return "done"
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/stash-take.py b/third_party/blink/web_tests/external/wpt/preload/resources/stash-take.py
new file mode 100644
index 0000000..9977197
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/resources/stash-take.py
@@ -0,0 +1,14 @@
+from wptserve.handlers import json_handler
+
+
+@json_handler
+def main(request, response):
+ dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/'
+ key = request.GET.first(b"key")
+ response.headers.set(b'Access-Control-Allow-Origin', b'*')
+ value = request.server.stash.take(key, dir)
+ if value is None:
+ response.status = 404
+ return 'No entry is found'
+ response.status = 200
+ return value
diff --git a/third_party/blink/web_tests/http/tests/preload/preload-csp.html b/third_party/blink/web_tests/http/tests/preload/preload-csp.html
deleted file mode 100644
index 7a06d81f..0000000
--- a/third_party/blink/web_tests/http/tests/preload/preload-csp.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<meta http-equiv="Content-Security-Policy" content="font-src 'none'">
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
- var t = async_test('Makes sure that preload requests respect CSP');
-</script>
-<link rel=preload href="../resources/Ahem.ttf" as=font crossorigin>
-<script src="../resources/slow-script.pl?delay=200"></script>
-<script>
- window.onload = t.step(function(){
- var entries = performance.getEntriesByName(new URL("../resources/Ahem.ttf", location.href).href);
- assert_equals(entries.length, 0);
- t.done();
- });
-</script>
-