From 3edd48285e60ad94a7f4bc4a5d7e62f6a064072f Mon Sep 17 00:00:00 2001 From: Ari Chivukula Date: Thu, 1 Feb 2024 11:17:57 -0800 Subject: [PATCH] [SAA] Implementing SharedWorker support (Part 2: Expose same-site cookie IDL) The Storage Access API provides access to unpartitioned cookies in third-party contexts. This CL is part of a series to extend that access to SharedWorkers. Before we actually provide access to SharedWorkers, we need a way for the renderer to limit the scope of SameSite cookies provided to the worker. Normally, a worker with a first-party storage key could access all cookies, but if access is via the SAA handle we want to limit that access to just SameSite: None cookies. This CL is part of a series to allow that limiting ability. For now, we expose the option in IDL but do not implement the change needed to limit cookie access in first-party contexts when the option is set to 'none'. The next CL will implement this limit. Note: The ability to request 'all' in a third-party context is not added here nor will it be added. We verify that an exception is thrown if this is attempted. Explainer: https://privacycg.github.io/saa-non-cookie-storage/shared-workers.html Part 1: Expose same-site cookie IPC Part 2: Expose same-site cookie IDL Part 3: Implement same-site cookie filtering Part 4: Add SharedWorker support to SAA handle Bug: 1484966 Change-Id: I8c56c02025950e119e3967afd49ed684446fd6e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5251551 Reviewed-by: Weizhong Xia Auto-Submit: Ari Chivukula Commit-Queue: Ari Chivukula Reviewed-by: Sun Yueru Reviewed-by: Nate Chapin Cr-Commit-Position: refs/heads/main@{#1255183} --- .../first-party.all.tentative.https.window.js | 19 ++++++++++++ ...st-party.default.tentative.https.window.js | 19 ++++++++++++ ...first-party.none.tentative.https.window.js | 19 ++++++++++++ .../resources/iframe-iframe.html | 31 +++++++++++++++++++ .../resources/iframe.sub.html | 14 +++++++++ workers/same-site-cookies/resources/worker.js | 5 +++ ...rd-party.all.tentative.sub.https.window.js | 24 ++++++++++++++ ...arty.default.tentative.sub.https.window.js | 24 ++++++++++++++ ...d-party.none.tentative.sub.https.window.js | 24 ++++++++++++++ 9 files changed, 179 insertions(+) create mode 100644 workers/same-site-cookies/first-party.all.tentative.https.window.js create mode 100644 workers/same-site-cookies/first-party.default.tentative.https.window.js create mode 100644 workers/same-site-cookies/first-party.none.tentative.https.window.js create mode 100644 workers/same-site-cookies/resources/iframe-iframe.html create mode 100644 workers/same-site-cookies/resources/iframe.sub.html create mode 100644 workers/same-site-cookies/resources/worker.js create mode 100644 workers/same-site-cookies/third-party.all.tentative.sub.https.window.js create mode 100644 workers/same-site-cookies/third-party.default.tentative.sub.https.window.js create mode 100644 workers/same-site-cookies/third-party.none.tentative.sub.https.window.js diff --git a/workers/same-site-cookies/first-party.all.tentative.https.window.js b/workers/same-site-cookies/first-party.all.tentative.https.window.js new file mode 100644 index 00000000000000..d7e5f2ee42ca31 --- /dev/null +++ b/workers/same-site-cookies/first-party.all.tentative.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (window) Set up listener for "DidStart" message and start worker. +// Step 2 (worker) Send "DidStart" message to window. +// Step 3 (window) Receive "DidStart" message and cleanup. + +async_test(t => { + // Step 1 + const worker = new SharedWorker("/workers/same-site-cookies/resources/worker.js", {sameSiteCookies: "all"}); + worker.port.onmessage = t.step_func(e => { + // Step 3 + assert_equals(e.data, "DidStart", "Worker should have started"); + t.done(); + }); +}, "Check SharedWorker sameSiteCookies option all for first-party"); diff --git a/workers/same-site-cookies/first-party.default.tentative.https.window.js b/workers/same-site-cookies/first-party.default.tentative.https.window.js new file mode 100644 index 00000000000000..b120014c1a82ba --- /dev/null +++ b/workers/same-site-cookies/first-party.default.tentative.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (window) Set up listener for "DidStart" message and start worker. +// Step 2 (worker) Send "DidStart" message to window. +// Step 3 (window) Receive "DidStart" message and cleanup. + +async_test(t => { + // Step 1 + const worker = new SharedWorker("/workers/same-site-cookies/resources/worker.js"); + worker.port.onmessage = t.step_func(e => { + // Step 3 + assert_equals(e.data, "DidStart", "Worker should have started"); + t.done(); + }); +}, "Check SharedWorker sameSiteCookies option default for first-party"); diff --git a/workers/same-site-cookies/first-party.none.tentative.https.window.js b/workers/same-site-cookies/first-party.none.tentative.https.window.js new file mode 100644 index 00000000000000..762d924eb92c03 --- /dev/null +++ b/workers/same-site-cookies/first-party.none.tentative.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (window) Set up listener for "DidStart" message and start worker. +// Step 2 (worker) Send "DidStart" message to window. +// Step 3 (window) Receive "DidStart" message and cleanup. + +async_test(t => { + // Step 1 + const worker = new SharedWorker("/workers/same-site-cookies/resources/worker.js", {sameSiteCookies: "none"}); + worker.port.onmessage = t.step_func(e => { + // Step 3 + assert_equals(e.data, "DidStart", "Worker should have started"); + t.done(); + }); +}, "Check SharedWorker sameSiteCookies option none for first-party"); diff --git a/workers/same-site-cookies/resources/iframe-iframe.html b/workers/same-site-cookies/resources/iframe-iframe.html new file mode 100644 index 00000000000000..0c5582176d4fe0 --- /dev/null +++ b/workers/same-site-cookies/resources/iframe-iframe.html @@ -0,0 +1,31 @@ + + + + + + + diff --git a/workers/same-site-cookies/resources/iframe.sub.html b/workers/same-site-cookies/resources/iframe.sub.html new file mode 100644 index 00000000000000..2531f3d62039df --- /dev/null +++ b/workers/same-site-cookies/resources/iframe.sub.html @@ -0,0 +1,14 @@ + + + + + + + diff --git a/workers/same-site-cookies/resources/worker.js b/workers/same-site-cookies/resources/worker.js new file mode 100644 index 00000000000000..658f499e92ac50 --- /dev/null +++ b/workers/same-site-cookies/resources/worker.js @@ -0,0 +1,5 @@ +// Step 2/4 (workers/same-site-cookies/{}) +self.onconnect = (e) => { + e.ports[0].postMessage("DidStart"); + self.close(); +} diff --git a/workers/same-site-cookies/third-party.all.tentative.sub.https.window.js b/workers/same-site-cookies/third-party.all.tentative.sub.https.window.js new file mode 100644 index 00000000000000..51ad1d3b02543b --- /dev/null +++ b/workers/same-site-cookies/third-party.all.tentative.sub.https.window.js @@ -0,0 +1,24 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "DidNotStart" message and open cross-site iframe. +// Step 2 (sub-frame) Open iframe same-site to top-frame. +// Step 3 (sub-sub-frame) Set up listener for message and start worker. +// Step 4 (worker) Skipped. +// Step 5 (sub-sub-frame) Worker failed to start and window messages "DidNotStart". +// Step 6 (top-frame) Receive "DidNotStart" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 6 + assert_equals(e.data, "DidNotStart", "Worker should not have started"); + t.done(); + })); + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/workers/same-site-cookies/resources/iframe.sub.html?type=all"; + document.body.appendChild(iframe); +}, "Check SharedWorker sameSiteCookies option all for third-party"); diff --git a/workers/same-site-cookies/third-party.default.tentative.sub.https.window.js b/workers/same-site-cookies/third-party.default.tentative.sub.https.window.js new file mode 100644 index 00000000000000..194df38390ed40 --- /dev/null +++ b/workers/same-site-cookies/third-party.default.tentative.sub.https.window.js @@ -0,0 +1,24 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "DidStart" message and open cross-site iframe. +// Step 2 (sub-frame) Open iframe same-site to top-frame. +// Step 3 (sub-sub-frame) Set up listener for message and start worker. +// Step 4 (worker) Send "DidStart" message to iframe. +// Step 5 (sub-sub-frame) Receive message and pass on to window. +// Step 6 (top-frame) Receive "DidStart" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 6 + assert_equals(e.data, "DidStart", "Worker should have started"); + t.done(); + })); + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/workers/same-site-cookies/resources/iframe.sub.html?type=default"; + document.body.appendChild(iframe); +}, "Check SharedWorker sameSiteCookies option default for third-party"); diff --git a/workers/same-site-cookies/third-party.none.tentative.sub.https.window.js b/workers/same-site-cookies/third-party.none.tentative.sub.https.window.js new file mode 100644 index 00000000000000..b91b9d7ab27ce8 --- /dev/null +++ b/workers/same-site-cookies/third-party.none.tentative.sub.https.window.js @@ -0,0 +1,24 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "DidStart" message and open cross-site iframe. +// Step 2 (sub-frame) Open iframe same-site to top-frame. +// Step 3 (sub-sub-frame) Set up listener for message and start worker. +// Step 4 (worker) Send "DidStart" message to iframe. +// Step 5 (sub-sub-frame) Receive message and pass on to window. +// Step 6 (top-frame) Receive "DidStart" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 6 + assert_equals(e.data, "DidStart", "Worker should have started"); + t.done(); + })); + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/workers/same-site-cookies/resources/iframe.sub.html?type=none"; + document.body.appendChild(iframe); +}, "Check SharedWorker sameSiteCookies option none for third-party");