1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "storage/browser/fileapi/quota/quota_backend_impl.h" 6 7#include <string> 8 9#include "base/bind.h" 10#include "base/callback.h" 11#include "base/logging.h" 12#include "base/numerics/safe_conversions.h" 13#include "base/sequenced_task_runner.h" 14#include "storage/browser/fileapi/file_system_usage_cache.h" 15#include "storage/browser/quota/quota_client.h" 16#include "storage/browser/quota/quota_manager_proxy.h" 17#include "storage/common/fileapi/file_system_util.h" 18 19namespace storage { 20 21QuotaBackendImpl::QuotaBackendImpl( 22 base::SequencedTaskRunner* file_task_runner, 23 ObfuscatedFileUtil* obfuscated_file_util, 24 FileSystemUsageCache* file_system_usage_cache, 25 storage::QuotaManagerProxy* quota_manager_proxy) 26 : file_task_runner_(file_task_runner), 27 obfuscated_file_util_(obfuscated_file_util), 28 file_system_usage_cache_(file_system_usage_cache), 29 quota_manager_proxy_(quota_manager_proxy), 30 weak_ptr_factory_(this) { 31} 32 33QuotaBackendImpl::~QuotaBackendImpl() { 34} 35 36void QuotaBackendImpl::ReserveQuota(const GURL& origin, 37 FileSystemType type, 38 int64 delta, 39 const ReserveQuotaCallback& callback) { 40 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 41 DCHECK(origin.is_valid()); 42 if (!delta) { 43 callback.Run(base::File::FILE_OK, 0); 44 return; 45 } 46 DCHECK(quota_manager_proxy_.get()); 47 quota_manager_proxy_->GetUsageAndQuota( 48 file_task_runner_.get(), 49 origin, 50 FileSystemTypeToQuotaStorageType(type), 51 base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota, 52 weak_ptr_factory_.GetWeakPtr(), 53 QuotaReservationInfo(origin, type, delta), 54 callback)); 55} 56 57void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin, 58 FileSystemType type, 59 int64 size) { 60 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 61 DCHECK(origin.is_valid()); 62 DCHECK_LE(0, size); 63 if (!size) 64 return; 65 ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size)); 66} 67 68void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin, 69 FileSystemType type, 70 int64 delta) { 71 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 72 DCHECK(origin.is_valid()); 73 if (!delta) 74 return; 75 ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta)); 76 base::FilePath path; 77 if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) 78 return; 79 bool result = file_system_usage_cache_->AtomicUpdateUsageByDelta(path, delta); 80 DCHECK(result); 81} 82 83void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin, 84 FileSystemType type) { 85 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 86 DCHECK(origin.is_valid()); 87 base::FilePath path; 88 if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) 89 return; 90 DCHECK(file_system_usage_cache_); 91 file_system_usage_cache_->IncrementDirty(path); 92} 93 94void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin, 95 FileSystemType type) { 96 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 97 DCHECK(origin.is_valid()); 98 base::FilePath path; 99 if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) 100 return; 101 DCHECK(file_system_usage_cache_); 102 file_system_usage_cache_->DecrementDirty(path); 103} 104 105void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota( 106 const QuotaReservationInfo& info, 107 const ReserveQuotaCallback& callback, 108 storage::QuotaStatusCode status, 109 int64 usage, 110 int64 quota) { 111 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 112 DCHECK(info.origin.is_valid()); 113 DCHECK_LE(0, usage); 114 DCHECK_LE(0, quota); 115 if (status != storage::kQuotaStatusOk) { 116 callback.Run(base::File::FILE_ERROR_FAILED, 0); 117 return; 118 } 119 120 QuotaReservationInfo normalized_info = info; 121 if (info.delta > 0) { 122 int64 new_usage = 123 base::saturated_cast<int64>(usage + static_cast<uint64>(info.delta)); 124 if (quota < new_usage) 125 new_usage = quota; 126 normalized_info.delta = std::max(static_cast<int64>(0), new_usage - usage); 127 } 128 129 ReserveQuotaInternal(normalized_info); 130 if (callback.Run(base::File::FILE_OK, normalized_info.delta)) 131 return; 132 // The requester could not accept the reserved quota. Revert it. 133 ReserveQuotaInternal( 134 QuotaReservationInfo(normalized_info.origin, 135 normalized_info.type, 136 -normalized_info.delta)); 137} 138 139void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { 140 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 141 DCHECK(info.origin.is_valid()); 142 DCHECK(quota_manager_proxy_.get()); 143 quota_manager_proxy_->NotifyStorageModified( 144 storage::QuotaClient::kFileSystem, 145 info.origin, 146 FileSystemTypeToQuotaStorageType(info.type), 147 info.delta); 148} 149 150base::File::Error QuotaBackendImpl::GetUsageCachePath( 151 const GURL& origin, 152 FileSystemType type, 153 base::FilePath* usage_file_path) { 154 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); 155 DCHECK(origin.is_valid()); 156 DCHECK(usage_file_path); 157 base::File::Error error = base::File::FILE_OK; 158 *usage_file_path = 159 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( 160 obfuscated_file_util_, origin, type, &error); 161 return error; 162} 163 164QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo( 165 const GURL& origin, FileSystemType type, int64 delta) 166 : origin(origin), type(type), delta(delta) { 167} 168 169QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() { 170} 171 172} // namespace storage 173