OLD | NEW |
---|---|
(Empty) | |
1 <!DOCTYPE html> | |
2 <title>Service Worker: UseCounter</title> | |
3 <script src="../../resources/testharness.js"></script> | |
4 <script src="../../resources/testharnessreport.js"></script> | |
5 <script src="../resources/test-helpers.js"></script> | |
6 <script> | |
7 | |
8 const kFeature = 675; // From UseCounter.h | |
9 const kDeprecatedFeature = 538; // From Deprecation.h | |
10 | |
11 function isUseCounted(win, feature) { | |
12 return win.internals.isUseCounted(win.document, feature); | |
13 } | |
14 | |
15 // Use a window instead of an iframe because UseCounter is shared among frames | |
16 // in a document and these tests cannot be conducted in such an environment. | |
17 // A window has its own UseCounter. | |
18 function openWindow(url) { | |
19 return new Promise(resolve => { | |
20 let win = window.open(url, '_blank'); | |
21 add_completion_callback(() => win.close()); | |
22 window.onmessage = e => { | |
23 assert_equals(e.data, 'LOADED'); | |
24 resolve(win); | |
25 }; | |
26 }); | |
27 } | |
28 | |
29 promise_test(t => { | |
30 let url = 'resources/usecounter-worker.js'; | |
31 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.
| |
32 let worker; | |
33 let win1; | |
34 let win2; | |
35 | |
36 return service_worker_unregister_and_register(t, url, scope) | |
37 .then(registration => { | |
38 add_completion_callback(function() { registration.unregister(); }); | |
39 worker = registration.installing; | |
40 return wait_for_state(t, registration.installing, 'activated'); | |
41 }) | |
42 .then(() => { return openWindow(scope); }) | |
43 .then(win => { | |
44 win1 = win; | |
45 return openWindow(scope); | |
46 }) | |
47 .then(win => { | |
48 win2 = win; | |
49 | |
50 assert_false(isUseCounted(win1, kFeature)); | |
51 assert_false(isUseCounted(win2, kFeature)); | |
52 | |
53 // Request to count a feature. | |
54 return new Promise(resolve => { | |
55 navigator.serviceWorker.onmessage = resolve; | |
56 worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); | |
57 }); | |
58 }) | |
59 .then(e => { | |
60 assert_equals(e.data.type, 'COUNTED'); | |
61 | |
62 // API use on ServiceWorkerGlobalScope should be recorded in all | |
63 // controlled windows. | |
64 assert_true(isUseCounted(win1, kFeature)); | |
65 assert_true(isUseCounted(win2, kFeature)); | |
66 | |
67 assert_false(isUseCounted(win1, kDeprecatedFeature)); | |
68 assert_false(isUseCounted(win2, kDeprecatedFeature)); | |
69 | |
70 // Request to count a deprecated feature. | |
71 return new Promise(resolve => { | |
72 navigator.serviceWorker.onmessage = resolve; | |
73 worker.postMessage( | |
74 {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); | |
75 }); | |
76 }) | |
77 .then(e => { | |
78 assert_equals(e.data.type, 'COUNTED'); | |
79 | |
80 // Deprecated API use on ServiceWorkerGlobalScope should be recorded | |
81 // in all controlled windows. | |
82 assert_true(isUseCounted(win1, kDeprecatedFeature)); | |
83 assert_true(isUseCounted(win2, kDeprecatedFeature)); | |
84 | |
85 return openWindow(scope); | |
86 }) | |
87 .then(win => { | |
88 assert_true(isUseCounted(win, kFeature)); | |
89 assert_true(isUseCounted(win, kDeprecatedFeature)); | |
90 }); | |
91 }, 'UseCounter on ServiceWorkerGlobalScope'); | |
92 | |
93 promise_test(t => { | |
94 let url = 'resources/usecounter-worker.js'; | |
95 let scope = 'resources/usecounter-window.html?claim'; | |
falken
2017/02/08 05:01:54
const
nhiroki
2017/02/09 05:11:32
Done.
| |
96 let worker; | |
97 let win1; | |
98 let win2; | |
99 | |
100 return openWindow(scope) | |
101 .then(win => { | |
102 win1 = win; | |
103 return openWindow(scope); | |
104 }) | |
105 .then(win => { | |
106 win2 = win; | |
107 return service_worker_unregister_and_register(t, url, scope) | |
108 }) | |
109 .then(registration => { | |
110 add_completion_callback(function() { registration.unregister(); }); | |
111 worker = registration.installing; | |
112 return wait_for_state(t, registration.installing, 'activated'); | |
113 }) | |
114 .then(() => { | |
115 // Request to count a feature. | |
116 return new Promise(resolve => { | |
117 navigator.serviceWorker.onmessage = resolve; | |
118 worker.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); | |
119 }); | |
120 }) | |
121 .then(e => { | |
122 assert_equals(e.data.type, 'COUNTED'); | |
123 | |
124 // API use on ServiceWorkerGlobalScope should not be recorded in | |
125 // windows because they are not controlled yet. | |
126 assert_false(isUseCounted(win1, kFeature)); | |
127 assert_false(isUseCounted(win2, kFeature)); | |
128 | |
129 // Request to count a deprecated feature. | |
130 return new Promise(resolve => { | |
131 navigator.serviceWorker.onmessage = resolve; | |
132 worker.postMessage( | |
133 {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); | |
134 }); | |
135 }) | |
136 .then(e => { | |
137 assert_equals(e.data.type, 'COUNTED'); | |
138 | |
139 // Deprecated API use on ServiceWorkerGlobalScope should not be | |
140 // recorded in windows because they are not controlled yet. | |
141 assert_false(isUseCounted(win1, kDeprecatedFeature)); | |
142 assert_false(isUseCounted(win2, kDeprecatedFeature)); | |
143 | |
144 assert_equals(win1.navigator.serviceWorker.controller, null); | |
145 assert_equals(win2.navigator.serviceWorker.controller, null); | |
146 | |
147 // Request to claim. | |
148 return new Promise(resolve => { | |
149 navigator.serviceWorker.onmessage = resolve; | |
150 worker.postMessage({type: 'CLAIM'}); | |
151 }); | |
152 }) | |
153 .then(e => { | |
154 assert_equals(e.data.type, 'CLAIMED'); | |
155 assert_false(e.data.restarted); | |
156 assert_not_equals(win1.navigator.serviceWorker.controller, null); | |
157 assert_not_equals(win2.navigator.serviceWorker.controller, null); | |
158 | |
159 // The windows are now controlled by the service worker. Their | |
160 // UseCounter should be synchronized with worker's counter. | |
161 assert_true(isUseCounted(win1, kFeature)); | |
162 assert_true(isUseCounted(win2, kFeature)); | |
163 assert_true(isUseCounted(win1, kDeprecatedFeature)); | |
164 assert_true(isUseCounted(win2, kDeprecatedFeature)); | |
165 }); | |
166 }, 'UseCounter on ServiceWorkerGlobalScope - A use counter owned by newly ' + | |
167 'controlled window should be synchronized with worker\'s counter'); | |
168 | |
169 // Test that features used during service worker installation are persisted. | |
170 // This test could be non-deterministic because there is no handy way to | |
171 // sweep out on-memory representation of ServiceWorker in the browser process | |
172 // and make sure to restore it from the storage. | |
173 promise_test(t => { | |
174 let url = 'resources/usecounter-worker.js'; | |
175 let scope = 'resources/usecounter-window.html' + | |
176 '?type=features-during-install' + | |
177 '&feature=' + kFeature + | |
178 '&deprecated=' + kDeprecatedFeature; | |
falken
2017/02/08 05:01:54
const?
nhiroki
2017/02/09 05:11:32
Done.
| |
179 let worker; | |
180 let win1; | |
181 let win2; | |
182 | |
183 return openWindow(scope) | |
184 .then(win => { | |
185 win1 = win; | |
186 return openWindow(scope); | |
187 }) | |
188 .then(win => { | |
189 win2 = win; | |
190 // A service worker will call some APIs during the install event. | |
191 return service_worker_unregister_and_register(t, url, scope) | |
192 }) | |
193 .then(registration => { | |
194 add_completion_callback(function() { registration.unregister(); }); | |
195 worker = registration.installing; | |
196 return wait_for_state(t, registration.installing, 'activated'); | |
197 }) | |
198 .then(e => { | |
199 assert_equals(win1.navigator.serviceWorker.controller, null); | |
200 assert_equals(win2.navigator.serviceWorker.controller, null); | |
201 | |
202 // API use on ServiceWorkerGlobalScope should not be recorded in | |
203 // windows because they are not controlled yet. | |
204 assert_false(isUseCounted(win1, kFeature)); | |
205 assert_false(isUseCounted(win2, kFeature)); | |
206 assert_false(isUseCounted(win1, kDeprecatedFeature)); | |
207 assert_false(isUseCounted(win2, kDeprecatedFeature)); | |
208 | |
209 // Terminate the service worker. | |
210 internals.terminateServiceWorker(worker); | |
211 | |
212 // Request to claim. This will restart the service worker. | |
213 return new Promise(resolve => { | |
214 navigator.serviceWorker.onmessage = resolve; | |
215 worker.postMessage({type: 'CLAIM'}); | |
216 }); | |
217 }) | |
218 .then(e => { | |
219 assert_equals(e.data.type, 'CLAIMED'); | |
220 assert_true(e.data.restarted); | |
221 assert_not_equals(win1.navigator.serviceWorker.controller, null); | |
222 assert_not_equals(win2.navigator.serviceWorker.controller, null); | |
223 | |
224 // The windows are now controlled by the service worker. Their | |
225 // UseCounter should be synchronized with worker's counter retrieved | |
226 // from the storage. | |
227 assert_true(isUseCounted(win1, kFeature)); | |
228 assert_true(isUseCounted(win2, kFeature)); | |
229 assert_true(isUseCounted(win1, kDeprecatedFeature)); | |
230 assert_true(isUseCounted(win2, kDeprecatedFeature)); | |
231 }); | |
232 }, 'UseCounter on ServiceWorkerGlobalScope - counts during the install ' + | |
233 'event should be persisted'); | |
234 | |
235 // TODO(nhiroki): Test that features used after service worker installation are | |
236 // not persisted. This could be impossible because there is no handy way to | |
237 // sweep out on-memory representation of ServiceWorker in the browser process | |
238 // and make sure to restore it from the storage. | |
239 | |
240 promise_test(t => { | |
241 let url = 'resources/usecounter-worker.js'; | |
242 let scope = 'resources/usecounter-window.html?type=skip-waiting'; | |
243 let worker1; | |
244 let worker2; | |
245 let win1; | |
246 let win2; | |
247 | |
248 return service_worker_unregister_and_register(t, url, scope) | |
249 .then(registration => { | |
250 add_completion_callback(function() { registration.unregister(); }); | |
251 worker1 = registration.installing; | |
252 return wait_for_state(t, registration.installing, 'activated'); | |
253 }) | |
254 .then(() => { return openWindow(scope); }) | |
255 .then(win => { | |
256 win1 = win; | |
257 assert_false(isUseCounted(win1, kFeature)); | |
258 | |
259 // Request to count a feature. | |
260 return new Promise(resolve => { | |
261 navigator.serviceWorker.onmessage = resolve; | |
262 worker1.postMessage({type: 'COUNT_FEATURE', feature: kFeature}); | |
263 }); | |
264 }) | |
265 .then(e => { | |
266 assert_equals(e.data.type, 'COUNTED'); | |
267 | |
268 // API use on ServiceWorkerGlobalScope should be recorded in a | |
269 // controlled window. | |
270 assert_true(isUseCounted(win1, kFeature)); | |
271 | |
272 // Update a controller using skipWaiting(). | |
273 return navigator.serviceWorker.register( | |
274 url + '?skip-waiting', {scope: scope}); | |
275 }) | |
276 .then(registration => { | |
277 add_completion_callback(function() { registration.unregister(); }); | |
278 worker2 = registration.installing; | |
279 // Wait until the new worker gets activated. | |
280 return wait_for_state(t, worker2, 'activated'); | |
281 }) | |
282 .then(() => { return openWindow(scope); }) | |
283 .then(win => { | |
284 // This window wasn't controlled by the previous worker. | |
285 win2 = win; | |
286 assert_not_equals(win2.navigator.serviceWorker.controller, undefined); | |
287 | |
288 // An updated worker does not take over the previous counter, so API | |
289 // use on the previous worker should not be recorded in the newly | |
290 // controlled window. | |
291 assert_true(isUseCounted(win1, kFeature)); | |
292 assert_false(isUseCounted(win2, kFeature)); | |
293 | |
294 assert_false(isUseCounted(win1, kDeprecatedFeature)); | |
295 assert_false(isUseCounted(win2, kDeprecatedFeature)); | |
296 | |
297 // Request to count a deprecated feature. | |
298 return new Promise(resolve => { | |
299 navigator.serviceWorker.onmessage = resolve; | |
300 worker2.postMessage( | |
301 {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature}); | |
302 }); | |
303 }) | |
304 .then(e => { | |
305 assert_equals(e.data.type, 'COUNTED'); | |
306 | |
307 // Deprecated API use on the updated worker should be recorded in | |
308 // all controlled windows. | |
309 assert_true(isUseCounted(win1, kFeature)); | |
310 assert_false(isUseCounted(win2, kFeature)); | |
311 assert_true(isUseCounted(win1, kDeprecatedFeature)); | |
312 assert_true(isUseCounted(win2, kDeprecatedFeature)); | |
313 }); | |
314 }, 'UseCounter on ServiceWorkerGlobalScope - an updated worker should not ' + | |
315 'take over a previous counter'); | |
316 | |
317 // 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.
| |
318 // is connected from multiple windows. In such a case, API use on ServiceWorker | |
319 // should be propagated to all connecting windows via SharedWorker. | |
320 | |
321 </script> | |
322 </html> | |
OLD | NEW |