Chromium Code Reviews| 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..cf71cb438bff0191fe6bac2f8c3f5f7ce717301d |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium/usecounter.html |
| @@ -0,0 +1,322 @@ |
| +<!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); |
| +} |
| + |
| +// 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 => { |
| + let url = 'resources/usecounter-worker.js'; |
| + let scope = 'resources/usecounter-window.html?basic'; |
|
falken
2017/02/08 05:01:54
const for these?
nhiroki
2017/02/09 05:11:32
Done.
|
| + let worker; |
| + let win1; |
| + let win2; |
| + |
| + return service_worker_unregister_and_register(t, url, scope) |
| + .then(registration => { |
| + add_completion_callback(function() { registration.unregister(); }); |
| + worker = registration.installing; |
| + return wait_for_state(t, registration.installing, 'activated'); |
| + }) |
| + .then(() => { return openWindow(scope); }) |
| + .then(win => { |
| + win1 = win; |
| + return openWindow(scope); |
| + }) |
| + .then(win => { |
| + win2 = win; |
| + |
| + assert_false(isUseCounted(win1, kFeature)); |
| + assert_false(isUseCounted(win2, kFeature)); |
| + |
| + // Request to count a feature. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // 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. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker.postMessage( |
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // Deprecated API use on ServiceWorkerGlobalScope should be recorded |
| + // in all controlled windows. |
| + assert_true(isUseCounted(win1, kDeprecatedFeature)); |
| + assert_true(isUseCounted(win2, kDeprecatedFeature)); |
| + |
| + return openWindow(scope); |
| + }) |
| + .then(win => { |
| + assert_true(isUseCounted(win, kFeature)); |
| + assert_true(isUseCounted(win, kDeprecatedFeature)); |
| + }); |
| + }, 'UseCounter on ServiceWorkerGlobalScope'); |
| + |
| +promise_test(t => { |
| + let url = 'resources/usecounter-worker.js'; |
| + let scope = 'resources/usecounter-window.html?claim'; |
|
falken
2017/02/08 05:01:54
const
nhiroki
2017/02/09 05:11:32
Done.
|
| + let worker; |
| + let win1; |
| + let win2; |
| + |
| + return openWindow(scope) |
| + .then(win => { |
| + win1 = win; |
| + return openWindow(scope); |
| + }) |
| + .then(win => { |
| + win2 = win; |
| + return service_worker_unregister_and_register(t, url, scope) |
| + }) |
| + .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. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // 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. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker.postMessage( |
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // 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 => { |
| + let url = 'resources/usecounter-worker.js'; |
| + let scope = 'resources/usecounter-window.html' + |
| + '?type=features-during-install' + |
| + '&feature=' + kFeature + |
| + '&deprecated=' + kDeprecatedFeature; |
|
falken
2017/02/08 05:01:54
const?
nhiroki
2017/02/09 05:11:32
Done.
|
| + let worker; |
| + let win1; |
| + let win2; |
| + |
| + return openWindow(scope) |
| + .then(win => { |
| + win1 = win; |
| + return openWindow(scope); |
| + }) |
| + .then(win => { |
| + win2 = win; |
| + // A service worker will call some APIs during the install event. |
| + return service_worker_unregister_and_register(t, url, scope) |
| + }) |
| + .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 => { |
| + let url = 'resources/usecounter-worker.js'; |
| + let scope = 'resources/usecounter-window.html?type=skip-waiting'; |
| + let worker1; |
| + let worker2; |
| + let win1; |
| + let win2; |
| + |
| + return service_worker_unregister_and_register(t, url, scope) |
| + .then(registration => { |
| + add_completion_callback(function() { registration.unregister(); }); |
| + worker1 = registration.installing; |
| + return wait_for_state(t, registration.installing, 'activated'); |
| + }) |
| + .then(() => { return openWindow(scope); }) |
| + .then(win => { |
| + win1 = win; |
| + assert_false(isUseCounted(win1, kFeature)); |
| + |
| + // Request to count a feature. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker1.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // 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( |
| + url + '?skip-waiting', {scope: scope}); |
| + }) |
| + .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(scope); }) |
| + .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. |
| + return new Promise(resolve => { |
| + navigator.serviceWorker.onmessage = resolve; |
| + worker2.postMessage( |
| + {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); |
| + }); |
| + }) |
| + .then(e => { |
| + assert_equals(e.data.type, 'COUNTED'); |
| + |
| + // 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 controles SharedWorker that |
|
falken
2017/02/08 05:01:54
nit: controls
nhiroki
2017/02/09 05:11:32
Done.
|
| +// is connected from multiple windows. In such a case, API use on ServiceWorker |
| +// should be propagated to all connecting windows via SharedWorker. |
| + |
| +</script> |
| +</html> |