Commit 9996ac89 authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

ServiceWorker: Modernize http/tests/serviceworker/usecounter.html using async/await etc

This is a mechanical cleanup CL for making it easier to add new use counter tests.

Bug: 900444
Change-Id: Ib8d3c708c0f6ed1fd00b00bbcc9e873097cccd64
Reviewed-on: https://chromium-review.googlesource.com/c/1308240
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604166}
parent a4c9e64d
...@@ -21,7 +21,7 @@ function observeUseCounter(win, feature) { ...@@ -21,7 +21,7 @@ function observeUseCounter(win, feature) {
// A window has its own UseCounter. // A window has its own UseCounter.
function openWindow(url) { function openWindow(url) {
return new Promise(resolve => { return new Promise(resolve => {
let win = window.open(url, '_blank'); const win = window.open(url, '_blank');
add_completion_callback(() => win.close()); add_completion_callback(() => win.close());
window.onmessage = e => { window.onmessage = e => {
assert_equals(e.data, 'LOADED'); assert_equals(e.data, 'LOADED');
...@@ -30,351 +30,264 @@ function openWindow(url) { ...@@ -30,351 +30,264 @@ function openWindow(url) {
}); });
} }
promise_test(t => { promise_test(async t => {
const kUrl = 'resources/usecounter-worker.js'; const kUrl = 'resources/usecounter-worker.js';
const kScope = 'resources/usecounter-window.html?basic'; const kScope = 'resources/usecounter-window.html?basic';
let worker;
let win1; const registration =
let win2; await service_worker_unregister_and_register(t, kUrl, kScope);
t.add_cleanup(() => registration.unregister());
return service_worker_unregister_and_register(t, kUrl, kScope) const worker = registration.installing;
.then(registration => { await wait_for_state(t, registration.installing, 'activated');
add_completion_callback(function() { registration.unregister(); }); const win1 = await openWindow(kScope);
worker = registration.installing; const win2 = await openWindow(kScope);
return wait_for_state(t, registration.installing, 'activated'); assert_false(isUseCounted(win1, kFeature));
}) assert_false(isUseCounted(win2, kFeature));
.then(() => { return openWindow(kScope); })
.then(win => { // Request to count a feature.
win1 = win; worker.postMessage({ type: 'COUNT_FEATURE', feature: kFeature });
return openWindow(kScope); await observeUseCounter(win1, kFeature);
}) await observeUseCounter(win2, kFeature);
.then(win => {
win2 = win; // API use on ServiceWorkerGlobalScope should be recorded in all controlled
// windows.
assert_false(isUseCounted(win1, kFeature)); assert_true(isUseCounted(win1, kFeature));
assert_false(isUseCounted(win2, kFeature)); assert_true(isUseCounted(win2, kFeature));
// Request to count a feature. assert_false(isUseCounted(win1, kDeprecatedFeature));
worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); assert_false(isUseCounted(win2, kDeprecatedFeature));
return Promise.all([
observeUseCounter(win1, kFeature), // Request to count a deprecated feature.
observeUseCounter(win2, kFeature) worker.postMessage(
]); { type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature });
}) await observeUseCounter(win1, kDeprecatedFeature);
.then(() => { await observeUseCounter(win2, kDeprecatedFeature);
// API use on ServiceWorkerGlobalScope should be recorded in all
// controlled windows. // Deprecated API use on ServiceWorkerGlobalScope should be recorded in all
assert_true(isUseCounted(win1, kFeature)); // controlled windows.
assert_true(isUseCounted(win2, kFeature)); assert_true(isUseCounted(win1, kDeprecatedFeature));
assert_true(isUseCounted(win2, kDeprecatedFeature));
assert_false(isUseCounted(win1, kDeprecatedFeature));
assert_false(isUseCounted(win2, kDeprecatedFeature)); // Check UseCounters have been sent to the new window. Since this can happen
// after the new window's document load, an observer is used to wait until it
// Request to count a deprecated feature. // happens.
worker.postMessage( const win = await openWindow(kScope);
{type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); await observeUseCounter(win, kFeature);
return Promise.all([ await observeUseCounter(win, kDeprecatedFeature);
observeUseCounter(win1, kDeprecatedFeature), }, 'UseCounter on ServiceWorkerGlobalScope');
observeUseCounter(win2, kDeprecatedFeature)
]); promise_test(async t => {
}) const kUrl = 'resources/usecounter-worker.js';
.then(() => { const kScope = 'resources/usecounter-window.html?claim';
// Deprecated API use on ServiceWorkerGlobalScope should be recorded
// in all controlled windows. const win1 = await openWindow(kScope);
assert_true(isUseCounted(win1, kDeprecatedFeature)); const win2 = await openWindow(kScope);
assert_true(isUseCounted(win2, kDeprecatedFeature)); const registration =
await service_worker_unregister_and_register(t, kUrl, kScope);
return openWindow(kScope); t.add_cleanup(() => registration.unregister());
}) const worker = registration.installing;
.then(win => { await wait_for_state(t, registration.installing, 'activated');
// Check UseCounters have been sent to the new window. Since this is can
// happen after the new window's document load, an observer is used to // Request to count a feature.
// wait until it happens. worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
return Promise.all([ let msgEvent = await new Promise(resolve => {
observeUseCounter(win, kFeature), navigator.serviceWorker.onmessage = resolve;
observeUseCounter(win, kDeprecatedFeature) // There is no way to verify that API use is never counted. As a workaround,
]); // wait for only one round-trip.
}) worker.postMessage({type: 'PING'});
}, 'UseCounter on ServiceWorkerGlobalScope'); });
assert_equals(msgEvent.data.type, 'PONG');
promise_test(t => {
const kUrl = 'resources/usecounter-worker.js'; // API use on ServiceWorkerGlobalScope should not be recorded in windows
const kScope = 'resources/usecounter-window.html?claim'; // because they are not controlled yet.
let worker; assert_false(isUseCounted(win1, kFeature));
let win1; assert_false(isUseCounted(win2, kFeature));
let win2;
// Request to count a deprecated feature.
return openWindow(kScope) worker.postMessage(
.then(win => { { type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature });
win1 = win; msgEvent = await new Promise(resolve => {
return openWindow(kScope); navigator.serviceWorker.onmessage = resolve;
}) // There is no way to verify that API use is never counted. As a workaround,
.then(win => { // wait for only one round-trip.
win2 = win; worker.postMessage({type: 'PING'});
return service_worker_unregister_and_register(t, kUrl, kScope) });
}) assert_equals(msgEvent.data.type, 'PONG');
.then(registration => {
add_completion_callback(function() { registration.unregister(); }); // Deprecated API use on ServiceWorkerGlobalScope should not be recorded in
worker = registration.installing; // windows because they are not controlled yet.
return wait_for_state(t, registration.installing, 'activated'); assert_false(isUseCounted(win1, kDeprecatedFeature));
}) assert_false(isUseCounted(win2, kDeprecatedFeature));
.then(() => {
// Request to count a feature. assert_equals(win1.navigator.serviceWorker.controller, null);
worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); assert_equals(win2.navigator.serviceWorker.controller, null);
return new Promise(resolve => {
navigator.serviceWorker.onmessage = resolve; // Request to claim.
// There is no way to verify that API use is never counted. As a msgEvent = await new Promise(resolve => {
// workaround, wait for only one round-trip. navigator.serviceWorker.onmessage = resolve;
worker.postMessage({type: 'PING'}); worker.postMessage({type: 'CLAIM'});
}); });
})
.then(e => { assert_equals(msgEvent.data.type, 'CLAIMED');
assert_equals(e.data.type, 'PONG'); assert_false(msgEvent.data.restarted);
assert_not_equals(win1.navigator.serviceWorker.controller, null);
// API use on ServiceWorkerGlobalScope should not be recorded in assert_not_equals(win2.navigator.serviceWorker.controller, null);
// windows because they are not controlled yet.
assert_false(isUseCounted(win1, kFeature)); // The windows are now controlled by the service worker. Their UseCounter
assert_false(isUseCounted(win2, kFeature)); // should be synchronized with worker's counter.
assert_true(isUseCounted(win1, kFeature));
// Request to count a deprecated feature. assert_true(isUseCounted(win2, kFeature));
worker.postMessage( assert_true(isUseCounted(win1, kDeprecatedFeature));
{type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); assert_true(isUseCounted(win2, kDeprecatedFeature));
return new Promise(resolve => { }, 'UseCounter on ServiceWorkerGlobalScope - A use counter owned by newly ' +
navigator.serviceWorker.onmessage = resolve; 'controlled window should be synchronized with worker\'s counter');
// There is no way to verify that API use is never counted. As a
// workaround, wait for only one round-trip.
worker.postMessage({type: 'PING'});
});
})
.then(e => {
assert_equals(e.data.type, 'PONG');
// Deprecated API use on ServiceWorkerGlobalScope should not be
// recorded in windows because they are not controlled yet.
assert_false(isUseCounted(win1, kDeprecatedFeature));
assert_false(isUseCounted(win2, kDeprecatedFeature));
assert_equals(win1.navigator.serviceWorker.controller, null);
assert_equals(win2.navigator.serviceWorker.controller, null);
// Request to claim.
return new Promise(resolve => {
navigator.serviceWorker.onmessage = resolve;
worker.postMessage({type: 'CLAIM'});
});
})
.then(e => {
assert_equals(e.data.type, 'CLAIMED');
assert_false(e.data.restarted);
assert_not_equals(win1.navigator.serviceWorker.controller, null);
assert_not_equals(win2.navigator.serviceWorker.controller, null);
// The windows are now controlled by the service worker. Their
// UseCounter should be synchronized with worker's counter.
assert_true(isUseCounted(win1, kFeature));
assert_true(isUseCounted(win2, kFeature));
assert_true(isUseCounted(win1, kDeprecatedFeature));
assert_true(isUseCounted(win2, kDeprecatedFeature));
});
}, 'UseCounter on ServiceWorkerGlobalScope - A use counter owned by newly ' +
'controlled window should be synchronized with worker\'s counter');
// Test that features used during service worker installation are persisted. // Test that features used during service worker installation are persisted.
// This test could be non-deterministic because there is no handy way to // This test could be non-deterministic because there is no handy way to sweep
// sweep out on-memory representation of ServiceWorker in the browser process // out on-memory representation of ServiceWorker in the browser process and make
// and make sure to restore it from the storage. // sure to restore it from the storage.
promise_test(t => { promise_test(async t => {
const kUrl = 'resources/usecounter-worker.js'; const kUrl = 'resources/usecounter-worker.js';
const kScope = 'resources/usecounter-window.html' + const kScope = 'resources/usecounter-window.html' +
'?type=features-during-install' + '?type=features-during-install' +
'&feature=' + kFeature + '&feature=' + kFeature +
'&deprecated=' + kDeprecatedFeature; '&deprecated=' + kDeprecatedFeature;
let worker;
let win1; const win1 = await openWindow(kScope);
let win2; const win2 = await openWindow(kScope);
return openWindow(kScope) // A service worker will call some APIs during the install event.
.then(win => { const registration =
win1 = win; await service_worker_unregister_and_register(t, kUrl, kScope);
return openWindow(kScope); t.add_cleanup(() => registration.unregister());
}) const worker = registration.installing;
.then(win => { await wait_for_state(t, registration.installing, 'activated');
win2 = win;
// A service worker will call some APIs during the install event. assert_equals(win1.navigator.serviceWorker.controller, null);
return service_worker_unregister_and_register(t, kUrl, kScope) assert_equals(win2.navigator.serviceWorker.controller, null);
})
.then(registration => { // API use on ServiceWorkerGlobalScope should not be recorded in windows
add_completion_callback(function() { registration.unregister(); }); // because they are not controlled yet.
worker = registration.installing; assert_false(isUseCounted(win1, kFeature));
return wait_for_state(t, registration.installing, 'activated'); assert_false(isUseCounted(win2, kFeature));
}) assert_false(isUseCounted(win1, kDeprecatedFeature));
.then(e => { assert_false(isUseCounted(win2, kDeprecatedFeature));
assert_equals(win1.navigator.serviceWorker.controller, null);
assert_equals(win2.navigator.serviceWorker.controller, null); // Terminate the service worker.
await internals.terminateServiceWorker(worker);
// API use on ServiceWorkerGlobalScope should not be recorded in
// windows because they are not controlled yet. // Request to claim. This will restart the service worker.
assert_false(isUseCounted(win1, kFeature)); const msgEvent = await new Promise(resolve => {
assert_false(isUseCounted(win2, kFeature)); navigator.serviceWorker.onmessage = resolve;
assert_false(isUseCounted(win1, kDeprecatedFeature)); worker.postMessage({type: 'CLAIM'});
assert_false(isUseCounted(win2, kDeprecatedFeature)); });
// Terminate the service worker. assert_equals(msgEvent.data.type, 'CLAIMED');
return internals.terminateServiceWorker(worker); assert_true(msgEvent.data.restarted);
}) assert_not_equals(win1.navigator.serviceWorker.controller, null);
.then(() => { assert_not_equals(win2.navigator.serviceWorker.controller, null);
// Request to claim. This will restart the service worker.
return new Promise(resolve => { // The windows are now controlled by the service worker. Their UseCounter
navigator.serviceWorker.onmessage = resolve; // should be synchronized with worker's counter retrieved from the storage.
worker.postMessage({type: 'CLAIM'}); assert_true(isUseCounted(win1, kFeature));
}); assert_true(isUseCounted(win2, kFeature));
}) assert_true(isUseCounted(win1, kDeprecatedFeature));
.then(e => { assert_true(isUseCounted(win2, kDeprecatedFeature));
assert_equals(e.data.type, 'CLAIMED'); }, 'UseCounter on ServiceWorkerGlobalScope - counts during the install ' +
assert_true(e.data.restarted); 'event should be persisted');
assert_not_equals(win1.navigator.serviceWorker.controller, null);
assert_not_equals(win2.navigator.serviceWorker.controller, null);
// The windows are now controlled by the service worker. Their
// UseCounter should be synchronized with worker's counter retrieved
// from the storage.
assert_true(isUseCounted(win1, kFeature));
assert_true(isUseCounted(win2, kFeature));
assert_true(isUseCounted(win1, kDeprecatedFeature));
assert_true(isUseCounted(win2, kDeprecatedFeature));
});
}, 'UseCounter on ServiceWorkerGlobalScope - counts during the install ' +
'event should be persisted');
// TODO(nhiroki): Test that features used after service worker installation are // TODO(nhiroki): Test that features used after service worker installation are
// not persisted. This could be impossible because there is no handy way to // not persisted. This could be impossible because there is no handy way to
// sweep out on-memory representation of ServiceWorker in the browser process // sweep out on-memory representation of ServiceWorker in the browser process
// and make sure to restore it from the storage. // and make sure to restore it from the storage.
promise_test(t => { promise_test(async t => {
const kUrl = 'resources/usecounter-worker.js'; const kUrl = 'resources/usecounter-worker.js';
const kScope = 'resources/usecounter-window.html?type=skip-waiting'; const kScope = 'resources/usecounter-window.html?type=skip-waiting';
let worker1;
let worker2; const registration1 =
let win1; await service_worker_unregister_and_register(t, kUrl, kScope);
let win2; t.add_cleanup(() => registration1.unregister());
const worker1 = registration1.installing;
return service_worker_unregister_and_register(t, kUrl, kScope) await wait_for_state(t, registration1.installing, 'activated');
.then(registration => { const win1 = await openWindow(kScope);
add_completion_callback(function() { registration.unregister(); }); assert_false(isUseCounted(win1, kFeature));
worker1 = registration.installing;
return wait_for_state(t, registration.installing, 'activated'); // Request to count a feature.
}) worker1.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
.then(() => { return openWindow(kScope); }) await observeUseCounter(win1, kFeature);
.then(win => {
win1 = win; // API use on ServiceWorkerGlobalScope should be recorded in a controlled
assert_false(isUseCounted(win1, kFeature)); // window.
assert_true(isUseCounted(win1, kFeature));
// Request to count a feature.
worker1.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); // Update a controller using skipWaiting().
return observeUseCounter(win1, kFeature); const registration2 = await navigator.serviceWorker.register(
}) kUrl + '?skip-waiting', {scope: kScope});
.then(e => { t.add_cleanup(() => registration2.unregister());
// API use on ServiceWorkerGlobalScope should be recorded in a const worker2 = registration2.installing;
// controlled window.
assert_true(isUseCounted(win1, kFeature)); // Wait until the new worker gets activated.
await wait_for_state(t, worker2, 'activated');
// Update a controller using skipWaiting(). const win2 = await openWindow(kScope);
return navigator.serviceWorker.register(
kUrl + '?skip-waiting', {scope: kScope}); // This window wasn't controlled by the previous worker.
}) assert_not_equals(win2.navigator.serviceWorker.controller, undefined);
.then(registration => {
add_completion_callback(function() { registration.unregister(); }); // An updated worker does not take over the previous counter, so API use on
worker2 = registration.installing; // the previous worker should not be recorded in the newly controlled window.
// Wait until the new worker gets activated. assert_true(isUseCounted(win1, kFeature));
return wait_for_state(t, worker2, 'activated'); assert_false(isUseCounted(win2, kFeature));
})
.then(() => { return openWindow(kScope); }) assert_false(isUseCounted(win1, kDeprecatedFeature));
.then(win => { assert_false(isUseCounted(win2, kDeprecatedFeature));
// This window wasn't controlled by the previous worker.
win2 = win; // Request to count a deprecated feature.
assert_not_equals(win2.navigator.serviceWorker.controller, undefined); worker2.postMessage(
{ type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature });
// An updated worker does not take over the previous counter, so API await observeUseCounter(win1, kDeprecatedFeature);
// use on the previous worker should not be recorded in the newly await observeUseCounter(win2, kDeprecatedFeature);
// controlled window.
assert_true(isUseCounted(win1, kFeature)); // Deprecated API use on the updated worker should be recorded in all
assert_false(isUseCounted(win2, kFeature)); // controlled windows.
assert_true(isUseCounted(win1, kFeature));
assert_false(isUseCounted(win1, kDeprecatedFeature)); assert_false(isUseCounted(win2, kFeature));
assert_false(isUseCounted(win2, kDeprecatedFeature)); assert_true(isUseCounted(win1, kDeprecatedFeature));
assert_true(isUseCounted(win2, kDeprecatedFeature));
// Request to count a deprecated feature. }, 'UseCounter on ServiceWorkerGlobalScope - an updated worker should not ' +
worker2.postMessage( 'take over a previous counter');
{type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature});
return Promise.all([ promise_test(async t => {
observeUseCounter(win1, kDeprecatedFeature), const kFetchEventIsReload = 2032; // from web_feature.mojom
observeUseCounter(win2, kDeprecatedFeature) const kUrl = 'resources/use-isReload-worker.js';
]); const kScope = 'resources/usecounter-window.html?isReload';
})
.then(e => { const registration =
// Deprecated API use on the updated worker should be recorded in await service_worker_unregister_and_register(t, kUrl, kScope);
// all controlled windows. add_result_callback(() => registration.unregister());
assert_true(isUseCounted(win1, kFeature)); await wait_for_state(t, registration.installing, 'activated');
assert_false(isUseCounted(win2, kFeature));
assert_true(isUseCounted(win1, kDeprecatedFeature)); const win = await openWindow(kScope);
assert_true(isUseCounted(win2, kDeprecatedFeature)); await observeUseCounter(win, kFetchEventIsReload);
}); assert_true(isUseCounted(win, kFetchEventIsReload));
}, 'UseCounter on ServiceWorkerGlobalScope - an updated worker should not ' + }, 'FetchEvent.isReload is counted');
'take over a previous counter');
promise_test(async t => {
promise_test(t => { const kServiceWorkerFrameType = 2033; // from web_feature.mojom
const kFetchEventIsReload = 2032; // from web_feature.mojom const kUrl = 'resources/feature-worker.js';
const kUrl = 'resources/use-isReload-worker.js'; const kScope = 'resources/usecounter-window.html?frameType';
const kScope = 'resources/usecounter-window.html?isReload';
let win; const registration =
return service_worker_unregister_and_register(t, kUrl, kScope) await service_worker_unregister_and_register(t, kUrl, kScope);
.then(registration => { add_result_callback(() => registration.unregister());
add_result_callback(() => { const worker = registration.installing;
if (win) { await wait_for_state(t, worker, 'activated');
win.close();
} const win = await openWindow(kScope);
registration.unregister(); worker.postMessage('use-frameType');
}); await observeUseCounter(win, kServiceWorkerFrameType);
return wait_for_state(t, registration.installing, 'activated'); assert_true(isUseCounted(win, kServiceWorkerFrameType));
}) }, 'Client.frameType is counted');
.then(() => { return openWindow(kScope); })
.then(new_window => {
win = new_window;
return observeUseCounter(win, kFetchEventIsReload);
})
.then(() => {
assert_true(isUseCounted(win, kFetchEventIsReload));
});
}, 'FetchEvent.isReload is counted');
promise_test(t => {
const kServiceWorkerFrameType = 2033; // from web_feature.mojom
const kUrl = 'resources/feature-worker.js';
const kScope = 'resources/usecounter-window.html?frameType';
let worker;
let win;
return service_worker_unregister_and_register(t, kUrl, kScope)
.then(registration => {
add_result_callback(() => {
if (win) {
win.close();
}
registration.unregister();
});
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(() => { return openWindow(kScope); })
.then(new_window => {
win = new_window;
worker.postMessage('use-frameType');
return observeUseCounter(win, kServiceWorkerFrameType);
})
.then(() => {
assert_true(isUseCounted(win, kServiceWorkerFrameType));
});
}, 'Client.frameType is counted');
// TODO(nhiroki): Test a case where ServiceWorker controls SharedWorker that is // TODO(nhiroki): Test a case where ServiceWorker controls SharedWorker that is
// connected from multiple windows. In such a case, API use on ServiceWorker // connected from multiple windows. In such a case, API use on ServiceWorker
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment