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..b33acb7c1bef50fb12327bedfb5d1aeab2286292 |
--- /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 => { |
+ 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. |
+ 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(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. |
+ 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 => { |
+ 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. |
+ 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( |
+ 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. |
+ 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 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> |