Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage.cc
blob71d2c352b983168a5181b3381fc987f01ea41c2b
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/sha1.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "content/browser/cache_storage/cache_storage.pb.h"
22 #include "content/browser/cache_storage/cache_storage_cache.h"
23 #include "content/browser/cache_storage/cache_storage_scheduler.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "net/base/directory_lister.h"
26 #include "net/base/net_errors.h"
27 #include "net/url_request/url_request_context_getter.h"
28 #include "storage/browser/blob/blob_storage_context.h"
29 #include "storage/browser/quota/quota_manager_proxy.h"
31 namespace content {
33 namespace {
35 void CloseAllCachesDidCloseCache(const scoped_refptr<CacheStorageCache>& cache,
36 const base::Closure& barrier_closure) {
37 barrier_closure.Run();
40 } // namespace
42 const char CacheStorage::kIndexFileName[] = "index.txt";
44 // Handles the loading and clean up of CacheStorageCache objects. The
45 // callback of every public method is guaranteed to be called.
46 class CacheStorage::CacheLoader {
47 public:
48 typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&)>
49 CacheCallback;
50 typedef base::Callback<void(bool)> BoolCallback;
51 typedef base::Callback<void(scoped_ptr<std::vector<std::string>>)>
52 StringVectorCallback;
54 CacheLoader(
55 base::SequencedTaskRunner* cache_task_runner,
56 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
57 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
58 base::WeakPtr<storage::BlobStorageContext> blob_context,
59 const GURL& origin)
60 : cache_task_runner_(cache_task_runner),
61 request_context_getter_(request_context_getter),
62 quota_manager_proxy_(quota_manager_proxy),
63 blob_context_(blob_context),
64 origin_(origin) {
65 DCHECK(!origin_.is_empty());
68 virtual ~CacheLoader() {}
70 // Creates a CacheStorageCache with the given name. It does not attempt to
71 // load the backend, that happens lazily when the cache is used.
72 virtual scoped_refptr<CacheStorageCache> CreateCache(
73 const std::string& cache_name) = 0;
75 // Deletes any pre-existing cache of the same name and then loads it.
76 virtual void CreateCache(const std::string& cache_name,
77 const CacheCallback& callback) = 0;
79 // After the backend has been deleted, do any extra house keeping such as
80 // removing the cache's directory.
81 virtual void CleanUpDeletedCache(const std::string& key,
82 const BoolCallback& callback) = 0;
84 // Writes the cache names (and sizes) to disk if applicable.
85 virtual void WriteIndex(const StringVector& cache_names,
86 const BoolCallback& callback) = 0;
88 // Loads the cache names from disk if applicable.
89 virtual void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
90 const StringVectorCallback& callback) = 0;
92 protected:
93 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
94 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
95 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
96 base::WeakPtr<storage::BlobStorageContext> blob_context_;
97 GURL origin_;
100 // Creates memory-only ServiceWorkerCaches. Because these caches have no
101 // persistent storage it is not safe to free them from memory if they might be
102 // used again. Therefore this class holds a reference to each cache until the
103 // cache is deleted.
104 class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
105 public:
106 MemoryLoader(
107 base::SequencedTaskRunner* cache_task_runner,
108 const scoped_refptr<net::URLRequestContextGetter>& request_context,
109 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
110 base::WeakPtr<storage::BlobStorageContext> blob_context,
111 const GURL& origin)
112 : CacheLoader(cache_task_runner,
113 request_context,
114 quota_manager_proxy,
115 blob_context,
116 origin) {}
118 scoped_refptr<CacheStorageCache> CreateCache(
119 const std::string& cache_name) override {
120 return CacheStorageCache::CreateMemoryCache(
121 origin_, request_context_getter_, quota_manager_proxy_, blob_context_);
124 void CreateCache(const std::string& cache_name,
125 const CacheCallback& callback) override {
126 scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
127 cache_refs_.insert(std::make_pair(cache_name, cache));
128 callback.Run(cache);
131 void CleanUpDeletedCache(const std::string& cache_name,
132 const BoolCallback& callback) override {
133 CacheRefMap::iterator it = cache_refs_.find(cache_name);
134 DCHECK(it != cache_refs_.end());
135 cache_refs_.erase(it);
136 callback.Run(true);
139 void WriteIndex(const StringVector& cache_names,
140 const BoolCallback& callback) override {
141 callback.Run(false);
144 void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
145 const StringVectorCallback& callback) override {
146 callback.Run(cache_names.Pass());
149 private:
150 typedef std::map<std::string, scoped_refptr<CacheStorageCache>> CacheRefMap;
151 ~MemoryLoader() override {}
153 // Keep a reference to each cache to ensure that it's not freed before the
154 // client calls CacheStorage::Delete or the CacheStorage is
155 // freed.
156 CacheRefMap cache_refs_;
159 class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
160 public:
161 SimpleCacheLoader(
162 const base::FilePath& origin_path,
163 base::SequencedTaskRunner* cache_task_runner,
164 const scoped_refptr<net::URLRequestContextGetter>& request_context,
165 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
166 base::WeakPtr<storage::BlobStorageContext> blob_context,
167 const GURL& origin)
168 : CacheLoader(cache_task_runner,
169 request_context,
170 quota_manager_proxy,
171 blob_context,
172 origin),
173 origin_path_(origin_path),
174 weak_ptr_factory_(this) {}
176 scoped_refptr<CacheStorageCache> CreateCache(
177 const std::string& cache_name) override {
178 DCHECK_CURRENTLY_ON(BrowserThread::IO);
180 return CacheStorageCache::CreatePersistentCache(
181 origin_, CreatePersistentCachePath(origin_path_, cache_name),
182 request_context_getter_, quota_manager_proxy_, blob_context_);
185 void CreateCache(const std::string& cache_name,
186 const CacheCallback& callback) override {
187 DCHECK_CURRENTLY_ON(BrowserThread::IO);
189 // 1. Delete the cache's directory if it exists.
190 // (CreateCacheDeleteFilesInPool)
191 // 2. Load the cache. (LoadCreateDirectoryInPool)
193 base::FilePath cache_path =
194 CreatePersistentCachePath(origin_path_, cache_name);
196 PostTaskAndReplyWithResult(
197 cache_task_runner_.get(), FROM_HERE,
198 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
199 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir, cache_name,
200 callback, weak_ptr_factory_.GetWeakPtr()));
203 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
204 if (base::PathExists(cache_path))
205 base::DeleteFile(cache_path, /* recursive */ true);
206 return base::CreateDirectory(cache_path);
209 static void CreateCachePreppedDir(const std::string& cache_name,
210 const CacheCallback& callback,
211 base::WeakPtr<SimpleCacheLoader> loader,
212 bool success) {
213 if (!success || !loader) {
214 callback.Run(scoped_refptr<CacheStorageCache>());
215 return;
218 callback.Run(loader->CreateCache(cache_name));
221 void CleanUpDeletedCache(const std::string& cache_name,
222 const BoolCallback& callback) override {
223 DCHECK_CURRENTLY_ON(BrowserThread::IO);
225 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
227 base::FilePath cache_path =
228 CreatePersistentCachePath(origin_path_, cache_name);
229 cache_task_runner_->PostTask(
230 FROM_HERE,
231 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, cache_path,
232 callback, base::ThreadTaskRunnerHandle::Get()));
235 static void CleanUpDeleteCacheDirInPool(
236 const base::FilePath& cache_path,
237 const BoolCallback& callback,
238 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
239 bool rv = base::DeleteFile(cache_path, true);
240 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
243 void WriteIndex(const StringVector& cache_names,
244 const BoolCallback& callback) override {
245 DCHECK_CURRENTLY_ON(BrowserThread::IO);
247 // 1. Create the index file as a string. (WriteIndex)
248 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
250 CacheStorageIndex index;
251 index.set_origin(origin_.spec());
253 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
254 CacheStorageIndex::Cache* index_cache = index.add_cache();
255 index_cache->set_name(cache_names[i]);
258 std::string serialized;
259 bool success = index.SerializeToString(&serialized);
260 DCHECK(success);
262 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
263 base::FilePath index_path =
264 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
266 cache_task_runner_->PostTask(
267 FROM_HERE, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
268 tmp_path, index_path, serialized, callback,
269 base::ThreadTaskRunnerHandle::Get()));
272 static void WriteIndexWriteToFileInPool(
273 const base::FilePath& tmp_path,
274 const base::FilePath& index_path,
275 const std::string& data,
276 const BoolCallback& callback,
277 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
278 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
279 if (bytes_written != implicit_cast<int>(data.size())) {
280 base::DeleteFile(tmp_path, /* recursive */ false);
281 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, false));
284 // Atomically rename the temporary index file to become the real one.
285 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
286 original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
289 void LoadIndex(scoped_ptr<std::vector<std::string>> names,
290 const StringVectorCallback& callback) override {
291 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 // 1. Read the file from disk. (LoadIndexReadFileInPool)
294 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
296 base::FilePath index_path =
297 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
299 cache_task_runner_->PostTask(
300 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
301 index_path, base::Passed(names.Pass()), callback,
302 base::ThreadTaskRunnerHandle::Get()));
305 static void LoadIndexReadFileInPool(
306 const base::FilePath& index_path,
307 scoped_ptr<std::vector<std::string>> names,
308 const StringVectorCallback& callback,
309 const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
310 std::string body;
311 base::ReadFileToString(index_path, &body);
313 original_task_runner->PostTask(
314 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
315 base::Passed(names.Pass()), callback, body));
318 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,
319 const StringVectorCallback& callback,
320 const std::string& serialized) {
321 DCHECK_CURRENTLY_ON(BrowserThread::IO);
323 CacheStorageIndex index;
324 if (index.ParseFromString(serialized)) {
325 for (int i = 0, max = index.cache_size(); i < max; ++i) {
326 const CacheStorageIndex::Cache& cache = index.cache(i);
327 names->push_back(cache.name());
331 // TODO(jkarlin): Delete caches that are in the directory and not returned
332 // in LoadIndex.
333 callback.Run(names.Pass());
336 private:
337 ~SimpleCacheLoader() override {}
339 static std::string HexedHash(const std::string& value) {
340 std::string value_hash = base::SHA1HashString(value);
341 std::string valued_hexed_hash = base::StringToLowerASCII(
342 base::HexEncode(value_hash.c_str(), value_hash.length()));
343 return valued_hexed_hash;
346 static base::FilePath CreatePersistentCachePath(
347 const base::FilePath& origin_path,
348 const std::string& cache_name) {
349 return origin_path.AppendASCII(HexedHash(cache_name));
352 const base::FilePath origin_path_;
354 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
357 CacheStorage::CacheStorage(
358 const base::FilePath& path,
359 bool memory_only,
360 base::SequencedTaskRunner* cache_task_runner,
361 const scoped_refptr<net::URLRequestContextGetter>& request_context,
362 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
363 base::WeakPtr<storage::BlobStorageContext> blob_context,
364 const GURL& origin)
365 : initialized_(false),
366 initializing_(false),
367 scheduler_(new CacheStorageScheduler()),
368 origin_path_(path),
369 cache_task_runner_(cache_task_runner),
370 memory_only_(memory_only),
371 weak_factory_(this) {
372 if (memory_only)
373 cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
374 request_context, quota_manager_proxy,
375 blob_context, origin));
376 else
377 cache_loader_.reset(new SimpleCacheLoader(
378 origin_path_, cache_task_runner_.get(), request_context,
379 quota_manager_proxy, blob_context, origin));
382 CacheStorage::~CacheStorage() {
385 void CacheStorage::OpenCache(const std::string& cache_name,
386 const CacheAndErrorCallback& callback) {
387 DCHECK_CURRENTLY_ON(BrowserThread::IO);
389 if (!initialized_)
390 LazyInit();
392 CacheAndErrorCallback pending_callback =
393 base::Bind(&CacheStorage::PendingCacheAndErrorCallback,
394 weak_factory_.GetWeakPtr(), callback);
395 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl,
396 weak_factory_.GetWeakPtr(),
397 cache_name, pending_callback));
400 void CacheStorage::HasCache(const std::string& cache_name,
401 const BoolAndErrorCallback& callback) {
402 DCHECK_CURRENTLY_ON(BrowserThread::IO);
404 if (!initialized_)
405 LazyInit();
407 BoolAndErrorCallback pending_callback =
408 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
409 weak_factory_.GetWeakPtr(), callback);
410 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl,
411 weak_factory_.GetWeakPtr(),
412 cache_name, pending_callback));
415 void CacheStorage::DeleteCache(const std::string& cache_name,
416 const BoolAndErrorCallback& callback) {
417 DCHECK_CURRENTLY_ON(BrowserThread::IO);
419 if (!initialized_)
420 LazyInit();
422 BoolAndErrorCallback pending_callback =
423 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
424 weak_factory_.GetWeakPtr(), callback);
425 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl,
426 weak_factory_.GetWeakPtr(),
427 cache_name, pending_callback));
430 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback& callback) {
431 DCHECK_CURRENTLY_ON(BrowserThread::IO);
433 if (!initialized_)
434 LazyInit();
436 StringsAndErrorCallback pending_callback =
437 base::Bind(&CacheStorage::PendingStringsAndErrorCallback,
438 weak_factory_.GetWeakPtr(), callback);
439 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl,
440 weak_factory_.GetWeakPtr(),
441 pending_callback));
444 void CacheStorage::MatchCache(
445 const std::string& cache_name,
446 scoped_ptr<ServiceWorkerFetchRequest> request,
447 const CacheStorageCache::ResponseCallback& callback) {
448 DCHECK_CURRENTLY_ON(BrowserThread::IO);
450 if (!initialized_)
451 LazyInit();
453 CacheStorageCache::ResponseCallback pending_callback =
454 base::Bind(&CacheStorage::PendingResponseCallback,
455 weak_factory_.GetWeakPtr(), callback);
456 scheduler_->ScheduleOperation(
457 base::Bind(&CacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
458 cache_name, base::Passed(request.Pass()), pending_callback));
461 void CacheStorage::MatchAllCaches(
462 scoped_ptr<ServiceWorkerFetchRequest> request,
463 const CacheStorageCache::ResponseCallback& callback) {
464 DCHECK_CURRENTLY_ON(BrowserThread::IO);
466 if (!initialized_)
467 LazyInit();
469 CacheStorageCache::ResponseCallback pending_callback =
470 base::Bind(&CacheStorage::PendingResponseCallback,
471 weak_factory_.GetWeakPtr(), callback);
472 scheduler_->ScheduleOperation(
473 base::Bind(&CacheStorage::MatchAllCachesImpl, weak_factory_.GetWeakPtr(),
474 base::Passed(request.Pass()), pending_callback));
477 void CacheStorage::CloseAllCaches(const base::Closure& callback) {
478 DCHECK_CURRENTLY_ON(BrowserThread::IO);
480 if (!initialized_) {
481 callback.Run();
482 return;
485 base::Closure pending_callback = base::Bind(
486 &CacheStorage::PendingClosure, weak_factory_.GetWeakPtr(), callback);
487 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl,
488 weak_factory_.GetWeakPtr(),
489 pending_callback));
492 int64 CacheStorage::MemoryBackedSize() const {
493 DCHECK_CURRENTLY_ON(BrowserThread::IO);
495 if (!initialized_ || !memory_only_)
496 return 0;
498 int64 sum = 0;
499 for (auto& key_value : cache_map_) {
500 if (key_value.second)
501 sum += key_value.second->MemoryBackedSize();
503 return sum;
506 void CacheStorage::StartAsyncOperationForTesting() {
507 scheduler_->ScheduleOperation(base::Bind(&base::DoNothing));
510 void CacheStorage::CompleteAsyncOperationForTesting() {
511 scheduler_->CompleteOperationAndRunNext();
514 // Init is run lazily so that it is called on the proper MessageLoop.
515 void CacheStorage::LazyInit() {
516 DCHECK_CURRENTLY_ON(BrowserThread::IO);
517 DCHECK(!initialized_);
519 if (initializing_)
520 return;
522 DCHECK(!scheduler_->ScheduledOperations());
524 initializing_ = true;
525 scheduler_->ScheduleOperation(
526 base::Bind(&CacheStorage::LazyInitImpl, weak_factory_.GetWeakPtr()));
529 void CacheStorage::LazyInitImpl() {
530 DCHECK_CURRENTLY_ON(BrowserThread::IO);
531 DCHECK(!initialized_);
532 DCHECK(initializing_);
534 // 1. Get the list of cache names (async call)
535 // 2. For each cache name, load the cache (async call)
536 // 3. Once each load is complete, update the map variables.
537 // 4. Call the list of waiting callbacks.
539 scoped_ptr<std::vector<std::string>> indexed_cache_names(
540 new std::vector<std::string>());
542 cache_loader_->LoadIndex(indexed_cache_names.Pass(),
543 base::Bind(&CacheStorage::LazyInitDidLoadIndex,
544 weak_factory_.GetWeakPtr()));
547 void CacheStorage::LazyInitDidLoadIndex(
548 scoped_ptr<std::vector<std::string>> indexed_cache_names) {
549 DCHECK_CURRENTLY_ON(BrowserThread::IO);
551 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
552 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
553 base::WeakPtr<CacheStorageCache>()));
554 ordered_cache_names_.push_back(indexed_cache_names->at(i));
557 initializing_ = false;
558 initialized_ = true;
560 scheduler_->CompleteOperationAndRunNext();
563 void CacheStorage::OpenCacheImpl(const std::string& cache_name,
564 const CacheAndErrorCallback& callback) {
565 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
566 if (cache.get()) {
567 callback.Run(cache, CACHE_STORAGE_OK);
568 return;
571 cache_loader_->CreateCache(
572 cache_name, base::Bind(&CacheStorage::CreateCacheDidCreateCache,
573 weak_factory_.GetWeakPtr(), cache_name, callback));
576 void CacheStorage::CreateCacheDidCreateCache(
577 const std::string& cache_name,
578 const CacheAndErrorCallback& callback,
579 const scoped_refptr<CacheStorageCache>& cache) {
580 DCHECK_CURRENTLY_ON(BrowserThread::IO);
582 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
583 cache != nullptr);
585 if (!cache.get()) {
586 callback.Run(scoped_refptr<CacheStorageCache>(),
587 CACHE_STORAGE_ERROR_STORAGE);
588 return;
591 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
592 ordered_cache_names_.push_back(cache_name);
594 cache_loader_->WriteIndex(
595 ordered_cache_names_,
596 base::Bind(&CacheStorage::CreateCacheDidWriteIndex,
597 weak_factory_.GetWeakPtr(), callback, cache));
600 void CacheStorage::CreateCacheDidWriteIndex(
601 const CacheAndErrorCallback& callback,
602 const scoped_refptr<CacheStorageCache>& cache,
603 bool success) {
604 DCHECK_CURRENTLY_ON(BrowserThread::IO);
605 DCHECK(cache.get());
607 // TODO(jkarlin): Handle !success.
609 callback.Run(cache, CACHE_STORAGE_OK);
612 void CacheStorage::HasCacheImpl(const std::string& cache_name,
613 const BoolAndErrorCallback& callback) {
614 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
616 callback.Run(has_cache, CACHE_STORAGE_OK);
619 void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
620 const BoolAndErrorCallback& callback) {
621 CacheMap::iterator it = cache_map_.find(cache_name);
622 if (it == cache_map_.end()) {
623 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
624 return;
627 base::WeakPtr<CacheStorageCache> cache = it->second;
628 cache_map_.erase(it);
630 // Delete the name from ordered_cache_names_.
631 StringVector::iterator iter = std::find(
632 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
633 DCHECK(iter != ordered_cache_names_.end());
634 ordered_cache_names_.erase(iter);
636 base::Closure closure =
637 base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(),
638 cache_name, callback, ordered_cache_names_,
639 make_scoped_refptr(cache.get()));
641 if (cache) {
642 cache->Close(closure);
643 return;
646 closure.Run();
649 void CacheStorage::DeleteCacheDidClose(
650 const std::string& cache_name,
651 const BoolAndErrorCallback& callback,
652 const StringVector& ordered_cache_names,
653 const scoped_refptr<CacheStorageCache>& cache /* might be null */) {
654 cache_loader_->WriteIndex(
655 ordered_cache_names,
656 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex,
657 weak_factory_.GetWeakPtr(), cache_name, callback));
660 void CacheStorage::DeleteCacheDidWriteIndex(
661 const std::string& cache_name,
662 const BoolAndErrorCallback& callback,
663 bool success) {
664 DCHECK_CURRENTLY_ON(BrowserThread::IO);
666 cache_loader_->CleanUpDeletedCache(
667 cache_name, base::Bind(&CacheStorage::DeleteCacheDidCleanUp,
668 weak_factory_.GetWeakPtr(), callback));
671 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback& callback,
672 bool success) {
673 DCHECK_CURRENTLY_ON(BrowserThread::IO);
675 callback.Run(true, CACHE_STORAGE_OK);
678 void CacheStorage::EnumerateCachesImpl(
679 const StringsAndErrorCallback& callback) {
680 callback.Run(ordered_cache_names_, CACHE_STORAGE_OK);
683 void CacheStorage::MatchCacheImpl(
684 const std::string& cache_name,
685 scoped_ptr<ServiceWorkerFetchRequest> request,
686 const CacheStorageCache::ResponseCallback& callback) {
687 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
689 if (!cache.get()) {
690 callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND,
691 scoped_ptr<ServiceWorkerResponse>(),
692 scoped_ptr<storage::BlobDataHandle>());
693 return;
696 // Pass the cache along to the callback to keep the cache open until match is
697 // done.
698 cache->Match(request.Pass(),
699 base::Bind(&CacheStorage::MatchCacheDidMatch,
700 weak_factory_.GetWeakPtr(), cache, callback));
703 void CacheStorage::MatchCacheDidMatch(
704 const scoped_refptr<CacheStorageCache>& cache,
705 const CacheStorageCache::ResponseCallback& callback,
706 CacheStorageError error,
707 scoped_ptr<ServiceWorkerResponse> response,
708 scoped_ptr<storage::BlobDataHandle> handle) {
709 callback.Run(error, response.Pass(), handle.Pass());
712 void CacheStorage::MatchAllCachesImpl(
713 scoped_ptr<ServiceWorkerFetchRequest> request,
714 const CacheStorageCache::ResponseCallback& callback) {
715 scoped_ptr<CacheStorageCache::ResponseCallback> callback_copy(
716 new CacheStorageCache::ResponseCallback(callback));
718 CacheStorageCache::ResponseCallback* callback_ptr = callback_copy.get();
719 base::Closure barrier_closure =
720 base::BarrierClosure(ordered_cache_names_.size(),
721 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll,
722 weak_factory_.GetWeakPtr(),
723 base::Passed(callback_copy.Pass())));
725 for (const std::string& cache_name : ordered_cache_names_) {
726 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
727 DCHECK(cache.get());
729 cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
730 base::Bind(&CacheStorage::MatchAllCachesDidMatch,
731 weak_factory_.GetWeakPtr(), cache, barrier_closure,
732 callback_ptr));
736 void CacheStorage::MatchAllCachesDidMatch(
737 scoped_refptr<CacheStorageCache> cache,
738 const base::Closure& barrier_closure,
739 CacheStorageCache::ResponseCallback* callback,
740 CacheStorageError error,
741 scoped_ptr<ServiceWorkerResponse> response,
742 scoped_ptr<storage::BlobDataHandle> handle) {
743 if (callback->is_null() || error == CACHE_STORAGE_ERROR_NOT_FOUND) {
744 barrier_closure.Run();
745 return;
747 callback->Run(error, response.Pass(), handle.Pass());
748 callback->Reset(); // Only call the callback once.
750 barrier_closure.Run();
753 void CacheStorage::MatchAllCachesDidMatchAll(
754 scoped_ptr<CacheStorageCache::ResponseCallback> callback) {
755 if (!callback->is_null()) {
756 callback->Run(CACHE_STORAGE_ERROR_NOT_FOUND,
757 scoped_ptr<ServiceWorkerResponse>(),
758 scoped_ptr<storage::BlobDataHandle>());
762 scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
763 const std::string& cache_name) {
764 DCHECK_CURRENTLY_ON(BrowserThread::IO);
765 DCHECK(initialized_);
767 CacheMap::iterator map_iter = cache_map_.find(cache_name);
768 if (map_iter == cache_map_.end())
769 return scoped_refptr<CacheStorageCache>();
771 base::WeakPtr<CacheStorageCache> cache = map_iter->second;
773 if (!cache) {
774 scoped_refptr<CacheStorageCache> new_cache =
775 cache_loader_->CreateCache(cache_name);
776 map_iter->second = new_cache->AsWeakPtr();
777 return new_cache;
780 return make_scoped_refptr(cache.get());
783 void CacheStorage::CloseAllCachesImpl(const base::Closure& callback) {
784 int live_cache_count = 0;
785 for (const auto& key_value : cache_map_) {
786 if (key_value.second)
787 live_cache_count += 1;
790 if (live_cache_count == 0) {
791 callback.Run();
792 return;
795 // The closure might modify this object so delay calling it until after
796 // iterating through cache_map_ by adding one to the barrier.
797 base::Closure barrier_closure =
798 base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
800 for (auto& key_value : cache_map_) {
801 if (key_value.second) {
802 key_value.second->Close(base::Bind(
803 CloseAllCachesDidCloseCache,
804 make_scoped_refptr(key_value.second.get()), barrier_closure));
808 barrier_closure.Run();
811 void CacheStorage::PendingClosure(const base::Closure& callback) {
812 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
814 callback.Run();
815 if (cache_storage)
816 scheduler_->CompleteOperationAndRunNext();
819 void CacheStorage::PendingBoolAndErrorCallback(
820 const BoolAndErrorCallback& callback,
821 bool found,
822 CacheStorageError error) {
823 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
825 callback.Run(found, error);
826 if (cache_storage)
827 scheduler_->CompleteOperationAndRunNext();
830 void CacheStorage::PendingCacheAndErrorCallback(
831 const CacheAndErrorCallback& callback,
832 const scoped_refptr<CacheStorageCache>& cache,
833 CacheStorageError error) {
834 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
836 callback.Run(cache, error);
837 if (cache_storage)
838 scheduler_->CompleteOperationAndRunNext();
841 void CacheStorage::PendingStringsAndErrorCallback(
842 const StringsAndErrorCallback& callback,
843 const StringVector& strings,
844 CacheStorageError error) {
845 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
847 callback.Run(strings, error);
848 if (cache_storage)
849 scheduler_->CompleteOperationAndRunNext();
852 void CacheStorage::PendingResponseCallback(
853 const CacheStorageCache::ResponseCallback& callback,
854 CacheStorageError error,
855 scoped_ptr<ServiceWorkerResponse> response,
856 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
857 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
859 callback.Run(error, response.Pass(), blob_data_handle.Pass());
860 if (cache_storage)
861 scheduler_->CompleteOperationAndRunNext();
864 } // namespace content