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/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/service_worker/service_worker_cache.h"
19 #include "content/browser/service_worker/service_worker_cache.pb.h"
20 #include "content/browser/service_worker/service_worker_cache_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"
31 void CloseAllCachesDidCloseCache(const scoped_refptr
<ServiceWorkerCache
>& cache
,
32 const base::Closure
& barrier_closure
) {
33 barrier_closure
.Run();
38 const char ServiceWorkerCacheStorage::kIndexFileName
[] = "index.txt";
40 // Handles the loading and clean up of ServiceWorkerCache objects. The
41 // callback of every public method is guaranteed to be called.
42 class ServiceWorkerCacheStorage::CacheLoader
{
44 typedef base::Callback
<void(const scoped_refptr
<ServiceWorkerCache
>&)>
46 typedef base::Callback
<void(bool)> BoolCallback
;
47 typedef base::Callback
<void(scoped_ptr
<std::vector
<std::string
> >)>
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
,
56 : cache_task_runner_(cache_task_runner
),
57 request_context_(request_context
),
58 quota_manager_proxy_(quota_manager_proxy
),
59 blob_context_(blob_context
),
61 DCHECK(!origin_
.is_empty());
64 virtual ~CacheLoader() {}
66 // Creates a ServiceWorkerCache 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
<ServiceWorkerCache
> CreateServiceWorkerCache(
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;
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_
;
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
100 class ServiceWorkerCacheStorage::MemoryLoader
101 : public ServiceWorkerCacheStorage::CacheLoader
{
104 base::SequencedTaskRunner
* cache_task_runner
,
105 net::URLRequestContext
* request_context
,
106 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
107 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
109 : CacheLoader(cache_task_runner
,
115 scoped_refptr
<ServiceWorkerCache
> CreateServiceWorkerCache(
116 const std::string
& cache_name
) override
{
117 return ServiceWorkerCache::CreateMemoryCache(
118 origin_
, request_context_
, quota_manager_proxy_
, blob_context_
);
121 void CreateCache(const std::string
& cache_name
,
122 const CacheCallback
& callback
) override
{
123 scoped_refptr
<ServiceWorkerCache
> cache
=
124 CreateServiceWorkerCache(cache_name
);
125 cache_refs_
.insert(std::make_pair(cache_name
, cache
));
129 void CleanUpDeletedCache(const std::string
& cache_name
,
130 const BoolCallback
& callback
) override
{
131 CacheRefMap::iterator it
= cache_refs_
.find(cache_name
);
132 DCHECK(it
!= cache_refs_
.end());
133 cache_refs_
.erase(it
);
137 void WriteIndex(const StringVector
& cache_names
,
138 const BoolCallback
& callback
) override
{
142 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
143 const StringVectorCallback
& callback
) override
{
144 callback
.Run(cache_names
.Pass());
148 typedef std::map
<std::string
, scoped_refptr
<ServiceWorkerCache
> > CacheRefMap
;
149 ~MemoryLoader() override
{}
151 // Keep a reference to each cache to ensure that it's not freed before the
152 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
154 CacheRefMap cache_refs_
;
157 class ServiceWorkerCacheStorage::SimpleCacheLoader
158 : public ServiceWorkerCacheStorage::CacheLoader
{
161 const base::FilePath
& origin_path
,
162 base::SequencedTaskRunner
* cache_task_runner
,
163 net::URLRequestContext
* request_context
,
164 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
165 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
167 : CacheLoader(cache_task_runner
,
172 origin_path_(origin_path
),
173 weak_ptr_factory_(this) {}
175 scoped_refptr
<ServiceWorkerCache
> CreateServiceWorkerCache(
176 const std::string
& cache_name
) override
{
177 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
179 return ServiceWorkerCache::CreatePersistentCache(
181 CreatePersistentCachePath(origin_path_
, cache_name
),
183 quota_manager_proxy_
,
187 void CreateCache(const std::string
& cache_name
,
188 const CacheCallback
& callback
) override
{
189 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
191 // 1. Delete the cache's directory if it exists.
192 // (CreateCacheDeleteFilesInPool)
193 // 2. Load the cache. (LoadCreateDirectoryInPool)
195 base::FilePath cache_path
=
196 CreatePersistentCachePath(origin_path_
, cache_name
);
198 PostTaskAndReplyWithResult(
199 cache_task_runner_
.get(),
201 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool
, cache_path
),
202 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir
,
205 weak_ptr_factory_
.GetWeakPtr()));
208 static bool CreateCachePrepDirInPool(const base::FilePath
& cache_path
) {
209 if (base::PathExists(cache_path
))
210 base::DeleteFile(cache_path
, /* recursive */ true);
211 return base::CreateDirectory(cache_path
);
214 static void CreateCachePreppedDir(const std::string
& cache_name
,
215 const CacheCallback
& callback
,
216 base::WeakPtr
<SimpleCacheLoader
> loader
,
218 if (!success
|| !loader
) {
219 callback
.Run(scoped_refptr
<ServiceWorkerCache
>());
223 callback
.Run(loader
->CreateServiceWorkerCache(cache_name
));
226 void CleanUpDeletedCache(const std::string
& cache_name
,
227 const BoolCallback
& callback
) override
{
228 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
230 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
232 base::FilePath cache_path
=
233 CreatePersistentCachePath(origin_path_
, cache_name
);
234 cache_task_runner_
->PostTask(
236 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
,
239 base::MessageLoopProxy::current()));
242 static void CleanUpDeleteCacheDirInPool(
243 const base::FilePath
& cache_path
,
244 const BoolCallback
& callback
,
245 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
246 bool rv
= base::DeleteFile(cache_path
, true);
247 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
250 void WriteIndex(const StringVector
& cache_names
,
251 const BoolCallback
& callback
) override
{
252 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
254 // 1. Create the index file as a string. (WriteIndex)
255 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
257 ServiceWorkerCacheStorageIndex index
;
258 index
.set_origin(origin_
.spec());
260 for (size_t i
= 0u, max
= cache_names
.size(); i
< max
; ++i
) {
261 ServiceWorkerCacheStorageIndex::Cache
* index_cache
= index
.add_cache();
262 index_cache
->set_name(cache_names
[i
]);
265 std::string serialized
;
266 bool success
= index
.SerializeToString(&serialized
);
269 base::FilePath tmp_path
= origin_path_
.AppendASCII("index.txt.tmp");
270 base::FilePath index_path
=
271 origin_path_
.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName
);
273 cache_task_runner_
->PostTask(
275 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
280 base::MessageLoopProxy::current()));
283 static void WriteIndexWriteToFileInPool(
284 const base::FilePath
& tmp_path
,
285 const base::FilePath
& index_path
,
286 const std::string
& data
,
287 const BoolCallback
& callback
,
288 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
289 int bytes_written
= base::WriteFile(tmp_path
, data
.c_str(), data
.size());
290 if (bytes_written
!= implicit_cast
<int>(data
.size())) {
291 base::DeleteFile(tmp_path
, /* recursive */ false);
292 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, false));
295 // Atomically rename the temporary index file to become the real one.
296 bool rv
= base::ReplaceFile(tmp_path
, index_path
, NULL
);
297 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
300 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> names
,
301 const StringVectorCallback
& callback
) override
{
302 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
304 // 1. Read the file from disk. (LoadIndexReadFileInPool)
305 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
307 base::FilePath index_path
=
308 origin_path_
.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName
);
310 cache_task_runner_
->PostTask(
312 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
314 base::Passed(names
.Pass()),
316 base::MessageLoopProxy::current()));
319 static void LoadIndexReadFileInPool(
320 const base::FilePath
& index_path
,
321 scoped_ptr
<std::vector
<std::string
> > names
,
322 const StringVectorCallback
& callback
,
323 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
325 base::ReadFileToString(index_path
, &body
);
327 original_loop
->PostTask(FROM_HERE
,
328 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
329 base::Passed(names
.Pass()),
334 static void LoadIndexDidReadFile(scoped_ptr
<std::vector
<std::string
> > names
,
335 const StringVectorCallback
& callback
,
336 const std::string
& serialized
) {
337 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
339 ServiceWorkerCacheStorageIndex index
;
340 if (index
.ParseFromString(serialized
)) {
341 for (int i
= 0, max
= index
.cache_size(); i
< max
; ++i
) {
342 const ServiceWorkerCacheStorageIndex::Cache
& cache
= index
.cache(i
);
343 names
->push_back(cache
.name());
347 // TODO(jkarlin): Delete caches that are in the directory and not returned
349 callback
.Run(names
.Pass());
353 ~SimpleCacheLoader() override
{}
355 static std::string
HexedHash(const std::string
& value
) {
356 std::string value_hash
= base::SHA1HashString(value
);
357 std::string valued_hexed_hash
= base::StringToLowerASCII(
358 base::HexEncode(value_hash
.c_str(), value_hash
.length()));
359 return valued_hexed_hash
;
362 static base::FilePath
CreatePersistentCachePath(
363 const base::FilePath
& origin_path
,
364 const std::string
& cache_name
) {
365 return origin_path
.AppendASCII(HexedHash(cache_name
));
368 const base::FilePath origin_path_
;
370 base::WeakPtrFactory
<SimpleCacheLoader
> weak_ptr_factory_
;
373 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
374 const base::FilePath
& path
,
376 base::SequencedTaskRunner
* cache_task_runner
,
377 net::URLRequestContext
* request_context
,
378 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
379 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
381 : initialized_(false),
382 initializing_(false),
383 scheduler_(new ServiceWorkerCacheScheduler()),
385 cache_task_runner_(cache_task_runner
),
386 memory_only_(memory_only
),
387 weak_factory_(this) {
389 cache_loader_
.reset(new MemoryLoader(cache_task_runner_
.get(),
395 cache_loader_
.reset(new SimpleCacheLoader(origin_path_
,
396 cache_task_runner_
.get(),
403 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
406 void ServiceWorkerCacheStorage::OpenCache(
407 const std::string
& cache_name
,
408 const CacheAndErrorCallback
& callback
) {
409 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
414 CacheAndErrorCallback pending_callback
=
415 base::Bind(&ServiceWorkerCacheStorage::PendingCacheAndErrorCallback
,
416 weak_factory_
.GetWeakPtr(), callback
);
417 scheduler_
->ScheduleOperation(
418 base::Bind(&ServiceWorkerCacheStorage::OpenCacheImpl
,
419 weak_factory_
.GetWeakPtr(), cache_name
, pending_callback
));
422 void ServiceWorkerCacheStorage::HasCache(const std::string
& cache_name
,
423 const BoolAndErrorCallback
& callback
) {
424 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
429 BoolAndErrorCallback pending_callback
=
430 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback
,
431 weak_factory_
.GetWeakPtr(), callback
);
432 scheduler_
->ScheduleOperation(
433 base::Bind(&ServiceWorkerCacheStorage::HasCacheImpl
,
434 weak_factory_
.GetWeakPtr(), cache_name
, pending_callback
));
437 void ServiceWorkerCacheStorage::DeleteCache(
438 const std::string
& cache_name
,
439 const BoolAndErrorCallback
& callback
) {
440 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
445 BoolAndErrorCallback pending_callback
=
446 base::Bind(&ServiceWorkerCacheStorage::PendingBoolAndErrorCallback
,
447 weak_factory_
.GetWeakPtr(), callback
);
448 scheduler_
->ScheduleOperation(
449 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheImpl
,
450 weak_factory_
.GetWeakPtr(), cache_name
, pending_callback
));
453 void ServiceWorkerCacheStorage::EnumerateCaches(
454 const StringsAndErrorCallback
& callback
) {
455 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
460 StringsAndErrorCallback pending_callback
=
461 base::Bind(&ServiceWorkerCacheStorage::PendingStringsAndErrorCallback
,
462 weak_factory_
.GetWeakPtr(), callback
);
463 scheduler_
->ScheduleOperation(
464 base::Bind(&ServiceWorkerCacheStorage::EnumerateCachesImpl
,
465 weak_factory_
.GetWeakPtr(), pending_callback
));
468 void ServiceWorkerCacheStorage::MatchCache(
469 const std::string
& cache_name
,
470 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
471 const ServiceWorkerCache::ResponseCallback
& callback
) {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
477 ServiceWorkerCache::ResponseCallback pending_callback
=
478 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback
,
479 weak_factory_
.GetWeakPtr(), callback
);
480 scheduler_
->ScheduleOperation(base::Bind(
481 &ServiceWorkerCacheStorage::MatchCacheImpl
, weak_factory_
.GetWeakPtr(),
482 cache_name
, base::Passed(request
.Pass()), pending_callback
));
485 void ServiceWorkerCacheStorage::MatchAllCaches(
486 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
487 const ServiceWorkerCache::ResponseCallback
& callback
) {
488 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
493 ServiceWorkerCache::ResponseCallback pending_callback
=
494 base::Bind(&ServiceWorkerCacheStorage::PendingResponseCallback
,
495 weak_factory_
.GetWeakPtr(), callback
);
496 scheduler_
->ScheduleOperation(
497 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesImpl
,
498 weak_factory_
.GetWeakPtr(), base::Passed(request
.Pass()),
502 void ServiceWorkerCacheStorage::CloseAllCaches(const base::Closure
& callback
) {
503 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
510 base::Closure pending_callback
=
511 base::Bind(&ServiceWorkerCacheStorage::PendingClosure
,
512 weak_factory_
.GetWeakPtr(), callback
);
513 scheduler_
->ScheduleOperation(
514 base::Bind(&ServiceWorkerCacheStorage::CloseAllCachesImpl
,
515 weak_factory_
.GetWeakPtr(), pending_callback
));
518 int64
ServiceWorkerCacheStorage::MemoryBackedSize() const {
519 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
521 if (!initialized_
|| !memory_only_
)
525 for (auto& key_value
: cache_map_
) {
526 if (key_value
.second
)
527 sum
+= key_value
.second
->MemoryBackedSize();
532 void ServiceWorkerCacheStorage::StartAsyncOperationForTesting() {
533 scheduler_
->ScheduleOperation(base::Bind(&base::DoNothing
));
536 void ServiceWorkerCacheStorage::CompleteAsyncOperationForTesting() {
537 scheduler_
->CompleteOperationAndRunNext();
540 // Init is run lazily so that it is called on the proper MessageLoop.
541 void ServiceWorkerCacheStorage::LazyInit() {
542 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
543 DCHECK(!initialized_
);
548 DCHECK(!scheduler_
->ScheduledOperations());
550 initializing_
= true;
551 scheduler_
->ScheduleOperation(base::Bind(
552 &ServiceWorkerCacheStorage::LazyInitImpl
, weak_factory_
.GetWeakPtr()));
555 void ServiceWorkerCacheStorage::LazyInitImpl() {
556 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
557 DCHECK(!initialized_
);
558 DCHECK(initializing_
);
560 // 1. Get the list of cache names (async call)
561 // 2. For each cache name, load the cache (async call)
562 // 3. Once each load is complete, update the map variables.
563 // 4. Call the list of waiting callbacks.
565 scoped_ptr
<std::vector
<std::string
> > indexed_cache_names(
566 new std::vector
<std::string
>());
568 cache_loader_
->LoadIndex(
569 indexed_cache_names
.Pass(),
570 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex
,
571 weak_factory_
.GetWeakPtr()));
574 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
575 scoped_ptr
<std::vector
<std::string
> > indexed_cache_names
) {
576 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
578 for (size_t i
= 0u, max
= indexed_cache_names
->size(); i
< max
; ++i
) {
579 cache_map_
.insert(std::make_pair(indexed_cache_names
->at(i
),
580 base::WeakPtr
<ServiceWorkerCache
>()));
581 ordered_cache_names_
.push_back(indexed_cache_names
->at(i
));
584 initializing_
= false;
587 scheduler_
->CompleteOperationAndRunNext();
590 void ServiceWorkerCacheStorage::OpenCacheImpl(
591 const std::string
& cache_name
,
592 const CacheAndErrorCallback
& callback
) {
593 scoped_refptr
<ServiceWorkerCache
> cache
= GetLoadedCache(cache_name
);
595 callback
.Run(cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
599 cache_loader_
->CreateCache(
601 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache
,
602 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
605 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
606 const std::string
& cache_name
,
607 const CacheAndErrorCallback
& callback
,
608 const scoped_refptr
<ServiceWorkerCache
>& cache
) {
609 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
612 callback
.Run(scoped_refptr
<ServiceWorkerCache
>(),
613 CACHE_STORAGE_ERROR_CLOSING
);
617 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
620 cache_map_
.insert(std::make_pair(cache_name
, cache
->AsWeakPtr()));
621 ordered_cache_names_
.push_back(cache_name
);
623 cache_loader_
->WriteIndex(
624 ordered_cache_names_
,
625 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex
,
626 weak_factory_
.GetWeakPtr(),
631 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
632 const CacheAndErrorCallback
& callback
,
633 const scoped_refptr
<ServiceWorkerCache
>& cache
,
635 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
638 // TODO(jkarlin): Handle !success.
640 callback
.Run(cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
643 void ServiceWorkerCacheStorage::HasCacheImpl(
644 const std::string
& cache_name
,
645 const BoolAndErrorCallback
& callback
) {
646 bool has_cache
= cache_map_
.find(cache_name
) != cache_map_
.end();
648 callback
.Run(has_cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
651 void ServiceWorkerCacheStorage::DeleteCacheImpl(
652 const std::string
& cache_name
,
653 const BoolAndErrorCallback
& callback
) {
654 CacheMap::iterator it
= cache_map_
.find(cache_name
);
655 if (it
== cache_map_
.end()) {
656 callback
.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND
);
660 base::WeakPtr
<ServiceWorkerCache
> cache
= it
->second
;
661 cache_map_
.erase(it
);
663 // Delete the name from ordered_cache_names_.
664 StringVector::iterator iter
= std::find(
665 ordered_cache_names_
.begin(), ordered_cache_names_
.end(), cache_name
);
666 DCHECK(iter
!= ordered_cache_names_
.end());
667 ordered_cache_names_
.erase(iter
);
669 base::Closure closure
=
670 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidClose
,
671 weak_factory_
.GetWeakPtr(), cache_name
, callback
,
672 ordered_cache_names_
, make_scoped_refptr(cache
.get()));
675 cache
->Close(closure
);
682 void ServiceWorkerCacheStorage::DeleteCacheDidClose(
683 const std::string
& cache_name
,
684 const BoolAndErrorCallback
& callback
,
685 const StringVector
& ordered_cache_names
,
686 const scoped_refptr
<ServiceWorkerCache
>& cache
/* might be null */) {
687 cache_loader_
->WriteIndex(
689 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex
,
690 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
693 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
694 const std::string
& cache_name
,
695 const BoolAndErrorCallback
& callback
,
697 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
699 cache_loader_
->CleanUpDeletedCache(
701 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp
,
702 weak_factory_
.GetWeakPtr(),
706 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
707 const BoolAndErrorCallback
& callback
,
709 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
711 callback
.Run(true, CACHE_STORAGE_ERROR_NO_ERROR
);
714 void ServiceWorkerCacheStorage::EnumerateCachesImpl(
715 const StringsAndErrorCallback
& callback
) {
716 callback
.Run(ordered_cache_names_
, CACHE_STORAGE_ERROR_NO_ERROR
);
719 void ServiceWorkerCacheStorage::MatchCacheImpl(
720 const std::string
& cache_name
,
721 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
722 const ServiceWorkerCache::ResponseCallback
& callback
) {
723 scoped_refptr
<ServiceWorkerCache
> cache
= GetLoadedCache(cache_name
);
726 callback
.Run(ServiceWorkerCache::ERROR_TYPE_NOT_FOUND
,
727 scoped_ptr
<ServiceWorkerResponse
>(),
728 scoped_ptr
<storage::BlobDataHandle
>());
732 // Pass the cache along to the callback to keep the cache open until match is
734 cache
->Match(request
.Pass(),
735 base::Bind(&ServiceWorkerCacheStorage::MatchCacheDidMatch
,
736 weak_factory_
.GetWeakPtr(), cache
, callback
));
739 void ServiceWorkerCacheStorage::MatchCacheDidMatch(
740 const scoped_refptr
<ServiceWorkerCache
>& cache
,
741 const ServiceWorkerCache::ResponseCallback
& callback
,
742 ServiceWorkerCache::ErrorType error
,
743 scoped_ptr
<ServiceWorkerResponse
> response
,
744 scoped_ptr
<storage::BlobDataHandle
> handle
) {
745 callback
.Run(error
, response
.Pass(), handle
.Pass());
748 void ServiceWorkerCacheStorage::MatchAllCachesImpl(
749 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
750 const ServiceWorkerCache::ResponseCallback
& callback
) {
751 scoped_ptr
<ServiceWorkerCache::ResponseCallback
> callback_copy(
752 new ServiceWorkerCache::ResponseCallback(callback
));
754 ServiceWorkerCache::ResponseCallback
* callback_ptr
= callback_copy
.get();
755 base::Closure barrier_closure
= base::BarrierClosure(
756 ordered_cache_names_
.size(),
757 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll
,
758 weak_factory_
.GetWeakPtr(),
759 base::Passed(callback_copy
.Pass())));
761 for (const std::string
& cache_name
: ordered_cache_names_
) {
762 scoped_refptr
<ServiceWorkerCache
> cache
= GetLoadedCache(cache_name
);
765 cache
->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request
)),
766 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatch
,
767 weak_factory_
.GetWeakPtr(), cache
, barrier_closure
,
772 void ServiceWorkerCacheStorage::MatchAllCachesDidMatch(
773 scoped_refptr
<ServiceWorkerCache
> cache
,
774 const base::Closure
& barrier_closure
,
775 ServiceWorkerCache::ResponseCallback
* callback
,
776 ServiceWorkerCache::ErrorType error
,
777 scoped_ptr
<ServiceWorkerResponse
> response
,
778 scoped_ptr
<storage::BlobDataHandle
> handle
) {
779 if (callback
->is_null() ||
780 error
== ServiceWorkerCache::ERROR_TYPE_NOT_FOUND
) {
781 barrier_closure
.Run();
784 callback
->Run(error
, response
.Pass(), handle
.Pass());
785 callback
->Reset(); // Only call the callback once.
787 barrier_closure
.Run();
790 void ServiceWorkerCacheStorage::MatchAllCachesDidMatchAll(
791 scoped_ptr
<ServiceWorkerCache::ResponseCallback
> callback
) {
792 if (!callback
->is_null()) {
793 callback
->Run(ServiceWorkerCache::ERROR_TYPE_NOT_FOUND
,
794 scoped_ptr
<ServiceWorkerResponse
>(),
795 scoped_ptr
<storage::BlobDataHandle
>());
799 scoped_refptr
<ServiceWorkerCache
> ServiceWorkerCacheStorage::GetLoadedCache(
800 const std::string
& cache_name
) {
801 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
802 DCHECK(initialized_
);
804 CacheMap::iterator map_iter
= cache_map_
.find(cache_name
);
805 if (map_iter
== cache_map_
.end())
806 return scoped_refptr
<ServiceWorkerCache
>();
808 base::WeakPtr
<ServiceWorkerCache
> cache
= map_iter
->second
;
811 scoped_refptr
<ServiceWorkerCache
> new_cache
=
812 cache_loader_
->CreateServiceWorkerCache(cache_name
);
813 map_iter
->second
= new_cache
->AsWeakPtr();
817 return make_scoped_refptr(cache
.get());
820 void ServiceWorkerCacheStorage::CloseAllCachesImpl(
821 const base::Closure
& callback
) {
822 int live_cache_count
= 0;
823 for (const auto& key_value
: cache_map_
) {
824 if (key_value
.second
)
825 live_cache_count
+= 1;
828 if (live_cache_count
== 0) {
833 // The closure might modify this object so delay calling it until after
834 // iterating through cache_map_ by adding one to the barrier.
835 base::Closure barrier_closure
=
836 base::BarrierClosure(live_cache_count
+ 1, base::Bind(callback
));
838 for (auto& key_value
: cache_map_
) {
839 if (key_value
.second
) {
840 key_value
.second
->Close(base::Bind(
841 CloseAllCachesDidCloseCache
,
842 make_scoped_refptr(key_value
.second
.get()), barrier_closure
));
846 barrier_closure
.Run();
849 void ServiceWorkerCacheStorage::PendingClosure(const base::Closure
& callback
) {
850 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
851 weak_factory_
.GetWeakPtr();
855 scheduler_
->CompleteOperationAndRunNext();
858 void ServiceWorkerCacheStorage::PendingBoolAndErrorCallback(
859 const BoolAndErrorCallback
& callback
,
861 CacheStorageError error
) {
862 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
863 weak_factory_
.GetWeakPtr();
865 callback
.Run(found
, error
);
867 scheduler_
->CompleteOperationAndRunNext();
870 void ServiceWorkerCacheStorage::PendingCacheAndErrorCallback(
871 const CacheAndErrorCallback
& callback
,
872 const scoped_refptr
<ServiceWorkerCache
>& cache
,
873 CacheStorageError error
) {
874 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
875 weak_factory_
.GetWeakPtr();
877 callback
.Run(cache
, error
);
879 scheduler_
->CompleteOperationAndRunNext();
882 void ServiceWorkerCacheStorage::PendingStringsAndErrorCallback(
883 const StringsAndErrorCallback
& callback
,
884 const StringVector
& strings
,
885 CacheStorageError error
) {
886 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
887 weak_factory_
.GetWeakPtr();
889 callback
.Run(strings
, error
);
891 scheduler_
->CompleteOperationAndRunNext();
894 void ServiceWorkerCacheStorage::PendingResponseCallback(
895 const ServiceWorkerCache::ResponseCallback
& callback
,
896 ServiceWorkerCache::ErrorType error
,
897 scoped_ptr
<ServiceWorkerResponse
> response
,
898 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
899 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
900 weak_factory_
.GetWeakPtr();
902 callback
.Run(error
, response
.Pass(), blob_data_handle
.Pass());
904 scheduler_
->CompleteOperationAndRunNext();
907 } // namespace content