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/sha1.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "content/browser/cache_storage/cache_storage.pb.h"
22 #include "content/browser/cache_storage/cache_storage_cache.h"
23 #include "content/browser/cache_storage/cache_storage_scheduler.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "net/base/directory_lister.h"
26 #include "net/base/net_errors.h"
27 #include "net/url_request/url_request_context_getter.h"
28 #include "storage/browser/blob/blob_storage_context.h"
29 #include "storage/browser/quota/quota_manager_proxy.h"
35 void CloseAllCachesDidCloseCache(const scoped_refptr
<CacheStorageCache
>& cache
,
36 const base::Closure
& barrier_closure
) {
37 barrier_closure
.Run();
42 const char CacheStorage::kIndexFileName
[] = "index.txt";
44 // Handles the loading and clean up of CacheStorageCache objects. The
45 // callback of every public method is guaranteed to be called.
46 class CacheStorage::CacheLoader
{
48 typedef base::Callback
<void(const scoped_refptr
<CacheStorageCache
>&)>
50 typedef base::Callback
<void(bool)> BoolCallback
;
51 typedef base::Callback
<void(scoped_ptr
<std::vector
<std::string
>>)>
55 base::SequencedTaskRunner
* cache_task_runner
,
56 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
57 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
58 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
60 : cache_task_runner_(cache_task_runner
),
61 request_context_getter_(request_context_getter
),
62 quota_manager_proxy_(quota_manager_proxy
),
63 blob_context_(blob_context
),
65 DCHECK(!origin_
.is_empty());
68 virtual ~CacheLoader() {}
70 // Creates a CacheStorageCache with the given name. It does not attempt to
71 // load the backend, that happens lazily when the cache is used.
72 virtual scoped_refptr
<CacheStorageCache
> CreateCache(
73 const std::string
& cache_name
) = 0;
75 // Deletes any pre-existing cache of the same name and then loads it.
76 virtual void CreateCache(const std::string
& cache_name
,
77 const CacheCallback
& callback
) = 0;
79 // After the backend has been deleted, do any extra house keeping such as
80 // removing the cache's directory.
81 virtual void CleanUpDeletedCache(const std::string
& key
,
82 const BoolCallback
& callback
) = 0;
84 // Writes the cache names (and sizes) to disk if applicable.
85 virtual void WriteIndex(const StringVector
& cache_names
,
86 const BoolCallback
& callback
) = 0;
88 // Loads the cache names from disk if applicable.
89 virtual void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
90 const StringVectorCallback
& callback
) = 0;
93 scoped_refptr
<base::SequencedTaskRunner
> cache_task_runner_
;
94 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
95 scoped_refptr
<storage::QuotaManagerProxy
> quota_manager_proxy_
;
96 base::WeakPtr
<storage::BlobStorageContext
> blob_context_
;
100 // Creates memory-only ServiceWorkerCaches. Because these caches have no
101 // persistent storage it is not safe to free them from memory if they might be
102 // used again. Therefore this class holds a reference to each cache until the
104 class CacheStorage::MemoryLoader
: public CacheStorage::CacheLoader
{
107 base::SequencedTaskRunner
* cache_task_runner
,
108 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
109 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
110 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
112 : CacheLoader(cache_task_runner
,
118 scoped_refptr
<CacheStorageCache
> CreateCache(
119 const std::string
& cache_name
) override
{
120 return CacheStorageCache::CreateMemoryCache(
121 origin_
, request_context_getter_
, quota_manager_proxy_
, blob_context_
);
124 void CreateCache(const std::string
& cache_name
,
125 const CacheCallback
& callback
) override
{
126 scoped_refptr
<CacheStorageCache
> cache
= CreateCache(cache_name
);
127 cache_refs_
.insert(std::make_pair(cache_name
, cache
));
131 void CleanUpDeletedCache(const std::string
& cache_name
,
132 const BoolCallback
& callback
) override
{
133 CacheRefMap::iterator it
= cache_refs_
.find(cache_name
);
134 DCHECK(it
!= cache_refs_
.end());
135 cache_refs_
.erase(it
);
139 void WriteIndex(const StringVector
& cache_names
,
140 const BoolCallback
& callback
) override
{
144 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> cache_names
,
145 const StringVectorCallback
& callback
) override
{
146 callback
.Run(cache_names
.Pass());
150 typedef std::map
<std::string
, scoped_refptr
<CacheStorageCache
>> CacheRefMap
;
151 ~MemoryLoader() override
{}
153 // Keep a reference to each cache to ensure that it's not freed before the
154 // client calls CacheStorage::Delete or the CacheStorage is
156 CacheRefMap cache_refs_
;
159 class CacheStorage::SimpleCacheLoader
: public CacheStorage::CacheLoader
{
162 const base::FilePath
& origin_path
,
163 base::SequencedTaskRunner
* cache_task_runner
,
164 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
165 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
166 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
168 : CacheLoader(cache_task_runner
,
173 origin_path_(origin_path
),
174 weak_ptr_factory_(this) {}
176 scoped_refptr
<CacheStorageCache
> CreateCache(
177 const std::string
& cache_name
) override
{
178 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
180 return CacheStorageCache::CreatePersistentCache(
181 origin_
, CreatePersistentCachePath(origin_path_
, cache_name
),
182 request_context_getter_
, quota_manager_proxy_
, blob_context_
);
185 void CreateCache(const std::string
& cache_name
,
186 const CacheCallback
& callback
) override
{
187 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
189 // 1. Delete the cache's directory if it exists.
190 // (CreateCacheDeleteFilesInPool)
191 // 2. Load the cache. (LoadCreateDirectoryInPool)
193 base::FilePath cache_path
=
194 CreatePersistentCachePath(origin_path_
, cache_name
);
196 PostTaskAndReplyWithResult(
197 cache_task_runner_
.get(), FROM_HERE
,
198 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool
, cache_path
),
199 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir
, cache_name
,
200 callback
, weak_ptr_factory_
.GetWeakPtr()));
203 static bool CreateCachePrepDirInPool(const base::FilePath
& cache_path
) {
204 if (base::PathExists(cache_path
))
205 base::DeleteFile(cache_path
, /* recursive */ true);
206 return base::CreateDirectory(cache_path
);
209 static void CreateCachePreppedDir(const std::string
& cache_name
,
210 const CacheCallback
& callback
,
211 base::WeakPtr
<SimpleCacheLoader
> loader
,
213 if (!success
|| !loader
) {
214 callback
.Run(scoped_refptr
<CacheStorageCache
>());
218 callback
.Run(loader
->CreateCache(cache_name
));
221 void CleanUpDeletedCache(const std::string
& cache_name
,
222 const BoolCallback
& callback
) override
{
223 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
225 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
227 base::FilePath cache_path
=
228 CreatePersistentCachePath(origin_path_
, cache_name
);
229 cache_task_runner_
->PostTask(
231 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool
, cache_path
,
232 callback
, base::ThreadTaskRunnerHandle::Get()));
235 static void CleanUpDeleteCacheDirInPool(
236 const base::FilePath
& cache_path
,
237 const BoolCallback
& callback
,
238 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
239 bool rv
= base::DeleteFile(cache_path
, true);
240 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
243 void WriteIndex(const StringVector
& cache_names
,
244 const BoolCallback
& callback
) override
{
245 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
247 // 1. Create the index file as a string. (WriteIndex)
248 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
250 CacheStorageIndex index
;
251 index
.set_origin(origin_
.spec());
253 for (size_t i
= 0u, max
= cache_names
.size(); i
< max
; ++i
) {
254 CacheStorageIndex::Cache
* index_cache
= index
.add_cache();
255 index_cache
->set_name(cache_names
[i
]);
258 std::string serialized
;
259 bool success
= index
.SerializeToString(&serialized
);
262 base::FilePath tmp_path
= origin_path_
.AppendASCII("index.txt.tmp");
263 base::FilePath index_path
=
264 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
266 cache_task_runner_
->PostTask(
267 FROM_HERE
, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool
,
268 tmp_path
, index_path
, serialized
, callback
,
269 base::ThreadTaskRunnerHandle::Get()));
272 static void WriteIndexWriteToFileInPool(
273 const base::FilePath
& tmp_path
,
274 const base::FilePath
& index_path
,
275 const std::string
& data
,
276 const BoolCallback
& callback
,
277 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
278 int bytes_written
= base::WriteFile(tmp_path
, data
.c_str(), data
.size());
279 if (bytes_written
!= implicit_cast
<int>(data
.size())) {
280 base::DeleteFile(tmp_path
, /* recursive */ false);
281 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, false));
284 // Atomically rename the temporary index file to become the real one.
285 bool rv
= base::ReplaceFile(tmp_path
, index_path
, NULL
);
286 original_task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, rv
));
289 void LoadIndex(scoped_ptr
<std::vector
<std::string
>> names
,
290 const StringVectorCallback
& callback
) override
{
291 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
293 // 1. Read the file from disk. (LoadIndexReadFileInPool)
294 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
296 base::FilePath index_path
=
297 origin_path_
.AppendASCII(CacheStorage::kIndexFileName
);
299 cache_task_runner_
->PostTask(
300 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool
,
301 index_path
, base::Passed(names
.Pass()), callback
,
302 base::ThreadTaskRunnerHandle::Get()));
305 static void LoadIndexReadFileInPool(
306 const base::FilePath
& index_path
,
307 scoped_ptr
<std::vector
<std::string
>> names
,
308 const StringVectorCallback
& callback
,
309 const scoped_refptr
<base::SingleThreadTaskRunner
>& original_task_runner
) {
311 base::ReadFileToString(index_path
, &body
);
313 original_task_runner
->PostTask(
314 FROM_HERE
, base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile
,
315 base::Passed(names
.Pass()), callback
, body
));
318 static void LoadIndexDidReadFile(scoped_ptr
<std::vector
<std::string
>> names
,
319 const StringVectorCallback
& callback
,
320 const std::string
& serialized
) {
321 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
323 CacheStorageIndex index
;
324 if (index
.ParseFromString(serialized
)) {
325 for (int i
= 0, max
= index
.cache_size(); i
< max
; ++i
) {
326 const CacheStorageIndex::Cache
& cache
= index
.cache(i
);
327 names
->push_back(cache
.name());
331 // TODO(jkarlin): Delete caches that are in the directory and not returned
333 callback
.Run(names
.Pass());
337 ~SimpleCacheLoader() override
{}
339 static std::string
HexedHash(const std::string
& value
) {
340 std::string value_hash
= base::SHA1HashString(value
);
341 std::string valued_hexed_hash
= base::StringToLowerASCII(
342 base::HexEncode(value_hash
.c_str(), value_hash
.length()));
343 return valued_hexed_hash
;
346 static base::FilePath
CreatePersistentCachePath(
347 const base::FilePath
& origin_path
,
348 const std::string
& cache_name
) {
349 return origin_path
.AppendASCII(HexedHash(cache_name
));
352 const base::FilePath origin_path_
;
354 base::WeakPtrFactory
<SimpleCacheLoader
> weak_ptr_factory_
;
357 CacheStorage::CacheStorage(
358 const base::FilePath
& path
,
360 base::SequencedTaskRunner
* cache_task_runner
,
361 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
362 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
363 base::WeakPtr
<storage::BlobStorageContext
> blob_context
,
365 : initialized_(false),
366 initializing_(false),
367 scheduler_(new CacheStorageScheduler()),
369 cache_task_runner_(cache_task_runner
),
370 memory_only_(memory_only
),
371 weak_factory_(this) {
373 cache_loader_
.reset(new MemoryLoader(cache_task_runner_
.get(),
374 request_context
, quota_manager_proxy
,
375 blob_context
, origin
));
377 cache_loader_
.reset(new SimpleCacheLoader(
378 origin_path_
, cache_task_runner_
.get(), request_context
,
379 quota_manager_proxy
, blob_context
, origin
));
382 CacheStorage::~CacheStorage() {
385 void CacheStorage::OpenCache(const std::string
& cache_name
,
386 const CacheAndErrorCallback
& callback
) {
387 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
392 CacheAndErrorCallback pending_callback
=
393 base::Bind(&CacheStorage::PendingCacheAndErrorCallback
,
394 weak_factory_
.GetWeakPtr(), callback
);
395 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::OpenCacheImpl
,
396 weak_factory_
.GetWeakPtr(),
397 cache_name
, pending_callback
));
400 void CacheStorage::HasCache(const std::string
& cache_name
,
401 const BoolAndErrorCallback
& callback
) {
402 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
407 BoolAndErrorCallback pending_callback
=
408 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
409 weak_factory_
.GetWeakPtr(), callback
);
410 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::HasCacheImpl
,
411 weak_factory_
.GetWeakPtr(),
412 cache_name
, pending_callback
));
415 void CacheStorage::DeleteCache(const std::string
& cache_name
,
416 const BoolAndErrorCallback
& callback
) {
417 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
422 BoolAndErrorCallback pending_callback
=
423 base::Bind(&CacheStorage::PendingBoolAndErrorCallback
,
424 weak_factory_
.GetWeakPtr(), callback
);
425 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::DeleteCacheImpl
,
426 weak_factory_
.GetWeakPtr(),
427 cache_name
, pending_callback
));
430 void CacheStorage::EnumerateCaches(const StringsAndErrorCallback
& callback
) {
431 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
436 StringsAndErrorCallback pending_callback
=
437 base::Bind(&CacheStorage::PendingStringsAndErrorCallback
,
438 weak_factory_
.GetWeakPtr(), callback
);
439 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::EnumerateCachesImpl
,
440 weak_factory_
.GetWeakPtr(),
444 void CacheStorage::MatchCache(
445 const std::string
& cache_name
,
446 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
447 const CacheStorageCache::ResponseCallback
& callback
) {
448 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
453 CacheStorageCache::ResponseCallback pending_callback
=
454 base::Bind(&CacheStorage::PendingResponseCallback
,
455 weak_factory_
.GetWeakPtr(), callback
);
456 scheduler_
->ScheduleOperation(
457 base::Bind(&CacheStorage::MatchCacheImpl
, weak_factory_
.GetWeakPtr(),
458 cache_name
, base::Passed(request
.Pass()), pending_callback
));
461 void CacheStorage::MatchAllCaches(
462 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
463 const CacheStorageCache::ResponseCallback
& callback
) {
464 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
469 CacheStorageCache::ResponseCallback pending_callback
=
470 base::Bind(&CacheStorage::PendingResponseCallback
,
471 weak_factory_
.GetWeakPtr(), callback
);
472 scheduler_
->ScheduleOperation(
473 base::Bind(&CacheStorage::MatchAllCachesImpl
, weak_factory_
.GetWeakPtr(),
474 base::Passed(request
.Pass()), pending_callback
));
477 void CacheStorage::CloseAllCaches(const base::Closure
& callback
) {
478 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
485 base::Closure pending_callback
= base::Bind(
486 &CacheStorage::PendingClosure
, weak_factory_
.GetWeakPtr(), callback
);
487 scheduler_
->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl
,
488 weak_factory_
.GetWeakPtr(),
492 int64
CacheStorage::MemoryBackedSize() const {
493 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
495 if (!initialized_
|| !memory_only_
)
499 for (auto& key_value
: cache_map_
) {
500 if (key_value
.second
)
501 sum
+= key_value
.second
->MemoryBackedSize();
506 void CacheStorage::StartAsyncOperationForTesting() {
507 scheduler_
->ScheduleOperation(base::Bind(&base::DoNothing
));
510 void CacheStorage::CompleteAsyncOperationForTesting() {
511 scheduler_
->CompleteOperationAndRunNext();
514 // Init is run lazily so that it is called on the proper MessageLoop.
515 void CacheStorage::LazyInit() {
516 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
517 DCHECK(!initialized_
);
522 DCHECK(!scheduler_
->ScheduledOperations());
524 initializing_
= true;
525 scheduler_
->ScheduleOperation(
526 base::Bind(&CacheStorage::LazyInitImpl
, weak_factory_
.GetWeakPtr()));
529 void CacheStorage::LazyInitImpl() {
530 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
531 DCHECK(!initialized_
);
532 DCHECK(initializing_
);
534 // 1. Get the list of cache names (async call)
535 // 2. For each cache name, load the cache (async call)
536 // 3. Once each load is complete, update the map variables.
537 // 4. Call the list of waiting callbacks.
539 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names(
540 new std::vector
<std::string
>());
542 cache_loader_
->LoadIndex(indexed_cache_names
.Pass(),
543 base::Bind(&CacheStorage::LazyInitDidLoadIndex
,
544 weak_factory_
.GetWeakPtr()));
547 void CacheStorage::LazyInitDidLoadIndex(
548 scoped_ptr
<std::vector
<std::string
>> indexed_cache_names
) {
549 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
551 for (size_t i
= 0u, max
= indexed_cache_names
->size(); i
< max
; ++i
) {
552 cache_map_
.insert(std::make_pair(indexed_cache_names
->at(i
),
553 base::WeakPtr
<CacheStorageCache
>()));
554 ordered_cache_names_
.push_back(indexed_cache_names
->at(i
));
557 initializing_
= false;
560 scheduler_
->CompleteOperationAndRunNext();
563 void CacheStorage::OpenCacheImpl(const std::string
& cache_name
,
564 const CacheAndErrorCallback
& callback
) {
565 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
567 callback
.Run(cache
, CACHE_STORAGE_OK
);
571 cache_loader_
->CreateCache(
572 cache_name
, base::Bind(&CacheStorage::CreateCacheDidCreateCache
,
573 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
576 void CacheStorage::CreateCacheDidCreateCache(
577 const std::string
& cache_name
,
578 const CacheAndErrorCallback
& callback
,
579 const scoped_refptr
<CacheStorageCache
>& cache
) {
580 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
582 UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
586 callback
.Run(scoped_refptr
<CacheStorageCache
>(),
587 CACHE_STORAGE_ERROR_STORAGE
);
591 cache_map_
.insert(std::make_pair(cache_name
, cache
->AsWeakPtr()));
592 ordered_cache_names_
.push_back(cache_name
);
594 cache_loader_
->WriteIndex(
595 ordered_cache_names_
,
596 base::Bind(&CacheStorage::CreateCacheDidWriteIndex
,
597 weak_factory_
.GetWeakPtr(), callback
, cache
));
600 void CacheStorage::CreateCacheDidWriteIndex(
601 const CacheAndErrorCallback
& callback
,
602 const scoped_refptr
<CacheStorageCache
>& cache
,
604 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
607 // TODO(jkarlin): Handle !success.
609 callback
.Run(cache
, CACHE_STORAGE_OK
);
612 void CacheStorage::HasCacheImpl(const std::string
& cache_name
,
613 const BoolAndErrorCallback
& callback
) {
614 bool has_cache
= cache_map_
.find(cache_name
) != cache_map_
.end();
616 callback
.Run(has_cache
, CACHE_STORAGE_OK
);
619 void CacheStorage::DeleteCacheImpl(const std::string
& cache_name
,
620 const BoolAndErrorCallback
& callback
) {
621 CacheMap::iterator it
= cache_map_
.find(cache_name
);
622 if (it
== cache_map_
.end()) {
623 callback
.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND
);
627 base::WeakPtr
<CacheStorageCache
> cache
= it
->second
;
628 cache_map_
.erase(it
);
630 // Delete the name from ordered_cache_names_.
631 StringVector::iterator iter
= std::find(
632 ordered_cache_names_
.begin(), ordered_cache_names_
.end(), cache_name
);
633 DCHECK(iter
!= ordered_cache_names_
.end());
634 ordered_cache_names_
.erase(iter
);
636 base::Closure closure
=
637 base::Bind(&CacheStorage::DeleteCacheDidClose
, weak_factory_
.GetWeakPtr(),
638 cache_name
, callback
, ordered_cache_names_
,
639 make_scoped_refptr(cache
.get()));
642 cache
->Close(closure
);
649 void CacheStorage::DeleteCacheDidClose(
650 const std::string
& cache_name
,
651 const BoolAndErrorCallback
& callback
,
652 const StringVector
& ordered_cache_names
,
653 const scoped_refptr
<CacheStorageCache
>& cache
/* might be null */) {
654 cache_loader_
->WriteIndex(
656 base::Bind(&CacheStorage::DeleteCacheDidWriteIndex
,
657 weak_factory_
.GetWeakPtr(), cache_name
, callback
));
660 void CacheStorage::DeleteCacheDidWriteIndex(
661 const std::string
& cache_name
,
662 const BoolAndErrorCallback
& callback
,
664 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
666 cache_loader_
->CleanUpDeletedCache(
667 cache_name
, base::Bind(&CacheStorage::DeleteCacheDidCleanUp
,
668 weak_factory_
.GetWeakPtr(), callback
));
671 void CacheStorage::DeleteCacheDidCleanUp(const BoolAndErrorCallback
& callback
,
673 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
675 callback
.Run(true, CACHE_STORAGE_OK
);
678 void CacheStorage::EnumerateCachesImpl(
679 const StringsAndErrorCallback
& callback
) {
680 callback
.Run(ordered_cache_names_
, CACHE_STORAGE_OK
);
683 void CacheStorage::MatchCacheImpl(
684 const std::string
& cache_name
,
685 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
686 const CacheStorageCache::ResponseCallback
& callback
) {
687 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
690 callback
.Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
691 scoped_ptr
<ServiceWorkerResponse
>(),
692 scoped_ptr
<storage::BlobDataHandle
>());
696 // Pass the cache along to the callback to keep the cache open until match is
698 cache
->Match(request
.Pass(),
699 base::Bind(&CacheStorage::MatchCacheDidMatch
,
700 weak_factory_
.GetWeakPtr(), cache
, callback
));
703 void CacheStorage::MatchCacheDidMatch(
704 const scoped_refptr
<CacheStorageCache
>& cache
,
705 const CacheStorageCache::ResponseCallback
& callback
,
706 CacheStorageError error
,
707 scoped_ptr
<ServiceWorkerResponse
> response
,
708 scoped_ptr
<storage::BlobDataHandle
> handle
) {
709 callback
.Run(error
, response
.Pass(), handle
.Pass());
712 void CacheStorage::MatchAllCachesImpl(
713 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
714 const CacheStorageCache::ResponseCallback
& callback
) {
715 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback_copy(
716 new CacheStorageCache::ResponseCallback(callback
));
718 CacheStorageCache::ResponseCallback
* callback_ptr
= callback_copy
.get();
719 base::Closure barrier_closure
=
720 base::BarrierClosure(ordered_cache_names_
.size(),
721 base::Bind(&CacheStorage::MatchAllCachesDidMatchAll
,
722 weak_factory_
.GetWeakPtr(),
723 base::Passed(callback_copy
.Pass())));
725 for (const std::string
& cache_name
: ordered_cache_names_
) {
726 scoped_refptr
<CacheStorageCache
> cache
= GetLoadedCache(cache_name
);
729 cache
->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request
)),
730 base::Bind(&CacheStorage::MatchAllCachesDidMatch
,
731 weak_factory_
.GetWeakPtr(), cache
, barrier_closure
,
736 void CacheStorage::MatchAllCachesDidMatch(
737 scoped_refptr
<CacheStorageCache
> cache
,
738 const base::Closure
& barrier_closure
,
739 CacheStorageCache::ResponseCallback
* callback
,
740 CacheStorageError error
,
741 scoped_ptr
<ServiceWorkerResponse
> response
,
742 scoped_ptr
<storage::BlobDataHandle
> handle
) {
743 if (callback
->is_null() || error
== CACHE_STORAGE_ERROR_NOT_FOUND
) {
744 barrier_closure
.Run();
747 callback
->Run(error
, response
.Pass(), handle
.Pass());
748 callback
->Reset(); // Only call the callback once.
750 barrier_closure
.Run();
753 void CacheStorage::MatchAllCachesDidMatchAll(
754 scoped_ptr
<CacheStorageCache::ResponseCallback
> callback
) {
755 if (!callback
->is_null()) {
756 callback
->Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
757 scoped_ptr
<ServiceWorkerResponse
>(),
758 scoped_ptr
<storage::BlobDataHandle
>());
762 scoped_refptr
<CacheStorageCache
> CacheStorage::GetLoadedCache(
763 const std::string
& cache_name
) {
764 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
765 DCHECK(initialized_
);
767 CacheMap::iterator map_iter
= cache_map_
.find(cache_name
);
768 if (map_iter
== cache_map_
.end())
769 return scoped_refptr
<CacheStorageCache
>();
771 base::WeakPtr
<CacheStorageCache
> cache
= map_iter
->second
;
774 scoped_refptr
<CacheStorageCache
> new_cache
=
775 cache_loader_
->CreateCache(cache_name
);
776 map_iter
->second
= new_cache
->AsWeakPtr();
780 return make_scoped_refptr(cache
.get());
783 void CacheStorage::CloseAllCachesImpl(const base::Closure
& callback
) {
784 int live_cache_count
= 0;
785 for (const auto& key_value
: cache_map_
) {
786 if (key_value
.second
)
787 live_cache_count
+= 1;
790 if (live_cache_count
== 0) {
795 // The closure might modify this object so delay calling it until after
796 // iterating through cache_map_ by adding one to the barrier.
797 base::Closure barrier_closure
=
798 base::BarrierClosure(live_cache_count
+ 1, base::Bind(callback
));
800 for (auto& key_value
: cache_map_
) {
801 if (key_value
.second
) {
802 key_value
.second
->Close(base::Bind(
803 CloseAllCachesDidCloseCache
,
804 make_scoped_refptr(key_value
.second
.get()), barrier_closure
));
808 barrier_closure
.Run();
811 void CacheStorage::PendingClosure(const base::Closure
& callback
) {
812 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
816 scheduler_
->CompleteOperationAndRunNext();
819 void CacheStorage::PendingBoolAndErrorCallback(
820 const BoolAndErrorCallback
& callback
,
822 CacheStorageError error
) {
823 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
825 callback
.Run(found
, error
);
827 scheduler_
->CompleteOperationAndRunNext();
830 void CacheStorage::PendingCacheAndErrorCallback(
831 const CacheAndErrorCallback
& callback
,
832 const scoped_refptr
<CacheStorageCache
>& cache
,
833 CacheStorageError error
) {
834 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
836 callback
.Run(cache
, error
);
838 scheduler_
->CompleteOperationAndRunNext();
841 void CacheStorage::PendingStringsAndErrorCallback(
842 const StringsAndErrorCallback
& callback
,
843 const StringVector
& strings
,
844 CacheStorageError error
) {
845 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
847 callback
.Run(strings
, error
);
849 scheduler_
->CompleteOperationAndRunNext();
852 void CacheStorage::PendingResponseCallback(
853 const CacheStorageCache::ResponseCallback
& callback
,
854 CacheStorageError error
,
855 scoped_ptr
<ServiceWorkerResponse
> response
,
856 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
857 base::WeakPtr
<CacheStorage
> cache_storage
= weak_factory_
.GetWeakPtr();
859 callback
.Run(error
, response
.Pass(), blob_data_handle
.Pass());
861 scheduler_
->CompleteOperationAndRunNext();
864 } // namespace content