Move more Signed Exchange layout tests to WPT

Bug: 895723
Change-Id: If7918de7e3717b01619ee21fa87eeaffb971287c
Reviewed-on: https://chromium-review.googlesource.com/c/1292661
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Reviewed-by: Tsuyoshi Horo <horo@chromium.org>
Commit-Queue: Kunihiko Sakamoto <ksakamoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601828}
diff --git a/signed-exchange/fallback-to-another-sxg.tentative.html b/signed-exchange/fallback-to-another-sxg.tentative.html
new file mode 100644
index 0000000..0dbbd4a
--- /dev/null
+++ b/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/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/signed-exchange/nested-sxg.tentative.html b/signed-exchange/nested-sxg.tentative.html
new file mode 100644
index 0000000..b661a02
--- /dev/null
+++ b/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/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/signed-exchange/resources/failure.html b/signed-exchange/resources/failure.html
new file mode 100644
index 0000000..1071f08
--- /dev/null
+++ b/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/signed-exchange/resources/fallback-to-another-sxg.sxg b/signed-exchange/resources/fallback-to-another-sxg.sxg
new file mode 100644
index 0000000..0a60182
--- /dev/null
+++ b/signed-exchange/resources/fallback-to-another-sxg.sxg
Binary files differ
diff --git a/signed-exchange/resources/fallback-to-another-sxg.sxg.headers b/signed-exchange/resources/fallback-to-another-sxg.sxg.headers
new file mode 100644
index 0000000..ab188e5
--- /dev/null
+++ b/signed-exchange/resources/fallback-to-another-sxg.sxg.headers
@@ -0,0 +1 @@
+Content-Type: application/signed-exchange;v=b2
diff --git a/signed-exchange/resources/generate-test-sxgs.sh b/signed-exchange/resources/generate-test-sxgs.sh
index 551de1d..3552729 100755
--- a/signed-exchange/resources/generate-test-sxgs.sh
+++ b/signed-exchange/resources/generate-test-sxgs.sh
@@ -1,7 +1,12 @@
 #!/bin/sh
+
 certfile=127.0.0.1.sxg.pem
 keyfile=127.0.0.1.sxg.key
-host=127.0.0.1
+inner_url_origin=https://127.0.0.1:8444
+# TODO: Stop hard-coding "web-platform.test" in certUrl when generating
+# Signed Exchanges on the fly.
+cert_url_origin=https://web-platform.test:8444
+sxg_content_type='content-type: application/signed-exchange;v=b2'
 
 set -e
 
@@ -18,20 +23,65 @@
 echo -n OCSP >$tmpdir/ocsp
 gen-certurl -pem $certfile -ocsp $tmpdir/ocsp > $certfile.cbor
 
-# TODO: Stop hard-coding "web-platform.test" in certUrl when generating
-# Signed Exchanges on the fly.
+# A valid Signed Exchange.
 gen-signedexchange \
   -version 1b2 \
-  -uri https://$host/signed-exchange/resources/inner-url.html \
+  -uri $inner_url_origin/signed-exchange/resources/inner-url.html \
   -status 200 \
   -content sxg-location.html \
   -certificate $certfile \
-  -certUrl https://web-platform.test:8444/signed-exchange/resources/$certfile.cbor \
-  -validityUrl https://$host/signed-exchange/resources/resource.validity.msg \
+  -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-location.sxg \
   -miRecordSize 100
 
+# validityUrl is different origin from request URL.
+gen-signedexchange \
+  -version 1b2 \
+  -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-invalid-validity-url.sxg \
+  -miRecordSize 100
+
+# certUrl is 404 and fallback URL is another signed exchange.
+gen-signedexchange \
+  -version 1b2 \
+  -uri $inner_url_origin/signed-exchange/resources/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 fallback-to-another-sxg.sxg \
+  -miRecordSize 100
+
+# Nested signed exchange.
+gen-signedexchange \
+  -version 1b2 \
+  -uri "$inner_url_origin/signed-exchange/resources/inner-url.html?fallback-from-nested-sxg" \
+  -status 200 \
+  -content 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 nested-sxg.sxg \
+  -miRecordSize 100
+
 rm -fr $tmpdir
