| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/cache_storage/cache_storage_cache.h" | 5 #include "content/browser/cache_storage/cache_storage_cache.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 response(std::move(response)), | 268 response(std::move(response)), |
| 269 blob_data_handle(std::move(blob_data_handle)), | 269 blob_data_handle(std::move(blob_data_handle)), |
| 270 callback(callback) {} | 270 callback(callback) {} |
| 271 | 271 |
| 272 // Input parameters to the Put function. | 272 // Input parameters to the Put function. |
| 273 scoped_ptr<ServiceWorkerFetchRequest> request; | 273 scoped_ptr<ServiceWorkerFetchRequest> request; |
| 274 scoped_ptr<ServiceWorkerResponse> response; | 274 scoped_ptr<ServiceWorkerResponse> response; |
| 275 scoped_ptr<storage::BlobDataHandle> blob_data_handle; | 275 scoped_ptr<storage::BlobDataHandle> blob_data_handle; |
| 276 CacheStorageCache::ErrorCallback callback; | 276 CacheStorageCache::ErrorCallback callback; |
| 277 disk_cache::ScopedEntryPtr cache_entry; | 277 disk_cache::ScopedEntryPtr cache_entry; |
| 278 int64_t available_bytes = 0; | |
| 279 | 278 |
| 280 private: | 279 private: |
| 281 DISALLOW_COPY_AND_ASSIGN(PutContext); | 280 DISALLOW_COPY_AND_ASSIGN(PutContext); |
| 282 }; | 281 }; |
| 283 | 282 |
| 284 // static | 283 // static |
| 285 scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache( | 284 scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache( |
| 286 const GURL& origin, | 285 const GURL& origin, |
| 287 const std::string& cache_name, | 286 const std::string& cache_name, |
| 288 scoped_refptr<net::URLRequestContextGetter> request_context_getter, | 287 scoped_refptr<net::URLRequestContextGetter> request_context_getter, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 new MatchAllContext(std::move(request), match_params, pending_callback)); | 348 new MatchAllContext(std::move(request), match_params, pending_callback)); |
| 350 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl, | 349 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl, |
| 351 weak_ptr_factory_.GetWeakPtr(), | 350 weak_ptr_factory_.GetWeakPtr(), |
| 352 base::Passed(std::move(context)))); | 351 base::Passed(std::move(context)))); |
| 353 } | 352 } |
| 354 | 353 |
| 355 void CacheStorageCache::BatchOperation( | 354 void CacheStorageCache::BatchOperation( |
| 356 const std::vector<CacheStorageBatchOperation>& operations, | 355 const std::vector<CacheStorageBatchOperation>& operations, |
| 357 const ErrorCallback& callback) { | 356 const ErrorCallback& callback) { |
| 358 if (!LazyInitialize()) { | 357 if (!LazyInitialize()) { |
| 359 callback.Run(CACHE_STORAGE_ERROR_STORAGE); | 358 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 359 FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_STORAGE)); |
| 360 return; | 360 return; |
| 361 } | 361 } |
| 362 | 362 |
| 363 // Estimate the required size of the put operations. The size of the deletes |
| 364 // is unknown and not considered. |
| 365 int64_t space_required = 0; |
| 366 for (const auto& operation : operations) { |
| 367 if (operation.operation_type == CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT) { |
| 368 space_required += |
| 369 operation.request.blob_size + operation.response.blob_size; |
| 370 } |
| 371 } |
| 372 if (space_required > 0) { |
| 373 // GetUsageAndQuota is called before entering a scheduled operation since it |
| 374 // can call Size, another scheduled operation. This is racy. The decision |
| 375 // to commit is made before the scheduled Put operation runs. By the time |
| 376 // Put runs, the cache might already be full and the origin will be larger |
| 377 // than it's supposed to be. |
| 378 quota_manager_proxy_->GetUsageAndQuota( |
| 379 base::ThreadTaskRunnerHandle::Get().get(), origin_, |
| 380 storage::kStorageTypeTemporary, |
| 381 base::Bind(&CacheStorageCache::BatchDidGetUsageAndQuota, |
| 382 weak_ptr_factory_.GetWeakPtr(), operations, callback, |
| 383 space_required)); |
| 384 return; |
| 385 } |
| 386 |
| 387 BatchDidGetUsageAndQuota(operations, callback, 0 /* space_required */, |
| 388 storage::kQuotaStatusOk, 0 /* usage */, |
| 389 0 /* quota */); |
| 390 } |
| 391 |
| 392 void CacheStorageCache::BatchDidGetUsageAndQuota( |
| 393 const std::vector<CacheStorageBatchOperation>& operations, |
| 394 const ErrorCallback& callback, |
| 395 int64_t space_required, |
| 396 storage::QuotaStatusCode status_code, |
| 397 int64_t usage, |
| 398 int64_t quota) { |
| 399 if (status_code != storage::kQuotaStatusOk || |
| 400 space_required > quota - usage) { |
| 401 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 402 FROM_HERE, base::Bind(callback, CACHE_STORAGE_ERROR_QUOTA_EXCEEDED)); |
| 403 return; |
| 404 } |
| 405 |
| 363 scoped_ptr<ErrorCallback> callback_copy(new ErrorCallback(callback)); | 406 scoped_ptr<ErrorCallback> callback_copy(new ErrorCallback(callback)); |
| 364 ErrorCallback* callback_ptr = callback_copy.get(); | 407 ErrorCallback* callback_ptr = callback_copy.get(); |
| 365 base::Closure barrier_closure = base::BarrierClosure( | 408 base::Closure barrier_closure = base::BarrierClosure( |
| 366 operations.size(), | 409 operations.size(), |
| 367 base::Bind(&CacheStorageCache::BatchDidAllOperations, this, | 410 base::Bind(&CacheStorageCache::BatchDidAllOperations, this, |
| 368 base::Passed(std::move(callback_copy)))); | 411 base::Passed(std::move(callback_copy)))); |
| 369 ErrorCallback completion_callback = | 412 ErrorCallback completion_callback = |
| 370 base::Bind(&CacheStorageCache::BatchDidOneOperation, this, | 413 base::Bind(&CacheStorageCache::BatchDidOneOperation, this, |
| 371 barrier_closure, callback_ptr); | 414 barrier_closure, callback_ptr); |
| 372 | 415 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } | 481 } |
| 439 | 482 |
| 440 void CacheStorageCache::Size(const SizeCallback& callback) { | 483 void CacheStorageCache::Size(const SizeCallback& callback) { |
| 441 if (!LazyInitialize()) { | 484 if (!LazyInitialize()) { |
| 442 // TODO(jkarlin): Delete caches that can't be initialized. | 485 // TODO(jkarlin): Delete caches that can't be initialized. |
| 443 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 486 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 444 base::Bind(callback, 0)); | 487 base::Bind(callback, 0)); |
| 445 return; | 488 return; |
| 446 } | 489 } |
| 447 | 490 |
| 448 if (initializing_) { | 491 SizeCallback pending_callback = |
| 449 // Note that Size doesn't use the scheduler, see header comments for why. | 492 base::Bind(&CacheStorageCache::PendingSizeCallback, |
| 450 pending_size_callbacks_.push_back(callback); | 493 weak_ptr_factory_.GetWeakPtr(), callback); |
| 451 return; | |
| 452 } | |
| 453 | 494 |
| 454 // Run immediately so that we don't deadlock on | 495 scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::SizeImpl, |
| 455 // CacheStorageCache::PutDidDelete's call to | 496 weak_ptr_factory_.GetWeakPtr(), |
| 456 // quota_manager_proxy_->GetUsageAndQuota. | 497 pending_callback)); |
| 457 SizeImpl(callback); | |
| 458 } | 498 } |
| 459 | 499 |
| 460 void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) { | 500 void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) { |
| 461 if (!LazyInitialize()) { | 501 if (!LazyInitialize()) { |
| 462 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 502 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 463 base::Bind(callback, 0)); | 503 base::Bind(callback, 0)); |
| 464 return; | 504 return; |
| 465 } | 505 } |
| 466 | 506 |
| 467 SizeCallback pending_callback = | 507 SizeCallback pending_callback = |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 weak_ptr_factory_.GetWeakPtr(), | 863 weak_ptr_factory_.GetWeakPtr(), |
| 824 base::Passed(std::move(put_context)))); | 864 base::Passed(std::move(put_context)))); |
| 825 } | 865 } |
| 826 | 866 |
| 827 void CacheStorageCache::PutDidDelete(scoped_ptr<PutContext> put_context, | 867 void CacheStorageCache::PutDidDelete(scoped_ptr<PutContext> put_context, |
| 828 CacheStorageError delete_error) { | 868 CacheStorageError delete_error) { |
| 829 if (backend_state_ != BACKEND_OPEN) { | 869 if (backend_state_ != BACKEND_OPEN) { |
| 830 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); | 870 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); |
| 831 return; | 871 return; |
| 832 } | 872 } |
| 833 | 873 std::unique_ptr<disk_cache::Entry*> scoped_entry_ptr( |
| 834 quota_manager_proxy_->GetUsageAndQuota( | 874 new disk_cache::Entry*()); |
| 835 base::ThreadTaskRunnerHandle::Get().get(), origin_, | |
| 836 storage::kStorageTypeTemporary, | |
| 837 base::Bind(&CacheStorageCache::PutDidGetUsageAndQuota, | |
| 838 weak_ptr_factory_.GetWeakPtr(), | |
| 839 base::Passed(std::move(put_context)))); | |
| 840 } | |
| 841 | |
| 842 void CacheStorageCache::PutDidGetUsageAndQuota( | |
| 843 scoped_ptr<PutContext> put_context, | |
| 844 storage::QuotaStatusCode status_code, | |
| 845 int64_t usage, | |
| 846 int64_t quota) { | |
| 847 if (backend_state_ != BACKEND_OPEN) { | |
| 848 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); | |
| 849 return; | |
| 850 } | |
| 851 | |
| 852 if (status_code != storage::kQuotaStatusOk) { | |
| 853 put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED); | |
| 854 return; | |
| 855 } | |
| 856 | |
| 857 put_context->available_bytes = quota - usage; | |
| 858 | |
| 859 scoped_ptr<disk_cache::Entry*> scoped_entry_ptr(new disk_cache::Entry*()); | |
| 860 disk_cache::Entry** entry_ptr = scoped_entry_ptr.get(); | 875 disk_cache::Entry** entry_ptr = scoped_entry_ptr.get(); |
| 861 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); | 876 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); |
| 862 disk_cache::Backend* backend_ptr = backend_.get(); | 877 disk_cache::Backend* backend_ptr = backend_.get(); |
| 863 | 878 |
| 864 net::CompletionCallback create_entry_callback = base::Bind( | 879 net::CompletionCallback create_entry_callback = base::Bind( |
| 865 &CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(), | 880 &CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(), |
| 866 base::Passed(std::move(scoped_entry_ptr)), | 881 base::Passed(std::move(scoped_entry_ptr)), |
| 867 base::Passed(std::move(put_context))); | 882 base::Passed(std::move(put_context))); |
| 868 | 883 |
| 869 int create_rv = backend_ptr->CreateEntry(request_ptr->url.spec(), entry_ptr, | 884 int create_rv = backend_ptr->CreateEntry(request_ptr->url.spec(), entry_ptr, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 | 932 |
| 918 scoped_ptr<std::string> serialized(new std::string()); | 933 scoped_ptr<std::string> serialized(new std::string()); |
| 919 if (!metadata.SerializeToString(serialized.get())) { | 934 if (!metadata.SerializeToString(serialized.get())) { |
| 920 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); | 935 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE); |
| 921 return; | 936 return; |
| 922 } | 937 } |
| 923 | 938 |
| 924 scoped_refptr<net::StringIOBuffer> buffer( | 939 scoped_refptr<net::StringIOBuffer> buffer( |
| 925 new net::StringIOBuffer(std::move(serialized))); | 940 new net::StringIOBuffer(std::move(serialized))); |
| 926 | 941 |
| 927 int64_t bytes_to_write = buffer->size() + put_context->response->blob_size; | |
| 928 if (put_context->available_bytes < bytes_to_write) { | |
| 929 put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED); | |
| 930 return; | |
| 931 } | |
| 932 | |
| 933 // Get a temporary copy of the entry pointer before passing it in base::Bind. | 942 // Get a temporary copy of the entry pointer before passing it in base::Bind. |
| 934 disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get(); | 943 disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get(); |
| 935 | 944 |
| 936 net::CompletionCallback write_headers_callback = base::Bind( | 945 net::CompletionCallback write_headers_callback = base::Bind( |
| 937 &CacheStorageCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(), | 946 &CacheStorageCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(), |
| 938 base::Passed(std::move(put_context)), buffer->size()); | 947 base::Passed(std::move(put_context)), buffer->size()); |
| 939 | 948 |
| 940 rv = temp_entry_ptr->WriteData(INDEX_HEADERS, 0 /* offset */, buffer.get(), | 949 rv = temp_entry_ptr->WriteData(INDEX_HEADERS, 0 /* offset */, buffer.get(), |
| 941 buffer->size(), write_headers_callback, | 950 buffer->size(), write_headers_callback, |
| 942 true /* truncate */); | 951 true /* truncate */); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 | 1305 |
| 1297 void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error, | 1306 void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error, |
| 1298 int cache_size) { | 1307 int cache_size) { |
| 1299 cache_size_ = cache_size; | 1308 cache_size_ = cache_size; |
| 1300 initializing_ = false; | 1309 initializing_ = false; |
| 1301 backend_state_ = (cache_create_error == CACHE_STORAGE_OK && backend_ && | 1310 backend_state_ = (cache_create_error == CACHE_STORAGE_OK && backend_ && |
| 1302 backend_state_ == BACKEND_UNINITIALIZED) | 1311 backend_state_ == BACKEND_UNINITIALIZED) |
| 1303 ? BACKEND_OPEN | 1312 ? BACKEND_OPEN |
| 1304 : BACKEND_CLOSED; | 1313 : BACKEND_CLOSED; |
| 1305 | 1314 |
| 1306 for (const SizeCallback& callback : pending_size_callbacks_) | |
| 1307 SizeImpl(callback); | |
| 1308 pending_size_callbacks_.clear(); | |
| 1309 | |
| 1310 UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", | 1315 UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", |
| 1311 cache_create_error, CACHE_STORAGE_ERROR_LAST + 1); | 1316 cache_create_error, CACHE_STORAGE_ERROR_LAST + 1); |
| 1312 | 1317 |
| 1313 scheduler_->CompleteOperationAndRunNext(); | 1318 scheduler_->CompleteOperationAndRunNext(); |
| 1314 } | 1319 } |
| 1315 | 1320 |
| 1316 void CacheStorageCache::PendingClosure(const base::Closure& callback) { | 1321 void CacheStorageCache::PendingClosure(const base::Closure& callback) { |
| 1317 base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr(); | 1322 base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| 1318 | 1323 |
| 1319 callback.Run(); | 1324 callback.Run(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1405 storage::BlobDataBuilder blob_data(response->blob_uuid); | 1410 storage::BlobDataBuilder blob_data(response->blob_uuid); |
| 1406 | 1411 |
| 1407 disk_cache::Entry* temp_entry = entry.get(); | 1412 disk_cache::Entry* temp_entry = entry.get(); |
| 1408 blob_data.AppendDiskCacheEntry( | 1413 blob_data.AppendDiskCacheEntry( |
| 1409 new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry, | 1414 new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry, |
| 1410 INDEX_RESPONSE_BODY); | 1415 INDEX_RESPONSE_BODY); |
| 1411 return blob_storage_context_->AddFinishedBlob(&blob_data); | 1416 return blob_storage_context_->AddFinishedBlob(&blob_data); |
| 1412 } | 1417 } |
| 1413 | 1418 |
| 1414 } // namespace content | 1419 } // namespace content |
| OLD | NEW |