Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage.cc
blob42f0215b8477c7a4afac97353e844b331c97e3f4
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/cache_storage/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/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/sha1.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/thread_task_runner_handle.h"
22 #include "content/browser/cache_storage/cache_storage.pb.h"
23 #include "content/browser/cache_storage/cache_storage_cache.h"
24 #include "content/browser/cache_storage/cache_storage_scheduler.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "net/base/directory_lister.h"
27 #include "net/base/net_errors.h"
28 #include "net/url_request/url_request_context_getter.h"
29 #include "storage/browser/blob/blob_storage_context.h"
30 #include "storage/browser/quota/quota_manager_proxy.h"
32 namespace content {
34 namespace {
36 void CloseAllCachesDidCloseCache(const scoped_refptr<CacheStorageCache>& cache,
37 const base::Closure& barrier_closure) {
38 barrier_closure.Run();
41 } // namespace
43 const char CacheStorage::kIndexFileName[] = "index.txt";
45 // Handles the loading and clean up of CacheStorageCache objects. The
46 // callback of every public method is guaranteed to be called.
47 class CacheStorage::CacheLoader {
48 public:
49 typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&)>
50 CacheCallback;
51 typedef base::Callback<void(bool)> BoolCallback;
52 typedef base::Callback<void(scoped_ptr<std::vector<std::string>>)>
53 StringVectorCallback;
55 CacheLoader(
56 base::SequencedTaskRunner* cache_task_runner,
57 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
58 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
59 base::WeakPtr<storage::BlobStorageContext> blob_context,
60 const GURL& origin)
61 : cache_task_runner_(cache_task_runner),
62 request_context_getter_(request_context_getter),
63 quota_manager_proxy_(quota_manager_proxy),
64 blob_context_(blob_context),
65 origin_(origin) {
66 DCHECK(!origin_.is_empty());
69 virtual ~CacheLoader() {}
71 // Creates a CacheStorageCache with the given name. It does not attempt to
72 // load the backend, that happens lazily when the cache is used.
73 virtual scoped_refptr<CacheStorageCache> CreateCache(
74 const std::string& cache_name) = 0;
76 // Deletes any pre-existing cache of the same name and then loads it.
77 virtual void CreateCache(const std::string& cache_name,
78 const CacheCallback& callback) = 0;
80 // After the backend has been deleted, do any extra house keeping such as
81 // removing the cache's directory.
82 virtual void CleanUpDeletedCache(const std::string& key,
83 const BoolCallback& callback) = 0;
85 // Writes the cache names (and sizes) to disk if applicable.
86 virtual void WriteIndex(const StringVector& cache_names,
87 const BoolCallback& callback) = 0;
89 // Loads the cache names from disk if applicable.
90 virtual void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
91 const StringVectorCallback& callback) = 0;
93 protected:
94 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
95 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
96 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
97 base::WeakPtr<storage::BlobStorageContext> blob_context_;
98 GURL origin_;
101 // Creates memory-only ServiceWorkerCaches. Because these caches have no
102 // persistent storage it is not safe to free them from memory if they might be
103 // used again. Therefore this class holds a reference to each cache until the
104 // cache is deleted.
105 class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
106 public:
107 MemoryLoader(
108 base::SequencedTaskRunner* cache_task_runner,
109 const scoped_refptr<net::URLRequestContextGetter>& request_context,
110 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
111 base::WeakPtr<storage::BlobStorageContext> blob_context,
112 const GURL& origin)
113 : CacheLoader(cache_task_runner,
114 request_context,
115 quota_manager_proxy,
116 blob_context,
117 origin) {}
119 scoped_refptr<CacheStorageCache> CreateCache(
120 const std::string& cache_name) override {
121 return CacheStorageCache::CreateMemoryCache(
122 origin_, request_context_getter_, quota_manager_proxy_, blob_context_);
125 void CreateCache(const std::string& cache_name,
126 const CacheCallback& callback) override {
127 scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
128 cache_refs_.insert(std::make_pair(cache_name, cache));
129 callback.Run(cache);
132 void CleanUpDeletedCache(const std::string& cache_name,
133 const BoolCallback& callback) override {
134 CacheRefMap::iterator it = cache_refs_.find(cache_name);
135 DCHECK(it != cache_refs_.end());
136 cache_refs_.erase(it);
137 callback.Run(true);
140 void WriteIndex(const StringVector& cache_names,
141 const BoolCallback& callback) override {
142 callback.Run(false);
145 void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
146 const StringVectorCallback& callback) override {
147 callback.Run(cache_names.Pass());
150 private:
151 typedef std::map<std::string, scoped_refptr<CacheStorageCache>> CacheRefMap;
152 ~MemoryLoader() override {}
154 // Keep a reference to each cache to ensure that it's not freed before the
155 // client calls CacheStorage::Delete or the CacheStorage is
156 // freed.
157 CacheRefMap cache_refs_;
160 class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
161 public:
162 SimpleCacheLoader(
163 const base::FilePath& origin_path,
164 base::SequencedTaskRunner* cache_task_runner,
165 const scoped_refptr<net::URLRequestContextGetter>& request_context,
166 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
167 base::WeakPtr<storage::BlobStorageContext> blob_context,
168 const GURL& origin)
169 : CacheLoader(cache_task_runner,
170 request_context,
171 quota_manager_proxy,
172 blob_context,
173 origin),
174 origin_path_(origin_path),
175 weak_ptr_factory_(this) {}
177 scoped_refptr<CacheStorageCache> CreateCache(
178 const std::string& cache_name) override {
179 DCHECK_CURRENTLY_ON(BrowserThread::IO);
181 return CacheStorageCache::CreatePersistentCache(
182 origin_, CreatePersistentCachePath(origin_path_, cache_name),
183 request_context_getter_, quota_manager_proxy_, blob_context_);
186 void CreateCache(const std::string& cache_name,
187 const CacheCallback& callback) override {
188 DCHECK_CURRENTLY_ON(BrowserThread::IO);
190 // 1. Delete the cache's directory if it exists.
191 // (CreateCacheDeleteFilesInPool)
192 // 2. Load the cache. (LoadCreateDirectoryInPool)
194 base::FilePath cache_path =
195 CreatePersistentCachePath(origin_path_, cache_name);
197 PostTaskAndReplyWithResult(
198 cache_task_runner_.get(), FROM_HERE,
199 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
200 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir, cache_name,
201 callback, weak_ptr_factory_.GetWeakPtr()));
204 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
205 if (base::PathExists(cache_path))
206 base::DeleteFile(cache_path, /* recursive */ true);
207 return base::CreateDirectory(cache_path);
210 static void CreateCachePreppedDir(const std::string& cache_name,
211 const CacheCallback& callback,
212 base::WeakPtr<SimpleCacheLoader> loader,
213 bool success) {
214 if (!success || !loader) {
215 callback.Run(scoped_refptr<CacheStorageCache>());
216 return;
219 callback.Run(loader->CreateCache(cache_name));
222 void CleanUpDeletedCache(const std::string& cache_name,
223 const BoolCallback& callback) override {
224 DCHECK_CURRENTLY_ON(BrowserThread::IO);
226 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
228 base::FilePath cache_path =
229 CreatePersistentCachePath(origin_path_, cache_name);
230 cache_task_runner_->PostTask(
231 FROM_HERE,
232 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, cache_path,
233 callback, base::ThreadTaskRunnerHandle::Get()));
236 static void CleanUpDeleteCacheDirInPool(
237 const base::FilePath& cache_path,
238 const BoolCallback& callback,
239 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
240 bool rv = base::DeleteFile(cache_path, true);
241 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
244 void WriteIndex(const StringVector& cache_names,
245 const BoolCallback& callback) override {
246 DCHECK_CURRENTLY_ON(BrowserThread::IO);
248 // 1. Create the index file as a string. (WriteIndex)
249 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
251 CacheStorageIndex index;
252 index.set_origin(origin_.spec());
254 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
255 CacheStorageIndex::Cache* index_cache = index.add_cache();
256 index_cache->set_name(cache_names[i]);
259 std::string serialized;
260 bool success = index.SerializeToString(&serialized);
261 DCHECK(success);
263 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
264 base::FilePath index_path =
265 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
267 cache_task_runner_->PostTask(
268 FROM_HERE, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
269 tmp_path, index_path, serialized, callback,
270 base::ThreadTaskRunnerHandle::Get()));
273 static void WriteIndexWriteToFileInPool(
274 const base::FilePath& tmp_path,
275 const base::FilePath& index_path,
276 const std::string& data,
277 const BoolCallback& callback,
278 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
279 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
280 if (bytes_written != base::checked_cast<int>(data.size())) {
281 base::DeleteFile(tmp_path, /* recursive */ false);
282 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, false));
285 // Atomically rename the temporary index file to become the real one.
286 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
287 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
290 void LoadIndex(scoped_ptr<std::vector<std::string>> names,
291 const StringVectorCallback& callback) override {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO);
294 // 1. Read the file from disk. (LoadIndexReadFileInPool)
295 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
297 base::FilePath index_path =
298 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
300 cache_task_runner_->PostTask(
301 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
302 index_path, base::Passed(names.Pass()), callback,
303 base::ThreadTaskRunnerHandle::Get()));
306 static void LoadIndexReadFileInPool(
307 const base::FilePath& index_path,
308 scoped_ptr<std::vector<std::string>> names,
309 const StringVectorCallback& callback,
310 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
311 std::string body;
312 base::ReadFileToString(index_path, &body);
314 original_task_runner->PostTask(
315 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
316 base::Passed(names.Pass()), callback, body));
319 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,
320 const StringVectorCallback& callback,
321 const std::string& serialized) {
322 DCHECK_CURRENTLY_ON(BrowserThread::IO);
324 CacheStorageIndex index;
325 if (index.ParseFromString(serialized)) {
326 for (int i = 0, max = index.cache_size(); i < max; ++i) {
327 const CacheStorageIndex::Cache& cache = index.cache(i);
328 names->push_back(cache.name());
332 // TODO(jkarlin): Delete caches that are in the directory and not returned
333 // in LoadIndex.
334 callback.Run(names.Pass());
337 private:
338 ~SimpleCacheLoader() override {}
340 static std::string HexedHash(const std::string& value) {
341 std::string value_hash = base::SHA1HashString(value);
342 std::string valued_hexed_hash = base::ToLowerASCII(
343 base::HexEncode(value_hash.c_str(), value_hash.length()));
344 return valued_hexed_hash;
347 static base::FilePath CreatePersistentCachePath(
348 const base::FilePath& origin_path,
349 const std::string& cache_name) {
350 return origin_path.AppendASCII(HexedHash(cache_name));
353 const base::FilePath origin_path_;
355 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
358 CacheStorage::CacheStorage(
359 const base::FilePath& path,
360 bool memory_only,
361 base::SequencedTaskRunner* cache_task_runner,
362 const scoped_refptr<net::URLRequestContextGetter>& request_context,
363 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
364 base::WeakPtr<storage::BlobStorageContext> blob_context,
365 const GURL& origin)
366 : initialized_(false),
367 initializing_(false),
368 scheduler_(new CacheStorageScheduler()),
369 origin_path_(path),
370 cache_task_runner_(cache_task_runner),
371 memory_only_(memory_only),
372 weak_factory_(this) {
373 if (memory_only)
374 cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
375 request_context, quota_manager_proxy,
376 blob_context, origin));
377 else
378 cache_loader_.reset(new SimpleCacheLoader(
379 origin_path_, cache_task_runner_.get(), request_context,
380 quota_manager_proxy, blob_context, origin));
383 CacheStorage::~CacheStorage() {
386 void CacheStorage::OpenCache(const std::string& cache_name,
387 const CacheAndErrorCallback& callback) {
388 DCHECK_CURRENTLY_ON(BrowserThread::IO);
390 if (!initialized_)
391 LazyInit();
393 CacheAndErrorCallback pending_callback =
394 base::Bind(&CacheStorage::PendingCacheAndErrorCallback,
395 weak_factory_.GetWeakPtr(), callback);
396 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl,
397 weak_factory_.GetWeakPtr(),
398 cache_name, pending_callback));
401 void CacheStorage::HasCache(const std::string& cache_name,
402 const BoolAndErrorCallback& callback) {
403 DCHECK_CURRENTLY_ON(BrowserThread::IO);
405 if (!initialized_)
406 LazyInit();
408 BoolAndErrorCallback pending_callback =
409 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
410 weak_factory_.GetWeakPtr(), callback);
411 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl,
412 weak_factory_.GetWeakPtr(),
413 cache_name, pending_callback));
416 void CacheStorage::DeleteCache(const std::string& cache_name,
417 const BoolAndErrorCallback& callback) {
418 DCHECK_CURRENTLY_ON(BrowserThread::IO);
420 if (!initialized_)
421 LazyInit();
423 BoolAndErrorCallback pending_callback =
424 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
425 weak_factory_.GetWeakPtr(), callback);
426 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl,
427 weak_factory_.GetWeakPtr(),
428 cache_name, pending_callback));
431 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback& callback) {
432 DCHECK_CURRENTLY_ON(BrowserThread::IO);
434 if (!initialized_)
435 LazyInit();
437 StringsAndErrorCallback pending_callback =
438 base::Bind(&CacheStorage::PendingStringsAndErrorCallback,
439 weak_factory_.GetWeakPtr(), callback);
440 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl,
441 weak_factory_.GetWeakPtr(),
442 pending_callback));
445 void CacheStorage::MatchCache(
446 const std::string& cache_name,
447 scoped_ptr<ServiceWorkerFetchRequest> request,
448 const CacheStorageCache::ResponseCallback& callback) {
449 DCHECK_CURRENTLY_ON(BrowserThread::IO);
451 if (!initialized_)
452 LazyInit();
454 CacheStorageCache::ResponseCallback pending_callback =
455 base::Bind(&CacheStorage::PendingResponseCallback,
456 weak_factory_.GetWeakPtr(), callback);
457 scheduler_->ScheduleOperation(
458 base::Bind(&CacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
459 cache_name, base::Passed(request.Pass()), pending_callback));
462 void CacheStorage::MatchAllCaches(
463 scoped_ptr<ServiceWorkerFetchRequest> request,
464 const CacheStorageCache::ResponseCallback& callback) {
465 DCHECK_CURRENTLY_ON(BrowserThread::IO);
467 if (!initialized_)
468 LazyInit();
470 CacheStorageCache::ResponseCallback pending_callback =
471 base::Bind(&CacheStorage::PendingResponseCallback,
472 weak_factory_.GetWeakPtr(), callback);
473 scheduler_->ScheduleOperation(
474 base::Bind(&CacheStorage::MatchAllCachesImpl, weak_factory_.GetWeakPtr(),
475 base::Passed(request.Pass()), pending_callback));
478 void CacheStorage::CloseAllCaches(const base::Closure& callback) {
479 DCHECK_CURRENTLY_ON(BrowserThread::IO);
481 if (!initialized_) {
482 callback.Run();
483 return;
486 base::Closure pending_callback = base::Bind(
487 &CacheStorage::PendingClosure, weak_factory_.GetWeakPtr(), callback);
488 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl,
489 weak_factory_.GetWeakPtr(),
490 pending_callback));
493 int64 CacheStorage::MemoryBackedSize() const {
494 DCHECK_CURRENTLY_ON(BrowserThread::IO);
496 if (!initialized_ || !memory_only_)
497 return 0;
499 int64 sum = 0;
500 for (auto& key_value : cache_map_) {
501 if (key_value.second)
502 sum += key_value.second->MemoryBackedSize();
504 return sum;
507 void CacheStorage::StartAsyncOperationForTesting() {
508 scheduler_->ScheduleOperation(base::Bind(&base::DoNothing));
511 void CacheStorage::CompleteAsyncOperationForTesting() {
512 scheduler_->CompleteOperationAndRunNext();
515 // Init is run lazily so that it is called on the proper MessageLoop.
516 void CacheStorage::LazyInit() {
517 DCHECK_CURRENTLY_ON(BrowserThread::IO);
518 DCHECK(!initialized_);
520 if (initializing_)
521 return;
523 DCHECK(!scheduler_->ScheduledOperations());
525 initializing_ = true;
526 scheduler_->ScheduleOperation(
527 base::Bind(&CacheStorage::LazyInitImpl, weak_factory_.GetWeakPtr()));
530 void CacheStorage::LazyInitImpl() {
531 DCHECK_CURRENTLY_ON(BrowserThread::IO);
532 DCHECK(!initialized_);
533 DCHECK(initializing_);
535 // 1. Get the list of cache names (async call)
536 // 2. For each cache name, load the cache (async call)
537 // 3. Once each load is complete, update the map variables.
538 // 4. Call the list of waiting callbacks.
540 scoped_ptr<std::vector<std::string>> indexed_cache_names(
541 new std::vector<std::string>());
543 cache_loader_->LoadIndex(indexed_cache_names.Pass(),
544 base::Bind(&CacheStorage::LazyInitDidLoadIndex,
545 weak_factory_.GetWeakPtr()));
548 void CacheStorage::LazyInitDidLoadIndex(
549 scoped_ptr<std::vector<std::string>> indexed_cache_names) {
550 DCHECK_CURRENTLY_ON(BrowserThread::IO);
552 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
553 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
554 base::WeakPtr<CacheStorageCache>()));
555 ordered_cache_names_.push_back(indexed_cache_names->at(i));
558 initializing_ = false;
559 initialized_ = true;
561 scheduler_->CompleteOperationAndRunNext();
564 void CacheStorage::OpenCacheImpl(const std::string& cache_name,
565 const CacheAndErrorCallback& callback) {
566 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
567 if (cache.get()) {
568 callback.Run(cache, CACHE_STORAGE_OK);
569 return;
572 cache_loader_->CreateCache(
573 cache_name, base::Bind(&CacheStorage::CreateCacheDidCreateCache,
574 weak_factory_.GetWeakPtr(), cache_name, callback));
577 void CacheStorage::CreateCacheDidCreateCache(
578 const std::string& cache_name,
579 const CacheAndErrorCallback& callback,
580 const scoped_refptr<CacheStorageCache>& cache) {
581 DCHECK_CURRENTLY_ON(BrowserThread::IO);
583 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
584 cache != nullptr);
586 if (!cache.get()) {
587 callback.Run(scoped_refptr<CacheStorageCache>(),
588 CACHE_STORAGE_ERROR_STORAGE);
589 return;
592 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
593 ordered_cache_names_.push_back(cache_name);
595 cache_loader_->WriteIndex(
596 ordered_cache_names_,
597 base::Bind(&CacheStorage::CreateCacheDidWriteIndex,
598 weak_factory_.GetWeakPtr(), callback, cache));
601 void CacheStorage::CreateCacheDidWriteIndex(
602 const CacheAndErrorCallback& callback,
603 const scoped_refptr<CacheStorageCache>& cache,
604 bool success) {
605 DCHECK_CURRENTLY_ON(BrowserThread::IO);
606 DCHECK(cache.get());
608 // TODO(jkarlin): Handle !success.
610 callback.Run(cache, CACHE_STORAGE_OK);
613 void CacheStorage::HasCacheImpl(const std::string& cache_name,
614 const BoolAndErrorCallback& callback) {
615 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
617 callback.Run(has_cache, CACHE_STORAGE_OK);
620 void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
621 const BoolAndErrorCallback& callback) {
622 CacheMap::iterator it = cache_map_.find(cache_name);
623 if (it == cache_map_.end()) {
624 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
625 return;
628 base::WeakPtr<CacheStorageCache> cache = it->second;
629 cache_map_.erase(it);
631 // Delete the name from ordered_cache_names_.
632 StringVector::iterator iter = std::find(
633 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
634 DCHECK(iter != ordered_cache_names_.end());
635 ordered_cache_names_.erase(iter);
637 base::Closure closure =
638 base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(),
639 cache_name, callback, ordered_cache_names_,
640 make_scoped_refptr(cache.get()));
642 if (cache) {
643 cache->Close(closure);
644 return;
647 closure.Run();
650 void CacheStorage::DeleteCacheDidClose(
651 const std::string& cache_name,
652 const BoolAndErrorCallback& callback,
653 const StringVector& ordered_cache_names,
654 const scoped_refptr<CacheStorageCache>& cache /* might be null */) {
655 cache_loader_->WriteIndex(
656 ordered_cache_names,
657 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex,
658 weak_factory_.GetWeakPtr(), cache_name, callback));
661 void CacheStorage::DeleteCacheDidWriteIndex(
662 const std::string& cache_name,
663 const BoolAndErrorCallback& callback,
664 bool success) {
665 DCHECK_CURRENTLY_ON(BrowserThread::IO);
667 cache_loader_->CleanUpDeletedCache(
668 cache_name, base::Bind(&CacheStorage::DeleteCacheDidCleanUp,
669 weak_factory_.GetWeakPtr(), callback));
672 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback& callback,
673 bool success) {
674 DCHECK_CURRENTLY_ON(BrowserThread::IO);
676 callback.Run(true, CACHE_STORAGE_OK);
679 void CacheStorage::EnumerateCachesImpl(
680 const StringsAndErrorCallback& callback) {
681 callback.Run(ordered_cache_names_, CACHE_STORAGE_OK);
684 void CacheStorage::MatchCacheImpl(
685 const std::string& cache_name,
686 scoped_ptr<ServiceWorkerFetchRequest> request,
687 const CacheStorageCache::ResponseCallback& callback) {
688 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
690 if (!cache.get()) {
691 callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND,
692 scoped_ptr<ServiceWorkerResponse>(),
693 scoped_ptr<storage::BlobDataHandle>());
694 return;
697 // Pass the cache along to the callback to keep the cache open until match is
698 // done.
699 cache->Match(request.Pass(),
700 base::Bind(&CacheStorage::MatchCacheDidMatch,
701 weak_factory_.GetWeakPtr(), cache, callback));
704 void CacheStorage::MatchCacheDidMatch(
705 const scoped_refptr<CacheStorageCache>& cache,
706 const CacheStorageCache::ResponseCallback& callback,
707 CacheStorageError error,
708 scoped_ptr<ServiceWorkerResponse> response,
709 scoped_ptr<storage::BlobDataHandle> handle) {
710 callback.Run(error, response.Pass(), handle.Pass());
713 void CacheStorage::MatchAllCachesImpl(
714 scoped_ptr<ServiceWorkerFetchRequest> request,
715 const CacheStorageCache::ResponseCallback& callback) {
716 scoped_ptr<CacheStorageCache::ResponseCallback> callback_copy(
717 new CacheStorageCache::ResponseCallback(callback));
719 CacheStorageCache::ResponseCallback* callback_ptr = callback_copy.get();
720 base::Closure barrier_closure =
721 base::BarrierClosure(ordered_cache_names_.size(),
722 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll,
723 weak_factory_.GetWeakPtr(),
724 base::Passed(callback_copy.Pass())));
726 for (const std::string& cache_name : ordered_cache_names_) {
727 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
728 DCHECK(cache.get());
730 cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
731 base::Bind(&CacheStorage::MatchAllCachesDidMatch,
732 weak_factory_.GetWeakPtr(), cache, barrier_closure,
733 callback_ptr));
737 void CacheStorage::MatchAllCachesDidMatch(
738 scoped_refptr<CacheStorageCache> cache,
739 const base::Closure& barrier_closure,
740 CacheStorageCache::ResponseCallback* callback,
741 CacheStorageError error,
742 scoped_ptr<ServiceWorkerResponse> response,
743 scoped_ptr<storage::BlobDataHandle> handle) {
744 if (callback->is_null() || error == CACHE_STORAGE_ERROR_NOT_FOUND) {
745 barrier_closure.Run();
746 return;
748 callback->Run(error, response.Pass(), handle.Pass());
749 callback->Reset(); // Only call the callback once.
751 barrier_closure.Run();
754 void CacheStorage::MatchAllCachesDidMatchAll(
755 scoped_ptr<CacheStorageCache::ResponseCallback> callback) {
756 if (!callback->is_null()) {
757 callback->Run(CACHE_STORAGE_ERROR_NOT_FOUND,
758 scoped_ptr<ServiceWorkerResponse>(),
759 scoped_ptr<storage::BlobDataHandle>());
763 scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
764 const std::string& cache_name) {
765 DCHECK_CURRENTLY_ON(BrowserThread::IO);
766 DCHECK(initialized_);
768 CacheMap::iterator map_iter = cache_map_.find(cache_name);
769 if (map_iter == cache_map_.end())
770 return scoped_refptr<CacheStorageCache>();
772 base::WeakPtr<CacheStorageCache> cache = map_iter->second;
774 if (!cache) {
775 scoped_refptr<CacheStorageCache> new_cache =
776 cache_loader_->CreateCache(cache_name);
777 map_iter->second = new_cache->AsWeakPtr();
778 return new_cache;
781 return make_scoped_refptr(cache.get());
784 void CacheStorage::CloseAllCachesImpl(const base::Closure& callback) {
785 int live_cache_count = 0;
786 for (const auto& key_value : cache_map_) {
787 if (key_value.second)
788 live_cache_count += 1;
791 if (live_cache_count == 0) {
792 callback.Run();
793 return;
796 // The closure might modify this object so delay calling it until after
797 // iterating through cache_map_ by adding one to the barrier.
798 base::Closure barrier_closure =
799 base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
801 for (auto& key_value : cache_map_) {
802 if (key_value.second) {
803 key_value.second->Close(base::Bind(
804 CloseAllCachesDidCloseCache,
805 make_scoped_refptr(key_value.second.get()), barrier_closure));
809 barrier_closure.Run();
812 void CacheStorage::PendingClosure(const base::Closure& callback) {
813 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
815 callback.Run();
816 if (cache_storage)
817 scheduler_->CompleteOperationAndRunNext();
820 void CacheStorage::PendingBoolAndErrorCallback(
821 const BoolAndErrorCallback& callback,
822 bool found,
823 CacheStorageError error) {
824 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
826 callback.Run(found, error);
827 if (cache_storage)
828 scheduler_->CompleteOperationAndRunNext();
831 void CacheStorage::PendingCacheAndErrorCallback(
832 const CacheAndErrorCallback& callback,
833 const scoped_refptr<CacheStorageCache>& cache,
834 CacheStorageError error) {
835 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
837 callback.Run(cache, error);
838 if (cache_storage)
839 scheduler_->CompleteOperationAndRunNext();
842 void CacheStorage::PendingStringsAndErrorCallback(
843 const StringsAndErrorCallback& callback,
844 const StringVector& strings,
845 CacheStorageError error) {
846 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
848 callback.Run(strings, error);
849 if (cache_storage)
850 scheduler_->CompleteOperationAndRunNext();
853 void CacheStorage::PendingResponseCallback(
854 const CacheStorageCache::ResponseCallback& callback,
855 CacheStorageError error,
856 scoped_ptr<ServiceWorkerResponse> response,
857 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
858 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
860 callback.Run(error, response.Pass(), blob_data_handle.Pass());
861 if (cache_storage)
862 scheduler_->CompleteOperationAndRunNext();
865 } // namespace content