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.
5 #include "content/public/browser/service_worker_context.h"
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"
26 void SaveResponseCallback(bool* called,
27 int64* store_registration_id,
28 int64* store_version_id,
29 ServiceWorkerStatusCode status,
30 int64 registration_id,
32 EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
34 *store_registration_id = registration_id;
35 *store_version_id = version_id;
38 ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
40 int64* store_registration_id,
41 int64* store_version_id) {
42 return base::Bind(&SaveResponseCallback, called,
43 store_registration_id,
47 void CallCompletedCallback(bool* called, ServiceWorkerStatusCode) {
51 ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
53 return base::Bind(&CallCompletedCallback, called);
56 void ExpectRegisteredWorkers(
57 ServiceWorkerStatusCode expect_status,
58 int64 expect_version_id,
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);
70 EXPECT_TRUE(registration->waiting_version());
71 EXPECT_EQ(expect_version_id,
72 registration->waiting_version()->version_id());
74 EXPECT_FALSE(registration->waiting_version());
78 EXPECT_TRUE(registration->active_version());
79 EXPECT_EQ(expect_version_id,
80 registration->active_version()->version_id());
82 EXPECT_FALSE(registration->active_version());
86 class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
88 explicit RejectInstallTestHelper(int mock_render_process_id)
89 : EmbeddedWorkerTestHelper(mock_render_process_id) {}
91 virtual void OnInstallEvent(int embedded_worker_id,
93 int active_version_id) OVERRIDE {
95 new ServiceWorkerHostMsg_InstallEventFinished(
96 embedded_worker_id, request_id,
97 blink::WebServiceWorkerEventResultRejected));
101 class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
103 explicit RejectActivateTestHelper(int mock_render_process_id)
104 : EmbeddedWorkerTestHelper(mock_render_process_id) {}
106 virtual void OnActivateEvent(int embedded_worker_id,
107 int request_id) OVERRIDE {
109 new ServiceWorkerHostMsg_ActivateEventFinished(
110 embedded_worker_id, request_id,
111 blink::WebServiceWorkerEventResultRejected));
117 class ServiceWorkerContextTest : public testing::Test {
119 ServiceWorkerContextTest()
120 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
121 render_process_id_(99) {}
123 virtual void SetUp() OVERRIDE {
124 helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
127 virtual void TearDown() OVERRIDE {
131 ServiceWorkerContextCore* context() { return helper_->context(); }
134 TestBrowserThreadBundle browser_thread_bundle_;
135 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
136 const int render_process_id_;
139 // Make sure basic registration is working.
140 TEST_F(ServiceWorkerContextTest, Register) {
141 int64 registration_id = kInvalidServiceWorkerRegistrationId;
142 int64 version_id = kInvalidServiceWorkerVersionId;
144 context()->RegisterServiceWorker(
145 GURL("http://www.example.com/"),
146 GURL("http://www.example.com/service_worker.js"),
149 MakeRegisteredCallback(&called, ®istration_id, &version_id));
151 ASSERT_FALSE(called);
152 base::RunLoop().RunUntilIdle();
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);
167 context()->storage()->FindRegistrationForId(
169 GURL("http://www.example.com"),
170 base::Bind(&ExpectRegisteredWorkers,
173 false /* expect_waiting */,
174 true /* expect_active */));
175 base::RunLoop().RunUntilIdle();
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;
187 context()->RegisterServiceWorker(
188 GURL("http://www.example.com/"),
189 GURL("http://www.example.com/service_worker.js"),
192 MakeRegisteredCallback(&called, ®istration_id, &version_id));
194 ASSERT_FALSE(called);
195 base::RunLoop().RunUntilIdle();
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);
210 context()->storage()->FindRegistrationForId(
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();
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;
230 context()->RegisterServiceWorker(
231 GURL("http://www.example.com/"),
232 GURL("http://www.example.com/service_worker.js"),
235 MakeRegisteredCallback(&called, ®istration_id, &version_id));
237 ASSERT_FALSE(called);
238 base::RunLoop().RunUntilIdle();
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);
253 context()->storage()->FindRegistrationForId(
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();
264 // Make sure registrations are cleaned up when they are unregistered.
265 TEST_F(ServiceWorkerContextTest, Unregister) {
266 GURL pattern("http://www.example.com/");
269 int64 registration_id = kInvalidServiceWorkerRegistrationId;
270 int64 version_id = kInvalidServiceWorkerVersionId;
271 context()->RegisterServiceWorker(
273 GURL("http://www.example.com/service_worker.js"),
276 MakeRegisteredCallback(&called, ®istration_id, &version_id));
278 ASSERT_FALSE(called);
279 base::RunLoop().RunUntilIdle();
281 EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
282 EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
285 context()->UnregisterServiceWorker(pattern,
286 MakeUnregisteredCallback(&called));
288 ASSERT_FALSE(called);
289 base::RunLoop().RunUntilIdle();
292 context()->storage()->FindRegistrationForId(
295 base::Bind(&ExpectRegisteredWorkers,
296 SERVICE_WORKER_ERROR_NOT_FOUND,
297 kInvalidServiceWorkerVersionId,
298 false /* expect_waiting */,
299 false /* expect_active */));
300 base::RunLoop().RunUntilIdle();
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/");
309 int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
310 int64 old_version_id = kInvalidServiceWorkerVersionId;
311 context()->RegisterServiceWorker(
313 GURL("http://www.example.com/service_worker.js"),
316 MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
318 ASSERT_FALSE(called);
319 base::RunLoop().RunUntilIdle();
321 EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
322 EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
325 int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
326 int64 new_version_id = kInvalidServiceWorkerVersionId;
327 context()->RegisterServiceWorker(
329 GURL("http://www.example.com/service_worker_new.js"),
332 MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
334 ASSERT_FALSE(called);
335 base::RunLoop().RunUntilIdle();
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);
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");
353 int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
354 int64 old_version_id = kInvalidServiceWorkerVersionId;
355 context()->RegisterServiceWorker(
360 MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
362 ASSERT_FALSE(called);
363 base::RunLoop().RunUntilIdle();
365 EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
366 EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
369 int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
370 int64 new_version_id = kInvalidServiceWorkerVersionId;
371 context()->RegisterServiceWorker(
376 MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
378 ASSERT_FALSE(called);
379 base::RunLoop().RunUntilIdle();
381 EXPECT_EQ(old_registration_id, new_registration_id);
382 EXPECT_EQ(old_version_id, new_version_id);
385 // TODO(nhiroki): Test this for on-disk storage.
386 TEST_F(ServiceWorkerContextTest, DeleteAndStartOver) {
387 int64 registration_id = kInvalidServiceWorkerRegistrationId;
388 int64 version_id = kInvalidServiceWorkerVersionId;
390 context()->RegisterServiceWorker(
391 GURL("http://www.example.com/"),
392 GURL("http://www.example.com/service_worker.js"),
395 MakeRegisteredCallback(&called, ®istration_id, &version_id));
397 ASSERT_FALSE(called);
398 base::RunLoop().RunUntilIdle();
401 context()->storage()->FindRegistrationForId(
403 GURL("http://www.example.com"),
404 base::Bind(&ExpectRegisteredWorkers,
407 false /* expect_waiting */,
408 true /* expect_active */));
409 base::RunLoop().RunUntilIdle();
411 context()->ScheduleDeleteAndStartOver();
413 // The storage is disabled while the recovery process is running, so the
414 // operation should be failed.
415 context()->storage()->FindRegistrationForId(
417 GURL("http://www.example.com"),
418 base::Bind(&ExpectRegisteredWorkers,
419 SERVICE_WORKER_ERROR_FAILED,
421 false /* expect_waiting */,
422 true /* expect_active */));
423 base::RunLoop().RunUntilIdle();
425 // The context started over and the storage was re-initialized, so the
426 // registration should not be found.
427 context()->storage()->FindRegistrationForId(
429 GURL("http://www.example.com"),
430 base::Bind(&ExpectRegisteredWorkers,
431 SERVICE_WORKER_ERROR_NOT_FOUND,
433 false /* expect_waiting */,
434 true /* expect_active */));
435 base::RunLoop().RunUntilIdle();
438 context()->RegisterServiceWorker(
439 GURL("http://www.example.com/"),
440 GURL("http://www.example.com/service_worker.js"),
443 MakeRegisteredCallback(&called, ®istration_id, &version_id));
445 ASSERT_FALSE(called);
446 base::RunLoop().RunUntilIdle();
449 context()->storage()->FindRegistrationForId(
451 GURL("http://www.example.com"),
452 base::Bind(&ExpectRegisteredWorkers,
455 false /* expect_waiting */,
456 true /* expect_active */));
457 base::RunLoop().RunUntilIdle();
460 } // namespace content