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"
9 #include "base/bind_helpers.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/sequenced_task_runner.h"
12 #include "base/task_runner_util.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_info.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/browser/service_worker/service_worker_utils.h"
18 #include "content/browser/service_worker/service_worker_version.h"
19 #include "content/common/service_worker/service_worker_types.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "net/base/net_errors.h"
22 #include "webkit/browser/quota/quota_manager_proxy.h"
28 typedef base::Callback<void(
29 ServiceWorkerStorage::InitialData* data,
30 bool success)> InitializeCallback;
31 typedef base::Callback<void(
32 const ServiceWorkerDatabase::RegistrationData& data,
33 const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources,
34 ServiceWorkerStatusCode status)> ReadRegistrationCallback;
35 typedef base::Callback<void(
36 bool origin_is_deletable,
37 ServiceWorkerStatusCode status)> DeleteRegistrationCallback;
39 void RunSoon(const tracked_objects::Location& from_here,
40 const base::Closure& closure) {
41 base::MessageLoop::current()->PostTask(from_here, closure);
45 const scoped_refptr<ServiceWorkerRegistration>& registration,
46 ServiceWorkerStatusCode status,
47 const ServiceWorkerStorage::FindRegistrationCallback& callback) {
48 callback.Run(status, registration);
51 void CompleteFindSoon(
52 const tracked_objects::Location& from_here,
53 const scoped_refptr<ServiceWorkerRegistration>& registration,
54 ServiceWorkerStatusCode status,
55 const ServiceWorkerStorage::FindRegistrationCallback& callback) {
56 RunSoon(from_here, base::Bind(callback, status, registration));
59 const base::FilePath::CharType kServiceWorkerDirectory[] =
60 FILE_PATH_LITERAL("Service Worker");
61 const base::FilePath::CharType kDatabaseName[] =
62 FILE_PATH_LITERAL("Database");
64 const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
66 void EmptyCompletionCallback(int) {}
68 void ReadInitialDataFromDB(
69 ServiceWorkerDatabase* database,
70 scoped_refptr<base::SequencedTaskRunner> original_task_runner,
71 const InitializeCallback& callback) {
73 ServiceWorkerStorage::InitialData* data =
74 new ServiceWorkerStorage::InitialData();
76 database->GetNextAvailableIds(&data->next_registration_id,
77 &data->next_version_id,
78 &data->next_resource_id) &&
79 database->GetOriginsWithRegistrations(&data->origins);
80 original_task_runner->PostTask(
81 FROM_HERE, base::Bind(callback, base::Owned(data), success));
84 void ReadRegistrationFromDB(
85 ServiceWorkerDatabase* database,
86 scoped_refptr<base::SequencedTaskRunner> original_task_runner,
87 int64 registration_id,
89 const ReadRegistrationCallback& callback) {
91 ServiceWorkerDatabase::RegistrationData data;
92 std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
94 // TODO(nhiroki): The database should return more detailed status like
95 // ServiceWorkerStatusCode instead of bool value.
96 ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
97 if (!database->ReadRegistration(registration_id, origin, &data, &resources)) {
98 status = database->is_disabled() ? SERVICE_WORKER_ERROR_FAILED
99 : SERVICE_WORKER_ERROR_NOT_FOUND;
101 original_task_runner->PostTask(
102 FROM_HERE, base::Bind(callback, data, resources, status));
105 void DeleteRegistrationFromDB(
106 ServiceWorkerDatabase* database,
107 scoped_refptr<base::SequencedTaskRunner> original_task_runner,
108 int64 registration_id,
110 const DeleteRegistrationCallback& callback) {
112 if (!database->DeleteRegistration(registration_id, origin)) {
113 original_task_runner->PostTask(
114 FROM_HERE, base::Bind(callback, false, SERVICE_WORKER_ERROR_FAILED));
118 // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the
119 // unique origin list.
120 std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
121 if (!database->GetRegistrationsForOrigin(origin, ®istrations)) {
122 original_task_runner->PostTask(
123 FROM_HERE, base::Bind(callback, false, SERVICE_WORKER_ERROR_FAILED));
127 bool deletable = registrations.empty();
128 original_task_runner->PostTask(
129 FROM_HERE, base::Bind(callback, deletable, SERVICE_WORKER_OK));
132 void UpdateToActiveStateInDB(
133 ServiceWorkerDatabase* database,
134 scoped_refptr<base::SequencedTaskRunner> original_task_runner,
135 int64 registration_id,
137 const ServiceWorkerStorage::StatusCallback& callback) {
140 // TODO(nhiroki): The database should return more detailed status like
141 // ServiceWorkerStatusCode instead of bool value.
142 ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
143 if (!database->UpdateVersionToActive(registration_id, origin)) {
144 status = database->is_disabled() ? SERVICE_WORKER_ERROR_FAILED
145 : SERVICE_WORKER_ERROR_NOT_FOUND;
147 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, status));
152 ServiceWorkerStorage::InitialData::InitialData()
153 : next_registration_id(kInvalidServiceWorkerRegistrationId),
154 next_version_id(kInvalidServiceWorkerVersionId),
155 next_resource_id(kInvalidServiceWorkerResourceId) {
158 ServiceWorkerStorage::InitialData::~InitialData() {
161 ServiceWorkerStorage::ServiceWorkerStorage(
162 const base::FilePath& path,
163 base::WeakPtr<ServiceWorkerContextCore> context,
164 base::SequencedTaskRunner* database_task_runner,
165 quota::QuotaManagerProxy* quota_manager_proxy)
166 : next_registration_id_(kInvalidServiceWorkerRegistrationId),
167 next_version_id_(kInvalidServiceWorkerVersionId),
168 next_resource_id_(kInvalidServiceWorkerResourceId),
169 state_(UNINITIALIZED),
171 database_task_runner_(database_task_runner),
172 quota_manager_proxy_(quota_manager_proxy),
173 weak_factory_(this) {
175 path_ = path.Append(kServiceWorkerDirectory);
176 database_.reset(new ServiceWorkerDatabase(path_.Append(kDatabaseName)));
178 // Create an in-memory database.
179 database_.reset(new ServiceWorkerDatabase(base::FilePath()));
183 ServiceWorkerStorage::~ServiceWorkerStorage() {
184 weak_factory_.InvalidateWeakPtrs();
185 database_task_runner_->DeleteSoon(FROM_HERE, database_.release());
188 void ServiceWorkerStorage::FindRegistrationForPattern(
190 const FindRegistrationCallback& callback) {
191 scoped_refptr<ServiceWorkerRegistration> null_registration;
192 if (!LazyInitialize(base::Bind(
193 &ServiceWorkerStorage::FindRegistrationForPattern,
194 weak_factory_.GetWeakPtr(), scope, callback))) {
195 if (state_ != INITIALIZING || !context_) {
196 CompleteFindSoon(FROM_HERE, null_registration,
197 SERVICE_WORKER_ERROR_FAILED, callback);
201 DCHECK_EQ(INITIALIZED, state_);
203 // See if there are any stored registrations for the origin.
204 if (!ContainsKey(registered_origins_, scope.GetOrigin())) {
205 // Look for something currently being installed.
206 scoped_refptr<ServiceWorkerRegistration> installing_registration =
207 FindInstallingRegistrationForPattern(scope);
208 if (installing_registration) {
210 FROM_HERE, installing_registration, SERVICE_WORKER_OK, callback);
214 FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
218 RegistrationList* registrations = new RegistrationList();
219 PostTaskAndReplyWithResult(
220 database_task_runner_,
222 base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
223 base::Unretained(database_.get()),
224 scope.GetOrigin(), base::Unretained(registrations)),
225 base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForPattern,
226 weak_factory_.GetWeakPtr(), scope, callback,
227 base::Owned(registrations)));
230 void ServiceWorkerStorage::FindRegistrationForDocument(
231 const GURL& document_url,
232 const FindRegistrationCallback& callback) {
233 scoped_refptr<ServiceWorkerRegistration> null_registration;
234 if (!LazyInitialize(base::Bind(
235 &ServiceWorkerStorage::FindRegistrationForDocument,
236 weak_factory_.GetWeakPtr(), document_url, callback))) {
237 if (state_ != INITIALIZING || !context_)
238 CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback);
241 DCHECK_EQ(INITIALIZED, state_);
243 // See if there are any stored registrations for the origin.
244 if (!ContainsKey(registered_origins_, document_url.GetOrigin())) {
245 // Look for something currently being installed.
246 scoped_refptr<ServiceWorkerRegistration> installing_registration =
247 FindInstallingRegistrationForDocument(document_url);
248 if (installing_registration) {
249 CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback);
253 null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
257 RegistrationList* registrations = new RegistrationList();
258 PostTaskAndReplyWithResult(
259 database_task_runner_,
261 base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
262 base::Unretained(database_.get()),
263 document_url.GetOrigin(), base::Unretained(registrations)),
264 base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForDocument,
265 weak_factory_.GetWeakPtr(), document_url, callback,
266 base::Owned(registrations)));
269 void ServiceWorkerStorage::FindRegistrationForId(
270 int64 registration_id,
272 const FindRegistrationCallback& callback) {
273 scoped_refptr<ServiceWorkerRegistration> null_registration;
274 if (!LazyInitialize(base::Bind(
275 &ServiceWorkerStorage::FindRegistrationForId,
276 weak_factory_.GetWeakPtr(), registration_id, origin, callback))) {
277 if (state_ != INITIALIZING || !context_)
278 CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback);
281 DCHECK_EQ(INITIALIZED, state_);
283 // See if there are any stored registrations for the origin.
284 if (!ContainsKey(registered_origins_, origin)) {
285 // Look for somthing currently being installed.
286 scoped_refptr<ServiceWorkerRegistration> installing_registration =
287 FindInstallingRegistrationForId(registration_id);
288 if (installing_registration) {
289 CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback);
293 null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
297 scoped_refptr<ServiceWorkerRegistration> registration =
298 context_->GetLiveRegistration(registration_id);
300 CompleteFindNow(registration, SERVICE_WORKER_OK, callback);
304 database_task_runner_->PostTask(
306 base::Bind(&ReadRegistrationFromDB,
308 base::MessageLoopProxy::current(),
309 registration_id, origin,
310 base::Bind(&ServiceWorkerStorage::DidReadRegistrationForId,
311 weak_factory_.GetWeakPtr(), callback)));
314 void ServiceWorkerStorage::GetAllRegistrations(
315 const GetAllRegistrationInfosCallback& callback) {
316 if (!LazyInitialize(base::Bind(
317 &ServiceWorkerStorage::GetAllRegistrations,
318 weak_factory_.GetWeakPtr(), callback))) {
319 if (state_ != INITIALIZING || !context_) {
320 RunSoon(FROM_HERE, base::Bind(
321 callback, std::vector<ServiceWorkerRegistrationInfo>()));
325 DCHECK_EQ(INITIALIZED, state_);
327 RegistrationList* registrations = new RegistrationList;
328 PostTaskAndReplyWithResult(
329 database_task_runner_,
331 base::Bind(&ServiceWorkerDatabase::GetAllRegistrations,
332 base::Unretained(database_.get()),
333 base::Unretained(registrations)),
334 base::Bind(&ServiceWorkerStorage::DidGetAllRegistrations,
335 weak_factory_.GetWeakPtr(),
337 base::Owned(registrations)));
340 void ServiceWorkerStorage::StoreRegistration(
341 ServiceWorkerRegistration* registration,
342 ServiceWorkerVersion* version,
343 const StatusCallback& callback) {
344 DCHECK(registration);
347 DCHECK(state_ == INITIALIZED || state_ == DISABLED);
348 if (state_ != INITIALIZED || !context_) {
349 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
353 ServiceWorkerDatabase::RegistrationData data;
354 data.registration_id = registration->id();
355 data.scope = registration->pattern();
356 data.script = registration->script_url();
357 data.has_fetch_handler = true;
358 data.version_id = version->version_id();
359 data.last_update_check = base::Time::Now();
360 data.is_active = false; // initially stored in the waiting state
362 ResourceList resources;
363 PostTaskAndReplyWithResult(
364 database_task_runner_,
366 base::Bind(&ServiceWorkerDatabase::WriteRegistration,
367 base::Unretained(database_.get()), data, resources),
368 base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
369 weak_factory_.GetWeakPtr(),
370 registration->script_url().GetOrigin(),
374 void ServiceWorkerStorage::UpdateToActiveState(
375 ServiceWorkerRegistration* registration,
376 const StatusCallback& callback) {
377 DCHECK(registration);
379 DCHECK(state_ == INITIALIZED || state_ == DISABLED);
380 if (state_ != INITIALIZED || !context_) {
381 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
385 database_task_runner_->PostTask(
387 base::Bind(&UpdateToActiveStateInDB,
389 base::MessageLoopProxy::current(),
391 registration->script_url().GetOrigin(),
395 void ServiceWorkerStorage::DeleteRegistration(
396 int64 registration_id,
398 const StatusCallback& callback) {
399 DCHECK(state_ == INITIALIZED || state_ == DISABLED);
400 if (state_ != INITIALIZED || !context_) {
401 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
405 database_task_runner_->PostTask(
407 base::Bind(&DeleteRegistrationFromDB,
409 base::MessageLoopProxy::current(),
410 registration_id, origin,
411 base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
412 weak_factory_.GetWeakPtr(), origin, callback)));
414 // TODO(michaeln): Either its instance should also be
415 // removed from liveregistrations map or the live object
416 // should marked as deleted in some way and not 'findable'
420 scoped_ptr<ServiceWorkerResponseReader>
421 ServiceWorkerStorage::CreateResponseReader(int64 response_id) {
422 return make_scoped_ptr(
423 new ServiceWorkerResponseReader(response_id, disk_cache()));
426 scoped_ptr<ServiceWorkerResponseWriter>
427 ServiceWorkerStorage::CreateResponseWriter(int64 response_id) {
428 return make_scoped_ptr(
429 new ServiceWorkerResponseWriter(response_id, disk_cache()));
432 int64 ServiceWorkerStorage::NewRegistrationId() {
433 if (state_ == DISABLED)
434 return kInvalidServiceWorkerRegistrationId;
435 DCHECK_EQ(INITIALIZED, state_);
436 return next_registration_id_++;
439 int64 ServiceWorkerStorage::NewVersionId() {
440 if (state_ == DISABLED)
441 return kInvalidServiceWorkerVersionId;
442 DCHECK_EQ(INITIALIZED, state_);
443 return next_version_id_++;
446 int64 ServiceWorkerStorage::NewResourceId() {
447 if (state_ == DISABLED)
448 return kInvalidServiceWorkerResourceId;
449 DCHECK_EQ(INITIALIZED, state_);
450 return next_resource_id_++;
453 void ServiceWorkerStorage::NotifyInstallingRegistration(
454 ServiceWorkerRegistration* registration) {
455 installing_registrations_[registration->id()] = registration;
458 void ServiceWorkerStorage::NotifyDoneInstallingRegistration(
459 ServiceWorkerRegistration* registration) {
460 installing_registrations_.erase(registration->id());
463 bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
473 pending_tasks_.push_back(callback);
476 pending_tasks_.push_back(callback);
480 state_ = INITIALIZING;
481 database_task_runner_->PostTask(
483 base::Bind(&ReadInitialDataFromDB,
485 base::MessageLoopProxy::current(),
486 base::Bind(&ServiceWorkerStorage::DidReadInitialData,
487 weak_factory_.GetWeakPtr())));
491 void ServiceWorkerStorage::DidReadInitialData(
495 DCHECK_EQ(INITIALIZING, state_);
498 next_registration_id_ = data->next_registration_id;
499 next_version_id_ = data->next_version_id;
500 next_resource_id_ = data->next_resource_id;
501 registered_origins_.swap(data->origins);
502 state_ = INITIALIZED;
504 DLOG(WARNING) << "Failed to initialize.";
508 for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin();
509 it != pending_tasks_.end(); ++it) {
510 RunSoon(FROM_HERE, *it);
512 pending_tasks_.clear();
515 void ServiceWorkerStorage::DidGetRegistrationsForPattern(
517 const FindRegistrationCallback& callback,
518 RegistrationList* registrations,
520 DCHECK(registrations);
522 callback.Run(SERVICE_WORKER_ERROR_FAILED,
523 scoped_refptr<ServiceWorkerRegistration>());
527 // Find one with a matching scope.
528 for (RegistrationList::const_iterator it = registrations->begin();
529 it != registrations->end(); ++it) {
530 if (scope == it->scope) {
531 scoped_refptr<ServiceWorkerRegistration> registration =
532 context_->GetLiveRegistration(it->registration_id);
534 registration = CreateRegistration(*it);
535 callback.Run(SERVICE_WORKER_OK, registration);
540 // Look for something currently being installed.
541 scoped_refptr<ServiceWorkerRegistration> installing_registration =
542 FindInstallingRegistrationForPattern(scope);
543 if (installing_registration) {
544 callback.Run(SERVICE_WORKER_OK, installing_registration);
548 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
549 scoped_refptr<ServiceWorkerRegistration>());
552 void ServiceWorkerStorage::DidGetRegistrationsForDocument(
553 const GURL& document_url,
554 const FindRegistrationCallback& callback,
555 RegistrationList* registrations,
557 DCHECK(registrations);
559 callback.Run(SERVICE_WORKER_ERROR_FAILED,
560 scoped_refptr<ServiceWorkerRegistration>());
564 // Find one with a pattern match.
565 for (RegistrationList::const_iterator it = registrations->begin();
566 it != registrations->end(); ++it) {
567 // TODO(michaeln): if there are multiple matches the one with
568 // the longest scope should win.
569 if (ServiceWorkerUtils::ScopeMatches(it->scope, document_url)) {
570 scoped_refptr<ServiceWorkerRegistration> registration =
571 context_->GetLiveRegistration(it->registration_id);
573 callback.Run(SERVICE_WORKER_OK, registration);
576 callback.Run(SERVICE_WORKER_OK, CreateRegistration(*it));
581 // Look for something currently being installed.
582 // TODO(michaeln): Should be mixed in with the stored registrations
584 scoped_refptr<ServiceWorkerRegistration> installing_registration =
585 FindInstallingRegistrationForDocument(document_url);
586 if (installing_registration) {
587 callback.Run(SERVICE_WORKER_OK, installing_registration);
591 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
592 scoped_refptr<ServiceWorkerRegistration>());
595 void ServiceWorkerStorage::DidReadRegistrationForId(
596 const FindRegistrationCallback& callback,
597 const ServiceWorkerDatabase::RegistrationData& registration,
598 const ResourceList& resources,
599 ServiceWorkerStatusCode status) {
600 if (status == SERVICE_WORKER_OK) {
601 callback.Run(status, CreateRegistration(registration));
605 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
606 // Look for somthing currently being installed.
607 scoped_refptr<ServiceWorkerRegistration> installing_registration =
608 FindInstallingRegistrationForId(registration.registration_id);
609 if (installing_registration) {
610 callback.Run(SERVICE_WORKER_OK, installing_registration);
613 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
614 scoped_refptr<ServiceWorkerRegistration>());
618 callback.Run(status, scoped_refptr<ServiceWorkerRegistration>());
622 void ServiceWorkerStorage::DidGetAllRegistrations(
623 const GetAllRegistrationInfosCallback& callback,
624 RegistrationList* registrations,
626 DCHECK(registrations);
628 callback.Run(std::vector<ServiceWorkerRegistrationInfo>());
632 // Add all stored registrations.
633 std::set<int64> pushed_registrations;
634 std::vector<ServiceWorkerRegistrationInfo> infos;
635 for (RegistrationList::const_iterator it = registrations->begin();
636 it != registrations->end(); ++it) {
637 DCHECK(pushed_registrations.insert(it->registration_id).second);
638 ServiceWorkerRegistration* registration =
639 context_->GetLiveRegistration(it->registration_id);
641 infos.push_back(registration->GetInfo());
644 ServiceWorkerRegistrationInfo info;
645 info.pattern = it->scope;
646 info.script_url = it->script;
647 info.active_version.is_null = false;
649 info.active_version.status = ServiceWorkerVersion::ACTIVE;
651 info.active_version.status = ServiceWorkerVersion::INSTALLED;
652 info.active_version.version_id = it->version_id;
653 infos.push_back(info);
656 // Add unstored registrations that are being installed.
657 for (RegistrationRefsById::const_iterator it =
658 installing_registrations_.begin();
659 it != installing_registrations_.end(); ++it) {
660 if (pushed_registrations.insert(it->first).second)
661 infos.push_back(it->second->GetInfo());
667 void ServiceWorkerStorage::DidStoreRegistration(
669 const StatusCallback& callback,
672 callback.Run(SERVICE_WORKER_ERROR_FAILED);
675 registered_origins_.insert(origin);
676 callback.Run(SERVICE_WORKER_OK);
679 void ServiceWorkerStorage::DidDeleteRegistration(
681 const StatusCallback& callback,
682 bool origin_is_deletable,
683 ServiceWorkerStatusCode status) {
684 if (origin_is_deletable)
685 registered_origins_.erase(origin);
686 callback.Run(status);
689 scoped_refptr<ServiceWorkerRegistration>
690 ServiceWorkerStorage::CreateRegistration(
691 const ServiceWorkerDatabase::RegistrationData& data) {
692 scoped_refptr<ServiceWorkerRegistration> registration(
693 new ServiceWorkerRegistration(
694 data.scope, data.script, data.registration_id, context_));
696 scoped_refptr<ServiceWorkerVersion> version =
697 context_->GetLiveVersion(data.version_id);
699 version = new ServiceWorkerVersion(registration, data.version_id, context_);
700 version->SetStatus(data.GetVersionStatus());
703 if (version->status() == ServiceWorkerVersion::ACTIVE)
704 registration->set_active_version(version);
705 else if (version->status() == ServiceWorkerVersion::INSTALLED)
706 registration->set_pending_version(version);
709 // TODO(michaeln): Hmmm, what if DeleteReg was invoked after
710 // the Find result we're returning here? NOTREACHED condition?
715 ServiceWorkerRegistration*
716 ServiceWorkerStorage::FindInstallingRegistrationForDocument(
717 const GURL& document_url) {
718 // TODO(michaeln): if there are multiple matches the one with
719 // the longest scope should win, and these should on equal footing
720 // with the stored registrations in FindRegistrationForDocument().
721 for (RegistrationRefsById::const_iterator it =
722 installing_registrations_.begin();
723 it != installing_registrations_.end(); ++it) {
724 if (ServiceWorkerUtils::ScopeMatches(
725 it->second->pattern(), document_url)) {
732 ServiceWorkerRegistration*
733 ServiceWorkerStorage::FindInstallingRegistrationForPattern(
735 for (RegistrationRefsById::const_iterator it =
736 installing_registrations_.begin();
737 it != installing_registrations_.end(); ++it) {
738 if (it->second->pattern() == scope)
744 ServiceWorkerRegistration*
745 ServiceWorkerStorage::FindInstallingRegistrationForId(
746 int64 registration_id) {
747 RegistrationRefsById::const_iterator found =
748 installing_registrations_.find(registration_id);
749 if (found == installing_registrations_.end())
751 return found->second;
754 ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
756 return disk_cache_.get();
758 // TODO(michaeln): Store data on disk and do error checking.
759 disk_cache_.reset(new ServiceWorkerDiskCache);
760 int rv = disk_cache_->InitWithMemBackend(
761 kMaxMemDiskCacheSize,
762 base::Bind(&EmptyCompletionCallback));
763 DCHECK_EQ(net::OK, rv);
764 return disk_cache_.get();
767 } // namespace content