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"
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"
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
,
35 scoped_ptr
<ServiceWorkerCache
> cache
)
36 : name(name
), id(id
), cache(cache
.Pass()) {}
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
{
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
> >)>
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;
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
{
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
{
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
{
114 virtual void WriteIndex(const CacheMap
& caches
,
115 const BoolCallback
& callback
) OVERRIDE
{
119 virtual void LoadIndex(scoped_ptr
<std::vector
<std::string
> > cache_names
,
120 const StringsCallback
& callback
) OVERRIDE
{
121 callback
.Run(cache_names
.Pass());
125 virtual ~MemoryLoader() {}
128 class ServiceWorkerCacheStorage::SimpleCacheLoader
129 : public ServiceWorkerCacheStorage::CacheLoader
{
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(
148 base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool
,
149 CreatePersistentCachePath(origin_path_
, cache_name
),
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(
165 base::Bind(&SimpleCacheLoader::LoadDidCreateDirectory
,
172 static void LoadDidCreateDirectory(const std::string
& cache_name
,
173 const CacheCallback
& callback
,
174 base::WeakPtr
<SimpleCacheLoader
> loader
,
176 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
178 if (!dir_rv
|| !loader
) {
179 callback
.Run(scoped_ptr
<ServiceWorkerCache
>());
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(
204 base::Bind(&SimpleCacheLoader::CreateCacheDeleteFilesInPool
,
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(
237 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
,
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();
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
);
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(
277 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
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(
313 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
315 base::Passed(names
.Pass()),
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
) {
326 base::ReadFileToString(index_path
, &body
);
328 original_loop
->PostTask(FROM_HERE
,
329 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
330 base::Passed(names
.Pass()),
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
350 callback
.Run(names
.Pass());
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
,
377 base::SequencedTaskRunner
* cache_task_runner
,
378 net::URLRequestContext
* request_context
,
379 base::WeakPtr
<storage::BlobStorageContext
> blob_context
)
380 : initialized_(false),
383 cache_task_runner_(cache_task_runner
),
384 weak_factory_(this) {
386 cache_loader_
.reset(new MemoryLoader(
387 cache_task_runner_
.get(), request_context
, blob_context
));
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
) {
401 LazyInit(base::Bind(&ServiceWorkerCacheStorage::CreateCache
,
402 weak_factory_
.GetWeakPtr(),
408 if (cache_name
.empty()) {
409 callback
.Run(kInvalidCacheID
, CACHE_STORAGE_ERROR_EMPTY_KEY
);
413 if (GetLoadedCache(cache_name
)) {
414 callback
.Run(kInvalidCacheID
, CACHE_STORAGE_ERROR_EXISTS
);
418 cache_loader_
->CreateCache(
420 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache
,
421 weak_factory_
.GetWeakPtr(),
426 void ServiceWorkerCacheStorage::GetCache(
427 const std::string
& cache_name
,
428 const CacheAndErrorCallback
& callback
) {
429 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
432 LazyInit(base::Bind(&ServiceWorkerCacheStorage::GetCache
,
433 weak_factory_
.GetWeakPtr(),
439 if (cache_name
.empty()) {
440 callback
.Run(kInvalidCacheID
, CACHE_STORAGE_ERROR_EMPTY_KEY
);
444 CacheContext
* cache_context
= GetLoadedCache(cache_name
);
445 if (!cache_context
) {
446 callback
.Run(kInvalidCacheID
, CACHE_STORAGE_ERROR_NOT_FOUND
);
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(),
462 void ServiceWorkerCacheStorage::HasCache(const std::string
& cache_name
,
463 const BoolAndErrorCallback
& callback
) {
464 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
467 LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache
,
468 weak_factory_
.GetWeakPtr(),
474 if (cache_name
.empty()) {
475 callback
.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY
);
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
);
490 LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache
,
491 weak_factory_
.GetWeakPtr(),
497 if (cache_name
.empty()) {
498 callback
.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY
);
502 scoped_ptr
<CacheContext
> cache_context(GetLoadedCache(cache_name
));
503 if (!cache_context
) {
504 callback
.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND
);
508 name_map_
.erase(cache_name
);
509 cache_map_
.erase(cache_context
->id
);
510 cache_context
.reset();
513 cache_loader_
->WriteIndex(
515 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex
,
516 weak_factory_
.GetWeakPtr(),
521 void ServiceWorkerCacheStorage::EnumerateCaches(
522 const StringsAndErrorCallback
& callback
) {
523 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
526 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches
,
527 weak_factory_
.GetWeakPtr(),
532 std::vector
<std::string
> names
;
533 for (NameMap::const_iterator it
= name_map_
.begin(); it
!= name_map_
.end();
535 names
.push_back(it
->first
);
538 callback
.Run(names
, CACHE_STORAGE_ERROR_NO_ERROR
);
541 void ServiceWorkerCacheStorage::DidCreateBackend(
542 base::WeakPtr
<ServiceWorkerCache
> cache
,
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
);
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)
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(),
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()) {
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(
600 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName
,
601 weak_factory_
.GetWeakPtr(),
603 base::Passed(indexed_cache_names
.Pass()),
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
);
617 AddCacheToMaps(cache_name
, cache
.Pass());
619 if (iter
== indexed_cache_names
->end()) {
624 std::vector
<std::string
>::const_iterator iter_next
= iter
+ 1;
625 cache_loader_
->LoadCache(
627 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName
,
628 weak_factory_
.GetWeakPtr(),
630 base::Passed(indexed_cache_names
.Pass()),
635 void ServiceWorkerCacheStorage::LazyInitDone() {
637 for (std::vector
<base::Closure
>::iterator it
= init_callbacks_
.begin();
638 it
!= init_callbacks_
.end();
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
);
665 callback
.Run(kInvalidCacheID
, CACHE_STORAGE_ERROR_CLOSING
);
669 CacheContext
* cache_context
= AddCacheToMaps(cache_name
, cache
.Pass());
671 cache_loader_
->WriteIndex(
673 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex
,
674 weak_factory_
.GetWeakPtr(),
676 cache_context
->cache
->AsWeakPtr(),
680 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
681 const CacheAndErrorCallback
& callback
,
682 base::WeakPtr
<ServiceWorkerCache
> cache
,
685 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
687 callback
.Run(false, CACHE_STORAGE_ERROR_CLOSING
);
691 cache
->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend
,
692 weak_factory_
.GetWeakPtr(),
698 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
699 const std::string
& cache_name
,
700 const BoolAndErrorCallback
& callback
,
702 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
704 cache_loader_
->CleanUpDeletedCache(
706 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp
,
707 weak_factory_
.GetWeakPtr(),
711 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
712 const BoolAndErrorCallback
& callback
,
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())
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