#include <string>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/ref_counted.h"
#include "base/sha1.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "content/browser/service_worker/service_worker_cache.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/directory_lister.h"
#include "net/base/net_errors.h"
-#include "webkit/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_storage_context.h"
namespace content {
-// Handles the loading and clean up of ServiceWorkerCache objects.
-class ServiceWorkerCacheStorage::CacheLoader
- : public base::RefCountedThreadSafe<
- ServiceWorkerCacheStorage::CacheLoader> {
+
+// Handles the loading and clean up of ServiceWorkerCache objects. The
+// callback of every public method is guaranteed to be called.
+class ServiceWorkerCacheStorage::CacheLoader {
public:
- typedef base::Callback<void(scoped_ptr<ServiceWorkerCache>)> CacheCallback;
+ typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)>
+ CacheCallback;
typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
- StringsCallback;
+ StringVectorCallback;
- CacheLoader(
- base::SequencedTaskRunner* cache_task_runner,
- net::URLRequestContext* request_context,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_context)
+ CacheLoader(base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
: cache_task_runner_(cache_task_runner),
request_context_(request_context),
blob_context_(blob_context) {}
- // Loads the given cache_name, the cache is NULL if it fails. If the cache
- // doesn't exist a new one is created.
- virtual void LoadCache(const std::string& cache_name,
- const CacheCallback& callback) = 0;
+ virtual ~CacheLoader() {}
+
+ // Creates a ServiceWorkerCache with the given name. It does not attempt to
+ // load the backend, that happens lazily when the cache is used.
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) = 0;
// Deletes any pre-existing cache of the same name and then loads it.
virtual void CreateCache(const std::string& cache_name,
const BoolCallback& callback) = 0;
// Writes the cache names (and sizes) to disk if applicable.
- virtual void WriteIndex(CacheMap* caches, const BoolCallback& callback) = 0;
+ virtual void WriteIndex(const StringVector& cache_names,
+ const BoolCallback& callback) = 0;
// Loads the cache names from disk if applicable.
virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
- const StringsCallback& callback) = 0;
+ const StringVectorCallback& callback) = 0;
protected:
- friend class base::RefCountedThreadSafe<
- ServiceWorkerCacheStorage::CacheLoader>;
-
- virtual ~CacheLoader() {};
- virtual void LoadCacheImpl(const std::string&) {}
-
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
net::URLRequestContext* request_context_;
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_context_;
+ base::WeakPtr<storage::BlobStorageContext> blob_context_;
};
+// Creates memory-only ServiceWorkerCaches. Because these caches have no
+// persistent storage it is not safe to free them from memory if they might be
+// used again. Therefore this class holds a reference to each cache until the
+// cache is deleted.
class ServiceWorkerCacheStorage::MemoryLoader
: public ServiceWorkerCacheStorage::CacheLoader {
public:
- MemoryLoader(
- base::SequencedTaskRunner* cache_task_runner,
- net::URLRequestContext* request_context,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_context)
+ MemoryLoader(base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheLoader(cache_task_runner, request_context, blob_context) {}
- virtual void LoadCache(const std::string& cache_name,
- const CacheCallback& callback) OVERRIDE {
- NOTREACHED();
+
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) OVERRIDE {
+ return ServiceWorkerCache::CreateMemoryCache(request_context_,
+ blob_context_);
}
virtual void CreateCache(const std::string& cache_name,
const CacheCallback& callback) OVERRIDE {
- scoped_ptr<ServiceWorkerCache> cache =
- ServiceWorkerCache::CreateMemoryCache(
- cache_name, request_context_, blob_context_);
- callback.Run(cache.Pass());
+ scoped_refptr<ServiceWorkerCache> cache =
+ ServiceWorkerCache::CreateMemoryCache(request_context_, blob_context_);
+ cache_refs_.insert(std::make_pair(cache_name, cache));
+ callback.Run(cache);
}
virtual void CleanUpDeletedCache(const std::string& cache_name,
const BoolCallback& callback) OVERRIDE {
+ CacheRefMap::iterator it = cache_refs_.find(cache_name);
+ DCHECK(it != cache_refs_.end());
+ cache_refs_.erase(it);
callback.Run(true);
}
- virtual void WriteIndex(CacheMap* caches,
+ virtual void WriteIndex(const StringVector& cache_names,
const BoolCallback& callback) OVERRIDE {
callback.Run(false);
}
virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
- const StringsCallback& callback) OVERRIDE {
+ const StringVectorCallback& callback) OVERRIDE {
callback.Run(cache_names.Pass());
}
private:
+ typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap;
virtual ~MemoryLoader() {}
+
+ // Keep a reference to each cache to ensure that it's not freed before the
+ // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
+ // freed.
+ CacheRefMap cache_refs_;
};
class ServiceWorkerCacheStorage::SimpleCacheLoader
SimpleCacheLoader(const base::FilePath& origin_path,
base::SequencedTaskRunner* cache_task_runner,
net::URLRequestContext* request_context,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_context)
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheLoader(cache_task_runner, request_context, blob_context),
- origin_path_(origin_path) {}
+ origin_path_(origin_path),
+ weak_ptr_factory_(this) {}
- virtual void LoadCache(const std::string& cache_name,
- const CacheCallback& callback) OVERRIDE {
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) OVERRIDE {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // 1. Create the cache's directory if necessary. (LoadCreateDirectoryInPool)
- // 2. Create the cache object. (LoadDidCreateDirectory)
-
- cache_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool,
- this,
- CreatePersistentCachePath(origin_path_, cache_name),
- cache_name,
- callback,
- base::MessageLoopProxy::current()));
- }
-
- void LoadCreateDirectoryInPool(
- const base::FilePath& path,
- const std::string& cache_name,
- const CacheCallback& callback,
- const scoped_refptr<base::MessageLoopProxy>& original_loop) {
- DCHECK(cache_task_runner_->RunsTasksOnCurrentThread());
-
- bool rv = base::CreateDirectory(path);
- original_loop->PostTask(
- FROM_HERE,
- base::Bind(&SimpleCacheLoader::LoadDidCreateDirectory,
- this,
- cache_name,
- callback,
- rv));
- }
-
- void LoadDidCreateDirectory(const std::string& cache_name,
- const CacheCallback& callback,
- bool dir_rv) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!dir_rv) {
- callback.Run(scoped_ptr<ServiceWorkerCache>());
- return;
- }
-
- scoped_ptr<ServiceWorkerCache> cache =
- ServiceWorkerCache::CreatePersistentCache(
- CreatePersistentCachePath(origin_path_, cache_name),
- cache_name,
- request_context_,
- blob_context_);
- callback.Run(cache.Pass());
+ return ServiceWorkerCache::CreatePersistentCache(
+ CreatePersistentCachePath(origin_path_, cache_name),
+ request_context_,
+ blob_context_);
}
virtual void CreateCache(const std::string& cache_name,
base::FilePath cache_path =
CreatePersistentCachePath(origin_path_, cache_name);
- cache_task_runner_->PostTask(
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(),
FROM_HERE,
- base::Bind(&SimpleCacheLoader::CreateCacheDeleteFilesInPool,
- this,
- cache_path,
+ base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
+ base::Bind(&SimpleCacheLoader::CreateCachePreppedDir,
cache_name,
callback,
- base::MessageLoopProxy::current()));
+ weak_ptr_factory_.GetWeakPtr()));
}
- void CreateCacheDeleteFilesInPool(
- const base::FilePath& cache_path,
- const std::string& cache_name,
- const CacheCallback& callback,
- const scoped_refptr<base::MessageLoopProxy>& original_loop) {
- DCHECK(cache_task_runner_->RunsTasksOnCurrentThread());
+ static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
+ if (base::PathExists(cache_path))
+ base::DeleteFile(cache_path, /* recursive */ true);
+ return base::CreateDirectory(cache_path);
+ }
- base::FilePath path(cache_path);
- if (base::PathExists(path))
- base::DeleteFile(path, /* recursive */ true);
+ static void CreateCachePreppedDir(const std::string& cache_name,
+ const CacheCallback& callback,
+ base::WeakPtr<SimpleCacheLoader> loader,
+ bool success) {
+ if (!success || !loader) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>());
+ return;
+ }
- // Jump straight into LoadCache on the same thread.
- cache_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool,
- this,
- cache_path,
- cache_name,
- callback,
- original_loop));
+ callback.Run(loader->CreateServiceWorkerCache(cache_name));
}
virtual void CleanUpDeletedCache(const std::string& cache_name,
cache_task_runner_->PostTask(
FROM_HERE,
base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
- this,
cache_path,
callback,
base::MessageLoopProxy::current()));
}
- void CleanUpDeleteCacheDirInPool(
+ static void CleanUpDeleteCacheDirInPool(
const base::FilePath& cache_path,
const BoolCallback& callback,
const scoped_refptr<base::MessageLoopProxy>& original_loop) {
- DCHECK(cache_task_runner_->RunsTasksOnCurrentThread());
-
bool rv = base::DeleteFile(cache_path, true);
original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
}
- virtual void WriteIndex(CacheMap* caches,
+ virtual void WriteIndex(const StringVector& cache_names,
const BoolCallback& callback) OVERRIDE {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceWorkerCacheStorageIndex index;
- for (CacheMap::const_iterator iter(caches); !iter.IsAtEnd();
- iter.Advance()) {
- const ServiceWorkerCache* cache = iter.GetCurrentValue();
+ for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
- index_cache->set_name(cache->name());
+ index_cache->set_name(cache_names[i]);
index_cache->set_size(0); // TODO(jkarlin): Make this real.
}
cache_task_runner_->PostTask(
FROM_HERE,
base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
- this,
tmp_path,
index_path,
serialized,
- caches,
callback,
base::MessageLoopProxy::current()));
}
- void WriteIndexWriteToFileInPool(
+ static void WriteIndexWriteToFileInPool(
const base::FilePath& tmp_path,
const base::FilePath& index_path,
const std::string& data,
- CacheMap* caches,
const BoolCallback& callback,
const scoped_refptr<base::MessageLoopProxy>& original_loop) {
- DCHECK(cache_task_runner_->RunsTasksOnCurrentThread());
-
int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
if (bytes_written != implicit_cast<int>(data.size())) {
base::DeleteFile(tmp_path, /* recursive */ false);
}
virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names,
- const StringsCallback& callback) OVERRIDE {
+ const StringVectorCallback& callback) OVERRIDE {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// 1. Read the file from disk. (LoadIndexReadFileInPool)
cache_task_runner_->PostTask(
FROM_HERE,
base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
- this,
index_path,
base::Passed(names.Pass()),
callback,
base::MessageLoopProxy::current()));
}
- void LoadIndexReadFileInPool(
+ static void LoadIndexReadFileInPool(
const base::FilePath& index_path,
scoped_ptr<std::vector<std::string> > names,
- const StringsCallback& callback,
+ const StringVectorCallback& callback,
const scoped_refptr<base::MessageLoopProxy>& original_loop) {
- DCHECK(cache_task_runner_->RunsTasksOnCurrentThread());
-
std::string body;
base::ReadFileToString(index_path, &body);
original_loop->PostTask(FROM_HERE,
base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
- this,
base::Passed(names.Pass()),
callback,
body));
}
- void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
- const StringsCallback& callback,
- const std::string& serialized) {
+ static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
+ const StringVectorCallback& callback,
+ const std::string& serialized) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceWorkerCacheStorageIndex index;
- index.ParseFromString(serialized);
-
- for (int i = 0, max = index.cache_size(); i < max; ++i) {
- const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
- names->push_back(cache.name());
+ if (index.ParseFromString(serialized)) {
+ for (int i = 0, max = index.cache_size(); i < max; ++i) {
+ const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
+ names->push_back(cache.name());
+ }
}
// TODO(jkarlin): Delete caches that are in the directory and not returned
private:
virtual ~SimpleCacheLoader() {}
- std::string HexedHash(const std::string& value) {
+ static std::string HexedHash(const std::string& value) {
std::string value_hash = base::SHA1HashString(value);
std::string valued_hexed_hash = base::StringToLowerASCII(
base::HexEncode(value_hash.c_str(), value_hash.length()));
return valued_hexed_hash;
}
- base::FilePath CreatePersistentCachePath(const base::FilePath& origin_path,
- const std::string& cache_name) {
+ static base::FilePath CreatePersistentCachePath(
+ const base::FilePath& origin_path,
+ const std::string& cache_name) {
return origin_path.AppendASCII(HexedHash(cache_name));
}
const base::FilePath origin_path_;
+
+ base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
};
ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
net::URLRequestContext* request_context,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_context)
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
: initialized_(false),
origin_path_(path),
cache_task_runner_(cache_task_runner),
+ memory_only_(memory_only),
weak_factory_(this) {
if (memory_only)
- cache_loader_ =
- new MemoryLoader(cache_task_runner_, request_context, blob_context);
+ cache_loader_.reset(new MemoryLoader(
+ cache_task_runner_.get(), request_context, blob_context));
else
- cache_loader_ = new SimpleCacheLoader(
- origin_path_, cache_task_runner_, request_context, blob_context);
+ cache_loader_.reset(new SimpleCacheLoader(
+ origin_path_, cache_task_runner_.get(), request_context, blob_context));
}
ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
return;
}
- if (cache_name.empty()) {
- callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY);
- return;
- }
-
- if (GetLoadedCache(cache_name)) {
- callback.Run(0, CACHE_STORAGE_ERROR_EXISTS);
+ if (cache_map_.find(cache_name) != cache_map_.end()) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>(),
+ CACHE_STORAGE_ERROR_EXISTS);
return;
}
return;
}
- if (cache_name.empty()) {
- callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY);
+ scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
+ if (!cache.get()) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>(),
+ CACHE_STORAGE_ERROR_NOT_FOUND);
return;
}
- ServiceWorkerCache* cache = GetLoadedCache(cache_name);
- if (!cache) {
- callback.Run(0, CACHE_STORAGE_ERROR_NOT_FOUND);
- return;
- }
-
- cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend,
- weak_factory_.GetWeakPtr(),
- cache->AsWeakPtr(),
- callback));
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
}
void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
return;
}
- if (cache_name.empty()) {
- callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY);
- return;
- }
-
- bool has_cache = GetLoadedCache(cache_name) != NULL;
+ bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
}
return;
}
- if (cache_name.empty()) {
- callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY);
- return;
- }
-
- ServiceWorkerCache* cache = GetLoadedCache(cache_name);
- if (!cache) {
+ CacheMap::iterator it = cache_map_.find(cache_name);
+ if (it == cache_map_.end()) {
callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
return;
}
- name_map_.erase(cache_name);
- cache_map_.Remove(cache->id()); // deletes cache
+ base::WeakPtr<ServiceWorkerCache> cache = it->second;
+ if (cache)
+ cache->Close();
+
+ cache_map_.erase(it);
+
+ // Delete the name from ordered_cache_names_.
+ StringVector::iterator iter = std::find(
+ ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
+ DCHECK(iter != ordered_cache_names_.end());
+ ordered_cache_names_.erase(iter);
// Update the Index
cache_loader_->WriteIndex(
- &cache_map_,
+ ordered_cache_names_,
base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
weak_factory_.GetWeakPtr(),
cache_name,
return;
}
- std::vector<std::string> names;
- for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end();
- ++it) {
- names.push_back(it->first);
- }
-
- callback.Run(names, CACHE_STORAGE_ERROR_NO_ERROR);
-}
-
-void ServiceWorkerCacheStorage::DidCreateBackend(
- base::WeakPtr<ServiceWorkerCache> cache,
- const CacheAndErrorCallback& callback,
- bool success) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!success || !cache) {
- // TODO(jkarlin): This should delete the directory and try again in case
- // the cache is simply corrupt.
- callback.Run(0, CACHE_STORAGE_ERROR_STORAGE);
- return;
- }
- callback.Run(cache->id(), CACHE_STORAGE_ERROR_NO_ERROR);
+ callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
}
// Init is run lazily so that it is called on the proper MessageLoop.
scoped_ptr<std::vector<std::string> > indexed_cache_names) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (indexed_cache_names->empty()) {
- LazyInitDone();
- return;
+ for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
+ cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
+ base::WeakPtr<ServiceWorkerCache>()));
+ ordered_cache_names_.push_back(indexed_cache_names->at(i));
}
- std::vector<std::string>::const_iterator iter = indexed_cache_names->begin();
- std::vector<std::string>::const_iterator iter_next = iter + 1;
-
- cache_loader_->LoadCache(
- *iter,
- base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName,
- weak_factory_.GetWeakPtr(),
- callback,
- base::Passed(indexed_cache_names.Pass()),
- iter_next));
-}
-
-void ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName(
- const base::Closure& callback,
- scoped_ptr<std::vector<std::string> > indexed_cache_names,
- const std::vector<std::string>::const_iterator& iter,
- scoped_ptr<ServiceWorkerCache> cache) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (cache)
- AddCacheToMaps(cache.Pass());
-
- if (iter == indexed_cache_names->end()) {
- LazyInitDone();
- return;
- }
-
- std::vector<std::string>::const_iterator iter_next = iter + 1;
- cache_loader_->LoadCache(
- *iter,
- base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName,
- weak_factory_.GetWeakPtr(),
- callback,
- base::Passed(indexed_cache_names.Pass()),
- iter_next));
-}
-
-void ServiceWorkerCacheStorage::LazyInitDone() {
initialized_ = true;
for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
it != init_callbacks_.end();
init_callbacks_.clear();
}
-void ServiceWorkerCacheStorage::AddCacheToMaps(
- scoped_ptr<ServiceWorkerCache> cache) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- ServiceWorkerCache* cache_ptr = cache.release();
- CacheID id = cache_map_.Add(cache_ptr);
- name_map_.insert(std::make_pair(cache_ptr->name(), id));
- cache_ptr->set_id(id);
-}
-
void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
const std::string& cache_name,
const CacheAndErrorCallback& callback,
- scoped_ptr<ServiceWorkerCache> cache) {
+ const scoped_refptr<ServiceWorkerCache>& cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!cache) {
- callback.Run(0, CACHE_STORAGE_ERROR_STORAGE);
+ if (!cache.get()) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>(),
+ CACHE_STORAGE_ERROR_CLOSING);
return;
}
- base::WeakPtr<ServiceWorkerCache> cache_ptr = cache->AsWeakPtr();
-
- AddCacheToMaps(cache.Pass());
+ cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
+ ordered_cache_names_.push_back(cache_name);
cache_loader_->WriteIndex(
- &cache_map_,
- base::Bind(
- &ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
- weak_factory_.GetWeakPtr(),
- callback,
- cache_ptr)); // cache is owned by this->CacheMap and won't be deleted
+ ordered_cache_names_,
+ base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ cache));
}
void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
const CacheAndErrorCallback& callback,
- base::WeakPtr<ServiceWorkerCache> cache,
+ const scoped_refptr<ServiceWorkerCache>& cache,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!cache) {
- callback.Run(false, CACHE_STORAGE_ERROR_STORAGE);
- return;
- }
- cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend,
- weak_factory_.GetWeakPtr(),
- cache,
- callback));
+ DCHECK(cache.get());
+
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
}
void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
}
-ServiceWorkerCache* ServiceWorkerCacheStorage::GetLoadedCache(
- const std::string& cache_name) const {
+scoped_refptr<ServiceWorkerCache> ServiceWorkerCacheStorage::GetLoadedCache(
+ const std::string& cache_name) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(initialized_);
- NameMap::const_iterator it = name_map_.find(cache_name);
- if (it == name_map_.end())
- return NULL;
+ CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ if (map_iter == cache_map_.end())
+ return scoped_refptr<ServiceWorkerCache>();
+
+ base::WeakPtr<ServiceWorkerCache> cache = map_iter->second;
+
+ if (!cache) {
+ scoped_refptr<ServiceWorkerCache> new_cache =
+ cache_loader_->CreateServiceWorkerCache(cache_name);
+ map_iter->second = new_cache->AsWeakPtr();
+ return new_cache;
+ }
- ServiceWorkerCache* cache = cache_map_.Lookup(it->second);
- DCHECK(cache);
- return cache;
+ return make_scoped_refptr(cache.get());
}
} // namespace content