Set network_isolation_key for signed exchange cert fetch (#21511)

Currently network_isolation_key is not set for signed exchange cert fetch.
So, even if the signed exchange and the certificate were prefetched,
the certificate is fetched again while navigation when
SplitCacheByNetworkIsolationKey is enabled.

Bug=1047110

Change-Id: I524df1da097c6f544777f20cca5a3e53246693cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2029564
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737251}

Co-authored-by: Tsuyoshi Horo <horo@google.com>
diff --git a/signed-exchange/resources/generate-test-sxgs.sh b/signed-exchange/resources/generate-test-sxgs.sh
index 81a5e04..7214fc1 100755
--- a/signed-exchange/resources/generate-test-sxgs.sh
+++ b/signed-exchange/resources/generate-test-sxgs.sh
@@ -576,4 +576,22 @@
   -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"
 
+
+# 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/signed-exchange/resources/prefetch-test-cert.py b/signed-exchange/resources/prefetch-test-cert.py
new file mode 100644
index 0000000..7aec0aa
--- /dev/null
+++ b/signed-exchange/resources/prefetch-test-cert.py
@@ -0,0 +1,17 @@
+import os
+
+
+def main(request, response):
+    stash_id = request.GET.first("id")
+    if request.server.stash.take(stash_id) is not None:
+        response.status = (404, "Not Found")
+        response.headers.set("Content-Type", "text/plain")
+        return "not found"
+    request.server.stash.put(stash_id, True)
+
+    path = os.path.join(os.path.dirname(__file__), "127.0.0.1.sxg.pem.cbor")
+    body = open(path, "rb").read()
+
+    response.headers.set("Content-Type", "application/cert-chain+cbor")
+    response.headers.set("Cache-Control", "public, max-age=600")
+    return body
diff --git a/signed-exchange/resources/prefetch-test-sxg.py b/signed-exchange/resources/prefetch-test-sxg.py
new file mode 100644
index 0000000..822273e
--- /dev/null
+++ b/signed-exchange/resources/prefetch-test-sxg.py
@@ -0,0 +1,19 @@
+import os
+
+
+def main(request, response):
+    stash_id = request.GET.first("id")
+    if request.server.stash.take(stash_id) is not None:
+        response.status = (404, "Not Found")
+        response.headers.set("Content-Type", "text/plain")
+        return "not found"
+    request.server.stash.put(stash_id, True)
+
+    path = os.path.join(os.path.dirname(__file__), "sxg", "sxg-prefetch-test.sxg")
+    body = open(path, "rb").read()
+
+    response.headers.set("Content-Type", "application/signed-exchange;v=b3")
+    response.headers.set("X-Content-Type-Options", "nosniff")
+    response.headers.set("Cache-Control", "public, max-age=600")
+
+    return body.replace('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', stash_id)
diff --git a/signed-exchange/resources/sxg-prefetch-test.html b/signed-exchange/resources/sxg-prefetch-test.html
new file mode 100644
index 0000000..5383a4a
--- /dev/null
+++ b/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/signed-exchange/resources/sxg/sxg-prefetch-test.sxg b/signed-exchange/resources/sxg/sxg-prefetch-test.sxg
new file mode 100644
index 0000000..f452270
--- /dev/null
+++ b/signed-exchange/resources/sxg/sxg-prefetch-test.sxg
Binary files differ
diff --git a/signed-exchange/sxg-prefetch.tentative.https.html b/signed-exchange/sxg-prefetch.tentative.https.html
new file mode 100644
index 0000000..a6e5556
--- /dev/null
+++ b/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>