ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_cache_storage.cc
blobd5fb07c6789be43dc86f66bce251e0ed19fa0b81
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/sha1.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "content/browser/service_worker/service_worker_cache.h"
18 #include "content/browser/service_worker/service_worker_cache.pb.h"
19 #include "content/browser/service_worker/service_worker_cache_scheduler.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "net/base/directory_lister.h"
22 #include "net/base/net_errors.h"
23 #include "storage/browser/blob/blob_storage_context.h"
24 #include "storage/browser/quota/quota_manager_proxy.h"
26 namespace content {
28 namespace {
30 void CloseAllCachesDidCloseCache(const scoped_refptr<ServiceWorkerCache>& cache,
31 const base::Closure& barrier_closure) {
32 barrier_closure.Run();
35 } // namespace
37 const char ServiceWorkerCacheStorage::kIndexFileName[] = "index.txt";
39 // Handles the loading and clean up of ServiceWorkerCache objects. The
40 // callback of every public method is guaranteed to be called.
41 class ServiceWorkerCacheStorage::CacheLoader {
42 public:
43 typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)>
44 CacheCallback;
45 typedef base::Callback<void(bool)> BoolCallback;
46 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
47 StringVectorCallback;
49 CacheLoader(
50 base::SequencedTaskRunner* cache_task_runner,
51 net::URLRequestContext* request_context,
52 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
53 base::WeakPtr<storage::BlobStorageContext> blob_context,
54 const GURL& origin)
55 : cache_task_runner_(cache_task_runner),
56 request_context_(request_context),
57 quota_manager_proxy_(quota_manager_proxy),
58 blob_context_(blob_context),
59 origin_(origin) {
60 DCHECK(!origin_.is_empty());
63 virtual ~CacheLoader() {}
65 // Creates a ServiceWorkerCache with the given name. It does not attempt to
66 // load the backend, that happens lazily when the cache is used.
67 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
68 const std::string& cache_name) = 0;
70 // Deletes any pre-existing cache of the same name and then loads it.
71 virtual void CreateCache(const std::string& cache_name,
72 const CacheCallback& callback) = 0;
74 // After the backend has been deleted, do any extra house keeping such as
75 // removing the cache's directory.
76 virtual void CleanUpDeletedCache(const std::string& key,
77 const BoolCallback& callback) = 0;
79 // Writes the cache names (and sizes) to disk if applicable.
80 virtual void WriteIndex(const StringVector& cache_names,
81 const BoolCallback& callback) = 0;
83 // Loads the cache names from disk if applicable.
84 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
85 const StringVectorCallback& callback) = 0;
87 protected:
88 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
89 net::URLRequestContext* request_context_;
90 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
91 base::WeakPtr<storage::BlobStorageContext> blob_context_;
92 GURL origin_;
95 // Creates memory-only ServiceWorkerCaches. Because these caches have no
96 // persistent storage it is not safe to free them from memory if they might be
97 // used again. Therefore this class holds a reference to each cache until the
98 // cache is deleted.
99 class ServiceWorkerCacheStorage::MemoryLoader
100 : public ServiceWorkerCacheStorage::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<ServiceWorkerCache> CreateServiceWorkerCache(
115 const std::string& cache_name) override {
116 return ServiceWorkerCache::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<ServiceWorkerCache> cache =
123 CreateServiceWorkerCache(cache_name);
124 cache_refs_.insert(std::make_pair(cache_name, cache));
125 callback.Run(cache);
128 void CleanUpDeletedCache(const std::string& cache_name,
129 const BoolCallback& callback) override {
130 CacheRefMap::iterator it = cache_refs_.find(cache_name);
131 DCHECK(it != cache_refs_.end());
132 cache_refs_.erase(it);
133 callback.Run(true);
136 void WriteIndex(const StringVector& cache_names,
137 const BoolCallback& callback) override {
138 callback.Run(false);
141 void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
142 const StringVectorCallback& callback) override {
143 callback.Run(cache_names.Pass());
146 private:
147 typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap;
148 ~MemoryLoader() override {}
150 // Keep a reference to each cache to ensure that it's not freed before the
151 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
152 // freed.
153 CacheRefMap cache_refs_;
156 class ServiceWorkerCacheStorage::SimpleCacheLoader
157 : public ServiceWorkerCacheStorage::CacheLoader {
158 public:
159 SimpleCacheLoader(
160 const base::FilePath& origin_path,
161 base::SequencedTaskRunner* cache_task_runner,
162 net::URLRequestContext* request_context,
163 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
164 base::WeakPtr<storage::BlobStorageContext> blob_context,
165 const GURL& origin)
166 : CacheLoader(cache_task_runner,
167 request_context,
168 quota_manager_proxy,
169 blob_context,
170 origin),
171 origin_path_(origin_path),
172 weak_ptr_factory_(this) {}
174 scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
175 const std::string& cache_name) override {
176 DCHECK_CURRENTLY_ON(BrowserThread::IO);
178 return ServiceWorkerCache::CreatePersistentCache(
179 origin_,
180 CreatePersistentCachePath(origin_path_, cache_name),
181 request_context_,
182 quota_manager_proxy_,
183 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(),
199 FROM_HERE,
200 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
201 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir,
202 cache_name,
203 callback,
204 weak_ptr_factory_.GetWeakPtr()));
207 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
208 if (base::PathExists(cache_path))
209 base::DeleteFile(cache_path, /* recursive */ true);
210 return base::CreateDirectory(cache_path);
213 static void CreateCachePreppedDir(const std::string& cache_name,
214 const CacheCallback& callback,
215 base::WeakPtr<SimpleCacheLoader> loader,
216 bool success) {
217 if (!success || !loader) {
218 callback.Run(scoped_refptr<ServiceWorkerCache>());
219 return;
222 callback.Run(loader->CreateServiceWorkerCache(cache_name));
225 void CleanUpDeletedCache(const std::string& cache_name,
226 const BoolCallback& callback) override {
227 DCHECK_CURRENTLY_ON(BrowserThread::IO);
229 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
231 base::FilePath cache_path =
232 CreatePersistentCachePath(origin_path_, cache_name);
233 cache_task_runner_->PostTask(
234 FROM_HERE,
235 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
236 cache_path,
237 callback,
238 base::MessageLoopProxy::current()));
241 static void CleanUpDeleteCacheDirInPool(
242 const base::FilePath& cache_path,
243 const BoolCallback& callback,
244 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
245 bool rv = base::DeleteFile(cache_path, true);
246 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
249 void WriteIndex(const StringVector& cache_names,
250 const BoolCallback& callback) override {
251 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 // 1. Create the index file as a string. (WriteIndex)
254 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
256 ServiceWorkerCacheStorageIndex index;
257 index.set_origin(origin_.spec());
259 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
260 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
261 index_cache->set_name(cache_names[i]);
264 std::string serialized;
265 bool success = index.SerializeToString(&serialized);
266 DCHECK(success);
268 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
269 base::FilePath index_path =
270 origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
272 cache_task_runner_->PostTask(
273 FROM_HERE,
274 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
275 tmp_path,
276 index_path,
277 serialized,
278 callback,
279 base::MessageLoopProxy::current()));
282 static void WriteIndexWriteToFileInPool(
283 const base::FilePath& tmp_path,
284 const base::FilePath& index_path,
285 const std::string& data,
286 const BoolCallback& callback,
287 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
288 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
289 if (bytes_written != implicit_cast<int>(data.size())) {
290 base::DeleteFile(tmp_path, /* recursive */ false);
291 original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
294 // Atomically rename the temporary index file to become the real one.
295 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
296 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
299 void LoadIndex(scoped_ptr<std::vector<std::string>> names,
300 const StringVectorCallback& callback) override {
301 DCHECK_CURRENTLY_ON(BrowserThread::IO);
303 // 1. Read the file from disk. (LoadIndexReadFileInPool)
304 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
306 base::FilePath index_path =
307 origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
309 cache_task_runner_->PostTask(
310 FROM_HERE,
311 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
312 index_path,
313 base::Passed(names.Pass()),
314 callback,
315 base::MessageLoopProxy::current()));
318 static void LoadIndexReadFileInPool(
319 const base::FilePath& index_path,
320 scoped_ptr<std::vector<std::string> > names,
321 const StringVectorCallback& callback,
322 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
323 std::string body;
324 base::ReadFileToString(index_path, &body);
326 original_loop->PostTask(FROM_HERE,
327 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
328 base::Passed(names.Pass()),
329 callback,
330 body));
333 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
334 const StringVectorCallback& callback,
335 const std::string& serialized) {
336 DCHECK_CURRENTLY_ON(BrowserThread::IO);
338 ServiceWorkerCacheStorageIndex index;
339 if (index.ParseFromString(serialized)) {
340 for (int i = 0, max = index.cache_size(); i < max; ++i) {
341 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
342 names->push_back(cache.name());
346 // TODO(jkarlin): Delete caches that are in the directory and not returned
347 // in LoadIndex.
348 callback.Run(names.Pass());
351 private:
352 ~SimpleCacheLoader() override {}
354 static std::string HexedHash(const std::string& value) {
355 std::string value_hash = base::SHA1HashString(value);
356 std::string valued_hexed_hash = base::StringToLowerASCII(
357 base::HexEncode(value_hash.c_str(), value_hash.length()));
358 return valued_hexed_hash;
361 static base::FilePath CreatePersistentCachePath(
362 const base::FilePath& origin_path,
363 const std::string& cache_name) {
364 return origin_path.AppendASCII(HexedHash(cache_name));
367 const base::FilePath origin_path_;
369 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
372 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
373 const base::FilePath& path,
374 bool memory_only,
375 base::SequencedTaskRunner* cache_task_runner,
376 net::URLRequestContext* request_context,
377 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
378 base::WeakPtr<storage::BlobStorageContext> blob_context,
379 const GURL& origin)
380 : initialized_(false),
381 initializing_(false),
382 scheduler_(new ServiceWorkerCacheScheduler()),
383 origin_path_(path),
384 cache_task_runner_(cache_task_runner),
385 memory_only_(memory_only),
386 weak_factory_(this) {
387 if (memory_only)
388 cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
389 request_context,
390 quota_manager_proxy,
391 blob_context,
392 origin));
393 else
394 cache_loader_.reset(new SimpleCacheLoader(origin_path_,
395 cache_task_runner_.get(),
396 request_context,
397 quota_manager_proxy,
398 blob_context,
399 origin));
402 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
405 void ServiceWorkerCacheStorage::OpenCache(
406 const std::string& cache_name,
407 const CacheAndErrorCallback& callback) {
408 DCHECK_CURRENTLY_ON(BrowserThread::IO);
410 if (!initialized_)
411 LazyInit();
413 CacheAndErrorCallback pending_callback =
414 base::Bind(&ServiceWorkerCacheStorage::PendingCacheAndErrorCallback,
415 weak_factory_.GetWeakPtr(), callback);
416 scheduler_->ScheduleOperation(
417 base::Bind(&ServiceWorkerCacheStorage::OpenCacheImpl,
418 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
421 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
422 const BoolAndErrorCallback& callback) {
423 DCHECK_CURRENTLY_ON(BrowserThread::IO);
425 if (!initialized_)
426 LazyInit();
428 BoolAndErrorCallback pending_callback =
429 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback,
430 weak_factory_.GetWeakPtr(), callback);
431 scheduler_->ScheduleOperation(
432 base::Bind(&ServiceWorkerCacheStorage::HasCacheImpl,
433 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
436 void ServiceWorkerCacheStorage::DeleteCache(
437 const std::string& cache_name,
438 const BoolAndErrorCallback& callback) {
439 DCHECK_CURRENTLY_ON(BrowserThread::IO);
441 if (!initialized_)
442 LazyInit();
444 BoolAndErrorCallback pending_callback =
445 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback,
446 weak_factory_.GetWeakPtr(), callback);
447 scheduler_->ScheduleOperation(
448 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheImpl,
449 weak_factory_.GetWeakPtr(), cache_name, pending_callback));
452 void ServiceWorkerCacheStorage::EnumerateCaches(
453 const StringsAndErrorCallback& callback) {
454 DCHECK_CURRENTLY_ON(BrowserThread::IO);
456 if (!initialized_)
457 LazyInit();
459 StringsAndErrorCallback pending_callback =
460 base::Bind(&ServiceWorkerCacheStorage::PendingStringsAndErrorCallback,
461 weak_factory_.GetWeakPtr(), callback);
462 scheduler_->ScheduleOperation(
463 base::Bind(&ServiceWorkerCacheStorage::EnumerateCachesImpl,
464 weak_factory_.GetWeakPtr(), pending_callback));
467 void ServiceWorkerCacheStorage::MatchCache(
468 const std::string& cache_name,
469 scoped_ptr<ServiceWorkerFetchRequest> request,
470 const ServiceWorkerCache::ResponseCallback& callback) {
471 DCHECK_CURRENTLY_ON(BrowserThread::IO);
473 if (!initialized_)
474 LazyInit();
476 ServiceWorkerCache::ResponseCallback pending_callback =
477 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback,
478 weak_factory_.GetWeakPtr(), callback);
479 scheduler_->ScheduleOperation(base::Bind(
480 &ServiceWorkerCacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
481 cache_name, base::Passed(request.Pass()), pending_callback));
484 void ServiceWorkerCacheStorage::MatchAllCaches(
485 scoped_ptr<ServiceWorkerFetchRequest> request,
486 const ServiceWorkerCache::ResponseCallback& callback) {
487 DCHECK_CURRENTLY_ON(BrowserThread::IO);
489 if (!initialized_)
490 LazyInit();
492 ServiceWorkerCache::ResponseCallback pending_callback =
493 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback,
494 weak_factory_.GetWeakPtr(), callback);
495 scheduler_->ScheduleOperation(
496 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesImpl,
497 weak_factory_.GetWeakPtr(), base::Passed(request.Pass()),
498 pending_callback));
501 void ServiceWorkerCacheStorage::CloseAllCaches(const base::Closure& callback) {
502 DCHECK_CURRENTLY_ON(BrowserThread::IO);
504 if (!initialized_) {
505 callback.Run();
506 return;
509 base::Closure pending_callback =
510 base::Bind(&ServiceWorkerCacheStorage::PendingClosure,
511 weak_factory_.GetWeakPtr(), callback);
512 scheduler_->ScheduleOperation(
513 base::Bind(&ServiceWorkerCacheStorage::CloseAllCachesImpl,
514 weak_factory_.GetWeakPtr(), pending_callback));
517 int64 ServiceWorkerCacheStorage::MemoryBackedSize() const {
518 DCHECK_CURRENTLY_ON(BrowserThread::IO);
520 if (!initialized_ || !memory_only_)
521 return 0;
523 int64 sum = 0;
524 for (auto& key_value : cache_map_) {
525 if (key_value.second)
526 sum += key_value.second->MemoryBackedSize();
528 return sum;
531 void ServiceWorkerCacheStorage::StartAsyncOperationForTesting() {
532 scheduler_->ScheduleOperation(base::Bind(&base::DoNothing));
535 void ServiceWorkerCacheStorage::CompleteAsyncOperationForTesting() {
536 scheduler_->CompleteOperationAndRunNext();
539 // Init is run lazily so that it is called on the proper MessageLoop.
540 void ServiceWorkerCacheStorage::LazyInit() {
541 DCHECK_CURRENTLY_ON(BrowserThread::IO);
542 DCHECK(!initialized_);
544 if (initializing_)
545 return;
547 DCHECK(scheduler_->Empty());
549 initializing_ = true;
550 scheduler_->ScheduleOperation(base::Bind(
551 &ServiceWorkerCacheStorage::LazyInitImpl, weak_factory_.GetWeakPtr()));
554 void ServiceWorkerCacheStorage::LazyInitImpl() {
555 DCHECK_CURRENTLY_ON(BrowserThread::IO);
556 DCHECK(!initialized_);
557 DCHECK(initializing_);
559 // 1. Get the list of cache names (async call)
560 // 2. For each cache name, load the cache (async call)
561 // 3. Once each load is complete, update the map variables.
562 // 4. Call the list of waiting callbacks.
564 scoped_ptr<std::vector<std::string> > indexed_cache_names(
565 new std::vector<std::string>());
567 cache_loader_->LoadIndex(
568 indexed_cache_names.Pass(),
569 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex,
570 weak_factory_.GetWeakPtr()));
573 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
574 scoped_ptr<std::vector<std::string> > indexed_cache_names) {
575 DCHECK_CURRENTLY_ON(BrowserThread::IO);
577 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
578 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
579 base::WeakPtr<ServiceWorkerCache>()));
580 ordered_cache_names_.push_back(indexed_cache_names->at(i));
583 initializing_ = false;
584 initialized_ = true;
586 scheduler_->CompleteOperationAndRunNext();
589 void ServiceWorkerCacheStorage::OpenCacheImpl(
590 const std::string& cache_name,
591 const CacheAndErrorCallback& callback) {
592 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
593 if (cache.get()) {
594 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
595 return;
598 cache_loader_->CreateCache(
599 cache_name,
600 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache,
601 weak_factory_.GetWeakPtr(), cache_name, callback));
604 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
605 const std::string& cache_name,
606 const CacheAndErrorCallback& callback,
607 const scoped_refptr<ServiceWorkerCache>& cache) {
608 DCHECK_CURRENTLY_ON(BrowserThread::IO);
610 if (!cache.get()) {
611 callback.Run(scoped_refptr<ServiceWorkerCache>(),
612 CACHE_STORAGE_ERROR_CLOSING);
613 return;
616 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
617 ordered_cache_names_.push_back(cache_name);
619 cache_loader_->WriteIndex(
620 ordered_cache_names_,
621 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
622 weak_factory_.GetWeakPtr(),
623 callback,
624 cache));
627 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
628 const CacheAndErrorCallback& callback,
629 const scoped_refptr<ServiceWorkerCache>& cache,
630 bool success) {
631 DCHECK_CURRENTLY_ON(BrowserThread::IO);
632 DCHECK(cache.get());
634 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
637 void ServiceWorkerCacheStorage::HasCacheImpl(
638 const std::string& cache_name,
639 const BoolAndErrorCallback& callback) {
640 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
642 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
645 void ServiceWorkerCacheStorage::DeleteCacheImpl(
646 const std::string& cache_name,
647 const BoolAndErrorCallback& callback) {
648 CacheMap::iterator it = cache_map_.find(cache_name);
649 if (it == cache_map_.end()) {
650 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
651 return;
654 base::WeakPtr<ServiceWorkerCache> cache = it->second;
655 cache_map_.erase(it);
657 // Delete the name from ordered_cache_names_.
658 StringVector::iterator iter = std::find(
659 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
660 DCHECK(iter != ordered_cache_names_.end());
661 ordered_cache_names_.erase(iter);
663 base::Closure closure =
664 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidClose,
665 weak_factory_.GetWeakPtr(), cache_name, callback,
666 ordered_cache_names_, make_scoped_refptr(cache.get()));
668 if (cache) {
669 cache->Close(closure);
670 return;
673 closure.Run();
676 void ServiceWorkerCacheStorage::DeleteCacheDidClose(
677 const std::string& cache_name,
678 const BoolAndErrorCallback& callback,
679 const StringVector& ordered_cache_names,
680 const scoped_refptr<ServiceWorkerCache>& cache /* might be null */) {
681 cache_loader_->WriteIndex(
682 ordered_cache_names,
683 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
684 weak_factory_.GetWeakPtr(), cache_name, callback));
687 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
688 const std::string& cache_name,
689 const BoolAndErrorCallback& callback,
690 bool success) {
691 DCHECK_CURRENTLY_ON(BrowserThread::IO);
693 cache_loader_->CleanUpDeletedCache(
694 cache_name,
695 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp,
696 weak_factory_.GetWeakPtr(),
697 callback));
700 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
701 const BoolAndErrorCallback& callback,
702 bool success) {
703 DCHECK_CURRENTLY_ON(BrowserThread::IO);
705 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
708 void ServiceWorkerCacheStorage::EnumerateCachesImpl(
709 const StringsAndErrorCallback& callback) {
710 callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
713 void ServiceWorkerCacheStorage::MatchCacheImpl(
714 const std::string& cache_name,
715 scoped_ptr<ServiceWorkerFetchRequest> request,
716 const ServiceWorkerCache::ResponseCallback& callback) {
717 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
719 if (!cache.get()) {
720 callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
721 scoped_ptr<ServiceWorkerResponse>(),
722 scoped_ptr<storage::BlobDataHandle>());
723 return;
726 // Pass the cache along to the callback to keep the cache open until match is
727 // done.
728 cache->Match(request.Pass(),
729 base::Bind(&ServiceWorkerCacheStorage::MatchCacheDidMatch,
730 weak_factory_.GetWeakPtr(), cache, callback));
733 void ServiceWorkerCacheStorage::MatchCacheDidMatch(
734 const scoped_refptr<ServiceWorkerCache>& cache,
735 const ServiceWorkerCache::ResponseCallback& callback,
736 ServiceWorkerCache::ErrorType error,
737 scoped_ptr<ServiceWorkerResponse> response,
738 scoped_ptr<storage::BlobDataHandle> handle) {
739 callback.Run(error, response.Pass(), handle.Pass());
742 void ServiceWorkerCacheStorage::MatchAllCachesImpl(
743 scoped_ptr<ServiceWorkerFetchRequest> request,
744 const ServiceWorkerCache::ResponseCallback& callback) {
745 scoped_ptr<ServiceWorkerCache::ResponseCallback> callback_copy(
746 new ServiceWorkerCache::ResponseCallback(callback));
748 ServiceWorkerCache::ResponseCallback* callback_ptr = callback_copy.get();
749 base::Closure barrier_closure = base::BarrierClosure(
750 ordered_cache_names_.size(),
751 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll,
752 weak_factory_.GetWeakPtr(),
753 base::Passed(callback_copy.Pass())));
755 for (const std::string& cache_name : ordered_cache_names_) {
756 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
757 DCHECK(cache.get());
759 cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
760 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatch,
761 weak_factory_.GetWeakPtr(), cache, barrier_closure,
762 callback_ptr));
766 void ServiceWorkerCacheStorage::MatchAllCachesDidMatch(
767 scoped_refptr<ServiceWorkerCache> cache,
768 const base::Closure& barrier_closure,
769 ServiceWorkerCache::ResponseCallback* callback,
770 ServiceWorkerCache::ErrorType error,
771 scoped_ptr<ServiceWorkerResponse> response,
772 scoped_ptr<storage::BlobDataHandle> handle) {
773 if (callback->is_null() || error == ServiceWorkerCache::ErrorTypeNotFound) {
774 barrier_closure.Run();
775 return;
777 callback->Run(error, response.Pass(), handle.Pass());
778 callback->Reset(); // Only call the callback once.
780 barrier_closure.Run();
783 void ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll(
784 scoped_ptr<ServiceWorkerCache::ResponseCallback> callback) {
785 if (!callback->is_null()) {
786 callback->Run(ServiceWorkerCache::ErrorTypeNotFound,
787 scoped_ptr<ServiceWorkerResponse>(),
788 scoped_ptr<storage::BlobDataHandle>());
792 scoped_refptr<ServiceWorkerCache> ServiceWorkerCacheStorage::GetLoadedCache(
793 const std::string& cache_name) {
794 DCHECK_CURRENTLY_ON(BrowserThread::IO);
795 DCHECK(initialized_);
797 CacheMap::iterator map_iter = cache_map_.find(cache_name);
798 if (map_iter == cache_map_.end())
799 return scoped_refptr<ServiceWorkerCache>();
801 base::WeakPtr<ServiceWorkerCache> cache = map_iter->second;
803 if (!cache) {
804 scoped_refptr<ServiceWorkerCache> new_cache =
805 cache_loader_->CreateServiceWorkerCache(cache_name);
806 map_iter->second = new_cache->AsWeakPtr();
807 return new_cache;
810 return make_scoped_refptr(cache.get());
813 void ServiceWorkerCacheStorage::CloseAllCachesImpl(
814 const base::Closure& callback) {
815 int live_cache_count = 0;
816 for (const auto& key_value : cache_map_) {
817 if (key_value.second)
818 live_cache_count += 1;
821 if (live_cache_count == 0) {
822 callback.Run();
823 return;
826 // The closure might modify this object so delay calling it until after
827 // iterating through cache_map_ by adding one to the barrier.
828 base::Closure barrier_closure =
829 base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
831 for (auto& key_value : cache_map_) {
832 if (key_value.second) {
833 key_value.second->Close(base::Bind(
834 CloseAllCachesDidCloseCache,
835 make_scoped_refptr(key_value.second.get()), barrier_closure));
839 barrier_closure.Run();
842 void ServiceWorkerCacheStorage::PendingClosure(const base::Closure& callback) {
843 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
844 weak_factory_.GetWeakPtr();
846 callback.Run();
847 if (cache_storage)
848 scheduler_->CompleteOperationAndRunNext();
851 void ServiceWorkerCacheStorage::PendingBoolAndErrorCallback(
852 const BoolAndErrorCallback& callback,
853 bool found,
854 CacheStorageError error) {
855 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
856 weak_factory_.GetWeakPtr();
858 callback.Run(found, error);
859 if (cache_storage)
860 scheduler_->CompleteOperationAndRunNext();
863 void ServiceWorkerCacheStorage::PendingCacheAndErrorCallback(
864 const CacheAndErrorCallback& callback,
865 const scoped_refptr<ServiceWorkerCache>& cache,
866 CacheStorageError error) {
867 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
868 weak_factory_.GetWeakPtr();
870 callback.Run(cache, error);
871 if (cache_storage)
872 scheduler_->CompleteOperationAndRunNext();
875 void ServiceWorkerCacheStorage::PendingStringsAndErrorCallback(
876 const StringsAndErrorCallback& callback,
877 const StringVector& strings,
878 CacheStorageError error) {
879 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
880 weak_factory_.GetWeakPtr();
882 callback.Run(strings, error);
883 if (cache_storage)
884 scheduler_->CompleteOperationAndRunNext();
887 void ServiceWorkerCacheStorage::PendingResponseCallback(
888 const ServiceWorkerCache::ResponseCallback& callback,
889 ServiceWorkerCache::ErrorType error,
890 scoped_ptr<ServiceWorkerResponse> response,
891 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
892 base::WeakPtr<ServiceWorkerCacheStorage> cache_storage =
893 weak_factory_.GetWeakPtr();
895 callback.Run(error, response.Pass(), blob_data_handle.Pass());
896 if (cache_storage)
897 scheduler_->CompleteOperationAndRunNext();
900 } // namespace content