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/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"
30 void CloseAllCachesDidCloseCache(const scoped_refptr
<ServiceWorkerCache
>& cache
,
31 const base::Closure
& barrier_closure
) {
32 barrier_closure
.Run();
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
{
43 typedef base::Callback
<void(const scoped_refptr
<ServiceWorkerCache
>&)>
45 typedef base::Callback
<void(bool)> BoolCallback
;
46 typedef base::Callback
<void(scoped_ptr
<std::vector
<std::string
> >)>
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
,
55 : cache_task_runner_(cache_task_runner
),
56 request_context_(request_context
),
57 quota_manager_proxy_(quota_manager_proxy
),
58 blob_context_(blob_context
),
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;
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_
;
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
99 class ServiceWorkerCacheStorage::MemoryLoader
100 : public ServiceWorkerCacheStorage::CacheLoader
{
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
,
108 : CacheLoader(cache_task_runner
,
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
));
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
);
136 void WriteIndex(const StringVector
& cache_names
,
137 const BoolCallback
& callback
) override
{
141 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
142 const StringVectorCallback
& callback
) override
{
143 callback
.Run(cache_names
.Pass());
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
153 CacheRefMap cache_refs_
;
156 class ServiceWorkerCacheStorage::SimpleCacheLoader
157 : public ServiceWorkerCacheStorage::CacheLoader
{
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
,
166 : CacheLoader(cache_task_runner
,
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(
180 CreatePersistentCachePath(origin_path_
, cache_name
),
182 quota_manager_proxy_
,
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(),
200 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool
, cache_path
),
201 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir
,
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
,
217 if (!success
|| !loader
) {
218 callback
.Run(scoped_refptr
<ServiceWorkerCache
>());
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(
235 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
,
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
);
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(
274 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
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(
311 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
313 base::Passed(names
.Pass()),
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
) {
324 base::ReadFileToString(index_path
, &body
);
326 original_loop
->PostTask(FROM_HERE
,
327 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
328 base::Passed(names
.Pass()),
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
348 callback
.Run(names
.Pass());
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
,
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
,
380 : initialized_(false),
381 initializing_(false),
382 scheduler_(new ServiceWorkerCacheScheduler()),
384 cache_task_runner_(cache_task_runner
),
385 memory_only_(memory_only
),
386 weak_factory_(this) {
388 cache_loader_
.reset(new MemoryLoader(cache_task_runner_
.get(),
394 cache_loader_
.reset(new SimpleCacheLoader(origin_path_
,
395 cache_task_runner_
.get(),
402 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
405 void ServiceWorkerCacheStorage::OpenCache(
406 const std::string
& cache_name
,
407 const CacheAndErrorCallback
& callback
) {
408 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
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
);
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
);
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
);
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
);
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()),
501 void ServiceWorkerCacheStorage::CloseAllCaches(const base::Closure
& callback
) {
502 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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_
)
524 for (auto& key_value
: cache_map_
) {
525 if (key_value
.second
)
526 sum
+= key_value
.second
->MemoryBackedSize();
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_
);
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;
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
);
594 callback
.Run(cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
598 cache_loader_
->CreateCache(
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
);
611 callback
.Run(scoped_refptr
<ServiceWorkerCache
>(),
612 CACHE_STORAGE_ERROR_CLOSING
);
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(),
627 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
628 const CacheAndErrorCallback
& callback
,
629 const scoped_refptr
<ServiceWorkerCache
>& cache
,
631 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
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
);
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()));
669 cache
->Close(closure
);
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(
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
,
691 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
693 cache_loader_
->CleanUpDeletedCache(
695 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp
,
696 weak_factory_
.GetWeakPtr(),
700 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
701 const BoolAndErrorCallback
& callback
,
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
);
720 callback
.Run(ServiceWorkerCache::ErrorTypeNotFound
,
721 scoped_ptr
<ServiceWorkerResponse
>(),
722 scoped_ptr
<storage::BlobDataHandle
>());
726 // Pass the cache along to the callback to keep the cache open until match is
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
);
759 cache
->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request
)),
760 base::Bind(&ServiceWorkerCacheStorage::MatchAllCachesDidMatch
,
761 weak_factory_
.GetWeakPtr(), cache
, barrier_closure
,
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();
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
;
804 scoped_refptr
<ServiceWorkerCache
> new_cache
=
805 cache_loader_
->CreateServiceWorkerCache(cache_name
);
806 map_iter
->second
= new_cache
->AsWeakPtr();
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) {
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();
848 scheduler_
->CompleteOperationAndRunNext();
851 void ServiceWorkerCacheStorage::PendingBoolAndErrorCallback(
852 const BoolAndErrorCallback
& callback
,
854 CacheStorageError error
) {
855 base::WeakPtr
<ServiceWorkerCacheStorage
> cache_storage
=
856 weak_factory_
.GetWeakPtr();
858 callback
.Run(found
, error
);
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
);
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
);
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());
897 scheduler_
->CompleteOperationAndRunNext();
900 } // namespace content