| Index: third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium/usecounter.html
|
| diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium/usecounter.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium/usecounter.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9b0f94fbf8a29c2a5d487df58a7026897c5fa9bf
|
| --- /dev/null
|
| +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium/usecounter.html
|
| @@ -0,0 +1,325 @@
|
| +<!DOCTYPE html>
|
| +<title>Service Worker: UseCounter</title>
|
| +<script src="../../resources/testharness.js"></script>
|
| +<script src="../../resources/testharnessreport.js"></script>
|
| +<script src="../resources/test-helpers.js"></script>
|
| +<script>
|
| +
|
| +const kFeature = 675; // From UseCounter.h
|
| +const kDeprecatedFeature = 538; // From Deprecation.h
|
| +
|
| +function isUseCounted(win, feature) {
|
| + return win.internals.isUseCounted(win.document, feature);
|
| +}
|
| +
|
| +function observeUseCounter(win, feature) {
|
| + return win.internals.observeUseCounter(win.document, feature);
|
| +}
|
| +
|
| +// Use a window instead of an iframe because UseCounter is shared among frames
|
| +// in a document and these tests cannot be conducted in such an environment.
|
| +// A window has its own UseCounter.
|
| +function openWindow(url) {
|
| + return new Promise(resolve => {
|
| + let win = window.open(url, '_blank');
|
| + add_completion_callback(() => win.close());
|
| + window.onmessage = e => {
|
| + assert_equals(e.data, 'LOADED');
|
| + resolve(win);
|
| + };
|
| + });
|
| +}
|
| +
|
| +promise_test(t => {
|
| + const kUrl = 'resources/usecounter-worker.js';
|
| + const kScope = 'resources/usecounter-window.html?basic';
|
| + let worker;
|
| + let win1;
|
| + let win2;
|
| +
|
| + return service_worker_unregister_and_register(t, kUrl, kScope)
|
| + .then(registration => {
|
| + add_completion_callback(function() { registration.unregister(); });
|
| + worker = registration.installing;
|
| + return wait_for_state(t, registration.installing, 'activated');
|
| + })
|
| + .then(() => { return openWindow(kScope); })
|
| + .then(win => {
|
| + win1 = win;
|
| + return openWindow(kScope);
|
| + })
|
| + .then(win => {
|
| + win2 = win;
|
| +
|
| + assert_false(isUseCounted(win1, kFeature));
|
| + assert_false(isUseCounted(win2, kFeature));
|
| +
|
| + // Request to count a feature.
|
| + worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
|
| + return Promise.all([
|
| + observeUseCounter(win1, kFeature),
|
| + observeUseCounter(win2, kFeature)
|
| + ]);
|
| + })
|
| + .then(() => {
|
| + // API use on ServiceWorkerGlobalScope should be recorded in all
|
| + // controlled windows.
|
| + assert_true(isUseCounted(win1, kFeature));
|
| + assert_true(isUseCounted(win2, kFeature));
|
| +
|
| + assert_false(isUseCounted(win1, kDeprecatedFeature));
|
| + assert_false(isUseCounted(win2, kDeprecatedFeature));
|
| +
|
| + // Request to count a deprecated feature.
|
| + worker.postMessage(
|
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature});
|
| + return Promise.all([
|
| + observeUseCounter(win1, kDeprecatedFeature),
|
| + observeUseCounter(win2, kDeprecatedFeature)
|
| + ]);
|
| + })
|
| + .then(() => {
|
| + // Deprecated API use on ServiceWorkerGlobalScope should be recorded
|
| + // in all controlled windows.
|
| + assert_true(isUseCounted(win1, kDeprecatedFeature));
|
| + assert_true(isUseCounted(win2, kDeprecatedFeature));
|
| +
|
| + return openWindow(kScope);
|
| + })
|
| + .then(win => {
|
| + assert_true(isUseCounted(win, kFeature));
|
| + assert_true(isUseCounted(win, kDeprecatedFeature));
|
| + });
|
| + }, 'UseCounter on ServiceWorkerGlobalScope');
|
| +
|
| +promise_test(t => {
|
| + const kUrl = 'resources/usecounter-worker.js';
|
| + const kScope = 'resources/usecounter-window.html?claim';
|
| + let worker;
|
| + let win1;
|
| + let win2;
|
| +
|
| + return openWindow(kScope)
|
| + .then(win => {
|
| + win1 = win;
|
| + return openWindow(kScope);
|
| + })
|
| + .then(win => {
|
| + win2 = win;
|
| + return service_worker_unregister_and_register(t, kUrl, kScope)
|
| + })
|
| + .then(registration => {
|
| + add_completion_callback(function() { registration.unregister(); });
|
| + worker = registration.installing;
|
| + return wait_for_state(t, registration.installing, 'activated');
|
| + })
|
| + .then(() => {
|
| + // Request to count a feature.
|
| + worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
|
| + return new Promise(resolve => {
|
| + navigator.serviceWorker.onmessage = resolve;
|
| + // 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');
|
| +
|
| + // API use on ServiceWorkerGlobalScope should not be recorded in
|
| + // windows because they are not controlled yet.
|
| + assert_false(isUseCounted(win1, kFeature));
|
| + assert_false(isUseCounted(win2, kFeature));
|
| +
|
| + // Request to count a deprecated feature.
|
| + worker.postMessage(
|
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature});
|
| + return new Promise(resolve => {
|
| + navigator.serviceWorker.onmessage = resolve;
|
| + // 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.
|
| +// This test could be non-deterministic because there is no handy way to
|
| +// sweep out on-memory representation of ServiceWorker in the browser process
|
| +// and make sure to restore it from the storage.
|
| +promise_test(t => {
|
| + const kUrl = 'resources/usecounter-worker.js';
|
| + const kScope = 'resources/usecounter-window.html' +
|
| + '?type=features-during-install' +
|
| + '&feature=' + kFeature +
|
| + '&deprecated=' + kDeprecatedFeature;
|
| + let worker;
|
| + let win1;
|
| + let win2;
|
| +
|
| + return openWindow(kScope)
|
| + .then(win => {
|
| + win1 = win;
|
| + return openWindow(kScope);
|
| + })
|
| + .then(win => {
|
| + win2 = win;
|
| + // A service worker will call some APIs during the install event.
|
| + return service_worker_unregister_and_register(t, kUrl, kScope)
|
| + })
|
| + .then(registration => {
|
| + add_completion_callback(function() { registration.unregister(); });
|
| + worker = registration.installing;
|
| + return wait_for_state(t, registration.installing, 'activated');
|
| + })
|
| + .then(e => {
|
| + assert_equals(win1.navigator.serviceWorker.controller, null);
|
| + assert_equals(win2.navigator.serviceWorker.controller, null);
|
| +
|
| + // API use on ServiceWorkerGlobalScope should not be recorded in
|
| + // windows because they are not controlled yet.
|
| + assert_false(isUseCounted(win1, kFeature));
|
| + assert_false(isUseCounted(win2, kFeature));
|
| + assert_false(isUseCounted(win1, kDeprecatedFeature));
|
| + assert_false(isUseCounted(win2, kDeprecatedFeature));
|
| +
|
| + // Terminate the service worker.
|
| + internals.terminateServiceWorker(worker);
|
| +
|
| + // Request to claim. This will restart the service worker.
|
| + return new Promise(resolve => {
|
| + navigator.serviceWorker.onmessage = resolve;
|
| + worker.postMessage({type: 'CLAIM'});
|
| + });
|
| + })
|
| + .then(e => {
|
| + assert_equals(e.data.type, 'CLAIMED');
|
| + assert_true(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 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
|
| +// not persisted. This could be impossible because there is no handy way to
|
| +// sweep out on-memory representation of ServiceWorker in the browser process
|
| +// and make sure to restore it from the storage.
|
| +
|
| +promise_test(t => {
|
| + const kUrl = 'resources/usecounter-worker.js';
|
| + const kScope = 'resources/usecounter-window.html?type=skip-waiting';
|
| + let worker1;
|
| + let worker2;
|
| + let win1;
|
| + let win2;
|
| +
|
| + return service_worker_unregister_and_register(t, kUrl, kScope)
|
| + .then(registration => {
|
| + add_completion_callback(function() { registration.unregister(); });
|
| + worker1 = registration.installing;
|
| + return wait_for_state(t, registration.installing, 'activated');
|
| + })
|
| + .then(() => { return openWindow(kScope); })
|
| + .then(win => {
|
| + win1 = win;
|
| + assert_false(isUseCounted(win1, kFeature));
|
| +
|
| + // Request to count a feature.
|
| + worker1.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
|
| + return observeUseCounter(win1, kFeature);
|
| + })
|
| + .then(e => {
|
| + // API use on ServiceWorkerGlobalScope should be recorded in a
|
| + // controlled window.
|
| + assert_true(isUseCounted(win1, kFeature));
|
| +
|
| + // Update a controller using skipWaiting().
|
| + return navigator.serviceWorker.register(
|
| + kUrl + '?skip-waiting', {scope: kScope});
|
| + })
|
| + .then(registration => {
|
| + add_completion_callback(function() { registration.unregister(); });
|
| + worker2 = registration.installing;
|
| + // Wait until the new worker gets activated.
|
| + return wait_for_state(t, worker2, 'activated');
|
| + })
|
| + .then(() => { return openWindow(kScope); })
|
| + .then(win => {
|
| + // This window wasn't controlled by the previous worker.
|
| + win2 = win;
|
| + assert_not_equals(win2.navigator.serviceWorker.controller, undefined);
|
| +
|
| + // An updated worker does not take over the previous counter, so API
|
| + // use on the previous worker should not be recorded in the newly
|
| + // controlled window.
|
| + assert_true(isUseCounted(win1, kFeature));
|
| + assert_false(isUseCounted(win2, kFeature));
|
| +
|
| + assert_false(isUseCounted(win1, kDeprecatedFeature));
|
| + assert_false(isUseCounted(win2, kDeprecatedFeature));
|
| +
|
| + // Request to count a deprecated feature.
|
| + worker2.postMessage(
|
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature});
|
| + return Promise.all([
|
| + observeUseCounter(win1, kDeprecatedFeature),
|
| + observeUseCounter(win2, kDeprecatedFeature)
|
| + ]);
|
| + })
|
| + .then(e => {
|
| + // Deprecated API use on the updated worker should be recorded in
|
| + // all controlled windows.
|
| + assert_true(isUseCounted(win1, kFeature));
|
| + assert_false(isUseCounted(win2, kFeature));
|
| + assert_true(isUseCounted(win1, kDeprecatedFeature));
|
| + assert_true(isUseCounted(win2, kDeprecatedFeature));
|
| + });
|
| + }, 'UseCounter on ServiceWorkerGlobalScope - an updated worker should not ' +
|
| + 'take over a previous counter');
|
| +
|
| +// TODO(nhiroki): Test a case where ServiceWorker controls SharedWorker that is
|
| +// connected from multiple windows. In such a case, API use on ServiceWorker
|
| +// should be propagated to all connecting windows via SharedWorker.
|
| +
|
| +</script>
|
| +</html>
|
|
|