Index: content/browser/service_worker/service_worker_cache_storage.cc |
diff --git a/content/browser/service_worker/service_worker_cache_storage.cc b/content/browser/service_worker/service_worker_cache_storage.cc |
index 4f5f6d293a2a843739b9ccd1724edb98a93ac591..5084fc661c8abeab78e02379142d05315b86ebe0 100644 |
--- a/content/browser/service_worker/service_worker_cache_storage.cc |
+++ b/content/browser/service_worker/service_worker_cache_storage.cc |
@@ -22,28 +22,13 @@ |
namespace content { |
-// static |
-const int ServiceWorkerCacheStorage::kInvalidCacheID = -1; |
- |
-// The meta information related to each ServiceWorkerCache that the |
-// ServiceWorkerCacheManager needs to keep track of. |
-// TODO(jkarlin): Add reference counting so that the deletion of javascript |
-// objects can delete the ServiceWorkerCache. |
-struct ServiceWorkerCacheStorage::CacheContext { |
- CacheContext(const std::string& name, |
- CacheID id, |
- scoped_ptr<ServiceWorkerCache> cache) |
- : name(name), id(id), cache(cache.Pass()) {} |
- std::string name; |
- CacheID id; |
- scoped_ptr<ServiceWorkerCache> cache; |
-}; |
// 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; |
@@ -59,7 +44,7 @@ class ServiceWorkerCacheStorage::CacheLoader { |
// Loads the given cache_name, the cache is NULL if it fails. If the cache |
// doesn't exist a new one is created. |
- virtual scoped_ptr<ServiceWorkerCache> CreateServiceWorkerCache( |
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache( |
const std::string& cache_name) = 0; |
// Deletes any pre-existing cache of the same name and then loads it. |
@@ -85,6 +70,10 @@ class ServiceWorkerCacheStorage::CacheLoader { |
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: |
@@ -93,7 +82,7 @@ class ServiceWorkerCacheStorage::MemoryLoader |
base::WeakPtr<storage::BlobStorageContext> blob_context) |
: CacheLoader(cache_task_runner, request_context, blob_context) {} |
- virtual scoped_ptr<ServiceWorkerCache> CreateServiceWorkerCache( |
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache( |
const std::string& cache_name) OVERRIDE { |
return ServiceWorkerCache::CreateMemoryCache(request_context_, |
blob_context_); |
@@ -101,11 +90,17 @@ class ServiceWorkerCacheStorage::MemoryLoader |
virtual void CreateCache(const std::string& cache_name, |
const CacheCallback& callback) OVERRIDE { |
- callback.Run(CreateServiceWorkerCache(cache_name).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); |
} |
@@ -120,7 +115,13 @@ class ServiceWorkerCacheStorage::MemoryLoader |
} |
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 |
@@ -134,7 +135,7 @@ class ServiceWorkerCacheStorage::SimpleCacheLoader |
origin_path_(origin_path), |
weak_ptr_factory_(this) {} |
- virtual scoped_ptr<ServiceWorkerCache> CreateServiceWorkerCache( |
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache( |
const std::string& cache_name) OVERRIDE { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
@@ -176,7 +177,7 @@ class ServiceWorkerCacheStorage::SimpleCacheLoader |
base::WeakPtr<SimpleCacheLoader> loader, |
bool success) { |
if (!success || !loader) { |
- callback.Run(scoped_ptr<ServiceWorkerCache>()); |
+ callback.Run(scoped_refptr<ServiceWorkerCache>()); |
return; |
} |
@@ -218,9 +219,8 @@ class ServiceWorkerCacheStorage::SimpleCacheLoader |
for (CacheMap::const_iterator it = caches.begin(); it != caches.end(); |
++it) { |
- const CacheContext* cache = it->second; |
ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); |
- index_cache->set_name(cache->name); |
+ index_cache->set_name(it->first); |
index_cache->set_size(0); // TODO(jkarlin): Make this real. |
} |
@@ -337,9 +337,9 @@ ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( |
net::URLRequestContext* request_context, |
base::WeakPtr<storage::BlobStorageContext> blob_context) |
: initialized_(false), |
- next_cache_id_(0), |
origin_path_(path), |
cache_task_runner_(cache_task_runner), |
+ memory_only_(memory_only), |
weak_factory_(this) { |
if (memory_only) |
cache_loader_.reset(new MemoryLoader( |
@@ -350,7 +350,6 @@ ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( |
} |
ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() { |
- STLDeleteContainerPairSecondPointers(cache_map_.begin(), cache_map_.end()); |
} |
void ServiceWorkerCacheStorage::CreateCache( |
@@ -364,8 +363,9 @@ void ServiceWorkerCacheStorage::CreateCache( |
return; |
} |
- if (GetLoadedCache(cache_name)) { |
- callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_EXISTS); |
+ if (cache_map_.find(cache_name) != cache_map_.end()) { |
+ callback.Run(scoped_refptr<ServiceWorkerCache>(), |
+ CACHE_STORAGE_ERROR_EXISTS); |
return; |
} |
@@ -390,13 +390,14 @@ void ServiceWorkerCacheStorage::GetCache( |
return; |
} |
- CacheContext* cache_context = GetLoadedCache(cache_name); |
- if (!cache_context) { |
- callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_NOT_FOUND); |
+ scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name); |
+ if (!cache.get()) { |
+ callback.Run(scoped_refptr<ServiceWorkerCache>(), |
+ CACHE_STORAGE_ERROR_NOT_FOUND); |
return; |
} |
- callback.Run(cache_context->id, CACHE_STORAGE_ERROR_NO_ERROR); |
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR); |
} |
void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, |
@@ -411,7 +412,7 @@ void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, |
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); |
} |
@@ -429,15 +430,18 @@ void ServiceWorkerCacheStorage::DeleteCache( |
return; |
} |
- scoped_ptr<CacheContext> cache_context(GetLoadedCache(cache_name)); |
- if (!cache_context) { |
+ |
+ 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_.erase(cache_context->id); |
- cache_context.reset(); |
+ base::WeakPtr<ServiceWorkerCache> cache = it->second; |
+ if (cache) |
+ cache->Close(); |
+ |
+ cache_map_.erase(it); |
// Update the Index |
cache_loader_->WriteIndex( |
@@ -460,7 +464,7 @@ void ServiceWorkerCacheStorage::EnumerateCaches( |
} |
std::vector<std::string> names; |
- for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end(); |
+ for (CacheMap::const_iterator it = cache_map_.begin(); it != cache_map_.end(); |
++it) { |
names.push_back(it->first); |
} |
@@ -500,14 +504,10 @@ void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( |
scoped_ptr<std::vector<std::string> > indexed_cache_names) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- for (std::vector<std::string>::iterator it = indexed_cache_names->begin(); |
- it != indexed_cache_names->end(); |
- ++it) { |
- scoped_ptr<ServiceWorkerCache> cache = |
- cache_loader_->CreateServiceWorkerCache(*it); |
- if (!cache) |
- continue; |
- AddCacheToMaps(*it, cache.Pass()); |
+ |
+ 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>())); |
} |
initialized_ = true; |
@@ -519,53 +519,36 @@ void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( |
init_callbacks_.clear(); |
} |
-ServiceWorkerCacheStorage::CacheContext* |
-ServiceWorkerCacheStorage::AddCacheToMaps( |
- const std::string& cache_name, |
- scoped_ptr<ServiceWorkerCache> cache) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- |
- CacheID id = next_cache_id_++; |
- CacheContext* cache_context = new CacheContext(cache_name, id, cache.Pass()); |
- cache_map_.insert(std::make_pair(id, cache_context)); // Takes ownership |
- name_map_.insert(std::make_pair(cache_name, id)); |
- return cache_context; |
-} |
- |
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(kInvalidCacheID, CACHE_STORAGE_ERROR_CLOSING); |
+ if (!cache.get()) { |
+ callback.Run(scoped_refptr<ServiceWorkerCache>(), |
+ CACHE_STORAGE_ERROR_CLOSING); |
return; |
} |
- CacheContext* cache_context = AddCacheToMaps(cache_name, cache.Pass()); |
+ cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr())); |
cache_loader_->WriteIndex( |
cache_map_, |
base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex, |
weak_factory_.GetWeakPtr(), |
callback, |
- cache_context->cache->AsWeakPtr(), |
- cache_context->id)); |
+ cache)); |
} |
void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex( |
const CacheAndErrorCallback& callback, |
- base::WeakPtr<ServiceWorkerCache> cache, |
- CacheID id, |
+ const scoped_refptr<ServiceWorkerCache>& cache, |
bool success) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- if (!cache) { |
- callback.Run(kInvalidCacheID, CACHE_STORAGE_ERROR_CLOSING); |
- return; |
- } |
+ DCHECK(cache.get()); |
- callback.Run(id, CACHE_STORAGE_ERROR_NO_ERROR); |
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR); |
} |
void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex( |
@@ -589,18 +572,25 @@ void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp( |
callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR); |
} |
-ServiceWorkerCacheStorage::CacheContext* |
-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 name_iter = name_map_.find(cache_name); |
- if (name_iter == 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; |
+ } |
- CacheMap::const_iterator map_iter = cache_map_.find(name_iter->second); |
- DCHECK(map_iter != cache_map_.end()); |
- return map_iter->second; |
+ return make_scoped_refptr(cache.get()); |
} |
} // namespace content |