Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage.cc
blobbca88cd7b8b7dd718910227db663c0068594ab05
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/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/cache_storage/cache_storage.pb.h"
19 #include "content/browser/cache_storage/cache_storage_cache.h"
20 #include "content/browser/cache_storage/cache_storage_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<CacheStorageCache>& cache,
32 const base::Closure& barrier_closure) {
33 barrier_closure.Run();
36 } // namespace
38 const char CacheStorage::kIndexFileName[] = "index.txt";
40 // Handles the loading and clean up of CacheStorageCache objects. The
41 // callback of every public method is guaranteed to be called.
42 class CacheStorage::CacheLoader {
43 public:
44 typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&)>
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 CacheStorageCache 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<CacheStorageCache> CreateCache(
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 CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
101 public:
102 MemoryLoader(
103 base::SequencedTaskRunner* cache_task_runner,
104 net::URLRequestContext* request_context,
105 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
106 base::WeakPtr<storage::BlobStorageContext> blob_context,
107 const GURL& origin)
108 : CacheLoader(cache_task_runner,
109 request_context,
110 quota_manager_proxy,
111 blob_context,
112 origin) {}
114 scoped_refptr<CacheStorageCache> CreateCache(
115 const std::string& cache_name) override {
116 return CacheStorageCache::CreateMemoryCache(
117 origin_, request_context_, quota_manager_proxy_, blob_context_);
120 void CreateCache(const std::string& cache_name,
121 const CacheCallback& callback) override {
122 scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
123 cache_refs_.insert(std::make_pair(cache_name, cache));
124 callback.Run(cache);
127 void CleanUpDeletedCache(const std::string& cache_name,
128 const BoolCallback& callback) override {
129 CacheRefMap::iterator it = cache_refs_.find(cache_name);
130 DCHECK(it != cache_refs_.end());
131 cache_refs_.erase(it);
132 callback.Run(true);
135 void WriteIndex(const StringVector& cache_names,
136 const BoolCallback& callback) override {
137 callback.Run(false);
140 void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
141 const StringVectorCallback& callback) override {
142 callback.Run(cache_names.Pass());
145 private:
146 typedef std::map<std::string, scoped_refptr<CacheStorageCache>> CacheRefMap;
147 ~MemoryLoader() override {}
149 // Keep a reference to each cache to ensure that it's not freed before the
150 // client calls CacheStorage::Delete or the CacheStorage is
151 // freed.
152 CacheRefMap cache_refs_;
155 class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
156 public:
157 SimpleCacheLoader(
158 const base::FilePath& origin_path,
159 base::SequencedTaskRunner* cache_task_runner,
160 net::URLRequestContext* request_context,
161 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
162 base::WeakPtr<storage::BlobStorageContext> blob_context,
163 const GURL& origin)
164 : CacheLoader(cache_task_runner,
165 request_context,
166 quota_manager_proxy,
167 blob_context,
168 origin),
169 origin_path_(origin_path),
170 weak_ptr_factory_(this) {}
172 scoped_refptr<CacheStorageCache> CreateCache(
173 const std::string& cache_name) override {
174 DCHECK_CURRENTLY_ON(BrowserThread::IO);
176 return CacheStorageCache::CreatePersistentCache(
177 origin_, CreatePersistentCachePath(origin_path_, cache_name),
178 request_context_, quota_manager_proxy_, blob_context_);
181 void CreateCache(const std::string& cache_name,
182 const CacheCallback& callback) override {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO);
185 // 1. Delete the cache's directory if it exists.
186 // (CreateCacheDeleteFilesInPool)
187 // 2. Load the cache. (LoadCreateDirectoryInPool)
189 base::FilePath cache_path =
190 CreatePersistentCachePath(origin_path_, cache_name);
192 PostTaskAndReplyWithResult(
193 cache_task_runner_.get(), FROM_HERE,
194 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
195 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir, cache_name,
196 callback, weak_ptr_factory_.GetWeakPtr()));
199 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
200 if (base::PathExists(cache_path))
201 base::DeleteFile(cache_path, /* recursive */ true);
202 return base::CreateDirectory(cache_path);
205 static void CreateCachePreppedDir(const std::string& cache_name,
206 const CacheCallback& callback,
207 base::WeakPtr<SimpleCacheLoader> loader,
208 bool success) {
209 if (!success || !loader) {
210 callback.Run(scoped_refptr<CacheStorageCache>());
211 return;
214 callback.Run(loader->CreateCache(cache_name));
217 void CleanUpDeletedCache(const std::string& cache_name,
218 const BoolCallback& callback) override {
219 DCHECK_CURRENTLY_ON(BrowserThread::IO);
221 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
223 base::FilePath cache_path =
224 CreatePersistentCachePath(origin_path_, cache_name);
225 cache_task_runner_->PostTask(
226 FROM_HERE,
227 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, cache_path,
228 callback, base::MessageLoopProxy::current()));
231 static void CleanUpDeleteCacheDirInPool(
232 const base::FilePath& cache_path,
233 const BoolCallback& callback,
234 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
235 bool rv = base::DeleteFile(cache_path, true);
236 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
239 void WriteIndex(const StringVector& cache_names,
240 const BoolCallback& callback) override {
241 DCHECK_CURRENTLY_ON(BrowserThread::IO);
243 // 1. Create the index file as a string. (WriteIndex)
244 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
246 CacheStorageIndex index;
247 index.set_origin(origin_.spec());
249 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
250 CacheStorageIndex::Cache* index_cache = index.add_cache();
251 index_cache->set_name(cache_names[i]);
254 std::string serialized;
255 bool success = index.SerializeToString(&serialized);
256 DCHECK(success);
258 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
259 base::FilePath index_path =
260 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
262 cache_task_runner_->PostTask(
263 FROM_HERE, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
264 tmp_path, index_path, serialized, callback,
265 base::MessageLoopProxy::current()));
268 static void WriteIndexWriteToFileInPool(
269 const base::FilePath& tmp_path,
270 const base::FilePath& index_path,
271 const std::string& data,
272 const BoolCallback& callback,
273 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
274 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
275 if (bytes_written != implicit_cast<int>(data.size())) {
276 base::DeleteFile(tmp_path, /* recursive */ false);
277 original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
280 // Atomically rename the temporary index file to become the real one.
281 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
282 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
285 void LoadIndex(scoped_ptr<std::vector<std::string>> names,
286 const StringVectorCallback& callback) override {
287 DCHECK_CURRENTLY_ON(BrowserThread::IO);
289 // 1. Read the file from disk. (LoadIndexReadFileInPool)
290 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
292 base::FilePath index_path =
293 origin_path_.AppendASCII(CacheStorage::kIndexFileName);
295 cache_task_runner_->PostTask(
296 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
297 index_path, base::Passed(names.Pass()), callback,
298 base::MessageLoopProxy::current()));
301 static void LoadIndexReadFileInPool(
302 const base::FilePath& index_path,
303 scoped_ptr<std::vector<std::string>> names,
304 const StringVectorCallback& callback,
305 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
306 std::string body;
307 base::ReadFileToString(index_path, &body);
309 original_loop->PostTask(
310 FROM_HERE, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
311 base::Passed(names.Pass()), callback, body));
314 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,
315 const StringVectorCallback& callback,
316 const std::string& serialized) {
317 DCHECK_CURRENTLY_ON(BrowserThread::IO);
319 CacheStorageIndex index;
320 if (index.ParseFromString(serialized)) {
321 for (int i = 0, max = index.cache_size(); i < max; ++i) {
322 const CacheStorageIndex::Cache& cache = index.cache(i);
323 names->push_back(cache.name());
327 // TODO(jkarlin): Delete caches that are in the directory and not returned
328 // in LoadIndex.
329 callback.Run(names.Pass());
332 private:
333 ~SimpleCacheLoader() override {}
335 static std::string HexedHash(const std::string& value) {
336 std::string value_hash = base::SHA1HashString(value);
337 std::string valued_hexed_hash = base::StringToLowerASCII(
338 base::HexEncode(value_hash.c_str(), value_hash.length()));
339 return valued_hexed_hash;
342 static base::FilePath CreatePersistentCachePath(
343 const base::FilePath& origin_path,
344 const std::string& cache_name) {
345 return origin_path.AppendASCII(HexedHash(cache_name));
348 const base::FilePath origin_path_;
350 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
353 CacheStorage::CacheStorage(
354 const base::FilePath& path,
355 bool memory_only,
356 base::SequencedTaskRunner* cache_task_runner,
357 net::URLRequestContext* request_context,
358 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
359 base::WeakPtr<storage::BlobStorageContext> blob_context,
360 const GURL& origin)
361 : initialized_(false),
362 initializing_(false),
363 scheduler_(new CacheStorageScheduler()),
364 origin_path_(path),
365 cache_task_runner_(cache_task_runner),
366 memory_only_(memory_only),
367 weak_factory_(this) {
368 if (memory_only)
369 cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
370 request_context, quota_manager_proxy,
371 blob_context, origin));
372 else
373 cache_loader_.reset(new SimpleCacheLoader(
374 origin_path_, cache_task_runner_.get(), request_context,
375 quota_manager_proxy, blob_context, origin));
378 CacheStorage::~CacheStorage() {
381 void CacheStorage::OpenCache(const std::string& cache_name,
382 const CacheAndErrorCallback& callback) {
383 DCHECK_CURRENTLY_ON(BrowserThread::IO);
385 if (!initialized_)
386 LazyInit();
388 CacheAndErrorCallback pending_callback =
389 base::Bind(&CacheStorage::PendingCacheAndErrorCallback,
390 weak_factory_.GetWeakPtr(), callback);
391 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl,
392 weak_factory_.GetWeakPtr(),
393 cache_name, pending_callback));
396 void CacheStorage::HasCache(const std::string& cache_name,
397 const BoolAndErrorCallback& callback) {
398 DCHECK_CURRENTLY_ON(BrowserThread::IO);
400 if (!initialized_)
401 LazyInit();
403 BoolAndErrorCallback pending_callback =
404 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
405 weak_factory_.GetWeakPtr(), callback);
406 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl,
407 weak_factory_.GetWeakPtr(),
408 cache_name, pending_callback));
411 void CacheStorage::DeleteCache(const std::string& cache_name,
412 const BoolAndErrorCallback& callback) {
413 DCHECK_CURRENTLY_ON(BrowserThread::IO);
415 if (!initialized_)
416 LazyInit();
418 BoolAndErrorCallback pending_callback =
419 base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
420 weak_factory_.GetWeakPtr(), callback);
421 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl,
422 weak_factory_.GetWeakPtr(),
423 cache_name, pending_callback));
426 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback& callback) {
427 DCHECK_CURRENTLY_ON(BrowserThread::IO);
429 if (!initialized_)
430 LazyInit();
432 StringsAndErrorCallback pending_callback =
433 base::Bind(&CacheStorage::PendingStringsAndErrorCallback,
434 weak_factory_.GetWeakPtr(), callback);
435 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl,
436 weak_factory_.GetWeakPtr(),
437 pending_callback));
440 void CacheStorage::MatchCache(
441 const std::string& cache_name,
442 scoped_ptr<ServiceWorkerFetchRequest> request,
443 const CacheStorageCache::ResponseCallback& callback) {
444 DCHECK_CURRENTLY_ON(BrowserThread::IO);
446 if (!initialized_)
447 LazyInit();
449 CacheStorageCache::ResponseCallback pending_callback =
450 base::Bind(&CacheStorage::PendingResponseCallback,
451 weak_factory_.GetWeakPtr(), callback);
452 scheduler_->ScheduleOperation(
453 base::Bind(&CacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
454 cache_name, base::Passed(request.Pass()), pending_callback));
457 void CacheStorage::MatchAllCaches(
458 scoped_ptr<ServiceWorkerFetchRequest> request,
459 const CacheStorageCache::ResponseCallback& callback) {
460 DCHECK_CURRENTLY_ON(BrowserThread::IO);
462 if (!initialized_)
463 LazyInit();
465 CacheStorageCache::ResponseCallback pending_callback =
466 base::Bind(&CacheStorage::PendingResponseCallback,
467 weak_factory_.GetWeakPtr(), callback);
468 scheduler_->ScheduleOperation(
469 base::Bind(&CacheStorage::MatchAllCachesImpl, weak_factory_.GetWeakPtr(),
470 base::Passed(request.Pass()), pending_callback));
473 void CacheStorage::CloseAllCaches(const base::Closure& callback) {
474 DCHECK_CURRENTLY_ON(BrowserThread::IO);
476 if (!initialized_) {
477 callback.Run();
478 return;
481 base::Closure pending_callback = base::Bind(
482 &CacheStorage::PendingClosure, weak_factory_.GetWeakPtr(), callback);
483 scheduler_->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl,
484 weak_factory_.GetWeakPtr(),
485 pending_callback));
488 int64 CacheStorage::MemoryBackedSize() const {
489 DCHECK_CURRENTLY_ON(BrowserThread::IO);
491 if (!initialized_ || !memory_only_)
492 return 0;
494 int64 sum = 0;
495 for (auto& key_value : cache_map_) {
496 if (key_value.second)
497 sum += key_value.second->MemoryBackedSize();
499 return sum;
502 void CacheStorage::StartAsyncOperationForTesting() {
503 scheduler_->ScheduleOperation(base::Bind(&base::DoNothing));
506 void CacheStorage::CompleteAsyncOperationForTesting() {
507 scheduler_->CompleteOperationAndRunNext();
510 // Init is run lazily so that it is called on the proper MessageLoop.
511 void CacheStorage::LazyInit() {
512 DCHECK_CURRENTLY_ON(BrowserThread::IO);
513 DCHECK(!initialized_);
515 if (initializing_)
516 return;
518 DCHECK(!scheduler_->ScheduledOperations());
520 initializing_ = true;
521 scheduler_->ScheduleOperation(
522 base::Bind(&CacheStorage::LazyInitImpl, weak_factory_.GetWeakPtr()));
525 void CacheStorage::LazyInitImpl() {
526 DCHECK_CURRENTLY_ON(BrowserThread::IO);
527 DCHECK(!initialized_);
528 DCHECK(initializing_);
530 // 1. Get the list of cache names (async call)
531 // 2. For each cache name, load the cache (async call)
532 // 3. Once each load is complete, update the map variables.
533 // 4. Call the list of waiting callbacks.
535 scoped_ptr<std::vector<std::string>> indexed_cache_names(
536 new std::vector<std::string>());
538 cache_loader_->LoadIndex(indexed_cache_names.Pass(),
539 base::Bind(&CacheStorage::LazyInitDidLoadIndex,
540 weak_factory_.GetWeakPtr()));
543 void CacheStorage::LazyInitDidLoadIndex(
544 scoped_ptr<std::vector<std::string>> indexed_cache_names) {
545 DCHECK_CURRENTLY_ON(BrowserThread::IO);
547 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
548 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
549 base::WeakPtr<CacheStorageCache>()));
550 ordered_cache_names_.push_back(indexed_cache_names->at(i));
553 initializing_ = false;
554 initialized_ = true;
556 scheduler_->CompleteOperationAndRunNext();
559 void CacheStorage::OpenCacheImpl(const std::string& cache_name,
560 const CacheAndErrorCallback& callback) {
561 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
562 if (cache.get()) {
563 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
564 return;
567 cache_loader_->CreateCache(
568 cache_name, base::Bind(&CacheStorage::CreateCacheDidCreateCache,
569 weak_factory_.GetWeakPtr(), cache_name, callback));
572 void CacheStorage::CreateCacheDidCreateCache(
573 const std::string& cache_name,
574 const CacheAndErrorCallback& callback,
575 const scoped_refptr<CacheStorageCache>& cache) {
576 DCHECK_CURRENTLY_ON(BrowserThread::IO);
578 if (!cache.get()) {
579 callback.Run(scoped_refptr<CacheStorageCache>(),
580 CACHE_STORAGE_ERROR_CLOSING);
581 return;
584 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
585 cache != nullptr);
587 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
588 ordered_cache_names_.push_back(cache_name);
590 cache_loader_->WriteIndex(
591 ordered_cache_names_,
592 base::Bind(&CacheStorage::CreateCacheDidWriteIndex,
593 weak_factory_.GetWeakPtr(), callback, cache));
596 void CacheStorage::CreateCacheDidWriteIndex(
597 const CacheAndErrorCallback& callback,
598 const scoped_refptr<CacheStorageCache>& cache,
599 bool success) {
600 DCHECK_CURRENTLY_ON(BrowserThread::IO);
601 DCHECK(cache.get());
603 // TODO(jkarlin): Handle !success.
605 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
608 void CacheStorage::HasCacheImpl(const std::string& cache_name,
609 const BoolAndErrorCallback& callback) {
610 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
612 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
615 void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
616 const BoolAndErrorCallback& callback) {
617 CacheMap::iterator it = cache_map_.find(cache_name);
618 if (it == cache_map_.end()) {
619 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
620 return;
623 base::WeakPtr<CacheStorageCache> cache = it->second;
624 cache_map_.erase(it);
626 // Delete the name from ordered_cache_names_.
627 StringVector::iterator iter = std::find(
628 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
629 DCHECK(iter != ordered_cache_names_.end());
630 ordered_cache_names_.erase(iter);
632 base::Closure closure =
633 base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(),
634 cache_name, callback, ordered_cache_names_,
635 make_scoped_refptr(cache.get()));
637 if (cache) {
638 cache->Close(closure);
639 return;
642 closure.Run();
645 void CacheStorage::DeleteCacheDidClose(
646 const std::string& cache_name,
647 const BoolAndErrorCallback& callback,
648 const StringVector& ordered_cache_names,
649 const scoped_refptr<CacheStorageCache>& cache /* might be null */) {
650 cache_loader_->WriteIndex(
651 ordered_cache_names,
652 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex,
653 weak_factory_.GetWeakPtr(), cache_name, callback));
656 void CacheStorage::DeleteCacheDidWriteIndex(
657 const std::string& cache_name,
658 const BoolAndErrorCallback& callback,
659 bool success) {
660 DCHECK_CURRENTLY_ON(BrowserThread::IO);
662 cache_loader_->CleanUpDeletedCache(
663 cache_name, base::Bind(&CacheStorage::DeleteCacheDidCleanUp,
664 weak_factory_.GetWeakPtr(), callback));
667 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback& callback,
668 bool success) {
669 DCHECK_CURRENTLY_ON(BrowserThread::IO);
671 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
674 void CacheStorage::EnumerateCachesImpl(
675 const StringsAndErrorCallback& callback) {
676 callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
679 void CacheStorage::MatchCacheImpl(
680 const std::string& cache_name,
681 scoped_ptr<ServiceWorkerFetchRequest> request,
682 const CacheStorageCache::ResponseCallback& callback) {
683 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
685 if (!cache.get()) {
686 callback.Run(CacheStorageCache::ERROR_TYPE_NOT_FOUND,
687 scoped_ptr<ServiceWorkerResponse>(),
688 scoped_ptr<storage::BlobDataHandle>());
689 return;
692 // Pass the cache along to the callback to keep the cache open until match is
693 // done.
694 cache->Match(request.Pass(),
695 base::Bind(&CacheStorage::MatchCacheDidMatch,
696 weak_factory_.GetWeakPtr(), cache, callback));
699 void CacheStorage::MatchCacheDidMatch(
700 const scoped_refptr<CacheStorageCache>& cache,
701 const CacheStorageCache::ResponseCallback& callback,
702 CacheStorageCache::ErrorType error,
703 scoped_ptr<ServiceWorkerResponse> response,
704 scoped_ptr<storage::BlobDataHandle> handle) {
705 callback.Run(error, response.Pass(), handle.Pass());
708 void CacheStorage::MatchAllCachesImpl(
709 scoped_ptr<ServiceWorkerFetchRequest> request,
710 const CacheStorageCache::ResponseCallback& callback) {
711 scoped_ptr<CacheStorageCache::ResponseCallback> callback_copy(
712 new CacheStorageCache::ResponseCallback(callback));
714 CacheStorageCache::ResponseCallback* callback_ptr = callback_copy.get();
715 base::Closure barrier_closure =
716 base::BarrierClosure(ordered_cache_names_.size(),
717 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll,
718 weak_factory_.GetWeakPtr(),
719 base::Passed(callback_copy.Pass())));
721 for (const std::string& cache_name : ordered_cache_names_) {
722 scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
723 DCHECK(cache.get());
725 cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
726 base::Bind(&CacheStorage::MatchAllCachesDidMatch,
727 weak_factory_.GetWeakPtr(), cache, barrier_closure,
728 callback_ptr));
732 void CacheStorage::MatchAllCachesDidMatch(
733 scoped_refptr<CacheStorageCache> cache,
734 const base::Closure& barrier_closure,
735 CacheStorageCache::ResponseCallback* callback,
736 CacheStorageCache::ErrorType error,
737 scoped_ptr<ServiceWorkerResponse> response,
738 scoped_ptr<storage::BlobDataHandle> handle) {
739 if (callback->is_null() || error == CacheStorageCache::ERROR_TYPE_NOT_FOUND) {
740 barrier_closure.Run();
741 return;
743 callback->Run(error, response.Pass(), handle.Pass());
744 callback->Reset(); // Only call the callback once.
746 barrier_closure.Run();
749 void CacheStorage::MatchAllCachesDidMatchAll(
750 scoped_ptr<CacheStorageCache::ResponseCallback> callback) {
751 if (!callback->is_null()) {
752 callback->Run(CacheStorageCache::ERROR_TYPE_NOT_FOUND,
753 scoped_ptr<ServiceWorkerResponse>(),
754 scoped_ptr<storage::BlobDataHandle>());
758 scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
759 const std::string& cache_name) {
760 DCHECK_CURRENTLY_ON(BrowserThread::IO);
761 DCHECK(initialized_);
763 CacheMap::iterator map_iter = cache_map_.find(cache_name);
764 if (map_iter == cache_map_.end())
765 return scoped_refptr<CacheStorageCache>();
767 base::WeakPtr<CacheStorageCache> cache = map_iter->second;
769 if (!cache) {
770 scoped_refptr<CacheStorageCache> new_cache =
771 cache_loader_->CreateCache(cache_name);
772 map_iter->second = new_cache->AsWeakPtr();
773 return new_cache;
776 return make_scoped_refptr(cache.get());
779 void CacheStorage::CloseAllCachesImpl(const base::Closure& callback) {
780 int live_cache_count = 0;
781 for (const auto& key_value : cache_map_) {
782 if (key_value.second)
783 live_cache_count += 1;
786 if (live_cache_count == 0) {
787 callback.Run();
788 return;
791 // The closure might modify this object so delay calling it until after
792 // iterating through cache_map_ by adding one to the barrier.
793 base::Closure barrier_closure =
794 base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
796 for (auto& key_value : cache_map_) {
797 if (key_value.second) {
798 key_value.second->Close(base::Bind(
799 CloseAllCachesDidCloseCache,
800 make_scoped_refptr(key_value.second.get()), barrier_closure));
804 barrier_closure.Run();
807 void CacheStorage::PendingClosure(const base::Closure& callback) {
808 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
810 callback.Run();
811 if (cache_storage)
812 scheduler_->CompleteOperationAndRunNext();
815 void CacheStorage::PendingBoolAndErrorCallback(
816 const BoolAndErrorCallback& callback,
817 bool found,
818 CacheStorageError error) {
819 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
821 callback.Run(found, error);
822 if (cache_storage)
823 scheduler_->CompleteOperationAndRunNext();
826 void CacheStorage::PendingCacheAndErrorCallback(
827 const CacheAndErrorCallback& callback,
828 const scoped_refptr<CacheStorageCache>& cache,
829 CacheStorageError error) {
830 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
832 callback.Run(cache, error);
833 if (cache_storage)
834 scheduler_->CompleteOperationAndRunNext();
837 void CacheStorage::PendingStringsAndErrorCallback(
838 const StringsAndErrorCallback& callback,
839 const StringVector& strings,
840 CacheStorageError error) {
841 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
843 callback.Run(strings, error);
844 if (cache_storage)
845 scheduler_->CompleteOperationAndRunNext();
848 void CacheStorage::PendingResponseCallback(
849 const CacheStorageCache::ResponseCallback& callback,
850 CacheStorageCache::ErrorType error,
851 scoped_ptr<ServiceWorkerResponse> response,
852 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
853 base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
855 callback.Run(error, response.Pass(), blob_data_handle.Pass());
856 if (cache_storage)
857 scheduler_->CompleteOperationAndRunNext();
860 } // namespace content