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/cache_storage/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/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/sha1.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/thread_task_runner_handle.h"
22 #include "content/browser/cache_storage/cache_storage.pb.h"
23 #include "content/browser/cache_storage/cache_storage_cache.h"
24 #include "content/browser/cache_storage/cache_storage_scheduler.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "net/base/directory_lister.h"
27 #include "net/base/net_errors.h"
28 #include "net/url_request/url_request_context_getter.h"
29 #include "storage/browser/blob/blob_storage_context.h"
30 #include "storage/browser/quota/quota_manager_proxy.h"
36 void CloseAllCachesDidCloseCache(const scoped_refptr
<CacheStorageCache
>& cache
,
37 const base::Closure
& barrier_closure
) {
38 barrier_closure
.Run();
43 const char CacheStorage::kIndexFileName
[] = "index.txt";
45 // Handles the loading and clean up of CacheStorageCache objects. The
46 // callback of every public method is guaranteed to be called.
47 class CacheStorage::CacheLoader
{
49 typedef base::Callback
<void(const scoped_refptr
<CacheStorageCache
>&)>
51 typedef base::Callback
<void(bool)> BoolCallback
;
52 typedef base::Callback
<void(scoped_ptr
<std::vector
<std::string
>>)>
56 base::SequencedTaskRunner
* cache_task_runner
,
57 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
58 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
59 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
61 : cache_task_runner_(cache_task_runner
),
62 request_context_getter_(request_context_getter
),
63 quota_manager_proxy_(quota_manager_proxy
),
64 blob_context_(blob_context
),
66 DCHECK(!origin_
.is_empty());
69 virtual ~CacheLoader() {}
71 // Creates a CacheStorageCache with the given name. It does not attempt to
72 // load the backend, that happens lazily when the cache is used.
73 virtual scoped_refptr
<CacheStorageCache
> CreateCache(
74 const std::string
& cache_name
) = 0;
76 // Deletes any pre-existing cache of the same name and then loads it.
77 virtual void CreateCache(const std::string
& cache_name
,
78 const CacheCallback
& callback
) = 0;
80 // After the backend has been deleted, do any extra house keeping such as
81 // removing the cache's directory.
82 virtual void CleanUpDeletedCache(const std::string
& key
,
83 const BoolCallback
& callback
) = 0;
85 // Writes the cache names (and sizes) to disk if applicable.
86 virtual void WriteIndex(const StringVector
& cache_names
,
87 const BoolCallback
& callback
) = 0;
89 // Loads the cache names from disk if applicable.
90 virtual void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
91 const StringVectorCallback
& callback
) = 0;
94 scoped_refptr
<base::SequencedTaskRunner
> cache_task_runner_
;
95 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
96 scoped_refptr
<storage::QuotaManagerProxy
> quota_manager_proxy_
;
97 base::WeakPtr
<storage::BlobStorageContext
> blob_context_
;
101 // Creates memory-only ServiceWorkerCaches. Because these caches have no
102 // persistent storage it is not safe to free them from memory if they might be
103 // used again. Therefore this class holds a reference to each cache until the
105 class CacheStorage::MemoryLoader
: public CacheStorage::CacheLoader
{
108 base::SequencedTaskRunner
* cache_task_runner
,
109 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
110 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
111 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
113 : CacheLoader(cache_task_runner
,
119 scoped_refptr
<CacheStorageCache
> CreateCache(
120 const std::string
& cache_name
) override
{
121 return CacheStorageCache::CreateMemoryCache(
122 origin_
, request_context_getter_
, quota_manager_proxy_
, blob_context_
);
125 void CreateCache(const std::string
& cache_name
,
126 const CacheCallback
& callback
) override
{
127 scoped_refptr
<CacheStorageCache
> cache
= CreateCache(cache_name
);
128 cache_refs_
.insert(std::make_pair(cache_name
, cache
));
132 void CleanUpDeletedCache(const std::string
& cache_name
,
133 const BoolCallback
& callback
) override
{
134 CacheRefMap::iterator it
= cache_refs_
.find(cache_name
);
135 DCHECK(it
!= cache_refs_
.end());
136 cache_refs_
.erase(it
);
140 void WriteIndex(const StringVector
& cache_names
,
141 const BoolCallback
& callback
) override
{
145 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
146 const StringVectorCallback
& callback
) override
{
147 callback
.Run(cache_names
.Pass());
151 typedef std::map
<std::string
, scoped_refptr
<CacheStorageCache
>> CacheRefMap
;
152 ~MemoryLoader() override
{}
154 // Keep a reference to each cache to ensure that it's not freed before the
155 // client calls CacheStorage::Delete or the CacheStorage is
157 CacheRefMap cache_refs_
;
160 class CacheStorage::SimpleCacheLoader
: public CacheStorage::CacheLoader
{
163 const base::FilePath
& origin_path
,
164 base::SequencedTaskRunner
* cache_task_runner
,
165 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
166 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
167 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
169 : CacheLoader(cache_task_runner
,
174 origin_path_(origin_path
),
175 weak_ptr_factory_(this) {}
177 scoped_refptr
<CacheStorageCache
> CreateCache(
178 const std::string
& cache_name
) override
{
179 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
181 return CacheStorageCache::CreatePersistentCache(
182 origin_
, CreatePersistentCachePath(origin_path_
, cache_name
),
183 request_context_getter_
, quota_manager_proxy_
, blob_context_
);
186 void CreateCache(const std::string
& cache_name
,
187 const CacheCallback
& callback
) override
{
188 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
190 // 1. Delete the cache's directory if it exists.
191 // (CreateCacheDeleteFilesInPool)
192 // 2. Load the cache. (LoadCreateDirectoryInPool)
194 base::FilePath cache_path
=
195 CreatePersistentCachePath(origin_path_
, cache_name
);
197 PostTaskAndReplyWithResult(
198 cache_task_runner_
.get(), FROM_HERE
,
199 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool
, cache_path
),
200 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir
, cache_name
,
201 callback
, weak_ptr_factory_
.GetWeakPtr()));
204 static bool CreateCachePrepDirInPool(const base::FilePath
& cache_path
) {
205 if (base::PathExists(cache_path
))
206 base::DeleteFile(cache_path
, /* recursive */ true);
207 return base::CreateDirectory(cache_path
);
210 static void CreateCachePreppedDir(const std::string
& cache_name
,
211 const CacheCallback
& callback
,
212 base::WeakPtr
<SimpleCacheLoader
> loader
,
214 if (!success
|| !loader
) {
215 callback
.Run(scoped_refptr
<CacheStorageCache
>());
219 callback
.Run(loader
->CreateCache(cache_name
));
222 void CleanUpDeletedCache(const std::string
& cache_name
,
223 const BoolCallback
& callback
) override
{
224 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
226 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
228 base::FilePath cache_path
=
229 CreatePersistentCachePath(origin_path_
, cache_name
);
230 cache_task_runner_
->PostTask(
232 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
, cache_path
,
233 callback
, base::ThreadTaskRunnerHandle::Get()));
236 static void CleanUpDeleteCacheDirInPool(
237 const base::FilePath
& cache_path
,
238 const BoolCallback
& callback
,
239 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
240 bool rv
= base::DeleteFile(cache_path
, true);
241 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
244 void WriteIndex(const StringVector
& cache_names
,
245 const BoolCallback
& callback
) override
{
246 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
248 // 1. Create the index file as a string. (WriteIndex)
249 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
251 CacheStorageIndex index
;
252 index
.set_origin(origin_
.spec());
254 for (size_t i
= 0u, max
= cache_names
.size(); i
< max
; ++i
) {
255 CacheStorageIndex::Cache
* index_cache
= index
.add_cache();
256 index_cache
->set_name(cache_names
[i
]);
259 std::string serialized
;
260 bool success
= index
.SerializeToString(&serialized
);
263 base::FilePath tmp_path
= origin_path_
.AppendASCII("index.txt.tmp");
264 base::FilePath index_path
=
265 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
267 cache_task_runner_
->PostTask(
268 FROM_HERE
, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
269 tmp_path
, index_path
, serialized
, callback
,
270 base::ThreadTaskRunnerHandle::Get()));
273 static void WriteIndexWriteToFileInPool(
274 const base::FilePath
& tmp_path
,
275 const base::FilePath
& index_path
,
276 const std::string
& data
,
277 const BoolCallback
& callback
,
278 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
279 int bytes_written
= base::WriteFile(tmp_path
, data
.c_str(), data
.size());
280 if (bytes_written
!= base::checked_cast
<int>(data
.size())) {
281 base::DeleteFile(tmp_path
, /* recursive */ false);
282 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, false));
285 // Atomically rename the temporary index file to become the real one.
286 bool rv
= base::ReplaceFile(tmp_path
, index_path
, NULL
);
287 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
290 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> names
,
291 const StringVectorCallback
& callback
) override
{
292 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
294 // 1. Read the file from disk. (LoadIndexReadFileInPool)
295 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
297 base::FilePath index_path
=
298 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
300 cache_task_runner_
->PostTask(
301 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
302 index_path
, base::Passed(names
.Pass()), callback
,
303 base::ThreadTaskRunnerHandle::Get()));
306 static void LoadIndexReadFileInPool(
307 const base::FilePath
& index_path
,
308 scoped_ptr
<std::vector
<std::string
>> names
,
309 const StringVectorCallback
& callback
,
310 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
312 base::ReadFileToString(index_path
, &body
);
314 original_task_runner
->PostTask(
315 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
316 base::Passed(names
.Pass()), callback
, body
));
319 static void LoadIndexDidReadFile(scoped_ptr
<std::vector
<std::string
>> names
,
320 const StringVectorCallback
& callback
,
321 const std::string
& serialized
) {
322 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
324 CacheStorageIndex index
;
325 if (index
.ParseFromString(serialized
)) {
326 for (int i
= 0, max
= index
.cache_size(); i
< max
; ++i
) {
327 const CacheStorageIndex::Cache
& cache
= index
.cache(i
);
328 names
->push_back(cache
.name());
332 // TODO(jkarlin): Delete caches that are in the directory and not returned
334 callback
.Run(names
.Pass());
338 ~SimpleCacheLoader() override
{}
340 static std::string
HexedHash(const std::string
& value
) {
341 std::string value_hash
= base::SHA1HashString(value
);
342 std::string valued_hexed_hash
= base::ToLowerASCII(
343 base::HexEncode(value_hash
.c_str(), value_hash
.length()));
344 return valued_hexed_hash
;
347 static base::FilePath
CreatePersistentCachePath(
348 const base::FilePath
& origin_path
,
349 const std::string
& cache_name
) {
350 return origin_path
.AppendASCII(HexedHash(cache_name
));
353 const base::FilePath origin_path_
;
355 base::WeakPtrFactory
<SimpleCacheLoader
> weak_ptr_factory_
;
358 CacheStorage::CacheStorage(
359 const base::FilePath
& path
,
361 base::SequencedTaskRunner
* cache_task_runner
,
362 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
363 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
364 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
366 : initialized_(false),
367 initializing_(false),
368 scheduler_(new CacheStorageScheduler()),
370 cache_task_runner_(cache_task_runner
),
371 memory_only_(memory_only
),
372 weak_factory_(this) {
374 cache_loader_
.reset(new MemoryLoader(cache_task_runner_
.get(),
375 request_context
, quota_manager_proxy
,
376 blob_context
, origin
));
378 cache_loader_
.reset(new SimpleCacheLoader(
379 origin_path_
, cache_task_runner_
.get(), request_context
,
380 quota_manager_proxy
, blob_context
, origin
));
383 CacheStorage::~CacheStorage() {
386 void CacheStorage::OpenCache(const std::string
& cache_name
,
387 const CacheAndErrorCallback
& callback
) {
388 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
393 CacheAndErrorCallback pending_callback
=
394 base::Bind(&CacheStorage::PendingCacheAndErrorCallback
,
395 weak_factory_
.GetWeakPtr(), callback
);
396 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl
,
397 weak_factory_
.GetWeakPtr(),
398 cache_name
, pending_callback
));
401 void CacheStorage::HasCache(const std::string
& cache_name
,
402 const BoolAndErrorCallback
& callback
) {
403 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
408 BoolAndErrorCallback pending_callback
=
409 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
410 weak_factory_
.GetWeakPtr(), callback
);
411 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl
,
412 weak_factory_
.GetWeakPtr(),
413 cache_name
, pending_callback
));
416 void CacheStorage::DeleteCache(const std::string
& cache_name
,
417 const BoolAndErrorCallback
& callback
) {
418 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
423 BoolAndErrorCallback pending_callback
=
424 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
425 weak_factory_
.GetWeakPtr(), callback
);
426 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl
,
427 weak_factory_
.GetWeakPtr(),
428 cache_name
, pending_callback
));
431 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback
& callback
) {
432 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
437 StringsAndErrorCallback pending_callback
=
438 base::Bind(&CacheStorage::PendingStringsAndErrorCallback
,
439 weak_factory_
.GetWeakPtr(), callback
);
440 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl
,
441 weak_factory_
.GetWeakPtr(),
445 void CacheStorage::MatchCache(
446 const std::string
& cache_name
,
447 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
448 const CacheStorageCache::ResponseCallback
& callback
) {
449 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
454 CacheStorageCache::ResponseCallback pending_callback
=
455 base::Bind(&CacheStorage::PendingResponseCallback
,
456 weak_factory_
.GetWeakPtr(), callback
);
457 scheduler_
->ScheduleOperation(
458 base::Bind(&CacheStorage::MatchCacheImpl
, weak_factory_
.GetWeakPtr(),
459 cache_name
, base::Passed(request
.Pass()), pending_callback
));
462 void CacheStorage::MatchAllCaches(
463 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
464 const CacheStorageCache::ResponseCallback
& callback
) {
465 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
470 CacheStorageCache::ResponseCallback pending_callback
=
471 base::Bind(&CacheStorage::PendingResponseCallback
,
472 weak_factory_
.GetWeakPtr(), callback
);
473 scheduler_
->ScheduleOperation(
474 base::Bind(&CacheStorage::MatchAllCachesImpl
, weak_factory_
.GetWeakPtr(),
475 base::Passed(request
.Pass()), pending_callback
));
478 void CacheStorage::CloseAllCaches(const base::Closure
& callback
) {
479 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
486 base::Closure pending_callback
= base::Bind(
487 &CacheStorage::PendingClosure
, weak_factory_
.GetWeakPtr(), callback
);
488 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl
,
489 weak_factory_
.GetWeakPtr(),
493 int64
CacheStorage::MemoryBackedSize() const {
494 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
496 if (!initialized_
|| !memory_only_
)
500 for (auto& key_value
: cache_map_
) {
501 if (key_value
.second
)
502 sum
+= key_value
.second
->MemoryBackedSize();
507 void CacheStorage::StartAsyncOperationForTesting() {
508 scheduler_
->ScheduleOperation(base::Bind(&base::DoNothing
));
511 void CacheStorage::CompleteAsyncOperationForTesting() {
512 scheduler_
->CompleteOperationAndRunNext();
515 // Init is run lazily so that it is called on the proper MessageLoop.
516 void CacheStorage::LazyInit() {
517 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
518 DCHECK(!initialized_
);
523 DCHECK(!scheduler_
->ScheduledOperations());
525 initializing_
= true;
526 scheduler_
->ScheduleOperation(
527 base::Bind(&CacheStorage::LazyInitImpl
, weak_factory_
.GetWeakPtr()));
530 void CacheStorage::LazyInitImpl() {
531 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
532 DCHECK(!initialized_
);
533 DCHECK(initializing_
);
535 // 1. Get the list of cache names (async call)
536 // 2. For each cache name, load the cache (async call)
537 // 3. Once each load is complete, update the map variables.
538 // 4. Call the list of waiting callbacks.
540 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names(
541 new std::vector
<std::string
>());
543 cache_loader_
->LoadIndex(indexed_cache_names
.Pass(),
544 base::Bind(&CacheStorage::LazyInitDidLoadIndex
,
545 weak_factory_
.GetWeakPtr()));
548 void CacheStorage::LazyInitDidLoadIndex(
549 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names
) {
550 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
552 for (size_t i
= 0u, max
= indexed_cache_names
->size(); i
< max
; ++i
) {
553 cache_map_
.insert(std::make_pair(indexed_cache_names
->at(i
),
554 base::WeakPtr
<CacheStorageCache
>()));
555 ordered_cache_names_
.push_back(indexed_cache_names
->at(i
));
558 initializing_
= false;
561 scheduler_
->CompleteOperationAndRunNext();
564 void CacheStorage::OpenCacheImpl(const std::string
& cache_name
,
565 const CacheAndErrorCallback
& callback
) {
566 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
568 callback
.Run(cache
, CACHE_STORAGE_OK
);
572 cache_loader_
->CreateCache(
573 cache_name
, base::Bind(&CacheStorage::CreateCacheDidCreateCache
,
574 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
577 void CacheStorage::CreateCacheDidCreateCache(
578 const std::string
& cache_name
,
579 const CacheAndErrorCallback
& callback
,
580 const scoped_refptr
<CacheStorageCache
>& cache
) {
581 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
583 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
587 callback
.Run(scoped_refptr
<CacheStorageCache
>(),
588 CACHE_STORAGE_ERROR_STORAGE
);
592 cache_map_
.insert(std::make_pair(cache_name
, cache
->AsWeakPtr()));
593 ordered_cache_names_
.push_back(cache_name
);
595 cache_loader_
->WriteIndex(
596 ordered_cache_names_
,
597 base::Bind(&CacheStorage::CreateCacheDidWriteIndex
,
598 weak_factory_
.GetWeakPtr(), callback
, cache
));
601 void CacheStorage::CreateCacheDidWriteIndex(
602 const CacheAndErrorCallback
& callback
,
603 const scoped_refptr
<CacheStorageCache
>& cache
,
605 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
608 // TODO(jkarlin): Handle !success.
610 callback
.Run(cache
, CACHE_STORAGE_OK
);
613 void CacheStorage::HasCacheImpl(const std::string
& cache_name
,
614 const BoolAndErrorCallback
& callback
) {
615 bool has_cache
= cache_map_
.find(cache_name
) != cache_map_
.end();
617 callback
.Run(has_cache
, CACHE_STORAGE_OK
);
620 void CacheStorage::DeleteCacheImpl(const std::string
& cache_name
,
621 const BoolAndErrorCallback
& callback
) {
622 CacheMap::iterator it
= cache_map_
.find(cache_name
);
623 if (it
== cache_map_
.end()) {
624 callback
.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND
);
628 base::WeakPtr
<CacheStorageCache
> cache
= it
->second
;
629 cache_map_
.erase(it
);
631 // Delete the name from ordered_cache_names_.
632 StringVector::iterator iter
= std::find(
633 ordered_cache_names_
.begin(), ordered_cache_names_
.end(), cache_name
);
634 DCHECK(iter
!= ordered_cache_names_
.end());
635 ordered_cache_names_
.erase(iter
);
637 base::Closure closure
=
638 base::Bind(&CacheStorage::DeleteCacheDidClose
, weak_factory_
.GetWeakPtr(),
639 cache_name
, callback
, ordered_cache_names_
,
640 make_scoped_refptr(cache
.get()));
643 cache
->Close(closure
);
650 void CacheStorage::DeleteCacheDidClose(
651 const std::string
& cache_name
,
652 const BoolAndErrorCallback
& callback
,
653 const StringVector
& ordered_cache_names
,
654 const scoped_refptr
<CacheStorageCache
>& cache
/* might be null */) {
655 cache_loader_
->WriteIndex(
657 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex
,
658 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
661 void CacheStorage::DeleteCacheDidWriteIndex(
662 const std::string
& cache_name
,
663 const BoolAndErrorCallback
& callback
,
665 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
667 cache_loader_
->CleanUpDeletedCache(
668 cache_name
, base::Bind(&CacheStorage::DeleteCacheDidCleanUp
,
669 weak_factory_
.GetWeakPtr(), callback
));
672 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback
& callback
,
674 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
676 callback
.Run(true, CACHE_STORAGE_OK
);
679 void CacheStorage::EnumerateCachesImpl(
680 const StringsAndErrorCallback
& callback
) {
681 callback
.Run(ordered_cache_names_
, CACHE_STORAGE_OK
);
684 void CacheStorage::MatchCacheImpl(
685 const std::string
& cache_name
,
686 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
687 const CacheStorageCache::ResponseCallback
& callback
) {
688 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
691 callback
.Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
692 scoped_ptr
<ServiceWorkerResponse
>(),
693 scoped_ptr
<storage::BlobDataHandle
>());
697 // Pass the cache along to the callback to keep the cache open until match is
699 cache
->Match(request
.Pass(),
700 base::Bind(&CacheStorage::MatchCacheDidMatch
,
701 weak_factory_
.GetWeakPtr(), cache
, callback
));
704 void CacheStorage::MatchCacheDidMatch(
705 const scoped_refptr
<CacheStorageCache
>& cache
,
706 const CacheStorageCache::ResponseCallback
& callback
,
707 CacheStorageError error
,
708 scoped_ptr
<ServiceWorkerResponse
> response
,
709 scoped_ptr
<storage::BlobDataHandle
> handle
) {
710 callback
.Run(error
, response
.Pass(), handle
.Pass());
713 void CacheStorage::MatchAllCachesImpl(
714 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
715 const CacheStorageCache::ResponseCallback
& callback
) {
716 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback_copy(
717 new CacheStorageCache::ResponseCallback(callback
));
719 CacheStorageCache::ResponseCallback
* callback_ptr
= callback_copy
.get();
720 base::Closure barrier_closure
=
721 base::BarrierClosure(ordered_cache_names_
.size(),
722 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll
,
723 weak_factory_
.GetWeakPtr(),
724 base::Passed(callback_copy
.Pass())));
726 for (const std::string
& cache_name
: ordered_cache_names_
) {
727 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
730 cache
->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request
)),
731 base::Bind(&CacheStorage::MatchAllCachesDidMatch
,
732 weak_factory_
.GetWeakPtr(), cache
, barrier_closure
,
737 void CacheStorage::MatchAllCachesDidMatch(
738 scoped_refptr
<CacheStorageCache
> cache
,
739 const base::Closure
& barrier_closure
,
740 CacheStorageCache::ResponseCallback
* callback
,
741 CacheStorageError error
,
742 scoped_ptr
<ServiceWorkerResponse
> response
,
743 scoped_ptr
<storage::BlobDataHandle
> handle
) {
744 if (callback
->is_null() || error
== CACHE_STORAGE_ERROR_NOT_FOUND
) {
745 barrier_closure
.Run();
748 callback
->Run(error
, response
.Pass(), handle
.Pass());
749 callback
->Reset(); // Only call the callback once.
751 barrier_closure
.Run();
754 void CacheStorage::MatchAllCachesDidMatchAll(
755 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback
) {
756 if (!callback
->is_null()) {
757 callback
->Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
758 scoped_ptr
<ServiceWorkerResponse
>(),
759 scoped_ptr
<storage::BlobDataHandle
>());
763 scoped_refptr
<CacheStorageCache
> CacheStorage::GetLoadedCache(
764 const std::string
& cache_name
) {
765 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
766 DCHECK(initialized_
);
768 CacheMap::iterator map_iter
= cache_map_
.find(cache_name
);
769 if (map_iter
== cache_map_
.end())
770 return scoped_refptr
<CacheStorageCache
>();
772 base::WeakPtr
<CacheStorageCache
> cache
= map_iter
->second
;
775 scoped_refptr
<CacheStorageCache
> new_cache
=
776 cache_loader_
->CreateCache(cache_name
);
777 map_iter
->second
= new_cache
->AsWeakPtr();
781 return make_scoped_refptr(cache
.get());
784 void CacheStorage::CloseAllCachesImpl(const base::Closure
& callback
) {
785 int live_cache_count
= 0;
786 for (const auto& key_value
: cache_map_
) {
787 if (key_value
.second
)
788 live_cache_count
+= 1;
791 if (live_cache_count
== 0) {
796 // The closure might modify this object so delay calling it until after
797 // iterating through cache_map_ by adding one to the barrier.
798 base::Closure barrier_closure
=
799 base::BarrierClosure(live_cache_count
+ 1, base::Bind(callback
));
801 for (auto& key_value
: cache_map_
) {
802 if (key_value
.second
) {
803 key_value
.second
->Close(base::Bind(
804 CloseAllCachesDidCloseCache
,
805 make_scoped_refptr(key_value
.second
.get()), barrier_closure
));
809 barrier_closure
.Run();
812 void CacheStorage::PendingClosure(const base::Closure
& callback
) {
813 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
817 scheduler_
->CompleteOperationAndRunNext();
820 void CacheStorage::PendingBoolAndErrorCallback(
821 const BoolAndErrorCallback
& callback
,
823 CacheStorageError error
) {
824 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
826 callback
.Run(found
, error
);
828 scheduler_
->CompleteOperationAndRunNext();
831 void CacheStorage::PendingCacheAndErrorCallback(
832 const CacheAndErrorCallback
& callback
,
833 const scoped_refptr
<CacheStorageCache
>& cache
,
834 CacheStorageError error
) {
835 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
837 callback
.Run(cache
, error
);
839 scheduler_
->CompleteOperationAndRunNext();
842 void CacheStorage::PendingStringsAndErrorCallback(
843 const StringsAndErrorCallback
& callback
,
844 const StringVector
& strings
,
845 CacheStorageError error
) {
846 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
848 callback
.Run(strings
, error
);
850 scheduler_
->CompleteOperationAndRunNext();
853 void CacheStorage::PendingResponseCallback(
854 const CacheStorageCache::ResponseCallback
& callback
,
855 CacheStorageError error
,
856 scoped_ptr
<ServiceWorkerResponse
> response
,
857 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
858 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
860 callback
.Run(error
, response
.Pass(), blob_data_handle
.Pass());
862 scheduler_
->CompleteOperationAndRunNext();
865 } // namespace content