-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WPT] BFCache: service worker clients
This CL adds tests for BFCache + Clients.claim(), Clients.matchAll() and unregister(). Bug: 1107415, 1204228, w3c/ServiceWorker#1594 Change-Id: I73233cf917e31dd91b974823d5490d0190f0eade
- Loading branch information
1 parent
9c0f68e
commit 58615a8
Showing
5 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
html/browsers/browsing-the-web/back-forward-cache/resources/service-worker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
self.addEventListener('message', function(event) { | ||
self.clients.claim() | ||
.then(function(result) { | ||
if (result !== undefined) { | ||
event.data.port.postMessage( | ||
'FAIL: claim() should be resolved with undefined'); | ||
return; | ||
} | ||
event.data.port.postMessage('PASS'); | ||
}) | ||
.catch(function(error) { | ||
event.data.port.postMessage('FAIL: exception: ' + error.name); | ||
}); | ||
}); | ||
|
||
self.addEventListener('fetch', e => { | ||
if (e.request.url.match(/\/is-controlled/)) { | ||
e.respondWith(new Response('controlled')); | ||
} | ||
else if (e.request.url.match(/\/get-clients-matchall/)) { | ||
const options = { includeUncontrolled: true, type: 'all' }; | ||
e.respondWith( | ||
self.clients.matchAll(options) | ||
.then(clients => { | ||
const client_urls = []; | ||
clients.forEach(client => client_urls.push(client.url)); | ||
return new Response(JSON.stringify(client_urls)); | ||
}) | ||
); | ||
} | ||
}); |
73 changes: 73 additions & 0 deletions
73
html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-claim.https.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<!doctype html> | ||
<meta name="timeout" content="long"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/common/utils.js"></script> | ||
<script src="/common/dispatcher/dispatcher.js"></script> | ||
<script src="resources/helper.sub.js"></script> | ||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | ||
<script> | ||
|
||
promise_test(async t => { | ||
const pageA = new RemoteContext(token()); | ||
const pageB = new RemoteContext(token()); | ||
|
||
const urlA = location.origin + executorPath + pageA.context_id; | ||
const urlB = originCrossSite + executorPath + pageB.context_id; | ||
|
||
window.open(urlA, '_blank', 'noopener'); | ||
|
||
// Set `oncontrollerchange` on `pageA`. | ||
await pageA.execute_script(waitForPageShow); | ||
|
||
// Register a service worker after `pageA` is loaded to make `pageA` | ||
// uncontrolled at this time. | ||
const workerUrl = | ||
'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)'; | ||
const registration = | ||
await service_worker_unregister_and_register(t, workerUrl, './'); | ||
t.add_cleanup(_ => registration.unregister()); | ||
await wait_for_state(t, registration.installing, 'activated'); | ||
|
||
// Navigate to `urlB`. | ||
await pageA.execute_script( | ||
(url) => { | ||
prepareNavigation(() => { location.href = url; }); | ||
}, | ||
[urlB]); | ||
await pageB.execute_script(waitForPageShow); | ||
|
||
// Call Clients.claim() on the service worker when `pageA` is in BFCache. | ||
// As per https://github.com/w3c/ServiceWorker/issues/1038#issuecomment-291028845, | ||
// this evicts `pageA` from BFCache. | ||
const controllerChanged = new Promise( | ||
resolve => navigator.serviceWorker.oncontrollerchange = resolve); | ||
await claim(t, registration.active); | ||
await controllerChanged; | ||
|
||
// `pageA` doesn't appear in matchAll(). | ||
const clients1 = await (await fetch('/get-clients-matchall')).json(); | ||
assert_true(clients1.indexOf(urlA) < 0, | ||
'1: matchAll() before back navigation'); | ||
|
||
// Back navigate and check that the page was evicted from BFCache. | ||
await pageB.execute_script( | ||
() => { | ||
prepareNavigation(() => { history.back(); }); | ||
} | ||
); | ||
await pageA.execute_script(waitForPageShow); | ||
await assert_not_bfcached(pageA); | ||
|
||
// After back navigation, `pageA` appear in matchAll(), because it was newly | ||
// loaded and controlled by the service worker. | ||
const clients2 = await (await fetch('/get-clients-matchall')).json(); | ||
const controlled2 = await pageA.execute_script( | ||
() => fetch('/is-controlled?claim-2').then(r => r.text())); | ||
assert_true(clients2.indexOf(urlA) >= 0, | ||
'2: matchAll() just after back navigation'); | ||
assert_equals(controlled2, 'controlled', | ||
'2: pageA should be controlled just after back navigation'); | ||
|
||
}, 'Clients.claim() evicts pages from BFCache'); | ||
</script> |
76 changes: 76 additions & 0 deletions
76
html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<!doctype html> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/common/utils.js"></script> | ||
<script src="/common/dispatcher/dispatcher.js"></script> | ||
<script src="resources/helper.sub.js"></script> | ||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | ||
<script> | ||
|
||
promise_test(async t => { | ||
// Register a service worker and make this page controlled. | ||
const workerUrl = | ||
'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)'; | ||
const registration = | ||
await service_worker_unregister_and_register(t, workerUrl, './'); | ||
t.add_cleanup(_ => registration.unregister()); | ||
await wait_for_state(t, registration.installing, 'activated'); | ||
const controllerChanged = new Promise( | ||
resolve => navigator.serviceWorker.oncontrollerchange = resolve); | ||
await claim(t, registration.active); | ||
await controllerChanged; | ||
|
||
const pageA = new RemoteContext(token()); | ||
const pageB = new RemoteContext(token()); | ||
|
||
const urlA = location.origin + executorPath + pageA.context_id; | ||
const urlB = originCrossSite + executorPath + pageB.context_id; | ||
|
||
// Open `urlA`. | ||
window.open(urlA, '_blank', 'noopener'); | ||
await pageA.execute_script(waitForPageShow); | ||
|
||
// Get Clients.matchAll() and check whether `pageA` is controlled. | ||
// Actual `assert_*()` is called after `assert_bfcached()` below. | ||
const clients1 = await (await fetch('/get-clients-matchall')).json(); | ||
const controlled1 = await pageA.execute_script( | ||
() => fetch('/is-controlled?matchall-1').then(r => r.text())); | ||
|
||
// Navigate to `urlB` and get Clients.matchAll() when `urlA` is in BFCache. | ||
await pageA.execute_script( | ||
(url) => prepareNavigation(() => { | ||
location.href = url; | ||
}), | ||
[urlB]); | ||
await pageB.execute_script(waitForPageShow); | ||
const clients2 = await (await fetch('/get-clients-matchall')).json(); | ||
|
||
// Back navigate and check whether the page is restored from BFCache. | ||
await pageB.execute_script( | ||
() => { | ||
prepareNavigation(() => { history.back(); }); | ||
} | ||
); | ||
await pageA.execute_script(waitForPageShow); | ||
await assert_bfcached(pageA); | ||
|
||
// Get Clients.matchAll() and check whether `pageA` is controlled. | ||
const clients3 = await (await fetch('/get-clients-matchall')).json(); | ||
const controlled3 = await pageA.execute_script( | ||
() => fetch('/is-controlled?matchall-3').then(r => r.text())); | ||
|
||
// Clients.matchAll() should not list `urlA` when it is in BFCache. | ||
assert_true(clients1.indexOf(urlA) >= 0, | ||
'1: matchAll() before navigation'); | ||
assert_true(clients2.indexOf(urlA) < 0, | ||
'2: matchAll() before back navigation'); | ||
assert_true(clients3.indexOf(urlA) >= 0, | ||
'3: matchAll() after back navigation'); | ||
|
||
// `pageA` should be controlled before/after BFCached. | ||
assert_equals(controlled1, 'controlled', | ||
'pageA should be controlled before BFCached'); | ||
assert_equals(controlled3, 'controlled', | ||
'pageA should be controlled after restored'); | ||
}, 'Serviceworker Clients.matchAll()'); | ||
</script> |
62 changes: 62 additions & 0 deletions
62
html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<!doctype html> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/common/utils.js"></script> | ||
<script src="/common/dispatcher/dispatcher.js"></script> | ||
<script src="resources/helper.sub.js"></script> | ||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | ||
<script> | ||
|
||
promise_test(async t => { | ||
// Register a service worker and make this page controlled. | ||
const workerUrl = | ||
'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)'; | ||
const registration = | ||
await service_worker_unregister_and_register(t, workerUrl, './'); | ||
t.add_cleanup(_ => registration.unregister()); | ||
await wait_for_state(t, registration.installing, 'activated'); | ||
const controllerChanged = new Promise( | ||
resolve => navigator.serviceWorker.oncontrollerchange = resolve); | ||
await claim(t, registration.active); | ||
await controllerChanged; | ||
|
||
const pageA = new RemoteContext(token()); | ||
const pageB = new RemoteContext(token()); | ||
|
||
const urlA = location.origin + executorPath + pageA.context_id; | ||
const urlB = originCrossSite + executorPath + pageB.context_id; | ||
|
||
// Open `urlA`. | ||
window.open(urlA, '_blank', 'noopener'); | ||
await pageA.execute_script(waitForPageShow); | ||
|
||
// Navigate to `urlB`. | ||
await pageA.execute_script( | ||
(url) => prepareNavigation(() => { | ||
location.href = url; | ||
}), | ||
[urlB]); | ||
await pageB.execute_script(waitForPageShow); | ||
|
||
// Unregister the service worker when the controlled `pageA` is in BFCache. | ||
// This should not crash. | ||
await registration.unregister(); | ||
|
||
// Back navigate and check whether the page is restored from BFCache. | ||
await pageB.execute_script( | ||
() => { | ||
prepareNavigation(() => { history.back(); }); | ||
} | ||
); | ||
await pageA.execute_script(waitForPageShow); | ||
await assert_bfcached(pageA); | ||
|
||
// `pageA` should be still controlled after restored from BFCache. | ||
assert_equals( | ||
await pageA.execute_script( | ||
() => fetch('/is-controlled').then(r => r.text())), | ||
'controlled', | ||
'pageA should be still controlled'); | ||
|
||
}, 'Unregister service worker while a controlled page is in BFCache'); | ||
</script> |