Make partitioned service workers only send cookies from their partition

Before this change, workers would use partitioned cookies from their own site's partition in network requests from service workers. This could allow sites to join state across different partitions.

For first-party partitioned/unpartitioned workers, the resulting IsolationInfo's top-level and current origin is the worker origin. Site for cookies ends up being the site of the worker origin.

For third-party partitioned workers, the top-level origin is derived from StorageKey's top-frame site. In these contexts, SFC is null.

This CL does *not* ensure partitioning bounds for cookies sent in service worker script requests. I will be adding that in a follow-up CL.

Bug: 1147281,1427879
Change-Id: I1a47f2ca4927bfd39bc8d0c159c6b5b0a6114d3b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4494754
Reviewed-by: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Commit-Queue: Dylan Cutler <dylancutler@google.com>
Cr-Commit-Position: refs/heads/main@{#1139255}
diff --git a/service-workers/service-worker/partitioned-cookies.tentative.https.html b/service-workers/service-worker/partitioned-cookies.tentative.https.html
index 6744edc..ab66701 100644
--- a/service-workers/service-worker/partitioned-cookies.tentative.https.html
+++ b/service-workers/service-worker/partitioned-cookies.tentative.https.html
@@ -59,7 +59,7 @@
   document.cookie = '__Host-partitioned=123; Secure; Path=/; SameSite=None; Partitioned;';
   assert_true(document.cookie.includes('__Host-partitioned=123'));
 
-  // Test that the partitioned cookie is available to this worker.
+  // Test that the partitioned cookie is available to this worker via HTTP.
   wait_promise = new Promise(resolve => {
     resolve_wait_promise = resolve;
   });
@@ -67,10 +67,23 @@
     got = ev.data;
     resolve_wait_promise();
   };
-  filtered_registrations[0].active.postMessage({type: 'echo_cookies'});
+  filtered_registrations[0].active.postMessage({type: 'echo_cookies_http'});
   await wait_promise;
   assert_true(got.ok, 'Get cookies');
-  assert_true(got.cookies.includes('__Host-partitioned'), 'Can access partitioned cookie');
+  assert_true(got.cookies.includes('__Host-partitioned'), 'Can access partitioned cookie via HTTP');
+
+  // Test that the partitioned cookie is available to this worker via CookieStore API.
+  wait_promise = new Promise(resolve => {
+    resolve_wait_promise = resolve;
+  });
+  on_message = ev => {
+    got = ev.data;
+    resolve_wait_promise();
+  };
+  filtered_registrations[0].active.postMessage({type: 'echo_cookies_js'});
+  await wait_promise;
+  assert_true(got.ok, 'Get cookies');
+  assert_true(got.cookies.includes('__Host-partitioned'), 'Can access partitioned cookie via JS');
 
   const popup = window.open(
       new URL(
diff --git a/service-workers/service-worker/resources/partitioned-cookies-3p-credentialless-frame.html b/service-workers/service-worker/resources/partitioned-cookies-3p-credentialless-frame.html
index ff24bf3..3fdf937 100644
--- a/service-workers/service-worker/resources/partitioned-cookies-3p-credentialless-frame.html
+++ b/service-workers/service-worker/resources/partitioned-cookies-3p-credentialless-frame.html
@@ -50,7 +50,7 @@
   await wait_promise;
   assert_true(got.ok, 'Message passing');
 
-  // Test that the partitioned cookie is available to this worker.
+  // Test that the partitioned cookie is available to this worker via CookieStore API.
   wait_promise = new Promise(resolve => {
     resolve_wait_promise = resolve;
   });
@@ -58,7 +58,7 @@
     got = ev.data;
     resolve_wait_promise();
   };
-  filtered_registrations[0].active.postMessage({type: 'echo_cookies'});
+  filtered_registrations[0].active.postMessage({type: 'echo_cookies_js'});
   await wait_promise;
   assert_true(got.ok, 'Get cookies');
   assert_true(got.cookies.includes('__Host-partitioned'), 'Can access partitioned cookie');;
diff --git a/service-workers/service-worker/resources/partitioned-cookies-3p-frame.html b/service-workers/service-worker/resources/partitioned-cookies-3p-frame.html
index d3962d2..6a8ed6c 100644
--- a/service-workers/service-worker/resources/partitioned-cookies-3p-frame.html
+++ b/service-workers/service-worker/resources/partitioned-cookies-3p-frame.html
@@ -46,7 +46,7 @@
   await wait_promise;
   assert_true(got.ok, 'Message passing');
 
-  // Test that the partitioned cookie is not available to this worker.
+  // Test that the partitioned cookie is not available to this worker via HTTP.
   wait_promise = new Promise(resolve => {
     resolve_wait_promise = resolve;
   });
@@ -54,7 +54,22 @@
     got = ev.data;
     resolve_wait_promise();
   };
