From 28b1110370900897ab652cb420c371fab8857ad4 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 1 Aug 2016 12:59:39 +0200 Subject: BASELINE: Update Chromium to 53.0.2785.41 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also adds a few extra files for extensions. Change-Id: Iccdd55d98660903331cf8b7b29188da781830af4 Reviewed-by: Michael Brüning --- .../content/browser/cache_storage/cache_storage.cc | 270 +++++++++++++-------- .../content/browser/cache_storage/cache_storage.h | 78 +++--- .../browser/cache_storage/cache_storage.proto | 1 + .../browser/cache_storage/cache_storage_cache.cc | 91 ++++--- .../browser/cache_storage/cache_storage_cache.h | 34 ++- .../cache_storage/cache_storage_cache_handle.cc | 28 +++ .../cache_storage/cache_storage_cache_handle.h | 41 ++++ .../cache_storage/cache_storage_cache_unittest.cc | 57 +++-- .../cache_storage/cache_storage_dispatcher_host.cc | 78 +++--- .../cache_storage/cache_storage_dispatcher_host.h | 37 +-- .../cache_storage_manager_unittest.cc | 184 +++++++++----- .../cache_storage/cache_storage_unittest.cc | 139 ----------- 12 files changed, 585 insertions(+), 453 deletions(-) create mode 100644 chromium/content/browser/cache_storage/cache_storage_cache_handle.cc create mode 100644 chromium/content/browser/cache_storage/cache_storage_cache_handle.h delete mode 100644 chromium/content/browser/cache_storage/cache_storage_unittest.cc (limited to 'chromium/content/browser/cache_storage') diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc index c1e9820e0ee..3bf66235ea8 100644 --- a/chromium/content/browser/cache_storage/cache_storage.cc +++ b/chromium/content/browser/cache_storage/cache_storage.cc @@ -27,6 +27,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/browser/cache_storage/cache_storage.pb.h" #include "content/browser/cache_storage/cache_storage_cache.h" +#include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/cache_storage/cache_storage_scheduler.h" #include "content/public/browser/browser_thread.h" #include "net/base/directory_lister.h" @@ -39,8 +40,6 @@ namespace content { namespace { -const int kCachePreservationInSecs = 30; - std::string HexedHash(const std::string& value) { std::string value_hash = base::SHA1HashString(value); std::string valued_hexed_hash = base::ToLowerASCII( @@ -48,10 +47,11 @@ std::string HexedHash(const std::string& value) { return valued_hexed_hash; } -void SizeRetrievedFromCache(const scoped_refptr& cache, - const base::Closure& closure, - int64_t* accumulator, - int64_t size) { +void SizeRetrievedFromCache( + std::unique_ptr cache_handle, + const base::Closure& closure, + int64_t* accumulator, + int64_t size) { *accumulator += size; closure.Run(); } @@ -78,7 +78,8 @@ struct CacheStorage::CacheMatchResponse { // Handles the loading and clean up of CacheStorageCache objects. class CacheStorage::CacheLoader { public: - typedef base::Callback)> CacheCallback; + typedef base::Callback)> + CacheCallback; typedef base::Callback BoolCallback; typedef base::Callback>)> StringVectorCallback; @@ -88,11 +89,13 @@ class CacheStorage::CacheLoader { scoped_refptr request_context_getter, storage::QuotaManagerProxy* quota_manager_proxy, base::WeakPtr blob_context, + CacheStorage* cache_storage, const GURL& origin) : cache_task_runner_(cache_task_runner), request_context_getter_(request_context_getter), quota_manager_proxy_(quota_manager_proxy), blob_context_(blob_context), + cache_storage_(cache_storage), origin_(origin) { DCHECK(!origin_.is_empty()); } @@ -101,7 +104,7 @@ class CacheStorage::CacheLoader { // Creates a CacheStorageCache with the given name. It does not attempt to // load the backend, that happens lazily when the cache is used. - virtual scoped_refptr CreateCache( + virtual std::unique_ptr CreateCache( const std::string& cache_name) = 0; // Deletes any pre-existing cache of the same name and then loads it. @@ -129,6 +132,10 @@ class CacheStorage::CacheLoader { storage::QuotaManagerProxy* quota_manager_proxy_; base::WeakPtr blob_context_; + + // Raw pointer is safe because this object is owned by cache_storage_. + CacheStorage* cache_storage_; + GURL origin_; }; @@ -142,32 +149,33 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader { scoped_refptr request_context, storage::QuotaManagerProxy* quota_manager_proxy, base::WeakPtr blob_context, + CacheStorage* cache_storage, const GURL& origin) : CacheLoader(cache_task_runner, request_context, quota_manager_proxy, blob_context, + cache_storage, origin) {} - scoped_refptr CreateCache( + std::unique_ptr CreateCache( const std::string& cache_name) override { return CacheStorageCache::CreateMemoryCache( - origin_, cache_name, request_context_getter_, quota_manager_proxy_, - blob_context_); + origin_, cache_name, cache_storage_, request_context_getter_, + quota_manager_proxy_, blob_context_); } void PrepareNewCacheDestination(const std::string& cache_name, const CacheCallback& callback) override { - scoped_refptr cache = CreateCache(cache_name); - cache_refs_.insert(std::make_pair(cache_name, cache)); + std::unique_ptr cache = CreateCache(cache_name); callback.Run(std::move(cache)); } 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); + CacheHandles::iterator it = cache_handles_.find(cache_name); + DCHECK(it != cache_handles_.end()); + cache_handles_.erase(it); callback.Run(true); } @@ -181,14 +189,21 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader { callback.Run(std::move(cache_names)); } + void StoreCacheHandle(const std::string& cache_name, + std::unique_ptr cache_handle) { + DCHECK(!ContainsKey(cache_handles_, cache_name)); + cache_handles_.insert(std::make_pair(cache_name, std::move(cache_handle))); + } + private: - typedef std::map> CacheRefMap; + typedef std::map> + CacheHandles; ~MemoryLoader() override {} // Keep a reference to each cache to ensure that it's not freed before the // client calls CacheStorage::Delete or the CacheStorage is // freed. - CacheRefMap cache_refs_; + CacheHandles cache_handles_; }; class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader { @@ -198,16 +213,18 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader { scoped_refptr request_context, storage::QuotaManagerProxy* quota_manager_proxy, base::WeakPtr blob_context, + CacheStorage* cache_storage, const GURL& origin) : CacheLoader(cache_task_runner, request_context, quota_manager_proxy, blob_context, + cache_storage, origin), origin_path_(origin_path), weak_ptr_factory_(this) {} - scoped_refptr CreateCache( + std::unique_ptr CreateCache( const std::string& cache_name) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(ContainsKey(cache_name_to_cache_dir_, cache_name)); @@ -215,8 +232,8 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader { std::string cache_dir = cache_name_to_cache_dir_[cache_name]; base::FilePath cache_path = origin_path_.AppendASCII(cache_dir); return CacheStorageCache::CreatePersistentCache( - origin_, cache_name, cache_path, request_context_getter_, - quota_manager_proxy_, blob_context_); + origin_, cache_name, cache_storage_, cache_path, + request_context_getter_, quota_manager_proxy_, blob_context_); } void PrepareNewCacheDestination(const std::string& cache_name, @@ -248,7 +265,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader { const CacheCallback& callback, const std::string& cache_dir) { if (cache_dir.empty()) { - callback.Run(scoped_refptr()); + callback.Run(std::unique_ptr()); return; } @@ -467,6 +484,7 @@ CacheStorage::CacheStorage( const GURL& origin) : initialized_(false), initializing_(false), + memory_only_(memory_only), scheduler_(new CacheStorageScheduler()), origin_path_(path), cache_task_runner_(cache_task_runner), @@ -474,13 +492,13 @@ CacheStorage::CacheStorage( origin_(origin), weak_factory_(this) { if (memory_only) - cache_loader_.reset( - new MemoryLoader(cache_task_runner_.get(), std::move(request_context), - quota_manager_proxy.get(), blob_context, origin)); + cache_loader_.reset(new MemoryLoader( + cache_task_runner_.get(), std::move(request_context), + quota_manager_proxy.get(), blob_context, this, origin)); else cache_loader_.reset(new SimpleCacheLoader( origin_path_, cache_task_runner_.get(), std::move(request_context), - quota_manager_proxy.get(), blob_context, origin)); + quota_manager_proxy.get(), blob_context, this, origin)); } CacheStorage::~CacheStorage() { @@ -676,7 +694,7 @@ void CacheStorage::LazyInitDidLoadIndex( 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())); + std::unique_ptr())); ordered_cache_names_.push_back(indexed_cache_names->at(i)); } @@ -688,9 +706,10 @@ void CacheStorage::LazyInitDidLoadIndex( void CacheStorage::OpenCacheImpl(const std::string& cache_name, const CacheAndErrorCallback& callback) { - scoped_refptr cache = GetLoadedCache(cache_name); - if (cache.get()) { - callback.Run(std::move(cache), CACHE_STORAGE_OK); + std::unique_ptr cache_handle = + GetLoadedCache(cache_name); + if (cache_handle) { + callback.Run(std::move(cache_handle), CACHE_STORAGE_OK); return; } @@ -702,39 +721,45 @@ void CacheStorage::OpenCacheImpl(const std::string& cache_name, void CacheStorage::CreateCacheDidCreateCache( const std::string& cache_name, const CacheAndErrorCallback& callback, - scoped_refptr cache) { + std::unique_ptr cache) { DCHECK_CURRENTLY_ON(BrowserThread::IO); UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult", static_cast(cache)); - if (!cache.get()) { - callback.Run(scoped_refptr(), + if (!cache) { + callback.Run(std::unique_ptr(), CACHE_STORAGE_ERROR_STORAGE); return; } - cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr())); + CacheStorageCache* cache_ptr = cache.get(); + + cache_map_.insert(std::make_pair(cache_name, std::move(cache))); ordered_cache_names_.push_back(cache_name); - TemporarilyPreserveCache(cache); + if (memory_only_) { + static_cast(cache_loader_.get()) + ->StoreCacheHandle(cache_name, CreateCacheHandle(cache_ptr)); + } cache_loader_->WriteIndex( ordered_cache_names_, base::Bind(&CacheStorage::CreateCacheDidWriteIndex, - weak_factory_.GetWeakPtr(), callback, std::move(cache))); + weak_factory_.GetWeakPtr(), callback, + base::Passed(CreateCacheHandle(cache_ptr)))); } void CacheStorage::CreateCacheDidWriteIndex( const CacheAndErrorCallback& callback, - scoped_refptr cache, + std::unique_ptr cache_handle, bool success) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(cache.get()); + DCHECK(cache_handle); // TODO(jkarlin): Handle !success. - callback.Run(std::move(cache), CACHE_STORAGE_OK); + callback.Run(std::move(cache_handle), CACHE_STORAGE_OK); } void CacheStorage::HasCacheImpl(const std::string& cache_name, @@ -745,14 +770,17 @@ void CacheStorage::HasCacheImpl(const std::string& cache_name, void CacheStorage::DeleteCacheImpl(const std::string& cache_name, const BoolAndErrorCallback& callback) { - scoped_refptr cache = GetLoadedCache(cache_name); - if (!cache.get()) { + std::unique_ptr cache_handle = + GetLoadedCache(cache_name); + if (!cache_handle) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_NOT_FOUND)); return; } CacheMap::iterator map_iter = cache_map_.find(cache_name); + deleted_caches_.insert( + std::make_pair(cache_handle->value(), std::move(map_iter->second))); cache_map_.erase(map_iter); // Delete the name from ordered_cache_names_. @@ -761,16 +789,19 @@ void CacheStorage::DeleteCacheImpl(const std::string& cache_name, DCHECK(iter != ordered_cache_names_.end()); ordered_cache_names_.erase(iter); - cache->GetSizeThenClose(base::Bind(&CacheStorage::DeleteCacheDidClose, - weak_factory_.GetWeakPtr(), cache_name, - callback, ordered_cache_names_, cache)); + CacheStorageCache* cache_ptr = cache_handle->value(); + cache_ptr->GetSizeThenClose( + base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(), + cache_name, callback, ordered_cache_names_, + base::Passed(std::move(cache_handle)))); } -void CacheStorage::DeleteCacheDidClose(const std::string& cache_name, - const BoolAndErrorCallback& callback, - const StringVector& ordered_cache_names, - scoped_refptr cache, - int64_t cache_size) { +void CacheStorage::DeleteCacheDidClose( + const std::string& cache_name, + const BoolAndErrorCallback& callback, + const StringVector& ordered_cache_names, + std::unique_ptr cache_handle, + int64_t cache_size) { cache_loader_->WriteIndex( ordered_cache_names, base::Bind(&CacheStorage::DeleteCacheDidWriteIndex, @@ -809,24 +840,27 @@ void CacheStorage::MatchCacheImpl( const std::string& cache_name, std::unique_ptr request, const CacheStorageCache::ResponseCallback& callback) { - scoped_refptr cache = GetLoadedCache(cache_name); + std::unique_ptr cache_handle = + GetLoadedCache(cache_name); - if (!cache.get()) { + if (!cache_handle) { callback.Run(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND, std::unique_ptr(), std::unique_ptr()); return; } - // Pass the cache along to the callback to keep the cache open until match is - // done. - cache->Match(std::move(request), - base::Bind(&CacheStorage::MatchCacheDidMatch, - weak_factory_.GetWeakPtr(), cache, callback)); + // Pass the cache handle along to the callback to keep the cache open until + // match is done. + CacheStorageCache* cache_ptr = cache_handle->value(); + cache_ptr->Match( + std::move(request), + base::Bind(&CacheStorage::MatchCacheDidMatch, weak_factory_.GetWeakPtr(), + base::Passed(std::move(cache_handle)), callback)); } void CacheStorage::MatchCacheDidMatch( - scoped_refptr cache, + std::unique_ptr cache_handle, const CacheStorageCache::ResponseCallback& callback, CacheStorageError error, std::unique_ptr response, @@ -847,19 +881,21 @@ void CacheStorage::MatchAllCachesImpl( base::Passed(base::WrapUnique(match_responses)), callback)); for (size_t i = 0, max = ordered_cache_names_.size(); i < max; ++i) { - scoped_refptr cache = + std::unique_ptr cache_handle = GetLoadedCache(ordered_cache_names_[i]); - DCHECK(cache.get()); - - cache->Match(base::WrapUnique(new ServiceWorkerFetchRequest(*request)), - base::Bind(&CacheStorage::MatchAllCachesDidMatch, - weak_factory_.GetWeakPtr(), cache, - &match_responses->at(i), barrier_closure)); + DCHECK(cache_handle); + + CacheStorageCache* cache_ptr = cache_handle->value(); + cache_ptr->Match(base::WrapUnique(new ServiceWorkerFetchRequest(*request)), + base::Bind(&CacheStorage::MatchAllCachesDidMatch, + weak_factory_.GetWeakPtr(), + base::Passed(std::move(cache_handle)), + &match_responses->at(i), barrier_closure)); } } void CacheStorage::MatchAllCachesDidMatch( - scoped_refptr cache, + std::unique_ptr cache_handle, CacheMatchResponse* out_match_response, const base::Closure& barrier_closure, CacheStorageError error, @@ -888,54 +924,70 @@ void CacheStorage::MatchAllCachesDidMatchAll( std::unique_ptr()); } -scoped_refptr CacheStorage::GetLoadedCache( - const std::string& cache_name) { +void CacheStorage::AddCacheHandleRef(CacheStorageCache* cache) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(initialized_); - - CacheMap::iterator map_iter = cache_map_.find(cache_name); - if (map_iter == cache_map_.end()) - return scoped_refptr(); + auto iter = cache_handle_counts_.find(cache); + if (iter == cache_handle_counts_.end()) { + cache_handle_counts_[cache] = 1; + return; + } - base::WeakPtr cache = map_iter->second; + iter->second += 1; +} - if (!cache) { - scoped_refptr new_cache = - cache_loader_->CreateCache(cache_name); - map_iter->second = new_cache->AsWeakPtr(); +void CacheStorage::DropCacheHandleRef(CacheStorageCache* cache) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + auto iter = cache_handle_counts_.find(cache); + DCHECK(iter != cache_handle_counts_.end()); + DCHECK(iter->second >= 1); + + iter->second -= 1; + if (iter->second == 0) { + // Delete the CacheStorageCache object. It's either in the main cache map or + // the CacheStorage::Delete operation has run on the cache, in which case + // it's in the deleted caches map. + auto cache_map_iter = cache_map_.find(cache->cache_name()); + + if (cache_map_iter == cache_map_.end()) { + auto deleted_caches_iter = deleted_caches_.find(cache); + DCHECK(deleted_caches_iter != deleted_caches_.end()); + deleted_caches_.erase(deleted_caches_iter); + return; + } - TemporarilyPreserveCache(new_cache); - return new_cache; + cache_map_iter->second.reset(); + cache_handle_counts_.erase(iter); } +} - return make_scoped_refptr(cache.get()); +std::unique_ptr CacheStorage::CreateCacheHandle( + CacheStorageCache* cache) { + DCHECK(cache); + return std::unique_ptr(new CacheStorageCacheHandle( + cache->AsWeakPtr(), weak_factory_.GetWeakPtr())); } -void CacheStorage::TemporarilyPreserveCache( - scoped_refptr cache) { +std::unique_ptr CacheStorage::GetLoadedCache( + const std::string& cache_name) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!ContainsKey(preserved_caches_, cache.get())); + DCHECK(initialized_); - preserved_caches_[cache.get()] = cache; - SchedulePreservedCacheRemoval(base::Bind(&CacheStorage::RemovePreservedCache, - weak_factory_.GetWeakPtr(), - base::Unretained(cache.get()))); -} + CacheMap::iterator map_iter = cache_map_.find(cache_name); + if (map_iter == cache_map_.end()) + return std::unique_ptr(); -void CacheStorage::SchedulePreservedCacheRemoval( - const base::Closure& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + CacheStorageCache* cache = map_iter->second.get(); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, callback, - base::TimeDelta::FromSeconds(kCachePreservationInSecs)); -} + if (!cache) { + std::unique_ptr new_cache = + cache_loader_->CreateCache(cache_name); + CacheStorageCache* cache_ptr = new_cache.get(); + map_iter->second = std::move(new_cache); -void CacheStorage::RemovePreservedCache(const CacheStorageCache* cache) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(ContainsKey(preserved_caches_, cache)); + return CreateCacheHandle(cache_ptr); + } - preserved_caches_.erase(cache); + return CreateCacheHandle(cache); } void CacheStorage::GetSizeThenCloseAllCachesImpl(const SizeCallback& callback) { @@ -951,8 +1003,11 @@ void CacheStorage::GetSizeThenCloseAllCachesImpl(const SizeCallback& callback) { base::Passed(std::move(accumulator)), callback)); for (const std::string& cache_name : ordered_cache_names_) { - scoped_refptr cache = GetLoadedCache(cache_name); - cache->GetSizeThenClose(base::Bind(&SizeRetrievedFromCache, cache, + std::unique_ptr cache_handle = + GetLoadedCache(cache_name); + CacheStorageCache* cache = cache_handle->value(); + cache->GetSizeThenClose(base::Bind(&SizeRetrievedFromCache, + base::Passed(std::move(cache_handle)), barrier_closure, accumulator_ptr)); } } @@ -970,9 +1025,12 @@ void CacheStorage::SizeImpl(const SizeCallback& callback) { base::Passed(std::move(accumulator)), callback)); for (const std::string& cache_name : ordered_cache_names_) { - scoped_refptr cache = GetLoadedCache(cache_name); - cache->Size(base::Bind(&SizeRetrievedFromCache, cache, barrier_closure, - accumulator_ptr)); + std::unique_ptr cache_handle = + GetLoadedCache(cache_name); + CacheStorageCache* cache = cache_handle->value(); + cache->Size(base::Bind(&SizeRetrievedFromCache, + base::Passed(std::move(cache_handle)), + barrier_closure, accumulator_ptr)); } } @@ -997,11 +1055,11 @@ void CacheStorage::PendingBoolAndErrorCallback( void CacheStorage::PendingCacheAndErrorCallback( const CacheAndErrorCallback& callback, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error) { base::WeakPtr cache_storage = weak_factory_.GetWeakPtr(); - callback.Run(std::move(cache), error); + callback.Run(std::move(cache_handle), error); if (cache_storage) scheduler_->CompleteOperationAndRunNext(); } diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h index 2cea28b2cd7..20376c1257e 100644 --- a/chromium/content/browser/cache_storage/cache_storage.h +++ b/chromium/content/browser/cache_storage/cache_storage.h @@ -31,6 +31,7 @@ class BlobStorageContext; namespace content { class CacheStorageScheduler; +class CacheStorageCacheHandle; // TODO(jkarlin): Constrain the total bytes used per origin. @@ -41,7 +42,7 @@ class CONTENT_EXPORT CacheStorage { public: typedef std::vector StringVector; typedef base::Callback BoolAndErrorCallback; - typedef base::Callback, + typedef base::Callback, CacheStorageError)> CacheAndErrorCallback; typedef base::Callback @@ -64,7 +65,10 @@ class CONTENT_EXPORT CacheStorage { virtual ~CacheStorage(); // Get the cache for the given key. If the cache is not found it is - // created. + // created. The CacheStorgeCacheHandle in the callback prolongs the lifetime + // of the cache. Once all handles to a cache are deleted the cache is deleted. + // The cache will also be deleted in the CacheStorage's destructor so be sure + // to check the handle's value before using it. void OpenCache(const std::string& cache_name, const CacheAndErrorCallback& callback); @@ -106,24 +110,25 @@ class CONTENT_EXPORT CacheStorage { void CompleteAsyncOperationForTesting(); private: - friend class TestCacheStorage; + friend class CacheStorageCacheHandle; + friend class CacheStorageCache; class CacheLoader; class MemoryLoader; class SimpleCacheLoader; struct CacheMatchResponse; - typedef std::map> CacheMap; + typedef std::map> CacheMap; - // Return a CacheStorageCache for the given name if the name is known. If the - // CacheStorageCache has been deleted, creates a new one. - scoped_refptr GetLoadedCache( - const std::string& cache_name); + // Functions for exposing handles to CacheStorageCache to clients. + std::unique_ptr CreateCacheHandle( + CacheStorageCache* cache); + void AddCacheHandleRef(CacheStorageCache* cache); + void DropCacheHandleRef(CacheStorageCache* cache); - // Holds a reference to a cache for thirty seconds. - void TemporarilyPreserveCache(scoped_refptr cache); - virtual void SchedulePreservedCacheRemoval( - const base::Closure& callback); // Virtual for testing. - void RemovePreservedCache(const CacheStorageCache* cache); + // Returns a CacheStorageCacheHandle for the given name if the name is known. + // If the CacheStorageCache has been deleted, creates a new one. + std::unique_ptr GetLoadedCache( + const std::string& cache_name); // Initializer and its callback are below. void LazyInit(); @@ -136,10 +141,11 @@ class CONTENT_EXPORT CacheStorage { const CacheAndErrorCallback& callback); void CreateCacheDidCreateCache(const std::string& cache_name, const CacheAndErrorCallback& callback, - scoped_refptr cache); - void CreateCacheDidWriteIndex(const CacheAndErrorCallback& callback, - scoped_refptr cache, - bool success); + std::unique_ptr cache); + void CreateCacheDidWriteIndex( + const CacheAndErrorCallback& callback, + std::unique_ptr cache_handle, + bool success); // The HasCache callbacks are below. void HasCacheImpl(const std::string& cache_name, @@ -149,11 +155,12 @@ class CONTENT_EXPORT CacheStorage { void DeleteCacheImpl(const std::string& cache_name, const BoolAndErrorCallback& callback); - void DeleteCacheDidClose(const std::string& cache_name, - const BoolAndErrorCallback& callback, - const StringVector& ordered_cache_names, - scoped_refptr cache, - int64_t cache_size); + void DeleteCacheDidClose( + const std::string& cache_name, + const BoolAndErrorCallback& callback, + const StringVector& ordered_cache_names, + std::unique_ptr cache_handle, + int64_t cache_size); void DeleteCacheDidWriteIndex(const std::string& cache_name, const BoolAndErrorCallback& callback, int cache_size, @@ -168,7 +175,7 @@ class CONTENT_EXPORT CacheStorage { void MatchCacheImpl(const std::string& cache_name, std::unique_ptr request, const CacheStorageCache::ResponseCallback& callback); - void MatchCacheDidMatch(scoped_refptr cache, + void MatchCacheDidMatch(std::unique_ptr cache_handle, const CacheStorageCache::ResponseCallback& callback, CacheStorageError error, std::unique_ptr response, @@ -178,7 +185,7 @@ class CONTENT_EXPORT CacheStorage { void MatchAllCachesImpl(std::unique_ptr request, const CacheStorageCache::ResponseCallback& callback); void MatchAllCachesDidMatch( - scoped_refptr cache, + std::unique_ptr cache_handle, CacheMatchResponse* out_match_response, const base::Closure& barrier_closure, CacheStorageError error, @@ -196,9 +203,10 @@ class CONTENT_EXPORT CacheStorage { void PendingBoolAndErrorCallback(const BoolAndErrorCallback& callback, bool found, CacheStorageError error); - void PendingCacheAndErrorCallback(const CacheAndErrorCallback& callback, - scoped_refptr cache, - CacheStorageError error); + void PendingCacheAndErrorCallback( + const CacheAndErrorCallback& callback, + std::unique_ptr cache_handle, + CacheStorageError error); void PendingStringsAndErrorCallback(const StringsAndErrorCallback& callback, const StringVector& strings, CacheStorageError error); @@ -214,12 +222,23 @@ class CONTENT_EXPORT CacheStorage { bool initialized_; bool initializing_; + // True if the backend is supposed to reside in memory only. + bool memory_only_; + // The pending operation scheduler. std::unique_ptr scheduler_; // The map of cache names to CacheStorageCache objects. CacheMap cache_map_; + // Caches that have been deleted but must still be held onto until all handles + // have been released. + std::map> + deleted_caches_; + + // CacheStorageCacheHandle reference counts + std::map cache_handle_counts_; + // The names of caches in the order that they were created. StringVector ordered_cache_names_; @@ -232,11 +251,6 @@ class CONTENT_EXPORT CacheStorage { // Performs backend specific operations (memory vs disk). std::unique_ptr cache_loader_; - // Holds ref pointers to recently opened caches so that they can be reused - // without having the open the cache again. - std::map> - preserved_caches_; - // The quota manager. scoped_refptr quota_manager_proxy_; diff --git a/chromium/content/browser/cache_storage/cache_storage.proto b/chromium/content/browser/cache_storage/cache_storage.proto index 07a61700cff..9850fa85684 100644 --- a/chromium/content/browser/cache_storage/cache_storage.proto +++ b/chromium/content/browser/cache_storage/cache_storage.proto @@ -43,6 +43,7 @@ message CacheResponse { repeated CacheHeaderMap headers = 4; optional string url = 5; optional int64 response_time = 6; + repeated string cors_exposed_header_names = 7; } message CacheMetadata { diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc index f94071a319e..5a9bb3dbc86 100644 --- a/chromium/content/browser/cache_storage/cache_storage_cache.cc +++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc @@ -18,6 +18,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/browser/cache_storage/cache_storage.pb.h" #include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h" +#include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/cache_storage/cache_storage_scheduler.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/referrer.h" @@ -42,14 +43,15 @@ namespace { class CacheStorageCacheDataHandle : public storage::BlobDataBuilder::DataHandle { public: - CacheStorageCacheDataHandle(scoped_refptr cache, - disk_cache::ScopedEntryPtr entry) - : cache_(cache), entry_(std::move(entry)) {} + CacheStorageCacheDataHandle( + std::unique_ptr cache_handle, + disk_cache::ScopedEntryPtr entry) + : cache_handle_(std::move(cache_handle)), entry_(std::move(entry)) {} private: ~CacheStorageCacheDataHandle() override {} - scoped_refptr cache_; + std::unique_ptr cache_handle_; disk_cache::ScopedEntryPtr entry_; DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheDataHandle); @@ -280,32 +282,32 @@ struct CacheStorageCache::PutContext { }; // static -scoped_refptr CacheStorageCache::CreateMemoryCache( +std::unique_ptr CacheStorageCache::CreateMemoryCache( const GURL& origin, const std::string& cache_name, + CacheStorage* cache_storage, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, base::WeakPtr blob_context) { - return make_scoped_refptr(new CacheStorageCache( - origin, cache_name, base::FilePath(), std::move(request_context_getter), - std::move(quota_manager_proxy), blob_context)); + return std::unique_ptr( + new CacheStorageCache(origin, cache_name, base::FilePath(), cache_storage, + std::move(request_context_getter), + std::move(quota_manager_proxy), blob_context)); } // static -scoped_refptr CacheStorageCache::CreatePersistentCache( +std::unique_ptr CacheStorageCache::CreatePersistentCache( const GURL& origin, const std::string& cache_name, + CacheStorage* cache_storage, const base::FilePath& path, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, base::WeakPtr blob_context) { - return make_scoped_refptr(new CacheStorageCache( - origin, cache_name, path, std::move(request_context_getter), - std::move(quota_manager_proxy), blob_context)); -} - -CacheStorageCache::~CacheStorageCache() { - quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_); + return std::unique_ptr( + new CacheStorageCache(origin, cache_name, path, cache_storage, + std::move(request_context_getter), + std::move(quota_manager_proxy), blob_context)); } base::WeakPtr CacheStorageCache::AsWeakPtr() { @@ -427,12 +429,12 @@ void CacheStorageCache::BatchDidGetUsageAndQuota( std::unique_ptr callback_copy(new ErrorCallback(callback)); ErrorCallback* callback_ptr = callback_copy.get(); base::Closure barrier_closure = base::BarrierClosure( - operations.size(), - base::Bind(&CacheStorageCache::BatchDidAllOperations, this, - base::Passed(std::move(callback_copy)))); + operations.size(), base::Bind(&CacheStorageCache::BatchDidAllOperations, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(std::move(callback_copy)))); ErrorCallback completion_callback = - base::Bind(&CacheStorageCache::BatchDidOneOperation, this, - barrier_closure, callback_ptr); + base::Bind(&CacheStorageCache::BatchDidOneOperation, + weak_ptr_factory_.GetWeakPtr(), barrier_closure, callback_ptr); for (const auto& operation : operations) { switch (operation.operation_type) { @@ -535,16 +537,22 @@ void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) { weak_ptr_factory_.GetWeakPtr(), pending_callback))); } +CacheStorageCache::~CacheStorageCache() { + quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_); +} + CacheStorageCache::CacheStorageCache( const GURL& origin, const std::string& cache_name, const base::FilePath& path, + CacheStorage* cache_storage, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, base::WeakPtr blob_context) : origin_(origin), cache_name_(cache_name), path_(path), + cache_storage_(cache_storage), request_context_getter_(std::move(request_context_getter)), quota_manager_proxy_(std::move(quota_manager_proxy)), blob_storage_context_(blob_context), @@ -954,7 +962,8 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation, operation.response.blob_size, operation.response.stream_url, operation.response.error, operation.response.response_time, false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */)); + std::string() /* cache_storage_cache_name */, + operation.response.cors_exposed_header_names)); std::unique_ptr blob_data_handle; @@ -971,6 +980,12 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation, } } + UMA_HISTOGRAM_ENUMERATION( + "ServiceWorkerCache.Cache.AllWritesResponseType", + operation.response.response_type, + blink::WebServiceWorkerResponseType::WebServiceWorkerResponseTypeLast + + 1); + ErrorCallback pending_callback = base::Bind(&CacheStorageCache::PendingErrorCallback, weak_ptr_factory_.GetWeakPtr(), callback); @@ -1066,6 +1081,8 @@ void CacheStorageCache::PutDidCreateEntry( header_map->set_name(it->first); header_map->set_value(it->second); } + for (const auto& header : put_context->response->cors_exposed_header_names) + response_metadata->add_cors_exposed_header_names(header); std::unique_ptr serialized(new std::string()); if (!metadata.SerializeToString(serialized.get())) { @@ -1155,16 +1172,20 @@ void CacheStorageCache::UpdateCacheSize() { if (backend_state_ != BACKEND_OPEN) return; - // Note that the callback holds a refptr to |this| since UpdateCacheSize is - // often called after an operation completes and the cache might be freed. - int rv = backend_->CalculateSizeOfAllEntries( - base::Bind(&CacheStorageCache::UpdateCacheSizeGotSize, this)); + // Note that the callback holds a cache handle to keep the cache alive during + // the operation since this UpdateCacheSize is often run after an operation + // completes and runs its callback. + int rv = backend_->CalculateSizeOfAllEntries(base::Bind( + &CacheStorageCache::UpdateCacheSizeGotSize, + weak_ptr_factory_.GetWeakPtr(), base::Passed(CreateCacheHandle()))); if (rv != net::ERR_IO_PENDING) - UpdateCacheSizeGotSize(rv); + UpdateCacheSizeGotSize(CreateCacheHandle(), rv); } -void CacheStorageCache::UpdateCacheSizeGotSize(int current_cache_size) { +void CacheStorageCache::UpdateCacheSizeGotSize( + std::unique_ptr cache_handle, + int current_cache_size) { int64_t old_cache_size = cache_size_; cache_size_ = current_cache_size; @@ -1528,7 +1549,10 @@ void CacheStorageCache::PopulateResponseMetadata( ServiceWorkerHeaderMap(), "", 0, GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time::FromInternalValue(metadata.response().response_time()), - true /* is_in_cache_storage */, cache_name_); + true /* is_in_cache_storage */, cache_name_, + ServiceWorkerHeaderList( + metadata.response().cors_exposed_header_names().begin(), + metadata.response().cors_exposed_header_names().end())); for (int i = 0; i < metadata.response().headers_size(); ++i) { const CacheHeaderMap header = metadata.response().headers(i); @@ -1550,9 +1574,14 @@ CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry, disk_cache::Entry* temp_entry = entry.get(); blob_data.AppendDiskCacheEntryWithSideData( - new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry, - INDEX_RESPONSE_BODY, INDEX_SIDE_DATA); + new CacheStorageCacheDataHandle(CreateCacheHandle(), std::move(entry)), + temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA); return blob_storage_context_->AddFinishedBlob(&blob_data); } +std::unique_ptr +CacheStorageCache::CreateCacheHandle() { + return cache_storage_->CreateCacheHandle(this); +} + } // namespace content diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h index 4b3a72e3207..787e13ad24a 100644 --- a/chromium/content/browser/cache_storage/cache_storage_cache.h +++ b/chromium/content/browser/cache_storage/cache_storage_cache.h @@ -13,7 +13,6 @@ #include "base/files/file_path.h" #include "base/id_map.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/common/cache_storage/cache_storage_types.h" #include "content/common/service_worker/service_worker_types.h" @@ -33,8 +32,9 @@ class QuotaManagerProxy; } namespace content { - +class CacheStorage; class CacheStorageBlobToDiskCache; +class CacheStorageCacheHandle; class CacheMetadata; class CacheStorageScheduler; class TestCacheStorageCache; @@ -43,8 +43,7 @@ class TestCacheStorageCache; // https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ The // asynchronous methods are executed serially. Callbacks to the public functions // will be called so long as the cache object lives. -class CONTENT_EXPORT CacheStorageCache - : public base::RefCounted { +class CONTENT_EXPORT CacheStorageCache { public: using ErrorCallback = base::Callback; using ResponseCallback = @@ -64,15 +63,17 @@ class CONTENT_EXPORT CacheStorageCache enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA }; - static scoped_refptr CreateMemoryCache( + static std::unique_ptr CreateMemoryCache( const GURL& origin, const std::string& cache_name, + CacheStorage* cache_storage, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, base::WeakPtr blob_context); - static scoped_refptr CreatePersistentCache( + static std::unique_ptr CreatePersistentCache( const GURL& origin, const std::string& cache_name, + CacheStorage* cache_storage, const base::FilePath& path, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, @@ -142,8 +143,13 @@ class CONTENT_EXPORT CacheStorageCache // the cache's size. void GetSizeThenClose(const SizeCallback& callback); + // Async operations in progress will cancel and not run their callbacks. + virtual ~CacheStorageCache(); + base::FilePath path() const { return path_; } + std::string cache_name() const { return cache_name_; } + base::WeakPtr AsWeakPtr(); private: @@ -175,13 +181,11 @@ class CONTENT_EXPORT CacheStorageCache const GURL& origin, const std::string& cache_name, const base::FilePath& path, + CacheStorage* cache_storage, scoped_refptr request_context_getter, scoped_refptr quota_manager_proxy, base::WeakPtr blob_context); - // Async operations in progress will cancel and not run their callbacks. - virtual ~CacheStorageCache(); - // Returns true if the backend is ready to operate. bool LazyInitialize(); @@ -280,9 +284,10 @@ class CONTENT_EXPORT CacheStorageCache // Asynchronously calculates the current cache size, notifies the quota // manager of any change from the last report, and sets cache_size_ to the new - // size. Runs |callback| once complete. + // size. void UpdateCacheSize(); - void UpdateCacheSizeGotSize(int current_cache_size); + void UpdateCacheSizeGotSize(std::unique_ptr, + int current_cache_size); // Returns ERROR_NOT_FOUND if not found. Otherwise deletes and returns OK. void Delete(const CacheStorageBatchOperation& operation, @@ -355,12 +360,19 @@ class CONTENT_EXPORT CacheStorageCache disk_cache::ScopedEntryPtr entry, ServiceWorkerResponse* response); + // Virtual for testing. + virtual std::unique_ptr CreateCacheHandle(); + // Be sure to check |backend_state_| before use. std::unique_ptr backend_; GURL origin_; const std::string cache_name_; base::FilePath path_; + + // Raw pointer is safe because CacheStorage owns this object. + CacheStorage* cache_storage_; + scoped_refptr request_context_getter_; scoped_refptr quota_manager_proxy_; base::WeakPtr blob_storage_context_; diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc b/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc new file mode 100644 index 00000000000..13cdebd541e --- /dev/null +++ b/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc @@ -0,0 +1,28 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/cache_storage/cache_storage_cache_handle.h" + +namespace content { + +CacheStorageCacheHandle::~CacheStorageCacheHandle() { + if (cache_storage_ && cache_storage_cache_) + cache_storage_->DropCacheHandleRef(cache_storage_cache_.get()); +} + +std::unique_ptr CacheStorageCacheHandle::Clone() { + return std::unique_ptr( + new CacheStorageCacheHandle(cache_storage_cache_, cache_storage_)); +} + +CacheStorageCacheHandle::CacheStorageCacheHandle( + base::WeakPtr cache_storage_cache, + base::WeakPtr cache_storage) + : cache_storage_cache_(cache_storage_cache), cache_storage_(cache_storage) { + DCHECK(cache_storage); + DCHECK(cache_storage_cache_); + cache_storage_->AddCacheHandleRef(cache_storage_cache_.get()); +} + +} // namespace content diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_handle.h b/chromium/content/browser/cache_storage/cache_storage_cache_handle.h new file mode 100644 index 00000000000..9a043bbd0e8 --- /dev/null +++ b/chromium/content/browser/cache_storage/cache_storage_cache_handle.h @@ -0,0 +1,41 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_ +#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_ + +#include "base/memory/weak_ptr.h" +#include "content/browser/cache_storage/cache_storage.h" +#include "content/browser/cache_storage/cache_storage_cache.h" + +namespace content { + +// Holds a reference to a CacheStorageCache. The CacheStorage will keep the +// CacheStorageCache alive until the last handle is destroyed or the +// CacheStorage is deleted. +class CONTENT_EXPORT CacheStorageCacheHandle { + public: + ~CacheStorageCacheHandle(); + + // Returns the underlying CacheStorageCache*. Will return nullptr if the + // CacheStorage has been deleted. + CacheStorageCache* value() { return cache_storage_cache_.get(); } + + std::unique_ptr Clone(); + + private: + friend class CacheStorage; + + CacheStorageCacheHandle(base::WeakPtr cache_storage_cache, + base::WeakPtr cache_storage); + + base::WeakPtr cache_storage_cache_; + base::WeakPtr cache_storage_; + + DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheHandle); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_ diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc index 81af984dbb1..e800a4b11d1 100644 --- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc @@ -19,6 +19,7 @@ #include "base/strings/string_split.h" #include "base/threading/thread_task_runner_handle.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" +#include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/fileapi/mock_url_request_delegate.h" #include "content/browser/quota/mock_quota_manager_proxy.h" #include "content/common/cache_storage/cache_storage_types.h" @@ -228,6 +229,11 @@ bool ResponseMetadataEqual(const ServiceWorkerResponse& expected, if (expected.cache_storage_cache_name != actual.cache_storage_cache_name) return false; + EXPECT_EQ(expected.cors_exposed_header_names, + actual.cors_exposed_header_names); + if (expected.cors_exposed_header_names != actual.cors_exposed_header_names) + return false; + return true; } @@ -246,11 +252,10 @@ bool ResponseSideDataEqual(const std::string& expected_side_data, } ServiceWorkerResponse SetCacheName(const ServiceWorkerResponse& original) { - return ServiceWorkerResponse( - original.url, original.status_code, original.status_text, - original.response_type, original.headers, original.blob_uuid, - original.blob_size, original.stream_url, original.error, - original.response_time, true, kCacheName); + ServiceWorkerResponse result(original); + result.is_in_cache_storage = true; + result.cache_storage_cache_name = kCacheName; + return result; } } // namespace @@ -262,12 +267,14 @@ class TestCacheStorageCache : public CacheStorageCache { const GURL& origin, const std::string& cache_name, const base::FilePath& path, + CacheStorage* cache_storage, const scoped_refptr& request_context_getter, const scoped_refptr& quota_manager_proxy, base::WeakPtr blob_context) : CacheStorageCache(origin, cache_name, path, + cache_storage, request_context_getter, quota_manager_proxy, blob_context), @@ -299,7 +306,11 @@ class TestCacheStorageCache : public CacheStorageCache { } private: - ~TestCacheStorageCache() override {} + std::unique_ptr CreateCacheHandle() override { + // Returns an empty handle. There is no need for CacheStorage and its + // handles in these tests. + return std::unique_ptr(); + } bool delay_backend_creation_; ErrorCallback backend_creation_callback_; @@ -345,11 +356,11 @@ class CacheStorageCacheTest : public testing::Test { CreateRequests(blob_storage_context); - cache_ = make_scoped_refptr(new TestCacheStorageCache( - GURL(kOrigin), kCacheName, temp_dir_.path(), - BrowserContext::GetDefaultStoragePartition(&browser_context_)-> - GetURLRequestContext(), - quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr())); + cache_ = base::MakeUnique( + GURL(kOrigin), kCacheName, temp_dir_.path(), nullptr /* CacheStorage */, + BrowserContext::GetDefaultStoragePartition(&browser_context_) + ->GetURLRequestContext(), + quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()); } void TearDown() override { @@ -388,7 +399,8 @@ class CacheStorageCacheTest : public testing::Test { blob_handle_->uuid(), expected_blob_data_.size(), GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(), false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */); + std::string() /* cache_storage_cache_name */, + ServiceWorkerHeaderList() /* cors_exposed_header_names */); body_response_with_query_ = ServiceWorkerResponse( GURL("http://example.com/body.html?query=test"), 200, "OK", @@ -396,14 +408,16 @@ class CacheStorageCacheTest : public testing::Test { blob_handle_->uuid(), expected_blob_data_.size(), GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(), false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */); + std::string() /* cache_storage_cache_name */, + {"a"} /* cors_exposed_header_names */); no_body_response_ = ServiceWorkerResponse( GURL("http://example.com/no_body.html"), 200, "OK", blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(), false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */); + std::string() /* cache_storage_cache_name */, + ServiceWorkerHeaderList() /* cors_exposed_header_names */); } std::unique_ptr CopyFetchRequest( @@ -663,7 +677,7 @@ class CacheStorageCacheTest : public testing::Test { scoped_refptr quota_manager_proxy_; storage::BlobStorageContext* blob_storage_context_; - scoped_refptr cache_; + std::unique_ptr cache_; ServiceWorkerFetchRequest body_request_; ServiceWorkerResponse body_response_; @@ -1224,12 +1238,13 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_NotFound) { TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) { // CacheStorageCache depends on ServiceWorkerResponse having caseless // headers so that it can quickly lookup vary headers. - ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK", - blink::WebServiceWorkerResponseTypeDefault, - ServiceWorkerHeaderMap(), "", 0, GURL(), - blink::WebServiceWorkerResponseErrorUnknown, - base::Time(), false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */); + ServiceWorkerResponse response( + GURL("http://www.example.com"), 200, "OK", + blink::WebServiceWorkerResponseTypeDefault, ServiceWorkerHeaderMap(), "", + 0, GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time(), + false /* is_in_cache_storage */, + std::string() /* cache_storage_cache_name */, + ServiceWorkerHeaderList() /* cors_exposed_header_names */); response.headers["content-type"] = "foo"; response.headers["Content-Type"] = "bar"; EXPECT_EQ("bar", response.headers["content-type"]); diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc index a12c93d6b6c..c34259ffc8e 100644 --- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc +++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc @@ -12,9 +12,12 @@ #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "content/browser/bad_message.h" #include "content/browser/cache_storage/cache_storage_cache.h" +#include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/cache_storage/cache_storage_context_impl.h" #include "content/browser/cache_storage/cache_storage_manager.h" #include "content/common/cache_storage/cache_storage_messages.h" @@ -30,6 +33,7 @@ namespace content { namespace { const uint32_t kFilteredMessageClasses[] = {CacheStorageMsgStart}; +const int32_t kCachePreservationSeconds = 5; blink::WebServiceWorkerCacheError ToWebServiceWorkerCacheError( CacheStorageError err) { @@ -58,12 +62,14 @@ bool OriginCanAccessCacheStorage(const url::Origin& origin) { return !origin.unique() && IsOriginSecure(GURL(origin.Serialize())); } +void StopPreservingCache( + std::unique_ptr cache_handle) {} + } // namespace CacheStorageDispatcherHost::CacheStorageDispatcherHost() : BrowserMessageFilter(kFilteredMessageClasses, - arraysize(kFilteredMessageClasses)) { -} + arraysize(kFilteredMessageClasses)) {} CacheStorageDispatcherHost::~CacheStorageDispatcherHost() { } @@ -216,20 +222,21 @@ void CacheStorageDispatcherHost::OnCacheMatch( const ServiceWorkerFetchRequest& request, const CacheStorageCacheQueryParams& match_params) { IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id); - if (it == id_to_cache_map_.end()) { + if (it == id_to_cache_map_.end() || !it->second->value()) { Send(new CacheStorageMsg_CacheMatchError( thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); return; } - scoped_refptr cache = it->second; + CacheStorageCache* cache = it->second->value(); std::unique_ptr scoped_request( new ServiceWorkerFetchRequest(request.url, request.method, request.headers, request.referrer, request.is_reload)); - cache->Match(std::move(scoped_request), - base::Bind(&CacheStorageDispatcherHost::OnCacheMatchCallback, - this, thread_id, request_id, cache)); + cache->Match( + std::move(scoped_request), + base::Bind(&CacheStorageDispatcherHost::OnCacheMatchCallback, this, + thread_id, request_id, base::Passed(it->second->Clone()))); } void CacheStorageDispatcherHost::OnCacheMatchAll( @@ -239,18 +246,18 @@ void CacheStorageDispatcherHost::OnCacheMatchAll( const ServiceWorkerFetchRequest& request, const CacheStorageCacheQueryParams& match_params) { IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id); - if (it == id_to_cache_map_.end()) { + if (it == id_to_cache_map_.end() || !it->second->value()) { Send(new CacheStorageMsg_CacheMatchError( thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); return; } - scoped_refptr cache = it->second; + CacheStorageCache* cache = it->second->value(); if (request.url.is_empty()) { cache->MatchAll( std::unique_ptr(), match_params, base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this, - thread_id, request_id, cache)); + thread_id, request_id, base::Passed(it->second->Clone()))); return; } @@ -262,13 +269,14 @@ void CacheStorageDispatcherHost::OnCacheMatchAll( cache->MatchAll( std::move(scoped_request), match_params, base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this, - thread_id, request_id, cache)); + thread_id, request_id, base::Passed(it->second->Clone()))); return; } cache->Match( std::move(scoped_request), base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter, - this, thread_id, request_id, cache)); + this, thread_id, request_id, + base::Passed(it->second->Clone()))); } void CacheStorageDispatcherHost::OnCacheKeys( @@ -278,16 +286,16 @@ void CacheStorageDispatcherHost::OnCacheKeys( const ServiceWorkerFetchRequest& request, const CacheStorageCacheQueryParams& match_params) { IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id); - if (it == id_to_cache_map_.end()) { + if (it == id_to_cache_map_.end() || !it->second->value()) { Send(new CacheStorageMsg_CacheKeysError( thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); return; } - scoped_refptr cache = it->second; - + CacheStorageCache* cache = it->second->value(); cache->Keys(base::Bind(&CacheStorageDispatcherHost::OnCacheKeysCallback, this, - thread_id, request_id, cache)); + thread_id, request_id, + base::Passed(it->second->Clone()))); } void CacheStorageDispatcherHost::OnCacheBatch( @@ -296,15 +304,17 @@ void CacheStorageDispatcherHost::OnCacheBatch( int cache_id, const std::vector& operations) { IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id); - if (it == id_to_cache_map_.end()) { + if (it == id_to_cache_map_.end() || !it->second->value()) { Send(new CacheStorageMsg_CacheBatchError( thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); return; } - scoped_refptr cache = it->second; + + CacheStorageCache* cache = it->second->value(); cache->BatchOperation( - operations, base::Bind(&CacheStorageDispatcherHost::OnCacheBatchCallback, - this, thread_id, request_id, cache)); + operations, + base::Bind(&CacheStorageDispatcherHost::OnCacheBatchCallback, this, + thread_id, request_id, base::Passed(it->second->Clone()))); } void CacheStorageDispatcherHost::OnCacheClosed(int cache_id) { @@ -336,14 +346,22 @@ void CacheStorageDispatcherHost::OnCacheStorageHasCallback( void CacheStorageDispatcherHost::OnCacheStorageOpenCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error) { if (error != CACHE_STORAGE_OK) { Send(new CacheStorageMsg_CacheStorageOpenError( thread_id, request_id, ToWebServiceWorkerCacheError(error))); return; } - CacheID cache_id = StoreCacheReference(std::move(cache)); + + // Hang on to the cache for a few seconds. This way if the user quickly closes + // and reopens it the cache backend won't have to be reinitialized. + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::Bind(&StopPreservingCache, base::Passed(cache_handle->Clone())), + base::TimeDelta::FromSeconds(kCachePreservationSeconds)); + + CacheID cache_id = StoreCacheReference(std::move(cache_handle)); Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id, request_id, cache_id)); } @@ -402,7 +420,7 @@ void CacheStorageDispatcherHost::OnCacheStorageMatchCallback( void CacheStorageDispatcherHost::OnCacheMatchCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr response, std::unique_ptr blob_data_handle) { @@ -421,7 +439,7 @@ void CacheStorageDispatcherHost::OnCacheMatchCallback( void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr response, std::unique_ptr blob_data_handle) { @@ -435,14 +453,14 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter( if (blob_data_handle) blob_data_handles->push_back(*blob_data_handle); } - OnCacheMatchAllCallback(thread_id, request_id, std::move(cache), error, + OnCacheMatchAllCallback(thread_id, request_id, std::move(cache_handle), error, std::move(responses), std::move(blob_data_handles)); } void CacheStorageDispatcherHost::OnCacheMatchAllCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr responses, std::unique_ptr blob_data_handles) { @@ -462,7 +480,7 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallback( void CacheStorageDispatcherHost::OnCacheKeysCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr requests) { if (error != CACHE_STORAGE_OK) { @@ -486,7 +504,7 @@ void CacheStorageDispatcherHost::OnCacheKeysCallback( void CacheStorageDispatcherHost::OnCacheBatchCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error) { if (error != CACHE_STORAGE_OK) { Send(new CacheStorageMsg_CacheBatchError( @@ -499,9 +517,9 @@ void CacheStorageDispatcherHost::OnCacheBatchCallback( CacheStorageDispatcherHost::CacheID CacheStorageDispatcherHost::StoreCacheReference( - scoped_refptr cache) { + std::unique_ptr cache_handle) { int cache_id = next_cache_id_++; - id_to_cache_map_[cache_id] = std::move(cache); + id_to_cache_map_[cache_id] = std::move(cache_handle); return cache_id; } diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h index a62755fce03..d937bac0348 100644 --- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h +++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h @@ -41,7 +41,8 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter { friend class base::DeleteHelper; typedef int32_t CacheID; // TODO(jkarlin): Bump to 64 bit. - typedef std::map> IDToCacheMap; + typedef std::map> + IDToCacheMap; typedef std::map> UUIDToBlobDataHandleList; @@ -95,10 +96,11 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter { int request_id, bool has_cache, CacheStorageError error); - void OnCacheStorageOpenCallback(int thread_id, - int request_id, - scoped_refptr cache, - CacheStorageError error); + void OnCacheStorageOpenCallback( + int thread_id, + int request_id, + std::unique_ptr cache_handle, + CacheStorageError error); void OnCacheStorageDeleteCallback(int thread_id, int request_id, bool deleted, @@ -118,21 +120,21 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter { void OnCacheMatchCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr response, std::unique_ptr blob_data_handle); void OnCacheMatchAllCallbackAdapter( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr response, std::unique_ptr blob_data_handle); void OnCacheMatchAllCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr> responses, std::unique_ptr blob_data_handles); @@ -144,18 +146,19 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter { void OnCacheKeysCallback( int thread_id, int request_id, - scoped_refptr cache, + std::unique_ptr cache_handle, CacheStorageError error, std::unique_ptr requests); - void OnCacheBatchCallback(int thread_id, - int request_id, - scoped_refptr cache, - CacheStorageError error); + void OnCacheBatchCallback( + int thread_id, + int request_id, + std::unique_ptr cache_handle, + CacheStorageError error); - // Hangs onto a scoped_refptr for the cache if it isn't already doing so. - // Returns a unique cache_id. Call DropCacheReference when the client is done - // with this cache. - CacheID StoreCacheReference(scoped_refptr cache); + // Hangs onto a cache handle. Returns a unique cache_id. Call + // DropCacheReference when the reference is no longer needed. + CacheID StoreCacheReference( + std::unique_ptr cache_handle); void DropCacheReference(CacheID cache_id); // Stores blob handles while waiting for acknowledgement of receipt from the diff --git a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc index 123774e1dd9..0da84acf861 100644 --- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc @@ -22,6 +22,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/cache_storage/cache_storage.pb.h" +#include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/cache_storage/cache_storage_quota_client.h" #include "content/browser/quota/mock_quota_manager_proxy.h" #include "content/public/browser/browser_thread.h" @@ -121,10 +122,11 @@ class CacheStorageManagerTest : public testing::Test { run_loop->Quit(); } - void CacheAndErrorCallback(base::RunLoop* run_loop, - scoped_refptr cache, - CacheStorageError error) { - callback_cache_ = std::move(cache); + void CacheAndErrorCallback( + base::RunLoop* run_loop, + std::unique_ptr cache_handle, + CacheStorageError error) { + callback_cache_handle_ = std::move(cache_handle); callback_error_ = error; run_loop->Quit(); } @@ -148,7 +150,7 @@ class CacheStorageManagerTest : public testing::Test { std::unique_ptr response, std::unique_ptr blob_data_handle) { callback_error_ = error; - callback_cache_response_ = std::move(response); + callback_cache_handle_response_ = std::move(response); callback_data_handle_ = std::move(blob_data_handle); run_loop->Quit(); } @@ -163,9 +165,9 @@ class CacheStorageManagerTest : public testing::Test { bool error = callback_error_ != CACHE_STORAGE_OK; if (error) - EXPECT_TRUE(!callback_cache_.get()); + EXPECT_FALSE(callback_cache_handle_); else - EXPECT_TRUE(callback_cache_.get()); + EXPECT_TRUE(callback_cache_handle_); return !error; } @@ -252,7 +254,8 @@ class CacheStorageManagerTest : public testing::Test { ServiceWorkerHeaderMap(), blob_handle->uuid(), url.spec().size(), GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time(), false /* is_in_cache_storage */, - std::string() /* cache_storage_cache_name */); + std::string() /* cache_storage_cache_name */, + ServiceWorkerHeaderList() /* cors_exposed_header_names */); CacheStorageBatchOperation operation; operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT; @@ -349,10 +352,10 @@ class CacheStorageManagerTest : public testing::Test { scoped_refptr quota_manager_proxy_; std::unique_ptr cache_manager_; - scoped_refptr callback_cache_; + std::unique_ptr callback_cache_handle_; int callback_bool_; CacheStorageError callback_error_; - std::unique_ptr callback_cache_response_; + std::unique_ptr callback_cache_handle_response_; std::unique_ptr callback_data_handle_; std::vector callback_strings_; @@ -392,23 +395,26 @@ TEST_P(CacheStorageManagerTestP, OpenTwoCaches) { TEST_P(CacheStorageManagerTestP, CachePointersDiffer) { EXPECT_TRUE(Open(origin1_, "foo")); - scoped_refptr cache = callback_cache_; + std::unique_ptr cache_handle = + std::move(callback_cache_handle_); EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_NE(callback_cache_.get(), cache.get()); + EXPECT_NE(callback_cache_handle_->value(), cache_handle->value()); } TEST_P(CacheStorageManagerTestP, Open2CachesSameNameDiffOrigins) { EXPECT_TRUE(Open(origin1_, "foo")); - scoped_refptr cache = callback_cache_; + std::unique_ptr cache_handle = + std::move(callback_cache_handle_); EXPECT_TRUE(Open(origin2_, "foo")); - EXPECT_NE(cache.get(), callback_cache_.get()); + EXPECT_NE(cache_handle->value(), callback_cache_handle_->value()); } TEST_P(CacheStorageManagerTestP, OpenExistingCache) { EXPECT_TRUE(Open(origin1_, "foo")); - scoped_refptr cache = callback_cache_; + std::unique_ptr cache_handle = + std::move(callback_cache_handle_); EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_EQ(callback_cache_.get(), cache.get()); + EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value()); } TEST_P(CacheStorageManagerTestP, HasCache) { @@ -436,7 +442,8 @@ TEST_P(CacheStorageManagerTestP, DeleteTwice) { TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); // The quota manager gets updated after the put operation runs its callback so // run the event loop. base::RunLoop().RunUntilIdle(); @@ -478,33 +485,38 @@ TEST_P(CacheStorageManagerTestP, DeletedKeysGone) { TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"))); } TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar"))); EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo"))); EXPECT_EQ(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo"))); } TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/bar"))); EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_); } @@ -519,8 +531,8 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) { // with the same URL should work. (see crbug.com/542668) const GURL kTestURL = GURL("http://example.com/foo"); EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL)); - EXPECT_TRUE(CacheMatch(callback_cache_.get(), kTestURL)); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL)); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), kTestURL)); std::unique_ptr data_handle = std::move(callback_data_handle_); @@ -528,28 +540,29 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) { // The cache is deleted but the handle to one of its entries is still // open. Creating a new cache in the same directory would fail on Windows. EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL)); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL)); } TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(), + EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_->value(), GURL("http://example.com/foo"), 200)); EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(), + EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_->value(), GURL("http://example.com/foo"), 201)); EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo"))); // The caches need to be searched in order of creation, so verify that the // response came from the first cache. - EXPECT_EQ(200, callback_cache_response_->status_code); + EXPECT_EQ(200, callback_cache_handle_response_->status_code); } TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) { EXPECT_TRUE(Open(origin1_, "foo")); EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_TRUE(Open(origin1_, "baz")); EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo"))); @@ -557,9 +570,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) { TEST_P(CacheStorageManagerTestP, Chinese) { EXPECT_TRUE(Open(origin1_, "你好")); - scoped_refptr cache = callback_cache_; + std::unique_ptr cache_handle = + std::move(callback_cache_handle_); EXPECT_TRUE(Open(origin1_, "你好")); - EXPECT_EQ(callback_cache_.get(), cache.get()); + EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value()); EXPECT_TRUE(Keys(origin1_)); EXPECT_EQ(1u, callback_strings_.size()); EXPECT_STREQ("你好", callback_strings_[0].c_str()); @@ -567,9 +581,10 @@ TEST_P(CacheStorageManagerTestP, Chinese) { TEST_F(CacheStorageManagerTest, EmptyKey) { EXPECT_TRUE(Open(origin1_, "")); - scoped_refptr cache = callback_cache_; + std::unique_ptr cache_handle = + std::move(callback_cache_handle_); EXPECT_TRUE(Open(origin1_, "")); - EXPECT_EQ(cache.get(), callback_cache_.get()); + EXPECT_EQ(cache_handle->value(), callback_cache_handle_->value()); EXPECT_TRUE(Keys(origin1_)); EXPECT_EQ(1u, callback_strings_.size()); EXPECT_STREQ("", callback_strings_[0].c_str()); @@ -624,10 +639,32 @@ TEST_F(CacheStorageManagerTest, BadOriginName) { EXPECT_STREQ("foo", callback_strings_[0].c_str()); } +// With a persistent cache if the client drops its reference to a +// CacheStorageCache it should be deleted. +TEST_F(CacheStorageManagerTest, DropReference) { + EXPECT_TRUE(Open(origin1_, "foo")); + base::WeakPtr cache = + callback_cache_handle_->value()->AsWeakPtr(); + callback_cache_handle_ = nullptr; + EXPECT_FALSE(cache); +} + +// With a memory cache the cache can't be freed from memory until the client +// calls delete. +TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryLosesReferenceOnlyAfterDelete) { + EXPECT_TRUE(Open(origin1_, "foo")); + base::WeakPtr cache = + callback_cache_handle_->value()->AsWeakPtr(); + callback_cache_handle_ = nullptr; + EXPECT_TRUE(cache); + EXPECT_TRUE(Delete(origin1_, "foo")); + EXPECT_FALSE(cache); +} + TEST_P(CacheStorageManagerTestP, DeleteBeforeRelease) { EXPECT_TRUE(Open(origin1_, "foo")); EXPECT_TRUE(Delete(origin1_, "foo")); - EXPECT_TRUE(callback_cache_->AsWeakPtr()); + EXPECT_TRUE(callback_cache_handle_->value()); } TEST_P(CacheStorageManagerTestP, OpenRunsSerially) { @@ -642,25 +679,27 @@ TEST_P(CacheStorageManagerTestP, OpenRunsSerially) { base::Unretained(this), base::Unretained(&open_loop))); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(callback_cache_); + EXPECT_FALSE(callback_cache_handle_); cache_storage->CompleteAsyncOperationForTesting(); open_loop.Run(); - EXPECT_TRUE(callback_cache_); + EXPECT_TRUE(callback_cache_handle_); } TEST_P(CacheStorageManagerTestP, GetOriginUsage) { EXPECT_EQ(0, GetOriginUsage(origin1_)); EXPECT_TRUE(Open(origin1_, "foo")); EXPECT_EQ(0, GetOriginUsage(origin1_)); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); int64_t foo_size = GetOriginUsage(origin1_); EXPECT_LT(0, GetOriginUsage(origin1_)); EXPECT_EQ(0, GetOriginUsage(origin2_)); // Add the same entry into a second cache, the size should double. EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_EQ(2 * foo_size, GetOriginUsage(origin1_)); } @@ -668,12 +707,15 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) { EXPECT_EQ(0ULL, GetAllOriginsUsage().size()); // Put one entry in a cache on origin 1. EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); // Put two entries (of identical size) in a cache on origin 2. EXPECT_TRUE(Open(origin2_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/bar"))); std::vector usage = GetAllOriginsUsage(); EXPECT_EQ(2ULL, usage.size()); @@ -697,22 +739,27 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) { TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) { EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo2"))); EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/bar"))); int64_t origin_size = GetOriginUsage(origin1_); EXPECT_LT(0, origin_size); EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_)); - EXPECT_FALSE(CachePut(callback_cache_.get(), GURL("http://example.com/baz"))); + EXPECT_FALSE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/baz"))); } TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) { // Create a referenced cache. EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); // Create an unreferenced directory next to the referenced one. base::FilePath origin_path = CacheStorageManager::ConstructOriginPath( @@ -728,8 +775,8 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) { // Verify that the referenced cache still works. EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE( - CacheMatch(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); // Verify that the unreferenced cache is gone. EXPECT_FALSE(base::DirectoryExists(unreferenced_path)); @@ -803,7 +850,7 @@ class CacheStorageMigrationTest : public CacheStorageManagerTest { ASSERT_FALSE(base::DirectoryExists(new_path_)); ASSERT_TRUE(Open(origin1_, cache1_)); ASSERT_TRUE(Open(origin1_, cache2_)); - callback_cache_ = nullptr; + callback_cache_handle_.reset(); ASSERT_FALSE(base::DirectoryExists(legacy_path_)); ASSERT_TRUE(base::DirectoryExists(new_path_)); @@ -893,11 +940,11 @@ class MigratedLegacyCacheDirectoryNameTest : public CacheStorageManagerTest { // Populate a legacy cache. ASSERT_TRUE(Open(origin1_, legacy_cache_name_)); - EXPECT_TRUE(CachePut(callback_cache_.get(), stored_url_)); - base::FilePath new_path = callback_cache_->path(); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), stored_url_)); + base::FilePath new_path = callback_cache_handle_->value()->path(); // Close the cache's backend so that the files can be moved. - callback_cache_->Close(base::Bind(&base::DoNothing)); + callback_cache_handle_->value()->Close(base::Bind(&base::DoNothing)); base::RunLoop().RunUntilIdle(); // Legacy index files didn't have the cache directory, so remove it from the @@ -946,29 +993,31 @@ TEST_F(MigratedLegacyCacheDirectoryNameTest, LegacyCacheMigrated) { ASSERT_FALSE(base::DirectoryExists(legacy_path_)); // Verify that the existing entry still works. - EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_)); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), stored_url_)); // Verify that adding new entries works. - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2"))); - EXPECT_TRUE( - CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo2"))); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), + GURL("http://example.com/foo2"))); } TEST_F(MigratedLegacyCacheDirectoryNameTest, RandomDirectoryCacheSideBySideWithLegacy) { EXPECT_TRUE(Open(origin1_, legacy_cache_name_)); EXPECT_TRUE(Open(origin1_, "bar")); - EXPECT_TRUE(CachePut(callback_cache_.get(), stored_url_)); - EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_)); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), stored_url_)); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), stored_url_)); } TEST_F(MigratedLegacyCacheDirectoryNameTest, DeleteLegacyCacheAndRecreateNew) { EXPECT_TRUE(Delete(origin1_, legacy_cache_name_)); EXPECT_TRUE(Open(origin1_, legacy_cache_name_)); - EXPECT_FALSE(CacheMatch(callback_cache_.get(), stored_url_)); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2"))); - EXPECT_TRUE( - CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2"))); + EXPECT_FALSE(CacheMatch(callback_cache_handle_->value(), stored_url_)); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo2"))); + EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), + GURL("http://example.com/foo2"))); } class CacheStorageQuotaClientTest : public CacheStorageManagerTest { @@ -1067,7 +1116,8 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaID) { TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginUsage) { EXPECT_EQ(0, QuotaGetOriginUsage(origin1_)); EXPECT_TRUE(Open(origin1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_LT(0, QuotaGetOriginUsage(origin1_)); } @@ -1096,7 +1146,8 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteOriginData) { EXPECT_EQ(0, QuotaGetOriginUsage(origin1_)); EXPECT_TRUE(Open(origin1_, "foo")); // Call put to test that initialized caches are properly deleted too. - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); EXPECT_TRUE(Open(origin1_, "bar")); EXPECT_TRUE(Open(origin2_, "baz")); @@ -1120,11 +1171,12 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyOrigin) { TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) { EXPECT_TRUE(Open(origin1_, "foo")); // Call put to test that initialized caches are properly deleted too. - EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo"))); + EXPECT_TRUE(CachePut(callback_cache_handle_->value(), + GURL("http://example.com/foo"))); // Close the cache backend so that it writes out its index to disk. base::RunLoop run_loop; - callback_cache_->Close(run_loop.QuitClosure()); + callback_cache_handle_->value()->Close(run_loop.QuitClosure()); run_loop.Run(); // Create a new CacheStorageManager that hasn't yet loaded the origin. diff --git a/chromium/content/browser/cache_storage/cache_storage_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_unittest.cc deleted file mode 100644 index 84e1e22aee0..00000000000 --- a/chromium/content/browser/cache_storage/cache_storage_unittest.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/cache_storage/cache_storage.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/browser/quota/mock_quota_manager_proxy.h" -#include "content/public/test/mock_special_storage_policy.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "net/url_request/url_request_context_getter.h" -#include "storage/browser/quota/quota_manager_proxy.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -namespace { -const char kOrigin[] = "http://example.com/"; -} - -class TestCacheStorage : public CacheStorage { - public: - TestCacheStorage( - const base::FilePath& file_path, - scoped_refptr quota_manager_proxy) - : CacheStorage(file_path, - false /* memory_only */, - base::ThreadTaskRunnerHandle::Get().get(), - scoped_refptr(), - quota_manager_proxy, - base::WeakPtr(), - GURL(kOrigin)), - delay_preserved_cache_callback_(false) {} - - void RunPreservedCacheCallback() { - ASSERT_FALSE(preserved_cache_callback_.is_null()); - preserved_cache_callback_.Run(); - preserved_cache_callback_.Reset(); - } - - void set_delay_preserved_cache_callback(bool should_delay) { - delay_preserved_cache_callback_ = should_delay; - } - - bool IsPreservingCache(const CacheStorageCache* cache) { - return ContainsKey(preserved_caches_, cache); - } - - private: - void SchedulePreservedCacheRemoval(const base::Closure& callback) override { - if (!delay_preserved_cache_callback_) { - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); - return; - } - preserved_cache_callback_ = callback; - } - - bool delay_preserved_cache_callback_; - base::Closure preserved_cache_callback_; -}; - -class CacheStorageTest : public testing::Test { - protected: - CacheStorageTest() - : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} - - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - quota_policy_ = new MockSpecialStoragePolicy; - mock_quota_manager_ = new MockQuotaManager( - false /* is incognito */, temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get().get(), - base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get()); - quota_manager_proxy_ = new MockQuotaManagerProxy( - mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get()); - - test_cache_storage_.reset( - new TestCacheStorage(temp_dir_.path(), quota_manager_proxy_)); - } - - bool OpenCache(const std::string& cache_name) { - bool callback_called = false; - test_cache_storage_->OpenCache( - cache_name, base::Bind(&CacheStorageTest::OpenCacheCallback, - base::Unretained(this), &callback_called)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(callback_called); - return callback_error_ == CACHE_STORAGE_OK; - } - - void OpenCacheCallback(bool* callback_called, - scoped_refptr cache, - CacheStorageError error) { - *callback_called = true; - callback_cache_ = cache; - callback_error_ = error; - } - - base::ScopedTempDir temp_dir_; - TestBrowserThreadBundle browser_thread_bundle_; - scoped_refptr quota_policy_; - scoped_refptr mock_quota_manager_; - scoped_refptr quota_manager_proxy_; - std::unique_ptr test_cache_storage_; - - scoped_refptr callback_cache_; - CacheStorageError callback_error_; -}; - -TEST_F(CacheStorageTest, PreserveCache) { - test_cache_storage_->set_delay_preserved_cache_callback(true); - EXPECT_TRUE(OpenCache("foo")); - EXPECT_TRUE(test_cache_storage_->IsPreservingCache(callback_cache_.get())); - test_cache_storage_->RunPreservedCacheCallback(); - EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get())); - - // Try opening it again, since the cache is already open (callback_cache_ is - // referencing it) the cache shouldn't be preserved again. - EXPECT_TRUE(OpenCache("foo")); - EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get())); - - // Remove the reference to the cache so that it's deleted. After that, the - // next time it's opened will require the cache to be created again and - // preserved. - callback_cache_ = nullptr; - EXPECT_TRUE(OpenCache("foo")); - EXPECT_TRUE(test_cache_storage_->IsPreservingCache(callback_cache_.get())); - test_cache_storage_->RunPreservedCacheCallback(); - EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get())); -} - -} // namespace content -- cgit v1.2.1