summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/signed-exchange
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/signed-exchange')
-rw-r--r--testing/web-platform/tests/signed-exchange/META.yml5
-rw-r--r--testing/web-platform/tests/signed-exchange/README.md23
-rw-r--r--testing/web-platform/tests/signed-exchange/check-cert-request.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/fallback-to-another-sxg.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/nested-sxg.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error-downgraded.tentative.html64
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error.tentative.html76
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error-downgraded.tentative.html65
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error.tentative.html76
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error-downgraded.tentative.html65
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error.tentative.html60
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative.html69
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-invalid_integrity_header.tentative.html61
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative.html68
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-no-referrer.tentative.html59
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-origin-referrer.tentative.html59
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok.tentative.html59
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative.html65
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error-downgraded.tentative.html65
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error.tentative.html60
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error-downgraded.tentative.html62
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error.tentative.html73
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error-downgraded.tentative.html63
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error.tentative.html73
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error-downgraded.tentative.html62
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error.tentative.html57
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative.html67
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-invalid_integrity_header.tentative.html58
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-mi_error.tentative.html58
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-ok.tentative.html56
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-parse_error.tentative.html54
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error-downgraded.tentative.html62
-rw-r--r--testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error.tentative.html57
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.ext7
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.key8
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem11
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cborbin0 -> 440 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor.headers1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/check-cert-request.py13
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/failure.html7
-rwxr-xr-xtesting/web-platform/tests/signed-exchange/resources/generate-test-certs.sh19
-rwxr-xr-xtesting/web-platform/tests/signed-exchange/resources/generate-test-sxgs.sh584
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/inner-url.html10
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor.headers1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/prefetch-test-cert.py18
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/prefetch-test-sxg.py20
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/register-sw-after-fallback.html23
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/register-sw.html23
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/service-worker.js5
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-location.html10
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-navigation-timing.html10
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-prefetch-test.html5
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-subresource-iframe.html29
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-subresource-mismatch-iframe.html29
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script-inner.js4
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script.js1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-subresource-sxg-inner.html2
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-util.js89
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxgbin0 -> 1005 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg.headers2
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/__dir__.headers2
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/check-cert-request.sxgbin0 -> 990 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/fallback-to-another-sxg.sxgbin0 -> 942 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-remote-origin.sxgbin0 -> 1014 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-same-origin.sxgbin0 -> 1004 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/nested-sxg.sxgbin0 -> 1965 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-after-fallback.sxgbin0 -> 999 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-from-sxg.sxgbin0 -> 1579 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxgbin0 -> 996 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found.sxgbin0 -> 992 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-data-cert-url.sxgbin0 -> 1540 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-hsts.sxgbin0 -> 1035 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-inner-url-bom.sxgbin0 -> 994 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxgbin0 -> 997 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxgbin0 -> 993 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxgbin0 -> 995 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxgbin0 -> 991 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-format.sxg1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxgbin0 -> 991 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-utf8-inner-url.sxgbin0 -> 985 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxgbin0 -> 923 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location-cert-on-alt-origin.sxgbin0 -> 995 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location.sxgbin0 -> 991 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxgbin0 -> 999 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-navigation-timing.sxgbin0 -> 1075 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-noncacheable.sxgbin0 -> 1014 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-prefetch-test.sxgbin0 -> 832 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-remote-origin.sxgbin0 -> 991 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-same-origin.sxgbin0 -> 981 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxgbin0 -> 996 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg.sub.headers1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-script.sxgbin0 -> 952 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxgbin0 -> 996 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg.sub.headers1
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-utf8-inner-url.sxgbin0 -> 990 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxgbin0 -> 995 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxgbin0 -> 991 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-match.sxgbin0 -> 1040 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-mismatch.sxgbin0 -> 1045 bytes
-rw-r--r--testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html23
-rw-r--r--testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register.tentative.https.html23
-rw-r--r--testing/web-platform/tests/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html144
-rw-r--r--testing/web-platform/tests/signed-exchange/subresource/sxg-subresource.tentative.html23
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-data-cert-url.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-double-prefetch.tentative.html37
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-fallback-with-fragment.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-hsts.tentative.html21
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-inner-url-bom.tentative.html25
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-invalid-utf8-inner-url.tentative.html25
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-invalid-validity-url.tentative.html19
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-location-fragment.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-location.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-merkle-integrity-error.tentative.html25
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-navigation-timing.tentative.html30
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-non-secure-origin.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-noncacheable.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-prefetch-merkle-integrity-error.tentative.html26
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-prefetch-resource-timing.tentative.html44
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-prefetch.tentative.https.html39
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-referrer-policy-header.tentative.https.html62
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-remote-logical.tentative.https.html67
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-same-logical.tentative.https.html66
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-remote-logical.tentative.https.html67
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-same-logical.tentative.https.html66
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-utf8-inner-url.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-variants-match.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-variants-mismatch.tentative.html17
-rw-r--r--testing/web-platform/tests/signed-exchange/sxg-version1b2.tentative.html20
129 files changed, 3794 insertions, 0 deletions
diff --git a/testing/web-platform/tests/signed-exchange/META.yml b/testing/web-platform/tests/signed-exchange/META.yml
new file mode 100644
index 0000000000..f56fbab13e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/META.yml
@@ -0,0 +1,5 @@
+spec: https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
+suggested_reviewers:
+ - irori
+ - jyasskin
+ - nyaxt
diff --git a/testing/web-platform/tests/signed-exchange/README.md b/testing/web-platform/tests/signed-exchange/README.md
new file mode 100644
index 0000000000..0987e90ad0
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/README.md
@@ -0,0 +1,23 @@
+This directory contains tests for the
+[b3 implementation snapshot](https://tools.ietf.org/html/draft-yasskin-httpbis-origin-signed-exchanges-impl-03) of the
+[Signed HTTP Exchanges](https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html).
+
+`resources` directory contains pregenerated signed exchanges and
+certificate files. To run the tests in this directory,
+`resources/127.0.0.1.sxg.pem` must be added as a trusted certificate
+in your OS/browser, or your browser must be configured to ignore
+errors for that certificate.
+
+Also, these pregenerated signed exchanges and cert files are likely to
+be expired, since they have short lifetime (maximum 7 days). If your
+browser does not have an option to ignore certificate errors,
+regenerate these files by running `generate-test-sxgs.sh` in the
+`resource` directory before running the tests.
+
+`generate-test-sxgs.sh` requires command-line tools in the
+[webpackage repository](https://github.com/WICG/webpackage).
+To install them, run:
+```
+go get -u github.com/WICG/webpackage/go/signedexchange/cmd/...
+export PATH=$PATH:$(go env GOPATH)/bin
+```
diff --git a/testing/web-platform/tests/signed-exchange/check-cert-request.tentative.html b/testing/web-platform/tests/signed-exchange/check-cert-request.tentative.html
new file mode 100644
index 0000000000..b1418e9290
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/check-cert-request.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Verify that certificate request has correct parameters.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/check-cert-request.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+}, 'Verify that certificate request has correct parameters.');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/fallback-to-another-sxg.tentative.html b/testing/web-platform/tests/signed-exchange/fallback-to-another-sxg.tentative.html
new file mode 100644
index 0000000000..8ccba86bd7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/fallback-to-another-sxg.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Fallback redirect to another SignedHTTPExchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/fallback-to-another-sxg.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+}, 'Fallback redirect to another SignedHTTPExchange');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/nested-sxg.tentative.html b/testing/web-platform/tests/signed-exchange/nested-sxg.tentative.html
new file mode 100644
index 0000000000..f1167f919a
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/nested-sxg.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Nested SignedHTTPExchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/nested-sxg.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html?fallback-from-nested-sxg');
+ assert_true(message.is_fallback);
+}, 'Nested SignedHTTPExchange');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error-downgraded.tentative.html
new file mode 100644
index 0000000000..ce20c4726e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error-downgraded.tentative.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_fetch_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin + '/signed-exchange/resources/sxg/sxg-cert-not-found.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from sxg.cert_fetch_error for' +
+ ' navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error.tentative.html
new file mode 100644
index 0000000000..15a7176e74
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_fetch_error.tentative.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_fetch_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg?navigation';
+ const cert_url =
+ alt_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is same as the reporting origin. So
+ // the report must not be downgraded.
+ type: "sxg.cert_fetch_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: cert_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "http.error",
+ status_code: 404,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_fetch_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error-downgraded.tentative.html
new file mode 100644
index 0000000000..e6cdad035e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error-downgraded.tentative.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_parse_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxg?navigation';
+ const cert_url =
+ test_origin + '/signed-exchange/resources/invalid-cert-format.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from sxg.cert_parse_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error.tentative.html
new file mode 100644
index 0000000000..a0cc607bf5
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_parse_error.tentative.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_parse_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxg?navigation';
+ const cert_url =
+ alt_origin + '/signed-exchange/resources/invalid-cert-format.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is same as the reporting origin. So
+ // the report must not be downgraded.
+ type: "sxg.cert_parse_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: cert_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_parse_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error-downgraded.tentative.html
new file mode 100644
index 0000000000..d3ad4204f2
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error-downgraded.tentative.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_verification_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html', 'location');
+ assert_true(message.is_fallback, 'is_fallback');
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from ' +
+ 'sxg.cert_verification_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error.tentative.html
new file mode 100644
index 0000000000..04fd0e785c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-cert_verification_error.tentative.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_verification_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg?navigation';
+ const cert_url = alt_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.cert_verification_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_verification_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative.html
new file mode 100644
index 0000000000..a92735f714
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed for navigation (zero success fraction)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithZeroSuccessFractionPolicyInIframe();
+ const sxg_url =
+ alt_origin + '/signed-exchange/resources/sxg/sxg-cert-not-found.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportExists(
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: cert_url
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ }
+ ), 'SXG error reporting must be downgraded when the cert URL is different ' +
+ 'from the reporting origin');
+ assert_false(await reportExists(
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ }
+ ), 'Succeeded normal NEL report should not be sent when success fraction ' +
+ 'is zero.');
+}, 'SXG error report must be downgraded when the cert URL is different from ' +
+ 'the reporting origin. And succeeded normal NEL report should not be sent ' +
+ ' when success fraction is zero.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-invalid_integrity_header.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-invalid_integrity_header.tentative.html
new file mode 100644
index 0000000000..3e00d9dbe3
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-invalid_integrity_header.tentative.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.invalid_integrity_header for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.invalid_integrity_header",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.invalid_integrity_header for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative.html
new file mode 100644
index 0000000000..b6d7ba3b1a
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.mi_error for navigation</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ try {
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ if (message.is_fallback) {
+ assert_unreached('Fallback redirect should not have happened');
+ } else {
+ assert_unreached('SXG should not have loaded');
+ }
+ } catch (e) {
+ assert_equals(e, 'timeout');
+ }
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.mi_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ }
+ ]));
+}, 'SXG reporting test of sxg.mi_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-no-referrer.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-no-referrer.tentative.html
new file mode 100644
index 0000000000..b6cadbca50
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-no-referrer.tentative.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>SXG reporting test of ok for navigation with no-referrer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url = alt_origin + '/signed-exchange/resources/sxg/sxg-location.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url, 'no-referrer');
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: '',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: '',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of ok for navigation with no-referrer.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-origin-referrer.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-origin-referrer.tentative.html
new file mode 100644
index 0000000000..351ad92782
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok-origin-referrer.tentative.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>SXG reporting test of ok for navigation with origin referrer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url = alt_origin + '/signed-exchange/resources/sxg/sxg-location.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url, 'origin');
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: document.location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: document.location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of ok for navigation with origin referrer.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok.tentative.html
new file mode 100644
index 0000000000..0afa626d09
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-ok.tentative.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>SXG reporting test of ok for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url = alt_origin + '/signed-exchange/resources/sxg/sxg-location.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG success report must be sent for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative.html
new file mode 100644
index 0000000000..95cd140cea
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.parse_error for navigation</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-format.sxg?navigation';
+ try {
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ if (message.is_fallback) {
+ assert_unreached('Fallback redirect should not have happened');
+ } else {
+ assert_unreached('SXG should not have loaded');
+ }
+ } catch (e) {
+ assert_equals(e, 'timeout');
+ }
+
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.parse_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ cert_url: []
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.parse_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error-downgraded.tentative.html
new file mode 100644
index 0000000000..2679ae5a6c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error-downgraded.tentative.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.signature_verification_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxg?navigation';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from ' +
+ 'sxg.signature_verification_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error.tentative.html
new file mode 100644
index 0000000000..f3e0b8f0e6
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error.tentative.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.signature_verification_error for navigation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_iframe_test(async t => {
+ await loadResourceWithBasicPolicyInIframe();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg?navigation';
+ const cert_url = alt_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxg_url);
+ assert_equals(message.location,
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.signature_verification_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.signature_verification_error for navigation.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error-downgraded.tentative.html
new file mode 100644
index 0000000000..82b5d8f11e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error-downgraded.tentative.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_fetch_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin + '/signed-exchange/resources/sxg/sxg-cert-not-found.sxg?prefetch';
+ const cert_url =
+ test_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from ' +
+ 'sxg.cert_fetch_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error.tentative.html
new file mode 100644
index 0000000000..32e3cad1b0
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_fetch_error.tentative.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_fetch_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg?prefetch';
+ const cert_url =
+ alt_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is same as the reporting origin. So
+ // the report must not be downgraded.
+ type: "sxg.cert_fetch_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: cert_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "http.error",
+ status_code: 404,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_fetch_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error-downgraded.tentative.html
new file mode 100644
index 0000000000..bbad6032e2
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error-downgraded.tentative.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_parse_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxg?prefetch';
+ const cert_url =
+ test_origin + '/signed-exchange/resources/invalid-cert-format.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from sxg.cert_parse_error for' +
+ ' prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error.tentative.html
new file mode 100644
index 0000000000..a6ea9e4eed
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_parse_error.tentative.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_parse_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxg?prefetch';
+ const cert_url =
+ alt_origin + '/signed-exchange/resources/invalid-cert-format.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is same as the reporting origin. So
+ // the report must not be downgraded.
+ type: "sxg.cert_parse_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: cert_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_parse_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error-downgraded.tentative.html
new file mode 100644
index 0000000000..b25bf491da
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error-downgraded.tentative.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.cert_verification_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxg?prefetch';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from ' +
+ 'sxg.cert_verification_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error.tentative.html
new file mode 100644
index 0000000000..f31a4c49d4
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-cert_verification_error.tentative.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.cert_verification_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg?prefetch';
+ const cert_url = alt_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.cert_verification_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.cert_verification_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative.html
new file mode 100644
index 0000000000..faa02bc0eb
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed for prefetch (zero success fraction)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithZeroSuccessFractionPolicy();
+ const sxg_url =
+ alt_origin + '/signed-exchange/resources/sxg/sxg-cert-not-found.sxg?prefetch';
+ const cert_url =
+ test_origin + '/signed-exchange/resources/not_found_certfile.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportExists(
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ), 'SXG error reporting must be downgraded when the cert URL is different ' +
+ 'from the reporting origin');
+ assert_false(await reportExists(
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ }
+ ), 'Succeeded normal NEL report should not be sent when success fraction ' +
+ 'is zero.');
+}, 'SXG error report must be downgraded when the cert URL is different from ' +
+ 'the reporting origin. And succeeded normal NEL report should not be sent ' +
+ ' when success fraction is zero.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-invalid_integrity_header.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-invalid_integrity_header.tentative.html
new file mode 100644
index 0000000000..990b4a387e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-invalid_integrity_header.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.invalid_integrity_header for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxg?prefetch';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.invalid_integrity_header",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.invalid_integrity_header for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-mi_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-mi_error.tentative.html
new file mode 100644
index 0000000000..f265a92058
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-mi_error.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.mi_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg?prefetch';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.mi_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ }
+ ]));
+}, 'SXG reporting test of sxg.mi_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-ok.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-ok.tentative.html
new file mode 100644
index 0000000000..e3c6a0eeea
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-ok.tentative.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>SXG reporting test of ok for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url = alt_origin + '/signed-exchange/resources/sxg/sxg-location.sxg?prefetch';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG success report must be sent for prefetching.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-parse_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-parse_error.tentative.html
new file mode 100644
index 0000000000..2e2b860e22
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-parse_error.tentative.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.parse_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-format.sxg?prefetch';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.parse_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ cert_url: []
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.parse_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error-downgraded.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error-downgraded.tentative.html
new file mode 100644
index 0000000000..fbeaeecff9
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error-downgraded.tentative.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.failed downgraded from sxg.signature_verification_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+const test_origin = get_host_info().HTTPS_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxg?prefetch';
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ // The origin of this SXG's certURL is different from the reporting
+ // origin. So the report must be downgraded.
+ type: "sxg.failed",
+ elapsed_time: 0,
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.failed downgraded from ' +
+ 'sxg.signature_verification_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error.tentative.html b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error.tentative.html
new file mode 100644
index 0000000000..f3805ad693
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error.tentative.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>SXG reporting test of sxg.signature_verification_error for prefetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+
+nel_test(async t => {
+ await fetchResourceWithBasicPolicy();
+ const sxg_url =
+ alt_origin +
+ '/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg?prefetch';
+ const cert_url = alt_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+ addPrefetch(sxg_url);
+ assert_true(await reportsExist([
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.signature_verification_error",
+ status_code: 200,
+ referrer: location.origin + '/',
+ sxg: {
+ outer_url: sxg_url,
+ inner_url:
+ innerURLOrigin() + '/signed-exchange/resources/inner-url.html',
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ {
+ url: sxg_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'SXG reporting test of sxg.signature_verification_error for prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.ext b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.ext
new file mode 100644
index 0000000000..8cdc25a9a7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.ext
@@ -0,0 +1,7 @@
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+subjectAltName = DNS:127.0.0.1
+
+# CanSignHttpExchanges extension
+# https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-cert-req
+1.3.6.1.4.1.11129.2.1.22 = ASN1:NULL
diff --git a/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.key b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.key
new file mode 100644
index 0000000000..53f80c86fa
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.key
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIENXRP9iROaUuhisQ+3Rb9hS14J8ny36TRPBDfuWNLfWoAoGCCqGSM49
+AwEHoUQDQgAELBO41fB7hYZ9BqY4V0xMPUJZIH20ZW5fLHw26gHs20Hv+4GKgnHR
+3Simlna0fLxxDD/WRmADUZiA6e1blThkJA==
+-----END EC PRIVATE KEY-----
diff --git a/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem
new file mode 100644
index 0000000000..2da2a807d2
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBmDCCAT+gAwIBAgIJANaBpqCSy2GLMAoGCCqGSM49BAMCMDAxEjAQBgNVBAMM
+CTEyNy4wLjAuMTENMAsGA1UECgwEVGVzdDELMAkGA1UEBhMCVVMwHhcNMTgxMDE1
+MDczNDAzWhcNMjgxMDEyMDczNDAzWjAwMRIwEAYDVQQDDAkxMjcuMC4wLjExDTAL
+BgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAELBO41fB7hYZ9BqY4V0xMPUJZIH20ZW5fLHw26gHs20Hv+4GKgnHR3Simlna0
+fLxxDD/WRmADUZiA6e1blThkJKNCMEAwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw
+FAYDVR0RBA0wC4IJMTI3LjAuMC4xMBAGCisGAQQB1nkCARYEAgUAMAoGCCqGSM49
+BAMCA0cAMEQCIBz3vP5lPS2h8noHlnQ8VupcIJoIbmIfWUExW/tsSj1uAiBxve6H
+aoDl5q91E6FisA8UhCUt0KSy2bL37IJwo6LwOg==
+-----END CERTIFICATE-----
diff --git a/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor
new file mode 100644
index 0000000000..9dedd96b5b
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor.headers b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor.headers
new file mode 100644
index 0000000000..d581d5987e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/127.0.0.1.sxg.pem.cbor.headers
@@ -0,0 +1 @@
+Content-Type: application/cert-chain+cbor
diff --git a/testing/web-platform/tests/signed-exchange/resources/check-cert-request.py b/testing/web-platform/tests/signed-exchange/resources/check-cert-request.py
new file mode 100644
index 0000000000..f5e898d2dc
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/check-cert-request.py
@@ -0,0 +1,13 @@
+import os
+
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ CertChainMimeType = b"application/cert-chain+cbor"
+
+ if request.headers.get(b"Accept") != CertChainMimeType:
+ return 400, [], u"Bad Request"
+
+ path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), u"127.0.0.1.sxg.pem.cbor")
+ body = open(path, u"rb").read()
+ return 200, [(b"Content-Type", CertChainMimeType)], body
diff --git a/testing/web-platform/tests/signed-exchange/resources/failure.html b/testing/web-platform/tests/signed-exchange/resources/failure.html
new file mode 100644
index 0000000000..1071f082b7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/failure.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<title>Content of invalid signed exchange</title>
+<script>
+window.addEventListener('message', (event) => {
+ event.data.port.postMessage("FAIL if this content is loaded");
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/generate-test-certs.sh b/testing/web-platform/tests/signed-exchange/resources/generate-test-certs.sh
new file mode 100755
index 0000000000..01330e46d8
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/generate-test-certs.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Creates a self-signed certificate to use for signing exchanges.
+# TODO: Integrate into tools/wptserve/wptserve/sslutils/openssl.py
+
+set -e
+
+openssl ecparam -out 127.0.0.1.sxg.key -name prime256v1 -genkey
+
+openssl req -new -sha256 \
+ -key 127.0.0.1.sxg.key \
+ -out 127.0.0.1.sxg.csr \
+ -subj '/CN=127.0.0.1/O=Test/C=US'
+
+openssl x509 -req -days 3650 \
+ -in 127.0.0.1.sxg.csr \
+ -extfile 127.0.0.1.sxg.ext \
+ -signkey 127.0.0.1.sxg.key \
+ -out 127.0.0.1.sxg.pem
diff --git a/testing/web-platform/tests/signed-exchange/resources/generate-test-sxgs.sh b/testing/web-platform/tests/signed-exchange/resources/generate-test-sxgs.sh
new file mode 100755
index 0000000000..bf25356d07
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/generate-test-sxgs.sh
@@ -0,0 +1,584 @@
+#!/bin/sh
+sxg_version=1b3
+certfile=127.0.0.1.sxg.pem
+keyfile=127.0.0.1.sxg.key
+inner_url_origin=https://127.0.0.1:8444
+# TODO: Stop hard-coding "web-platform.test" when generating Signed Exchanges on
+# the fly.
+wpt_test_origin=https://web-platform.test:8444
+wpt_test_remote_origin=https://www1.web-platform.test:8444
+wpt_test_alt_origin=https://not-web-platform.test:8444
+cert_url_origin=$wpt_test_origin
+sxg_content_type='content-type: application/signed-exchange;v=b3'
+variants_header=variants-04
+variant_key_header=variant-key-04
+
+set -e
+
+for cmd in gen-signedexchange gen-certurl dump-signedexchange; do
+ if ! command -v $cmd > /dev/null 2>&1; then
+ echo "$cmd is not installed. Please run:"
+ echo " go get -u github.com/WICG/webpackage/go/signedexchange/cmd/..."
+ echo ' export PATH=$PATH:$(go env GOPATH)/bin'
+ exit 1
+ fi
+done
+
+tmpdir=$(mktemp -d)
+
+echo -n OCSP >$tmpdir/ocsp
+gen-certurl -pem $certfile -ocsp $tmpdir/ocsp > $certfile.cbor
+
+option="-w 0"
+if [ "$(uname -s)" = "Darwin" ]; then
+ option=""
+fi
+
+cert_base64=$(base64 ${option} ${certfile}.cbor)
+data_cert_url="data:application/cert-chain+cbor;base64,$cert_base64"
+
+
+# A valid Signed Exchange.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-location.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange. The origin of certUrl is the "alt" origin where NEL
+# policy is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $wpt_test_alt_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-location-cert-on-alt-origin.sxg \
+ -miRecordSize 100
+
+# A signed exchange of unsupported version.
+gen-signedexchange \
+ -version 1b2 \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg-version1b2.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange for testing referrer which logical origin is the wpt
+# test origin.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $wpt_test_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-referrer-same-origin.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange for testing referrer which logical origin is the wpt
+# test remote origin.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_remote_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $wpt_test_remote_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-referrer-remote-origin.sxg \
+ -miRecordSize 100
+
+# A invalid Signed Exchange for testing referrer which logical origin is the wpt
+# test origin. Response has Cache-Control: no-store header.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "Cache-Control: no-store" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $wpt_test_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/invalid-sxg-referrer-same-origin.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# A invalid Signed Exchange for testing referrer which logical origin is the wpt
+# test remote origin. Response has Cache-Control: no-store header.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_remote_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "Cache-Control: no-store" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $wpt_test_remote_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/invalid-sxg-referrer-remote-origin.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# For check-cert-request.tentative.html
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/check-cert-request.py \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/check-cert-request.sxg \
+ -miRecordSize 100
+
+# validityUrl is different origin from request URL.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content failure.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl https://example.com/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-invalid-validity-url.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# certUrl is 404 and the origin of certUrl is different from the "alt" origin
+# where NEL policy is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/not_found_certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-cert-not-found.sxg \
+ -miRecordSize 100
+
+# certUrl is 404 and the origin of certUrl is the "alt" origin where NEL policy
+# is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $wpt_test_alt_origin/signed-exchange/resources/not_found_certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-cert-not-found-on-alt-origin.sxg \
+ -miRecordSize 100
+
+# certUrl is 404 and fallback URL is another signed exchange.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/sxg/sxg-location.sxg \
+ -status 200 \
+ -content failure.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/not_found_$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/fallback-to-another-sxg.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# certUrl is an invalid cert and the origin of certUrl is different from the
+# "alt" origin where NEL policy is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/invalid-cert-format.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-invalid-cert-format.sxg \
+ -miRecordSize 100
+
+# certUrl is an invalid cert and the origin of certUrl is the "alt" origin where
+# NEL policy is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $wpt_test_alt_origin/signed-exchange/resources/invalid-cert-format.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-invalid-cert-format-on-alt-origin.sxg \
+ -miRecordSize 100
+
+# Nested signed exchange.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri "$inner_url_origin/signed-exchange/resources/inner-url.html?fallback-from-nested-sxg" \
+ -status 200 \
+ -content sxg/sxg-location.sxg \
+ -responseHeader "$sxg_content_type" \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/nested-sxg.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Fallback URL has non-ASCII UTF-8 characters.
+gen-signedexchange \
+ -version $sxg_version \
+ -ignoreErrors \
+ -uri "$inner_url_origin/signed-exchange/resources/🌐📦.html" \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-utf8-inner-url.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Fallback URL has invalid UTF-8 sequence.
+gen-signedexchange \
+ -version $sxg_version \
+ -ignoreErrors \
+ -uri "$inner_url_origin/signed-exchange/resources/$(echo -e '\xce\xce\xa9').html" \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-invalid-utf8-inner-url.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Fallback URL has UTF-8 BOM.
+gen-signedexchange \
+ -version $sxg_version \
+ -ignoreErrors \
+ -uri "$(echo -e '\xef\xbb\xbf')$inner_url_origin/signed-exchange/resources/inner-url.html" \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-inner-url-bom.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Response has Cache-Control: no-store header.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "Cache-Control: no-store" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-noncacheable.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Response has a strict-transport-security header.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "Strict-Transport-Security: max-age=31536000" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-hsts.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Signed Exchange with payload integrity error.
+echo 'garbage' | cat sxg/sxg-location.sxg - >sxg/sxg-merkle-integrity-error.sxg
+
+# An invalid signed exchange which integrity header is invalid.
+cat sxg/sxg-location.sxg |
+ sed 's/digest\/mi-sha256-03/digest\/mi-sha256-xx/' \
+ > sxg/sxg-invalid-integrity-header.sxg
+
+# An invalid signed exchange which cert-sha256 is invalid.
+dummy_sha256=`echo "dummy" | openssl dgst -binary -sha256 | base64`
+cat sxg/sxg-location.sxg |
+ sed "s/cert-sha256=\*[^*]*\*;/cert-sha256=*$dummy_sha256*;/" \
+ > sxg/sxg-invalid-cert-sha256.sxg
+cat sxg/sxg-location-cert-on-alt-origin.sxg |
+ sed "s/cert-sha256=\*[^*]*\*;/cert-sha256=*$dummy_sha256*;/" \
+ > sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg
+
+# An invalid signed exchange which validity period is too long.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 300h \
+ -o sxg/sxg-validity-period-too-long.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# An invalid signed exchange which validity period is too long. The origin of
+# certUrl is the "alt" origin where NEL policy is installed in reporting tests.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $wpt_test_alt_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 300h \
+ -o sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg \
+ -miRecordSize 100 \
+ -ignoreErrors true
+
+# Signed Exchange with variants / variant-key that match any request.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "${variants_header}: accept-language;en" \
+ -responseHeader "${variant_key_header}: en" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-variants-match.sxg \
+ -miRecordSize 100
+
+# Signed Exchange with variants / variant-key that never match any request.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -responseHeader "${variants_header}: accept-language;en" \
+ -responseHeader "${variant_key_header}: unknown" \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-variants-mismatch.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange that reports navigation timing.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-navigation-timing.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-navigation-timing.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange for testing service worker registration.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_origin/signed-exchange/resources/register-sw-from-sxg.html \
+ -status 200 \
+ -content register-sw.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $wpt_test_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/register-sw-from-sxg.sxg \
+ -miRecordSize 100
+
+# An invalid Signed Exchange for testing service worker registration after
+# fallback.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $wpt_test_origin/signed-exchange/resources/register-sw-after-fallback.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/not_found_certfile.cbor \
+ -validityUrl $wpt_test_origin/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/register-sw-after-fallback.sxg \
+ -miRecordSize 100
+
+# A valid Signed Exchange using data URL for cert-url.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-location.html \
+ -certificate $certfile \
+ -certUrl $data_cert_url \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2018-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-data-cert-url.sxg \
+ -miRecordSize 100
+
+# Generate the signed exchange file of sxg-subresource-script-inner.js.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/sxg-subresource-script.js \
+ -status 200 \
+ -responseHeader "Content-Type: application/javascript" \
+ -content sxg-subresource-script-inner.js \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2030-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-subresource-script.sxg \
+ -miRecordSize 100
+
+# Get the header integrity hash value of sxg-subresource-script.sxg.
+header_integrity=$(dump-signedexchange -i sxg/sxg-subresource-script.sxg | \
+ grep -o "header integrity: sha256-.*" | \
+ grep -o "sha256-.*$")
+
+# Generate the signed exchange file of signed exchange subresource test.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/sxg-subresource-sxg.html \
+ -status 200 \
+ -content sxg-subresource-sxg-inner.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2030-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-subresource.sxg \
+ -miRecordSize 100 \
+ -responseHeader "link:<$inner_url_origin/signed-exchange/resources/sxg-subresource-script.js>;rel=allowed-alt-sxg;header-integrity=\"$header_integrity\",<$inner_url_origin/signed-exchange/resources/sxg-subresource-script.js>;rel=preload;as=script"
+
+# Generate the signed exchange file of signed exchange subresource test with
+# header integrity mismatch.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/sxg-subresource-sxg.html \
+ -status 200 \
+ -content sxg-subresource-sxg-inner.html \
+ -certificate $certfile \
+ -certUrl $cert_url_origin/signed-exchange/resources/$certfile.cbor \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2030-04-01T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-subresource-header-integrity-mismatch.sxg \
+ -miRecordSize 100 \
+ -responseHeader "link:<$inner_url_origin/signed-exchange/resources/sxg-subresource-script.js>;rel=allowed-alt-sxg;header-integrity=\"sha256-$dummy_sha256\",<$inner_url_origin/signed-exchange/resources/sxg-subresource-script.js>;rel=preload;as=script"
+
+# A Signed Exchange for testing prefetch.
+# The id query value "XXX..." of prefetch-test-cert.py will be replaced with
+# UUID for stash token by prefetch-test-sxg.py.
+gen-signedexchange \
+ -version $sxg_version \
+ -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
+ -status 200 \
+ -content sxg-prefetch-test.html \
+ -certificate $certfile \
+ -certUrl $wpt_test_remote_origin/signed-exchange/resources/prefetch-test-cert.py?id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
+ -validityUrl $inner_url_origin/signed-exchange/resources/resource.validity.msg \
+ -privateKey $keyfile \
+ -date 2020-01-29T00:00:00Z \
+ -expire 168h \
+ -o sxg/sxg-prefetch-test.sxg \
+ -miRecordSize 100
+
+rm -fr $tmpdir
diff --git a/testing/web-platform/tests/signed-exchange/resources/inner-url.html b/testing/web-platform/tests/signed-exchange/resources/inner-url.html
new file mode 100644
index 0000000000..5b247bbfe9
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/inner-url.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Content of fallback URL</title>
+<script>
+window.addEventListener('message', (event) => {
+ event.data.port.postMessage({
+ location: document.location.href,
+ referrer: document.referrer,
+ is_fallback: true});
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor b/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor
new file mode 100644
index 0000000000..82f15ff924
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor
@@ -0,0 +1 @@
+This is an invalid certificate file.
diff --git a/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor.headers b/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor.headers
new file mode 100644
index 0000000000..d581d5987e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/invalid-cert-format.cbor.headers
@@ -0,0 +1 @@
+Content-Type: application/cert-chain+cbor
diff --git a/testing/web-platform/tests/signed-exchange/resources/prefetch-test-cert.py b/testing/web-platform/tests/signed-exchange/resources/prefetch-test-cert.py
new file mode 100644
index 0000000000..e1dffebe18
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/prefetch-test-cert.py
@@ -0,0 +1,18 @@
+import os
+
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ stash_id = request.GET.first(b"id")
+ if request.server.stash.take(stash_id) is not None:
+ response.status = (404, b"Not Found")
+ response.headers.set(b"Content-Type", b"text/plain")
+ return u"not found"
+ request.server.stash.put(stash_id, True)
+
+ path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), u"127.0.0.1.sxg.pem.cbor")
+ body = open(path, u"rb").read()
+
+ response.headers.set(b"Content-Type", b"application/cert-chain+cbor")
+ response.headers.set(b"Cache-Control", b"public, max-age=600")
+ return body
diff --git a/testing/web-platform/tests/signed-exchange/resources/prefetch-test-sxg.py b/testing/web-platform/tests/signed-exchange/resources/prefetch-test-sxg.py
new file mode 100644
index 0000000000..84b9ebe408
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/prefetch-test-sxg.py
@@ -0,0 +1,20 @@
+import os
+
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ stash_id = request.GET.first(b"id")
+ if request.server.stash.take(stash_id) is not None:
+ response.status = (404, u"Not Found")
+ response.headers.set(b"Content-Type", b"text/plain")
+ return u"not found"
+ request.server.stash.put(stash_id, True)
+
+ path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), u"sxg", u"sxg-prefetch-test.sxg")
+ body = open(path, u"rb").read()
+
+ response.headers.set(b"Content-Type", b"application/signed-exchange;v=b3")
+ response.headers.set(b"X-Content-Type-Options", b"nosniff")
+ response.headers.set(b"Cache-Control", b"public, max-age=600")
+
+ return body.replace(b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', stash_id)
diff --git a/testing/web-platform/tests/signed-exchange/resources/register-sw-after-fallback.html b/testing/web-platform/tests/signed-exchange/resources/register-sw-after-fallback.html
new file mode 100644
index 0000000000..2711fc241f
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/register-sw-after-fallback.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="sxg-util.js"></script>
+<script>
+window.addEventListener('message', async (event) => {
+ try {
+ const scope = './scope/' + location.href;
+ await registerServiceWorkerAndWaitUntilActivated(
+ './service-worker.js', scope)
+ const iframe = await withIframe(scope, 'inner_iframe');
+ event.data.port.postMessage({
+ location: document.location.href,
+ is_fallback: true,
+ err: undefined,
+ iframe_body: iframe.contentWindow.document.body.innerHTML});
+ } catch (err) {
+ event.data.port.postMessage({
+ location: document.location.href,
+ is_fallback: true,
+ err: err.toString()
+ });
+ }
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/register-sw.html b/testing/web-platform/tests/signed-exchange/resources/register-sw.html
new file mode 100644
index 0000000000..8a3873bfde
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/register-sw.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="sxg-util.js"></script>
+<script>
+window.addEventListener('message', async (event) => {
+ try {
+ const scope = './scope/' + location.href;
+ await registerServiceWorkerAndWaitUntilActivated(
+ './service-worker.js', scope)
+ const iframe = await withIframe(scope, 'inner_iframe');
+ event.data.port.postMessage({
+ location: document.location.href,
+ is_fallback: false,
+ err: undefined,
+ iframe_body: iframe.contentWindow.document.body.innerHTML});
+ } catch (err) {
+ event.data.port.postMessage({
+ location: document.location.href,
+ is_fallback: false,
+ err: err.toString()
+ });
+ }
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/service-worker.js b/testing/web-platform/tests/signed-exchange/resources/service-worker.js
new file mode 100644
index 0000000000..2647f45a3e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/service-worker.js
@@ -0,0 +1,5 @@
+self.addEventListener('fetch', function(event) {
+ event.respondWith(new Response(
+ '<body>Generated by service worker</body>',
+ {headers:[['content-type', 'text/html']]}));
+});
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-location.html b/testing/web-platform/tests/signed-exchange/resources/sxg-location.html
new file mode 100644
index 0000000000..b3ebd2bde7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-location.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Content of SignedHTTPExchange</title>
+<script>
+window.addEventListener('message', (event) => {
+ event.data.port.postMessage({
+ location: document.location.href,
+ referrer: document.referrer,
+ is_fallback: false});
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-navigation-timing.html b/testing/web-platform/tests/signed-exchange/resources/sxg-navigation-timing.html
new file mode 100644
index 0000000000..ddbe350354
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-navigation-timing.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Navigation timing of SignedHTTPExchange</title>
+<script>
+window.addEventListener('message', (event) => {
+ event.data.port.postMessage({
+ location: document.location.href,
+ timing: JSON.stringify(performance.getEntriesByType('navigation')[0]),
+ is_fallback: false});
+}, false);
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-prefetch-test.html b/testing/web-platform/tests/signed-exchange/resources/sxg-prefetch-test.html
new file mode 100644
index 0000000000..5383a4a561
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-prefetch-test.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<title>Prefetch test SXG</title>
+<script>
+window.opener.postMessage('loaded', '*');
+</script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-iframe.html b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-iframe.html
new file mode 100644
index 0000000000..bd812857b4
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-iframe.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<body>
+<script>
+(async () => {
+ const sxg_path = 'sxg/sxg-subresource.sxg';
+ const scipt_sxg_path = 'sxg/sxg-subresource-script.sxg';
+ const scipt_path = 'sxg-subresource-script.js';
+ const wait_for_prefetch = new Promise((resolve) => {
+ new PerformanceObserver((list) => {
+ for (let e of list.getEntries()) {
+ if (e.name.endsWith(scipt_sxg_path)) {
+ resolve();
+ } else if (e.name.endsWith(scipt_path)) {
+ window.parent.postMessage(
+ scipt_path + ' should not be prefetched', '*');
+ }
+ }
+ }).observe({ entryTypes: ['resource'] });
+ });
+
+ const link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = sxg_path;
+ document.body.appendChild(link);
+ await wait_for_prefetch;
+ location.href = sxg_path;
+})()
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-mismatch-iframe.html b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-mismatch-iframe.html
new file mode 100644
index 0000000000..f05fcc99f8
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-mismatch-iframe.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<body>
+<script>
+(async () => {
+ const sxg_path = 'sxg/sxg-subresource-header-integrity-mismatch.sxg';
+ const scipt_sxg_path = 'sxg/sxg-subresource-script.sxg';
+ const scipt_path = 'sxg-subresource-script.js';
+ const wait_for_prefetch = new Promise((resolve) => {
+ new PerformanceObserver((list) => {
+ for (let e of list.getEntries()) {
+ if (e.name.endsWith(scipt_sxg_path)) {
+ resolve();
+ } else if (e.name.endsWith(scipt_path)) {
+ window.parent.postMessage(
+ scipt_path + ' should not be prefetched', '*');
+ }
+ }
+ }).observe({ entryTypes: ['resource'] });
+ });
+
+ const link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = sxg_path;
+ document.body.appendChild(link);
+ await wait_for_prefetch;
+ location.href = sxg_path;
+})()
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script-inner.js b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script-inner.js
new file mode 100644
index 0000000000..dcc7a356a0
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script-inner.js
@@ -0,0 +1,4 @@
+// Usually the alternate resource should have the same content as the original
+// one (sxg-subresource-script.js), but for now we use differentiated content
+// for easy testing.
+window.parent.postMessage('from signed exchange', '*');
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script.js b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script.js
new file mode 100644
index 0000000000..c730568fcf
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-script.js
@@ -0,0 +1 @@
+window.parent.postMessage('from server', '*');
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-sxg-inner.html b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-sxg-inner.html
new file mode 100644
index 0000000000..9dfff56ad8
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-subresource-sxg-inner.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<script src="sxg-subresource-script.js"></script>
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-util.js b/testing/web-platform/tests/signed-exchange/resources/sxg-util.js
new file mode 100644
index 0000000000..fa2d200fb2
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-util.js
@@ -0,0 +1,89 @@
+// Opens |url| in an iframe, establish a message channel with it, and waits for
+// a message from the frame content. Returns a promise that resolves with the
+// data of the message, or rejects on 15000ms timeout.
+// If the iframe load is expected to fail, the test should have
+// <meta name="timeout" content="long"> tag.
+function openSXGInIframeAndWaitForMessage(test_object, url, referrerPolicy) {
+ return new Promise(async (resolve, reject) => {
+ // We can't catch the network error on iframe. So we use the timer.
+ test_object.step_timeout(() => reject('timeout'), 15000);
+
+ const frame = await withIframe(url, 'sxg_iframe', referrerPolicy);
+ const channel = new MessageChannel();
+ channel.port1.onmessage = (event) => resolve(event.data);
+ frame.contentWindow.postMessage(
+ {port: channel.port2}, '*', [channel.port2]);
+ });
+}
+
+function withIframe(url, name, referrerPolicy) {
+ return new Promise((resolve, reject) => {
+ const frame = document.createElement('iframe');
+ frame.src = url;
+ frame.name = name;
+ if (referrerPolicy !== undefined) {
+ frame.referrerPolicy = referrerPolicy;
+ }
+ frame.onload = () => resolve(frame);
+ frame.onerror = () => reject('failed to load ' + url);
+ document.body.appendChild(frame);
+ });
+}
+
+function loadScript(url) {
+ return new Promise((resolve, reject) => {
+ const scriptTag = document.createElement('script');
+ scriptTag.src = url;
+ scriptTag.onload = () => resolve();
+ scriptTag.onerror = () => reject('failed to load ' + url);
+ document.head.appendChild(scriptTag);
+ });
+}
+
+function innerURLOrigin() {
+ return 'https://127.0.0.1:8444';
+}
+
+function runReferrerTests(test_cases) {
+ for (const i in test_cases) {
+ const test_case = test_cases[i];
+ promise_test(async (t) => {
+ const sxgUrl = test_case.origin + '/signed-exchange/resources/sxg/' +
+ test_case.sxg;
+ const message =
+ await openSXGInIframeAndWaitForMessage(
+ t, sxgUrl, test_case.referrerPolicy);
+ assert_false(message.is_fallback);
+ assert_equals(message.referrer, test_case.expectedReferrer);
+
+ const invalidSxgUrl =
+ test_case.origin + '/signed-exchange/resources/sxg/invalid-' +
+ test_case.sxg;
+ const fallbackMessage =
+ await openSXGInIframeAndWaitForMessage(
+ t, invalidSxgUrl, test_case.referrerPolicy);
+ assert_true(fallbackMessage.is_fallback);
+ assert_equals(fallbackMessage.referrer, test_case.expectedReferrer);
+ }, 'Referrer of SignedHTTPExchange test : ' + JSON.stringify(test_case));
+ }
+}
+
+function addPrefetch(url) {
+ const link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = url;
+ document.body.appendChild(link);
+}
+
+async function registerServiceWorkerAndWaitUntilActivated(script, scope) {
+ const reg = await navigator.serviceWorker.register(script, {scope: scope});
+ if (reg.active)
+ return;
+ const worker = reg.installing || reg.waiting;
+ await new Promise((resolve) => {
+ worker.addEventListener('statechange', (event) => {
+ if (event.target.state == 'activated')
+ resolve();
+ });
+ });
+}
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg
new file mode 100644
index 0000000000..092eb9d38f
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg.headers b/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg.headers
new file mode 100644
index 0000000000..ca41178420
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg-version1b2.sxg.headers
@@ -0,0 +1,2 @@
+Content-Type: application/signed-exchange;v=b2
+X-Content-Type-Options: nosniff
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/__dir__.headers b/testing/web-platform/tests/signed-exchange/resources/sxg/__dir__.headers
new file mode 100644
index 0000000000..83a3c128cf
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/__dir__.headers
@@ -0,0 +1,2 @@
+Content-Type: application/signed-exchange;v=b3
+X-Content-Type-Options: nosniff
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/check-cert-request.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/check-cert-request.sxg
new file mode 100644
index 0000000000..8129b5479c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/check-cert-request.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/fallback-to-another-sxg.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/fallback-to-another-sxg.sxg
new file mode 100644
index 0000000000..b5dcb6b86d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/fallback-to-another-sxg.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-remote-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-remote-origin.sxg
new file mode 100644
index 0000000000..db08ad072c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-remote-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-same-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-same-origin.sxg
new file mode 100644
index 0000000000..5057e9ddf4
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/invalid-sxg-referrer-same-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/nested-sxg.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/nested-sxg.sxg
new file mode 100644
index 0000000000..6d8538882d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/nested-sxg.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-after-fallback.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-after-fallback.sxg
new file mode 100644
index 0000000000..20ae275818
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-after-fallback.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-from-sxg.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-from-sxg.sxg
new file mode 100644
index 0000000000..792222029f
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/register-sw-from-sxg.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg
new file mode 100644
index 0000000000..2a7dbf6fa6
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found-on-alt-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found.sxg
new file mode 100644
index 0000000000..072125400a
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-cert-not-found.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-data-cert-url.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-data-cert-url.sxg
new file mode 100644
index 0000000000..b5972d545c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-data-cert-url.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-hsts.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-hsts.sxg
new file mode 100644
index 0000000000..8f57c63dfa
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-hsts.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-inner-url-bom.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-inner-url-bom.sxg
new file mode 100644
index 0000000000..0093eb1d37
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-inner-url-bom.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxg
new file mode 100644
index 0000000000..62acedd390
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format-on-alt-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxg
new file mode 100644
index 0000000000..30e4fcd912
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-format.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg
new file mode 100644
index 0000000000..066a3cc0a4
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256-cert-on-alt-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxg
new file mode 100644
index 0000000000..46d2bb1386
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-cert-sha256.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-format.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-format.sxg
new file mode 100644
index 0000000000..3fbb151b5c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-format.sxg
@@ -0,0 +1 @@
+This is an invalid Signed Exchange.
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxg
new file mode 100644
index 0000000000..95d358245c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-integrity-header.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-utf8-inner-url.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-utf8-inner-url.sxg
new file mode 100644
index 0000000000..65357e14ac
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-utf8-inner-url.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxg
new file mode 100644
index 0000000000..62e88d6386
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location-cert-on-alt-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location-cert-on-alt-origin.sxg
new file mode 100644
index 0000000000..a2ddc77951
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location-cert-on-alt-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location.sxg
new file mode 100644
index 0000000000..1678b751bc
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-location.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg
new file mode 100644
index 0000000000..0c6dce01da
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-navigation-timing.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-navigation-timing.sxg
new file mode 100644
index 0000000000..56a90d5125
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-navigation-timing.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-noncacheable.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-noncacheable.sxg
new file mode 100644
index 0000000000..88439982f6
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-noncacheable.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-prefetch-test.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-prefetch-test.sxg
new file mode 100644
index 0000000000..f452270c5b
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-prefetch-test.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-remote-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-remote-origin.sxg
new file mode 100644
index 0000000000..00aa755efc
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-remote-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-same-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-same-origin.sxg
new file mode 100644
index 0000000000..cc7793efa2
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-referrer-same-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg
new file mode 100644
index 0000000000..ace89dde64
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg.sub.headers b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg.sub.headers
new file mode 100644
index 0000000000..8f1b47ef06
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg.sub.headers
@@ -0,0 +1 @@
+Link: <https://{{hosts[alt][]}}:{{ports[https][0]}}/signed-exchange/resources/sxg/sxg-subresource-script.sxg>;rel=alternate;type="application/signed-exchange;v=b3";anchor="https://127.0.0.1:8444/signed-exchange/resources/sxg-subresource-script.js";
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-script.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-script.sxg
new file mode 100644
index 0000000000..fe1bd97645
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource-script.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg
new file mode 100644
index 0000000000..97823ee8f7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg.sub.headers b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg.sub.headers
new file mode 100644
index 0000000000..8bc3938df8
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-subresource.sxg.sub.headers
@@ -0,0 +1 @@
+Link: <https://{{host}}:{{ports[https][0]}}/signed-exchange/resources/sxg/sxg-subresource-script.sxg>;rel=alternate;type="application/signed-exchange;v=b3";anchor="https://127.0.0.1:8444/signed-exchange/resources/sxg-subresource-script.js";
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-utf8-inner-url.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-utf8-inner-url.sxg
new file mode 100644
index 0000000000..3edf285f1b
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-utf8-inner-url.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg
new file mode 100644
index 0000000000..294f97b097
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long-cert-on-alt-origin.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxg
new file mode 100644
index 0000000000..e90d9bc66d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-validity-period-too-long.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-match.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-match.sxg
new file mode 100644
index 0000000000..aed8bd175d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-match.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-mismatch.sxg b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-mismatch.sxg
new file mode 100644
index 0000000000..ae96b7213f
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/resources/sxg/sxg-variants-mismatch.sxg
Binary files differ
diff --git a/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html b/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html
new file mode 100644
index 0000000000..2b76a70dc9
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register-after-fallback.tentative.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Service worker registration after fallback</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl =
+ get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/sxg/register-sw-after-fallback.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location,
+ get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/register-sw-after-fallback.html');
+ assert_true(message.is_fallback);
+
+ assert_equals(message.err, undefined);
+ assert_equals(message.iframe_body, 'Generated by service worker');
+}, 'Service worker registration after fallback');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register.tentative.https.html b/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register.tentative.https.html
new file mode 100644
index 0000000000..ad21ebb20d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/service-workers/sxg-sw-register.tentative.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Service worker registration from signed exchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl =
+ get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/sxg/register-sw-from-sxg.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location,
+ get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/register-sw-from-sxg.html');
+ assert_false(message.is_fallback);
+
+ assert_equals(message.err, undefined);
+ assert_equals(message.iframe_body, 'Generated by service worker');
+}, 'Service worker registration from signed exchange');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html b/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html
new file mode 100644
index 0000000000..a7f42d9461
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<title>Subresource signed exchange prefetch.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/network-error-logging/support/nel.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+nel_iframe_test(async t => {
+ const alt_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
+ const test_origin = get_host_info().HTTPS_ORIGIN;
+ await loadResourceWithBasicPolicyInIframe();
+ const iframe_path =
+ alt_origin +
+ '/signed-exchange/resources/sxg-subresource-mismatch-iframe.html';
+ const wait_message = (new Promise((resolve) => {
+ const on_message = (event) => {
+ window.removeEventListener('message', on_message);
+ resolve(event.data);
+ };
+ window.addEventListener('message', on_message);
+ }));
+ withIframe(iframe_path);
+ const message = await wait_message;
+ assert_equals(message, 'from server');
+ const cert_url = test_origin + '/signed-exchange/resources/127.0.0.1.sxg.pem.cbor';
+
+ const main_outer_url = alt_origin + '/signed-exchange/resources/sxg/sxg-subresource-header-integrity-mismatch.sxg';
+ const main_inner_url = innerURLOrigin() + '/signed-exchange/resources/sxg-subresource-sxg.html';
+ const sub_outer_url = alt_origin + '/signed-exchange/resources/sxg/sxg-subresource-script.sxg';
+ const sub_inner_url = innerURLOrigin() + '/signed-exchange/resources/sxg-subresource-script.js';
+ const iframe_url = alt_origin + '/signed-exchange/resources/sxg-subresource-mismatch-iframe.html';
+ assert_true(await reportsExist([
+ // Normal NEL report for the iframe's HTML.
+ {
+ url: iframe_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: location.origin + '/',
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ // Normal NEL report for the main resource signed exchange.
+ {
+ url: main_outer_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: iframe_url,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ // Signed Exchange NEL report for the main resource signed exchange.
+ {
+ url: main_outer_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: iframe_url,
+ sxg: {
+ outer_url: main_outer_url,
+ inner_url: main_inner_url,
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ // Signed Exchange NEL report for the subresource signed exchange header
+ // integrity mismatch.
+ {
+ url: sub_outer_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "sxg.header_integrity_mismatch",
+ status_code: 200,
+ referrer: main_outer_url,
+ sxg: {
+ outer_url: sub_outer_url,
+ inner_url: sub_inner_url,
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ // Normal NEL report for the main resource signed exchange.
+ {
+ url: sub_outer_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "application",
+ type: "ok",
+ status_code: 200,
+ referrer: iframe_url,
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ // Signed Exchange NEL report for the sub resource signed exchange.
+ {
+ url: sub_outer_url,
+ user_agent: navigator.userAgent,
+ type: "network-error",
+ body: {
+ phase: "sxg",
+ type: "ok",
+ status_code: 200,
+ referrer: iframe_url,
+ sxg: {
+ outer_url: sub_outer_url,
+ inner_url: sub_inner_url,
+ cert_url: [cert_url]
+ }
+ },
+ metadata: {
+ content_type: "application/reports+json",
+ },
+ },
+ ]));
+}, 'Subresource signed exchange prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource.tentative.html b/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource.tentative.html
new file mode 100644
index 0000000000..8ca12b4cbc
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/subresource/sxg-subresource.tentative.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Subresource signed exchange prefetch.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="../resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const iframe_path = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg-subresource-iframe.html';
+ const wait_message = (new Promise((resolve) => {
+ const on_message = (event) => {
+ window.removeEventListener('message', on_message);
+ resolve(event.data);
+ };
+ window.addEventListener('message', on_message);
+ }));
+ withIframe(iframe_path);
+ const message = await wait_message;
+ assert_equals(message, 'from signed exchange');
+}, 'Subresource signed exchange prefetch.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-data-cert-url.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-data-cert-url.tentative.html
new file mode 100644
index 0000000000..0d6bd5602e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-data-cert-url.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange using data URL for cert-url</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-data-cert-url.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+}, 'SignedHTTPExchange using data URL for cert-url');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-double-prefetch.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-double-prefetch.tentative.html
new file mode 100644
index 0000000000..d682741744
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-double-prefetch.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Prefetching double SignedHTTPExchange files must not crash</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+function addPrefetch(url) {
+ let link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = url;
+ document.body.appendChild(link);
+}
+promise_test(async (t) => {
+ const sxg1_url =
+ get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg?1';
+ const sxg2_url =
+ get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg?2';
+ addPrefetch(sxg1_url);
+ addPrefetch(sxg2_url);
+ await new Promise(resolve => {
+ setInterval(() => {
+ const entries = performance.getEntriesByType("resource");
+ let hit_count = 0;
+ for (let i = 0; i < entries.length; ++i) {
+ const entry = entries[i];
+ if (entry.name == sxg1_url || entry.name == sxg2_url) {
+ if (++hit_count == 2)
+ resolve();
+ }
+ }
+ }, 100);
+ });
+}, 'Prefetching double SignedHTTPExchange files must not crash');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-fallback-with-fragment.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-fallback-with-fragment.tentative.html
new file mode 100644
index 0000000000..aae8fa8bd1
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-fallback-with-fragment.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Fallback redirect of SignedHTTPExchange should preserve URL fragment</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxg#fragment';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html#fragment');
+ assert_true(message.is_fallback);
+}, 'Fallback redirect of SignedHTTPExchange should preserve URL fragment');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-hsts.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-hsts.tentative.html
new file mode 100644
index 0000000000..6024e2879e
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-hsts.tentative.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Loading SignedHTTPExchange with strict-transport-security must fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/sxg/sxg-hsts.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ const innerURL = innerURLOrigin() +
+ '/signed-exchange/resources/inner-url.html';
+ assert_equals(message.location, innerURL);
+ assert_true(message.is_fallback);
+}, 'Loading SignedHTTPExchange with an uncached header ' +
+ 'Strict-Transport-Security must fail and fallback redirect.');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-inner-url-bom.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-inner-url-bom.tentative.html
new file mode 100644
index 0000000000..be2d7e5022
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-inner-url-bom.tentative.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange's fallback url must not have UTF-8 BOM</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ try {
+ const sxgUrl = get_host_info().HTTP_ORIGIN + '/signed-exchange/resources/sxg/sxg-inner-url-bom.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ if (message.is_fallback) {
+ assert_unreached('Fallback redirect should not have happened');
+ } else {
+ assert_unreached('SXG should not have loaded');
+ }
+ } catch (e) {
+ assert_equals(e, 'timeout');
+ }
+}, "SignedHTTPExchange's fallback url must not have UTF-8 BOM");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-invalid-utf8-inner-url.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-invalid-utf8-inner-url.tentative.html
new file mode 100644
index 0000000000..7512d639e8
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-invalid-utf8-inner-url.tentative.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange's fallback url must not have invalid UTF-8 sequence</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ try {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-invalid-utf8-inner-url.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ if (message.is_fallback) {
+ assert_unreached('Fallback redirect should not have happened');
+ } else {
+ assert_unreached('SXG should not have loaded');
+ }
+ } catch (e) {
+ assert_equals(e, 'timeout');
+ }
+}, "SignedHTTPExchange's fallback url must not have invalid UTF-8 sequence");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-invalid-validity-url.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-invalid-validity-url.tentative.html
new file mode 100644
index 0000000000..bb027b1669
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-invalid-validity-url.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Loading SignedHTTPExchange which validity URL is different origin from
+request URL must fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-invalid-validity-url.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+}, 'Loading SignedHTTPExchange which validity URL is different origin from ' +
+ 'request URL must fail');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-location-fragment.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-location-fragment.tentative.html
new file mode 100644
index 0000000000..92e1efbc20
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-location-fragment.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Navigating to a Signed Exchange should preserve URL fragment</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg#fragment';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html#fragment');
+ assert_false(message.is_fallback);
+}, 'Navigating to a Signed Exchange should preserve URL fragment');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-location.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-location.tentative.html
new file mode 100644
index 0000000000..17ca0768d6
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-location.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Location of SignedHTTPExchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+}, 'Location of SignedHTTPExchange');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-merkle-integrity-error.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-merkle-integrity-error.tentative.html
new file mode 100644
index 0000000000..a5c4a2f7ee
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-merkle-integrity-error.tentative.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange with payload integrity error</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ try {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ if (message.is_fallback) {
+ assert_unreached('Fallback redirect should not have happened');
+ } else {
+ assert_unreached('SXG should not have loaded');
+ }
+ } catch (e) {
+ assert_equals(e, 'timeout');
+ }
+}, "SignedHTTPExchange with payload integrity error");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-navigation-timing.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-navigation-timing.tentative.html
new file mode 100644
index 0000000000..b3f088241f
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-navigation-timing.tentative.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Navigation timing of SignedHTTPExchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-navigation-timing.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_false(message.is_fallback);
+
+ let timing = JSON.parse(message.timing);
+ let originalContent = await fetch('resources/sxg-navigation-timing.html').then(resp => resp.arrayBuffer());
+
+ assert_equals(timing.decodedBodySize, originalContent.byteLength);
+ assert_equals(timing.encodedBodySize, computeMiceLength(originalContent.byteLength, 100));
+ // TODO(https://crbug.com/928589): Test other fields too.
+}, 'Navigation timing of SignedHTTPExchange');
+
+// Returns content length after MI encode.
+function computeMiceLength(len, recordSize) {
+ const recordSizeLen = 8;
+ const sha256DigestLength = 32;
+ return recordSizeLen + len + Math.floor(len / recordSize) * sha256DigestLength;
+}
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-non-secure-origin.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-non-secure-origin.tentative.html
new file mode 100644
index 0000000000..84938da76d
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-non-secure-origin.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Loading SignedHTTPExchange from non secure origin must fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTP_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+}, 'Loading SignedHTTPExchange from non secure origin must fail');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-noncacheable.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-noncacheable.tentative.html
new file mode 100644
index 0000000000..1315360745
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-noncacheable.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Loading SignedHTTPExchange with non-cacheable response must fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-noncacheable.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+}, 'Loading SignedHTTPExchange with non-cacheable response must fail');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-prefetch-merkle-integrity-error.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-prefetch-merkle-integrity-error.tentative.html
new file mode 100644
index 0000000000..2086c38545
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-prefetch-merkle-integrity-error.tentative.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Prefetching SignedHTTPExchange with payload integrity error should fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-merkle-integrity-error.sxg';
+ await new Promise(resolve => {
+ const link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = sxgUrl;
+ link.addEventListener('error', t.step_func(() => {
+ resolve();
+ }));
+ link.addEventListener('load', t.step_func(() => {
+ assert_unreached('Prefetch should fail');
+ }));
+ document.body.appendChild(link);
+ });
+}, "Prefetching SignedHTTPExchange with payload integrity error should fail");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-prefetch-resource-timing.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-prefetch-resource-timing.tentative.html
new file mode 100644
index 0000000000..5b60ab9e1a
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-prefetch-resource-timing.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title>Resource Timing for prefetched SignedHTTPExchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+function addPrefetch(url) {
+ let link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = url;
+ document.body.appendChild(link);
+}
+
+async function waitForPerformanceEntries(url) {
+ let entries = performance.getEntriesByName(url);
+ if (entries.length > 0) {
+ return entries;
+ }
+ return new Promise((resolve) => {
+ new PerformanceObserver((list) => {
+ const entries = list.getEntriesByName(url);
+ if (entries.length > 0) {
+ resolve(entries);
+ }
+ }).observe({ entryTypes: ['resource'] });
+ });
+}
+
+promise_test(async (t) => {
+ const url = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-location.sxg';
+ addPrefetch(url);
+ return waitForPerformanceEntries(url).then((entries) => {
+ assert_equals(entries.length, 1, "Should have only one resource timing entry");
+ const e = entries[0];
+ assert_greater_than(e.duration, 0, "duration should be greater than 0");
+ assert_greater_than(e.fetchStart, 0, "fetchStart should be greater than 0");
+ assert_greater_than(e.responseEnd, e.fetchStart,
+ "responseEnd should be greater than fetchStart");
+ });
+}, 'Resource Timing for prefetched SignedHTTPExchange');
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-prefetch.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-prefetch.tentative.https.html
new file mode 100644
index 0000000000..a6e55567e0
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-prefetch.tentative.https.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>Prefetched signed exchange and certificate must not be fetched again</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/utils.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const id = token();
+ const sxgUrl = get_host_info().HTTPS_REMOTE_ORIGIN + '/signed-exchange/resources/prefetch-test-sxg.py?id=' + id;
+
+ await new Promise(resolve => {
+ const link = document.createElement('link');
+ link.rel = 'prefetch';
+ link.href = sxgUrl;
+ link.as = 'document';
+ link.addEventListener('error', t.step_func(() => {
+ assert_unreached('Prefetch should not fail');
+ }));
+ link.addEventListener('load', t.step_func(() => {
+ resolve();
+ }));
+ document.body.appendChild(link);
+ });
+ const message_promise = new Promise((resolve) => {
+ window.addEventListener('message', (event) => {
+ resolve(event.data);
+ }, false);
+ });
+ const win = window.open(sxgUrl, "_blank");
+ const message = await message_promise;
+ win.close();
+ assert_equals(message, 'loaded');
+}, 'Prefetched signed exchange and certificate must not be fetched again.');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-referrer-policy-header.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-referrer-policy-header.tentative.https.html
new file mode 100644
index 0000000000..5dff6af8cb
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-referrer-policy-header.tentative.https.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>Referrer-Policy header in outer SXG response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+(() => {
+ const SAME_ORIGIN = get_host_info().HTTPS_ORIGIN;
+ const SAME_ORIGIN_SXG = 'sxg-referrer-same-origin.sxg';
+ const TEST_CASES = [
+ // Referrer-Policy header in outer SXG response.
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG + '?pipe=header(Referrer-Policy,no-referrer)',
+ referrerPolicy: undefined,
+ expectedReferrer: ''
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG +
+ '?pipe=header(Referrer-Policy,no-referrer-when-downgrade)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG + '?pipe=header(Referrer-Policy,origin)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG + '?pipe=header(Referrer-Policy,same-origin)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG + '?pipe=header(Referrer-Policy,strict-origin)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG +
+ '?pipe=header(Referrer-Policy,strict-origin-when-cross-origin)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG + '?pipe=header(Referrer-Policy,unsafe-url)',
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.href
+ },
+ ];
+ runReferrerTests(TEST_CASES);
+})();
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-remote-logical.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-remote-logical.tentative.https.html
new file mode 100644
index 0000000000..67de083d27
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-remote-logical.tentative.https.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>Referrer of SignedHTTPExchange(physical:remote origin, logical:remote origin)</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+(() => {
+ const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
+ const REMOTE_ORIGIN_SXG = 'sxg-referrer-remote-origin.sxg';
+ const TEST_CASES = [
+ // Physical origin = remote origin. Logical origin = remote origin.
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer',
+ expectedReferrer: ''
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer-when-downgrade',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'same-origin',
+ expectedReferrer: ''
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin-when-cross-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'unsafe-url',
+ expectedReferrer: document.location.href
+ },
+ ];
+ runReferrerTests(TEST_CASES);
+})();
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-same-logical.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-same-logical.tentative.https.html
new file mode 100644
index 0000000000..4d8aff8081
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-referrer-remote-physical-same-logical.tentative.https.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>Referrer of SignedHTTPExchange(physical:remote origin, logical:same origin)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+(() => {
+ const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
+ const SAME_ORIGIN_SXG = 'sxg-referrer-same-origin.sxg';
+ const TEST_CASES = [
+ // Physical origin = remote origin. Logical origin = same origin.
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer',
+ expectedReferrer: ''
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer-when-downgrade',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'same-origin',
+ expectedReferrer: ''
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin-when-cross-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: REMOTE_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'unsafe-url',
+ expectedReferrer: document.location.href
+ },
+ ];
+ runReferrerTests(TEST_CASES);
+})();
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-remote-logical.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-remote-logical.tentative.https.html
new file mode 100644
index 0000000000..3ba597ed49
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-remote-logical.tentative.https.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>Referrer of SignedHTTPExchange(physical:same origin, logical:remote origin)</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+(() => {
+ const SAME_ORIGIN = get_host_info().HTTPS_ORIGIN;
+ const REMOTE_ORIGIN_SXG = 'sxg-referrer-remote-origin.sxg';
+ const TEST_CASES = [
+ // Physical origin = same origin. Logical origin = remote origin.
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer',
+ expectedReferrer: ''
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer-when-downgrade',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'same-origin',
+ expectedReferrer: ''
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin-when-cross-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: REMOTE_ORIGIN_SXG,
+ referrerPolicy: 'unsafe-url',
+ expectedReferrer: document.location.href
+ },
+ ];
+ runReferrerTests(TEST_CASES);
+})();
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-same-logical.tentative.https.html b/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-same-logical.tentative.https.html
new file mode 100644
index 0000000000..88917167b9
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-referrer-same-physical-same-logical.tentative.https.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>Referrer of SignedHTTPExchange(physical:same origin, logical:same origin)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+(() => {
+ const SAME_ORIGIN = get_host_info().HTTPS_ORIGIN;
+ const SAME_ORIGIN_SXG = 'sxg-referrer-same-origin.sxg';
+ const TEST_CASES = [
+ // Physical origin = same origin. Logical origin = same origin.
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: undefined,
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer',
+ expectedReferrer: ''
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'no-referrer-when-downgrade',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'same-origin',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin',
+ expectedReferrer: document.location.origin + '/'
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'strict-origin-when-cross-origin',
+ expectedReferrer: document.location.href
+ },
+ {
+ origin: SAME_ORIGIN,
+ sxg: SAME_ORIGIN_SXG,
+ referrerPolicy: 'unsafe-url',
+ expectedReferrer: document.location.href
+ },
+ ];
+ runReferrerTests(TEST_CASES);
+})();
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-utf8-inner-url.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-utf8-inner-url.tentative.html
new file mode 100644
index 0000000000..85670a786a
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-utf8-inner-url.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange with UTF-8 inner URL</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-utf8-inner-url.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, new URL(innerURLOrigin() + '/signed-exchange/resources/\uD83C\uDF10\uD83D\uDCE6.html').href);
+ assert_false(message.is_fallback);
+}, 'SignedHTTPExchange with UTF-8 inner URL');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-variants-match.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-variants-match.tentative.html
new file mode 100644
index 0000000000..21d1b80d3c
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-variants-match.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange should be loaded if Variants/Variant-Key match the request</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-variants-match.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_false(message.is_fallback);
+}, 'SignedHTTPExchange should be loaded if Variants/Variant-Key match the request');
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-variants-mismatch.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-variants-mismatch.tentative.html
new file mode 100644
index 0000000000..b57ec81926
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-variants-mismatch.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>SignedHTTPExchange should fallback if Variants/Variant-Key don't match the request</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg/sxg-variants-mismatch.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
+ assert_true(message.is_fallback);
+}, "SignedHTTPExchange should fallback if Variants/Variant-Key don't match the request");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/signed-exchange/sxg-version1b2.tentative.html b/testing/web-platform/tests/signed-exchange/sxg-version1b2.tentative.html
new file mode 100644
index 0000000000..43b340dbb7
--- /dev/null
+++ b/testing/web-platform/tests/signed-exchange/sxg-version1b2.tentative.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Loading SignedHTTPExchange of unsupported version must fail</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<p>Note: This test FAILs if your browser supports Signed Exchange version 1b2.</p>
+<script>
+promise_test(async (t) => {
+ const sxgUrl = get_host_info().HTTPS_ORIGIN +
+ '/signed-exchange/resources/sxg-version1b2.sxg';
+ const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+ const innerURL = innerURLOrigin() +
+ '/signed-exchange/resources/inner-url.html';
+ assert_equals(message.location, innerURL);
+ assert_true(message.is_fallback);
+}, 'Loading SignedHTTPExchange of unsupported version must fail and fallback redirect.');
+</script>
+</body>