Decouple Cache Storage messaging from Service Worker/Embedded Worker
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_cache_storage.cc
blob61b4c2723ffa3ee5ec64763af177a08a0e14f3d8
1 // Copyright 2014 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_cache_storage.h"
7 #include <string>
9 #include "base/barrier_closure.h"
10 #include "base/files/file_util.h"
11 #include "base/files/memory_mapped_file.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/sha1.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "content/browser/service_worker/service_worker_cache.h"
19 #include "content/browser/service_worker/service_worker_cache.pb.h"
20 #include "content/browser/service_worker/service_worker_cache_scheduler.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "net/base/directory_lister.h"
23 #include "net/base/net_errors.h"
24 #include "storage/browser/blob/blob_storage_context.h"
25 #include "storage/browser/quota/quota_manager_proxy.h"
27 namespace content {
29 namespace {
31 void CloseAllCachesDidCloseCache(const scoped_refptr<ServiceWorkerCache>& cache,
32 const base::Closure& barrier_closure) {
33 barrier_closure.Run();
36 } // namespace
38 const char ServiceWorkerCacheStorage::kIndexFileName[] = "index.txt";
40 // Handles the loading and clean up of ServiceWorkerCache objects. The
41 // callback of every public method is guaranteed to be called.
42 class ServiceWorkerCacheStorage::CacheLoader {
43 public:
44 typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)>
45 CacheCallback;
46 typedef base::Callback<void(bool)> BoolCallback;
47 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
48 StringVectorCallback;
50 CacheLoader(
51 base::SequencedTaskRunner* cache_task_runner,
52 net::URLRequestContext* request_context,
53 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
54 base::WeakPtr<storage::BlobStorageContext> blob_context,
55 const GURL& origin)
56 : cache_task_runner_(cache_task_runner),
57 request_context_(request_context),
58 quota_manager_proxy_(quota_manager_proxy),
59 blob_context_(blob_context),
60 origin_(origin) {
61 DCHECK(!origin_.is_empty());
64 virtual ~CacheLoader() {}
66 // Creates a ServiceWorkerCache with the given name. It does not attempt to
67 // load the backend, that happens lazily when the cache is used.
68 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
69 const std::string& cache_name) = 0;
71 // Deletes any pre-existing cache of the same name and then loads it.
72 virtual void CreateCache(const std::string& cache_name,
73 const CacheCallback& callback) = 0;
75 // After the backend has been deleted, do any extra house keeping such as
76 // removing the cache's directory.
77 virtual void CleanUpDeletedCache(const std::string& key,
78 const BoolCallback& callback) = 0;
80 // Writes the cache names (and sizes) to disk if applicable.
81 virtual void WriteIndex(const StringVector& cache_names,
82 const BoolCallback& callback) = 0;
84 // Loads the cache names from disk if applicable.
85 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
86 const StringVectorCallback& callback) = 0;
88 protected:
89 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
90 net::URLRequestContext* request_context_;
91 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
92 base::WeakPtr<storage::BlobStorageContext> blob_context_;
93 GURL origin_;
96 // Creates memory-only ServiceWorkerCaches. Because these caches have no
97 // persistent storage it is not safe to free them from memory if they might be
98 // used again. Therefore this class holds a reference to each cache until the
99 // cache is deleted.
100 class ServiceWorkerCacheStorage::MemoryLoader
101 : public ServiceWorkerCacheStorage::CacheLoader {
102 public:
103 MemoryLoader(
104 base::SequencedTaskRunner* cache_task_runner,
105 net::URLRequestContext* request_context,
106 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
107 base::WeakPtr<storage::BlobStorageContext> blob_context,
108 const GURL& origin)
109 : CacheLoader(cache_task_runner,
110 request_context,
111 quota_manager_proxy,
112 blob_context,
113 origin) {}
115 scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
116 const std::string& cache_name) override {
117 return ServiceWorkerCache::CreateMemoryCache(
118 origin_, request_context_, quota_manager_proxy_, blob_context_);
121 void CreateCache(const std::string& cache_name,
122 const CacheCallback& callback) override {
123 scoped_refptr<ServiceWorkerCache> cache =
124 CreateServiceWorkerCache(cache_name);
125 cache_refs_.insert(std::make_pair(cache_name, cache));
126 callback.Run(cache);
129 void CleanUpDeletedCache(const std::string& cache_name,
130 const BoolCallback& callback) override {
131 CacheRefMap::iterator it = cache_refs_.find(cache_name);
132 DCHECK(it != cache_refs_.end());
133 cache_refs_.erase(it);
134 callback.Run(true);
137 void WriteIndex(const StringVector& cache_names,
138 const BoolCallback& callback) override {
139 callback.Run(false);
142 void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
143 const StringVectorCallback& callback) override {
144 callback.Run(cache_names.Pass());
147 private:
148 typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap;
149 ~MemoryLoader() override {}
151 // Keep a reference to each cache to ensure that it's not freed before the
152 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
153 // freed.
154 CacheRefMap cache_refs_;
157 class ServiceWorkerCacheStorage::SimpleCacheLoader
158 : public ServiceWorkerCacheStorage::CacheLoader {
159 public:
160 SimpleCacheLoader(
161 const base::FilePath& origin_path,
162 base::SequencedTaskRunner* cache_task_runner,
163 net::URLRequestContext* request_context,
164 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
165 base::WeakPtr<storage::BlobStorageContext> blob_context,
166 const GURL& origin)
167 : CacheLoader(cache_task_runner,
168 request_context,
169 quota_manager_proxy,
170 blob_context,
171 origin),
172 origin_path_(origin_path),
173 weak_ptr_factory_(this) {}
175 scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
176 const std::string& cache_name) override {
177 DCHECK_CURRENTLY_ON(BrowserThread::IO);
179 return ServiceWorkerCache::CreatePersistentCache(
180 origin_,
181 CreatePersistentCachePath(origin_path_, cache_name),
182 request_context_,
183 quota_manager_proxy_,
184 blob_context_);
187 void CreateCache(const std::string& cache_name,
188 const CacheCallback& callback) override {
189 DCHECK_CURRENTLY_ON(BrowserThread::IO);
191 // 1. Delete the cache's directory if it exists.
192 // (CreateCacheDeleteFilesInPool)
193 // 2. Load the cache. (LoadCreateDirectoryInPool)
195 base::FilePath cache_path =
196 CreatePersistentCachePath(origin_path_, cache_name);
198 PostTaskAndReplyWithResult(
199 cache_task_runner_.get(),
200 FROM_HERE,
201 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
202 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir,
203 cache_name,
204 callback,
205 weak_ptr_factory_.GetWeakPtr()));
208 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
209 if (base::PathExists(cache_path))
210 base::DeleteFile(cache_path, /* recursive */ true);
211 return base::CreateDirectory(cache_path);
214 static void CreateCachePreppedDir(const std::string& cache_name,
215 const CacheCallback& callback,
216 base::WeakPtr<SimpleCacheLoader> loader,
217 bool success) {
218 if (!success || !loader) {
219 callback.Run(scoped_refptr<ServiceWorkerCache>());
220 return;
223 callback.Run(loader->CreateServiceWorkerCache(cache_name));
226 void CleanUpDeletedCache(const std::string& cache_name,
227 const BoolCallback& callback) override {
228 DCHECK_CURRENTLY_ON(BrowserThread::IO);
230 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
232 base::FilePath cache_path =
233 CreatePersistentCachePath(origin_path_, cache_name);
234 cache_task_runner_->PostTask(
235 FROM_HERE,
236 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
237 cache_path,
238 callback,
239 base::MessageLoopProxy::current()));
242 static void CleanUpDeleteCacheDirInPool(
243 const base::FilePath& cache_path,
244 const BoolCallback& callback,
245 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
246 bool rv = base::DeleteFile(cache_path, true);
247 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
250 void WriteIndex(const StringVector& cache_names,
251 const BoolCallback& callback) override {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO);
254 // 1. Create the index file as a string. (WriteIndex)
255 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
257 ServiceWorkerCacheStorageIndex index;
258 index.set_origin(origin_.spec());
260 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
261 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
262 index_cache->set_name(cache_names[i]);
265 std::string serialized;
266 bool success = index.SerializeToString(&serialized);
267 DCHECK(success);
269 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
270 base::FilePath index_path =
271 origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
273 cache_task_runner_->PostTask(
274 FROM_HERE,
275 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
276 tmp_path,
277 index_path,
278 serialized,
279 callback,
280 base::MessageLoopProxy::current()));
283 static void WriteIndexWriteToFileInPool(
284 const base::FilePath& tmp_path,
285 const base::FilePath& index_path,
286 const std::string& data,
287 const BoolCallback& callback,
288 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
289 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
290 if (bytes_written != implicit_cast<int>(data.size())) {
291 base::DeleteFile(tmp_path, /* recursive */ false);
292 original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
295 // Atomically rename the temporary index file to become the real one.
296 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
297 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
300 void LoadIndex(scoped_ptr<std::vector<std::string>> names,
301 const StringVectorCallback& callback) override {
302 DCHECK_CURRENTLY_ON(BrowserThread::IO);
304 // 1. Read the file from disk. (LoadIndexReadFileInPool)
305 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
307 base::FilePath index_path =
308 origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
310 cache_task_runner_->PostTask(
311 FROM_HERE,
312 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
313 index_path,
314 base::Passed(names.Pass()),
315 callback,
316 base::MessageLoopProxy::current()));
319 static void LoadIndexReadFileInPool(
320 const base::FilePath& index_path,
321 scoped_ptr<std::vector<std::string> > names,
322 const StringVectorCallback& callback,
323 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
324 std::string body;
325 base::ReadFileToString(index_path, &body);
327 original_loop->PostTask(FROM_HERE,
328 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
329 base::Passed(names.Pass()),
330 callback,
331 body));
334 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
335 const StringVectorCallback& callback,
336 const std::string& serialized) {
337 DCHECK_CURRENTLY_ON(BrowserThread::IO);
339 ServiceWorkerCacheStorageIndex index;
340 if (index.ParseFromString(serialized)) {
341 for (int i = 0, max = index.cache_size(); i < max; ++i) {
342 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
343 names->push_back(cache.name());
347 // TODO(jkarlin): Delete caches that are in the directory and not returned
348 // in LoadIndex.
349 callback.Run(names.Pass());
352 private:
353 ~SimpleCacheLoader() override {}
355 static std::string HexedHash(const std::string& value) {
356 std::string value_hash = base::SHA1HashString(value);
357 std::string valued_hexed_hash = base::StringToLowerASCII(
358 base::HexEncode(value_hash.c_str(), value_hash.length()));
359 return valued_hexed_hash;
362 static base::FilePath CreatePersistentCachePath(
363 const base::FilePath& origin_path,
364 const std::string& cache_name) {
365 return origin_path.AppendASCII(HexedHash(cache_name));
368 const base::FilePath origin_path_;
370 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
373 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
374 const base::FilePath& path,
375 bool memory_only,
376 base::SequencedTaskRunner* cache_task_runner,
377 net::URLRequestContext* request_context,
378 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
379 base::WeakPtr<storage::BlobStorageContext> blob_context,
380 const GURL& origin)
381 : initialized_(false),
382 initializing_(false),
383 scheduler_(new ServiceWorkerCacheScheduler()),
384 origin_path_(path),
385 cache_task_runner_(cache_task_runner),
386 memory_only_(memory_only),
387 weak_factory_(this) {
388 if (memory_only)
389 cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
390 request_context,
391 quota_manager_proxy,
392 blob_context,
393 origin));
394 else
395 cache_loader_.reset(new SimpleCacheLoader(origin_path_,
396 cache_task_runner_.get(),
397 request_context,
398 quota_manager_proxy,
399 blob_context,
400 origin));
403 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
406 void ServiceWorkerCacheStorage::OpenCache(
407 const std::string& cache_name,
408 const CacheAndErrorCallback& callback) {
409 DCHECK_CURRENTLY_ON(BrowserThread::IO);
411 if (!initialized_)
412 LazyInit();
414 CacheAndErrorCallback pending_callback =
415 base::Bind(&ServiceWorkerCacheStorage::PendingCacheAndErrorCallback,
416 weak_factory_.GetWeakPtr(), callback);
417 scheduler_->ScheduleOperation(
418 base::Bind(&ServiceWorkerCacheStorage::OpenCacheImpl,
419 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
422 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
423 const BoolAndErrorCallback& callback) {
424 DCHECK_CURRENTLY_ON(BrowserThread::IO);
426 if (!initialized_)
427 LazyInit();
429 BoolAndErrorCallback pending_callback =
430 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback,
431 weak_factory_.GetWeakPtr(), callback);
432 scheduler_->ScheduleOperation(
433 base::Bind(&ServiceWorkerCacheStorage::HasCacheImpl,
434 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
437 void ServiceWorkerCacheStorage::DeleteCache(
438 const std::string& cache_name,
439 const BoolAndErrorCallback& callback) {
440 DCHECK_CURRENTLY_ON(BrowserThread::IO);
442 if (!initialized_)
443 LazyInit();
445 BoolAndErrorCallback pending_callback =
446 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback,
447 weak_factory_.GetWeakPtr(), callback);
448 scheduler_->ScheduleOperation(
449 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheImpl,
450 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
453 void ServiceWorkerCacheStorage::EnumerateCaches(
454 const StringsAndErrorCallback& callback) {
455 DCHECK_CURRENTLY_ON(BrowserThread::IO);
457 if (!initialized_)
458 LazyInit();
460 StringsAndErrorCallback pending_callback =
461 base::Bind(&ServiceWorkerCacheStorage::PendingStringsAndErrorCallback,
462 weak_factory_.GetWeakPtr(), callback);
463 scheduler_->ScheduleOperation(
464 base::Bind(&ServiceWorkerCacheStorage::EnumerateCachesImpl,
465 weak_factory_.GetWeakPtr(), pending_callback));
468 void ServiceWorkerCacheStorage::MatchCache(
469 const std::string& cache_name,
470 scoped_ptr<ServiceWorkerFetchRequest> request,
471 const ServiceWorkerCache::ResponseCallback& callback) {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO);
474 if (!initialized_)
475 LazyInit();
477 ServiceWorkerCache::ResponseCallback pending_callback =
478 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback,
479 weak_factory_.GetWeakPtr(), callback);
480 scheduler_->ScheduleOperation(base::Bind(
481 &ServiceWorkerCacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
482 cache_name, base::Passed(request.Pass()), pending_callback));
485 void ServiceWorkerCacheStorage::MatchAllCaches(
486 scoped_ptr<ServiceWorkerFetchRequest> request,
487 const ServiceWorkerCache::ResponseCallback& callback) {
488 DCHECK_CURRENTLY_ON(BrowserThread::IO);
490 if (!initialized_)
491 LazyInit();
493 ServiceWorkerCache::ResponseCallback pending_callback =
494 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback,
495 weak_factory_.GetWeakPtr(), callback);
496 scheduler_->ScheduleOperation(
497 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesImpl,
498 weak_factory_.GetWeakPtr(), base::Passed(request.Pass()),
499 pending_callback));
502 void ServiceWorkerCacheStorage::CloseAllCaches(const base::Closure& callback) {
503 DCHECK_CURRENTLY_ON(BrowserThread::IO);
505 if (!initialized_) {
506 callback.Run();
507 return;
510 base::Closure pending_callback =
511 base::Bind(&ServiceWorkerCacheStorage::PendingClosure,
512 weak_factory_.GetWeakPtr(), callback);
513 scheduler_->ScheduleOperation(
514 base::Bind(&ServiceWorkerCacheStorage::CloseAllCachesImpl,
515 weak_factory_.GetWeakPtr(), pending_callback));
518 int64 ServiceWorkerCacheStorage::MemoryBackedSize() const {
519 DCHECK_CURRENTLY_ON(BrowserThread::IO);
521 if (!initialized_ || !memory_only_)
522 return 0;
524 int64 sum = 0;
525 for (auto& key_value : cache_map_) {
526 if (key_value.second)
527 sum += key_value.second->MemoryBackedSize();
529 return sum;
532 void ServiceWorkerCacheStorage::StartAsyncOperationForTesting() {
533 scheduler_->ScheduleOperation(base::Bind(&base::DoNothing));
536 void ServiceWorkerCacheStorage::CompleteAsyncOperationForTesting() {
537 scheduler_->CompleteOperationAndRunNext();
540 // Init is run lazily so that it is called on the proper MessageLoop.
541 void ServiceWorkerCacheStorage::LazyInit() {
542 DCHECK_CURRENTLY_ON(BrowserThread::IO);
543 DCHECK(!initialized_);
545 if (initializing_)
546 return;
548 DCHECK(!scheduler_->ScheduledOperations());
550 initializing_ = true;
551 scheduler_->ScheduleOperation(base::Bind(
552 &ServiceWorkerCacheStorage::LazyInitImpl, weak_factory_.GetWeakPtr()));
555 void ServiceWorkerCacheStorage::LazyInitImpl() {
556 DCHECK_CURRENTLY_ON(BrowserThread::IO);
557 DCHECK(!initialized_);
558 DCHECK(initializing_);
560 // 1. Get the list of cache names (async call)
561 // 2. For each cache name, load the cache (async call)
562 // 3. Once each load is complete, update the map variables.
563 // 4. Call the list of waiting callbacks.
565 scoped_ptr<std::vector<std::string> > indexed_cache_names(
566 new std::vector<std::string>());
568 cache_loader_->LoadIndex(
569 indexed_cache_names.Pass(),
570 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex,
571 weak_factory_.GetWeakPtr()));
574 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
575 scoped_ptr<std::vector<std::string> > indexed_cache_names) {
576 DCHECK_CURRENTLY_ON(BrowserThread::IO);
578 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
579 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
580 base::WeakPtr<ServiceWorkerCache>()));
581 ordered_cache_names_.push_back(indexed_cache_names->at(i));
584 initializing_ = false;
585 initialized_ = true;
587 scheduler_->CompleteOperationAndRunNext();
590 void ServiceWorkerCacheStorage::OpenCacheImpl(
591 const std::string& cache_name,
592 const CacheAndErrorCallback& callback) {
593 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
594 if (cache.get()) {
595 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
596 return;
599 cache_loader_->CreateCache(
600 cache_name,
601 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache,
602 weak_factory_.GetWeakPtr(), cache_name, callback));
605 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
606 const std::string& cache_name,
607 const CacheAndErrorCallback& callback,
608 const scoped_refptr<ServiceWorkerCache>& cache) {
609 DCHECK_CURRENTLY_ON(BrowserThread::IO);
611 if (!cache.get()) {
612 callback.Run(scoped_refptr<ServiceWorkerCache>(),
613 CACHE_STORAGE_ERROR_CLOSING);
614 return;
617 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
618 cache != nullptr);
620 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
621 ordered_cache_names_.push_back(cache_name);
623 cache_loader_->WriteIndex(
624 ordered_cache_names_,
625 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
626 weak_factory_.GetWeakPtr(),
627 callback,
628 cache));
631 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
632 const CacheAndErrorCallback& callback,
633 const scoped_refptr<ServiceWorkerCache>& cache,
634 bool success) {
635 DCHECK_CURRENTLY_ON(BrowserThread::IO);
636 DCHECK(cache.get());
638 // TODO(jkarlin): Handle !success.
640 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
643 void ServiceWorkerCacheStorage::HasCacheImpl(
644 const std::string& cache_name,
645 const BoolAndErrorCallback& callback) {
646 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
648 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
651 void ServiceWorkerCacheStorage::DeleteCacheImpl(
652 const std::string& cache_name,
653 const BoolAndErrorCallback& callback) {
654 CacheMap::iterator it = cache_map_.find(cache_name);
655 if (it == cache_map_.end()) {
656 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
657 return;
660 base::WeakPtr<ServiceWorkerCache> cache = it->second;
661 cache_map_.erase(it);
663 // Delete the name from ordered_cache_names_.
664 StringVector::iterator iter = std::find(
665 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
666 DCHECK(iter != ordered_cache_names_.end());
667 ordered_cache_names_.erase(iter);
669 base::Closure closure =
670 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidClose,
671 weak_factory_.GetWeakPtr(), cache_name, callback,
672 ordered_cache_names_, make_scoped_refptr(cache.get()));
674 if (cache) {
675 cache->Close(closure);
676 return;
679 closure.Run();
682 void ServiceWorkerCacheStorage::DeleteCacheDidClose(
683 const std::string& cache_name,
684 const BoolAndErrorCallback& callback,
685 const StringVector& ordered_cache_names,
686 const scoped_refptr<ServiceWorkerCache>& cache /* might be null */) {
687 cache_loader_->WriteIndex(
688 ordered_cache_names,
689 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
690 weak_factory_.GetWeakPtr(), cache_name, callback));
693 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
694 const std::string& cache_name,
695 const BoolAndErrorCallback& callback,
696 bool success) {
697 DCHECK_CURRENTLY_ON(BrowserThread::IO);
699 cache_loader_->CleanUpDeletedCache(
700 cache_name,
701 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp,
702 weak_factory_.GetWeakPtr(),
703 callback));
706 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
707 const BoolAndErrorCallback& callback,
708 bool success) {
709 DCHECK_CURRENTLY_ON(BrowserThread::IO);
711 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
714 void ServiceWorkerCacheStorage::EnumerateCachesImpl(
715 const StringsAndErrorCallback& callback) {
716 callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
719 void ServiceWorkerCacheStorage::MatchCacheImpl(
720 const std::string& cache_name,
721 scoped_ptr<ServiceWorkerFetchRequest> request,
722 const ServiceWorkerCache::ResponseCallback& callback) {
723 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
725 if (!cache.get()) {
726 callback.Run(ServiceWorkerCache::ERROR_TYPE_NOT_FOUND,
727 scoped_ptr<ServiceWorkerResponse>(),
728 scoped_ptr<storage::BlobDataHandle>());
729 return;
732 // Pass the cache along to the callback to keep the cache open until match is
733 // done.
734 cache->Match(request.Pass(),
735 base::Bind(&ServiceWorkerCacheStorage::MatchCacheDidMatch,
736 weak_factory_.GetWeakPtr(), cache, callback));
739 void ServiceWorkerCacheStorage::MatchCacheDidMatch(
740 const scoped_refptr<ServiceWorkerCache>& cache,
741 const ServiceWorkerCache::ResponseCallback& callback,
742 ServiceWorkerCache::ErrorType error,
743 scoped_ptr<ServiceWorkerResponse> response,
744 scoped_ptr<storage::BlobDataHandle> handle) {
745 callback.Run(error, response.Pass(), handle.Pass());
748 void ServiceWorkerCacheStorage::MatchAllCachesImpl(
749 scoped_ptr<ServiceWorkerFetchRequest> request,
750 const ServiceWorkerCache::ResponseCallback& callback) {
751 scoped_ptr<ServiceWorkerCache::ResponseCallback> callback_copy(
752 new ServiceWorkerCache::ResponseCallback(callback));
754 ServiceWorkerCache::ResponseCallback* callback_ptr = callback_copy.get();
755 base::Closure barrier_closure = base::BarrierClosure(
756 ordered_cache_names_.size(),
757 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll,
758 weak_factory_.GetWeakPtr(),
759 base::Passed(callback_copy.Pass())));
761 for (const std::string& cache_name : ordered_cache_names_) {
762 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
763 DCHECK(cache.get());
765 cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
766 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatch,
767 weak_factory_.GetWeakPtr(), cache, barrier_closure,
768 callback_ptr));
772 void ServiceWorkerCacheStorage::MatchAllCachesDidMatch(
773 scoped_refptr<ServiceWorkerCache> cache,
774 const base::Closure& barrier_closure,
775 ServiceWorkerCache::ResponseCallback* callback,
776 ServiceWorkerCache::ErrorType error,
777 scoped_ptr<ServiceWorkerResponse> response,
778 scoped_ptr<storage::BlobDataHandle> handle) {
779 if (callback->is_null() ||
780 error == ServiceWorkerCache::ERROR_TYPE_NOT_FOUND) {
781 barrier_closure.Run();
782 return;
784 callback->Run(error, response.Pass(), handle.Pass());
785 callback->Reset(); // Only call the callback once.
787 barrier_closure.Run();
790 void ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll(
791 scoped_ptr<ServiceWorkerCache::ResponseCallback> callback) {
792 if (!callback->is_null()) {
793 callback->Run(ServiceWorkerCache::ERROR_TYPE_NOT_FOUND,
794 scoped_ptr<ServiceWorkerResponse>(),
795 scoped_ptr<storage::BlobDataHandle>());
799 scoped_refptr<ServiceWorkerCache> ServiceWorkerCacheStorage::GetLoadedCache(
800 const std::string& cache_name) {
801 DCHECK_CURRENTLY_ON(BrowserThread::IO);
802 DCHECK(initialized_);
804 CacheMap::iterator map_iter = cache_map_.find(cache_name);
805 if (map_iter == cache_map_.end())
806 return scoped_refptr<ServiceWorkerCache>();
808 base::WeakPtr<ServiceWorkerCache> cache = map_iter->second;
810 if (!cache) {
811 scoped_refptr<ServiceWorkerCache> new_cache =
812 cache_loader_->CreateServiceWorkerCache(cache_name);
813 map_iter->second = new_cache->AsWeakPtr();
814 return new_cache;
817 return make_scoped_refptr(cache.get());
820 void ServiceWorkerCacheStorage::CloseAllCachesImpl(
821 const base::Closure& callback) {
822 int live_cache_count = 0;
823 for (const auto& key_value : cache_map_) {
824 if (key_value.second)
825 live_cache_count += 1;
828 if (live_cache_count == 0) {
829 callback.Run();
830 return;
833 // The closure might modify this object so delay calling it until after
834 // iterating through cache_map_ by adding one to the barrier.
835 base::Closure barrier_closure =
836 base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
838 for (auto& key_value : cache_map_) {
839 if (key_value.second) {
840 key_value.second->Close(base::Bind(
841 CloseAllCachesDidCloseCache,
842 make_scoped_refptr(key_value.second.get()), barrier_closure));
846 barrier_closure.Run();
849 void ServiceWorkerCacheStorage::PendingClosure(const base::Closure& callback) {
850 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
851 weak_factory_.GetWeakPtr();
853 callback.Run();
854 if (cache_storage)
855 scheduler_->CompleteOperationAndRunNext();
858 void ServiceWorkerCacheStorage::PendingBoolAndErrorCallback(
859 const BoolAndErrorCallback& callback,
860 bool found,
861 CacheStorageError error) {
862 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
863 weak_factory_.GetWeakPtr();
865 callback.Run(found, error);
866 if (cache_storage)
867 scheduler_->CompleteOperationAndRunNext();
870 void ServiceWorkerCacheStorage::PendingCacheAndErrorCallback(
871 const CacheAndErrorCallback& callback,
872 const scoped_refptr<ServiceWorkerCache>& cache,
873 CacheStorageError error) {
874 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
875 weak_factory_.GetWeakPtr();
877 callback.Run(cache, error);
878 if (cache_storage)
879 scheduler_->CompleteOperationAndRunNext();
882 void ServiceWorkerCacheStorage::PendingStringsAndErrorCallback(
883 const StringsAndErrorCallback& callback,
884 const StringVector& strings,
885 CacheStorageError error) {
886 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
887 weak_factory_.GetWeakPtr();
889 callback.Run(strings, error);
890 if (cache_storage)
891 scheduler_->CompleteOperationAndRunNext();
894 void ServiceWorkerCacheStorage::PendingResponseCallback(
895 const ServiceWorkerCache::ResponseCallback& callback,
896 ServiceWorkerCache::ErrorType error,
897 scoped_ptr<ServiceWorkerResponse> response,
898 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
899 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
900 weak_factory_.GetWeakPtr();
902 callback.Run(error, response.Pass(), blob_data_handle.Pass());
903 if (cache_storage)
904 scheduler_->CompleteOperationAndRunNext();
907 } // namespace content