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