Chromium Code Reviews| Index: webkit/browser/fileapi/quota/quota_backend_impl.cc |
| diff --git a/webkit/browser/fileapi/quota/quota_backend_impl.cc b/webkit/browser/fileapi/quota/quota_backend_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..defdb341641c3b9f1f1928ff6a33420c44b5668c |
| --- /dev/null |
| +++ b/webkit/browser/fileapi/quota/quota_backend_impl.cc |
| @@ -0,0 +1,190 @@ |
| +// Copyright 2013 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 "webkit/browser/fileapi/quota/quota_backend_impl.h" |
| + |
| +#include <string> |
| + |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/logging.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "webkit/browser/fileapi/file_system_usage_cache.h" |
| +#include "webkit/browser/quota/quota_client.h" |
| +#include "webkit/browser/quota/quota_manager.h" |
| +#include "webkit/common/fileapi/file_system_util.h" |
| + |
| +namespace fileapi { |
| + |
| +QuotaBackendImpl::QuotaBackendImpl( |
| + base::SequencedTaskRunner* file_task_runner, |
| + ObfuscatedFileUtil* obfuscated_file_util, |
| + FileSystemUsageCache* file_system_usage_cache, |
| + quota::QuotaManagerProxy* quota_manager_proxy) |
| + : file_task_runner_(file_task_runner), |
| + obfuscated_file_util_(obfuscated_file_util), |
| + file_system_usage_cache_(file_system_usage_cache), |
| + quota_manager_proxy_(quota_manager_proxy), |
| + weak_ptr_factory_(this) { |
| +} |
| + |
| +QuotaBackendImpl::~QuotaBackendImpl() { |
| +} |
| + |
| +void QuotaBackendImpl::ReserveQuota(const GURL& origin, |
| + FileSystemType type, |
| + int64 delta, |
| + const ReserveQuotaCallback& callback) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + if (!delta) { |
| + callback.Run(base::PLATFORM_FILE_OK); |
| + return; |
| + } |
| + DCHECK(quota_manager_proxy_); |
| + quota_manager_proxy_->GetUsageAndQuota( |
| + file_task_runner_, origin, FileSystemTypeToQuotaStorageType(type), |
| + base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + QuotaReservationInfo(origin, type, delta), callback)); |
| +} |
| + |
| +void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin, |
| + FileSystemType type, |
| + int64 size) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK_LE(0, size); |
| + if (!size) |
| + return; |
| + ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size)); |
| +} |
| + |
| +void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin, |
| + FileSystemType type, |
| + int64 delta, |
| + const StatusCallback& callback) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + if (!delta) { |
| + callback.Run(base::PLATFORM_FILE_OK); |
| + return; |
| + } |
| + DCHECK(quota_manager_proxy_); |
| + quota_manager_proxy_->GetUsageAndQuota( |
| + file_task_runner_, origin, FileSystemTypeToQuotaStorageType(type), |
| + base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForCommitQuotaUsage, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + QuotaReservationInfo(origin, type, delta), callback)); |
| +} |
| + |
| +void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin, |
| + FileSystemType type) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + base::FilePath path; |
| + if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK) |
| + return; |
| + DCHECK(file_system_usage_cache_); |
| + file_system_usage_cache_->IncrementDirty(path); |
| +} |
| + |
| +void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin, |
| + FileSystemType type) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + base::FilePath path; |
| + if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK) |
| + return; |
| + DCHECK(file_system_usage_cache_); |
| + file_system_usage_cache_->DecrementDirty(path); |
| +} |
| + |
| +void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota( |
| + const QuotaReservationInfo& info, |
| + const ReserveQuotaCallback& callback, |
| + quota::QuotaStatusCode status, int64 usage, int64 quota) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + if (status != quota::kQuotaStatusOk) { |
| + callback.Run(base::PLATFORM_FILE_ERROR_FAILED); |
| + return; |
| + } |
| + |
| + if (quota < usage + info.delta) { |
| + callback.Run(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| + return; |
| + } |
| + |
| + ReserveQuotaInternal(info); |
| + if (callback.Run(base::PLATFORM_FILE_OK)) |
| + return; |
| + // The requester could not accept the reserved quota. Revert it. |
| + ReserveQuotaInternal( |
| + QuotaReservationInfo(info.origin, info.type, -info.delta)); |
| +} |
| + |
| +void QuotaBackendImpl::DidGetUsageAndQuotaForCommitQuotaUsage( |
| + const QuotaReservationInfo& info, |
| + const StatusCallback& callback, |
| + quota::QuotaStatusCode status, int64 usage, int64 quota) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + if (status != quota::kQuotaStatusOk) { |
| + callback.Run(base::PLATFORM_FILE_ERROR_FAILED); |
| + return; |
| + } |
| + |
| + if (quota < usage + info.delta) { |
| + callback.Run(base::PLATFORM_FILE_ERROR_NO_SPACE); |
|
kinuko
2013/11/07 10:10:09
I don't think querying first and returning here re
nhiroki
2013/11/08 00:12:05
Removed the querying part.
|
| + return; |
| + } |
| + |
| + ReserveQuotaInternal(info); |
| + base::PlatformFileError error = CommitQuotaUsageInternal(info); |
| + if (error != base::PLATFORM_FILE_OK) { |
| + // Failed to update usage. Revert it. |
| + ReserveQuotaInternal( |
| + QuotaReservationInfo(info.origin, info.type, -info.delta)); |
| + } |
| + callback.Run(error); |
| +} |
| + |
| +void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK(quota_manager_proxy_); |
| + quota_manager_proxy_->NotifyStorageModified( |
| + quota::QuotaClient::kFileSystem, info.origin, |
| + FileSystemTypeToQuotaStorageType(info.type), info.delta); |
| +} |
| + |
| +base::PlatformFileError QuotaBackendImpl::CommitQuotaUsageInternal( |
| + const QuotaReservationInfo& info) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + base::FilePath path; |
| + base::PlatformFileError error = |
| + GetUsageCachePath(info.origin, info.type, &path); |
| + if (error != base::PLATFORM_FILE_OK) |
| + return error; |
| + bool result = |
| + file_system_usage_cache_->AtomicUpdateUsageByDelta(path, info.delta); |
| + return result ? base::PLATFORM_FILE_OK |
| + : base::PLATFORM_FILE_ERROR_FAILED; |
|
kinuko
2013/11/07 10:10:09
The quota reservation code doesn't seem to handle
tzik
2013/11/07 11:45:15
Ah right, it ignores the result. CommitQuotaUsage
nhiroki
2013/11/08 00:12:05
Okay, removed them. That looks simpler :)
|
| +} |
| + |
| +base::PlatformFileError QuotaBackendImpl::GetUsageCachePath( |
| + const GURL& origin, |
| + FileSystemType type, |
| + base::FilePath* usage_file_path) { |
| + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK(usage_file_path); |
| + base::PlatformFileError error = base::PLATFORM_FILE_OK; |
| + *usage_file_path = |
| + SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( |
| + obfuscated_file_util_, origin, type, &error); |
| + return error; |
| +} |
| + |
| +QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo( |
| + const GURL& origin, FileSystemType type, int64 delta) |
| + : origin(origin), type(type), delta(delta) { |
| +} |
| + |
| +QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() { |
| +} |
| + |
| +} // namespace fileapi |