Index: content/browser/service_worker/service_worker_cache_storage_manager.cc |
diff --git a/content/browser/service_worker/service_worker_cache_storage_manager.cc b/content/browser/service_worker/service_worker_cache_storage_manager.cc |
index 85afef9d7fe4127707a7c8b5beda0015ee532797..411a71170851c25faff6f5f87083faa8f7d5d03d 100644 |
--- a/content/browser/service_worker/service_worker_cache_storage_manager.cc |
+++ b/content/browser/service_worker/service_worker_cache_storage_manager.cc |
@@ -8,15 +8,24 @@ |
#include <string> |
#include "base/bind.h" |
+#include "base/files/file_enumerator.h" |
+#include "base/files/file_util.h" |
#include "base/id_map.h" |
#include "base/sha1.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
+#include "content/browser/service_worker/service_worker_cache.pb.h" |
+#include "content/browser/service_worker/service_worker_cache_quota_client.h" |
#include "content/browser/service_worker/service_worker_cache_storage.h" |
#include "content/browser/service_worker/service_worker_context_core.h" |
#include "content/public/browser/browser_thread.h" |
+#include "net/base/net_util.h" |
+#include "storage/browser/quota/quota_manager_proxy.h" |
+#include "storage/common/quota/quota_status_code.h" |
#include "url/gurl.h" |
+namespace content { |
+ |
namespace { |
base::FilePath ConstructOriginPath(const base::FilePath& root_path, |
@@ -27,23 +36,67 @@ base::FilePath ConstructOriginPath(const base::FilePath& root_path, |
return root_path.AppendASCII(origin_hash_hex); |
} |
-} // namespace |
+bool DeleteDir(const base::FilePath& path) { |
+ return base::DeleteFile(path, true /* recursive */); |
+} |
-namespace content { |
+void DeleteOriginDidDeleteDir( |
+ const storage::QuotaClient::DeletionCallback& callback, |
+ bool rv) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ callback.Run(rv ? storage::kQuotaStatusOk : storage::kQuotaErrorAbort); |
+} |
+ |
+std::set<GURL> ListOriginsOnDisk(base::FilePath root_path_) { |
+ std::set<GURL> origins; |
+ base::FileEnumerator file_enum( |
+ root_path_, false /* recursive */, base::FileEnumerator::DIRECTORIES); |
+ |
+ base::FilePath path; |
+ while (!(path = file_enum.Next()).empty()) { |
+ std::string protobuf; |
+ base::ReadFileToString( |
+ path.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName), &protobuf); |
+ |
+ ServiceWorkerCacheStorageIndex index; |
+ if (index.ParseFromString(protobuf)) { |
+ if (index.has_origin()) |
+ origins.insert(GURL(index.origin())); |
+ } |
+ } |
+ |
+ return origins; |
+} |
+ |
+void GetOriginsForHostDidListOrigins( |
+ const std::string& host, |
+ const storage::QuotaClient::GetOriginsCallback& callback, |
+ const std::set<GURL>& origins) { |
+ std::set<GURL> out_origins; |
+ for (const GURL& origin : origins) { |
+ if (host == net::GetHostOrSpecFromURL(origin)) |
+ out_origins.insert(origin); |
+ } |
+ callback.Run(out_origins); |
+} |
+ |
+} // namespace |
// static |
scoped_ptr<ServiceWorkerCacheStorageManager> |
ServiceWorkerCacheStorageManager::Create( |
const base::FilePath& path, |
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner) { |
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner, |
+ storage::QuotaManagerProxy* quota_manager_proxy) { |
base::FilePath root_path = path; |
if (!path.empty()) { |
root_path = path.Append(ServiceWorkerContextCore::kServiceWorkerDirectory) |
.AppendASCII("CacheStorage"); |
} |
- return make_scoped_ptr( |
- new ServiceWorkerCacheStorageManager(root_path, cache_task_runner)); |
+ return make_scoped_ptr(new ServiceWorkerCacheStorageManager( |
+ root_path, cache_task_runner, quota_manager_proxy)); |
} |
// static |
@@ -51,8 +104,10 @@ scoped_ptr<ServiceWorkerCacheStorageManager> |
ServiceWorkerCacheStorageManager::Create( |
ServiceWorkerCacheStorageManager* old_manager) { |
scoped_ptr<ServiceWorkerCacheStorageManager> manager( |
- new ServiceWorkerCacheStorageManager(old_manager->root_path(), |
- old_manager->cache_task_runner())); |
+ new ServiceWorkerCacheStorageManager( |
+ old_manager->root_path(), |
+ old_manager->cache_task_runner(), |
+ old_manager->quota_manager_proxy_.get())); |
// These values may be NULL, in which case this will be called again later by |
// the dispatcher host per usual. |
manager->SetBlobParametersForCache(old_manager->url_request_context(), |
@@ -61,6 +116,7 @@ ServiceWorkerCacheStorageManager::Create( |
} |
ServiceWorkerCacheStorageManager::~ServiceWorkerCacheStorageManager() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
for (ServiceWorkerCacheStorageMap::iterator it = cache_storage_map_.begin(); |
it != cache_storage_map_.end(); |
++it) { |
@@ -148,12 +204,95 @@ void ServiceWorkerCacheStorageManager::SetBlobParametersForCache( |
blob_context_ = blob_storage_context; |
} |
+void ServiceWorkerCacheStorageManager::GetOriginUsage( |
+ const GURL& origin_url, |
+ const storage::QuotaClient::GetUsageCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ // TODO(jkarlin): Get the actual disk usage for the origin. |
+ callback.Run(0); |
+} |
+ |
+void ServiceWorkerCacheStorageManager::GetOrigins( |
+ const storage::QuotaClient::GetOriginsCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ if (IsMemoryBacked()) { |
+ std::set<GURL> origins; |
+ for (const auto& key_value : cache_storage_map_) |
+ origins.insert(key_value.first); |
+ |
+ callback.Run(origins); |
+ return; |
+ } |
+ |
+ PostTaskAndReplyWithResult(cache_task_runner_.get(), |
+ FROM_HERE, |
+ base::Bind(&ListOriginsOnDisk, root_path_), |
+ base::Bind(callback)); |
+} |
+ |
+void ServiceWorkerCacheStorageManager::GetOriginsForHost( |
+ const std::string& host, |
+ const storage::QuotaClient::GetOriginsCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ if (IsMemoryBacked()) { |
+ std::set<GURL> origins; |
+ for (const auto& key_value : cache_storage_map_) { |
+ if (host == net::GetHostOrSpecFromURL(key_value.first)) |
+ origins.insert(key_value.first); |
+ } |
+ callback.Run(origins); |
+ return; |
+ } |
+ |
+ PostTaskAndReplyWithResult( |
+ cache_task_runner_.get(), |
+ FROM_HERE, |
+ base::Bind(&ListOriginsOnDisk, root_path_), |
+ base::Bind(&GetOriginsForHostDidListOrigins, host, callback)); |
+} |
+ |
+void ServiceWorkerCacheStorageManager::DeleteOriginData( |
+ const GURL& origin, |
+ const storage::QuotaClient::DeletionCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ ServiceWorkerCacheStorage* cache_storage = |
+ FindOrCreateServiceWorkerCacheManager(origin); |
+ cache_storage_map_.erase(origin); |
+ cache_storage->CloseAllCaches(); |
+ |
+ // TODO(jkarlin): Deleting the storage leaves any unfinished operations |
+ // hanging, resulting in unresolved promises. Fix this by guaranteeing that |
+ // callbacks are called in ServiceWorkerStorage. |
+ delete cache_storage; |
+ |
+ if (IsMemoryBacked()) { |
+ callback.Run(storage::kQuotaStatusOk); |
+ return; |
+ } |
+ |
+ PostTaskAndReplyWithResult( |
+ cache_task_runner_.get(), |
+ FROM_HERE, |
+ base::Bind(&DeleteDir, ConstructOriginPath(root_path_, origin)), |
+ base::Bind(&DeleteOriginDidDeleteDir, callback)); |
+} |
+ |
ServiceWorkerCacheStorageManager::ServiceWorkerCacheStorageManager( |
const base::FilePath& path, |
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner) |
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner, |
+ storage::QuotaManagerProxy* quota_manager_proxy) |
: root_path_(path), |
cache_task_runner_(cache_task_runner), |
- request_context_(NULL) { |
+ quota_manager_proxy_(quota_manager_proxy), |
+ request_context_(NULL), |
+ weak_ptr_factory_(this) { |
+ if (quota_manager_proxy_.get()) |
+ quota_manager_proxy_->RegisterClient( |
+ new ServiceWorkerCacheQuotaClient(weak_ptr_factory_.GetWeakPtr())); |
} |
ServiceWorkerCacheStorage* |
@@ -165,13 +304,13 @@ ServiceWorkerCacheStorageManager::FindOrCreateServiceWorkerCacheManager( |
ServiceWorkerCacheStorageMap::const_iterator it = |
cache_storage_map_.find(origin); |
if (it == cache_storage_map_.end()) { |
- bool memory_only = root_path_.empty(); |
ServiceWorkerCacheStorage* cache_storage = |
new ServiceWorkerCacheStorage(ConstructOriginPath(root_path_, origin), |
- memory_only, |
+ IsMemoryBacked(), |
cache_task_runner_.get(), |
request_context_, |
- blob_context_); |
+ blob_context_, |
+ origin); |
// The map owns fetch_stores. |
cache_storage_map_.insert(std::make_pair(origin, cache_storage)); |
return cache_storage; |