diff options
author | tzik@chromium.org <tzik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 09:59:48 +0000 |
---|---|---|
committer | tzik@chromium.org <tzik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 09:59:48 +0000 |
commit | bce0aaf723befbf7c69d3492964c71bd8dbbd87e (patch) | |
tree | b409ef8fb862765366b04602a9381fa14c1a7f69 /webkit | |
parent | eb7ef5f39f4041a06a2eef6e2916b0ab3039238f (diff) | |
download | chromium_src-bce0aaf723befbf7c69d3492964c71bd8dbbd87e.zip chromium_src-bce0aaf723befbf7c69d3492964c71bd8dbbd87e.tar.gz chromium_src-bce0aaf723befbf7c69d3492964c71bd8dbbd87e.tar.bz2 |
[FileAPI] Don't fail on ReserveQuota() even on insufficient space
Return maximum available quota when there isn't sufficient available space
to satisfy the requested amount of quota reservation.
BUG=340703
Review URL: https://codereview.chromium.org/155603002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249323 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
8 files changed, 64 insertions, 33 deletions
diff --git a/webkit/browser/fileapi/quota/quota_backend_impl.cc b/webkit/browser/fileapi/quota/quota_backend_impl.cc index 62cd5a86..de0b3ac 100644 --- a/webkit/browser/fileapi/quota/quota_backend_impl.cc +++ b/webkit/browser/fileapi/quota/quota_backend_impl.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/sequenced_task_runner.h" #include "webkit/browser/fileapi/file_system_usage_cache.h" #include "webkit/browser/quota/quota_client.h" @@ -39,7 +40,7 @@ void QuotaBackendImpl::ReserveQuota(const GURL& origin, DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); DCHECK(origin.is_valid()); if (!delta) { - callback.Run(base::File::FILE_OK); + callback.Run(base::File::FILE_OK, 0); return; } DCHECK(quota_manager_proxy_); @@ -104,22 +105,30 @@ void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota( quota::QuotaStatusCode status, int64 usage, int64 quota) { DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); DCHECK(info.origin.is_valid()); + DCHECK_LE(0, usage); + DCHECK_LE(0, quota); if (status != quota::kQuotaStatusOk) { - callback.Run(base::File::FILE_ERROR_FAILED); + callback.Run(base::File::FILE_ERROR_FAILED, 0); return; } - if (quota < usage + info.delta) { - callback.Run(base::File::FILE_ERROR_NO_SPACE); - return; + QuotaReservationInfo normalized_info = info; + if (info.delta > 0) { + int64 new_usage = + base::saturated_cast<int64>(usage + static_cast<uint64>(info.delta)); + if (quota < new_usage) + new_usage = quota; + normalized_info.delta = std::max(static_cast<int64>(0), new_usage - usage); } - ReserveQuotaInternal(info); - if (callback.Run(base::File::FILE_OK)) + ReserveQuotaInternal(normalized_info); + if (callback.Run(base::File::FILE_OK, normalized_info.delta)) return; // The requester could not accept the reserved quota. Revert it. ReserveQuotaInternal( - QuotaReservationInfo(info.origin, info.type, -info.delta)); + QuotaReservationInfo(normalized_info.origin, + normalized_info.type, + -normalized_info.delta)); } void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { diff --git a/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc b/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc index 6e7b94b..9f665e4 100644 --- a/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc +++ b/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc @@ -23,9 +23,13 @@ const char kOrigin[] = "http://example.com"; bool DidReserveQuota(bool accepted, base::File::Error* error_out, - base::File::Error error) { + int64* delta_out, + base::File::Error error, + int64 delta) { DCHECK(error_out); + DCHECK(delta_out); *error_out = error; + *delta_out = delta; return accepted; } @@ -51,7 +55,7 @@ class MockQuotaManagerProxy : public quota::QuotaManagerProxy { int64 delta) OVERRIDE { ++storage_modified_count_; usage_ += delta; - ASSERT_LT(usage_, quota_); + ASSERT_LE(usage_, quota_); } virtual void GetUsageAndQuota( @@ -150,18 +154,22 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) { InitializeForOriginAndType(GURL(kOrigin), type); quota_manager_proxy_->set_quota(10000); + int64 delta = 0; + const int64 kDelta1 = 1000; base::File::Error error = base::File::FILE_ERROR_FAILED; backend_->ReserveQuota(GURL(kOrigin), type, kDelta1, - base::Bind(&DidReserveQuota, true, &error)); + base::Bind(&DidReserveQuota, true, &error, &delta)); EXPECT_EQ(base::File::FILE_OK, error); + EXPECT_EQ(kDelta1, delta); EXPECT_EQ(kDelta1, quota_manager_proxy_->usage()); const int64 kDelta2 = -300; error = base::File::FILE_ERROR_FAILED; backend_->ReserveQuota(GURL(kOrigin), type, kDelta2, - base::Bind(&DidReserveQuota, true, &error)); + base::Bind(&DidReserveQuota, true, &error, &delta)); EXPECT_EQ(base::File::FILE_OK, error); + EXPECT_EQ(kDelta2, delta); EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage()); EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count()); @@ -172,14 +180,17 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) { InitializeForOriginAndType(GURL(kOrigin), type); quota_manager_proxy_->set_quota(100); + int64 delta = 0; + const int64 kDelta = 1000; base::File::Error error = base::File::FILE_ERROR_FAILED; backend_->ReserveQuota(GURL(kOrigin), type, kDelta, - base::Bind(&DidReserveQuota, true, &error)); - EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, error); - EXPECT_EQ(0, quota_manager_proxy_->usage()); + base::Bind(&DidReserveQuota, true, &error, &delta)); + EXPECT_EQ(base::File::FILE_OK, error); + EXPECT_EQ(100, delta); + EXPECT_EQ(100, quota_manager_proxy_->usage()); - EXPECT_EQ(0, quota_manager_proxy_->storage_modified_count()); + EXPECT_EQ(1, quota_manager_proxy_->storage_modified_count()); } TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) { @@ -187,11 +198,14 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) { InitializeForOriginAndType(GURL(kOrigin), type); quota_manager_proxy_->set_quota(10000); + int64 delta = 0; + const int64 kDelta = 1000; base::File::Error error = base::File::FILE_ERROR_FAILED; backend_->ReserveQuota(GURL(kOrigin), type, kDelta, - base::Bind(&DidReserveQuota, false, &error)); + base::Bind(&DidReserveQuota, false, &error, &delta)); EXPECT_EQ(base::File::FILE_OK, error); + EXPECT_EQ(kDelta, delta); EXPECT_EQ(0, quota_manager_proxy_->usage()); EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count()); diff --git a/webkit/browser/fileapi/quota/quota_reservation.cc b/webkit/browser/fileapi/quota/quota_reservation.cc index af74174..f199b35 100644 --- a/webkit/browser/fileapi/quota/quota_reservation.cc +++ b/webkit/browser/fileapi/quota/quota_reservation.cc @@ -25,7 +25,7 @@ void QuotaReservation::RefreshReservation( origin(), type(), size - remaining_quota_, base::Bind(&QuotaReservation::AdaptDidUpdateReservedQuota, weak_ptr_factory_.GetWeakPtr(), - size, callback)); + remaining_quota_, callback)); if (running_refresh_request_) remaining_quota_ = 0; @@ -93,20 +93,22 @@ QuotaReservation::~QuotaReservation() { // static bool QuotaReservation::AdaptDidUpdateReservedQuota( const base::WeakPtr<QuotaReservation>& reservation, - int64 new_reserved_size, + int64 previous_size, const StatusCallback& callback, - base::File::Error error) { + base::File::Error error, + int64 delta) { if (!reservation) return false; return reservation->DidUpdateReservedQuota( - new_reserved_size, callback, error); + previous_size, callback, error, delta); } bool QuotaReservation::DidUpdateReservedQuota( - int64 new_reserved_size, + int64 previous_size, const StatusCallback& callback, - base::File::Error error) { + base::File::Error error, + int64 delta) { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); DCHECK(running_refresh_request_); running_refresh_request_ = false; @@ -117,7 +119,7 @@ bool QuotaReservation::DidUpdateReservedQuota( } if (error == base::File::FILE_OK) - remaining_quota_ = new_reserved_size; + remaining_quota_ = previous_size + delta; callback.Run(error); return true; } diff --git a/webkit/browser/fileapi/quota/quota_reservation.h b/webkit/browser/fileapi/quota/quota_reservation.h index dad3b30..9233a24 100644 --- a/webkit/browser/fileapi/quota/quota_reservation.h +++ b/webkit/browser/fileapi/quota/quota_reservation.h @@ -28,7 +28,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT QuotaReservation typedef base::Callback<void(base::File::Error error)> StatusCallback; // Reclaims unused quota and reserves another |size| of quota. So that the - // resulting new |remaining_quota| will be same as |size|. + // resulting new |remaining_quota_| will be same as |size| as far as available + // space is enough. |remaining_quota_| may be less than |size| if there is + // not enough space available. // Invokes |callback| upon completion. void RefreshReservation(int64 size, const StatusCallback& callback); @@ -67,12 +69,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT QuotaReservation static bool AdaptDidUpdateReservedQuota( const base::WeakPtr<QuotaReservation>& reservation, - int64 new_reserved_size, + int64 previous_size, const StatusCallback& callback, - base::File::Error error); - bool DidUpdateReservedQuota(int64 new_reserved_size, + base::File::Error error, + int64 delta); + bool DidUpdateReservedQuota(int64 previous_size, const StatusCallback& callback, - base::File::Error error); + base::File::Error error, + int64 delta); bool client_crashed_; bool running_refresh_request_; diff --git a/webkit/browser/fileapi/quota/quota_reservation_buffer.cc b/webkit/browser/fileapi/quota/quota_reservation_buffer.cc index 662c415..9e44319 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_buffer.cc +++ b/webkit/browser/fileapi/quota/quota_reservation_buffer.cc @@ -92,7 +92,8 @@ bool QuotaReservationBuffer::DecrementDirtyCount( base::WeakPtr<QuotaReservationManager> reservation_manager, const GURL& origin, FileSystemType type, - base::File::Error error) { + base::File::Error error, + int64 delta_unused) { DCHECK(origin.is_valid()); if (error == base::File::FILE_OK && reservation_manager) { reservation_manager->DecrementDirtyCount(origin, type); diff --git a/webkit/browser/fileapi/quota/quota_reservation_buffer.h b/webkit/browser/fileapi/quota/quota_reservation_buffer.h index cc6a435..0d87a99 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_buffer.h +++ b/webkit/browser/fileapi/quota/quota_reservation_buffer.h @@ -60,7 +60,8 @@ class QuotaReservationBuffer : public base::RefCounted<QuotaReservationBuffer> { base::WeakPtr<QuotaReservationManager> reservation_manager, const GURL& origin, FileSystemType type, - base::File::Error error); + base::File::Error error, + int64 delta); typedef std::map<base::FilePath, OpenFileHandleContext*> OpenFileHandleContextByPath; diff --git a/webkit/browser/fileapi/quota/quota_reservation_manager.h b/webkit/browser/fileapi/quota/quota_reservation_manager.h index 9b64a15..2fea930 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_manager.h +++ b/webkit/browser/fileapi/quota/quota_reservation_manager.h @@ -28,7 +28,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT QuotaReservationManager { public: // Callback for ReserveQuota. When this callback returns false, ReserveQuota // operation should be reverted. - typedef base::Callback<bool(base::File::Error error)> + typedef base::Callback<bool(base::File::Error error, int64 delta)> ReserveQuotaCallback; // An abstraction of backing quota system. diff --git a/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc b/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc index 1ec2fb7..7b2b738 100644 --- a/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc +++ b/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc @@ -53,7 +53,7 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend { on_memory_usage_ += delta; base::MessageLoopProxy::current()->PostTask( FROM_HERE, - base::Bind(base::IgnoreResult(callback), base::File::FILE_OK)); + base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta)); } virtual void ReleaseReservedQuota(const GURL& origin, |