diff --git a/signed-exchange/resources/inner-url.html b/signed-exchange/resources/inner-url.html
new file mode 100644
index 0000000..628a18a
--- /dev/null
+++ b/signed-exchange/resources/inner-url.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<title>Content of fallback URL</title>
+<script>
+window.addEventListener('message', (event) => {
+  event.data.port.postMessage({location: document.location.href, is_fallback: true});
+}, false);
+</script>
diff --git a/signed-exchange/resources/nested-sxg.sxg b/signed-exchange/resources/nested-sxg.sxg
new file mode 100644
index 0000000..2970e2d
--- /dev/null
+++ b/signed-exchange/resources/nested-sxg.sxg
Binary files differ
diff --git a/signed-exchange/resources/nested-sxg.sxg.headers b/signed-exchange/resources/nested-sxg.sxg.headers
new file mode 100644
index 0000000..ab188e5
--- /dev/null
+++ b/signed-exchange/resources/nested-sxg.sxg.headers
@@ -0,0 +1 @@
+Content-Type: application/signed-exchange;v=b2
diff --git a/signed-exchange/resources/sxg-invalid-validity-url.sxg b/signed-exchange/resources/sxg-invalid-validity-url.sxg
new file mode 100644
index 0000000..3266e7e
--- /dev/null
+++ b/signed-exchange/resources/sxg-invalid-validity-url.sxg
Binary files differ
diff --git a/signed-exchange/resources/sxg-invalid-validity-url.sxg.headers b/signed-exchange/resources/sxg-invalid-validity-url.sxg.headers
new file mode 100644
index 0000000..ab188e5
--- /dev/null
+++ b/signed-exchange/resources/sxg-invalid-validity-url.sxg.headers
@@ -0,0 +1 @@
+Content-Type: application/signed-exchange;v=b2
diff --git a/signed-exchange/resources/sxg-location.sxg b/signed-exchange/resources/sxg-location.sxg
index 5e1ea71..a818541 100644
--- a/signed-exchange/resources/sxg-location.sxg
+++ b/signed-exchange/resources/sxg-location.sxg
Binary files differ
diff --git a/signed-exchange/resources/sxg-util.js b/signed-exchange/resources/sxg-util.js
index 966117d..b31bf98 100644
--- a/signed-exchange/resources/sxg-util.js
+++ b/signed-exchange/resources/sxg-util.js
@@ -34,3 +34,7 @@
     document.head.appendChild(scriptTag);
   });
 }
+
+function innerURLOrigin() {
+  return 'https://127.0.0.1:8444';
+}
diff --git a/signed-exchange/sxg-double-prefetch.tentative.html b/signed-exchange/sxg-double-prefetch.tentative.html
new file mode 100644
index 0000000..a73c18d
--- /dev/null
+++ b/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-location.sxg?1';
+  const sxg2_url =
+      get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/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/signed-exchange/sxg-fallback-with-fragment.tentative.html b/signed-exchange/sxg-fallback-with-fragment.tentative.html
new file mode 100644
index 0000000..6d9c9c5
--- /dev/null
+++ b/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-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/signed-exchange/sxg-invalid-validity-url.tentative.html b/signed-exchange/sxg-invalid-validity-url.tentative.html
new file mode 100644
index 0000000..7264e48
--- /dev/null
+++ b/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-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/signed-exchange/sxg-location-fragment.tentative.html b/signed-exchange/sxg-location-fragment.tentative.html
new file mode 100644
index 0000000..9bfac8a
--- /dev/null
+++ b/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-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/signed-exchange/sxg-location.tentative.html b/signed-exchange/sxg-location.tentative.html
index 01cee93..0d54ea5 100644
--- a/signed-exchange/sxg-location.tentative.html
+++ b/signed-exchange/sxg-location.tentative.html
@@ -9,7 +9,7 @@
 promise_test(async (t) => {
   const sxgUrl = get_host_info().HTTPS_ORIGIN + '/signed-exchange/resources/sxg-location.sxg';
   const message = await openSXGInIframeAndWaitForMessage(t, sxgUrl);
-  assert_equals(message.location, 'https://127.0.0.1/signed-exchange/resources/inner-url.html');
+  assert_equals(message.location, innerURLOrigin() + '/signed-exchange/resources/inner-url.html');
   assert_false(message.is_fallback);
 }, 'Location of SignedHTTPExchange');
 
diff --git a/signed-exchange/sxg-non-secure-origin.tentative.html b/signed-exchange/sxg-non-secure-origin.tentative.html
new file mode 100644
index 0000000..1737029
--- /dev/null
+++ b/signed-exchange/sxg-non-secure-origin.tentative.html
@@ -0,0 +1,20 @@
+<!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) => {
+  try {
+    const sxgUrl = get_host_info().HTTP_ORIGIN + '/signed-exchange/resources/sxg-location.sxg';
+    await openSXGInIframeAndWaitForMessage(t, sxgUrl);
+    assert_unreached('SXG should not have loaded');
+  } catch (e) {
+    assert_equals(e, 'timeout');
+  }
+}, 'Loading SignedHTTPExchange from non secure origin must fail');
+
+</script>
+</body>
diff --git a/signed-exchange/sxg-prefetch-resource-timing.tentative.html b/signed-exchange/sxg-prefetch-resource-timing.tentative.html
new file mode 100644
index 0000000..f0dc477
--- /dev/null
+++ b/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-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>