0

Add WPT for Partitioned Service Worker claim()

Add WPT that tests that clients.claim() is properly partitioned
when storage partitioning is enabled.

(For chrome) Also runs the test as part of the third-party storage
partitioning virtual test suite.

Bug: 1246549
Change-Id: I26f6f64ad8c1a1a531fe7503cfeb43abc99b4397
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3289538
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: Ben Kelly <wanderview@chromium.org>
Commit-Queue: Steven Bingler <bingler@chromium.org>
Cr-Commit-Position: refs/heads/main@{#944152}
This commit is contained in:
Steven Bingler
2021-11-22 18:02:30 +00:00
committed by Chromium LUCI CQ
parent 61aad523e7
commit 5720242fdc
6 changed files with 158 additions and 11 deletions

@@ -851,6 +851,7 @@
"external/wpt/service-workers/service-worker/partitioned-service-worker.tentative.https.html",
"external/wpt/service-workers/service-worker/partitioned-service-worker-getRegistrations.tentative.https.html",
"external/wpt/service-workers/service-worker/partitioned-service-worker-matchAll.tentative.https.html",
"external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https.html",
"external/wpt/webstorage/localstorage-basic-partitioned.tentative.sub.html"
],
"args": [ "--enable-features=ThirdPartyStoragePartitioning" ]

@@ -0,0 +1,4 @@
This is a testharness.js-based test.
FAIL ServiceWorker's clients.claim() is partitioned assert_equals: 3p iframe was successfully claimed expected "success" but got "failure"
Harness: the test ran to completion.

@@ -0,0 +1,74 @@
<!DOCTYPE html>
<meta charset="utf-8"/>
<title>Service Worker: Partitioned Service Workers</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/partitioned-utils.js"></script>
<body>
This test creates a iframe in a first-party context and then registers a
service worker (such that the iframe client is unclaimed).
A third-party iframe is then created which has its SW call clients.claim()
and then the test checks that the 1p iframe was not claimed int he process.
Finally the test has its SW call clients.claim() and confirms the 1p iframe is
claimed.
<script>
promise_test(async t => {
const script = './resources/partitioned-storage-sw.js';
const scope = './resources/partitioned-';
// Add a 1p iframe.
const wait_frame_url = new URL(
'./resources/partitioned-service-worker-iframe-claim.html?1p-mode',
self.location);
const frame = await with_iframe(wait_frame_url, false);
t.add_cleanup(async () => {
frame.remove();
});
// Add service worker to this 1P context.
const reg = await service_worker_unregister_and_register(t, script, scope);
t.add_cleanup(() => reg.unregister());
await wait_for_state(t, reg.installing, 'activated');
// Register the message listener.
self.addEventListener('message', messageEventHandler);
// Now we need to create a third-party iframe whose SW will claim it and then
// the iframe will postMessage that its serviceWorker.controller state has
// changed.
const third_party_iframe_url = new URL(
'./resources/partitioned-service-worker-iframe-claim.html?3p-mode',
get_host_info().HTTPS_ORIGIN + self.location.pathname);
// Create the 3p window (which will in turn create the iframe with the SW)
// and await on its data.
const frame_3p_data = await loadAndReturnSwData(t, third_party_iframe_url,
'window');
assert_equals(frame_3p_data.status, "success",
"3p iframe was successfully claimed");
// Confirm that the 1p iframe wasn't claimed at the same time.
const controller_1p_iframe = makeMessagePromise();
frame.contentWindow.postMessage({type: "get-controller"});
const controller_1p_iframe_data = await controller_1p_iframe;
assert_equals(controller_1p_iframe_data.controller, null,
"Test iframe client isn't claimed yet.");
// Tell the SW to claim.
const claimed_1p_iframe = makeMessagePromise();
reg.active.postMessage({type: "claim"});
const claimed_1p_iframe_data = await claimed_1p_iframe;
assert_equals(claimed_1p_iframe_data.status, "success",
"iframe client was successfully claimed.");
}, "ServiceWorker's clients.claim() is partitioned");
</script>
</body>

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<title>Service Worker: 3P iframe for partitioned service workers</title>
<script src="/test-helpers.sub.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="./partitioned-utils.js"></script>
<body>
<script>
// 1p mode will respond to requests for its current controller and
// postMessage when its controller changes.
async function onLoad1pMode(){
self.addEventListener('message', evt => {
if(!evt.data)
return;
if (evt.data.type === "get-controller") {
window.parent.postMessage({controller: navigator.serviceWorker.controller});
}
});
navigator.serviceWorker.addEventListener('controllerchange', evt => {
window.parent.postMessage({status: "success", context: "1p"}, '*');
});
}
// 3p mode will tell its SW to claim and then postMessage its results
// automatically.
async function onLoad3pMode() {
reg = await setup3pIframe();
if(navigator.serviceWorker.controller != null){
//This iframe is already under control of a service worker, testing for
// a controller change will timeout. Return a failure.
window.parent.postMessage({status: "failure", context: "3p"}, '*');
return;
}
// Once this client is claimed, let the test know.
navigator.serviceWorker.addEventListener('controllerchange', evt => {
window.parent.postMessage({status: "success", context: "3p"}, '*');
});
// Trigger the SW to claim.
reg.active.postMessage({type: "claim"});
}
const request_url = new URL(window.location.href);
var url_search = request_url.search.substr(1);
if(url_search == "1p-mode") {
self.addEventListener('load', onLoad1pMode);
}
else if(url_search == "3p-mode") {
self.addEventListener('load', onLoad3pMode);
}
// Else do nothing.
</script>
</body>

@@ -17,18 +17,23 @@ self.addEventListener('fetch', function(event) {
})
self.addEventListener('message', (event) => {
if(!event.data)
return;
event.waitUntil(async function() {
if(!event.data)
return;
if (event.data.type === "get-id") {
event.source.postMessage({ID: ID});
}
else if(event.data.type === "get-match-all") {
clients.matchAll({includeUncontrolled: true}).then(clients_list => {
const url_list = clients_list.map(item => item.url);
event.source.postMessage({urls_list: url_list});
});
}
if (event.data.type === "get-id") {
event.source.postMessage({ID: ID});
}
else if(event.data.type === "get-match-all") {
clients.matchAll({includeUncontrolled: true}).then(clients_list => {
const url_list = clients_list.map(item => item.url);
event.source.postMessage({urls_list: url_list});
});
}
else if(event.data.type === "claim") {
await clients.claim();
}
}());
});
async function fetchEventHandler(event){

@@ -0,0 +1,4 @@
This is a testharness.js-based test.
PASS ServiceWorker's clients.claim() is partitioned
Harness: the test ran to completion.