• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkit/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 "webkit/browser/fileapi/file_system_usage_cache.h"
15 #include "webkit/browser/quota/quota_client.h"
16 #include "webkit/browser/quota/quota_manager_proxy.h"
17 #include "webkit/common/fileapi/file_system_util.h"
18 
19 namespace fileapi {
20 
QuotaBackendImpl(base::SequencedTaskRunner * file_task_runner,ObfuscatedFileUtil * obfuscated_file_util,FileSystemUsageCache * file_system_usage_cache,quota::QuotaManagerProxy * quota_manager_proxy)21 QuotaBackendImpl::QuotaBackendImpl(
22     base::SequencedTaskRunner* file_task_runner,
23     ObfuscatedFileUtil* obfuscated_file_util,
24     FileSystemUsageCache* file_system_usage_cache,
25     quota::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 
~QuotaBackendImpl()33 QuotaBackendImpl::~QuotaBackendImpl() {
34 }
35 
ReserveQuota(const GURL & origin,FileSystemType type,int64 delta,const ReserveQuotaCallback & callback)36 void 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_);
47   quota_manager_proxy_->GetUsageAndQuota(
48       file_task_runner_, origin, FileSystemTypeToQuotaStorageType(type),
49       base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota,
50                  weak_ptr_factory_.GetWeakPtr(),
51                  QuotaReservationInfo(origin, type, delta), callback));
52 }
53 
ReleaseReservedQuota(const GURL & origin,FileSystemType type,int64 size)54 void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin,
55                                             FileSystemType type,
56                                             int64 size) {
57   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
58   DCHECK(origin.is_valid());
59   DCHECK_LE(0, size);
60   if (!size)
61     return;
62   ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size));
63 }
64 
CommitQuotaUsage(const GURL & origin,FileSystemType type,int64 delta)65 void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin,
66                                         FileSystemType type,
67                                         int64 delta) {
68   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
69   DCHECK(origin.is_valid());
70   if (!delta)
71     return;
72   ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta));
73   base::FilePath path;
74   if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK)
75     return;
76   bool result = file_system_usage_cache_->AtomicUpdateUsageByDelta(path, delta);
77   DCHECK(result);
78 }
79 
IncrementDirtyCount(const GURL & origin,FileSystemType type)80 void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin,
81                                            FileSystemType type) {
82   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
83   DCHECK(origin.is_valid());
84   base::FilePath path;
85   if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK)
86     return;
87   DCHECK(file_system_usage_cache_);
88   file_system_usage_cache_->IncrementDirty(path);
89 }
90 
DecrementDirtyCount(const GURL & origin,FileSystemType type)91 void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin,
92                                            FileSystemType type) {
93   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
94   DCHECK(origin.is_valid());
95   base::FilePath path;
96   if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK)
97     return;
98   DCHECK(file_system_usage_cache_);
99   file_system_usage_cache_->DecrementDirty(path);
100 }
101 
DidGetUsageAndQuotaForReserveQuota(const QuotaReservationInfo & info,const ReserveQuotaCallback & callback,quota::QuotaStatusCode status,int64 usage,int64 quota)102 void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota(
103     const QuotaReservationInfo& info,
104     const ReserveQuotaCallback& callback,
105     quota::QuotaStatusCode status, int64 usage, int64 quota) {
106   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
107   DCHECK(info.origin.is_valid());
108   DCHECK_LE(0, usage);
109   DCHECK_LE(0, quota);
110   if (status != quota::kQuotaStatusOk) {
111     callback.Run(base::File::FILE_ERROR_FAILED, 0);
112     return;
113   }
114 
115   QuotaReservationInfo normalized_info = info;
116   if (info.delta > 0) {
117     int64 new_usage =
118         base::saturated_cast<int64>(usage + static_cast<uint64>(info.delta));
119     if (quota < new_usage)
120       new_usage = quota;
121     normalized_info.delta = std::max(static_cast<int64>(0), new_usage - usage);
122   }
123 
124   ReserveQuotaInternal(normalized_info);
125   if (callback.Run(base::File::FILE_OK, normalized_info.delta))
126     return;
127   // The requester could not accept the reserved quota. Revert it.
128   ReserveQuotaInternal(
129       QuotaReservationInfo(normalized_info.origin,
130                            normalized_info.type,
131                            -normalized_info.delta));
132 }
133 
ReserveQuotaInternal(const QuotaReservationInfo & info)134 void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) {
135   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
136   DCHECK(info.origin.is_valid());
137   DCHECK(quota_manager_proxy_);
138   quota_manager_proxy_->NotifyStorageModified(
139       quota::QuotaClient::kFileSystem, info.origin,
140       FileSystemTypeToQuotaStorageType(info.type), info.delta);
141 }
142 
GetUsageCachePath(const GURL & origin,FileSystemType type,base::FilePath * usage_file_path)143 base::File::Error QuotaBackendImpl::GetUsageCachePath(
144     const GURL& origin,
145     FileSystemType type,
146     base::FilePath* usage_file_path) {
147   DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
148   DCHECK(origin.is_valid());
149   DCHECK(usage_file_path);
150   base::File::Error error = base::File::FILE_OK;
151   *usage_file_path =
152       SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
153           obfuscated_file_util_, origin, type, &error);
154   return error;
155 }
156 
QuotaReservationInfo(const GURL & origin,FileSystemType type,int64 delta)157 QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo(
158     const GURL& origin, FileSystemType type, int64 delta)
159     : origin(origin), type(type), delta(delta) {
160 }
161 
~QuotaReservationInfo()162 QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() {
163 }
164 
165 }  // namespace fileapi
166