From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../early-hints/404-with-early-hints.h2.window.js | 10 ++ .../arbitrary-header-in-early-hints.h2.window.js | 4 + ...arly-hints-none-final-require-corp.h2.window.js | 9 + ...arly-hints-require-corp-final-none.h2.window.js | 9 + ...sp-early-hints-absent-final-absent.h2.window.js | 8 + ...p-early-hints-absent-final-allowed.h2.window.js | 8 + ...arly-hints-absent-final-disallowed.h2.window.js | 8 + ...p-early-hints-allowed-final-absent.h2.window.js | 8 + ...-early-hints-allowed-final-allowed.h2.window.js | 8 + ...rly-hints-allowed-final-disallowed.h2.window.js | 8 + ...arly-hints-disallowed-final-absent.h2.window.js | 8 + ...rly-hints-disallowed-final-allowed.h2.window.js | 8 + ...-hints-disallowed-final-disallowed.h2.window.js | 8 + .../early-hints/early-hints-response-time.h2.html | 27 +++ .../loading/early-hints/embed-object.h2.window.js | 44 +++++ .../early-hints/iframe-coep-disallow.h2.html | 35 ++++ .../iframe-coep-disallow.h2.html.headers | 1 + .../loading/early-hints/iframe-pdf.h2.window.js | 31 ++++ .../iframe-x-frame-options-deny.h2.window.js | 27 +++ .../invalid-headers-in-early-hints.h2.window.js | 22 +++ ...dulepreload-as-worker-cross-origin.h2.window.js | 15 ++ .../modulepreload-as-worker.h2.window.js | 15 ++ .../modulepreload-cross-origin.h2.window.js | 13 ++ .../modulepreload-in-early-hints.h2.window.js | 20 +++ .../multiple-early-hints-responses.h2.window.js | 11 ++ .../preconnect-in-early-hints.h2.window.js | 12 ++ .../loading/early-hints/preload-fetch.h2.window.js | 10 ++ ...oad-finished-before-final-response.h2.window.js | 11 ++ ...hile-receiving-final-response-body.h2.window.js | 11 ++ .../preload-in-flight-when-consumed.h2.window.js | 11 ++ .../preload-initiator-type.h2.window.js | 9 + ...preload-with-csp-document-disallow.h2.window.js | 7 + .../preload-with-invalid-as.h2.window.js | 14 ++ .../early-hints/preload-without-as.h2.window.js | 13 ++ ...load-without-csp-document-disallow.h2.window.js | 7 + ...t-cross-origin-between-early-hints.h2.window.js | 14 ++ .../early-hints/redirect-cross-origin.h2.window.js | 10 ++ ...ct-same-origin-between-early-hints.h2.window.js | 14 ++ .../early-hints/redirect-same-origin.h2.window.js | 10 ++ .../referrer-policy-no-referrer.h2.window.js | 4 + ...er-policy-origin-when-cross-origin.h2.window.js | 4 + .../referrer-policy-origin.h2.window.js | 4 + .../referrer-policy-same-origin.h2.window.js | 4 + .../referrer-policy-unsafe-url.h2.window.js | 4 + .../resources/404-with-early-hints.h2.py | 24 +++ .../resources/404-with-early-hints.html | 15 ++ .../arbitrary-header-in-early-hints.h2.py | 24 +++ .../resources/arbitrary-header-in-early-hints.html | 11 ++ .../early-hints/resources/coep-mismatch.h2.py | 30 ++++ .../early-hints/resources/coep-mismatch.html | 24 +++ .../early-hints/resources/csp-basic-loader.h2.py | 47 ++++++ .../loading/early-hints/resources/csp-basic.html | 37 +++++ .../resources/csp-document-disallow-loader.h2.py | 39 +++++ .../resources/csp-document-disallow.html | 26 +++ .../loading/early-hints/resources/delayed-js.h2.py | 16 ++ .../early-hints/resources/early-hints-delay.h2.py | 20 +++ .../resources/early-hints-helpers.sub.js | 182 +++++++++++++++++++++ .../resources/early-hints-test-loader.h2.py | 51 ++++++ .../early-hints/resources/empty-corp-absent.js | 1 + .../resources/empty-corp-absent.js.headers | 1 + .../tests/loading/early-hints/resources/empty.js | 1 + .../loading/early-hints/resources/empty.js.headers | 4 + .../tests/loading/early-hints/resources/empty.json | 1 + .../early-hints/resources/empty.json.headers | 4 + .../loading/early-hints/resources/example.pdf | 50 ++++++ .../resources/fetch-and-record-js.h2.py | 16 ++ .../resources/get-fetch-timing-and-headers.h2.py | 12 ++ .../resources/html-with-early-hints.h2.py | 21 +++ .../resources/invalid-headers-in-early-hints.h2.py | 20 +++ .../resources/modulepreload-in-early-hints.h2.py | 29 ++++ .../resources/modulepreload-in-early-hints.html | 29 ++++ .../resources/multiple-early-hints-responses.h2.py | 39 +++++ .../resources/multiple-early-hints-responses.html | 20 +++ .../resources/pdf-with-early-hints.h2.py | 26 +++ .../resources/png-with-early-hints.h2.py | 26 +++ .../resources/preconnect-in-early-hints.h2.py | 26 +++ .../resources/preconnect-in-early-hints.html | 22 +++ .../early-hints/resources/preload-as-test.h2.py | 29 ++++ .../early-hints/resources/preload-as-test.html | 18 ++ .../early-hints/resources/preload-fetch.html | 18 ++ .../preload-finished-before-final-response.h2.py | 31 ++++ .../preload-finished-before-final-response.html | 15 ++ ...ished-while-receiving-final-response-body.h2.py | 31 ++++ ...nished-while-receiving-final-response-body.html | 15 ++ .../preload-in-flight-when-consumed.h2.py | 24 +++ .../resources/preload-in-flight-when-consumed.html | 19 +++ .../resources/preload-initiator-type.html | 22 +++ .../resources/redirect-between-early-hints.h2.py | 54 ++++++ .../redirect-cross-origin-between-early-hints.html | 22 +++ .../resources/redirect-cross-origin.html | 15 ++ .../redirect-same-origin-between-early-hints.html | 22 +++ .../resources/redirect-same-origin.html | 15 ++ .../resources/redirect-with-early-hints.h2.py | 20 +++ .../resources/referrer-policy-test-loader.h2.py | 39 +++++ .../resources/referrer-policy-test.html | 63 +++++++ .../early-hints/resources/resume-delayed-js.h2.py | 10 ++ .../tests/loading/early-hints/resources/square.png | Bin 0 -> 18299 bytes .../early-hints/resources/square.png.headers | 1 + .../tests/loading/early-hints/resources/utils.py | 45 +++++ .../preloader-css-import-no-quote.tentative.html | 31 ++++ ...reloader-css-import-no-semicolon.tentative.html | 31 ++++ .../preloader-css-import-no-space.tentative.html | 29 ++++ ...reloader-css-import-single-quote.tentative.html | 31 ++++ .../loading/preloader-css-import.tentative.html | 31 ++++ .../loading/preloader-link-media.tentative.html | 33 ++++ .../loading/preloader-template.tentative.html | 35 ++++ .../web-platform/tests/loading/resources/dummy.css | 1 + .../web-platform/tests/loading/resources/dummy.js | 1 + 108 files changed, 2183 insertions(+) create mode 100644 testing/web-platform/tests/loading/early-hints/404-with-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/arbitrary-header-in-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/coep-early-hints-none-final-require-corp.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/coep-early-hints-require-corp-final-none.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-absent.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-allowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-disallowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-absent.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-allowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-disallowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-absent.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-allowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/early-hints-response-time.h2.html create mode 100644 testing/web-platform/tests/loading/early-hints/embed-object.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html create mode 100644 testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html.headers create mode 100644 testing/web-platform/tests/loading/early-hints/iframe-pdf.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/iframe-x-frame-options-deny.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/invalid-headers-in-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/modulepreload-as-worker-cross-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/modulepreload-as-worker.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/modulepreload-cross-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/modulepreload-in-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/multiple-early-hints-responses.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preconnect-in-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-fetch.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-finished-before-final-response.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-finished-while-receiving-final-response-body.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-in-flight-when-consumed.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-initiator-type.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-with-csp-document-disallow.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-with-invalid-as.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-without-as.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/preload-without-csp-document-disallow.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/redirect-cross-origin-between-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/redirect-cross-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/redirect-same-origin-between-early-hints.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/redirect-same-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/referrer-policy-no-referrer.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/referrer-policy-origin-when-cross-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/referrer-policy-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/referrer-policy-same-origin.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/referrer-policy-unsafe-url.h2.window.js create mode 100644 testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/csp-basic-loader.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/csp-basic.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow-loader.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/delayed-js.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/early-hints-delay.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/early-hints-helpers.sub.js create mode 100644 testing/web-platform/tests/loading/early-hints/resources/early-hints-test-loader.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js.headers create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty.js create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty.js.headers create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty.json create mode 100644 testing/web-platform/tests/loading/early-hints/resources/empty.json.headers create mode 100644 testing/web-platform/tests/loading/early-hints/resources/example.pdf create mode 100644 testing/web-platform/tests/loading/early-hints/resources/fetch-and-record-js.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/get-fetch-timing-and-headers.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/html-with-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/invalid-headers-in-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/pdf-with-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/png-with-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-as-test.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-as-test.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-fetch.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/preload-initiator-type.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-between-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin-between-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin-between-early-hints.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/redirect-with-early-hints.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test-loader.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test.html create mode 100644 testing/web-platform/tests/loading/early-hints/resources/resume-delayed-js.h2.py create mode 100644 testing/web-platform/tests/loading/early-hints/resources/square.png create mode 100644 testing/web-platform/tests/loading/early-hints/resources/square.png.headers create mode 100644 testing/web-platform/tests/loading/early-hints/resources/utils.py create mode 100644 testing/web-platform/tests/loading/preloader-css-import-no-quote.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-css-import-no-semicolon.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-css-import-no-space.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-css-import-single-quote.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-css-import.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-link-media.tentative.html create mode 100644 testing/web-platform/tests/loading/preloader-template.tentative.html create mode 100644 testing/web-platform/tests/loading/resources/dummy.css create mode 100644 testing/web-platform/tests/loading/resources/dummy.js (limited to 'testing/web-platform/tests/loading') diff --git a/testing/web-platform/tests/loading/early-hints/404-with-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/404-with-early-hints.h2.window.js new file mode 100644 index 0000000000..f28208a30a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/404-with-early-hints.h2.window.js @@ -0,0 +1,10 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("resource-url", + SAME_ORIGIN_RESOURCES_URL + "/square.png?" + token()); + const test_url = "resources/404-with-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/arbitrary-header-in-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/arbitrary-header-in-early-hints.h2.window.js new file mode 100644 index 0000000000..f0e848ec10 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/arbitrary-header-in-early-hints.h2.window.js @@ -0,0 +1,4 @@ +test(() => { + const test_url = "resources/arbitrary-header-in-early-hints.h2.py"; + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/coep-early-hints-none-final-require-corp.h2.window.js b/testing/web-platform/tests/loading/early-hints/coep-early-hints-none-final-require-corp.h2.window.js new file mode 100644 index 0000000000..ab135b5493 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/coep-early-hints-none-final-require-corp.h2.window.js @@ -0,0 +1,9 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "unsafe-none"; + const final_policy = "require-corp"; + navigateToCrossOriginEmbedderPolicyMismatchTest(early_hints_policy, + final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/coep-early-hints-require-corp-final-none.h2.window.js b/testing/web-platform/tests/loading/early-hints/coep-early-hints-require-corp-final-none.h2.window.js new file mode 100644 index 0000000000..68e20ba42f --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/coep-early-hints-require-corp-final-none.h2.window.js @@ -0,0 +1,9 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "require-corp"; + const final_policy = "unsafe-none"; + navigateToCrossOriginEmbedderPolicyMismatchTest(early_hints_policy, + final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-absent.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-absent.h2.window.js new file mode 100644 index 0000000000..f61e268c8a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-absent.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "absent"; + const final_policy = "absent"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-allowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-allowed.h2.window.js new file mode 100644 index 0000000000..0e1762a28c --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-allowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "absent"; + const final_policy = "allowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-disallowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-disallowed.h2.window.js new file mode 100644 index 0000000000..3fcd89c4cc --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-absent-final-disallowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "absent"; + const final_policy = "disallowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-absent.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-absent.h2.window.js new file mode 100644 index 0000000000..15128ce5d9 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-absent.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "allowed"; + const final_policy = "absent"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-allowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-allowed.h2.window.js new file mode 100644 index 0000000000..ee51e78bf1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-allowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "allowed"; + const final_policy = "allowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-disallowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-disallowed.h2.window.js new file mode 100644 index 0000000000..67b39333ad --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-allowed-final-disallowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "allowed"; + const final_policy = "disallowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-absent.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-absent.h2.window.js new file mode 100644 index 0000000000..80b563dd88 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-absent.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "disallowed"; + const final_policy = "absent"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-allowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-allowed.h2.window.js new file mode 100644 index 0000000000..cfac9b0b98 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-allowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "disallowed"; + const final_policy = "allowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js new file mode 100644 index 0000000000..c8a7ca346f --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js @@ -0,0 +1,8 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "disallowed"; + const final_policy = "disallowed"; + navigateToContentSecurityPolicyBasicTest(early_hints_policy, final_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/early-hints-response-time.h2.html b/testing/web-platform/tests/loading/early-hints/early-hints-response-time.h2.html new file mode 100644 index 0000000000..ac70b3d332 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/early-hints-response-time.h2.html @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/embed-object.h2.window.js b/testing/web-platform/tests/loading/early-hints/embed-object.h2.window.js new file mode 100644 index 0000000000..82365fafdd --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/embed-object.h2.window.js @@ -0,0 +1,44 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +promise_test(async (t) => { + const resource_url = SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token(); + const promise = new Promise((resolve) => { + const params = new URLSearchParams(); + params.set("resource-url", resource_url); + params.set("token", token()); + const embed_url = SAME_ORIGIN_RESOURCES_URL + "/png-with-early-hints.h2.py?" + params.toString(); + + const el = document.createElement("embed"); + el.src = embed_url; + el.onload = resolve; + document.body.appendChild(el); + }); + await promise; + + await fetchScript(resource_url); + const entries = performance.getEntriesByName(resource_url); + assert_equals(entries.length, 1); + assert_not_equals(entries[0].transferSize, 0); +}, "Early hints for an embed element should be ignored."); + +promise_test(async (t) => { + const resource_url = SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token(); + const promise = new Promise((resolve) => { + const params = new URLSearchParams(); + params.set("resource-url", resource_url); + params.set("token", token()); + const object_url = SAME_ORIGIN_RESOURCES_URL + "/png-with-early-hints.h2.py?" + params.toString(); + + const el = document.createElement("object"); + el.data = object_url; + el.onload = resolve; + document.body.appendChild(el); + }); + await promise; + + await fetchScript(resource_url); + const entries = performance.getEntriesByName(resource_url); + assert_equals(entries.length, 1); + assert_not_equals(entries[0].transferSize, 0); +}, "Early hints for an object element should be ignored."); diff --git a/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html b/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html new file mode 100644 index 0000000000..d2efc0fefe --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html.headers b/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html.headers new file mode 100644 index 0000000000..6604450991 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/iframe-coep-disallow.h2.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/loading/early-hints/iframe-pdf.h2.window.js b/testing/web-platform/tests/loading/early-hints/iframe-pdf.h2.window.js new file mode 100644 index 0000000000..11c1443c34 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/iframe-pdf.h2.window.js @@ -0,0 +1,31 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +promise_test(async (t) => { + if (!navigator.pdfViewerEnabled) { + return; + } + + const iframe = document.createElement("iframe"); + const resource_url = SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token(); + const promise = new Promise((resolve) => { + const params = new URLSearchParams(); + params.set("resource-url", resource_url); + params.set("token", token()); + const iframe_url = SAME_ORIGIN_RESOURCES_URL + "/pdf-with-early-hints.h2.py?" + params.toString(); + + iframe.src = iframe_url; + iframe.onload = resolve; + document.body.appendChild(iframe); + }); + await promise; + + // `iframe` should not preload the hinted resource. + const iframe_entries = iframe.contentWindow.performance.getEntriesByName(resource_url); + assert_equals(iframe_entries.length, 0); + + await fetchScript(resource_url); + const entries = performance.getEntriesByName(resource_url); + assert_equals(entries.length, 1); + assert_not_equals(entries[0].transferSize, 0); +}, "Early hints for an iframe of which content is pdf should be ignored."); diff --git a/testing/web-platform/tests/loading/early-hints/iframe-x-frame-options-deny.h2.window.js b/testing/web-platform/tests/loading/early-hints/iframe-x-frame-options-deny.h2.window.js new file mode 100644 index 0000000000..b3a114f7c6 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/iframe-x-frame-options-deny.h2.window.js @@ -0,0 +1,27 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +promise_test(async (t) => { + const iframe = document.createElement("iframe"); + + const resource_url = SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token(); + const params = new URLSearchParams(); + params.set("resource-url", resource_url); + params.set("token", token()); + params.set("x-frame-options", "DENY"); + const iframe_url = SAME_ORIGIN_RESOURCES_URL + "/html-with-early-hints.h2.py?" + params.toString(); + + iframe.src = iframe_url; + document.body.appendChild(iframe); + // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a + // timeout is used here. Long term all network error handling should be similar and have a + // reliable event. + assert_equals(iframe.contentDocument.body.localName, "body"); + await t.step_wait(() => iframe.contentDocument === null); + + // Fetch the hinted resource and make sure it's not preloaded. + await fetchScript(resource_url); + const entries = performance.getEntriesByName(resource_url); + assert_equals(entries.length, 1); + assert_not_equals(entries[0].transferSize, 0); +}, "Early hints for an iframe that violates X-Frame-Options should be ignored."); diff --git a/testing/web-platform/tests/loading/early-hints/invalid-headers-in-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/invalid-headers-in-early-hints.h2.window.js new file mode 100644 index 0000000000..55181877df --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/invalid-headers-in-early-hints.h2.window.js @@ -0,0 +1,22 @@ +async function testInvalidHeader(t, header_value) { + const params = new URLSearchParams(); + params.set("header-value", header_value); + const test_url = "resources/invalid-headers-in-early-hints.h2.py?" + params.toString(); + const opened_window = window.open(test_url, "invalid-header-in-early-hints"); + + // Use step_timeout() because neither "load" event nor postMessage() would + // work. Opening the test page should result in a network protocol error and + // accessing the document of the opened window should throw a SecurityError. + await new Promise(resolve => t.step_timeout(resolve, 1000)); + assert_throws_dom("SecurityError", () => { + opened_window.document; + }, "window.open() should not load the test page successfully."); +} + +promise_test(async (t) => { + await testInvalidHeader(t, "foo\r\nbar"); +}, "Early Hints contains invalid header: newline byte"); + +promise_test(async (t) => { + await testInvalidHeader(t, "foo\x00bar"); +}, "Early Hints contains invalid header: nul byte"); diff --git a/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker-cross-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker-cross-origin.h2.window.js new file mode 100644 index 0000000000..3756d7f7fa --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker-cross-origin.h2.window.js @@ -0,0 +1,15 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +// see modulepreload-in-early-hints.h2.window.js for params explanation +test(() => { + const params = new URLSearchParams(); + params.set("description", + 'Modulepreload should not load with as="worker" from cross-origin url'); + params.set("resource-url", + CROSS_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("as", "worker"); + params.set("should-preload", false); + const test_url = "resources/modulepreload-in-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker.h2.window.js b/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker.h2.window.js new file mode 100644 index 0000000000..2fd36dfbf3 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/modulepreload-as-worker.h2.window.js @@ -0,0 +1,15 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +// see modulepreload-in-early-hints.h2.window.js for params explanation +test(() => { + const params = new URLSearchParams(); + params.set("description", + 'Modulepreload should load with as="worker" from same-origin url'); + params.set("resource-url", + SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("as", "worker"); + params.set("should-preload", true); + const test_url = "resources/modulepreload-in-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/modulepreload-cross-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/modulepreload-cross-origin.h2.window.js new file mode 100644 index 0000000000..3499b4d60d --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/modulepreload-cross-origin.h2.window.js @@ -0,0 +1,13 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +// see modulepreload-in-early-hints.h2.window.js for params explanation +test(() => { + const params = new URLSearchParams(); + params.set("description", "Modulepreload works in early hints from cross-origin url"); + params.set("resource-url", + CROSS_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("should-preload", true); + const test_url = "resources/modulepreload-in-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/modulepreload-in-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/modulepreload-in-early-hints.h2.window.js new file mode 100644 index 0000000000..bd592b0396 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/modulepreload-in-early-hints.h2.window.js @@ -0,0 +1,20 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +// params are sent to a Python handler[1] that returns a 103 Early Hints +// response based the values of "resource-url" and "as", and then that response +// is validated by a window test[2] according to the value of "should-preload" +// +// see: https://web-platform-tests.org/writing-tests/h2tests.html +// +// [1]: resources/modulepreload-in-early-hints.h2.py +// [2]: resources/modulepreload-in-early-hints.h2.html +test(() => { + const params = new URLSearchParams(); + params.set("description", "Modulepreload works in early hints"); + params.set("resource-url", + SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("should-preload", true); + const test_url = "resources/modulepreload-in-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/multiple-early-hints-responses.h2.window.js b/testing/web-platform/tests/loading/early-hints/multiple-early-hints-responses.h2.window.js new file mode 100644 index 0000000000..2aba051ead --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/multiple-early-hints-responses.h2.window.js @@ -0,0 +1,11 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("first-preload", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("second-preload", CROSS_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("second-preload-origin", CROSS_ORIGIN); + const test_url = "resources/multiple-early-hints-responses.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/preconnect-in-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/preconnect-in-early-hints.h2.window.js new file mode 100644 index 0000000000..821d0e40a8 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preconnect-in-early-hints.h2.window.js @@ -0,0 +1,12 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const resource_origin = CROSS_ORIGIN; + const resource_url = CROSS_ORIGIN + RESOURCES_PATH + "/empty.js?" + token(); + const params = new URLSearchParams(); + params.set("resource-origin", resource_origin); + params.set("resource-url", resource_url); + const test_url = "resources/preconnect-in-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/preload-fetch.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-fetch.h2.window.js new file mode 100644 index 0000000000..121913ed31 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-fetch.h2.window.js @@ -0,0 +1,10 @@ +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const preloads = [{ + "url": "empty.json?" + Date.now(), + "as_attr": "fetch", + "crossorigin_attr": "", + }]; + navigateToTestWithEarlyHints("resources/preload-fetch.html", preloads); +}); diff --git a/testing/web-platform/tests/loading/early-hints/preload-finished-before-final-response.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-finished-before-final-response.h2.window.js new file mode 100644 index 0000000000..c63239be1f --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-finished-before-final-response.h2.window.js @@ -0,0 +1,11 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + const id = token(); + params.set("resource-url", SAME_ORIGIN_RESOURCES_URL + "/fetch-and-record-js.h2.py?id=" + id); + params.set("resource-id", id); + const test_url = "resources/preload-finished-before-final-response.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/preload-finished-while-receiving-final-response-body.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-finished-while-receiving-final-response-body.h2.window.js new file mode 100644 index 0000000000..bb03902bd1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-finished-while-receiving-final-response-body.h2.window.js @@ -0,0 +1,11 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + const id = token(); + params.set("resource-url", SAME_ORIGIN_RESOURCES_URL + "/fetch-and-record-js.h2.py?id=" + id); + params.set("resource-id", id); + const test_url = "resources/preload-finished-while-receiving-final-response-body.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/preload-in-flight-when-consumed.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-in-flight-when-consumed.h2.window.js new file mode 100644 index 0000000000..beaa45e2dd --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-in-flight-when-consumed.h2.window.js @@ -0,0 +1,11 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + const id = token(); + params.set("resource-url", SAME_ORIGIN_RESOURCES_URL + "/delayed-js.h2.py?id=" + id); + params.set("resource-id", id); + const test_url = "resources/preload-in-flight-when-consumed.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/preload-initiator-type.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-initiator-type.h2.window.js new file mode 100644 index 0000000000..959aacef49 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-initiator-type.h2.window.js @@ -0,0 +1,9 @@ +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const preloads = [{ + "url": "empty.js?" + Date.now(), + "as_attr": "script", + }]; + navigateToTestWithEarlyHints("resources/preload-initiator-type.html", preloads); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/preload-with-csp-document-disallow.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-with-csp-document-disallow.h2.window.js new file mode 100644 index 0000000000..87759b28a0 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-with-csp-document-disallow.h2.window.js @@ -0,0 +1,7 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "allowed"; + navigateToContentSecurityPolicyDocumentDisallowTest(early_hints_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/preload-with-invalid-as.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-with-invalid-as.h2.window.js new file mode 100644 index 0000000000..bebd97887c --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-with-invalid-as.h2.window.js @@ -0,0 +1,14 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("description", + "An early hints preload with an invalid `as` attribute should be ignored."); + params.set("resource-url", + SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("as", "invalid"); + params.set("should-preload", false); + const test_url = "resources/preload-as-test.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/preload-without-as.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-without-as.h2.window.js new file mode 100644 index 0000000000..9ac1621050 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-without-as.h2.window.js @@ -0,0 +1,13 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("description", + "An early hints preload without `as` attribute should be ignored."); + params.set("resource-url", + SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("should-preload", false); + const test_url = "resources/preload-as-test.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/preload-without-csp-document-disallow.h2.window.js b/testing/web-platform/tests/loading/early-hints/preload-without-csp-document-disallow.h2.window.js new file mode 100644 index 0000000000..3de55d04c3 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/preload-without-csp-document-disallow.h2.window.js @@ -0,0 +1,7 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const early_hints_policy = "absent"; + navigateToContentSecurityPolicyDocumentDisallowTest(early_hints_policy); +}); diff --git a/testing/web-platform/tests/loading/early-hints/redirect-cross-origin-between-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/redirect-cross-origin-between-early-hints.h2.window.js new file mode 100644 index 0000000000..2ca92cf82c --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/redirect-cross-origin-between-early-hints.h2.window.js @@ -0,0 +1,14 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("preload-before-redirect", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("preload-after-redirect", CROSS_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("redirect-url", CROSS_ORIGIN_RESOURCES_URL + "/redirect-between-early-hints.h2.py"); + params.set("final-test-page", "redirect-cross-origin-between-early-hints.html"); + + params.set("test-step", "redirect"); + const test_url = "resources/redirect-between-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/redirect-cross-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/redirect-cross-origin.h2.window.js new file mode 100644 index 0000000000..548759b19c --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/redirect-cross-origin.h2.window.js @@ -0,0 +1,10 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("preload-url", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("redirect-url", CROSS_ORIGIN_RESOURCES_URL + "/redirect-cross-origin.html"); + const test_url = "resources/redirect-with-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); diff --git a/testing/web-platform/tests/loading/early-hints/redirect-same-origin-between-early-hints.h2.window.js b/testing/web-platform/tests/loading/early-hints/redirect-same-origin-between-early-hints.h2.window.js new file mode 100644 index 0000000000..276303608e --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/redirect-same-origin-between-early-hints.h2.window.js @@ -0,0 +1,14 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("preload-before-redirect", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("preload-after-redirect", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("redirect-url", SAME_ORIGIN_RESOURCES_URL + "/redirect-between-early-hints.h2.py"); + params.set("final-test-page", "redirect-same-origin-between-early-hints.html"); + + params.set("test-step", "redirect"); + const test_url = "resources/redirect-between-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/redirect-same-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/redirect-same-origin.h2.window.js new file mode 100644 index 0000000000..88d64f399a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/redirect-same-origin.h2.window.js @@ -0,0 +1,10 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => { + const params = new URLSearchParams(); + params.set("preload-url", SAME_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("redirect-url", SAME_ORIGIN_RESOURCES_URL + "/redirect-same-origin.html"); + const test_url = "resources/redirect-with-early-hints.h2.py?" + params.toString(); + window.location.replace(new URL(test_url, window.location)); +}); \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/referrer-policy-no-referrer.h2.window.js b/testing/web-platform/tests/loading/early-hints/referrer-policy-no-referrer.h2.window.js new file mode 100644 index 0000000000..10f2c2c4bc --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/referrer-policy-no-referrer.h2.window.js @@ -0,0 +1,4 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => testReferrerPolicy("no-referrer")); diff --git a/testing/web-platform/tests/loading/early-hints/referrer-policy-origin-when-cross-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/referrer-policy-origin-when-cross-origin.h2.window.js new file mode 100644 index 0000000000..250f350877 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/referrer-policy-origin-when-cross-origin.h2.window.js @@ -0,0 +1,4 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => testReferrerPolicy("origin-when-cross-origin")); diff --git a/testing/web-platform/tests/loading/early-hints/referrer-policy-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/referrer-policy-origin.h2.window.js new file mode 100644 index 0000000000..3fbe9dff76 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/referrer-policy-origin.h2.window.js @@ -0,0 +1,4 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => testReferrerPolicy("origin")); diff --git a/testing/web-platform/tests/loading/early-hints/referrer-policy-same-origin.h2.window.js b/testing/web-platform/tests/loading/early-hints/referrer-policy-same-origin.h2.window.js new file mode 100644 index 0000000000..4d24e1bf98 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/referrer-policy-same-origin.h2.window.js @@ -0,0 +1,4 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => testReferrerPolicy("same-origin")); diff --git a/testing/web-platform/tests/loading/early-hints/referrer-policy-unsafe-url.h2.window.js b/testing/web-platform/tests/loading/early-hints/referrer-policy-unsafe-url.h2.window.js new file mode 100644 index 0000000000..a0c304cb10 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/referrer-policy-unsafe-url.h2.window.js @@ -0,0 +1,4 @@ +// META: script=/common/utils.js +// META: script=resources/early-hints-helpers.sub.js + +test(() => testReferrerPolicy("unsafe-url")); diff --git a/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.h2.py new file mode 100644 index 0000000000..bb75bc0cbd --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.h2.py @@ -0,0 +1,24 @@ +import os + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=image".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 404 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "404-with-early-hints.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.html new file mode 100644 index 0000000000..2d351b08b8 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/404-with-early-hints.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.h2.py new file mode 100644 index 0000000000..bb118c3200 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.h2.py @@ -0,0 +1,24 @@ +import os + + +def handle_headers(frame, request, response): + # Send an early hints response with an unsupported header. + # User agents should ignore it. + early_hints = [ + (b":status", b"103"), + (b"x-arbitrary-header", b"foobar"), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "arbitrary-header-in-early-hints.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.html new file mode 100644 index 0000000000..cc939f5ea6 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/arbitrary-header-in-early-hints.html @@ -0,0 +1,11 @@ + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.h2.py b/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.h2.py new file mode 100644 index 0000000000..240a804f57 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.h2.py @@ -0,0 +1,30 @@ +import os + + +def handle_headers(frame, request, response): + # Send a 103 response. + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + coep_value = request.GET.first(b"early-hints-policy").decode() + early_hints = [ + (b":status", b"103"), + (b"cross-origin-embedder-policy", coep_value), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Send the final response header. + coep_value = request.GET.first(b"final-policy").decode() + response.status = 200 + response.headers["content-type"] = "text/html" + response.headers["cross-origin-embedder-policy"] = coep_value + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "coep-mismatch.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.html b/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.html new file mode 100644 index 0000000000..1811bf5506 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/coep-mismatch.html @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/csp-basic-loader.h2.py b/testing/web-platform/tests/loading/early-hints/resources/csp-basic-loader.h2.py new file mode 100644 index 0000000000..080901efe6 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/csp-basic-loader.h2.py @@ -0,0 +1,47 @@ +import os + + +def _calculate_csp_value(policy, resource_origin): + if policy == "absent": + return None + elif policy == "allowed": + return "script-src 'self' 'unsafe-inline' {}".format(resource_origin) + elif policy == "disallowed": + return "script-src 'self' 'unsafe-inline'" + else: + return None + + +def handle_headers(frame, request, response): + resource_origin = request.GET.first(b"resource-origin").decode() + + # Send a 103 response. + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + early_hints_csp = _calculate_csp_value( + request.GET.first(b"early-hints-policy").decode(), resource_origin) + if early_hints_csp: + early_hints.append((b"content-security-policy", early_hints_csp)) + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Send the final response header. + response.status = 200 + response.headers["content-type"] = "text/html" + final_csp = _calculate_csp_value( + request.GET.first(b"final-policy").decode(), resource_origin) + if final_csp: + response.headers["content-security-policy"] = final_csp + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "csp-basic.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/csp-basic.html b/testing/web-platform/tests/loading/early-hints/resources/csp-basic.html new file mode 100644 index 0000000000..0086711fb7 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/csp-basic.html @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow-loader.h2.py b/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow-loader.h2.py new file mode 100644 index 0000000000..bffa90c753 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow-loader.h2.py @@ -0,0 +1,39 @@ +import os + + +def handle_headers(frame, request, response): + # Send a 103 response. + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + + early_hints_policy = request.GET.first(b"early-hints-policy").decode() + # In this test handler "allowed" or "absent" are only valid policies because + # csp-document-disallow.html always sets CSP to disallow the preload. + # "disallowed" makes no observable changes in the test. Note that + # csp-basic.html covers disallowing preloads in Early Hints. + assert early_hints_policy == "allowed" or early_hints_policy == "absent" + + if early_hints_policy == "allowed": + resource_origin = request.GET.first(b"resource-origin").decode() + csp_value = "script-src 'self' 'unsafe-inline' {}".format(resource_origin) + early_hints.append((b"content-security-policy", csp_value)) + + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Send the final response header. + response.status = 200 + response.headers["content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "csp-document-disallow.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow.html b/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow.html new file mode 100644 index 0000000000..53b6ee232d --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/csp-document-disallow.html @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/delayed-js.h2.py b/testing/web-platform/tests/loading/early-hints/resources/delayed-js.h2.py new file mode 100644 index 0000000000..93865b930d --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/delayed-js.h2.py @@ -0,0 +1,16 @@ +import importlib + +utils = importlib.import_module("loading.early-hints.resources.utils") + + +def main(request, response): + id = request.GET.first(b"id") + # Wait until the id is set via resume-delayed-js.h2.py. + utils.wait_for_preload_to_finish(request, id) + + headers = [ + ("Content-Type", "text/javascript"), + ("Cache-Control", "max-age=600"), + ] + body = "/*empty script*/" + return (200, "OK"), headers, body diff --git a/testing/web-platform/tests/loading/early-hints/resources/early-hints-delay.h2.py b/testing/web-platform/tests/loading/early-hints/resources/early-hints-delay.h2.py new file mode 100644 index 0000000000..ba8796bc11 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/early-hints-delay.h2.py @@ -0,0 +1,20 @@ +import time + +def handle_headers(frame, request, response): + early_hints = [ + (b":status", b"103"), + (b"link", b"; rel=preload; as=script"), + ] + + time.sleep(int(request.GET.first(b"delay1")) / 1000) + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + time.sleep(int(request.GET.first(b"delay2")) / 1000) + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + response.writer.write_data(item="Hello", last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/early-hints-helpers.sub.js b/testing/web-platform/tests/loading/early-hints/resources/early-hints-helpers.sub.js new file mode 100644 index 0000000000..faf6119cf1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/early-hints-helpers.sub.js @@ -0,0 +1,182 @@ +"use strict"; + +const SAME_ORIGIN = "https://{{host}}:{{ports[h2][0]}}"; +const CROSS_ORIGIN = "https://{{hosts[alt][www]}}:{{ports[h2][0]}}"; + +const RESOURCES_PATH = "/loading/early-hints/resources"; +const SAME_ORIGIN_RESOURCES_URL = SAME_ORIGIN + RESOURCES_PATH; +const CROSS_ORIGIN_RESOURCES_URL = CROSS_ORIGIN + RESOURCES_PATH; + +/** + * Navigate to a test page with an Early Hints response. + * + * @typedef {Object} Preload + * @property {string} url - A URL to preload. Note: This is relative to the + * `test_url` parameter of `navigateToTestWithEarlyHints()`. + * @property {string} as_attr - `as` attribute of this preload. + * @property {string} [crossorigin_attr] - `crossorigin` attribute of this + * preload. + * + * @param {string} test_url - URL of a test after the Early Hints response. + * @param {Array} preloads - Preloads included in the Early Hints response. + */ +function navigateToTestWithEarlyHints(test_url, preloads) { + const params = new URLSearchParams(); + params.set("test_url", test_url); + for (const preload of preloads) { + params.append("preloads", JSON.stringify(preload)); + } + const url = "resources/early-hints-test-loader.h2.py?" + params.toString(); + window.location.replace(new URL(url, window.location)); +} + +/** + * Parses the query string of the current window location and returns preloads + * in the Early Hints response sent via `navigateToTestWithEarlyHints()`. + * + * @returns {Array} + */ +function getPreloadsFromSearchParams() { + const params = new URLSearchParams(window.location.search); + const encoded_preloads = params.getAll("preloads"); + const preloads = []; + for (const encoded of encoded_preloads) { + preloads.push(JSON.parse(encoded)); + } + return preloads; +} + +/** + * Fetches a script or an image. + * + * @param {string} element - "script" or "img". + * @param {string} url - URL of the resource. + */ +async function fetchResource(element, url) { + return new Promise((resolve, reject) => { + const el = document.createElement(element); + el.src = url; + el.onload = resolve; + el.onerror = _ => reject(new Error("Failed to fetch resource: " + url)); + document.body.appendChild(el); + }); +} + +/** + * Fetches a script. + * + * @param {string} url + */ +async function fetchScript(url) { + return fetchResource("script", url); +} + +/** + * Fetches an image. + * + * @param {string} url + */ + async function fetchImage(url) { + return fetchResource("img", url); +} + +/** + * Returns true when the resource is preloaded via Early Hints. + * + * @param {string} url + * @returns {boolean} + */ +function isPreloadedByEarlyHints(url) { + const entries = performance.getEntriesByName(url); + if (entries.length === 0) { + return false; + } + assert_equals(entries.length, 1); + return entries[0].initiatorType === "early-hints"; +} + +/** + * Navigate to the referrer policy test page. + * + * @param {string} referrer_policy - A value of Referrer-Policy to test. + */ +function testReferrerPolicy(referrer_policy) { + const params = new URLSearchParams(); + params.set("referrer-policy", referrer_policy); + const same_origin_preload_url = SAME_ORIGIN_RESOURCES_URL + "/fetch-and-record-js.h2.py?id=" + token(); + params.set("same-origin-preload-url", same_origin_preload_url); + const cross_origin_preload_url = CROSS_ORIGIN_RESOURCES_URL + "/fetch-and-record-js.h2.py?id=" + token(); + params.set("cross-origin-preload-url", cross_origin_preload_url); + + const path = "resources/referrer-policy-test-loader.h2.py?" + params.toString(); + const url = new URL(path, window.location); + window.location.replace(url); +} + +/** + * Navigate to the content security policy basic test. The test page sends an + * Early Hints response with a cross origin resource preload. CSP headers are + * configured based on the given policies. A policy should be one of the + * followings: + * "absent" - Do not send Content-Security-Policy header + * "allowed" - Set Content-Security-Policy to allow the cross origin preload + * "disallowed" - Set Content-Security-Policy to disallow the cross origin preload + * + * @param {string} early_hints_policy - The policy for the Early Hints response + * @param {string} final_policy - The policy for the final response + */ +function navigateToContentSecurityPolicyBasicTest( + early_hints_policy, final_policy) { + const params = new URLSearchParams(); + params.set("resource-origin", CROSS_ORIGIN); + params.set("resource-url", + CROSS_ORIGIN_RESOURCES_URL + "/empty.js?" + token()); + params.set("early-hints-policy", early_hints_policy); + params.set("final-policy", final_policy); + + const url = "resources/csp-basic-loader.h2.py?" + params.toString(); + window.location.replace(new URL(url, window.location)); +} + +/** + * Navigate to a test page which sends an Early Hints containing a cross origin + * preload link with/without Content-Security-Policy header. The CSP header is + * configured based on the given policy. The test page disallows the preload + * while the preload is in-flight. The policy should be one of the followings: + * "absent" - Do not send Content-Security-Policy header + * "allowed" - Set Content-Security-Policy to allow the cross origin preload + * + * @param {string} early_hints_policy + */ +function navigateToContentSecurityPolicyDocumentDisallowTest(early_hints_policy) { + const resource_id = token(); + const params = new URLSearchParams(); + params.set("resource-origin", CROSS_ORIGIN); + params.set("resource-url", + CROSS_ORIGIN_RESOURCES_URL + "/delayed-js.h2.py?id=" + resource_id); + params.set("resume-url", + CROSS_ORIGIN_RESOURCES_URL + "/resume-delayed-js.h2.py?id=" + resource_id); + params.set("early-hints-policy", early_hints_policy); + + const url = "resources/csp-document-disallow-loader.h2.py?" + params.toString(); + window.location.replace(new URL(url, window.location)); +} + +/** + * Navigate to a test page which sends different Cross-Origin-Embedder-Policy + * values in an Early Hints response and the final response. + * + * @param {string} early_hints_policy - The policy for the Early Hints response + * @param {string} final_policy - The policy for the final response + */ +function navigateToCrossOriginEmbedderPolicyMismatchTest( + early_hints_policy, final_policy) { + const params = new URLSearchParams(); + params.set("resource-url", + CROSS_ORIGIN_RESOURCES_URL + "/empty-corp-absent.js?" + token()); + params.set("early-hints-policy", early_hints_policy); + params.set("final-policy", final_policy); + + const url = "resources/coep-mismatch.h2.py?" + params.toString(); + window.location.replace(new URL(url, window.location)); +} diff --git a/testing/web-platform/tests/loading/early-hints/resources/early-hints-test-loader.h2.py b/testing/web-platform/tests/loading/early-hints/resources/early-hints-test-loader.h2.py new file mode 100644 index 0000000000..bb987209c5 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/early-hints-test-loader.h2.py @@ -0,0 +1,51 @@ +# An HTTP/2 handler for testing Early Hints. Used as an entry point of Early +# Hints related tests to inject Early Hints response. See comments in +# `early-hints-helpers.sub.js`. + +import json +import os +import time + + +def _remove_relative_resources_prefix(path): + if path.startswith("resources/"): + return path[len("resources/"):] + return path + + +def handle_headers(frame, request, response): + preload_headers = [] + for encoded_preload in request.GET.get_list(b"preloads"): + preload = json.loads(encoded_preload.decode("utf-8")) + header = "<{}>; rel=preload; as={}".format(preload["url"], preload["as_attr"]) + if "crossorigin_attr" in preload: + crossorigin = preload["crossorigin_attr"] + if crossorigin: + header += "; crossorigin={}".format(crossorigin) + else: + header += "; crossorigin" + preload_headers.append(header.encode()) + + # Send a 103 response. + early_hints = [(b":status", b"103")] + for header in preload_headers: + early_hints.append((b"link", header)) + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Simulate the response generation is taking time. + time.sleep(0.2) + response.status = 200 + response.headers[b"content-type"] = "text/html" + for header in preload_headers: + response.headers.append(b"link", header) + response.write_status_headers() + + +def main(request, response): + test_path = _remove_relative_resources_prefix( + request.GET[b"test_url"].decode("utf-8")) + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, test_path) + test_content = open(file_path, "r").read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js b/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js new file mode 100644 index 0000000000..b7965b64a1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js @@ -0,0 +1 @@ +// Empty script diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js.headers b/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js.headers new file mode 100644 index 0000000000..175cdf8046 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty-corp-absent.js.headers @@ -0,0 +1 @@ +cache-control: max-age=600 diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty.js b/testing/web-platform/tests/loading/early-hints/resources/empty.js new file mode 100644 index 0000000000..3e211cc8d2 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty.js @@ -0,0 +1 @@ +// Empty script \ No newline at end of file diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty.js.headers b/testing/web-platform/tests/loading/early-hints/resources/empty.js.headers new file mode 100644 index 0000000000..1738466bcb --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty.js.headers @@ -0,0 +1,4 @@ +cache-control: max-age=600 +access-control-allow-origin: * +timing-allow-origin: * +cross-origin-resource-policy: cross-origin diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty.json b/testing/web-platform/tests/loading/early-hints/resources/empty.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty.json @@ -0,0 +1 @@ +{} diff --git a/testing/web-platform/tests/loading/early-hints/resources/empty.json.headers b/testing/web-platform/tests/loading/early-hints/resources/empty.json.headers new file mode 100644 index 0000000000..1738466bcb --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/empty.json.headers @@ -0,0 +1,4 @@ +cache-control: max-age=600 +access-control-allow-origin: * +timing-allow-origin: * +cross-origin-resource-policy: cross-origin diff --git a/testing/web-platform/tests/loading/early-hints/resources/example.pdf b/testing/web-platform/tests/loading/early-hints/resources/example.pdf new file mode 100644 index 0000000000..7bad251ba7 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/example.pdf @@ -0,0 +1,50 @@ +%PDF-1.7 +% ò¤ô +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 300 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R +>> +endobj +4 0 obj << +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000230 00000 n +trailer<< /Root 1 0 R /Size 5 >> +startxref +456 +%%EOF diff --git a/testing/web-platform/tests/loading/early-hints/resources/fetch-and-record-js.h2.py b/testing/web-platform/tests/loading/early-hints/resources/fetch-and-record-js.h2.py new file mode 100644 index 0000000000..169f70c045 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/fetch-and-record-js.h2.py @@ -0,0 +1,16 @@ +import importlib +import time + +utils = importlib.import_module("loading.early-hints.resources.utils") + + +def main(request, response): + utils.store_request_timing_and_headers(request) + headers = [ + ("Content-Type", "text/javascript"), + ("Cache-Control", "max-age=600"), + ] + body = "/*empty script*/" + # Sleep to simulate loading time. + time.sleep(0.05) + return (200, "OK"), headers, body diff --git a/testing/web-platform/tests/loading/early-hints/resources/get-fetch-timing-and-headers.h2.py b/testing/web-platform/tests/loading/early-hints/resources/get-fetch-timing-and-headers.h2.py new file mode 100644 index 0000000000..59f67be3cf --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/get-fetch-timing-and-headers.h2.py @@ -0,0 +1,12 @@ +import importlib + +utils = importlib.import_module("loading.early-hints.resources.utils") + + +def main(request, response): + headers = [ + ("Content-Type", "application/json"), + ("Access-Control-Allow-Origin", "*"), + ] + body = utils.get_request_timing_and_headers(request) + return (200, "OK"), headers, body diff --git a/testing/web-platform/tests/loading/early-hints/resources/html-with-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/html-with-early-hints.h2.py new file mode 100644 index 0000000000..fc7ed0ffee --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/html-with-early-hints.h2.py @@ -0,0 +1,21 @@ +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + if b"x-frame-options" in request.GET: + x_frame_options = request.GET.first(b"x-frame-options").decode() + response.headers[b"x-frame-options"] = x_frame_options + response.write_status_headers() + + +def main(request, response): + content = "" + response.writer.write_data(item=content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/invalid-headers-in-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/invalid-headers-in-early-hints.h2.py new file mode 100644 index 0000000000..438d1c79ac --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/invalid-headers-in-early-hints.h2.py @@ -0,0 +1,20 @@ +import os + + +def handle_headers(frame, request, response): + header_value = request.GET.first(b"header-value") + early_hints = [ + (b":status", b"103"), + (b"invalid-header", header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + test_content = "
This page should not be loaded.
" + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.h2.py new file mode 100644 index 0000000000..cefd02a96a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.h2.py @@ -0,0 +1,29 @@ +import os + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + as_value = request.GET.first(b"as", None) + if as_value: + link_header_value = "<{}>; rel=modulepreload; as={}".format( + resource_url, as_value.decode()) + else: + link_header_value = "<{}>; rel=modulepreload".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "modulepreload-in-early-hints.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.html new file mode 100644 index 0000000000..64a0285504 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/modulepreload-in-early-hints.html @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.h2.py b/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.h2.py new file mode 100644 index 0000000000..3cc221abf2 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.h2.py @@ -0,0 +1,39 @@ +import os + + +def handle_headers(frame, request, response): + # Send two Early Hints responses. + + first_preload = request.GET.first(b"first-preload").decode() + link_header_value = "<{}>; rel=preload; as=script".format(first_preload) + early_hints = [ + (b":status", b"103"), + (b"content-security-policy", "script-src 'self' 'unsafe-inline'"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + second_preload = request.GET.first(b"second-preload").decode() + link_header_value = "<{}>; rel=preload; as=script".format(second_preload) + second_preload_origin = request.GET.first(b"second-preload-origin").decode() + csp_value = "script-src 'self' 'unsafe-inline' {}".format(second_preload_origin) + early_hints = [ + (b":status", b"103"), + (b"content-security-policy", csp_value), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "multiple-early-hints-responses.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.html b/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.html new file mode 100644 index 0000000000..3be2852348 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/multiple-early-hints-responses.html @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/pdf-with-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/pdf-with-early-hints.h2.py new file mode 100644 index 0000000000..0d05f2a3c5 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/pdf-with-early-hints.h2.py @@ -0,0 +1,26 @@ +import os +import time + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Sleep to simulate a slow generation of the final response. + time.sleep(0.1) + response.status = 200 + response.headers[b"content-type"] = "application/pdf" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "example.pdf") + with open(file_path, "rb") as f: + content = f.read() + response.writer.write_data(item=content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/png-with-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/png-with-early-hints.h2.py new file mode 100644 index 0000000000..0785d512c1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/png-with-early-hints.h2.py @@ -0,0 +1,26 @@ +import os +import time + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Sleep to simulate a slow generation of the final response. + time.sleep(0.1) + response.status = 200 + response.headers[b"content-type"] = "image/png" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "square.png") + with open(file_path, "rb") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.h2.py new file mode 100644 index 0000000000..e448fd0af7 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.h2.py @@ -0,0 +1,26 @@ +import os + + +def handle_headers(frame, request, response): + # Send a 103 response. + resource_origin = request.GET.first(b"resource-origin").decode() + link_header_value = "<{}>; rel=preconnect".format(resource_origin) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Send the final response header. + response.status = 200 + response.headers["content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "preconnect-in-early-hints.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.html new file mode 100644 index 0000000000..8ec8fde5e6 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preconnect-in-early-hints.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.h2.py b/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.h2.py new file mode 100644 index 0000000000..682edb56df --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.h2.py @@ -0,0 +1,29 @@ +import os + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + as_value = request.GET.first(b"as", None) + if as_value: + link_header_value = "<{}>; rel=preload; as={}".format( + resource_url, as_value.decode()) + else: + link_header_value = "<{}>; rel=preload".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "preload-as-test.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.html b/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.html new file mode 100644 index 0000000000..daea33160a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-as-test.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-fetch.html b/testing/web-platform/tests/loading/early-hints/resources/preload-fetch.html new file mode 100644 index 0000000000..2e90f76af1 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-fetch.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.h2.py b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.h2.py new file mode 100644 index 0000000000..d0b12408d9 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.h2.py @@ -0,0 +1,31 @@ +import importlib +import os + +utils = importlib.import_module("loading.early-hints.resources.utils") + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Wait for preload to finish before sending the final response headers. + resource_id = request.GET.first(b"resource-id").decode() + utils.wait_for_preload_to_finish(request, resource_id) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "preload-finished-before-final-response.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.html b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.html new file mode 100644 index 0000000000..d965b40420 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-before-final-response.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.h2.py b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.h2.py new file mode 100644 index 0000000000..1ba486002c --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.h2.py @@ -0,0 +1,31 @@ +import importlib +import os + +utils = importlib.import_module("loading.early-hints.resources.utils") + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + # Wait for preload to finish before sending the response body. + resource_id = request.GET.first(b"resource-id").decode() + utils.wait_for_preload_to_finish(request, resource_id) + + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "preload-finished-while-receiving-final-response-body.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.html b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.html new file mode 100644 index 0000000000..5a233612b2 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-finished-while-receiving-final-response-body.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.h2.py b/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.h2.py new file mode 100644 index 0000000000..c3d66160e3 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.h2.py @@ -0,0 +1,24 @@ +import os + + +def handle_headers(frame, request, response): + resource_url = request.GET.first(b"resource-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(resource_url) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + response.status = 200 + response.headers[b"content-type"] = "text/html" + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "preload-in-flight-when-consumed.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.html b/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.html new file mode 100644 index 0000000000..5075d92846 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-in-flight-when-consumed.html @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/preload-initiator-type.html b/testing/web-platform/tests/loading/early-hints/resources/preload-initiator-type.html new file mode 100644 index 0000000000..0fdeb2b903 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/preload-initiator-type.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-between-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/redirect-between-early-hints.h2.py new file mode 100644 index 0000000000..a1b3f15ca4 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-between-early-hints.h2.py @@ -0,0 +1,54 @@ +import os + + +def _send_early_hints(preload, writer): + link_header_value = "<{}>; rel=preload; as=script".format(preload) + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + writer.write_raw_header_frame(headers=early_hints, end_headers=True) + + +def handle_headers(frame, request, response): + step = request.GET.first(b"test-step").decode() + if step == "redirect": + preload = request.GET.first(b"preload-before-redirect").decode() + _send_early_hints(preload, response.writer) + + # Redirect to the final test page with parameters. + params = [] + for key, values in request.GET.items(): + if key == b"test-step": + params.append("test-step=final-response") + else: + params.append("{}={}".format(key.decode(), values[0].decode())) + + redirect_url = request.GET.first(b"redirect-url").decode() + location = "{}?{}".format(redirect_url, "&".join(params)) + + response.status = 302 + response.headers["location"] = location + response.write_status_headers() + elif step == "final-response": + preload = request.GET.first(b"preload-after-redirect").decode() + _send_early_hints(preload, response.writer) + + response.status = 200 + response.headers["content-type"] = "text/html" + response.write_status_headers() + else: + raise Exception("Invalid step: {}".format(step)) + + +def main(request, response): + step = request.GET.first(b"test-step").decode() + if step != "final-response": + return + + final_test_page = request.GET.first(b"final-test-page").decode() + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, final_test_page) + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin-between-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin-between-early-hints.html new file mode 100644 index 0000000000..46560bb2da --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin-between-early-hints.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin.html b/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin.html new file mode 100644 index 0000000000..39b37f8130 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-cross-origin.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin-between-early-hints.html b/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin-between-early-hints.html new file mode 100644 index 0000000000..395f7f1752 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin-between-early-hints.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin.html b/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin.html new file mode 100644 index 0000000000..6a2246a2ac --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-same-origin.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/redirect-with-early-hints.h2.py b/testing/web-platform/tests/loading/early-hints/resources/redirect-with-early-hints.h2.py new file mode 100644 index 0000000000..e501d85a6b --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/redirect-with-early-hints.h2.py @@ -0,0 +1,20 @@ +def handle_headers(frame, request, response): + preload_url = request.GET.first(b"preload-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(preload_url) + + early_hints = [ + (b":status", b"103"), + (b"link", link_header_value), + ] + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + redirect_url = request.GET.first(b"redirect-url").decode() + location = "{}?preload-url={}".format(redirect_url, preload_url) + response.status = 302 + response.headers["location"] = location + response.write_status_headers() + + +def main(request, response): + pass diff --git a/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test-loader.h2.py b/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test-loader.h2.py new file mode 100644 index 0000000000..901d64a01f --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test-loader.h2.py @@ -0,0 +1,39 @@ +import os +import time + + +def handle_headers(frame, request, response): + headers = [] + referrer_policy = request.GET.first(b"referrer-policy") + headers.append((b"referrer-policy", referrer_policy)) + + preload_url = request.GET.first(b"same-origin-preload-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(preload_url) + headers.append((b"link", link_header_value)) + preload_url = request.GET.first(b"cross-origin-preload-url").decode() + link_header_value = "<{}>; rel=preload; as=script".format(preload_url) + headers.append((b"link", link_header_value)) + + # Send a 103 response. + early_hints = [(b":status", b"103")] + for header in headers: + early_hints.append(header) + response.writer.write_raw_header_frame(headers=early_hints, + end_headers=True) + + # Simulate the response generation is taking time. + time.sleep(0.2) + + response.status = 200 + response.headers["content-type"] = "text/html" + for (name, value) in headers: + response.headers[name] = value + response.write_status_headers() + + +def main(request, response): + current_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(current_dir, "referrer-policy-test.html") + with open(file_path, "r") as f: + test_content = f.read() + response.writer.write_data(item=test_content, last=True) diff --git a/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test.html b/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test.html new file mode 100644 index 0000000000..d0389c2e11 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/referrer-policy-test.html @@ -0,0 +1,63 @@ + + + + + + + + diff --git a/testing/web-platform/tests/loading/early-hints/resources/resume-delayed-js.h2.py b/testing/web-platform/tests/loading/early-hints/resources/resume-delayed-js.h2.py new file mode 100644 index 0000000000..132f038ac9 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/resume-delayed-js.h2.py @@ -0,0 +1,10 @@ +def main(request, response): + id = request.GET.first(b"id") + url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + request.server.stash.put(id, True, url_dir) + headers = [ + ("Content-Type", "text/plain"), + ("Access-Control-Allow-Origin", "*"), + ] + body = "OK" + return (200, "OK"), headers, body diff --git a/testing/web-platform/tests/loading/early-hints/resources/square.png b/testing/web-platform/tests/loading/early-hints/resources/square.png new file mode 100644 index 0000000000..01c9666a8d Binary files /dev/null and b/testing/web-platform/tests/loading/early-hints/resources/square.png differ diff --git a/testing/web-platform/tests/loading/early-hints/resources/square.png.headers b/testing/web-platform/tests/loading/early-hints/resources/square.png.headers new file mode 100644 index 0000000000..175cdf8046 --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/square.png.headers @@ -0,0 +1 @@ +cache-control: max-age=600 diff --git a/testing/web-platform/tests/loading/early-hints/resources/utils.py b/testing/web-platform/tests/loading/early-hints/resources/utils.py new file mode 100644 index 0000000000..f24638ab3a --- /dev/null +++ b/testing/web-platform/tests/loading/early-hints/resources/utils.py @@ -0,0 +1,45 @@ +import datetime +import json +import time + + +def _url_dir(request): + return u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + + +def store_request_timing_and_headers(request): + """Store the current timestamp and request's headers in the stash object of + the server. The request must a GET request and must have the "id" parameter. + """ + id = request.GET.first(b"id") + timestamp = datetime.datetime.now().timestamp() + + value = { + "timestamp": timestamp, + "headers": request.raw_headers, + } + + url_dir = _url_dir(request) + request.server.stash.put(id, value, url_dir) + + +def get_request_timing_and_headers(request, id=None): + """Get previously stored timestamp and request headers associated with the + given "id". When "id" is not given the id is retrieved from "request". + """ + if id is None: + id = request.GET.first(b"id") + url_dir = _url_dir(request) + item = request.server.stash.take(id, url_dir) + if not item: + return None + return json.dumps(item) + + +def wait_for_preload_to_finish(request, id): + """Wait until a preload associated with "id" is sent.""" + while True: + if get_request_timing_and_headers(request, id): + break + time.sleep(0.1) + time.sleep(0.1) diff --git a/testing/web-platform/tests/loading/preloader-css-import-no-quote.tentative.html b/testing/web-platform/tests/loading/preloader-css-import-no-quote.tentative.html new file mode 100644 index 0000000000..6b982ea2ce --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-css-import-no-quote.tentative.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-css-import-no-semicolon.tentative.html b/testing/web-platform/tests/loading/preloader-css-import-no-semicolon.tentative.html new file mode 100644 index 0000000000..ab81c82192 --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-css-import-no-semicolon.tentative.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-css-import-no-space.tentative.html b/testing/web-platform/tests/loading/preloader-css-import-no-space.tentative.html new file mode 100644 index 0000000000..9e83bebe57 --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-css-import-no-space.tentative.html @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-css-import-single-quote.tentative.html b/testing/web-platform/tests/loading/preloader-css-import-single-quote.tentative.html new file mode 100644 index 0000000000..83c6415765 --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-css-import-single-quote.tentative.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-css-import.tentative.html b/testing/web-platform/tests/loading/preloader-css-import.tentative.html new file mode 100644 index 0000000000..6e84e13983 --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-css-import.tentative.html @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-link-media.tentative.html b/testing/web-platform/tests/loading/preloader-link-media.tentative.html new file mode 100644 index 0000000000..93fc7d969f --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-link-media.tentative.html @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/loading/preloader-template.tentative.html b/testing/web-platform/tests/loading/preloader-template.tentative.html new file mode 100644 index 0000000000..e816309184 --- /dev/null +++ b/testing/web-platform/tests/loading/preloader-template.tentative.html @@ -0,0 +1,35 @@ + + + + + diff --git a/testing/web-platform/tests/loading/resources/dummy.css b/testing/web-platform/tests/loading/resources/dummy.css new file mode 100644 index 0000000000..30ff5636e2 --- /dev/null +++ b/testing/web-platform/tests/loading/resources/dummy.css @@ -0,0 +1 @@ +/* dummy css */ diff --git a/testing/web-platform/tests/loading/resources/dummy.js b/testing/web-platform/tests/loading/resources/dummy.js new file mode 100644 index 0000000000..3cae1be79e --- /dev/null +++ b/testing/web-platform/tests/loading/resources/dummy.js @@ -0,0 +1 @@ +/* Nothing to see here */ -- cgit v1.2.3