Upstream version 10.39.225.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.get());
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       NULL,
148       MakeRegisteredCallback(&called, &registration_id, &version_id));
149
150   ASSERT_FALSE(called);
151   base::RunLoop().RunUntilIdle();
152   EXPECT_TRUE(called);
153
154   EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
155   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
156       EmbeddedWorkerMsg_StartWorker::ID));
157   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
158       ServiceWorkerMsg_InstallEvent::ID));
159   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
160       ServiceWorkerMsg_ActivateEvent::ID));
161   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
162       EmbeddedWorkerMsg_StopWorker::ID));
163   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
164   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
165
166   context()->storage()->FindRegistrationForId(
167       registration_id,
168       GURL("http://www.example.com"),
169       base::Bind(&ExpectRegisteredWorkers,
170                  SERVICE_WORKER_OK,
171                  version_id,
172                  false /* expect_waiting */,
173                  true /* expect_active */));
174   base::RunLoop().RunUntilIdle();
175 }
176
177 // Test registration when the service worker rejects the install event. The
178 // registration callback should indicate success, but there should be no waiting
179 // or active worker in the registration.
180 TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
181   helper_.reset();  // Make sure the process lookups stay overridden.
182   helper_.reset(new RejectInstallTestHelper(render_process_id_));
183   int64 registration_id = kInvalidServiceWorkerRegistrationId;
184   int64 version_id = kInvalidServiceWorkerVersionId;
185   bool called = false;
186   context()->RegisterServiceWorker(
187       GURL("http://www.example.com/"),
188       GURL("http://www.example.com/service_worker.js"),
189       NULL,
190       MakeRegisteredCallback(&called, &registration_id, &version_id));
191
192   ASSERT_FALSE(called);
193   base::RunLoop().RunUntilIdle();
194   EXPECT_TRUE(called);
195
196   EXPECT_EQ(3UL, helper_->ipc_sink()->message_count());
197   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
198       EmbeddedWorkerMsg_StartWorker::ID));
199   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
200       ServiceWorkerMsg_InstallEvent::ID));
201   EXPECT_FALSE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
202       ServiceWorkerMsg_ActivateEvent::ID));
203   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
204       EmbeddedWorkerMsg_StopWorker::ID));
205   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
206   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
207
208   context()->storage()->FindRegistrationForId(
209       registration_id,
210       GURL("http://www.example.com"),
211       base::Bind(&ExpectRegisteredWorkers,
212                  SERVICE_WORKER_ERROR_NOT_FOUND,
213                  kInvalidServiceWorkerVersionId,
214                  false /* expect_waiting */,
215                  false /* expect_active */));
216   base::RunLoop().RunUntilIdle();
217 }
218
219 // Test registration when the service worker rejects the activate event. The
220 // registration callback should indicate success, but there should be no waiting
221 // or active worker in the registration.
222 TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
223   helper_.reset();  // Make sure the process lookups stay overridden.
224   helper_.reset(new RejectActivateTestHelper(render_process_id_));
225   int64 registration_id = kInvalidServiceWorkerRegistrationId;
226   int64 version_id = kInvalidServiceWorkerVersionId;
227   bool called = false;
228   context()->RegisterServiceWorker(
229       GURL("http://www.example.com/"),
230       GURL("http://www.example.com/service_worker.js"),
231       NULL,
232       MakeRegisteredCallback(&called, &registration_id, &version_id));
233
234   ASSERT_FALSE(called);
235   base::RunLoop().RunUntilIdle();
236   EXPECT_TRUE(called);
237
238   EXPECT_EQ(4UL, helper_->ipc_sink()->message_count());
239   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
240       EmbeddedWorkerMsg_StartWorker::ID));
241   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
242       ServiceWorkerMsg_InstallEvent::ID));
243   EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
244       ServiceWorkerMsg_ActivateEvent::ID));
245   EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
246       EmbeddedWorkerMsg_StopWorker::ID));
247   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
248   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
249
250   context()->storage()->FindRegistrationForId(
251       registration_id,
252       GURL("http://www.example.com"),
253       base::Bind(&ExpectRegisteredWorkers,
254                  SERVICE_WORKER_ERROR_NOT_FOUND,
255                  kInvalidServiceWorkerVersionId,
256                  false /* expect_waiting */,
257                  false /* expect_active */));
258   base::RunLoop().RunUntilIdle();
259 }
260
261 // Make sure registrations are cleaned up when they are unregistered.
262 TEST_F(ServiceWorkerContextTest, Unregister) {
263   GURL pattern("http://www.example.com/");
264
265   bool called = false;
266   int64 registration_id = kInvalidServiceWorkerRegistrationId;
267   int64 version_id = kInvalidServiceWorkerVersionId;
268   context()->RegisterServiceWorker(
269       pattern,
270       GURL("http://www.example.com/service_worker.js"),
271       NULL,
272       MakeRegisteredCallback(&called, &registration_id, &version_id));
273
274   ASSERT_FALSE(called);
275   base::RunLoop().RunUntilIdle();
276   ASSERT_TRUE(called);
277   EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
278   EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
279
280   called = false;
281   context()->UnregisterServiceWorker(pattern,
282                                      MakeUnregisteredCallback(&called));
283
284   ASSERT_FALSE(called);
285   base::RunLoop().RunUntilIdle();
286   ASSERT_TRUE(called);
287
288   context()->storage()->FindRegistrationForId(
289       registration_id,
290       pattern.GetOrigin(),
291       base::Bind(&ExpectRegisteredWorkers,
292                  SERVICE_WORKER_ERROR_NOT_FOUND,
293                  kInvalidServiceWorkerVersionId,
294                  false /* expect_waiting */,
295                  false /* expect_active */));
296   base::RunLoop().RunUntilIdle();
297 }
298
299 // Make sure registering a new script creates a new version and shares an
300 // existing registration.
301 TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
302   GURL pattern("http://www.example.com/");
303
304   bool called = false;
305   int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
306   int64 old_version_id = kInvalidServiceWorkerVersionId;
307   context()->RegisterServiceWorker(
308       pattern,
309       GURL("http://www.example.com/service_worker.js"),
310       NULL,
311       MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
312
313   ASSERT_FALSE(called);
314   base::RunLoop().RunUntilIdle();
315   ASSERT_TRUE(called);
316   EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
317   EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
318
319   called = false;
320   int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
321   int64 new_version_id = kInvalidServiceWorkerVersionId;
322   context()->RegisterServiceWorker(
323       pattern,
324       GURL("http://www.example.com/service_worker_new.js"),
325       NULL,
326       MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
327
328   ASSERT_FALSE(called);
329   base::RunLoop().RunUntilIdle();
330   ASSERT_TRUE(called);
331
332   EXPECT_NE(kInvalidServiceWorkerRegistrationId, new_registration_id);
333   EXPECT_NE(kInvalidServiceWorkerVersionId, new_version_id);
334   EXPECT_EQ(old_registration_id, new_registration_id);
335   EXPECT_NE(old_version_id, new_version_id);
336 }
337
338 // Make sure that when registering a duplicate pattern+script_url
339 // combination, that the same registration is used.
340 TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
341   GURL pattern("http://www.example.com/");
342   GURL script_url("http://www.example.com/service_worker.js");
343
344   bool called = false;
345   int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
346   int64 old_version_id = kInvalidServiceWorkerVersionId;
347   context()->RegisterServiceWorker(
348       pattern,
349       script_url,
350       NULL,
351       MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
352
353   ASSERT_FALSE(called);
354   base::RunLoop().RunUntilIdle();
355   ASSERT_TRUE(called);
356   EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
357   EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
358
359   called = false;
360   int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
361   int64 new_version_id = kInvalidServiceWorkerVersionId;
362   context()->RegisterServiceWorker(
363       pattern,
364       script_url,
365       NULL,
366       MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
367
368   ASSERT_FALSE(called);
369   base::RunLoop().RunUntilIdle();
370   ASSERT_TRUE(called);
371   EXPECT_EQ(old_registration_id, new_registration_id);
372   EXPECT_EQ(old_version_id, new_version_id);
373 }
374
375 // TODO(nhiroki): Test this for on-disk storage.
376 TEST_F(ServiceWorkerContextTest, DeleteAndStartOver) {
377   int64 registration_id = kInvalidServiceWorkerRegistrationId;
378   int64 version_id = kInvalidServiceWorkerVersionId;
379   bool called = false;
380   context()->RegisterServiceWorker(
381       GURL("http://www.example.com/"),
382       GURL("http://www.example.com/service_worker.js"),
383       NULL,
384       MakeRegisteredCallback(&called, &registration_id, &version_id));
385
386   ASSERT_FALSE(called);
387   base::RunLoop().RunUntilIdle();
388   EXPECT_TRUE(called);
389
390   context()->storage()->FindRegistrationForId(
391       registration_id,
392       GURL("http://www.example.com"),
393       base::Bind(&ExpectRegisteredWorkers,
394                  SERVICE_WORKER_OK,
395                  version_id,
396                  false /* expect_waiting */,
397                  true /* expect_active */));
398   base::RunLoop().RunUntilIdle();
399
400   context()->ScheduleDeleteAndStartOver();
401
402   // The storage is disabled while the recovery process is running, so the
403   // operation should be failed.
404   context()->storage()->FindRegistrationForId(
405       registration_id,
406       GURL("http://www.example.com"),
407       base::Bind(&ExpectRegisteredWorkers,
408                  SERVICE_WORKER_ERROR_FAILED,
409                  version_id,
410                  false /* expect_waiting */,
411                  true /* expect_active */));
412   base::RunLoop().RunUntilIdle();
413
414   // The context started over and the storage was re-initialized, so the
415   // registration should not be found.
416   context()->storage()->FindRegistrationForId(
417       registration_id,
418       GURL("http://www.example.com"),
419       base::Bind(&ExpectRegisteredWorkers,
420                  SERVICE_WORKER_ERROR_NOT_FOUND,
421                  version_id,
422                  false /* expect_waiting */,
423                  true /* expect_active */));
424   base::RunLoop().RunUntilIdle();
425
426   called = false;
427   context()->RegisterServiceWorker(
428       GURL("http://www.example.com/"),
429       GURL("http://www.example.com/service_worker.js"),
430       NULL,
431       MakeRegisteredCallback(&called, &registration_id, &version_id));
432
433   ASSERT_FALSE(called);
434   base::RunLoop().RunUntilIdle();
435   EXPECT_TRUE(called);
436
437   context()->storage()->FindRegistrationForId(
438       registration_id,
439       GURL("http://www.example.com"),
440       base::Bind(&ExpectRegisteredWorkers,
441                  SERVICE_WORKER_OK,
442                  version_id,
443                  false /* expect_waiting */,
444                  true /* expect_active */));
445   base::RunLoop().RunUntilIdle();
446 }
447
448 }  // namespace content