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/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/cache_storage/cache_storage.pb.h"
19 #include "content/browser/cache_storage/cache_storage_cache.h"
20 #include "content/browser/cache_storage/cache_storage_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
<CacheStorageCache
>& cache
,
32 const base::Closure
& barrier_closure
) {
33 barrier_closure
.Run();
38 const char CacheStorage::kIndexFileName
[] = "index.txt";
40 // Handles the loading and clean up of CacheStorageCache objects. The
41 // callback of every public method is guaranteed to be called.
42 class CacheStorage::CacheLoader
{
44 typedef base::Callback
<void(const scoped_refptr
<CacheStorageCache
>&)>
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 CacheStorageCache 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
<CacheStorageCache
> CreateCache(
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 CacheStorage::MemoryLoader
: public CacheStorage::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
<CacheStorageCache
> CreateCache(
115 const std::string
& cache_name
) override
{
116 return CacheStorageCache::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
<CacheStorageCache
> cache
= CreateCache(cache_name
);
123 cache_refs_
.insert(std::make_pair(cache_name
, cache
));
127 void CleanUpDeletedCache(const std::string
& cache_name
,
128 const BoolCallback
& callback
) override
{
129 CacheRefMap::iterator it
= cache_refs_
.find(cache_name
);
130 DCHECK(it
!= cache_refs_
.end());
131 cache_refs_
.erase(it
);
135 void WriteIndex(const StringVector
& cache_names
,
136 const BoolCallback
& callback
) override
{
140 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
141 const StringVectorCallback
& callback
) override
{
142 callback
.Run(cache_names
.Pass());
146 typedef std::map
<std::string
, scoped_refptr
<CacheStorageCache
>> CacheRefMap
;
147 ~MemoryLoader() override
{}
149 // Keep a reference to each cache to ensure that it's not freed before the
150 // client calls CacheStorage::Delete or the CacheStorage is
152 CacheRefMap cache_refs_
;
155 class CacheStorage::SimpleCacheLoader
: public CacheStorage::CacheLoader
{
158 const base::FilePath
& origin_path
,
159 base::SequencedTaskRunner
* cache_task_runner
,
160 net::URLRequestContext
* request_context
,
161 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
162 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
164 : CacheLoader(cache_task_runner
,
169 origin_path_(origin_path
),
170 weak_ptr_factory_(this) {}
172 scoped_refptr
<CacheStorageCache
> CreateCache(
173 const std::string
& cache_name
) override
{
174 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
176 return CacheStorageCache::CreatePersistentCache(
177 origin_
, CreatePersistentCachePath(origin_path_
, cache_name
),
178 request_context_
, quota_manager_proxy_
, blob_context_
);
181 void CreateCache(const std::string
& cache_name
,
182 const CacheCallback
& callback
) override
{
183 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
185 // 1. Delete the cache's directory if it exists.
186 // (CreateCacheDeleteFilesInPool)
187 // 2. Load the cache. (LoadCreateDirectoryInPool)
189 base::FilePath cache_path
=
190 CreatePersistentCachePath(origin_path_
, cache_name
);
192 PostTaskAndReplyWithResult(
193 cache_task_runner_
.get(), FROM_HERE
,
194 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool
, cache_path
),
195 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir
, cache_name
,
196 callback
, weak_ptr_factory_
.GetWeakPtr()));
199 static bool CreateCachePrepDirInPool(const base::FilePath
& cache_path
) {
200 if (base::PathExists(cache_path
))
201 base::DeleteFile(cache_path
, /* recursive */ true);
202 return base::CreateDirectory(cache_path
);
205 static void CreateCachePreppedDir(const std::string
& cache_name
,
206 const CacheCallback
& callback
,
207 base::WeakPtr
<SimpleCacheLoader
> loader
,
209 if (!success
|| !loader
) {
210 callback
.Run(scoped_refptr
<CacheStorageCache
>());
214 callback
.Run(loader
->CreateCache(cache_name
));
217 void CleanUpDeletedCache(const std::string
& cache_name
,
218 const BoolCallback
& callback
) override
{
219 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
221 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
223 base::FilePath cache_path
=
224 CreatePersistentCachePath(origin_path_
, cache_name
);
225 cache_task_runner_
->PostTask(
227 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
, cache_path
,
228 callback
, base::MessageLoopProxy::current()));
231 static void CleanUpDeleteCacheDirInPool(
232 const base::FilePath
& cache_path
,
233 const BoolCallback
& callback
,
234 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
235 bool rv
= base::DeleteFile(cache_path
, true);
236 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
239 void WriteIndex(const StringVector
& cache_names
,
240 const BoolCallback
& callback
) override
{
241 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
243 // 1. Create the index file as a string. (WriteIndex)
244 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
246 CacheStorageIndex index
;
247 index
.set_origin(origin_
.spec());
249 for (size_t i
= 0u, max
= cache_names
.size(); i
< max
; ++i
) {
250 CacheStorageIndex::Cache
* index_cache
= index
.add_cache();
251 index_cache
->set_name(cache_names
[i
]);
254 std::string serialized
;
255 bool success
= index
.SerializeToString(&serialized
);
258 base::FilePath tmp_path
= origin_path_
.AppendASCII("index.txt.tmp");
259 base::FilePath index_path
=
260 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
262 cache_task_runner_
->PostTask(
263 FROM_HERE
, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
264 tmp_path
, index_path
, serialized
, callback
,
265 base::MessageLoopProxy::current()));
268 static void WriteIndexWriteToFileInPool(
269 const base::FilePath
& tmp_path
,
270 const base::FilePath
& index_path
,
271 const std::string
& data
,
272 const BoolCallback
& callback
,
273 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
274 int bytes_written
= base::WriteFile(tmp_path
, data
.c_str(), data
.size());
275 if (bytes_written
!= implicit_cast
<int>(data
.size())) {
276 base::DeleteFile(tmp_path
, /* recursive */ false);
277 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, false));
280 // Atomically rename the temporary index file to become the real one.
281 bool rv
= base::ReplaceFile(tmp_path
, index_path
, NULL
);
282 original_loop
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
285 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> names
,
286 const StringVectorCallback
& callback
) override
{
287 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
289 // 1. Read the file from disk. (LoadIndexReadFileInPool)
290 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
292 base::FilePath index_path
=
293 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
295 cache_task_runner_
->PostTask(
296 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
297 index_path
, base::Passed(names
.Pass()), callback
,
298 base::MessageLoopProxy::current()));
301 static void LoadIndexReadFileInPool(
302 const base::FilePath
& index_path
,
303 scoped_ptr
<std::vector
<std::string
>> names
,
304 const StringVectorCallback
& callback
,
305 const scoped_refptr
<base::MessageLoopProxy
>& original_loop
) {
307 base::ReadFileToString(index_path
, &body
);
309 original_loop
->PostTask(
310 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
311 base::Passed(names
.Pass()), callback
, body
));
314 static void LoadIndexDidReadFile(scoped_ptr
<std::vector
<std::string
>> names
,
315 const StringVectorCallback
& callback
,
316 const std::string
& serialized
) {
317 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
319 CacheStorageIndex index
;
320 if (index
.ParseFromString(serialized
)) {
321 for (int i
= 0, max
= index
.cache_size(); i
< max
; ++i
) {
322 const CacheStorageIndex::Cache
& cache
= index
.cache(i
);
323 names
->push_back(cache
.name());
327 // TODO(jkarlin): Delete caches that are in the directory and not returned
329 callback
.Run(names
.Pass());
333 ~SimpleCacheLoader() override
{}
335 static std::string
HexedHash(const std::string
& value
) {
336 std::string value_hash
= base::SHA1HashString(value
);
337 std::string valued_hexed_hash
= base::StringToLowerASCII(
338 base::HexEncode(value_hash
.c_str(), value_hash
.length()));
339 return valued_hexed_hash
;
342 static base::FilePath
CreatePersistentCachePath(
343 const base::FilePath
& origin_path
,
344 const std::string
& cache_name
) {
345 return origin_path
.AppendASCII(HexedHash(cache_name
));
348 const base::FilePath origin_path_
;
350 base::WeakPtrFactory
<SimpleCacheLoader
> weak_ptr_factory_
;
353 CacheStorage::CacheStorage(
354 const base::FilePath
& path
,
356 base::SequencedTaskRunner
* cache_task_runner
,
357 net::URLRequestContext
* request_context
,
358 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
359 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
361 : initialized_(false),
362 initializing_(false),
363 scheduler_(new CacheStorageScheduler()),
365 cache_task_runner_(cache_task_runner
),
366 memory_only_(memory_only
),
367 weak_factory_(this) {
369 cache_loader_
.reset(new MemoryLoader(cache_task_runner_
.get(),
370 request_context
, quota_manager_proxy
,
371 blob_context
, origin
));
373 cache_loader_
.reset(new SimpleCacheLoader(
374 origin_path_
, cache_task_runner_
.get(), request_context
,
375 quota_manager_proxy
, blob_context
, origin
));
378 CacheStorage::~CacheStorage() {
381 void CacheStorage::OpenCache(const std::string
& cache_name
,
382 const CacheAndErrorCallback
& callback
) {
383 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
388 CacheAndErrorCallback pending_callback
=
389 base::Bind(&CacheStorage::PendingCacheAndErrorCallback
,
390 weak_factory_
.GetWeakPtr(), callback
);
391 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl
,
392 weak_factory_
.GetWeakPtr(),
393 cache_name
, pending_callback
));
396 void CacheStorage::HasCache(const std::string
& cache_name
,
397 const BoolAndErrorCallback
& callback
) {
398 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
403 BoolAndErrorCallback pending_callback
=
404 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
405 weak_factory_
.GetWeakPtr(), callback
);
406 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl
,
407 weak_factory_
.GetWeakPtr(),
408 cache_name
, pending_callback
));
411 void CacheStorage::DeleteCache(const std::string
& cache_name
,
412 const BoolAndErrorCallback
& callback
) {
413 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
418 BoolAndErrorCallback pending_callback
=
419 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
420 weak_factory_
.GetWeakPtr(), callback
);
421 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl
,
422 weak_factory_
.GetWeakPtr(),
423 cache_name
, pending_callback
));
426 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback
& callback
) {
427 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
432 StringsAndErrorCallback pending_callback
=
433 base::Bind(&CacheStorage::PendingStringsAndErrorCallback
,
434 weak_factory_
.GetWeakPtr(), callback
);
435 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl
,
436 weak_factory_
.GetWeakPtr(),
440 void CacheStorage::MatchCache(
441 const std::string
& cache_name
,
442 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
443 const CacheStorageCache::ResponseCallback
& callback
) {
444 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
449 CacheStorageCache::ResponseCallback pending_callback
=
450 base::Bind(&CacheStorage::PendingResponseCallback
,
451 weak_factory_
.GetWeakPtr(), callback
);
452 scheduler_
->ScheduleOperation(
453 base::Bind(&CacheStorage::MatchCacheImpl
, weak_factory_
.GetWeakPtr(),
454 cache_name
, base::Passed(request
.Pass()), pending_callback
));
457 void CacheStorage::MatchAllCaches(
458 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
459 const CacheStorageCache::ResponseCallback
& callback
) {
460 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
465 CacheStorageCache::ResponseCallback pending_callback
=
466 base::Bind(&CacheStorage::PendingResponseCallback
,
467 weak_factory_
.GetWeakPtr(), callback
);
468 scheduler_
->ScheduleOperation(
469 base::Bind(&CacheStorage::MatchAllCachesImpl
, weak_factory_
.GetWeakPtr(),
470 base::Passed(request
.Pass()), pending_callback
));
473 void CacheStorage::CloseAllCaches(const base::Closure
& callback
) {
474 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
481 base::Closure pending_callback
= base::Bind(
482 &CacheStorage::PendingClosure
, weak_factory_
.GetWeakPtr(), callback
);
483 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl
,
484 weak_factory_
.GetWeakPtr(),
488 int64
CacheStorage::MemoryBackedSize() const {
489 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
491 if (!initialized_
|| !memory_only_
)
495 for (auto& key_value
: cache_map_
) {
496 if (key_value
.second
)
497 sum
+= key_value
.second
->MemoryBackedSize();
502 void CacheStorage::StartAsyncOperationForTesting() {
503 scheduler_
->ScheduleOperation(base::Bind(&base::DoNothing
));
506 void CacheStorage::CompleteAsyncOperationForTesting() {
507 scheduler_
->CompleteOperationAndRunNext();
510 // Init is run lazily so that it is called on the proper MessageLoop.
511 void CacheStorage::LazyInit() {
512 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
513 DCHECK(!initialized_
);
518 DCHECK(!scheduler_
->ScheduledOperations());
520 initializing_
= true;
521 scheduler_
->ScheduleOperation(
522 base::Bind(&CacheStorage::LazyInitImpl
, weak_factory_
.GetWeakPtr()));
525 void CacheStorage::LazyInitImpl() {
526 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
527 DCHECK(!initialized_
);
528 DCHECK(initializing_
);
530 // 1. Get the list of cache names (async call)
531 // 2. For each cache name, load the cache (async call)
532 // 3. Once each load is complete, update the map variables.
533 // 4. Call the list of waiting callbacks.
535 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names(
536 new std::vector
<std::string
>());
538 cache_loader_
->LoadIndex(indexed_cache_names
.Pass(),
539 base::Bind(&CacheStorage::LazyInitDidLoadIndex
,
540 weak_factory_
.GetWeakPtr()));
543 void CacheStorage::LazyInitDidLoadIndex(
544 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names
) {
545 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
547 for (size_t i
= 0u, max
= indexed_cache_names
->size(); i
< max
; ++i
) {
548 cache_map_
.insert(std::make_pair(indexed_cache_names
->at(i
),
549 base::WeakPtr
<CacheStorageCache
>()));
550 ordered_cache_names_
.push_back(indexed_cache_names
->at(i
));
553 initializing_
= false;
556 scheduler_
->CompleteOperationAndRunNext();
559 void CacheStorage::OpenCacheImpl(const std::string
& cache_name
,
560 const CacheAndErrorCallback
& callback
) {
561 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
563 callback
.Run(cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
567 cache_loader_
->CreateCache(
568 cache_name
, base::Bind(&CacheStorage::CreateCacheDidCreateCache
,
569 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
572 void CacheStorage::CreateCacheDidCreateCache(
573 const std::string
& cache_name
,
574 const CacheAndErrorCallback
& callback
,
575 const scoped_refptr
<CacheStorageCache
>& cache
) {
576 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
579 callback
.Run(scoped_refptr
<CacheStorageCache
>(),
580 CACHE_STORAGE_ERROR_CLOSING
);
584 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
587 cache_map_
.insert(std::make_pair(cache_name
, cache
->AsWeakPtr()));
588 ordered_cache_names_
.push_back(cache_name
);
590 cache_loader_
->WriteIndex(
591 ordered_cache_names_
,
592 base::Bind(&CacheStorage::CreateCacheDidWriteIndex
,
593 weak_factory_
.GetWeakPtr(), callback
, cache
));
596 void CacheStorage::CreateCacheDidWriteIndex(
597 const CacheAndErrorCallback
& callback
,
598 const scoped_refptr
<CacheStorageCache
>& cache
,
600 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
603 // TODO(jkarlin): Handle !success.
605 callback
.Run(cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
608 void CacheStorage::HasCacheImpl(const std::string
& cache_name
,
609 const BoolAndErrorCallback
& callback
) {
610 bool has_cache
= cache_map_
.find(cache_name
) != cache_map_
.end();
612 callback
.Run(has_cache
, CACHE_STORAGE_ERROR_NO_ERROR
);
615 void CacheStorage::DeleteCacheImpl(const std::string
& cache_name
,
616 const BoolAndErrorCallback
& callback
) {
617 CacheMap::iterator it
= cache_map_
.find(cache_name
);
618 if (it
== cache_map_
.end()) {
619 callback
.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND
);
623 base::WeakPtr
<CacheStorageCache
> cache
= it
->second
;
624 cache_map_
.erase(it
);
626 // Delete the name from ordered_cache_names_.
627 StringVector::iterator iter
= std::find(
628 ordered_cache_names_
.begin(), ordered_cache_names_
.end(), cache_name
);
629 DCHECK(iter
!= ordered_cache_names_
.end());
630 ordered_cache_names_
.erase(iter
);
632 base::Closure closure
=
633 base::Bind(&CacheStorage::DeleteCacheDidClose
, weak_factory_
.GetWeakPtr(),
634 cache_name
, callback
, ordered_cache_names_
,
635 make_scoped_refptr(cache
.get()));
638 cache
->Close(closure
);
645 void CacheStorage::DeleteCacheDidClose(
646 const std::string
& cache_name
,
647 const BoolAndErrorCallback
& callback
,
648 const StringVector
& ordered_cache_names
,
649 const scoped_refptr
<CacheStorageCache
>& cache
/* might be null */) {
650 cache_loader_
->WriteIndex(
652 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex
,
653 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
656 void CacheStorage::DeleteCacheDidWriteIndex(
657 const std::string
& cache_name
,
658 const BoolAndErrorCallback
& callback
,
660 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
662 cache_loader_
->CleanUpDeletedCache(
663 cache_name
, base::Bind(&CacheStorage::DeleteCacheDidCleanUp
,
664 weak_factory_
.GetWeakPtr(), callback
));
667 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback
& callback
,
669 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
671 callback
.Run(true, CACHE_STORAGE_ERROR_NO_ERROR
);
674 void CacheStorage::EnumerateCachesImpl(
675 const StringsAndErrorCallback
& callback
) {
676 callback
.Run(ordered_cache_names_
, CACHE_STORAGE_ERROR_NO_ERROR
);
679 void CacheStorage::MatchCacheImpl(
680 const std::string
& cache_name
,
681 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
682 const CacheStorageCache::ResponseCallback
& callback
) {
683 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
686 callback
.Run(CacheStorageCache::ERROR_TYPE_NOT_FOUND
,
687 scoped_ptr
<ServiceWorkerResponse
>(),
688 scoped_ptr
<storage::BlobDataHandle
>());
692 // Pass the cache along to the callback to keep the cache open until match is
694 cache
->Match(request
.Pass(),
695 base::Bind(&CacheStorage::MatchCacheDidMatch
,
696 weak_factory_
.GetWeakPtr(), cache
, callback
));
699 void CacheStorage::MatchCacheDidMatch(
700 const scoped_refptr
<CacheStorageCache
>& cache
,
701 const CacheStorageCache::ResponseCallback
& callback
,
702 CacheStorageCache::ErrorType error
,
703 scoped_ptr
<ServiceWorkerResponse
> response
,
704 scoped_ptr
<storage::BlobDataHandle
> handle
) {
705 callback
.Run(error
, response
.Pass(), handle
.Pass());
708 void CacheStorage::MatchAllCachesImpl(
709 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
710 const CacheStorageCache::ResponseCallback
& callback
) {
711 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback_copy(
712 new CacheStorageCache::ResponseCallback(callback
));
714 CacheStorageCache::ResponseCallback
* callback_ptr
= callback_copy
.get();
715 base::Closure barrier_closure
=
716 base::BarrierClosure(ordered_cache_names_
.size(),
717 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll
,
718 weak_factory_
.GetWeakPtr(),
719 base::Passed(callback_copy
.Pass())));
721 for (const std::string
& cache_name
: ordered_cache_names_
) {
722 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
725 cache
->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request
)),
726 base::Bind(&CacheStorage::MatchAllCachesDidMatch
,
727 weak_factory_
.GetWeakPtr(), cache
, barrier_closure
,
732 void CacheStorage::MatchAllCachesDidMatch(
733 scoped_refptr
<CacheStorageCache
> cache
,
734 const base::Closure
& barrier_closure
,
735 CacheStorageCache::ResponseCallback
* callback
,
736 CacheStorageCache::ErrorType error
,
737 scoped_ptr
<ServiceWorkerResponse
> response
,
738 scoped_ptr
<storage::BlobDataHandle
> handle
) {
739 if (callback
->is_null() || error
== CacheStorageCache::ERROR_TYPE_NOT_FOUND
) {
740 barrier_closure
.Run();
743 callback
->Run(error
, response
.Pass(), handle
.Pass());
744 callback
->Reset(); // Only call the callback once.
746 barrier_closure
.Run();
749 void CacheStorage::MatchAllCachesDidMatchAll(
750 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback
) {
751 if (!callback
->is_null()) {
752 callback
->Run(CacheStorageCache::ERROR_TYPE_NOT_FOUND
,
753 scoped_ptr
<ServiceWorkerResponse
>(),
754 scoped_ptr
<storage::BlobDataHandle
>());
758 scoped_refptr
<CacheStorageCache
> CacheStorage::GetLoadedCache(
759 const std::string
& cache_name
) {
760 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
761 DCHECK(initialized_
);
763 CacheMap::iterator map_iter
= cache_map_
.find(cache_name
);
764 if (map_iter
== cache_map_
.end())
765 return scoped_refptr
<CacheStorageCache
>();
767 base::WeakPtr
<CacheStorageCache
> cache
= map_iter
->second
;
770 scoped_refptr
<CacheStorageCache
> new_cache
=
771 cache_loader_
->CreateCache(cache_name
);
772 map_iter
->second
= new_cache
->AsWeakPtr();
776 return make_scoped_refptr(cache
.get());
779 void CacheStorage::CloseAllCachesImpl(const base::Closure
& callback
) {
780 int live_cache_count
= 0;
781 for (const auto& key_value
: cache_map_
) {
782 if (key_value
.second
)
783 live_cache_count
+= 1;
786 if (live_cache_count
== 0) {
791 // The closure might modify this object so delay calling it until after
792 // iterating through cache_map_ by adding one to the barrier.
793 base::Closure barrier_closure
=
794 base::BarrierClosure(live_cache_count
+ 1, base::Bind(callback
));
796 for (auto& key_value
: cache_map_
) {
797 if (key_value
.second
) {
798 key_value
.second
->Close(base::Bind(
799 CloseAllCachesDidCloseCache
,
800 make_scoped_refptr(key_value
.second
.get()), barrier_closure
));
804 barrier_closure
.Run();
807 void CacheStorage::PendingClosure(const base::Closure
& callback
) {
808 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
812 scheduler_
->CompleteOperationAndRunNext();
815 void CacheStorage::PendingBoolAndErrorCallback(
816 const BoolAndErrorCallback
& callback
,
818 CacheStorageError error
) {
819 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
821 callback
.Run(found
, error
);
823 scheduler_
->CompleteOperationAndRunNext();
826 void CacheStorage::PendingCacheAndErrorCallback(
827 const CacheAndErrorCallback
& callback
,
828 const scoped_refptr
<CacheStorageCache
>& cache
,
829 CacheStorageError error
) {
830 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
832 callback
.Run(cache
, error
);
834 scheduler_
->CompleteOperationAndRunNext();
837 void CacheStorage::PendingStringsAndErrorCallback(
838 const StringsAndErrorCallback
& callback
,
839 const StringVector
& strings
,
840 CacheStorageError error
) {
841 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
843 callback
.Run(strings
, error
);
845 scheduler_
->CompleteOperationAndRunNext();
848 void CacheStorage::PendingResponseCallback(
849 const CacheStorageCache::ResponseCallback
& callback
,
850 CacheStorageCache::ErrorType error
,
851 scoped_ptr
<ServiceWorkerResponse
> response
,
852 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
853 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
855 callback
.Run(error
, response
.Pass(), blob_data_handle
.Pass());
857 scheduler_
->CompleteOperationAndRunNext();
860 } // namespace content