Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_context_unittest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/public/browser/service_worker_context.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/browser/browser_thread_impl.h"
11 #include "content/browser/service_worker/embedded_worker_registry.h"
12 #include "content/browser/service_worker/embedded_worker_test_helper.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_registration.h"
15 #include "content/browser/service_worker/service_worker_storage.h"
16 #include "content/common/service_worker/embedded_worker_messages.h"
17 #include "content/common/service_worker/service_worker_messages.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "content/public/test/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace content {
23
24 namespace {
25
26 void SaveResponseCallback(bool* called,
27                           int64* store_registration_id,
28                           int64* store_version_id,
29                           ServiceWorkerStatusCode status,
30                           int64 registration_id,
31                           int64 version_id) {
32   EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
33   *called = true;
34   *store_registration_id = registration_id;
35   *store_version_id = version_id;
36 }
37
38 ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
39     bool* called,
40     int64* store_registration_id,
41     int64* store_version_id) {
42   return base::Bind(&SaveResponseCallback, called,
43                     store_registration_id,
44                     store_version_id);
45 }
46
47 void CallCompletedCallback(bool* called, ServiceWorkerStatusCode) {
48   *called = true;
49 }
50
51 ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
52     bool* called) {
53   return base::Bind(&CallCompletedCallback, called);
54 }
55
56 void ExpectRegisteredWorkers(
57     ServiceWorkerStatusCode expect_status,
58     int64 expect_version_id,
59     bool expect_waiting,
60     bool expect_active,
61     ServiceWorkerStatusCode status,
62     const scoped_refptr<ServiceWorkerRegistration>& registration) {
63   ASSERT_EQ(expect_status, status);
64   if (status != SERVICE_WORKER_OK) {
65     EXPECT_FALSE(registration);
66     return;
67   }
68
69   if (expect_waiting) {
70     EXPECT_TRUE(registration->waiting_version());
71     EXPECT_EQ(expect_version_id,
72               registration->waiting_version()->version_id());
73   } else {
74     EXPECT_FALSE(registration->waiting_version());
75   }
76
77   if (expect_active) {
78     EXPECT_TRUE(registration->active_version());
79     EXPECT_EQ(expect_version_id,
80               registration->active_version()->version_id());
81   } else {
82     EXPECT_FALSE(registration->active_version());
83   }
84 }
85
86 class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
87  public:
88   explicit RejectInstallTestHelper(int mock_render_process_id)
89       : EmbeddedWorkerTestHelper(mock_render_process_id) {}
90
91   virtual void OnInstallEvent(int embedded_worker_id,
92                               int request_id,
93                               int active_version_id) OVERRIDE {
94     SimulateSend(
95         new ServiceWorkerHostMsg_InstallEventFinished(
96             embedded_worker_id, request_id,
97             blink::WebServiceWorkerEventResultRejected));
98   }
99 };
100
101 class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
102  public:
103   explicit RejectActivateTestHelper(int mock_render_process_id)
104       : EmbeddedWorkerTestHelper(mock_render_process_id) {}
105
106   virtual void OnActivateEvent(int embedded_worker_id,
107                                int request_id) OVERRIDE {
108     SimulateSend(
109         new ServiceWorkerHostMsg_ActivateEventFinished(
110             embedded_worker_id, request_id,
111             blink::WebServiceWorkerEventResultRejected));
112   }
113 };
114
115 }  // namespace
116
117 class ServiceWorkerContextTest : public testing::Test {
118  public:
119   ServiceWorkerContextTest()
120       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
121         render_process_id_(99) {}
122
123   virtual void SetUp() OVERRIDE {
124     helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
125   }
126
127   virtual void TearDown() OVERRIDE {
128     helper_.reset();
129   }
130
131   ServiceWorkerContextCore* context() { return helper_->context(); }
132
133  protected:
134   TestBrowserThreadBundle browser_thread_bundle_;
135   scoped_ptr<EmbeddedWorkerTestHelper> helper_;
136   const int render_process_id_;
137 };
138
139 // Make sure basic registration is working.
140 TEST_F(ServiceWorkerContextTest, Register) {
141   int64 registration_id = kInvalidServiceWorkerRegistrationId;
142   int64 version_id = kInvalidServiceWorkerVersionId;
143   bool called = false;
144   context()->RegisterServiceWorker(
145       GURL("http://www.example.com/"),
146       GURL("http://www.example.com/service_worker.js"),
147       render_process_id_,
148       NULL,
149       MakeRegisteredCallback(&called, &registration_id, &version_id));
150
151   ASSERT_FALSE(called);
152   base::RunLoop().RunUntilIdle();
153   EXPECT_TRUE(called);
154
155   EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
156   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
157       EmbeddedWorkerMsg_StartWorker::ID));
158   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
159       ServiceWorkerMsg_InstallEvent::ID));
160   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
161       ServiceWorkerMsg_ActivateEvent::ID));
162   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
163       EmbeddedWorkerMsg_StopWorker::ID));
164   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
165   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
166
167   context()->storage()->FindRegistrationForId(
168       registration_id,
169       GURL("http://www.example.com"),
170       base::Bind(&ExpectRegisteredWorkers,
171                  SERVICE_WORKER_OK,
172                  version_id,
173                  false /* expect_waiting */,
174                  true /* expect_active */));
175   base::RunLoop().RunUntilIdle();
176 }
177
178 // Test registration when the service worker rejects the install event. The
179 // registration callback should indicate success, but there should be no waiting
180 // or active worker in the registration.
181 TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
182   helper_.reset();  // Make sure the process lookups stay overridden.
183   helper_.reset(new RejectInstallTestHelper(render_process_id_));
184   int64 registration_id = kInvalidServiceWorkerRegistrationId;
185   int64 version_id = kInvalidServiceWorkerVersionId;
186   bool called = false;
187   context()->RegisterServiceWorker(
188       GURL("http://www.example.com/"),
189       GURL("http://www.example.com/service_worker.js"),
190       render_process_id_,
191       NULL,
192       MakeRegisteredCallback(&called, &registration_id, &version_id));
193
194   ASSERT_FALSE(called);
195   base::RunLoop().RunUntilIdle();
196   EXPECT_TRUE(called);
197
198   EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
199   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
200       EmbeddedWorkerMsg_StartWorker::ID));
201   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
202       ServiceWorkerMsg_InstallEvent::ID));
203   EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
204       ServiceWorkerMsg_ActivateEvent::ID));
205   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
206       EmbeddedWorkerMsg_StopWorker::ID));
207   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
208   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
209
210   context()->storage()->FindRegistrationForId(
211       registration_id,
212       GURL("http://www.example.com"),
213       base::Bind(&ExpectRegisteredWorkers,
214                  SERVICE_WORKER_ERROR_NOT_FOUND,
215                  kInvalidServiceWorkerVersionId,
216                  false /* expect_waiting */,
217                  false /* expect_active */));
218   base::RunLoop().RunUntilIdle();
219 }
220
221 // Test registration when the service worker rejects the activate event. The
222 // registration callback should indicate success, but there should be no waiting
223 // or active worker in the registration.
224 TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
225   helper_.reset();  // Make sure the process lookups stay overridden.
226   helper_.reset(new RejectActivateTestHelper(render_process_id_));
227   int64 registration_id = kInvalidServiceWorkerRegistrationId;
228   int64 version_id = kInvalidServiceWorkerVersionId;
229   bool called = false;
230   context()->RegisterServiceWorker(
231       GURL("http://www.example.com/"),
232       GURL("http://www.example.com/service_worker.js"),
233       render_process_id_,
234       NULL,
235       MakeRegisteredCallback(&called, &registration_id, &version_id));
236
237   ASSERT_FALSE(called);
238   base::RunLoop().RunUntilIdle();
239   EXPECT_TRUE(called);
240
241   EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
242   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
243       EmbeddedWorkerMsg_StartWorker::ID));
244   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
245       ServiceWorkerMsg_InstallEvent::ID));
246   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
247       ServiceWorkerMsg_ActivateEvent::ID));
248   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
249       EmbeddedWorkerMsg_StopWorker::ID));
250   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
251   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
252
253   context()->storage()->FindRegistrationForId(
254       registration_id,
255       GURL("http://www.example.com"),
256       base::Bind(&ExpectRegisteredWorkers,
257                  SERVICE_WORKER_ERROR_NOT_FOUND,
258                  kInvalidServiceWorkerVersionId,
259                  false /* expect_waiting */,
260                  false /* expect_active */));
261   base::RunLoop().RunUntilIdle();
262 }
263
264 // Make sure registrations are cleaned up when they are unregistered.
265 TEST_F(ServiceWorkerContextTest, Unregister) {
266   GURL pattern("http://www.example.com/");
267
268   bool called = false;
269   int64 registration_id = kInvalidServiceWorkerRegistrationId;
270   int64 version_id = kInvalidServiceWorkerVersionId;
271   context()->RegisterServiceWorker(
272       pattern,
273       GURL("http://www.example.com/service_worker.js"),
274       render_process_id_,
275       NULL,
276       MakeRegisteredCallback(&called, &registration_id, &version_id));
277
278   ASSERT_FALSE(called);
279   base::RunLoop().RunUntilIdle();
280   ASSERT_TRUE(called);
281   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
282   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
283
284   called = false;
285   context()->UnregisterServiceWorker(pattern,
286                                      MakeUnregisteredCallback(&called));
287
288   ASSERT_FALSE(called);
289   base::RunLoop().RunUntilIdle();
290   ASSERT_TRUE(called);
291
292   context()->storage()->FindRegistrationForId(
293       registration_id,
294       pattern.GetOrigin(),
295       base::Bind(&ExpectRegisteredWorkers,
296                  SERVICE_WORKER_ERROR_NOT_FOUND,
297                  kInvalidServiceWorkerVersionId,
298                  false /* expect_waiting */,
299                  false /* expect_active */));
300   base::RunLoop().RunUntilIdle();
301 }
302
303 // Make sure that when a new registration replaces an existing
304 // registration, that the old one is cleaned up.
305 TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
306   GURL pattern("http://www.example.com/");
307
308   bool called = false;
309   int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
310   int64 old_version_id = kInvalidServiceWorkerVersionId;
311   context()->RegisterServiceWorker(
312       pattern,
313       GURL("http://www.example.com/service_worker.js"),
314       render_process_id_,
315       NULL,
316       MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
317
318   ASSERT_FALSE(called);
319   base::RunLoop().RunUntilIdle();
320   ASSERT_TRUE(called);
321   EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
322   EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
323
324   called = false;
325   int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
326   int64 new_version_id = kInvalidServiceWorkerVersionId;
327   context()->RegisterServiceWorker(
328       pattern,
329       GURL("http://www.example.com/service_worker_new.js"),
330       render_process_id_,
331       NULL,
332       MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
333
334   ASSERT_FALSE(called);
335   base::RunLoop().RunUntilIdle();
336   ASSERT_TRUE(called);
337
338   // Returned IDs should be valid, and should differ from the values
339   // returned for the previous registration.
340   EXPECT_NE(kInvalidServiceWorkerRegistrationId, new_registration_id);
341   EXPECT_NE(kInvalidServiceWorkerVersionId, new_version_id);
342   EXPECT_NE(old_registration_id, new_registration_id);
343   EXPECT_NE(old_version_id, new_version_id);
344 }
345
346 // Make sure that when registering a duplicate pattern+script_url
347 // combination, that the same registration is used.
348 TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
349   GURL pattern("http://www.example.com/");
350   GURL script_url("http://www.example.com/service_worker.js");
351
352   bool called = false;
353   int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
354   int64 old_version_id = kInvalidServiceWorkerVersionId;
355   context()->RegisterServiceWorker(
356       pattern,
357       script_url,
358       render_process_id_,
359       NULL,
360       MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
361
362   ASSERT_FALSE(called);
363   base::RunLoop().RunUntilIdle();
364   ASSERT_TRUE(called);
365   EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
366   EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
367
368   called = false;
369   int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
370   int64 new_version_id = kInvalidServiceWorkerVersionId;
371   context()->RegisterServiceWorker(
372       pattern,
373       script_url,
374       render_process_id_,
375       NULL,
376       MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
377
378   ASSERT_FALSE(called);
379   base::RunLoop().RunUntilIdle();
380   ASSERT_TRUE(called);
381   EXPECT_EQ(old_registration_id, new_registration_id);
382   EXPECT_EQ(old_version_id, new_version_id);
383 }
384
385 // TODO(nhiroki): Test this for on-disk storage.
386 TEST_F(ServiceWorkerContextTest, DeleteAndStartOver) {
387   int64 registration_id = kInvalidServiceWorkerRegistrationId;
388   int64 version_id = kInvalidServiceWorkerVersionId;
389   bool called = false;
390   context()->RegisterServiceWorker(
391       GURL("http://www.example.com/"),
392       GURL("http://www.example.com/service_worker.js"),
393       render_process_id_,
394       NULL,
395       MakeRegisteredCallback(&called, &registration_id, &version_id));
396
397   ASSERT_FALSE(called);
398   base::RunLoop().RunUntilIdle();
399   EXPECT_TRUE(called);
400
401   context()->storage()->FindRegistrationForId(
402       registration_id,
403       GURL("http://www.example.com"),
404       base::Bind(&ExpectRegisteredWorkers,
405                  SERVICE_WORKER_OK,
406                  version_id,
407                  false /* expect_waiting */,
408                  true /* expect_active */));
409   base::RunLoop().RunUntilIdle();
410
411   context()->ScheduleDeleteAndStartOver();
412
413   // The storage is disabled while the recovery process is running, so the
414   // operation should be failed.
415   context()->storage()->FindRegistrationForId(
416       registration_id,
417       GURL("http://www.example.com"),
418       base::Bind(&ExpectRegisteredWorkers,
419                  SERVICE_WORKER_ERROR_FAILED,
420                  version_id,
421                  false /* expect_waiting */,
422                  true /* expect_active */));
423   base::RunLoop().RunUntilIdle();
424
425   // The context started over and the storage was re-initialized, so the
426   // registration should not be found.
427   context()->storage()->FindRegistrationForId(
428       registration_id,
429       GURL("http://www.example.com"),
430       base::Bind(&ExpectRegisteredWorkers,
431                  SERVICE_WORKER_ERROR_NOT_FOUND,
432                  version_id,
433                  false /* expect_waiting */,
434                  true /* expect_active */));
435   base::RunLoop().RunUntilIdle();
436
437   called = false;
438   context()->RegisterServiceWorker(
439       GURL("http://www.example.com/"),
440       GURL("http://www.example.com/service_worker.js"),
441       render_process_id_,
442       NULL,
443       MakeRegisteredCallback(&called, &registration_id, &version_id));
444
445   ASSERT_FALSE(called);
446   base::RunLoop().RunUntilIdle();
447   EXPECT_TRUE(called);
448
449   context()->storage()->FindRegistrationForId(
450       registration_id,
451       GURL("http://www.example.com"),
452       base::Bind(&ExpectRegisteredWorkers,
453                  SERVICE_WORKER_OK,
454                  version_id,
455                  false /* expect_waiting */,
456                  true /* expect_active */));
457   base::RunLoop().RunUntilIdle();
458 }
459
460 }  // namespace content