Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_cache_storage.cc
blob5409289e81f73ba5d825b5e45f869a28d2c24ab5
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/file_util.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/sha1.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "content/browser/service_worker/service_worker_cache.h"
17 #include "content/browser/service_worker/service_worker_cache.pb.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/base/directory_lister.h"
20 #include "net/base/net_errors.h"
21 #include "webkit/browser/blob/blob_storage_context.h"
23 namespace content {
25 // static
26 const int ServiceWorkerCacheStorage::kInvalidCacheID = -1;
28 // The meta information related to each ServiceWorkerCache that the
29 // ServiceWorkerCacheManager needs to keep track of.
30 // TODO(jkarlin): Add reference counting so that the deletion of javascript
31 // objects can delete the ServiceWorkerCache.
32 struct ServiceWorkerCacheStorage::CacheContext {
33 CacheContext(const std::string& name,
34 CacheID id,
35 scoped_ptr<ServiceWorkerCache> cache)
36 : name(name), id(id), cache(cache.Pass()) {}
37 std::string name;
38 CacheID id;
39 scoped_ptr<ServiceWorkerCache> cache;
42 // Handles the loading and clean up of ServiceWorkerCache objects. The
43 // callback of every public method is guaranteed to be called.
44 class ServiceWorkerCacheStorage::CacheLoader {
45 public:
46 typedef base::Callback<void(scoped_ptr<ServiceWorkerCache>)> CacheCallback;
47 typedef base::Callback<void(bool)> BoolCallback;
48 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
49 StringsCallback;
51 CacheLoader(base::SequencedTaskRunner* cache_task_runner,
52 net::URLRequestContext* request_context,
53 base::WeakPtr<storage::BlobStorageContext> blob_context)
54 : cache_task_runner_(cache_task_runner),
55 request_context_(request_context),
56 blob_context_(blob_context) {}
58 virtual ~CacheLoader() {}
60 // Loads the given cache_name, the cache is NULL if it fails. If the cache
61 // doesn't exist a new one is created.
62 virtual void LoadCache(const std::string& cache_name,
63 const CacheCallback& callback) = 0;
65 // Deletes any pre-existing cache of the same name and then loads it.
66 virtual void CreateCache(const std::string& cache_name,
67 const CacheCallback& callback) = 0;
69 // After the backend has been deleted, do any extra house keeping such as
70 // removing the cache's directory.
71 virtual void CleanUpDeletedCache(const std::string& key,
72 const BoolCallback& callback) = 0;
74 // Writes the cache names (and sizes) to disk if applicable.
75 virtual void WriteIndex(const CacheMap& caches,
76 const BoolCallback& callback) = 0;
78 // Loads the cache names from disk if applicable.
79 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
80 const StringsCallback& callback) = 0;
82 protected:
83 virtual void LoadCacheImpl(const std::string&) {}
85 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
86 net::URLRequestContext* request_context_;
87 base::WeakPtr<storage::BlobStorageContext> blob_context_;
90 class ServiceWorkerCacheStorage::MemoryLoader
91 : public ServiceWorkerCacheStorage::CacheLoader {
92 public:
93 MemoryLoader(base::SequencedTaskRunner* cache_task_runner,
94 net::URLRequestContext* request_context,
95 base::WeakPtr<storage::BlobStorageContext> blob_context)
96 : CacheLoader(cache_task_runner, request_context, blob_context) {}
97 virtual void LoadCache(const std::string& cache_name,
98 const CacheCallback& callback) OVERRIDE {
99 NOTREACHED();
102 virtual void CreateCache(const std::string& cache_name,
103 const CacheCallback& callback) OVERRIDE {
104 scoped_ptr<ServiceWorkerCache> cache =
105 ServiceWorkerCache::CreateMemoryCache(request_context_, blob_context_);
106 callback.Run(cache.Pass());
109 virtual void CleanUpDeletedCache(const std::string& cache_name,
110 const BoolCallback& callback) OVERRIDE {
111 callback.Run(true);
114 virtual void WriteIndex(const CacheMap& caches,
115 const BoolCallback& callback) OVERRIDE {
116 callback.Run(false);
119 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
120 const StringsCallback& callback) OVERRIDE {
121 callback.Run(cache_names.Pass());
124 private:
125 virtual ~MemoryLoader() {}
128 class ServiceWorkerCacheStorage::SimpleCacheLoader
129 : public ServiceWorkerCacheStorage::CacheLoader {
130 public:
131 SimpleCacheLoader(const base::FilePath& origin_path,
132 base::SequencedTaskRunner* cache_task_runner,
133 net::URLRequestContext* request_context,
134 base::WeakPtr<storage::BlobStorageContext> blob_context)
135 : CacheLoader(cache_task_runner, request_context, blob_context),
136 origin_path_(origin_path),
137 weak_ptr_factory_(this) {}
139 virtual void LoadCache(const std::string& cache_name,
140 const CacheCallback& callback) OVERRIDE {
141 DCHECK_CURRENTLY_ON(BrowserThread::IO);
143 // 1. Create the cache's directory if necessary. (LoadCreateDirectoryInPool)
144 // 2. Create the cache object. (LoadDidCreateDirectory)
146 cache_task_runner_->PostTask(
147 FROM_HERE,
148 base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool,
149 CreatePersistentCachePath(origin_path_, cache_name),
150 cache_name,
151 callback,
152 weak_ptr_factory_.GetWeakPtr(),
153 base::MessageLoopProxy::current()));
156 static void LoadCreateDirectoryInPool(
157 const base::FilePath& path,
158 const std::string& cache_name,
159 const CacheCallback& callback,
160 base::WeakPtr<SimpleCacheLoader> loader,
161 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
162 bool rv = base::CreateDirectory(path);
163 original_loop->PostTask(
164 FROM_HERE,
165 base::Bind(&SimpleCacheLoader::LoadDidCreateDirectory,
166 cache_name,
167 callback,
168 loader,
169 rv));
172 static void LoadDidCreateDirectory(const std::string& cache_name,
173 const CacheCallback& callback,
174 base::WeakPtr<SimpleCacheLoader> loader,
175 bool dir_rv) {
176 DCHECK_CURRENTLY_ON(BrowserThread::IO);
178 if (!dir_rv || !loader) {
179 callback.Run(scoped_ptr<ServiceWorkerCache>());
180 return;
183 scoped_ptr<ServiceWorkerCache> cache =
184 ServiceWorkerCache::CreatePersistentCache(
185 CreatePersistentCachePath(loader->origin_path_, cache_name),
186 loader->request_context_,
187 loader->blob_context_);
188 callback.Run(cache.Pass());
191 virtual void CreateCache(const std::string& cache_name,
192 const CacheCallback& callback) OVERRIDE {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO);
195 // 1. Delete the cache's directory if it exists.
196 // (CreateCacheDeleteFilesInPool)
197 // 2. Load the cache. (LoadCreateDirectoryInPool)
199 base::FilePath cache_path =
200 CreatePersistentCachePath(origin_path_, cache_name);
202 cache_task_runner_->PostTask(
203 FROM_HERE,
204 base::Bind(&SimpleCacheLoader::CreateCacheDeleteFilesInPool,
205 cache_path,
206 cache_name,
207 callback,
208 weak_ptr_factory_.GetWeakPtr(),
209 base::MessageLoopProxy::current()));
212 static void CreateCacheDeleteFilesInPool(
213 const base::FilePath& cache_path,
214 const std::string& cache_name,
215 const CacheCallback& callback,
216 base::WeakPtr<SimpleCacheLoader> loader,
217 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
218 base::FilePath path(cache_path);
219 if (base::PathExists(path))
220 base::DeleteFile(path, /* recursive */ true);
222 // Jump straight into LoadCache on the same thread.
223 LoadCreateDirectoryInPool(
224 cache_path, cache_name, callback, loader, original_loop);
227 virtual void CleanUpDeletedCache(const std::string& cache_name,
228 const BoolCallback& callback) OVERRIDE {
229 DCHECK_CURRENTLY_ON(BrowserThread::IO);
231 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
233 base::FilePath cache_path =
234 CreatePersistentCachePath(origin_path_, cache_name);
235 cache_task_runner_->PostTask(
236 FROM_HERE,
237 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
238 cache_path,
239 callback,
240 base::MessageLoopProxy::current()));
243 static void CleanUpDeleteCacheDirInPool(
244 const base::FilePath& cache_path,
245 const BoolCallback& callback,
246 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
247 bool rv = base::DeleteFile(cache_path, true);
248 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
251 virtual void WriteIndex(const CacheMap& caches,
252 const BoolCallback& callback) OVERRIDE {
253 DCHECK_CURRENTLY_ON(BrowserThread::IO);
255 // 1. Create the index file as a string. (WriteIndex)
256 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
258 ServiceWorkerCacheStorageIndex index;
260 for (CacheMap::const_iterator it = caches.begin(); it != caches.end();
261 ++it) {
262 const CacheContext* cache = it->second;
263 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
264 index_cache->set_name(cache->name);
265 index_cache->set_size(0); // TODO(jkarlin): Make this real.
268 std::string serialized;
269 bool success = index.SerializeToString(&serialized);
270 DCHECK(success);
272 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
273 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
275 cache_task_runner_->PostTask(
276 FROM_HERE,
277 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
278 tmp_path,
279 index_path,
280 serialized,
281 callback,
282 base::MessageLoopProxy::current()));
285 static void WriteIndexWriteToFileInPool(
286 const base::FilePath& tmp_path,
287 const base::FilePath& index_path,
288 const std::string& data,
289 const BoolCallback& callback,
290 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
291 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
292 if (bytes_written != implicit_cast<int>(data.size())) {
293 base::DeleteFile(tmp_path, /* recursive */ false);
294 original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
297 // Atomically rename the temporary index file to become the real one.
298 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
299 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
302 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names,
303 const StringsCallback& callback) OVERRIDE {
304 DCHECK_CURRENTLY_ON(BrowserThread::IO);
306 // 1. Read the file from disk. (LoadIndexReadFileInPool)
307 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
309 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
311 cache_task_runner_->PostTask(
312 FROM_HERE,
313 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
314 index_path,
315 base::Passed(names.Pass()),
316 callback,
317 base::MessageLoopProxy::current()));
320 static void LoadIndexReadFileInPool(
321 const base::FilePath& index_path,
322 scoped_ptr<std::vector<std::string> > names,
323 const StringsCallback& callback,
324 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
325 std::string body;
326 base::ReadFileToString(index_path, &body);
328 original_loop->PostTask(FROM_HERE,
329 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
330 base::Passed(names.Pass()),
331 callback,
332 body));
335 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
336 const StringsCallback& callback,
337 const std::string& serialized) {
338 DCHECK_CURRENTLY_ON(BrowserThread::IO);
340 ServiceWorkerCacheStorageIndex index;
341 if (index.ParseFromString(serialized)) {
342 for (int i = 0, max = index.cache_size(); i < max; ++i) {
343 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
344 names->push_back(cache.name());
348 // TODO(jkarlin): Delete caches that are in the directory and not returned
349 // in LoadIndex.
350 callback.Run(names.Pass());
353 private:
354 virtual ~SimpleCacheLoader() {}
356 static std::string HexedHash(const std::string& value) {
357 std::string value_hash = base::SHA1HashString(value);
358 std::string valued_hexed_hash = base::StringToLowerASCII(
359 base::HexEncode(value_hash.c_str(), value_hash.length()));
360 return valued_hexed_hash;
363 static base::FilePath CreatePersistentCachePath(
364 const base::FilePath& origin_path,
365 const std::string& cache_name) {
366 return origin_path.AppendASCII(HexedHash(cache_name));
369 const base::FilePath origin_path_;
371 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
374 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
375 const base::FilePath& path,
376 bool memory_only,
377 base::SequencedTaskRunner* cache_task_runner,
378 net::URLRequestContext* request_context,
379 base::WeakPtr<storage::BlobStorageContext> blob_context)
380 : initialized_(false),
381 next_cache_id_(0),
382 origin_path_(path),
383 cache_task_runner_(cache_task_runner),
384 weak_factory_(this) {
385 if (memory_only)
386 cache_loader_.reset(new MemoryLoader(
387 cache_task_runner_.get(), request_context, blob_context));
388 else
389 cache_loader_.reset(new SimpleCacheLoader(
390 origin_path_, cache_task_runner_.get(), request_context, blob_context));
393 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
394 STLDeleteContainerPairSecondPointers(cache_map_.begin(), cache_map_.end());
397 void ServiceWorkerCacheStorage::CreateCache(
398 const std::string& cache_name,
399 const CacheAndErrorCallback& callback) {
400 if (!initialized_) {
401 LazyInit(base::Bind(&ServiceWorkerCacheStorage::CreateCache,
402 weak_factory_.GetWeakPtr(),
403 cache_name,
404 callback));
405 return;
408 if (cache_name.empty()) {
409 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_EMPTY_KEY);
410 return;
413 if (GetLoadedCache(cache_name)) {
414 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_EXISTS);
415 return;
418 cache_loader_->CreateCache(
419 cache_name,
420 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache,
421 weak_factory_.GetWeakPtr(),
422 cache_name,
423 callback));
426 void ServiceWorkerCacheStorage::GetCache(
427 const std::string& cache_name,
428 const CacheAndErrorCallback& callback) {
429 DCHECK_CURRENTLY_ON(BrowserThread::IO);
431 if (!initialized_) {
432 LazyInit(base::Bind(&ServiceWorkerCacheStorage::GetCache,
433 weak_factory_.GetWeakPtr(),
434 cache_name,
435 callback));
436 return;
439 if (cache_name.empty()) {
440 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_EMPTY_KEY);
441 return;
444 CacheContext* cache_context = GetLoadedCache(cache_name);
445 if (!cache_context) {
446 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_NOT_FOUND);
447 return;
450 ServiceWorkerCache* cache = cache_context->cache.get();
452 if (cache->HasCreatedBackend())
453 return callback.Run(cache_context->id, CACHE_STORAGE_ERROR_NO_ERROR);
455 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend,
456 weak_factory_.GetWeakPtr(),
457 cache->AsWeakPtr(),
458 cache_context->id,
459 callback));
462 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
463 const BoolAndErrorCallback& callback) {
464 DCHECK_CURRENTLY_ON(BrowserThread::IO);
466 if (!initialized_) {
467 LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache,
468 weak_factory_.GetWeakPtr(),
469 cache_name,
470 callback));
471 return;
474 if (cache_name.empty()) {
475 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY);
476 return;
479 bool has_cache = GetLoadedCache(cache_name) != NULL;
481 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
484 void ServiceWorkerCacheStorage::DeleteCache(
485 const std::string& cache_name,
486 const BoolAndErrorCallback& callback) {
487 DCHECK_CURRENTLY_ON(BrowserThread::IO);
489 if (!initialized_) {
490 LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache,
491 weak_factory_.GetWeakPtr(),
492 cache_name,
493 callback));
494 return;
497 if (cache_name.empty()) {
498 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY);
499 return;
502 scoped_ptr<CacheContext> cache_context(GetLoadedCache(cache_name));
503 if (!cache_context) {
504 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
505 return;
508 name_map_.erase(cache_name);
509 cache_map_.erase(cache_context->id);
510 cache_context.reset();
512 // Update the Index
513 cache_loader_->WriteIndex(
514 cache_map_,
515 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
516 weak_factory_.GetWeakPtr(),
517 cache_name,
518 callback));
521 void ServiceWorkerCacheStorage::EnumerateCaches(
522 const StringsAndErrorCallback& callback) {
523 DCHECK_CURRENTLY_ON(BrowserThread::IO);
525 if (!initialized_) {
526 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches,
527 weak_factory_.GetWeakPtr(),
528 callback));
529 return;
532 std::vector<std::string> names;
533 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end();
534 ++it) {
535 names.push_back(it->first);
538 callback.Run(names, CACHE_STORAGE_ERROR_NO_ERROR);
541 void ServiceWorkerCacheStorage::DidCreateBackend(
542 base::WeakPtr<ServiceWorkerCache> cache,
543 CacheID cache_id,
544 const CacheAndErrorCallback& callback,
545 ServiceWorkerCache::ErrorType error) {
546 DCHECK_CURRENTLY_ON(BrowserThread::IO);
548 if (error != ServiceWorkerCache::ErrorTypeOK || !cache) {
549 // TODO(jkarlin): This should delete the directory and try again in case
550 // the cache is simply corrupt.
551 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_STORAGE);
552 return;
555 callback.Run(cache_id, CACHE_STORAGE_ERROR_NO_ERROR);
558 // Init is run lazily so that it is called on the proper MessageLoop.
559 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) {
560 DCHECK_CURRENTLY_ON(BrowserThread::IO);
561 DCHECK(!initialized_);
563 init_callbacks_.push_back(callback);
565 // If this isn't the first call to LazyInit then return as the initialization
566 // has already started.
567 if (init_callbacks_.size() > 1u)
568 return;
570 // 1. Get the list of cache names (async call)
571 // 2. For each cache name, load the cache (async call)
572 // 3. Once each load is complete, update the map variables.
573 // 4. Call the list of waiting callbacks.
575 scoped_ptr<std::vector<std::string> > indexed_cache_names(
576 new std::vector<std::string>());
578 cache_loader_->LoadIndex(
579 indexed_cache_names.Pass(),
580 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex,
581 weak_factory_.GetWeakPtr(),
582 callback));
585 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
586 const base::Closure& callback,
587 scoped_ptr<std::vector<std::string> > indexed_cache_names) {
588 DCHECK_CURRENTLY_ON(BrowserThread::IO);
590 if (indexed_cache_names->empty()) {
591 LazyInitDone();
592 return;
595 std::vector<std::string>::const_iterator iter = indexed_cache_names->begin();
596 std::vector<std::string>::const_iterator iter_next = iter + 1;
598 cache_loader_->LoadCache(
599 *iter,
600 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName,
601 weak_factory_.GetWeakPtr(),
602 callback,
603 base::Passed(indexed_cache_names.Pass()),
604 iter_next,
605 *iter));
608 void ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName(
609 const base::Closure& callback,
610 scoped_ptr<std::vector<std::string> > indexed_cache_names,
611 const std::vector<std::string>::const_iterator& iter,
612 const std::string& cache_name,
613 scoped_ptr<ServiceWorkerCache> cache) {
614 DCHECK_CURRENTLY_ON(BrowserThread::IO);
616 if (cache)
617 AddCacheToMaps(cache_name, cache.Pass());
619 if (iter == indexed_cache_names->end()) {
620 LazyInitDone();
621 return;
624 std::vector<std::string>::const_iterator iter_next = iter + 1;
625 cache_loader_->LoadCache(
626 *iter,
627 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName,
628 weak_factory_.GetWeakPtr(),
629 callback,
630 base::Passed(indexed_cache_names.Pass()),
631 iter_next,
632 *iter));
635 void ServiceWorkerCacheStorage::LazyInitDone() {
636 initialized_ = true;
637 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
638 it != init_callbacks_.end();
639 ++it) {
640 it->Run();
642 init_callbacks_.clear();
645 ServiceWorkerCacheStorage::CacheContext*
646 ServiceWorkerCacheStorage::AddCacheToMaps(
647 const std::string& cache_name,
648 scoped_ptr<ServiceWorkerCache> cache) {
649 DCHECK_CURRENTLY_ON(BrowserThread::IO);
651 CacheID id = next_cache_id_++;
652 CacheContext* cache_context = new CacheContext(cache_name, id, cache.Pass());
653 cache_map_.insert(std::make_pair(id, cache_context)); // Takes ownership
654 name_map_.insert(std::make_pair(cache_name, id));
655 return cache_context;
658 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
659 const std::string& cache_name,
660 const CacheAndErrorCallback& callback,
661 scoped_ptr<ServiceWorkerCache> cache) {
662 DCHECK_CURRENTLY_ON(BrowserThread::IO);
664 if (!cache) {
665 callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_CLOSING);
666 return;
669 CacheContext* cache_context = AddCacheToMaps(cache_name, cache.Pass());
671 cache_loader_->WriteIndex(
672 cache_map_,
673 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
674 weak_factory_.GetWeakPtr(),
675 callback,
676 cache_context->cache->AsWeakPtr(),
677 cache_context->id));
680 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
681 const CacheAndErrorCallback& callback,
682 base::WeakPtr<ServiceWorkerCache> cache,
683 CacheID id,
684 bool success) {
685 DCHECK_CURRENTLY_ON(BrowserThread::IO);
686 if (!cache) {
687 callback.Run(false, CACHE_STORAGE_ERROR_CLOSING);
688 return;
691 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend,
692 weak_factory_.GetWeakPtr(),
693 cache,
695 callback));
698 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
699 const std::string& cache_name,
700 const BoolAndErrorCallback& callback,
701 bool success) {
702 DCHECK_CURRENTLY_ON(BrowserThread::IO);
704 cache_loader_->CleanUpDeletedCache(
705 cache_name,
706 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp,
707 weak_factory_.GetWeakPtr(),
708 callback));
711 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
712 const BoolAndErrorCallback& callback,
713 bool success) {
714 DCHECK_CURRENTLY_ON(BrowserThread::IO);
716 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
719 ServiceWorkerCacheStorage::CacheContext*
720 ServiceWorkerCacheStorage::GetLoadedCache(const std::string& cache_name) const {
721 DCHECK_CURRENTLY_ON(BrowserThread::IO);
722 DCHECK(initialized_);
724 NameMap::const_iterator name_iter = name_map_.find(cache_name);
725 if (name_iter == name_map_.end())
726 return NULL;
728 CacheMap::const_iterator map_iter = cache_map_.find(name_iter->second);
729 DCHECK(map_iter != cache_map_.end());
730 return map_iter->second;
733 } // namespace content