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.
4
5 #include "content/browser/service_worker/service_worker_cache_storage.h"
6
7 #include <string>
8
9 #include "base/files/file_util.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/sha1.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "content/browser/service_worker/service_worker_cache.h"
17 #include "content/browser/service_worker/service_worker_cache.pb.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/base/directory_lister.h"
20 #include "net/base/net_errors.h"
21 #include "storage/browser/blob/blob_storage_context.h"
22
23 namespace content {
24
25
26 // Handles the loading and clean up of ServiceWorkerCache objects. The
27 // callback of every public method is guaranteed to be called.
28 class ServiceWorkerCacheStorage::CacheLoader {
29 public:
30 typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)>
31 CacheCallback;
32 typedef base::Callback<void(bool)> BoolCallback;
33 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
34 StringVectorCallback;
35
CacheLoader(base::SequencedTaskRunner * cache_task_runner,net::URLRequestContext * request_context,base::WeakPtr<storage::BlobStorageContext> blob_context)36 CacheLoader(base::SequencedTaskRunner* cache_task_runner,
37 net::URLRequestContext* request_context,
38 base::WeakPtr<storage::BlobStorageContext> blob_context)
39 : cache_task_runner_(cache_task_runner),
40 request_context_(request_context),
41 blob_context_(blob_context) {}
42
~CacheLoader()43 virtual ~CacheLoader() {}
44
45 // Creates a ServiceWorkerCache with the given name. It does not attempt to
46 // load the backend, that happens lazily when the cache is used.
47 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
48 const std::string& cache_name) = 0;
49
50 // Deletes any pre-existing cache of the same name and then loads it.
51 virtual void CreateCache(const std::string& cache_name,
52 const CacheCallback& callback) = 0;
53
54 // After the backend has been deleted, do any extra house keeping such as
55 // removing the cache's directory.
56 virtual void CleanUpDeletedCache(const std::string& key,
57 const BoolCallback& callback) = 0;
58
59 // Writes the cache names (and sizes) to disk if applicable.
60 virtual void WriteIndex(const StringVector& cache_names,
61 const BoolCallback& callback) = 0;
62
63 // Loads the cache names from disk if applicable.
64 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
65 const StringVectorCallback& callback) = 0;
66
67 protected:
68 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
69 net::URLRequestContext* request_context_;
70 base::WeakPtr<storage::BlobStorageContext> blob_context_;
71 };
72
73 // Creates memory-only ServiceWorkerCaches. Because these caches have no
74 // persistent storage it is not safe to free them from memory if they might be
75 // used again. Therefore this class holds a reference to each cache until the
76 // cache is deleted.
77 class ServiceWorkerCacheStorage::MemoryLoader
78 : public ServiceWorkerCacheStorage::CacheLoader {
79 public:
MemoryLoader(base::SequencedTaskRunner * cache_task_runner,net::URLRequestContext * request_context,base::WeakPtr<storage::BlobStorageContext> blob_context)80 MemoryLoader(base::SequencedTaskRunner* cache_task_runner,
81 net::URLRequestContext* request_context,
82 base::WeakPtr<storage::BlobStorageContext> blob_context)
83 : CacheLoader(cache_task_runner, request_context, blob_context) {}
84
CreateServiceWorkerCache(const std::string & cache_name)85 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
86 const std::string& cache_name) OVERRIDE {
87 return ServiceWorkerCache::CreateMemoryCache(request_context_,
88 blob_context_);
89 }
90
CreateCache(const std::string & cache_name,const CacheCallback & callback)91 virtual void CreateCache(const std::string& cache_name,
92 const CacheCallback& callback) OVERRIDE {
93 scoped_refptr<ServiceWorkerCache> cache =
94 ServiceWorkerCache::CreateMemoryCache(request_context_, blob_context_);
95 cache_refs_.insert(std::make_pair(cache_name, cache));
96 callback.Run(cache);
97 }
98
CleanUpDeletedCache(const std::string & cache_name,const BoolCallback & callback)99 virtual void CleanUpDeletedCache(const std::string& cache_name,
100 const BoolCallback& callback) OVERRIDE {
101 CacheRefMap::iterator it = cache_refs_.find(cache_name);
102 DCHECK(it != cache_refs_.end());
103 cache_refs_.erase(it);
104 callback.Run(true);
105 }
106
WriteIndex(const StringVector & cache_names,const BoolCallback & callback)107 virtual void WriteIndex(const StringVector& cache_names,
108 const BoolCallback& callback) OVERRIDE {
109 callback.Run(false);
110 }
111
LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,const StringVectorCallback & callback)112 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
113 const StringVectorCallback& callback) OVERRIDE {
114 callback.Run(cache_names.Pass());
115 }
116
117 private:
118 typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap;
~MemoryLoader()119 virtual ~MemoryLoader() {}
120
121 // Keep a reference to each cache to ensure that it's not freed before the
122 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
123 // freed.
124 CacheRefMap cache_refs_;
125 };
126
127 class ServiceWorkerCacheStorage::SimpleCacheLoader
128 : public ServiceWorkerCacheStorage::CacheLoader {
129 public:
SimpleCacheLoader(const base::FilePath & origin_path,base::SequencedTaskRunner * cache_task_runner,net::URLRequestContext * request_context,base::WeakPtr<storage::BlobStorageContext> blob_context)130 SimpleCacheLoader(const base::FilePath& origin_path,
131 base::SequencedTaskRunner* cache_task_runner,
132 net::URLRequestContext* request_context,
133 base::WeakPtr<storage::BlobStorageContext> blob_context)
134 : CacheLoader(cache_task_runner, request_context, blob_context),
135 origin_path_(origin_path),
136 weak_ptr_factory_(this) {}
137
CreateServiceWorkerCache(const std::string & cache_name)138 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
139 const std::string& cache_name) OVERRIDE {
140 DCHECK_CURRENTLY_ON(BrowserThread::IO);
141
142 return ServiceWorkerCache::CreatePersistentCache(
143 CreatePersistentCachePath(origin_path_, cache_name),
144 request_context_,
145 blob_context_);
146 }
147
CreateCache(const std::string & cache_name,const CacheCallback & callback)148 virtual void CreateCache(const std::string& cache_name,
149 const CacheCallback& callback) OVERRIDE {
150 DCHECK_CURRENTLY_ON(BrowserThread::IO);
151
152 // 1. Delete the cache's directory if it exists.
153 // (CreateCacheDeleteFilesInPool)
154 // 2. Load the cache. (LoadCreateDirectoryInPool)
155
156 base::FilePath cache_path =
157 CreatePersistentCachePath(origin_path_, cache_name);
158
159 PostTaskAndReplyWithResult(
160 cache_task_runner_.get(),
161 FROM_HERE,
162 base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
163 base::Bind(&SimpleCacheLoader::CreateCachePreppedDir,
164 cache_name,
165 callback,
166 weak_ptr_factory_.GetWeakPtr()));
167 }
168
CreateCachePrepDirInPool(const base::FilePath & cache_path)169 static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
170 if (base::PathExists(cache_path))
171 base::DeleteFile(cache_path, /* recursive */ true);
172 return base::CreateDirectory(cache_path);
173 }
174
CreateCachePreppedDir(const std::string & cache_name,const CacheCallback & callback,base::WeakPtr<SimpleCacheLoader> loader,bool success)175 static void CreateCachePreppedDir(const std::string& cache_name,
176 const CacheCallback& callback,
177 base::WeakPtr<SimpleCacheLoader> loader,
178 bool success) {
179 if (!success || !loader) {
180 callback.Run(scoped_refptr<ServiceWorkerCache>());
181 return;
182 }
183
184 callback.Run(loader->CreateServiceWorkerCache(cache_name));
185 }
186
CleanUpDeletedCache(const std::string & cache_name,const BoolCallback & callback)187 virtual void CleanUpDeletedCache(const std::string& cache_name,
188 const BoolCallback& callback) OVERRIDE {
189 DCHECK_CURRENTLY_ON(BrowserThread::IO);
190
191 // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
192
193 base::FilePath cache_path =
194 CreatePersistentCachePath(origin_path_, cache_name);
195 cache_task_runner_->PostTask(
196 FROM_HERE,
197 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
198 cache_path,
199 callback,
200 base::MessageLoopProxy::current()));
201 }
202
CleanUpDeleteCacheDirInPool(const base::FilePath & cache_path,const BoolCallback & callback,const scoped_refptr<base::MessageLoopProxy> & original_loop)203 static void CleanUpDeleteCacheDirInPool(
204 const base::FilePath& cache_path,
205 const BoolCallback& callback,
206 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
207 bool rv = base::DeleteFile(cache_path, true);
208 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
209 }
210
WriteIndex(const StringVector & cache_names,const BoolCallback & callback)211 virtual void WriteIndex(const StringVector& cache_names,
212 const BoolCallback& callback) OVERRIDE {
213 DCHECK_CURRENTLY_ON(BrowserThread::IO);
214
215 // 1. Create the index file as a string. (WriteIndex)
216 // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
217
218 ServiceWorkerCacheStorageIndex index;
219
220 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
221 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
222 index_cache->set_name(cache_names[i]);
223 index_cache->set_size(0); // TODO(jkarlin): Make this real.
224 }
225
226 std::string serialized;
227 bool success = index.SerializeToString(&serialized);
228 DCHECK(success);
229
230 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
231 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
232
233 cache_task_runner_->PostTask(
234 FROM_HERE,
235 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
236 tmp_path,
237 index_path,
238 serialized,
239 callback,
240 base::MessageLoopProxy::current()));
241 }
242
WriteIndexWriteToFileInPool(const base::FilePath & tmp_path,const base::FilePath & index_path,const std::string & data,const BoolCallback & callback,const scoped_refptr<base::MessageLoopProxy> & original_loop)243 static void WriteIndexWriteToFileInPool(
244 const base::FilePath& tmp_path,
245 const base::FilePath& index_path,
246 const std::string& data,
247 const BoolCallback& callback,
248 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
249 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
250 if (bytes_written != implicit_cast<int>(data.size())) {
251 base::DeleteFile(tmp_path, /* recursive */ false);
252 original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
253 }
254
255 // Atomically rename the temporary index file to become the real one.
256 bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
257 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
258 }
259
LoadIndex(scoped_ptr<std::vector<std::string>> names,const StringVectorCallback & callback)260 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names,
261 const StringVectorCallback& callback) OVERRIDE {
262 DCHECK_CURRENTLY_ON(BrowserThread::IO);
263
264 // 1. Read the file from disk. (LoadIndexReadFileInPool)
265 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
266
267 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
268
269 cache_task_runner_->PostTask(
270 FROM_HERE,
271 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
272 index_path,
273 base::Passed(names.Pass()),
274 callback,
275 base::MessageLoopProxy::current()));
276 }
277
LoadIndexReadFileInPool(const base::FilePath & index_path,scoped_ptr<std::vector<std::string>> names,const StringVectorCallback & callback,const scoped_refptr<base::MessageLoopProxy> & original_loop)278 static void LoadIndexReadFileInPool(
279 const base::FilePath& index_path,
280 scoped_ptr<std::vector<std::string> > names,
281 const StringVectorCallback& callback,
282 const scoped_refptr<base::MessageLoopProxy>& original_loop) {
283 std::string body;
284 base::ReadFileToString(index_path, &body);
285
286 original_loop->PostTask(FROM_HERE,
287 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
288 base::Passed(names.Pass()),
289 callback,
290 body));
291 }
292
LoadIndexDidReadFile(scoped_ptr<std::vector<std::string>> names,const StringVectorCallback & callback,const std::string & serialized)293 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
294 const StringVectorCallback& callback,
295 const std::string& serialized) {
296 DCHECK_CURRENTLY_ON(BrowserThread::IO);
297
298 ServiceWorkerCacheStorageIndex index;
299 if (index.ParseFromString(serialized)) {
300 for (int i = 0, max = index.cache_size(); i < max; ++i) {
301 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
302 names->push_back(cache.name());
303 }
304 }
305
306 // TODO(jkarlin): Delete caches that are in the directory and not returned
307 // in LoadIndex.
308 callback.Run(names.Pass());
309 }
310
311 private:
~SimpleCacheLoader()312 virtual ~SimpleCacheLoader() {}
313
HexedHash(const std::string & value)314 static std::string HexedHash(const std::string& value) {
315 std::string value_hash = base::SHA1HashString(value);
316 std::string valued_hexed_hash = base::StringToLowerASCII(
317 base::HexEncode(value_hash.c_str(), value_hash.length()));
318 return valued_hexed_hash;
319 }
320
CreatePersistentCachePath(const base::FilePath & origin_path,const std::string & cache_name)321 static base::FilePath CreatePersistentCachePath(
322 const base::FilePath& origin_path,
323 const std::string& cache_name) {
324 return origin_path.AppendASCII(HexedHash(cache_name));
325 }
326
327 const base::FilePath origin_path_;
328
329 base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
330 };
331
ServiceWorkerCacheStorage(const base::FilePath & path,bool memory_only,base::SequencedTaskRunner * cache_task_runner,net::URLRequestContext * request_context,base::WeakPtr<storage::BlobStorageContext> blob_context)332 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
333 const base::FilePath& path,
334 bool memory_only,
335 base::SequencedTaskRunner* cache_task_runner,
336 net::URLRequestContext* request_context,
337 base::WeakPtr<storage::BlobStorageContext> blob_context)
338 : initialized_(false),
339 origin_path_(path),
340 cache_task_runner_(cache_task_runner),
341 memory_only_(memory_only),
342 weak_factory_(this) {
343 if (memory_only)
344 cache_loader_.reset(new MemoryLoader(
345 cache_task_runner_.get(), request_context, blob_context));
346 else
347 cache_loader_.reset(new SimpleCacheLoader(
348 origin_path_, cache_task_runner_.get(), request_context, blob_context));
349 }
350
~ServiceWorkerCacheStorage()351 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
352 }
353
CreateCache(const std::string & cache_name,const CacheAndErrorCallback & callback)354 void ServiceWorkerCacheStorage::CreateCache(
355 const std::string& cache_name,
356 const CacheAndErrorCallback& callback) {
357 if (!initialized_) {
358 LazyInit(base::Bind(&ServiceWorkerCacheStorage::CreateCache,
359 weak_factory_.GetWeakPtr(),
360 cache_name,
361 callback));
362 return;
363 }
364
365 if (cache_map_.find(cache_name) != cache_map_.end()) {
366 callback.Run(scoped_refptr<ServiceWorkerCache>(),
367 CACHE_STORAGE_ERROR_EXISTS);
368 return;
369 }
370
371 cache_loader_->CreateCache(
372 cache_name,
373 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache,
374 weak_factory_.GetWeakPtr(),
375 cache_name,
376 callback));
377 }
378
GetCache(const std::string & cache_name,const CacheAndErrorCallback & callback)379 void ServiceWorkerCacheStorage::GetCache(
380 const std::string& cache_name,
381 const CacheAndErrorCallback& callback) {
382 DCHECK_CURRENTLY_ON(BrowserThread::IO);
383
384 if (!initialized_) {
385 LazyInit(base::Bind(&ServiceWorkerCacheStorage::GetCache,
386 weak_factory_.GetWeakPtr(),
387 cache_name,
388 callback));
389 return;
390 }
391
392 scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
393 if (!cache.get()) {
394 callback.Run(scoped_refptr<ServiceWorkerCache>(),
395 CACHE_STORAGE_ERROR_NOT_FOUND);
396 return;
397 }
398
399 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
400 }
401
HasCache(const std::string & cache_name,const BoolAndErrorCallback & callback)402 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
403 const BoolAndErrorCallback& callback) {
404 DCHECK_CURRENTLY_ON(BrowserThread::IO);
405
406 if (!initialized_) {
407 LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache,
408 weak_factory_.GetWeakPtr(),
409 cache_name,
410 callback));
411 return;
412 }
413
414 bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
415
416 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
417 }
418
DeleteCache(const std::string & cache_name,const BoolAndErrorCallback & callback)419 void ServiceWorkerCacheStorage::DeleteCache(
420 const std::string& cache_name,
421 const BoolAndErrorCallback& callback) {
422 DCHECK_CURRENTLY_ON(BrowserThread::IO);
423
424 if (!initialized_) {
425 LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache,
426 weak_factory_.GetWeakPtr(),
427 cache_name,
428 callback));
429 return;
430 }
431
432 CacheMap::iterator it = cache_map_.find(cache_name);
433 if (it == cache_map_.end()) {
434 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
435 return;
436 }
437
438 base::WeakPtr<ServiceWorkerCache> cache = it->second;
439 if (cache)
440 cache->Close();
441
442 cache_map_.erase(it);
443
444 // Delete the name from ordered_cache_names_.
445 StringVector::iterator iter = std::find(
446 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
447 DCHECK(iter != ordered_cache_names_.end());
448 ordered_cache_names_.erase(iter);
449
450 // Update the Index
451 cache_loader_->WriteIndex(
452 ordered_cache_names_,
453 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
454 weak_factory_.GetWeakPtr(),
455 cache_name,
456 callback));
457 }
458
EnumerateCaches(const StringsAndErrorCallback & callback)459 void ServiceWorkerCacheStorage::EnumerateCaches(
460 const StringsAndErrorCallback& callback) {
461 DCHECK_CURRENTLY_ON(BrowserThread::IO);
462
463 if (!initialized_) {
464 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches,
465 weak_factory_.GetWeakPtr(),
466 callback));
467 return;
468 }
469
470 callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
471 }
472
473 // Init is run lazily so that it is called on the proper MessageLoop.
LazyInit(const base::Closure & callback)474 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) {
475 DCHECK_CURRENTLY_ON(BrowserThread::IO);
476 DCHECK(!initialized_);
477
478 init_callbacks_.push_back(callback);
479
480 // If this isn't the first call to LazyInit then return as the initialization
481 // has already started.
482 if (init_callbacks_.size() > 1u)
483 return;
484
485 // 1. Get the list of cache names (async call)
486 // 2. For each cache name, load the cache (async call)
487 // 3. Once each load is complete, update the map variables.
488 // 4. Call the list of waiting callbacks.
489
490 scoped_ptr<std::vector<std::string> > indexed_cache_names(
491 new std::vector<std::string>());
492
493 cache_loader_->LoadIndex(
494 indexed_cache_names.Pass(),
495 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex,
496 weak_factory_.GetWeakPtr(),
497 callback));
498 }
499
LazyInitDidLoadIndex(const base::Closure & callback,scoped_ptr<std::vector<std::string>> indexed_cache_names)500 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
501 const base::Closure& callback,
502 scoped_ptr<std::vector<std::string> > indexed_cache_names) {
503 DCHECK_CURRENTLY_ON(BrowserThread::IO);
504
505 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
506 cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
507 base::WeakPtr<ServiceWorkerCache>()));
508 ordered_cache_names_.push_back(indexed_cache_names->at(i));
509 }
510
511 initialized_ = true;
512 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
513 it != init_callbacks_.end();
514 ++it) {
515 it->Run();
516 }
517 init_callbacks_.clear();
518 }
519
CreateCacheDidCreateCache(const std::string & cache_name,const CacheAndErrorCallback & callback,const scoped_refptr<ServiceWorkerCache> & cache)520 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
521 const std::string& cache_name,
522 const CacheAndErrorCallback& callback,
523 const scoped_refptr<ServiceWorkerCache>& cache) {
524 DCHECK_CURRENTLY_ON(BrowserThread::IO);
525
526 if (!cache.get()) {
527 callback.Run(scoped_refptr<ServiceWorkerCache>(),
528 CACHE_STORAGE_ERROR_CLOSING);
529 return;
530 }
531
532 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
533 ordered_cache_names_.push_back(cache_name);
534
535 cache_loader_->WriteIndex(
536 ordered_cache_names_,
537 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
538 weak_factory_.GetWeakPtr(),
539 callback,
540 cache));
541 }
542
CreateCacheDidWriteIndex(const CacheAndErrorCallback & callback,const scoped_refptr<ServiceWorkerCache> & cache,bool success)543 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
544 const CacheAndErrorCallback& callback,
545 const scoped_refptr<ServiceWorkerCache>& cache,
546 bool success) {
547 DCHECK_CURRENTLY_ON(BrowserThread::IO);
548 DCHECK(cache.get());
549
550 callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
551 }
552
DeleteCacheDidWriteIndex(const std::string & cache_name,const BoolAndErrorCallback & callback,bool success)553 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
554 const std::string& cache_name,
555 const BoolAndErrorCallback& callback,
556 bool success) {
557 DCHECK_CURRENTLY_ON(BrowserThread::IO);
558
559 cache_loader_->CleanUpDeletedCache(
560 cache_name,
561 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp,
562 weak_factory_.GetWeakPtr(),
563 callback));
564 }
565
DeleteCacheDidCleanUp(const BoolAndErrorCallback & callback,bool success)566 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
567 const BoolAndErrorCallback& callback,
568 bool success) {
569 DCHECK_CURRENTLY_ON(BrowserThread::IO);
570
571 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
572 }
573
GetLoadedCache(const std::string & cache_name)574 scoped_refptr<ServiceWorkerCache> ServiceWorkerCacheStorage::GetLoadedCache(
575 const std::string& cache_name) {
576 DCHECK_CURRENTLY_ON(BrowserThread::IO);
577 DCHECK(initialized_);
578
579 CacheMap::iterator map_iter = cache_map_.find(cache_name);
580 if (map_iter == cache_map_.end())
581 return scoped_refptr<ServiceWorkerCache>();
582
583 base::WeakPtr<ServiceWorkerCache> cache = map_iter->second;
584
585 if (!cache) {
586 scoped_refptr<ServiceWorkerCache> new_cache =
587 cache_loader_->CreateServiceWorkerCache(cache_name);
588 map_iter->second = new_cache->AsWeakPtr();
589 return new_cache;
590 }
591
592 return make_scoped_refptr(cache.get());
593 }
594
595 } // namespace content
596