-  filtered_registrations[0].active.postMessage({type: 'echo_cookies'});
+  filtered_registrations[0].active.postMessage({type: 'echo_cookies_http'});
+  await wait_promise;
+  assert_true(got.ok, 'Get cookies');
+  assert_false(
+      got.cookies.includes('__Host-partitioned'),
+      'Worker cannot access partitioned cookie');
+
+  // Test that the partitioned cookie is not available to this worker via CookieStore API.
+  wait_promise = new Promise(resolve => {
+    resolve_wait_promise = resolve;
+  });
+  on_message = ev => {
+    got = ev.data;
+    resolve_wait_promise();
+  };
+  filtered_registrations[0].active.postMessage({type: 'echo_cookies_js'});
   await wait_promise;
   assert_true(got.ok, 'Get cookies');
   assert_false(
diff --git a/service-workers/service-worker/resources/partitioned-cookies-3p-sw.js b/service-workers/service-worker/resources/partitioned-cookies-3p-sw.js
index 2f54a98..bc2a283 100644
--- a/service-workers/service-worker/resources/partitioned-cookies-3p-sw.js
+++ b/service-workers/service-worker/resources/partitioned-cookies-3p-sw.js
@@ -6,8 +6,10 @@
   switch (event.data.type) {
     case 'test_message':
       return onTestMessage(event);
-    case 'echo_cookies':
-      return onEchoCookies(event);
+    case 'echo_cookies_http':
+      return onEchoCookiesHttp(event);
+    case 'echo_cookies_js':
+      return onEchoCookiesJs(event);
     default:
       return;
   }
@@ -18,8 +20,19 @@
   event.source.postMessage({ok: true});
 }
 
+async function onEchoCookiesHttp(event) {
+  try {
+    const resp = await fetch(
+        `${self.origin}/cookies/resources/list.py`, {credentials: 'include'});
+    const cookies = await resp.json();
+    event.source.postMessage({ok: true, cookies: Object.keys(cookies)});
+  } catch (err) {
+    event.source.postMessage({ok: false});
+  }
+}
+
 // echo_cookies returns the names of all of the cookies available to the worker.
-async function onEchoCookies(event) {
+async function onEchoCookiesJs(event) {
   try {
     const cookie_objects = await self.cookieStore.getAll();
     const cookies = cookie_objects.map(c => c.name);
diff --git a/service-workers/service-worker/resources/partitioned-cookies-sw.js b/service-workers/service-worker/resources/partitioned-cookies-sw.js
index 2f54a98..bc2a283 100644
--- a/service-workers/service-worker/resources/partitioned-cookies-sw.js
+++ b/service-workers/service-worker/resources/partitioned-cookies-sw.js
@@ -6,8 +6,10 @@
   switch (event.data.type) {
     case 'test_message':
       return onTestMessage(event);
-    case 'echo_cookies':
-      return onEchoCookies(event);
+    case 'echo_cookies_http':
+      return onEchoCookiesHttp(event);
+    case 'echo_cookies_js':
+      return onEchoCookiesJs(event);
     default:
       return;
   }
@@ -18,8 +20,19 @@
   event.source.postMessage({ok: true});
 }
 
+async function onEchoCookiesHttp(event) {
+  try {
+    const resp = await fetch(
+        `${self.origin}/cookies/resources/list.py`, {credentials: 'include'});
+    const cookies = await resp.json();
+    event.source.postMessage({ok: true, cookies: Object.keys(cookies)});
+  } catch (err) {
+    event.source.postMessage({ok: false});
+  }
+}
+
 // echo_cookies returns the names of all of the cookies available to the worker.
-async function onEchoCookies(event) {
+async function onEchoCookiesJs(event) {
   try {
     const cookie_objects = await self.cookieStore.getAll();
     const cookies = cookie_objects.map(c => c.name);