Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_storage_unittest.cc
blob9eb8af1cdd67490972b8301291f1104865422e63
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 <string>
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_disk_cache.h"
15 #include "content/browser/service_worker/service_worker_registration.h"
16 #include "content/browser/service_worker/service_worker_storage.h"
17 #include "content/browser/service_worker/service_worker_version.h"
18 #include "content/common/service_worker/service_worker_status_code.h"
19 #include "content/common/service_worker/service_worker_utils.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "ipc/ipc_message.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/http/http_response_headers.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using net::IOBuffer;
29 using net::TestCompletionCallback;
30 using net::WrappedIOBuffer;
32 namespace content {
34 namespace {
36 typedef ServiceWorkerDatabase::RegistrationData RegistrationData;
37 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord;
39 void StatusAndQuitCallback(ServiceWorkerStatusCode* result,
40 const base::Closure& quit_closure,
41 ServiceWorkerStatusCode status) {
42 *result = status;
43 quit_closure.Run();
46 void StatusCallback(bool* was_called,
47 ServiceWorkerStatusCode* result,
48 ServiceWorkerStatusCode status) {
49 *was_called = true;
50 *result = status;
53 ServiceWorkerStorage::StatusCallback MakeStatusCallback(
54 bool* was_called,
55 ServiceWorkerStatusCode* result) {
56 return base::Bind(&StatusCallback, was_called, result);
59 void FindCallback(
60 bool* was_called,
61 ServiceWorkerStatusCode* result,
62 scoped_refptr<ServiceWorkerRegistration>* found,
63 ServiceWorkerStatusCode status,
64 const scoped_refptr<ServiceWorkerRegistration>& registration) {
65 *was_called = true;
66 *result = status;
67 *found = registration;
70 ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
71 bool* was_called,
72 ServiceWorkerStatusCode* result,
73 scoped_refptr<ServiceWorkerRegistration>* found) {
74 return base::Bind(&FindCallback, was_called, result, found);
77 void GetAllCallback(
78 bool* was_called,
79 std::vector<scoped_refptr<ServiceWorkerRegistration>>* all_out,
80 const std::vector<scoped_refptr<ServiceWorkerRegistration>>& all) {
81 *was_called = true;
82 *all_out = all;
85 void GetAllInfosCallback(
86 bool* was_called,
87 std::vector<ServiceWorkerRegistrationInfo>* all_out,
88 const std::vector<ServiceWorkerRegistrationInfo>& all) {
89 *was_called = true;
90 *all_out = all;
93 ServiceWorkerStorage::GetRegistrationsCallback MakeGetRegistrationsCallback(
94 bool* was_called,
95 std::vector<scoped_refptr<ServiceWorkerRegistration>>* all) {
96 return base::Bind(&GetAllCallback, was_called, all);
99 ServiceWorkerStorage::GetRegistrationsInfosCallback
100 MakeGetRegistrationsInfosCallback(
101 bool* was_called,
102 std::vector<ServiceWorkerRegistrationInfo>* all) {
103 return base::Bind(&GetAllInfosCallback, was_called, all);
106 void GetUserDataCallback(
107 bool* was_called,
108 std::string* data_out,
109 ServiceWorkerStatusCode* status_out,
110 const std::string& data,
111 ServiceWorkerStatusCode status) {
112 *was_called = true;
113 *data_out = data;
114 *status_out = status;
117 void GetUserDataForAllRegistrationsCallback(
118 bool* was_called,
119 std::vector<std::pair<int64, std::string>>* data_out,
120 ServiceWorkerStatusCode* status_out,
121 const std::vector<std::pair<int64, std::string>>& data,
122 ServiceWorkerStatusCode status) {
123 *was_called = true;
124 *data_out = data;
125 *status_out = status;
128 void WriteResponse(
129 ServiceWorkerStorage* storage, int64 id,
130 const std::string& headers,
131 IOBuffer* body, int length) {
132 scoped_ptr<ServiceWorkerResponseWriter> writer =
133 storage->CreateResponseWriter(id);
135 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
136 info->request_time = base::Time::Now();
137 info->response_time = base::Time::Now();
138 info->was_cached = false;
139 info->headers = new net::HttpResponseHeaders(headers);
140 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
141 new HttpResponseInfoIOBuffer(info.release());
143 TestCompletionCallback cb;
144 writer->WriteInfo(info_buffer.get(), cb.callback());
145 int rv = cb.WaitForResult();
146 EXPECT_LT(0, rv);
149 TestCompletionCallback cb;
150 writer->WriteData(body, length, cb.callback());
151 int rv = cb.WaitForResult();
152 EXPECT_EQ(length, rv);
156 void WriteStringResponse(
157 ServiceWorkerStorage* storage, int64 id,
158 const std::string& headers,
159 const std::string& body) {
160 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
161 WriteResponse(storage, id, headers, body_buffer.get(), body.length());
164 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
165 scoped_ptr<ServiceWorkerResponseWriter> writer =
166 storage->CreateResponseWriter(id);
168 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
169 const char kHttpBody[] = "Hello";
170 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
171 WriteStringResponse(storage, id, headers, std::string(kHttpBody));
174 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
175 bool expected_positive_result) {
176 const std::string kExpectedHttpBody("Hello");
177 scoped_ptr<ServiceWorkerResponseReader> reader =
178 storage->CreateResponseReader(id);
179 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
180 new HttpResponseInfoIOBuffer();
182 TestCompletionCallback cb;
183 reader->ReadInfo(info_buffer.get(), cb.callback());
184 int rv = cb.WaitForResult();
185 if (expected_positive_result)
186 EXPECT_LT(0, rv);
187 if (rv <= 0)
188 return false;
191 std::string received_body;
193 const int kBigEnough = 512;
194 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
195 TestCompletionCallback cb;
196 reader->ReadData(buffer.get(), kBigEnough, cb.callback());
197 int rv = cb.WaitForResult();
198 EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
199 if (rv <= 0)
200 return false;
201 received_body.assign(buffer->data(), rv);
204 bool status_match =
205 std::string("HONKYDORY") ==
206 info_buffer->http_info->headers->GetStatusText();
207 bool data_match = kExpectedHttpBody == received_body;
209 EXPECT_TRUE(status_match);
210 EXPECT_TRUE(data_match);
211 return status_match && data_match;
214 int WriteResponseMetadata(ServiceWorkerStorage* storage,
215 int64 id,
216 const std::string& metadata) {
217 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(metadata.data()));
218 scoped_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer =
219 storage->CreateResponseMetadataWriter(id);
220 TestCompletionCallback cb;
221 metadata_writer->WriteMetadata(body_buffer.get(), metadata.length(),
222 cb.callback());
223 return cb.WaitForResult();
226 int WriteMetadata(ServiceWorkerVersion* version,
227 const GURL& url,
228 const std::string& metadata) {
229 const std::vector<char> data(metadata.begin(), metadata.end());
230 EXPECT_TRUE(version);
231 TestCompletionCallback cb;
232 version->script_cache_map()->WriteMetadata(url, data, cb.callback());
233 return cb.WaitForResult();
236 int ClearMetadata(ServiceWorkerVersion* version, const GURL& url) {
237 EXPECT_TRUE(version);
238 TestCompletionCallback cb;
239 version->script_cache_map()->ClearMetadata(url, cb.callback());
240 return cb.WaitForResult();
243 bool VerifyResponseMetadata(ServiceWorkerStorage* storage,
244 int64 id,
245 const std::string& expected_metadata) {
246 scoped_ptr<ServiceWorkerResponseReader> reader =
247 storage->CreateResponseReader(id);
248 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
249 new HttpResponseInfoIOBuffer();
251 TestCompletionCallback cb;
252 reader->ReadInfo(info_buffer.get(), cb.callback());
253 int rv = cb.WaitForResult();
254 EXPECT_LT(0, rv);
256 const net::HttpResponseInfo* read_head = info_buffer->http_info.get();
257 if (!read_head->metadata.get())
258 return false;
259 EXPECT_EQ(0, memcmp(expected_metadata.data(), read_head->metadata->data(),
260 expected_metadata.length()));
261 return true;
264 } // namespace
266 class ServiceWorkerStorageTest : public testing::Test {
267 public:
268 ServiceWorkerStorageTest()
269 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
272 void SetUp() override {
273 scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
274 new MockServiceWorkerDatabaseTaskManager(
275 base::ThreadTaskRunnerHandle::Get()));
276 context_.reset(
277 new ServiceWorkerContextCore(GetUserDataDirectory(),
278 database_task_manager.Pass(),
279 base::ThreadTaskRunnerHandle::Get(),
280 NULL,
281 NULL,
282 NULL,
283 NULL));
284 context_ptr_ = context_->AsWeakPtr();
287 void TearDown() override { context_.reset(); }
289 virtual base::FilePath GetUserDataDirectory() { return base::FilePath(); }
291 ServiceWorkerStorage* storage() { return context_->storage(); }
293 // A static class method for friendliness.
294 static void VerifyPurgeableListStatusCallback(
295 ServiceWorkerDatabase* database,
296 std::set<int64> *purgeable_ids,
297 bool* was_called,
298 ServiceWorkerStatusCode* result,
299 ServiceWorkerStatusCode status) {
300 *was_called = true;
301 *result = status;
302 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
303 database->GetPurgeableResourceIds(purgeable_ids));
306 protected:
307 void LazyInitialize() {
308 storage()->LazyInitialize(base::Bind(&base::DoNothing));
309 base::RunLoop().RunUntilIdle();
312 ServiceWorkerStatusCode StoreRegistration(
313 scoped_refptr<ServiceWorkerRegistration> registration,
314 scoped_refptr<ServiceWorkerVersion> version) {
315 bool was_called = false;
316 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
317 storage()->StoreRegistration(registration.get(),
318 version.get(),
319 MakeStatusCallback(&was_called, &result));
320 EXPECT_FALSE(was_called); // always async
321 base::RunLoop().RunUntilIdle();
322 EXPECT_TRUE(was_called);
323 return result;
326 ServiceWorkerStatusCode DeleteRegistration(
327 int64 registration_id,
328 const GURL& origin) {
329 bool was_called = false;
330 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
331 storage()->DeleteRegistration(
332 registration_id, origin, MakeStatusCallback(&was_called, &result));
333 EXPECT_FALSE(was_called); // always async
334 base::RunLoop().RunUntilIdle();
335 EXPECT_TRUE(was_called);
336 return result;
339 void GetAllRegistrationsInfos(
340 std::vector<ServiceWorkerRegistrationInfo>* registrations) {
341 bool was_called = false;
342 storage()->GetAllRegistrationsInfos(
343 MakeGetRegistrationsInfosCallback(&was_called, registrations));
344 EXPECT_FALSE(was_called); // always async
345 base::RunLoop().RunUntilIdle();
346 EXPECT_TRUE(was_called);
349 void GetRegistrationsForOrigin(
350 const GURL& origin,
351 std::vector<scoped_refptr<ServiceWorkerRegistration>>* registrations) {
352 bool was_called = false;
353 storage()->GetRegistrationsForOrigin(
354 origin, MakeGetRegistrationsCallback(&was_called, registrations));
355 EXPECT_FALSE(was_called); // always async
356 base::RunLoop().RunUntilIdle();
357 EXPECT_TRUE(was_called);
360 ServiceWorkerStatusCode GetUserData(
361 int64 registration_id,
362 const std::string& key,
363 std::string* data) {
364 bool was_called = false;
365 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
366 storage()->GetUserData(
367 registration_id, key,
368 base::Bind(&GetUserDataCallback, &was_called, data, &result));
369 EXPECT_FALSE(was_called); // always async
370 base::RunLoop().RunUntilIdle();
371 EXPECT_TRUE(was_called);
372 return result;
375 ServiceWorkerStatusCode StoreUserData(
376 int64 registration_id,
377 const GURL& origin,
378 const std::string& key,
379 const std::string& data) {
380 bool was_called = false;
381 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
382 storage()->StoreUserData(
383 registration_id, origin, key, data,
384 MakeStatusCallback(&was_called, &result));
385 EXPECT_FALSE(was_called); // always async
386 base::RunLoop().RunUntilIdle();
387 EXPECT_TRUE(was_called);
388 return result;
391 ServiceWorkerStatusCode ClearUserData(
392 int64 registration_id,
393 const std::string& key) {
394 bool was_called = false;
395 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
396 storage()->ClearUserData(
397 registration_id, key, MakeStatusCallback(&was_called, &result));
398 EXPECT_FALSE(was_called); // always async
399 base::RunLoop().RunUntilIdle();
400 EXPECT_TRUE(was_called);
401 return result;
404 ServiceWorkerStatusCode GetUserDataForAllRegistrations(
405 const std::string& key,
406 std::vector<std::pair<int64, std::string>>* data) {
407 bool was_called = false;
408 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
409 storage()->GetUserDataForAllRegistrations(
410 key, base::Bind(&GetUserDataForAllRegistrationsCallback, &was_called,
411 data, &result));
412 EXPECT_FALSE(was_called); // always async
413 base::RunLoop().RunUntilIdle();
414 EXPECT_TRUE(was_called);
415 return result;
418 ServiceWorkerStatusCode UpdateToActiveState(
419 scoped_refptr<ServiceWorkerRegistration> registration) {
420 bool was_called = false;
421 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
422 storage()->UpdateToActiveState(registration.get(),
423 MakeStatusCallback(&was_called, &result));
424 EXPECT_FALSE(was_called); // always async
425 base::RunLoop().RunUntilIdle();
426 EXPECT_TRUE(was_called);
427 return result;
430 void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration) {
431 storage()->UpdateLastUpdateCheckTime(registration);
432 base::RunLoop().RunUntilIdle();
435 ServiceWorkerStatusCode FindRegistrationForDocument(
436 const GURL& document_url,
437 scoped_refptr<ServiceWorkerRegistration>* registration) {
438 bool was_called = false;
439 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
440 storage()->FindRegistrationForDocument(
441 document_url, MakeFindCallback(&was_called, &result, registration));
442 base::RunLoop().RunUntilIdle();
443 EXPECT_TRUE(was_called);
444 return result;
447 ServiceWorkerStatusCode FindRegistrationForPattern(
448 const GURL& scope,
449 scoped_refptr<ServiceWorkerRegistration>* registration) {
450 bool was_called = false;
451 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
452 storage()->FindRegistrationForPattern(
453 scope, MakeFindCallback(&was_called, &result, registration));
454 EXPECT_FALSE(was_called); // always async
455 base::RunLoop().RunUntilIdle();
456 EXPECT_TRUE(was_called);
457 return result;
460 ServiceWorkerStatusCode FindRegistrationForId(
461 int64 registration_id,
462 const GURL& origin,
463 scoped_refptr<ServiceWorkerRegistration>* registration) {
464 bool was_called = false;
465 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
466 storage()->FindRegistrationForId(
467 registration_id, origin,
468 MakeFindCallback(&was_called, &result, registration));
469 base::RunLoop().RunUntilIdle();
470 EXPECT_TRUE(was_called);
471 return result;
474 ServiceWorkerStatusCode FindRegistrationForIdOnly(
475 int64 registration_id,
476 scoped_refptr<ServiceWorkerRegistration>* registration) {
477 bool was_called = false;
478 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
479 storage()->FindRegistrationForIdOnly(
480 registration_id, MakeFindCallback(&was_called, &result, registration));
481 base::RunLoop().RunUntilIdle();
482 EXPECT_TRUE(was_called);
483 return result;
486 scoped_ptr<ServiceWorkerContextCore> context_;
487 base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
488 TestBrowserThreadBundle browser_thread_bundle_;
491 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
492 const GURL kScope("http://www.test.not/scope/");
493 const GURL kScript("http://www.test.not/script.js");
494 const GURL kDocumentUrl("http://www.test.not/scope/document.html");
495 const GURL kResource1("http://www.test.not/scope/resource1.js");
496 const int64 kResource1Size = 1591234;
497 const GURL kResource2("http://www.test.not/scope/resource2.js");
498 const int64 kResource2Size = 51;
499 const int64 kRegistrationId = 0;
500 const int64 kVersionId = 0;
501 const base::Time kToday = base::Time::Now();
502 const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
504 scoped_refptr<ServiceWorkerRegistration> found_registration;
506 // We shouldn't find anything without having stored anything.
507 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
508 FindRegistrationForDocument(kDocumentUrl, &found_registration));
509 EXPECT_FALSE(found_registration.get());
511 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
512 FindRegistrationForPattern(kScope, &found_registration));
513 EXPECT_FALSE(found_registration.get());
515 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
516 FindRegistrationForId(
517 kRegistrationId, kScope.GetOrigin(), &found_registration));
518 EXPECT_FALSE(found_registration.get());
520 std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
521 resources.push_back(
522 ServiceWorkerDatabase::ResourceRecord(1, kResource1, kResource1Size));
523 resources.push_back(
524 ServiceWorkerDatabase::ResourceRecord(2, kResource2, kResource2Size));
526 // Store something.
527 scoped_refptr<ServiceWorkerRegistration> live_registration =
528 new ServiceWorkerRegistration(
529 kScope, kRegistrationId, context_ptr_);
530 scoped_refptr<ServiceWorkerVersion> live_version =
531 new ServiceWorkerVersion(
532 live_registration.get(), kScript, kVersionId, context_ptr_);
533 live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
534 live_version->script_cache_map()->SetResources(resources);
535 live_registration->SetWaitingVersion(live_version);
536 live_registration->set_last_update_check(kYesterday);
537 EXPECT_EQ(SERVICE_WORKER_OK,
538 StoreRegistration(live_registration, live_version));
540 // Now we should find it and get the live ptr back immediately.
541 EXPECT_EQ(SERVICE_WORKER_OK,
542 FindRegistrationForDocument(kDocumentUrl, &found_registration));
543 EXPECT_EQ(live_registration, found_registration);
544 EXPECT_EQ(kResource1Size + kResource2Size,
545 live_registration->resources_total_size_bytes());
546 EXPECT_EQ(kResource1Size + kResource2Size,
547 found_registration->resources_total_size_bytes());
548 found_registration = NULL;
550 // But FindRegistrationForPattern is always async.
551 EXPECT_EQ(SERVICE_WORKER_OK,
552 FindRegistrationForPattern(kScope, &found_registration));
553 EXPECT_EQ(live_registration, found_registration);
554 found_registration = NULL;
556 // Can be found by id too.
557 EXPECT_EQ(SERVICE_WORKER_OK,
558 FindRegistrationForId(
559 kRegistrationId, kScope.GetOrigin(), &found_registration));
560 ASSERT_TRUE(found_registration.get());
561 EXPECT_EQ(kRegistrationId, found_registration->id());
562 EXPECT_EQ(live_registration, found_registration);
563 found_registration = NULL;
565 // Can be found by just the id too.
566 EXPECT_EQ(SERVICE_WORKER_OK,
567 FindRegistrationForIdOnly(kRegistrationId, &found_registration));
568 ASSERT_TRUE(found_registration.get());
569 EXPECT_EQ(kRegistrationId, found_registration->id());
570 EXPECT_EQ(live_registration, found_registration);
571 found_registration = NULL;
573 // Drop the live registration, but keep the version live.
574 live_registration = NULL;
576 // Now FindRegistrationForDocument should be async.
577 EXPECT_EQ(SERVICE_WORKER_OK,
578 FindRegistrationForDocument(kDocumentUrl, &found_registration));
579 ASSERT_TRUE(found_registration.get());
580 EXPECT_EQ(kRegistrationId, found_registration->id());
581 EXPECT_TRUE(found_registration->HasOneRef());
583 // Check that sizes are populated correctly
584 EXPECT_EQ(live_version.get(), found_registration->waiting_version());
585 EXPECT_EQ(kResource1Size + kResource2Size,
586 found_registration->resources_total_size_bytes());
587 std::vector<ServiceWorkerRegistrationInfo> all_registrations;
588 GetAllRegistrationsInfos(&all_registrations);
589 EXPECT_EQ(1u, all_registrations.size());
590 ServiceWorkerRegistrationInfo info = all_registrations[0];
591 EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
592 all_registrations.clear();
594 // Finding by origin should provide the same result if origin is kScope.
595 std::vector<scoped_refptr<ServiceWorkerRegistration>>
596 registrations_for_origin;
597 GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
598 EXPECT_EQ(1u, registrations_for_origin.size());
599 registrations_for_origin.clear();
601 GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
602 &registrations_for_origin);
603 EXPECT_TRUE(registrations_for_origin.empty());
605 found_registration = NULL;
607 // Drop the live version too.
608 live_version = NULL;
610 // And FindRegistrationForPattern is always async.
611 EXPECT_EQ(SERVICE_WORKER_OK,
612 FindRegistrationForPattern(kScope, &found_registration));
613 ASSERT_TRUE(found_registration.get());
614 EXPECT_EQ(kRegistrationId, found_registration->id());
615 EXPECT_TRUE(found_registration->HasOneRef());
616 EXPECT_FALSE(found_registration->active_version());
617 ASSERT_TRUE(found_registration->waiting_version());
618 EXPECT_EQ(kYesterday, found_registration->last_update_check());
619 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
620 found_registration->waiting_version()->status());
622 // Update to active and update the last check time.
623 scoped_refptr<ServiceWorkerVersion> temp_version =
624 found_registration->waiting_version();
625 temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
626 found_registration->SetActiveVersion(temp_version);
627 temp_version = NULL;
628 EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
629 found_registration->set_last_update_check(kToday);
630 UpdateLastUpdateCheckTime(found_registration.get());
632 found_registration = NULL;
634 // Trying to update a unstored registration to active should fail.
635 scoped_refptr<ServiceWorkerRegistration> unstored_registration =
636 new ServiceWorkerRegistration(
637 kScope, kRegistrationId + 1, context_ptr_);
638 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
639 UpdateToActiveState(unstored_registration));
640 unstored_registration = NULL;
642 // The Find methods should return a registration with an active version
643 // and the expected update time.
644 EXPECT_EQ(SERVICE_WORKER_OK,
645 FindRegistrationForDocument(kDocumentUrl, &found_registration));
646 ASSERT_TRUE(found_registration.get());
647 EXPECT_EQ(kRegistrationId, found_registration->id());
648 EXPECT_TRUE(found_registration->HasOneRef());
649 EXPECT_FALSE(found_registration->waiting_version());
650 ASSERT_TRUE(found_registration->active_version());
651 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
652 found_registration->active_version()->status());
653 EXPECT_EQ(kToday, found_registration->last_update_check());
655 // Delete from storage but with a instance still live.
656 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
657 EXPECT_EQ(SERVICE_WORKER_OK,
658 DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
659 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
661 // Should no longer be found.
662 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
663 FindRegistrationForId(
664 kRegistrationId, kScope.GetOrigin(), &found_registration));
665 EXPECT_FALSE(found_registration.get());
666 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
667 FindRegistrationForIdOnly(kRegistrationId, &found_registration));
668 EXPECT_FALSE(found_registration.get());
670 // Deleting an unstored registration should succeed.
671 EXPECT_EQ(SERVICE_WORKER_OK,
672 DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
675 TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
676 const GURL kScope("http://www.test.not/scope/");
677 const GURL kScript("http://www.test.not/script.js");
678 const GURL kDocumentUrl("http://www.test.not/scope/document.html");
679 const int64 kRegistrationId = 0;
680 const int64 kVersionId = 0;
682 scoped_refptr<ServiceWorkerRegistration> found_registration;
684 // Create an unstored registration.
685 scoped_refptr<ServiceWorkerRegistration> live_registration =
686 new ServiceWorkerRegistration(
687 kScope, kRegistrationId, context_ptr_);
688 scoped_refptr<ServiceWorkerVersion> live_version =
689 new ServiceWorkerVersion(
690 live_registration.get(), kScript, kVersionId, context_ptr_);
691 live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
692 live_registration->SetWaitingVersion(live_version);
694 // Should not be findable, including by GetAllRegistrationsInfos.
695 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
696 FindRegistrationForId(
697 kRegistrationId, kScope.GetOrigin(), &found_registration));
698 EXPECT_FALSE(found_registration.get());
700 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
701 FindRegistrationForIdOnly(kRegistrationId, &found_registration));
702 EXPECT_FALSE(found_registration.get());
704 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
705 FindRegistrationForDocument(kDocumentUrl, &found_registration));
706 EXPECT_FALSE(found_registration.get());
708 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
709 FindRegistrationForPattern(kScope, &found_registration));
710 EXPECT_FALSE(found_registration.get());
712 std::vector<ServiceWorkerRegistrationInfo> all_registrations;
713 GetAllRegistrationsInfos(&all_registrations);
714 EXPECT_TRUE(all_registrations.empty());
716 std::vector<scoped_refptr<ServiceWorkerRegistration>>
717 registrations_for_origin;
718 GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
719 EXPECT_TRUE(registrations_for_origin.empty());
721 GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
722 &registrations_for_origin);
723 EXPECT_TRUE(registrations_for_origin.empty());
725 // Notify storage of it being installed.
726 storage()->NotifyInstallingRegistration(live_registration.get());
728 // Now should be findable.
729 EXPECT_EQ(SERVICE_WORKER_OK,
730 FindRegistrationForId(
731 kRegistrationId, kScope.GetOrigin(), &found_registration));
732 EXPECT_EQ(live_registration, found_registration);
733 found_registration = NULL;
735 EXPECT_EQ(SERVICE_WORKER_OK,
736 FindRegistrationForIdOnly(kRegistrationId, &found_registration));
737 EXPECT_EQ(live_registration, found_registration);
738 found_registration = NULL;
740 EXPECT_EQ(SERVICE_WORKER_OK,
741 FindRegistrationForDocument(kDocumentUrl, &found_registration));
742 EXPECT_EQ(live_registration, found_registration);
743 found_registration = NULL;
745 EXPECT_EQ(SERVICE_WORKER_OK,
746 FindRegistrationForPattern(kScope, &found_registration));
747 EXPECT_EQ(live_registration, found_registration);
748 found_registration = NULL;
750 GetAllRegistrationsInfos(&all_registrations);
751 EXPECT_EQ(1u, all_registrations.size());
752 all_registrations.clear();
754 // Finding by origin should provide the same result if origin is kScope.
755 GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
756 EXPECT_EQ(1u, registrations_for_origin.size());
757 registrations_for_origin.clear();
759 GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
760 &registrations_for_origin);
761 EXPECT_TRUE(registrations_for_origin.empty());
763 // Notify storage of installation no longer happening.
764 storage()->NotifyDoneInstallingRegistration(
765 live_registration.get(), NULL, SERVICE_WORKER_OK);
767 // Once again, should not be findable.
768 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
769 FindRegistrationForId(
770 kRegistrationId, kScope.GetOrigin(), &found_registration));
771 EXPECT_FALSE(found_registration.get());
773 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
774 FindRegistrationForIdOnly(kRegistrationId, &found_registration));
775 EXPECT_FALSE(found_registration.get());
777 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
778 FindRegistrationForDocument(kDocumentUrl, &found_registration));
779 EXPECT_FALSE(found_registration.get());
781 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
782 FindRegistrationForPattern(kScope, &found_registration));
783 EXPECT_FALSE(found_registration.get());
785 GetAllRegistrationsInfos(&all_registrations);
786 EXPECT_TRUE(all_registrations.empty());
788 GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
789 EXPECT_TRUE(registrations_for_origin.empty());
791 GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
792 &registrations_for_origin);
793 EXPECT_TRUE(registrations_for_origin.empty());
796 TEST_F(ServiceWorkerStorageTest, StoreUserData) {
797 const GURL kScope("http://www.test.not/scope/");
798 const GURL kScript("http://www.test.not/script.js");
799 const int64 kRegistrationId = 0;
800 const int64 kVersionId = 0;
802 LazyInitialize();
804 // Store a registration.
805 scoped_refptr<ServiceWorkerRegistration> live_registration =
806 new ServiceWorkerRegistration(
807 kScope, kRegistrationId, context_ptr_);
808 scoped_refptr<ServiceWorkerVersion> live_version =
809 new ServiceWorkerVersion(
810 live_registration.get(), kScript, kVersionId, context_ptr_);
811 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
812 records.push_back(ServiceWorkerDatabase::ResourceRecord(
813 1, live_version->script_url(), 100));
814 live_version->script_cache_map()->SetResources(records);
815 live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
816 live_registration->SetWaitingVersion(live_version);
817 EXPECT_EQ(SERVICE_WORKER_OK,
818 StoreRegistration(live_registration, live_version));
820 // Store user data associated with the registration.
821 std::string data_out;
822 EXPECT_EQ(SERVICE_WORKER_OK,
823 StoreUserData(kRegistrationId, kScope.GetOrigin(), "key", "data"));
824 EXPECT_EQ(SERVICE_WORKER_OK, GetUserData(kRegistrationId, "key", &data_out));
825 EXPECT_EQ("data", data_out);
826 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
827 GetUserData(kRegistrationId, "unknown_key", &data_out));
828 std::vector<std::pair<int64, std::string>> data_list_out;
829 EXPECT_EQ(SERVICE_WORKER_OK,
830 GetUserDataForAllRegistrations("key", &data_list_out));
831 ASSERT_EQ(1u, data_list_out.size());
832 EXPECT_EQ(kRegistrationId, data_list_out[0].first);
833 EXPECT_EQ("data", data_list_out[0].second);
834 data_list_out.clear();
835 EXPECT_EQ(SERVICE_WORKER_OK,
836 GetUserDataForAllRegistrations("unknown_key", &data_list_out));
837 EXPECT_EQ(0u, data_list_out.size());
838 EXPECT_EQ(SERVICE_WORKER_OK, ClearUserData(kRegistrationId, "key"));
839 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
840 GetUserData(kRegistrationId, "key", &data_out));
842 // User data should be deleted when the associated registration is deleted.
843 ASSERT_EQ(SERVICE_WORKER_OK,
844 StoreUserData(kRegistrationId, kScope.GetOrigin(), "key", "data"));
845 ASSERT_EQ(SERVICE_WORKER_OK,
846 GetUserData(kRegistrationId, "key", &data_out));
847 ASSERT_EQ("data", data_out);
849 EXPECT_EQ(SERVICE_WORKER_OK,
850 DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
851 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
852 GetUserData(kRegistrationId, "key", &data_out));
853 data_list_out.clear();
854 EXPECT_EQ(SERVICE_WORKER_OK,
855 GetUserDataForAllRegistrations("key", &data_list_out));
856 EXPECT_EQ(0u, data_list_out.size());
858 // Data access with an invalid registration id should be failed.
859 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
860 StoreUserData(kInvalidServiceWorkerRegistrationId,
861 kScope.GetOrigin(), "key", "data"));
862 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
863 GetUserData(kInvalidServiceWorkerRegistrationId, "key", &data_out));
864 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
865 ClearUserData(kInvalidServiceWorkerRegistrationId, "key"));
867 // Data access with an empty key should be failed.
868 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
869 StoreUserData(
870 kRegistrationId, kScope.GetOrigin(), std::string(), "data"));
871 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
872 GetUserData(kRegistrationId, std::string(), &data_out));
873 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
874 ClearUserData(kRegistrationId, std::string()));
875 data_list_out.clear();
876 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
877 GetUserDataForAllRegistrations(std::string(), &data_list_out));
880 class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
881 public:
882 void SetUp() override {
883 ServiceWorkerStorageTest::SetUp();
885 storage()->LazyInitialize(base::Bind(&base::DoNothing));
886 base::RunLoop().RunUntilIdle();
887 scope_ = GURL("http://www.test.not/scope/");
888 script_ = GURL("http://www.test.not/script.js");
889 import_ = GURL("http://www.test.not/import.js");
890 document_url_ = GURL("http://www.test.not/scope/document.html");
891 registration_id_ = storage()->NewRegistrationId();
892 version_id_ = storage()->NewVersionId();
893 resource_id1_ = storage()->NewResourceId();
894 resource_id2_ = storage()->NewResourceId();
895 resource_id1_size_ = 239193;
896 resource_id2_size_ = 59923;
898 // Cons up a new registration+version with two script resources.
899 RegistrationData data;
900 data.registration_id = registration_id_;
901 data.scope = scope_;
902 data.script = script_;
903 data.version_id = version_id_;
904 data.is_active = false;
905 std::vector<ResourceRecord> resources;
906 resources.push_back(
907 ResourceRecord(resource_id1_, script_, resource_id1_size_));
908 resources.push_back(
909 ResourceRecord(resource_id2_, import_, resource_id2_size_));
910 registration_ = storage()->GetOrCreateRegistration(data, resources);
911 registration_->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
913 // Add the resources ids to the uncommitted list.
914 storage()->StoreUncommittedResponseId(resource_id1_);
915 storage()->StoreUncommittedResponseId(resource_id2_);
916 base::RunLoop().RunUntilIdle();
917 std::set<int64> verify_ids;
918 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
919 storage()->database_->GetUncommittedResourceIds(&verify_ids));
920 EXPECT_EQ(2u, verify_ids.size());
922 // And dump something in the disk cache for them.
923 WriteBasicResponse(storage(), resource_id1_);
924 WriteBasicResponse(storage(), resource_id2_);
925 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
926 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
928 // Storing the registration/version should take the resources ids out
929 // of the uncommitted list.
930 EXPECT_EQ(
931 SERVICE_WORKER_OK,
932 StoreRegistration(registration_, registration_->waiting_version()));
933 verify_ids.clear();
934 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
935 storage()->database_->GetUncommittedResourceIds(&verify_ids));
936 EXPECT_TRUE(verify_ids.empty());
939 protected:
940 GURL scope_;
941 GURL script_;
942 GURL import_;
943 GURL document_url_;
944 int64 registration_id_;
945 int64 version_id_;
946 int64 resource_id1_;
947 uint64 resource_id1_size_;
948 int64 resource_id2_;
949 uint64 resource_id2_size_;
950 scoped_refptr<ServiceWorkerRegistration> registration_;
953 class ServiceWorkerResourceStorageDiskTest
954 : public ServiceWorkerResourceStorageTest {
955 public:
956 void SetUp() override {
957 ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
958 ServiceWorkerResourceStorageTest::SetUp();
961 base::FilePath GetUserDataDirectory() override {
962 return user_data_directory_.path();
965 protected:
966 base::ScopedTempDir user_data_directory_;
969 TEST_F(ServiceWorkerResourceStorageTest,
970 WriteMetadataWithServiceWorkerResponseMetadataWriter) {
971 const char kMetadata1[] = "Test metadata";
972 const char kMetadata2[] = "small";
973 int64 new_resource_id_ = storage()->NewResourceId();
974 // Writing metadata to nonexistent resoirce ID must fail.
975 EXPECT_GE(0, WriteResponseMetadata(storage(), new_resource_id_, kMetadata1));
977 // Check metadata is written.
978 EXPECT_EQ(static_cast<int>(strlen(kMetadata1)),
979 WriteResponseMetadata(storage(), resource_id1_, kMetadata1));
980 EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata1));
981 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
983 // Check metadata is written and truncated.
984 EXPECT_EQ(static_cast<int>(strlen(kMetadata2)),
985 WriteResponseMetadata(storage(), resource_id1_, kMetadata2));
986 EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata2));
987 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
989 // Check metadata is deleted.
990 EXPECT_EQ(0, WriteResponseMetadata(storage(), resource_id1_, ""));
991 EXPECT_FALSE(VerifyResponseMetadata(storage(), resource_id1_, ""));
992 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
995 TEST_F(ServiceWorkerResourceStorageTest,
996 WriteMetadataWithServiceWorkerScriptCacheMap) {
997 const char kMetadata1[] = "Test metadata";
998 const char kMetadata2[] = "small";
999 ServiceWorkerVersion* version = registration_->waiting_version();
1000 EXPECT_TRUE(version);
1002 // Writing metadata to nonexistent URL must fail.
1003 EXPECT_GE(0,
1004 WriteMetadata(version, GURL("http://www.test.not/nonexistent.js"),
1005 kMetadata1));
1006 // Clearing metadata of nonexistent URL must fail.
1007 EXPECT_GE(0,
1008 ClearMetadata(version, GURL("http://www.test.not/nonexistent.js")));
1010 // Check metadata is written.
1011 EXPECT_EQ(static_cast<int>(strlen(kMetadata1)),
1012 WriteMetadata(version, script_, kMetadata1));
1013 EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata1));
1014 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
1016 // Check metadata is written and truncated.
1017 EXPECT_EQ(static_cast<int>(strlen(kMetadata2)),
1018 WriteMetadata(version, script_, kMetadata2));
1019 EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata2));
1020 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
1022 // Check metadata is deleted.
1023 EXPECT_EQ(0, ClearMetadata(version, script_));
1024 EXPECT_FALSE(VerifyResponseMetadata(storage(), resource_id1_, ""));
1025 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
1028 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
1029 bool was_called = false;
1030 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
1031 std::set<int64> verify_ids;
1033 registration_->SetWaitingVersion(NULL);
1034 registration_ = NULL;
1036 // Deleting the registration should result in the resources being added to the
1037 // purgeable list and then doomed in the disk cache and removed from that
1038 // list.
1039 storage()->DeleteRegistration(
1040 registration_id_,
1041 scope_.GetOrigin(),
1042 base::Bind(&VerifyPurgeableListStatusCallback,
1043 base::Unretained(storage()->database_.get()),
1044 &verify_ids,
1045 &was_called,
1046 &result));
1047 base::RunLoop().RunUntilIdle();
1048 ASSERT_TRUE(was_called);
1049 EXPECT_EQ(SERVICE_WORKER_OK, result);
1050 EXPECT_EQ(2u, verify_ids.size());
1051 verify_ids.clear();
1052 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1053 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1054 EXPECT_TRUE(verify_ids.empty());
1056 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
1057 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
1060 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
1061 bool was_called = false;
1062 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
1063 std::set<int64> verify_ids;
1065 // Deleting the registration should result in the resources being added to the
1066 // purgeable list and then doomed in the disk cache and removed from that
1067 // list.
1068 storage()->DeleteRegistration(
1069 registration_->id(),
1070 scope_.GetOrigin(),
1071 base::Bind(&VerifyPurgeableListStatusCallback,
1072 base::Unretained(storage()->database_.get()),
1073 &verify_ids,
1074 &was_called,
1075 &result));
1076 base::RunLoop().RunUntilIdle();
1077 ASSERT_TRUE(was_called);
1078 EXPECT_EQ(SERVICE_WORKER_OK, result);
1079 EXPECT_EQ(2u, verify_ids.size());
1080 verify_ids.clear();
1081 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1082 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1083 EXPECT_EQ(2u, verify_ids.size());
1085 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
1086 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
1088 // Doom the version, now it happens.
1089 registration_->waiting_version()->Doom();
1090 base::RunLoop().RunUntilIdle();
1091 EXPECT_EQ(SERVICE_WORKER_OK, result);
1092 EXPECT_EQ(2u, verify_ids.size());
1093 verify_ids.clear();
1094 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1095 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1096 EXPECT_TRUE(verify_ids.empty());
1098 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
1099 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
1102 TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
1103 // Promote the worker to active and add a controllee.
1104 registration_->SetActiveVersion(registration_->waiting_version());
1105 storage()->UpdateToActiveState(
1106 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1107 scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
1108 33 /* dummy render process id */, MSG_ROUTING_NONE,
1109 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
1110 context_->AsWeakPtr(), NULL));
1111 registration_->active_version()->AddControllee(host.get());
1113 bool was_called = false;
1114 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
1115 std::set<int64> verify_ids;
1117 // Deleting the registration should move the resources to the purgeable list
1118 // but keep them available.
1119 storage()->DeleteRegistration(
1120 registration_->id(),
1121 scope_.GetOrigin(),
1122 base::Bind(&VerifyPurgeableListStatusCallback,
1123 base::Unretained(storage()->database_.get()),
1124 &verify_ids,
1125 &was_called,
1126 &result));
1127 base::RunLoop().RunUntilIdle();
1128 ASSERT_TRUE(was_called);
1129 EXPECT_EQ(SERVICE_WORKER_OK, result);
1130 EXPECT_EQ(2u, verify_ids.size());
1131 verify_ids.clear();
1132 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1133 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1134 EXPECT_EQ(2u, verify_ids.size());
1136 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
1137 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
1139 // Removing the controllee should cause the resources to be deleted.
1140 registration_->active_version()->RemoveControllee(host.get());
1141 registration_->active_version()->Doom();
1142 base::RunLoop().RunUntilIdle();
1143 verify_ids.clear();
1144 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1145 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1146 EXPECT_TRUE(verify_ids.empty());
1148 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
1149 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
1152 TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
1153 // Promote the worker to active and add a controllee.
1154 registration_->SetActiveVersion(registration_->waiting_version());
1155 registration_->SetWaitingVersion(NULL);
1156 storage()->UpdateToActiveState(
1157 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1158 scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
1159 33 /* dummy render process id */, MSG_ROUTING_NONE,
1160 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
1161 context_->AsWeakPtr(), NULL));
1162 registration_->active_version()->AddControllee(host.get());
1164 bool was_called = false;
1165 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
1166 std::set<int64> verify_ids;
1168 // Deleting the registration should move the resources to the purgeable list
1169 // but keep them available.
1170 storage()->DeleteRegistration(
1171 registration_->id(),
1172 scope_.GetOrigin(),
1173 base::Bind(&VerifyPurgeableListStatusCallback,
1174 base::Unretained(storage()->database_.get()),
1175 &verify_ids,
1176 &was_called,
1177 &result));
1178 base::RunLoop().RunUntilIdle();
1179 ASSERT_TRUE(was_called);
1180 EXPECT_EQ(SERVICE_WORKER_OK, result);
1181 EXPECT_EQ(2u, verify_ids.size());
1182 verify_ids.clear();
1183 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1184 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1185 EXPECT_EQ(2u, verify_ids.size());
1187 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
1188 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
1190 // Also add an uncommitted resource.
1191 int64 kStaleUncommittedResourceId = storage()->NewResourceId();
1192 storage()->StoreUncommittedResponseId(kStaleUncommittedResourceId);
1193 base::RunLoop().RunUntilIdle();
1194 verify_ids.clear();
1195 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1196 storage()->database_->GetUncommittedResourceIds(&verify_ids));
1197 EXPECT_EQ(1u, verify_ids.size());
1198 WriteBasicResponse(storage(), kStaleUncommittedResourceId);
1199 EXPECT_TRUE(
1200 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, true));
1202 // Simulate browser shutdown. The purgeable and uncommitted resources are now
1203 // stale.
1204 context_.reset();
1205 scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
1206 new MockServiceWorkerDatabaseTaskManager(
1207 base::ThreadTaskRunnerHandle::Get()));
1208 context_.reset(
1209 new ServiceWorkerContextCore(GetUserDataDirectory(),
1210 database_task_manager.Pass(),
1211 base::ThreadTaskRunnerHandle::Get(),
1212 NULL,
1213 NULL,
1214 NULL,
1215 NULL));
1216 storage()->LazyInitialize(base::Bind(&base::DoNothing));
1217 base::RunLoop().RunUntilIdle();
1219 // Store a new uncommitted resource. This triggers stale resource cleanup.
1220 int64 kNewResourceId = storage()->NewResourceId();
1221 WriteBasicResponse(storage(), kNewResourceId);
1222 storage()->StoreUncommittedResponseId(kNewResourceId);
1223 base::RunLoop().RunUntilIdle();
1225 // The stale resources should be purged, but the new resource should persist.
1226 verify_ids.clear();
1227 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1228 storage()->database_->GetUncommittedResourceIds(&verify_ids));
1229 ASSERT_EQ(1u, verify_ids.size());
1230 EXPECT_EQ(kNewResourceId, *verify_ids.begin());
1232 // Purging resources needs interactions with SimpleCache's worker thread,
1233 // so single RunUntilIdle() call may not be sufficient.
1234 while (storage()->is_purge_pending_)
1235 base::RunLoop().RunUntilIdle();
1237 verify_ids.clear();
1238 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1239 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1240 EXPECT_TRUE(verify_ids.empty());
1241 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
1242 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
1243 EXPECT_FALSE(
1244 VerifyBasicResponse(storage(), kStaleUncommittedResourceId, false));
1245 EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
1248 TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
1249 EXPECT_FALSE(storage()->IsDisabled());
1250 ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
1251 ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
1253 base::RunLoop run_loop;
1254 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
1255 storage()->DeleteAndStartOver(
1256 base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
1257 run_loop.Run();
1259 EXPECT_EQ(SERVICE_WORKER_OK, status);
1260 EXPECT_TRUE(storage()->IsDisabled());
1261 EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
1262 EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
1265 TEST_F(ServiceWorkerResourceStorageDiskTest,
1266 DeleteAndStartOver_UnrelatedFileExists) {
1267 EXPECT_FALSE(storage()->IsDisabled());
1268 ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
1269 ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
1271 // Create an unrelated file in the database directory to make sure such a file
1272 // does not prevent DeleteAndStartOver.
1273 base::FilePath file_path;
1274 ASSERT_TRUE(
1275 base::CreateTemporaryFileInDir(storage()->GetDatabasePath(), &file_path));
1276 ASSERT_TRUE(base::PathExists(file_path));
1278 base::RunLoop run_loop;
1279 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
1280 storage()->DeleteAndStartOver(
1281 base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
1282 run_loop.Run();
1284 EXPECT_EQ(SERVICE_WORKER_OK, status);
1285 EXPECT_TRUE(storage()->IsDisabled());
1286 EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
1287 EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
1290 TEST_F(ServiceWorkerResourceStorageDiskTest,
1291 DeleteAndStartOver_OpenedFileExists) {
1292 EXPECT_FALSE(storage()->IsDisabled());
1293 ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
1294 ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
1296 // Create an unrelated opened file in the database directory to make sure such
1297 // a file does not prevent DeleteAndStartOver on non-Windows platforms.
1298 base::FilePath file_path;
1299 base::ScopedFILE file(base::CreateAndOpenTemporaryFileInDir(
1300 storage()->GetDatabasePath(), &file_path));
1301 ASSERT_TRUE(file);
1302 ASSERT_TRUE(base::PathExists(file_path));
1304 base::RunLoop run_loop;
1305 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
1306 storage()->DeleteAndStartOver(
1307 base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
1308 run_loop.Run();
1310 #if defined(OS_WIN)
1311 // On Windows, deleting the directory containing an opened file should fail.
1312 EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
1313 EXPECT_TRUE(storage()->IsDisabled());
1314 EXPECT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
1315 EXPECT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
1316 #else
1317 EXPECT_EQ(SERVICE_WORKER_OK, status);
1318 EXPECT_TRUE(storage()->IsDisabled());
1319 EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
1320 EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
1321 #endif
1324 TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
1325 // Promote the worker to active worker and add a controllee.
1326 registration_->SetActiveVersion(registration_->waiting_version());
1327 storage()->UpdateToActiveState(
1328 registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1329 scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
1330 33 /* dummy render process id */, MSG_ROUTING_NONE,
1331 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
1332 context_->AsWeakPtr(), NULL));
1333 registration_->active_version()->AddControllee(host.get());
1335 bool was_called = false;
1336 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
1337 std::set<int64> verify_ids;
1339 // Make an updated registration.
1340 scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
1341 registration_.get(), script_, storage()->NewVersionId(), context_ptr_);
1342 live_version->SetStatus(ServiceWorkerVersion::NEW);
1343 registration_->SetWaitingVersion(live_version);
1344 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
1345 records.push_back(ServiceWorkerDatabase::ResourceRecord(
1346 10, live_version->script_url(), 100));
1347 live_version->script_cache_map()->SetResources(records);
1349 // Writing the registration should move the old version's resources to the
1350 // purgeable list but keep them available.
1351 storage()->StoreRegistration(
1352 registration_.get(),
1353 registration_->waiting_version(),
1354 base::Bind(&VerifyPurgeableListStatusCallback,
1355 base::Unretained(storage()->database_.get()),
1356 &verify_ids,
1357 &was_called,
1358 &result));
1359 base::RunLoop().RunUntilIdle();
1360 ASSERT_TRUE(was_called);
1361 EXPECT_EQ(SERVICE_WORKER_OK, result);
1362 EXPECT_EQ(2u, verify_ids.size());
1363 verify_ids.clear();
1364 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1365 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1366 EXPECT_EQ(2u, verify_ids.size());
1368 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
1369 EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
1371 // Removing the controllee should cause the old version's resources to be
1372 // deleted.
1373 registration_->active_version()->RemoveControllee(host.get());
1374 registration_->active_version()->Doom();
1375 base::RunLoop().RunUntilIdle();
1376 verify_ids.clear();
1377 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
1378 storage()->database_->GetPurgeableResourceIds(&verify_ids));
1379 EXPECT_TRUE(verify_ids.empty());
1381 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
1382 EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
1385 TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
1386 const GURL kDocumentUrl("http://www.example.com/scope/foo");
1387 scoped_refptr<ServiceWorkerRegistration> found_registration;
1389 // Registration for "/scope/".
1390 const GURL kScope1("http://www.example.com/scope/");
1391 const GURL kScript1("http://www.example.com/script1.js");
1392 const int64 kRegistrationId1 = 1;
1393 const int64 kVersionId1 = 1;
1394 scoped_refptr<ServiceWorkerRegistration> live_registration1 =
1395 new ServiceWorkerRegistration(
1396 kScope1, kRegistrationId1, context_ptr_);
1397 scoped_refptr<ServiceWorkerVersion> live_version1 =
1398 new ServiceWorkerVersion(
1399 live_registration1.get(), kScript1, kVersionId1, context_ptr_);
1400 std::vector<ServiceWorkerDatabase::ResourceRecord> records1;
1401 records1.push_back(ServiceWorkerDatabase::ResourceRecord(
1402 1, live_version1->script_url(), 100));
1403 live_version1->script_cache_map()->SetResources(records1);
1404 live_version1->SetStatus(ServiceWorkerVersion::INSTALLED);
1405 live_registration1->SetWaitingVersion(live_version1);
1407 // Registration for "/scope/foo".
1408 const GURL kScope2("http://www.example.com/scope/foo");
1409 const GURL kScript2("http://www.example.com/script2.js");
1410 const int64 kRegistrationId2 = 2;
1411 const int64 kVersionId2 = 2;
1412 scoped_refptr<ServiceWorkerRegistration> live_registration2 =
1413 new ServiceWorkerRegistration(
1414 kScope2, kRegistrationId2, context_ptr_);
1415 scoped_refptr<ServiceWorkerVersion> live_version2 =
1416 new ServiceWorkerVersion(
1417 live_registration2.get(), kScript2, kVersionId2, context_ptr_);
1418 std::vector<ServiceWorkerDatabase::ResourceRecord> records2;
1419 records2.push_back(ServiceWorkerDatabase::ResourceRecord(
1420 2, live_version2->script_url(), 100));
1421 live_version2->script_cache_map()->SetResources(records2);
1422 live_version2->SetStatus(ServiceWorkerVersion::INSTALLED);
1423 live_registration2->SetWaitingVersion(live_version2);
1425 // Registration for "/scope/foobar".
1426 const GURL kScope3("http://www.example.com/scope/foobar");
1427 const GURL kScript3("http://www.example.com/script3.js");
1428 const int64 kRegistrationId3 = 3;
1429 const int64 kVersionId3 = 3;
1430 scoped_refptr<ServiceWorkerRegistration> live_registration3 =
1431 new ServiceWorkerRegistration(
1432 kScope3, kRegistrationId3, context_ptr_);
1433 scoped_refptr<ServiceWorkerVersion> live_version3 =
1434 new ServiceWorkerVersion(
1435 live_registration3.get(), kScript3, kVersionId3, context_ptr_);
1436 std::vector<ServiceWorkerDatabase::ResourceRecord> records3;
1437 records3.push_back(ServiceWorkerDatabase::ResourceRecord(
1438 3, live_version3->script_url(), 100));
1439 live_version3->script_cache_map()->SetResources(records3);
1440 live_version3->SetStatus(ServiceWorkerVersion::INSTALLED);
1441 live_registration3->SetWaitingVersion(live_version3);
1443 // Notify storage of they being installed.
1444 storage()->NotifyInstallingRegistration(live_registration1.get());
1445 storage()->NotifyInstallingRegistration(live_registration2.get());
1446 storage()->NotifyInstallingRegistration(live_registration3.get());
1448 // Find a registration among installing ones.
1449 EXPECT_EQ(SERVICE_WORKER_OK,
1450 FindRegistrationForDocument(kDocumentUrl, &found_registration));
1451 EXPECT_EQ(live_registration2, found_registration);
1452 found_registration = NULL;
1454 // Store registrations.
1455 EXPECT_EQ(SERVICE_WORKER_OK,
1456 StoreRegistration(live_registration1, live_version1));
1457 EXPECT_EQ(SERVICE_WORKER_OK,
1458 StoreRegistration(live_registration2, live_version2));
1459 EXPECT_EQ(SERVICE_WORKER_OK,
1460 StoreRegistration(live_registration3, live_version3));
1462 // Notify storage of installations no longer happening.
1463 storage()->NotifyDoneInstallingRegistration(
1464 live_registration1.get(), NULL, SERVICE_WORKER_OK);
1465 storage()->NotifyDoneInstallingRegistration(
1466 live_registration2.get(), NULL, SERVICE_WORKER_OK);
1467 storage()->NotifyDoneInstallingRegistration(
1468 live_registration3.get(), NULL, SERVICE_WORKER_OK);
1470 // Find a registration among installed ones.
1471 EXPECT_EQ(SERVICE_WORKER_OK,
1472 FindRegistrationForDocument(kDocumentUrl, &found_registration));
1473 EXPECT_EQ(live_registration2, found_registration);
1476 } // namespace content