Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1037)

Unified Diff: content/browser/cache_storage/cache_storage_cache.cc

Issue 2085583002: [CacheStorage] Don't call GetUsageAndQuota from a scheduled operation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/cache_storage/cache_storage_cache.cc
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc
index 43fd58e77d5d347e51bb424f2146c32162f9d4dd..408dc5c48de6b48562be292e173881a49e6dd133 100644
--- a/content/browser/cache_storage/cache_storage_cache.cc
+++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -274,7 +274,6 @@ struct CacheStorageCache::PutContext {
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
CacheStorageCache::ErrorCallback callback;
disk_cache::ScopedEntryPtr cache_entry;
- int64_t available_bytes = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PutContext);
@@ -358,23 +357,70 @@ void CacheStorageCache::WriteSideData(const ErrorCallback& callback,
scoped_refptr<net::IOBuffer> buffer,
int buf_len) {
if (!LazyInitialize()) {
- callback.Run(CACHE_STORAGE_ERROR_STORAGE);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
jsbell 2016/06/21 15:19:55 Necessary for this CL, or just to ensure consisten
jkarlin 2016/06/21 15:22:53 Just to return consistently. I need to go over the
+ FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_STORAGE));
return;
}
- ErrorCallback pending_callback =
- base::Bind(&CacheStorageCache::PendingErrorCallback,
- weak_ptr_factory_.GetWeakPtr(), callback);
- scheduler_->ScheduleOperation(base::Bind(
- &CacheStorageCache::WriteSideDataImpl, weak_ptr_factory_.GetWeakPtr(),
- pending_callback, url, expected_response_time, buffer, buf_len));
+ // GetUsageAndQuota is called before entering a scheduled operation since it
+ // can call Size, another scheduled operation.
+ quota_manager_proxy_->GetUsageAndQuota(
+ base::ThreadTaskRunnerHandle::Get().get(), origin_,
+ storage::kStorageTypeTemporary,
+ base::Bind(&CacheStorageCache::WriteSideDataDidGetQuota,
+ weak_ptr_factory_.GetWeakPtr(), callback, url,
+ expected_response_time, buffer, buf_len));
}
void CacheStorageCache::BatchOperation(
const std::vector<CacheStorageBatchOperation>& operations,
const ErrorCallback& callback) {
if (!LazyInitialize()) {
- callback.Run(CACHE_STORAGE_ERROR_STORAGE);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_STORAGE));
+ return;
+ }
+
+ // Estimate the required size of the put operations. The size of the deletes
+ // is unknown and not considered.
+ int64_t space_required = 0;
+ for (const auto& operation : operations) {
+ if (operation.operation_type == CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT) {
+ space_required +=
+ operation.request.blob_size + operation.response.blob_size;
+ }
+ }
+ if (space_required > 0) {
+ // GetUsageAndQuota is called before entering a scheduled operation since it
+ // can call Size, another scheduled operation. This is racy. The decision
+ // to commit is made before the scheduled Put operation runs. By the time
+ // Put runs, the cache might already be full and the origin will be larger
+ // than it's supposed to be.
+ quota_manager_proxy_->GetUsageAndQuota(
+ base::ThreadTaskRunnerHandle::Get().get(), origin_,
+ storage::kStorageTypeTemporary,
+ base::Bind(&CacheStorageCache::BatchDidGetUsageAndQuota,
+ weak_ptr_factory_.GetWeakPtr(), operations, callback,
+ space_required));
+ return;
+ }
+
+ BatchDidGetUsageAndQuota(operations, callback, 0 /* space_required */,
+ storage::kQuotaStatusOk, 0 /* usage */,
+ 0 /* quota */);
+}
+
+void CacheStorageCache::BatchDidGetUsageAndQuota(
+ const std::vector<CacheStorageBatchOperation>& operations,
+ const ErrorCallback& callback,
+ int64_t space_required,
+ storage::QuotaStatusCode status_code,
+ int64_t usage,
+ int64_t quota) {
+ if (status_code != storage::kQuotaStatusOk ||
+ space_required > quota - usage) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_QUOTA_EXCEEDED));
return;
}
@@ -463,16 +509,13 @@ void CacheStorageCache::Size(const SizeCallback& callback) {
return;
}
- if (initializing_) {
- // Note that Size doesn't use the scheduler, see header comments for why.
- pending_size_callbacks_.push_back(callback);
- return;
- }
+ SizeCallback pending_callback =
+ base::Bind(&CacheStorageCache::PendingSizeCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
- // Run immediately so that we don't deadlock on
- // CacheStorageCache::PutDidDelete's call to
- // quota_manager_proxy_->GetUsageAndQuota.
- SizeImpl(callback);
+ scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::SizeImpl,
+ weak_ptr_factory_.GetWeakPtr(),
+ pending_callback));
}
void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) {
@@ -776,6 +819,30 @@ void CacheStorageCache::MatchAllDidReadMetadata(
MatchAllProcessNextEntry(std::move(context), iter + 1);
}
+void CacheStorageCache::WriteSideDataDidGetQuota(
+ const ErrorCallback& callback,
+ const GURL& url,
+ base::Time expected_response_time,
+ scoped_refptr<net::IOBuffer> buffer,
+ int buf_len,
+ storage::QuotaStatusCode status_code,
+ int64_t usage,
+ int64_t quota) {
+ if (status_code != storage::kQuotaStatusOk || (buf_len > quota - usage)) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_QUOTA_EXCEEDED));
+ return;
+ }
+
+ ErrorCallback pending_callback =
+ base::Bind(&CacheStorageCache::PendingErrorCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
+
+ scheduler_->ScheduleOperation(base::Bind(
+ &CacheStorageCache::WriteSideDataImpl, weak_ptr_factory_.GetWeakPtr(),
+ pending_callback, url, expected_response_time, buffer, buf_len));
+}
+
void CacheStorageCache::WriteSideDataImpl(const ErrorCallback& callback,
const GURL& url,
base::Time expected_response_time,
@@ -787,27 +854,6 @@ void CacheStorageCache::WriteSideDataImpl(const ErrorCallback& callback,
return;
}
- quota_manager_proxy_->GetUsageAndQuota(
- base::ThreadTaskRunnerHandle::Get().get(), origin_,
- storage::kStorageTypeTemporary,
- base::Bind(&CacheStorageCache::WriteSideDataDidGetUsageAndQuota,
- weak_ptr_factory_.GetWeakPtr(), callback, url,
- expected_response_time, buffer, buf_len));
-}
-
-void CacheStorageCache::WriteSideDataDidGetUsageAndQuota(
- const ErrorCallback& callback,
- const GURL& url,
- base::Time expected_response_time,
- scoped_refptr<net::IOBuffer> buffer,
- int buf_len,
- storage::QuotaStatusCode status_code,
- int64_t usage,
- int64_t quota) {
- if (status_code != storage::kQuotaStatusOk || quota - usage < buf_len) {
- callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
- return;
- }
std::unique_ptr<disk_cache::Entry*> scoped_entry_ptr(
new disk_cache::Entry*());
disk_cache::Entry** entry_ptr = scoped_entry_ptr.get();
@@ -962,31 +1008,6 @@ void CacheStorageCache::PutDidDelete(std::unique_ptr<PutContext> put_context,
return;
}
- quota_manager_proxy_->GetUsageAndQuota(
- base::ThreadTaskRunnerHandle::Get().get(), origin_,
- storage::kStorageTypeTemporary,
- base::Bind(&CacheStorageCache::PutDidGetUsageAndQuota,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(put_context))));
-}
-
-void CacheStorageCache::PutDidGetUsageAndQuota(
- std::unique_ptr<PutContext> put_context,
- storage::QuotaStatusCode status_code,
- int64_t usage,
- int64_t quota) {
- if (backend_state_ != BACKEND_OPEN) {
- put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
- return;
- }
-
- if (status_code != storage::kQuotaStatusOk) {
- put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
- return;
- }
-
- put_context->available_bytes = quota - usage;
-
std::unique_ptr<disk_cache::Entry*> scoped_entry_ptr(
new disk_cache::Entry*());
disk_cache::Entry** entry_ptr = scoped_entry_ptr.get();
@@ -1058,12 +1079,6 @@ void CacheStorageCache::PutDidCreateEntry(
scoped_refptr<net::StringIOBuffer> buffer(
new net::StringIOBuffer(std::move(serialized)));
- int64_t bytes_to_write = buffer->size() + put_context->response->blob_size;
- if (put_context->available_bytes < bytes_to_write) {
- put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
- return;
- }
-
// Get a temporary copy of the entry pointer before passing it in base::Bind.
disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get();
@@ -1439,10 +1454,6 @@ void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error,
? BACKEND_OPEN
: BACKEND_CLOSED;
- for (const SizeCallback& callback : pending_size_callbacks_)
- SizeImpl(callback);
- pending_size_callbacks_.clear();
-
UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult",
cache_create_error, CACHE_STORAGE_ERROR_LAST + 1);
« no previous file with comments | « content/browser/cache_storage/cache_storage_cache.h ('k') | content/browser/cache_storage/cache_storage_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698