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/browser/service_worker/service_worker_storage.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "content/browser/browser_thread_impl.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_registration.h"
13 #include "content/browser/service_worker/service_worker_version.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "testing/gtest/include/gtest/gtest.h"
21 void StatusCallback(bool* was_called
,
22 ServiceWorkerStatusCode
* result
,
23 ServiceWorkerStatusCode status
) {
28 ServiceWorkerStorage::StatusCallback
MakeStatusCallback(
30 ServiceWorkerStatusCode
* result
) {
31 return base::Bind(&StatusCallback
, was_called
, result
);
36 ServiceWorkerStatusCode
* result
,
37 scoped_refptr
<ServiceWorkerRegistration
>* found
,
38 ServiceWorkerStatusCode status
,
39 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
42 *found
= registration
;
45 ServiceWorkerStorage::FindRegistrationCallback
MakeFindCallback(
47 ServiceWorkerStatusCode
* result
,
48 scoped_refptr
<ServiceWorkerRegistration
>* found
) {
49 return base::Bind(&FindCallback
, was_called
, result
, found
);
54 std::vector
<ServiceWorkerRegistrationInfo
>* all_out
,
55 const std::vector
<ServiceWorkerRegistrationInfo
>& all
) {
60 ServiceWorkerStorage::GetAllRegistrationInfosCallback
MakeGetAllCallback(
62 std::vector
<ServiceWorkerRegistrationInfo
>* all
) {
63 return base::Bind(&GetAllCallback
, was_called
, all
);
68 class ServiceWorkerStorageTest
: public testing::Test
{
70 ServiceWorkerStorageTest()
71 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP
) {
74 virtual void SetUp() OVERRIDE
{
75 context_
.reset(new ServiceWorkerContextCore(
77 base::MessageLoopProxy::current(),
80 scoped_ptr
<ServiceWorkerProcessManager
>()));
81 context_ptr_
= context_
->AsWeakPtr();
82 storage()->simulated_lazy_initted_
= true;
85 virtual void TearDown() OVERRIDE
{
89 ServiceWorkerStorage
* storage() { return context_
->storage(); }
92 scoped_ptr
<ServiceWorkerContextCore
> context_
;
93 base::WeakPtr
<ServiceWorkerContextCore
> context_ptr_
;
94 TestBrowserThreadBundle browser_thread_bundle_
;
97 TEST_F(ServiceWorkerStorageTest
, StoreFindUpdateDeleteRegistration
) {
98 const GURL
kScope("http://www.test.com/scope/*");
99 const GURL
kScript("http://www.test.com/script.js");
100 const GURL
kDocumentUrl("http://www.test.com/scope/document.html");
101 const int64 kRegistrationId
= storage()->NewRegistrationId();
102 const int64 kVersionId
= storage()->NewVersionId();
104 bool was_called
= false;
105 ServiceWorkerStatusCode result
= SERVICE_WORKER_OK
;
106 scoped_refptr
<ServiceWorkerRegistration
> found_registration
;
108 // We shouldn't find anything without having stored anything.
109 storage()->FindRegistrationForDocument(
111 MakeFindCallback(&was_called
, &result
, &found_registration
));
112 base::RunLoop().RunUntilIdle();
113 ASSERT_TRUE(was_called
);
114 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
115 EXPECT_FALSE(found_registration
);
117 storage()->FindRegistrationForPattern(
119 MakeFindCallback(&was_called
, &result
, &found_registration
));
120 base::RunLoop().RunUntilIdle();
121 ASSERT_TRUE(was_called
);
122 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
123 EXPECT_FALSE(found_registration
);
125 storage()->FindRegistrationForId(
127 MakeFindCallback(&was_called
, &result
, &found_registration
));
128 base::RunLoop().RunUntilIdle();
129 ASSERT_TRUE(was_called
);
130 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
131 EXPECT_FALSE(found_registration
);
135 scoped_refptr
<ServiceWorkerRegistration
> live_registration
=
136 new ServiceWorkerRegistration(
137 kScope
, kScript
, kRegistrationId
, context_ptr_
);
138 scoped_refptr
<ServiceWorkerVersion
> live_version
=
139 new ServiceWorkerVersion(
140 live_registration
, kVersionId
, context_ptr_
);
141 live_version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
142 live_registration
->set_pending_version(live_version
);
143 storage()->StoreRegistration(live_registration
, live_version
,
144 MakeStatusCallback(&was_called
, &result
));
145 EXPECT_FALSE(was_called
); // always async
146 base::RunLoop().RunUntilIdle();
147 ASSERT_TRUE(was_called
);
148 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
151 // Now we should find it and get the live ptr back immediately.
152 storage()->FindRegistrationForDocument(
154 MakeFindCallback(&was_called
, &result
, &found_registration
));
155 ASSERT_TRUE(was_called
);
156 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
157 EXPECT_EQ(live_registration
, found_registration
);
159 found_registration
= NULL
;
161 // But FindRegistrationForPattern is always async.
162 storage()->FindRegistrationForPattern(
164 MakeFindCallback(&was_called
, &result
, &found_registration
));
165 EXPECT_FALSE(was_called
);
166 base::RunLoop().RunUntilIdle();
167 ASSERT_TRUE(was_called
);
168 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
169 EXPECT_EQ(live_registration
, found_registration
);
171 found_registration
= NULL
;
173 // Can be found by id too.
174 storage()->FindRegistrationForId(
176 MakeFindCallback(&was_called
, &result
, &found_registration
));
177 base::RunLoop().RunUntilIdle();
178 ASSERT_TRUE(was_called
);
179 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
180 ASSERT_TRUE(found_registration
);
181 EXPECT_EQ(kRegistrationId
, found_registration
->id());
182 EXPECT_EQ(live_registration
, found_registration
);
184 found_registration
= NULL
;
186 // Drop the live registration, but keep the version live.
187 live_registration
= NULL
;
189 // Now FindRegistrationForDocument should be async.
190 storage()->FindRegistrationForDocument(
192 MakeFindCallback(&was_called
, &result
, &found_registration
));
193 EXPECT_FALSE(was_called
);
194 base::RunLoop().RunUntilIdle();
195 ASSERT_TRUE(was_called
);
196 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
197 ASSERT_TRUE(found_registration
);
198 EXPECT_EQ(kRegistrationId
, found_registration
->id());
199 EXPECT_TRUE(found_registration
->HasOneRef());
200 EXPECT_EQ(live_version
,
201 found_registration
->pending_version());
203 found_registration
= NULL
;
205 // Drop the live version too.
208 // And FindRegistrationForPattern is always async.
209 storage()->FindRegistrationForPattern(
211 MakeFindCallback(&was_called
, &result
, &found_registration
));
212 EXPECT_FALSE(was_called
);
213 base::RunLoop().RunUntilIdle();
214 ASSERT_TRUE(was_called
);
215 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
216 ASSERT_TRUE(found_registration
);
217 EXPECT_EQ(kRegistrationId
, found_registration
->id());
218 EXPECT_TRUE(found_registration
->HasOneRef());
219 EXPECT_FALSE(found_registration
->active_version());
220 ASSERT_TRUE(found_registration
->pending_version());
221 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
222 found_registration
->pending_version()->status());
226 scoped_refptr
<ServiceWorkerVersion
> temp_version
=
227 found_registration
->pending_version();
228 found_registration
->set_pending_version(NULL
);
229 temp_version
->SetStatus(ServiceWorkerVersion::ACTIVE
);
230 found_registration
->set_active_version(temp_version
);
232 storage()->UpdateToActiveState(
234 MakeStatusCallback(&was_called
, &result
));
235 EXPECT_FALSE(was_called
);
236 base::RunLoop().RunUntilIdle();
237 ASSERT_TRUE(was_called
);
238 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
240 found_registration
= NULL
;
242 // Trying to update a unstored registration to active should fail.
243 scoped_refptr
<ServiceWorkerRegistration
> unstored_registration
=
244 new ServiceWorkerRegistration(
245 kScope
, kScript
, kRegistrationId
+ 1, context_ptr_
);
246 storage()->UpdateToActiveState(
247 unstored_registration
,
248 MakeStatusCallback(&was_called
, &result
));
249 EXPECT_FALSE(was_called
);
250 base::RunLoop().RunUntilIdle();
251 ASSERT_TRUE(was_called
);
252 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
254 unstored_registration
= NULL
;
256 // The Find methods should return a registration with an active version.
257 storage()->FindRegistrationForDocument(
259 MakeFindCallback(&was_called
, &result
, &found_registration
));
260 EXPECT_FALSE(was_called
);
261 base::RunLoop().RunUntilIdle();
262 ASSERT_TRUE(was_called
);
263 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
264 ASSERT_TRUE(found_registration
);
265 EXPECT_EQ(kRegistrationId
, found_registration
->id());
266 EXPECT_TRUE(found_registration
->HasOneRef());
267 EXPECT_FALSE(found_registration
->pending_version());
268 ASSERT_TRUE(found_registration
->active_version());
269 EXPECT_EQ(ServiceWorkerVersion::ACTIVE
,
270 found_registration
->active_version()->status());
273 // Delete from storage but with a instance still live.
274 EXPECT_TRUE(context_
->GetLiveVersion(kRegistrationId
));
275 storage()->DeleteRegistration(
277 MakeStatusCallback(&was_called
, &result
));
278 EXPECT_FALSE(was_called
);
279 base::RunLoop().RunUntilIdle();
280 EXPECT_TRUE(was_called
);
281 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
282 EXPECT_TRUE(context_
->GetLiveVersion(kRegistrationId
));
285 // Should no longer be found.
286 storage()->FindRegistrationForId(
288 MakeFindCallback(&was_called
, &result
, &found_registration
));
289 base::RunLoop().RunUntilIdle();
290 ASSERT_TRUE(was_called
);
291 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
292 EXPECT_FALSE(found_registration
);
295 // Deleting an unstored registration should fail.
296 storage()->DeleteRegistration(
298 MakeStatusCallback(&was_called
, &result
));
299 EXPECT_FALSE(was_called
);
300 base::RunLoop().RunUntilIdle();
301 EXPECT_TRUE(was_called
);
302 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
306 TEST_F(ServiceWorkerStorageTest
, InstallingRegistrationsAreFindable
) {
307 const GURL
kScope("http://www.test.com/scope/*");
308 const GURL
kScript("http://www.test.com/script.js");
309 const GURL
kDocumentUrl("http://www.test.com/scope/document.html");
310 const int64 kRegistrationId
= storage()->NewRegistrationId();
311 const int64 kVersionId
= storage()->NewVersionId();
313 bool was_called
= false;
314 ServiceWorkerStatusCode result
= SERVICE_WORKER_OK
;
315 scoped_refptr
<ServiceWorkerRegistration
> found_registration
;
317 // Create an unstored registration.
318 scoped_refptr
<ServiceWorkerRegistration
> live_registration
=
319 new ServiceWorkerRegistration(
320 kScope
, kScript
, kRegistrationId
, context_ptr_
);
321 scoped_refptr
<ServiceWorkerVersion
> live_version
=
322 new ServiceWorkerVersion(
323 live_registration
, kVersionId
, context_ptr_
);
324 live_version
->SetStatus(ServiceWorkerVersion::INSTALLING
);
325 live_registration
->set_pending_version(live_version
);
327 // Should not be findable, including by GetAllRegistrations.
328 storage()->FindRegistrationForId(
330 MakeFindCallback(&was_called
, &result
, &found_registration
));
331 base::RunLoop().RunUntilIdle();
332 ASSERT_TRUE(was_called
);
333 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
334 EXPECT_FALSE(found_registration
);
336 storage()->FindRegistrationForDocument(
338 MakeFindCallback(&was_called
, &result
, &found_registration
));
339 base::RunLoop().RunUntilIdle();
340 ASSERT_TRUE(was_called
);
341 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
342 EXPECT_FALSE(found_registration
);
344 storage()->FindRegistrationForPattern(
346 MakeFindCallback(&was_called
, &result
, &found_registration
));
347 base::RunLoop().RunUntilIdle();
348 ASSERT_TRUE(was_called
);
349 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
350 EXPECT_FALSE(found_registration
);
352 std::vector
<ServiceWorkerRegistrationInfo
> all_registrations
;
353 storage()->GetAllRegistrations(
354 MakeGetAllCallback(&was_called
, &all_registrations
));
355 base::RunLoop().RunUntilIdle();
356 ASSERT_TRUE(was_called
);
357 EXPECT_TRUE(all_registrations
.empty());
360 // Notify storage of it being installed.
361 storage()->NotifyInstallingRegistration(live_registration
);
363 // Now should be findable.
364 storage()->FindRegistrationForId(
366 MakeFindCallback(&was_called
, &result
, &found_registration
));
367 base::RunLoop().RunUntilIdle();
368 ASSERT_TRUE(was_called
);
369 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
370 EXPECT_EQ(live_registration
, found_registration
);
372 found_registration
= NULL
;
373 storage()->FindRegistrationForDocument(
375 MakeFindCallback(&was_called
, &result
, &found_registration
));
376 base::RunLoop().RunUntilIdle();
377 ASSERT_TRUE(was_called
);
378 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
379 EXPECT_EQ(live_registration
, found_registration
);
381 found_registration
= NULL
;
382 storage()->FindRegistrationForPattern(
384 MakeFindCallback(&was_called
, &result
, &found_registration
));
385 base::RunLoop().RunUntilIdle();
386 ASSERT_TRUE(was_called
);
387 EXPECT_EQ(SERVICE_WORKER_OK
, result
);
388 EXPECT_EQ(live_registration
, found_registration
);
390 found_registration
= NULL
;
391 storage()->GetAllRegistrations(
392 MakeGetAllCallback(&was_called
, &all_registrations
));
393 base::RunLoop().RunUntilIdle();
394 ASSERT_TRUE(was_called
);
395 EXPECT_EQ(1u, all_registrations
.size());
397 all_registrations
.clear();
399 // Notify storage of installation no longer happening.
400 storage()->NotifyDoneInstallingRegistration(live_registration
);
402 // Once again, should not be findable.
403 storage()->FindRegistrationForId(
405 MakeFindCallback(&was_called
, &result
, &found_registration
));
406 base::RunLoop().RunUntilIdle();
407 ASSERT_TRUE(was_called
);
408 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
409 EXPECT_FALSE(found_registration
);
411 storage()->FindRegistrationForDocument(
413 MakeFindCallback(&was_called
, &result
, &found_registration
));
414 base::RunLoop().RunUntilIdle();
415 ASSERT_TRUE(was_called
);
416 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
417 EXPECT_FALSE(found_registration
);
419 storage()->FindRegistrationForPattern(
421 MakeFindCallback(&was_called
, &result
, &found_registration
));
422 base::RunLoop().RunUntilIdle();
423 ASSERT_TRUE(was_called
);
424 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, result
);
425 EXPECT_FALSE(found_registration
);
428 storage()->GetAllRegistrations(
429 MakeGetAllCallback(&was_called
, &all_registrations
));
430 base::RunLoop().RunUntilIdle();
431 ASSERT_TRUE(was_called
);
432 EXPECT_TRUE(all_registrations
.empty());
436 } // namespace content