Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(347)

Side by Side Diff: storage/browser/quota/quota_manager.cc

Issue 2592793002: Revert of Change how the quota system computes the total poolsize for temporary storage (Closed)
Patch Set: Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « storage/browser/quota/quota_manager.h ('k') | storage/browser/quota/quota_manager_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "storage/browser/quota/quota_manager.h" 5 #include "storage/browser/quota/quota_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <functional> 11 #include <functional>
12 #include <limits> 12 #include <limits>
13 #include <memory> 13 #include <memory>
14 #include <utility> 14 #include <utility>
15 15
16 #include "base/barrier_closure.h"
17 #include "base/bind.h" 16 #include "base/bind.h"
18 #include "base/bind_helpers.h" 17 #include "base/bind_helpers.h"
19 #include "base/command_line.h" 18 #include "base/command_line.h"
20 #include "base/files/file_util.h" 19 #include "base/files/file_util.h"
21 #include "base/macros.h" 20 #include "base/macros.h"
22 #include "base/metrics/histogram_macros.h" 21 #include "base/metrics/histogram_macros.h"
23 #include "base/numerics/safe_conversions.h" 22 #include "base/numerics/safe_conversions.h"
24 #include "base/profiler/scoped_tracker.h" 23 #include "base/profiler/scoped_tracker.h"
25 #include "base/sequenced_task_runner.h" 24 #include "base/sequenced_task_runner.h"
26 #include "base/single_thread_task_runner.h" 25 #include "base/single_thread_task_runner.h"
27 #include "base/strings/string_number_conversions.h" 26 #include "base/strings/string_number_conversions.h"
28 #include "base/sys_info.h" 27 #include "base/sys_info.h"
29 #include "base/task_runner_util.h" 28 #include "base/task_runner_util.h"
30 #include "base/threading/thread_task_runner_handle.h"
31 #include "base/time/time.h" 29 #include "base/time/time.h"
32 #include "base/trace_event/trace_event.h" 30 #include "base/trace_event/trace_event.h"
33 #include "net/base/url_util.h" 31 #include "net/base/url_util.h"
34 #include "storage/browser/quota/client_usage_tracker.h" 32 #include "storage/browser/quota/client_usage_tracker.h"
35 #include "storage/browser/quota/quota_manager_proxy.h" 33 #include "storage/browser/quota/quota_manager_proxy.h"
36 #include "storage/browser/quota/quota_temporary_storage_evictor.h" 34 #include "storage/browser/quota/quota_temporary_storage_evictor.h"
37 #include "storage/browser/quota/storage_monitor.h" 35 #include "storage/browser/quota/storage_monitor.h"
38 #include "storage/browser/quota/usage_tracker.h" 36 #include "storage/browser/quota/usage_tracker.h"
39 #include "storage/common/quota/quota_types.h" 37 #include "storage/common/quota/quota_types.h"
40 38
39 #define UMA_HISTOGRAM_MBYTES(name, sample) \
40 UMA_HISTOGRAM_CUSTOM_COUNTS( \
41 (name), static_cast<int>((sample) / kMBytes), \
42 1, 10 * 1024 * 1024 /* 10TB */, 100)
43
41 namespace storage { 44 namespace storage {
42 45
43 namespace { 46 namespace {
44 47
45 const int64_t kMBytes = 1024 * 1024; 48 const int64_t kMBytes = 1024 * 1024;
46 const int kMinutesInMilliSeconds = 60 * 1000; 49 const int kMinutesInMilliSeconds = 60 * 1000;
50
47 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour 51 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
48 52 const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0; // 33%
49 #define UMA_HISTOGRAM_MBYTES(name, sample) \
50 UMA_HISTOGRAM_CUSTOM_COUNTS((name), static_cast<int>((sample) / kMBytes), 1, \
51 10 * 1024 * 1024 /* 10TB */, 100)
52 53
53 } // namespace 54 } // namespace
54 55
56 // Arbitrary for now, but must be reasonably small so that
57 // in-memory databases can fit.
58 // TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this.
59 const int64_t QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes;
60
55 const int64_t QuotaManager::kNoLimit = INT64_MAX; 61 const int64_t QuotaManager::kNoLimit = INT64_MAX;
56 62
63 const int QuotaManager::kPerHostTemporaryPortion = 5; // 20%
64
57 // Cap size for per-host persistent quota determined by the histogram. 65 // Cap size for per-host persistent quota determined by the histogram.
58 // This is a bit lax value because the histogram says nothing about per-host 66 // This is a bit lax value because the histogram says nothing about per-host
59 // persistent storage usage and we determined by global persistent storage 67 // persistent storage usage and we determined by global persistent storage
60 // usage that is less than 10GB for almost all users. 68 // usage that is less than 10GB for almost all users.
61 const int64_t QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes; 69 const int64_t QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes;
62 70
63 // Heuristics: assuming average cloud server allows a few Gigs storage
64 // on the server side and the storage needs to be shared for user data
65 // and by multiple apps.
66 int64_t QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes;
67
68 const char QuotaManager::kDatabaseName[] = "QuotaManager"; 71 const char QuotaManager::kDatabaseName[] = "QuotaManager";
69 72
70 const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3; 73 const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3;
74
75 // Preserve kMinimumPreserveForSystem disk space for system book-keeping
76 // when returning the quota to unlimited apps/extensions.
77 // TODO(kinuko): This should be like 10% of the actual disk space.
78 // For now we simply use a constant as getting the disk size needs
79 // platform-dependent code. (http://crbug.com/178976)
80 int64_t QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes;
81
71 const int QuotaManager::kEvictionIntervalInMilliSeconds = 82 const int QuotaManager::kEvictionIntervalInMilliSeconds =
72 30 * kMinutesInMilliSeconds; 83 30 * kMinutesInMilliSeconds;
73 84
74 const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] = 85 const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] =
75 "Quota.TimeBetweenRepeatedOriginEvictions"; 86 "Quota.TimeBetweenRepeatedOriginEvictions";
76 const char QuotaManager::kEvictedOriginAccessedCountHistogram[] = 87 const char QuotaManager::kEvictedOriginAccessedCountHistogram[] =
77 "Quota.EvictedOriginAccessCount"; 88 "Quota.EvictedOriginAccessCount";
78 const char QuotaManager::kEvictedOriginTimeSinceAccessHistogram[] = 89 const char QuotaManager::kEvictedOriginTimeSinceAccessHistogram[] =
79 "Quota.EvictedOriginTimeSinceAccess"; 90 "Quota.EvictedOriginTimeSinceAccess";
80 91
92 // Heuristics: assuming average cloud server allows a few Gigs storage
93 // on the server side and the storage needs to be shared for user data
94 // and by multiple apps.
95 int64_t QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes;
96
81 namespace { 97 namespace {
82 98
83 bool IsSupportedType(StorageType type) {
84 return type == kStorageTypeTemporary || type == kStorageTypePersistent ||
85 type == kStorageTypeSyncable;
86 }
87
88 bool IsSupportedIncognitoType(StorageType type) {
89 return type == kStorageTypeTemporary || type == kStorageTypePersistent;
90 }
91
92 void CountOriginType(const std::set<GURL>& origins, 99 void CountOriginType(const std::set<GURL>& origins,
93 SpecialStoragePolicy* policy, 100 SpecialStoragePolicy* policy,
94 size_t* protected_origins, 101 size_t* protected_origins,
95 size_t* unlimited_origins) { 102 size_t* unlimited_origins) {
96 DCHECK(protected_origins); 103 DCHECK(protected_origins);
97 DCHECK(unlimited_origins); 104 DCHECK(unlimited_origins);
98 *protected_origins = 0; 105 *protected_origins = 0;
99 *unlimited_origins = 0; 106 *unlimited_origins = 0;
100 if (!policy) 107 if (!policy)
101 return; 108 return;
102 for (std::set<GURL>::const_iterator itr = origins.begin(); 109 for (std::set<GURL>::const_iterator itr = origins.begin();
103 itr != origins.end(); 110 itr != origins.end();
104 ++itr) { 111 ++itr) {
105 if (policy->IsStorageProtected(*itr)) 112 if (policy->IsStorageProtected(*itr))
106 ++*protected_origins; 113 ++*protected_origins;
107 if (policy->IsStorageUnlimited(*itr)) 114 if (policy->IsStorageUnlimited(*itr))
108 ++*unlimited_origins; 115 ++*unlimited_origins;
109 } 116 }
110 } 117 }
111 118
119 bool SetTemporaryGlobalOverrideQuotaOnDBThread(int64_t* new_quota,
120 QuotaDatabase* database) {
121 DCHECK(database);
122 if (!database->SetQuotaConfigValue(
123 QuotaDatabase::kTemporaryQuotaOverrideKey, *new_quota)) {
124 *new_quota = -1;
125 return false;
126 }
127 return true;
128 }
129
112 bool GetPersistentHostQuotaOnDBThread(const std::string& host, 130 bool GetPersistentHostQuotaOnDBThread(const std::string& host,
113 int64_t* quota, 131 int64_t* quota,
114 QuotaDatabase* database) { 132 QuotaDatabase* database) {
115 DCHECK(database); 133 DCHECK(database);
116 database->GetHostQuota(host, kStorageTypePersistent, quota); 134 database->GetHostQuota(host, kStorageTypePersistent, quota);
117 return true; 135 return true;
118 } 136 }
119 137
120 bool SetPersistentHostQuotaOnDBThread(const std::string& host, 138 bool SetPersistentHostQuotaOnDBThread(const std::string& host,
121 int64_t* new_quota, 139 int64_t* new_quota,
122 QuotaDatabase* database) { 140 QuotaDatabase* database) {
123 DCHECK(database); 141 DCHECK(database);
124 if (database->SetHostQuota(host, kStorageTypePersistent, *new_quota)) 142 if (database->SetHostQuota(host, kStorageTypePersistent, *new_quota))
125 return true; 143 return true;
126 *new_quota = 0; 144 *new_quota = 0;
127 return false; 145 return false;
128 } 146 }
129 147
148 bool InitializeOnDBThread(int64_t* temporary_quota_override,
149 int64_t* desired_available_space,
150 QuotaDatabase* database) {
151 DCHECK(database);
152 database->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey,
153 temporary_quota_override);
154 database->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey,
155 desired_available_space);
156 return true;
157 }
158
130 bool GetLRUOriginOnDBThread(StorageType type, 159 bool GetLRUOriginOnDBThread(StorageType type,
131 const std::set<GURL>& exceptions, 160 const std::set<GURL>& exceptions,
132 SpecialStoragePolicy* policy, 161 SpecialStoragePolicy* policy,
133 GURL* url, 162 GURL* url,
134 QuotaDatabase* database) { 163 QuotaDatabase* database) {
135 DCHECK(database); 164 DCHECK(database);
136 database->GetLRUOrigin(type, exceptions, policy, url); 165 database->GetLRUOrigin(type, exceptions, policy, url);
137 return true; 166 return true;
138 } 167 }
139 168
(...skipping 28 matching lines...) Expand all
168 197
169 if (last_eviction_time != base::Time()) { 198 if (last_eviction_time != base::Time()) {
170 UMA_HISTOGRAM_LONG_TIMES( 199 UMA_HISTOGRAM_LONG_TIMES(
171 QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram, 200 QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram,
172 now - last_eviction_time); 201 now - last_eviction_time);
173 } 202 }
174 203
175 return database->SetOriginLastEvictionTime(origin, type, now); 204 return database->SetOriginLastEvictionTime(origin, type, now);
176 } 205 }
177 206
178 bool BootstrapDatabaseOnDBThread(const std::set<GURL>* origins, 207 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins,
179 QuotaDatabase* database) { 208 QuotaDatabase* database) {
180 DCHECK(database); 209 DCHECK(database);
181 if (database->IsOriginDatabaseBootstrapped()) 210 if (database->IsOriginDatabaseBootstrapped())
182 return true; 211 return true;
183 212
184 // Register existing origins with 0 last time access. 213 // Register existing origins with 0 last time access.
185 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { 214 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) {
186 database->SetOriginDatabaseBootstrapped(true); 215 database->SetOriginDatabaseBootstrapped(true);
187 return true; 216 return true;
188 } 217 }
189 return false; 218 return false;
190 } 219 }
191 220
192 bool UpdateAccessTimeOnDBThread(const GURL& origin, 221 bool UpdateAccessTimeOnDBThread(const GURL& origin,
193 StorageType type, 222 StorageType type,
194 base::Time accessed_time, 223 base::Time accessed_time,
195 QuotaDatabase* database) { 224 QuotaDatabase* database) {
196 DCHECK(database); 225 DCHECK(database);
197 return database->SetOriginLastAccessTime(origin, type, accessed_time); 226 return database->SetOriginLastAccessTime(origin, type, accessed_time);
198 } 227 }
199 228
200 bool UpdateModifiedTimeOnDBThread(const GURL& origin, 229 bool UpdateModifiedTimeOnDBThread(const GURL& origin,
201 StorageType type, 230 StorageType type,
202 base::Time modified_time, 231 base::Time modified_time,
203 QuotaDatabase* database) { 232 QuotaDatabase* database) {
204 DCHECK(database); 233 DCHECK(database);
205 return database->SetOriginLastModifiedTime(origin, type, modified_time); 234 return database->SetOriginLastModifiedTime(origin, type, modified_time);
206 } 235 }
207 236
237 int64_t CalculateTemporaryGlobalQuota(int64_t global_limited_usage,
238 int64_t available_space) {
239 DCHECK_GE(global_limited_usage, 0);
240 int64_t avail_space = available_space;
241 if (avail_space <
242 std::numeric_limits<int64_t>::max() - global_limited_usage) {
243 // We basically calculate the temporary quota by
244 // [available_space + space_used_for_temp] * kTempQuotaRatio,
245 // but make sure we'll have no overflow.
246 avail_space += global_limited_usage;
247 }
248 int64_t pool_size = avail_space * kTemporaryQuotaRatioToAvail;
249 UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", pool_size);
250 return pool_size;
251 }
252
253 void DispatchTemporaryGlobalQuotaCallback(
254 const QuotaCallback& callback,
255 QuotaStatusCode status,
256 const UsageAndQuota& usage_and_quota) {
257 if (status != kQuotaStatusOk) {
258 callback.Run(status, 0);
259 return;
260 }
261
262 callback.Run(status, CalculateTemporaryGlobalQuota(
263 usage_and_quota.global_limited_usage,
264 usage_and_quota.available_disk_space));
265 }
266
267 int64_t CalculateQuotaWithDiskSpace(int64_t available_disk_space,
268 int64_t usage,
269 int64_t quota) {
270 if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) {
271 LOG(WARNING)
272 << "Running out of disk space for profile."
273 << " QuotaManager starts forbidding further quota consumption.";
274 return usage;
275 }
276
277 if (quota < usage) {
278 // No more space; cap the quota to the current usage.
279 return usage;
280 }
281
282 available_disk_space -= QuotaManager::kMinimumPreserveForSystem;
283 if (available_disk_space < quota - usage)
284 return available_disk_space + usage;
285
286 return quota;
287 }
288
289 int64_t CalculateTemporaryHostQuota(int64_t host_usage,
290 int64_t global_quota,
291 int64_t global_limited_usage) {
292 DCHECK_GE(global_limited_usage, 0);
293 int64_t host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion;
294 if (global_limited_usage > global_quota)
295 host_quota = std::min(host_quota, host_usage);
296 return host_quota;
297 }
298
299 void DispatchUsageAndQuotaForWebApps(
300 StorageType type,
301 bool is_incognito,
302 bool is_unlimited,
303 bool can_query_disk_size,
304 const QuotaManager::GetUsageAndQuotaCallback& callback,
305 QuotaStatusCode status,
306 const UsageAndQuota& usage_and_quota) {
307 if (status != kQuotaStatusOk) {
308 callback.Run(status, 0, 0);
309 return;
310 }
311
312 int64_t usage = usage_and_quota.usage;
313 int64_t quota = usage_and_quota.quota;
314
315 if (type == kStorageTypeTemporary && !is_unlimited) {
316 quota = CalculateTemporaryHostQuota(
317 usage, quota, usage_and_quota.global_limited_usage);
318 }
319
320 if (is_incognito) {
321 quota = std::min(quota, QuotaManager::kIncognitoDefaultQuotaLimit);
322 callback.Run(status, usage, quota);
323 return;
324 }
325
326 // For apps with unlimited permission or can_query_disk_size is true (and not
327 // in incognito mode).
328 // We assume we can expose the actual disk size for them and cap the quota by
329 // the available disk space.
330 if (is_unlimited || can_query_disk_size) {
331 quota = CalculateQuotaWithDiskSpace(
332 usage_and_quota.available_disk_space,
333 usage, quota);
334 }
335
336 callback.Run(status, usage, quota);
337
338 if (type == kStorageTypeTemporary && !is_unlimited)
339 UMA_HISTOGRAM_MBYTES("Quota.QuotaForOrigin", quota);
340 }
341
208 } // namespace 342 } // namespace
209 343
210 class QuotaManager::UsageAndQuotaHelper : public QuotaTask { 344 UsageAndQuota::UsageAndQuota()
345 : usage(0),
346 global_limited_usage(0),
347 quota(0),
348 available_disk_space(0) {
349 }
350
351 UsageAndQuota::UsageAndQuota(int64_t usage,
352 int64_t global_limited_usage,
353 int64_t quota,
354 int64_t available_disk_space)
355 : usage(usage),
356 global_limited_usage(global_limited_usage),
357 quota(quota),
358 available_disk_space(available_disk_space) {}
359
360 class UsageAndQuotaCallbackDispatcher
361 : public QuotaTask,
362 public base::SupportsWeakPtr<UsageAndQuotaCallbackDispatcher> {
211 public: 363 public:
212 UsageAndQuotaHelper(QuotaManager* manager, 364 explicit UsageAndQuotaCallbackDispatcher(QuotaManager* manager)
213 const GURL& origin,
214 StorageType type,
215 bool is_unlimited,
216 bool is_incognito,
217 const UsageAndQuotaCallback& callback)
218 : QuotaTask(manager), 365 : QuotaTask(manager),
219 origin_(origin), 366 has_usage_(false),
220 callback_(callback), 367 has_global_limited_usage_(false),
221 type_(type), 368 has_quota_(false),
222 is_unlimited_(is_unlimited), 369 has_available_disk_space_(false),
223 is_incognito_(is_incognito), 370 status_(kQuotaStatusUnknown),
224 weak_factory_(this) {} 371 usage_and_quota_(-1, -1, -1, -1),
225 372 waiting_callbacks_(1) {}
226 protected: 373
374 ~UsageAndQuotaCallbackDispatcher() override {}
375
376 void WaitForResults(const QuotaManager::UsageAndQuotaCallback& callback) {
377 callback_ = callback;
378 Start();
379 }
380
381 void set_usage(int64_t usage) {
382 usage_and_quota_.usage = usage;
383 has_usage_ = true;
384 }
385
386 void set_global_limited_usage(int64_t global_limited_usage) {
387 usage_and_quota_.global_limited_usage = global_limited_usage;
388 has_global_limited_usage_ = true;
389 }
390
391 void set_quota(int64_t quota) {
392 usage_and_quota_.quota = quota;
393 has_quota_ = true;
394 }
395
396 void set_available_disk_space(int64_t available_disk_space) {
397 usage_and_quota_.available_disk_space = available_disk_space;
398 has_available_disk_space_ = true;
399 }
400
401 UsageCallback GetHostUsageCallback() {
402 ++waiting_callbacks_;
403 has_usage_ = true;
404 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage,
405 AsWeakPtr());
406 }
407
408 UsageCallback GetGlobalLimitedUsageCallback() {
409 ++waiting_callbacks_;
410 has_global_limited_usage_ = true;
411 return base::Bind(
412 &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage,
413 AsWeakPtr());
414 }
415
416 QuotaCallback GetQuotaCallback() {
417 ++waiting_callbacks_;
418 has_quota_ = true;
419 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota,
420 AsWeakPtr());
421 }
422
423 QuotaCallback GetAvailableSpaceCallback() {
424 ++waiting_callbacks_;
425 has_available_disk_space_ = true;
426 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace,
427 AsWeakPtr());
428 }
429
430 private:
431 void DidGetHostUsage(int64_t usage) {
432 if (status_ == kQuotaStatusUnknown)
433 status_ = kQuotaStatusOk;
434 usage_and_quota_.usage = usage;
435 CheckCompleted();
436 }
437
438 void DidGetGlobalLimitedUsage(int64_t limited_usage) {
439 if (status_ == kQuotaStatusUnknown)
440 status_ = kQuotaStatusOk;
441 usage_and_quota_.global_limited_usage = limited_usage;
442 CheckCompleted();
443 }
444
445 void DidGetQuota(QuotaStatusCode status, int64_t quota) {
446 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk)
447 status_ = status;
448 usage_and_quota_.quota = quota;
449 CheckCompleted();
450 }
451
452 void DidGetAvailableSpace(QuotaStatusCode status, int64_t space) {
453 // crbug.com/349708
454 TRACE_EVENT0(
455 "io", "UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace");
456
457 DCHECK_GE(space, 0);
458 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk)
459 status_ = status;
460 usage_and_quota_.available_disk_space = space;
461 CheckCompleted();
462 }
463
227 void Run() override { 464 void Run() override {
228 // Start the async process of gathering the info we need. 465 // We initialize waiting_callbacks to 1 so that we won't run
229 // Gather 4 pieces of info before computing an answer: 466 // the completion callback until here even some of the callbacks
230 // settings, device_storage_capacity, host_usage, and host_quota. 467 // are dispatched synchronously.
231 base::Closure barrier = base::BarrierClosure( 468 CheckCompleted();
232 4, base::Bind(&UsageAndQuotaHelper::OnBarrierComplete,
233 weak_factory_.GetWeakPtr()));
234
235 std::string host = net::GetHostOrSpecFromURL(origin_);
236
237 manager()->GetQuotaSettings(base::Bind(&UsageAndQuotaHelper::OnGotSettings,
238 weak_factory_.GetWeakPtr(),
239 barrier));
240 manager()->GetStorageCapacity(
241 base::Bind(&UsageAndQuotaHelper::OnGotCapacity,
242 weak_factory_.GetWeakPtr(), barrier));
243 manager()->GetHostUsage(host, type_,
244 base::Bind(&UsageAndQuotaHelper::OnGotHostUsage,
245 weak_factory_.GetWeakPtr(), barrier));
246
247 // Determine host_quota differently depending on type.
248 if (is_unlimited_) {
249 SetDesiredHostQuota(barrier, kQuotaStatusOk, kNoLimit);
250 } else if (type_ == kStorageTypeSyncable) {
251 SetDesiredHostQuota(barrier, kQuotaStatusOk,
252 kSyncableStorageDefaultHostQuota);
253 } else if (type_ == kStorageTypePersistent) {
254 manager()->GetPersistentHostQuota(
255 host, base::Bind(&UsageAndQuotaHelper::SetDesiredHostQuota,
256 weak_factory_.GetWeakPtr(), barrier));
257 } else {
258 DCHECK_EQ(kStorageTypeTemporary, type_);
259 // For temporary storge, OnGotSettings will set the host quota.
260 }
261 } 469 }
262 470
263 void Aborted() override { 471 void Aborted() override {
264 weak_factory_.InvalidateWeakPtrs(); 472 callback_.Run(kQuotaErrorAbort, UsageAndQuota());
265 callback_.Run(kQuotaErrorAbort, 0, 0);
266 DeleteSoon(); 473 DeleteSoon();
267 } 474 }
268 475
269 void Completed() override { 476 void Completed() override {
270 weak_factory_.InvalidateWeakPtrs(); 477 // crbug.com/349708
271 478 TRACE_EVENT0("io", "UsageAndQuotaCallbackDispatcher::Completed");
272 // Constrain the desired |host_quota| to something that fits. 479
273 // If available space is too low, cap usage at current levels. 480 DCHECK(!has_usage_ || usage_and_quota_.usage >= 0);
274 // If it's close to being too low, cap growth to avoid it getting too low. 481 DCHECK(!has_global_limited_usage_ ||
275 int64_t host_quota = 482 usage_and_quota_.global_limited_usage >= 0);
276 std::min(desired_host_quota_, 483 DCHECK(!has_quota_ || usage_and_quota_.quota >= 0);
277 host_usage_ + 484 DCHECK(!has_available_disk_space_ ||
278 std::max(INT64_C(0), available_space_ - 485 usage_and_quota_.available_disk_space >= 0);
279 settings_.must_remain_available)); 486
280 callback_.Run(kQuotaStatusOk, host_usage_, host_quota); 487 callback_.Run(status_, usage_and_quota_);
281 if (type_ == kStorageTypeTemporary && !is_incognito_ && !is_unlimited_)
282 UMA_HISTOGRAM_MBYTES("Quota.QuotaForOrigin", host_quota);
283 DeleteSoon(); 488 DeleteSoon();
284 } 489 }
285 490
286 private: 491 void CheckCompleted() {
287 QuotaManager* manager() const { 492 if (--waiting_callbacks_ <= 0)
288 return static_cast<QuotaManager*>(observer()); 493 CallCompleted();
289 } 494 }
290 495
291 void OnGotSettings(const base::Closure& barrier_closure, 496 // For sanity checks, they're checked only when DCHECK is on.
292 const QuotaSettings& settings) { 497 bool has_usage_;
293 settings_ = settings; 498 bool has_global_limited_usage_;
294 barrier_closure.Run(); 499 bool has_quota_;
295 if (type_ == kStorageTypeTemporary && !is_unlimited_) { 500 bool has_available_disk_space_;
296 SetDesiredHostQuota(barrier_closure, kQuotaStatusOk, 501
297 settings.per_host_quota); 502 QuotaStatusCode status_;
298 } 503 UsageAndQuota usage_and_quota_;
299 }
300
301 void OnGotCapacity(const base::Closure& barrier_closure,
302 int64_t total_space,
303 int64_t available_space) {
304 total_space_ = total_space;
305 available_space_ = available_space;
306 barrier_closure.Run();
307 }
308
309 void OnGotHostUsage(const base::Closure& barrier_closure, int64_t usage) {
310 host_usage_ = usage;
311 barrier_closure.Run();
312 }
313
314 void SetDesiredHostQuota(const base::Closure& barrier_closure,
315 QuotaStatusCode status,
316 int64_t quota) {
317 desired_host_quota_ = quota;
318 barrier_closure.Run();
319 }
320
321 void OnBarrierComplete() { CallCompleted(); }
322
323 GURL origin_;
324 QuotaManager::UsageAndQuotaCallback callback_; 504 QuotaManager::UsageAndQuotaCallback callback_;
325 StorageType type_; 505 int waiting_callbacks_;
326 bool is_unlimited_; 506
327 bool is_incognito_; 507 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher);
328 int64_t available_space_ = 0;
329 int64_t total_space_ = 0;
330 int64_t desired_host_quota_ = 0;
331 int64_t host_usage_ = 0;
332 QuotaSettings settings_;
333 base::WeakPtrFactory<UsageAndQuotaHelper> weak_factory_;
334 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaHelper);
335 }; 508 };
336 509
337 // Helper to asychronously gather information needed at the start of an
338 // eviction round.
339 class QuotaManager::EvictionRoundInfoHelper : public QuotaTask {
340 public:
341 EvictionRoundInfoHelper(QuotaManager* manager,
342 const EvictionRoundInfoCallback& callback)
343 : QuotaTask(manager), callback_(callback), weak_factory_(this) {}
344
345 protected:
346 void Run() override {
347 // Gather 2 pieces of info before deciding if we need to get GlobalUsage:
348 // settings and device_storage_capacity.
349 base::Closure barrier = base::BarrierClosure(
350 2, base::Bind(&EvictionRoundInfoHelper::OnBarrierComplete,
351 weak_factory_.GetWeakPtr()));
352
353 manager()->GetQuotaSettings(
354 base::Bind(&EvictionRoundInfoHelper::OnGotSettings,
355 weak_factory_.GetWeakPtr(), barrier));
356 manager()->GetStorageCapacity(
357 base::Bind(&EvictionRoundInfoHelper::OnGotCapacity,
358 weak_factory_.GetWeakPtr(), barrier));
359 }
360
361 void Aborted() override {
362 weak_factory_.InvalidateWeakPtrs();
363 callback_.Run(kQuotaErrorAbort, QuotaSettings(), 0, 0, 0, false);
364 DeleteSoon();
365 }
366
367 void Completed() override {
368 weak_factory_.InvalidateWeakPtrs();
369 callback_.Run(kQuotaStatusOk, settings_, available_space_, total_space_,
370 global_usage_, global_usage_is_complete_);
371 DeleteSoon();
372 }
373
374 private:
375 QuotaManager* manager() const {
376 return static_cast<QuotaManager*>(observer());
377 }
378
379 void OnGotSettings(const base::Closure& barrier_closure,
380 const QuotaSettings& settings) {
381 settings_ = settings;
382 barrier_closure.Run();
383 }
384
385 void OnGotCapacity(const base::Closure& barrier_closure,
386 int64_t total_space,
387 int64_t available_space) {
388 total_space_ = total_space;
389 available_space_ = available_space;
390 barrier_closure.Run();
391 }
392
393 void OnBarrierComplete() {
394 // Avoid computing the full current_usage when there's no pressure.
395 int64_t consumed_space = total_space_ - available_space_;
396 if (consumed_space < settings_.pool_size &&
397 available_space_ > settings_.must_remain_available) {
398 DCHECK(!global_usage_is_complete_);
399 global_usage_ =
400 manager()->GetUsageTracker(kStorageTypeTemporary)->GetCachedUsage();
401 CallCompleted();
402 return;
403 }
404 manager()->GetGlobalUsage(
405 kStorageTypeTemporary,
406 base::Bind(&EvictionRoundInfoHelper::OnGotGlobalUsage,
407 weak_factory_.GetWeakPtr()));
408 }
409
410 void OnGotGlobalUsage(int64_t usage, int64_t unlimited_usage) {
411 global_usage_ = std::max(INT64_C(0), usage - unlimited_usage);
412 global_usage_is_complete_ = true;
413 CallCompleted();
414 }
415
416 EvictionRoundInfoCallback callback_;
417 QuotaSettings settings_;
418 int64_t available_space_ = 0;
419 int64_t total_space_ = 0;
420 int64_t global_usage_ = 0;
421 bool global_usage_is_complete_ = false;
422 base::WeakPtrFactory<EvictionRoundInfoHelper> weak_factory_;
423 DISALLOW_COPY_AND_ASSIGN(EvictionRoundInfoHelper);
424 };
425
426 class QuotaManager::GetUsageInfoTask : public QuotaTask { 510 class QuotaManager::GetUsageInfoTask : public QuotaTask {
427 public: 511 public:
428 GetUsageInfoTask( 512 GetUsageInfoTask(
429 QuotaManager* manager, 513 QuotaManager* manager,
430 const GetUsageInfoCallback& callback) 514 const GetUsageInfoCallback& callback)
431 : QuotaTask(manager), 515 : QuotaTask(manager),
432 callback_(callback), 516 callback_(callback),
433 weak_factory_(this) { 517 weak_factory_(this) {
434 } 518 }
435 519
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 OriginInfoTableEntries entries_; 859 OriginInfoTableEntries entries_;
776 }; 860 };
777 861
778 // QuotaManager --------------------------------------------------------------- 862 // QuotaManager ---------------------------------------------------------------
779 863
780 QuotaManager::QuotaManager( 864 QuotaManager::QuotaManager(
781 bool is_incognito, 865 bool is_incognito,
782 const base::FilePath& profile_path, 866 const base::FilePath& profile_path,
783 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, 867 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
784 const scoped_refptr<base::SequencedTaskRunner>& db_thread, 868 const scoped_refptr<base::SequencedTaskRunner>& db_thread,
785 const scoped_refptr<SpecialStoragePolicy>& special_storage_policy, 869 const scoped_refptr<SpecialStoragePolicy>& special_storage_policy)
786 const GetQuotaSettingsFunc& get_settings_function)
787 : is_incognito_(is_incognito), 870 : is_incognito_(is_incognito),
788 profile_path_(profile_path), 871 profile_path_(profile_path),
789 proxy_(new QuotaManagerProxy(this, io_thread)), 872 proxy_(new QuotaManagerProxy(this, io_thread)),
790 db_disabled_(false), 873 db_disabled_(false),
791 eviction_disabled_(false), 874 eviction_disabled_(false),
792 io_thread_(io_thread), 875 io_thread_(io_thread),
793 db_thread_(db_thread), 876 db_thread_(db_thread),
794 get_settings_function_(get_settings_function),
795 is_getting_eviction_origin_(false), 877 is_getting_eviction_origin_(false),
878 temporary_quota_initialized_(false),
879 temporary_quota_override_(-1),
796 special_storage_policy_(special_storage_policy), 880 special_storage_policy_(special_storage_policy),
797 get_volume_info_fn_(&QuotaManager::GetVolumeInfo), 881 get_volume_info_fn_(&QuotaManager::GetVolumeInfo),
798 storage_monitor_(new StorageMonitor(this)), 882 storage_monitor_(new StorageMonitor(this)),
799 weak_factory_(this) { 883 weak_factory_(this) {}
800 DCHECK_EQ(settings_.refresh_interval, base::TimeDelta::Max());
801 if (!get_settings_function.is_null()) {
802 // Reset the interval to ensure we use the get_settings_function
803 // the first times settings_ is needed.
804 settings_.refresh_interval = base::TimeDelta();
805 get_settings_task_runner_ = base::ThreadTaskRunnerHandle::Get();
806 }
807 }
808
809 void QuotaManager::SetQuotaSettings(const QuotaSettings& settings) {
810 settings_ = settings;
811 settings_timestamp_ = base::TimeTicks::Now();
812 }
813 884
814 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) { 885 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) {
815 LazyInitialize(); 886 LazyInitialize();
816 GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback); 887 GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback);
817 get_usage_info->Start(); 888 get_usage_info->Start();
818 } 889 }
819 890
820 void QuotaManager::GetUsageAndQuotaForWebApps( 891 void QuotaManager::GetUsageAndQuotaForWebApps(
821 const GURL& origin, 892 const GURL& origin,
822 StorageType type, 893 StorageType type,
823 const UsageAndQuotaCallback& callback) { 894 const GetUsageAndQuotaCallback& callback) {
824 DCHECK(origin == origin.GetOrigin()); 895 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
825 if (!IsSupportedType(type) || 896 tracked_objects::ScopedTracker tracking_profile(
826 (is_incognito_ && !IsSupportedIncognitoType(type))) { 897 FROM_HERE_WITH_EXPLICIT_FUNCTION(
898 "477117 QuotaManager::GetUsageAndQuotaForWebApps"));
899 if (type != kStorageTypeTemporary &&
900 type != kStorageTypePersistent &&
901 type != kStorageTypeSyncable) {
827 callback.Run(kQuotaErrorNotSupported, 0, 0); 902 callback.Run(kQuotaErrorNotSupported, 0, 0);
828 return; 903 return;
829 } 904 }
905
906 DCHECK(origin == origin.GetOrigin());
830 LazyInitialize(); 907 LazyInitialize();
831 UsageAndQuotaHelper* helper = new UsageAndQuotaHelper( 908
832 this, origin, type, IsStorageUnlimited(origin, type), is_incognito_, 909 bool unlimited = IsStorageUnlimited(origin, type);
833 callback); 910 bool can_query_disk_size = CanQueryDiskSize(origin);
834 helper->Start(); 911
912 UsageAndQuotaCallbackDispatcher* dispatcher =
913 new UsageAndQuotaCallbackDispatcher(this);
914
915 if (unlimited) {
916 dispatcher->set_quota(kNoLimit);
917 } else {
918 if (type == kStorageTypeTemporary) {
919 GetUsageTracker(type)->GetGlobalLimitedUsage(
920 dispatcher->GetGlobalLimitedUsageCallback());
921 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
922 } else if (type == kStorageTypePersistent) {
923 GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin),
924 dispatcher->GetQuotaCallback());
925 } else {
926 dispatcher->set_quota(kSyncableStorageDefaultHostQuota);
927 }
928 }
929
930 DCHECK(GetUsageTracker(type));
931 GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin),
932 dispatcher->GetHostUsageCallback());
933
934 if (!is_incognito_ && (unlimited || can_query_disk_size))
935 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
936
937 dispatcher->WaitForResults(base::Bind(
938 &DispatchUsageAndQuotaForWebApps,
939 type, is_incognito_, unlimited, can_query_disk_size,
940 callback));
835 } 941 }
836 942
837 void QuotaManager::GetUsageAndQuota(const GURL& origin, 943 void QuotaManager::GetUsageAndQuota(
838 StorageType type, 944 const GURL& origin, StorageType type,
839 const UsageAndQuotaCallback& callback) { 945 const GetUsageAndQuotaCallback& callback) {
840 DCHECK(origin == origin.GetOrigin()); 946 DCHECK(origin == origin.GetOrigin());
841 947
842 if (IsStorageUnlimited(origin, type)) { 948 if (IsStorageUnlimited(origin, type)) {
843 // TODO(michaeln): This seems like a non-obvious odd behavior, probably for
844 // apps/extensions, but it would be good to elimiate this special case.
845 callback.Run(kQuotaStatusOk, 0, kNoLimit); 949 callback.Run(kQuotaStatusOk, 0, kNoLimit);
846 return; 950 return;
847 } 951 }
848 952
849 GetUsageAndQuotaForWebApps(origin, type, callback); 953 GetUsageAndQuotaForWebApps(origin, type, callback);
850 } 954 }
851 955
852 void QuotaManager::NotifyStorageAccessed( 956 void QuotaManager::NotifyStorageAccessed(
853 QuotaClient::ID client_id, 957 QuotaClient::ID client_id,
854 const GURL& origin, StorageType type) { 958 const GURL& origin, StorageType type) {
(...skipping 25 matching lines...) Expand all
880 984
881 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, 985 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id,
882 const GURL& origin, 986 const GURL& origin,
883 StorageType type, 987 StorageType type,
884 bool enabled) { 988 bool enabled) {
885 LazyInitialize(); 989 LazyInitialize();
886 DCHECK(GetUsageTracker(type)); 990 DCHECK(GetUsageTracker(type));
887 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); 991 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled);
888 } 992 }
889 993
994 void QuotaManager::SetTemporaryStorageEvictionPolicy(
995 std::unique_ptr<QuotaEvictionPolicy> policy) {
996 temporary_storage_eviction_policy_ = std::move(policy);
997 }
998
890 void QuotaManager::DeleteOriginData(const GURL& origin, 999 void QuotaManager::DeleteOriginData(const GURL& origin,
891 StorageType type, 1000 StorageType type,
892 int quota_client_mask, 1001 int quota_client_mask,
893 const StatusCallback& callback) { 1002 const StatusCallback& callback) {
894 DeleteOriginDataInternal(origin, type, quota_client_mask, false, callback); 1003 DeleteOriginDataInternal(origin, type, quota_client_mask, false, callback);
895 } 1004 }
896 1005
897 void QuotaManager::DeleteHostData(const std::string& host, 1006 void QuotaManager::DeleteHostData(const std::string& host,
898 StorageType type, 1007 StorageType type,
899 int quota_client_mask, 1008 int quota_client_mask,
900 const StatusCallback& callback) { 1009 const StatusCallback& callback) {
901 LazyInitialize(); 1010 LazyInitialize();
1011
902 if (host.empty() || clients_.empty()) { 1012 if (host.empty() || clients_.empty()) {
903 callback.Run(kQuotaStatusOk); 1013 callback.Run(kQuotaStatusOk);
904 return; 1014 return;
905 } 1015 }
906 1016
907 HostDataDeleter* deleter = 1017 HostDataDeleter* deleter =
908 new HostDataDeleter(this, host, type, quota_client_mask, callback); 1018 new HostDataDeleter(this, host, type, quota_client_mask, callback);
909 deleter->Start(); 1019 deleter->Start();
910 } 1020 }
911 1021
1022 void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback& callback) {
1023 if (!available_space_callbacks_.Add(callback))
1024 return;
1025 // crbug.com/349708
1026 TRACE_EVENT0("io", "QuotaManager::GetAvailableSpace");
1027
1028 PostTaskAndReplyWithResult(
1029 db_thread_.get(),
1030 FROM_HERE,
1031 base::Bind(&QuotaManager::CallGetAmountOfFreeDiskSpace,
1032 get_volume_info_fn_, profile_path_),
1033 base::Bind(&QuotaManager::DidGetAvailableSpace,
1034 weak_factory_.GetWeakPtr()));
1035 }
1036
1037 void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) {
1038 LazyInitialize();
1039 if (!temporary_quota_initialized_) {
1040 db_initialization_callbacks_.Add(base::Bind(
1041 &QuotaManager::GetTemporaryGlobalQuota,
1042 weak_factory_.GetWeakPtr(), callback));
1043 return;
1044 }
1045
1046 if (temporary_quota_override_ > 0) {
1047 callback.Run(kQuotaStatusOk, temporary_quota_override_);
1048 return;
1049 }
1050
1051 UsageAndQuotaCallbackDispatcher* dispatcher =
1052 new UsageAndQuotaCallbackDispatcher(this);
1053 GetUsageTracker(kStorageTypeTemporary)->
1054 GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
1055 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
1056 dispatcher->WaitForResults(
1057 base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback));
1058 }
1059
1060 void QuotaManager::SetTemporaryGlobalOverrideQuota(
1061 int64_t new_quota,
1062 const QuotaCallback& callback) {
1063 LazyInitialize();
1064
1065 if (new_quota < 0) {
1066 if (!callback.is_null())
1067 callback.Run(kQuotaErrorInvalidModification, -1);
1068 return;
1069 }
1070
1071 if (db_disabled_) {
1072 if (!callback.is_null())
1073 callback.Run(kQuotaErrorInvalidAccess, -1);
1074 return;
1075 }
1076
1077 int64_t* new_quota_ptr = new int64_t(new_quota);
1078 PostTaskAndReplyWithResultForDBThread(
1079 FROM_HERE,
1080 base::Bind(&SetTemporaryGlobalOverrideQuotaOnDBThread,
1081 base::Unretained(new_quota_ptr)),
1082 base::Bind(&QuotaManager::DidSetTemporaryGlobalOverrideQuota,
1083 weak_factory_.GetWeakPtr(),
1084 callback,
1085 base::Owned(new_quota_ptr)));
1086 }
1087
912 void QuotaManager::GetPersistentHostQuota(const std::string& host, 1088 void QuotaManager::GetPersistentHostQuota(const std::string& host,
913 const QuotaCallback& callback) { 1089 const QuotaCallback& callback) {
914 LazyInitialize(); 1090 LazyInitialize();
915 if (host.empty()) { 1091 if (host.empty()) {
916 // This could happen if we are called on file:///. 1092 // This could happen if we are called on file:///.
917 // TODO(kinuko) We may want to respect --allow-file-access-from-files 1093 // TODO(kinuko) We may want to respect --allow-file-access-from-files
918 // command line switch. 1094 // command line switch.
919 callback.Run(kQuotaStatusOk, 0); 1095 callback.Run(kQuotaStatusOk, 0);
920 return; 1096 return;
921 } 1097 }
(...skipping 21 matching lines...) Expand all
943 // This could happen if we are called on file:///. 1119 // This could happen if we are called on file:///.
944 callback.Run(kQuotaErrorNotSupported, 0); 1120 callback.Run(kQuotaErrorNotSupported, 0);
945 return; 1121 return;
946 } 1122 }
947 1123
948 if (new_quota < 0) { 1124 if (new_quota < 0) {
949 callback.Run(kQuotaErrorInvalidModification, -1); 1125 callback.Run(kQuotaErrorInvalidModification, -1);
950 return; 1126 return;
951 } 1127 }
952 1128
953 // Cap the requested size at the per-host quota limit. 1129 if (kPerHostPersistentQuotaLimit < new_quota) {
954 new_quota = std::min(new_quota, kPerHostPersistentQuotaLimit); 1130 // Cap the requested size at the per-host quota limit.
1131 new_quota = kPerHostPersistentQuotaLimit;
1132 }
955 1133
956 if (db_disabled_) { 1134 if (db_disabled_) {
957 callback.Run(kQuotaErrorInvalidAccess, -1); 1135 callback.Run(kQuotaErrorInvalidAccess, -1);
958 return; 1136 return;
959 } 1137 }
960 1138
961 int64_t* new_quota_ptr = new int64_t(new_quota); 1139 int64_t* new_quota_ptr = new int64_t(new_quota);
962 PostTaskAndReplyWithResultForDBThread( 1140 PostTaskAndReplyWithResultForDBThread(
963 FROM_HERE, 1141 FROM_HERE,
964 base::Bind(&SetPersistentHostQuotaOnDBThread, 1142 base::Bind(&SetPersistentHostQuotaOnDBThread,
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 QuotaManager::EvictionContext::EvictionContext() 1282 QuotaManager::EvictionContext::EvictionContext()
1105 : evicted_type(kStorageTypeUnknown) { 1283 : evicted_type(kStorageTypeUnknown) {
1106 } 1284 }
1107 1285
1108 QuotaManager::EvictionContext::~EvictionContext() { 1286 QuotaManager::EvictionContext::~EvictionContext() {
1109 } 1287 }
1110 1288
1111 void QuotaManager::LazyInitialize() { 1289 void QuotaManager::LazyInitialize() {
1112 DCHECK(io_thread_->BelongsToCurrentThread()); 1290 DCHECK(io_thread_->BelongsToCurrentThread());
1113 if (database_) { 1291 if (database_) {
1114 // Already initialized. 1292 // Initialization seems to be done already.
1115 return; 1293 return;
1116 } 1294 }
1117 1295
1118 // Use an empty path to open an in-memory only databse for incognito. 1296 // Use an empty path to open an in-memory only databse for incognito.
1119 database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : 1297 database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() :
1120 profile_path_.AppendASCII(kDatabaseName))); 1298 profile_path_.AppendASCII(kDatabaseName)));
1121 1299
1122 temporary_usage_tracker_.reset(new UsageTracker( 1300 temporary_usage_tracker_.reset(new UsageTracker(
1123 clients_, kStorageTypeTemporary, special_storage_policy_.get(), 1301 clients_, kStorageTypeTemporary, special_storage_policy_.get(),
1124 storage_monitor_.get())); 1302 storage_monitor_.get()));
1125 persistent_usage_tracker_.reset(new UsageTracker( 1303 persistent_usage_tracker_.reset(new UsageTracker(
1126 clients_, kStorageTypePersistent, special_storage_policy_.get(), 1304 clients_, kStorageTypePersistent, special_storage_policy_.get(),
1127 storage_monitor_.get())); 1305 storage_monitor_.get()));
1128 syncable_usage_tracker_.reset(new UsageTracker( 1306 syncable_usage_tracker_.reset(new UsageTracker(
1129 clients_, kStorageTypeSyncable, special_storage_policy_.get(), 1307 clients_, kStorageTypeSyncable, special_storage_policy_.get(),
1130 storage_monitor_.get())); 1308 storage_monitor_.get()));
1131 1309
1132 if (!is_incognito_) { 1310 int64_t* temporary_quota_override = new int64_t(-1);
1133 histogram_timer_.Start( 1311 int64_t* desired_available_space = new int64_t(-1);
1134 FROM_HERE, base::TimeDelta::FromMilliseconds(kReportHistogramInterval),
1135 this, &QuotaManager::ReportHistogram);
1136 }
1137
1138 base::PostTaskAndReplyWithResult(
1139 db_thread_.get(), FROM_HERE,
1140 base::Bind(&QuotaDatabase::IsOriginDatabaseBootstrapped,
1141 base::Unretained(database_.get())),
1142 base::Bind(&QuotaManager::FinishLazyInitialize,
1143 weak_factory_.GetWeakPtr()));
1144 }
1145
1146 void QuotaManager::FinishLazyInitialize(bool is_database_bootstrapped) {
1147 is_database_bootstrapped_ = is_database_bootstrapped;
1148 StartEviction();
1149 }
1150
1151 void QuotaManager::BootstrapDatabaseForEviction(
1152 const GetOriginCallback& did_get_origin_callback,
1153 int64_t usage,
1154 int64_t unlimited_usage) {
1155 // The usage cache should be fully populated now so we can
1156 // seed the database with origins we know about.
1157 std::set<GURL>* origins = new std::set<GURL>;
1158 temporary_usage_tracker_->GetCachedOrigins(origins);
1159 PostTaskAndReplyWithResultForDBThread( 1312 PostTaskAndReplyWithResultForDBThread(
1160 FROM_HERE, base::Bind(&BootstrapDatabaseOnDBThread, base::Owned(origins)), 1313 FROM_HERE,
1161 base::Bind(&QuotaManager::DidBootstrapDatabase, 1314 base::Bind(&InitializeOnDBThread,
1162 weak_factory_.GetWeakPtr(), did_get_origin_callback)); 1315 base::Unretained(temporary_quota_override),
1163 } 1316 base::Unretained(desired_available_space)),
1164 1317 base::Bind(&QuotaManager::DidInitialize,
1165 void QuotaManager::DidBootstrapDatabase( 1318 weak_factory_.GetWeakPtr(),
1166 const GetOriginCallback& did_get_origin_callback, 1319 base::Owned(temporary_quota_override),
1167 bool success) { 1320 base::Owned(desired_available_space)));
1168 is_database_bootstrapped_ = success;
1169 DidDatabaseWork(success);
1170 GetLRUOrigin(kStorageTypeTemporary, did_get_origin_callback);
1171 } 1321 }
1172 1322
1173 void QuotaManager::RegisterClient(QuotaClient* client) { 1323 void QuotaManager::RegisterClient(QuotaClient* client) {
1174 DCHECK(!database_.get()); 1324 DCHECK(!database_.get());
1175 clients_.push_back(client); 1325 clients_.push_back(client);
1176 } 1326 }
1177 1327
1178 UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { 1328 UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const {
1179 switch (type) { 1329 switch (type) {
1180 case kStorageTypeTemporary: 1330 case kStorageTypeTemporary:
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread, 1405 base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread,
1256 base::Unretained(helper)), 1406 base::Unretained(helper)),
1257 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable, 1407 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable,
1258 base::Owned(helper), 1408 base::Owned(helper),
1259 weak_factory_.GetWeakPtr(), 1409 weak_factory_.GetWeakPtr(),
1260 callback)); 1410 callback));
1261 } 1411 }
1262 1412
1263 void QuotaManager::StartEviction() { 1413 void QuotaManager::StartEviction() {
1264 DCHECK(!temporary_storage_evictor_.get()); 1414 DCHECK(!temporary_storage_evictor_.get());
1265 if (eviction_disabled_)
1266 return;
1267 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( 1415 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
1268 this, kEvictionIntervalInMilliSeconds)); 1416 this, kEvictionIntervalInMilliSeconds));
1417 if (desired_available_space_ >= 0)
1418 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
1419 desired_available_space_);
1269 temporary_storage_evictor_->Start(); 1420 temporary_storage_evictor_->Start();
1270 } 1421 }
1271 1422
1272 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin, 1423 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin,
1273 StorageType type, 1424 StorageType type,
1274 bool is_eviction) { 1425 bool is_eviction) {
1275 LazyInitialize(); 1426 LazyInitialize();
1276 if (db_disabled_) 1427 if (db_disabled_)
1277 return; 1428 return;
1278 1429
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 const GetOriginCallback& callback) { 1595 const GetOriginCallback& callback) {
1445 LazyInitialize(); 1596 LazyInitialize();
1446 // This must not be called while there's an in-flight task. 1597 // This must not be called while there's an in-flight task.
1447 DCHECK(!is_getting_eviction_origin_); 1598 DCHECK(!is_getting_eviction_origin_);
1448 is_getting_eviction_origin_ = true; 1599 is_getting_eviction_origin_ = true;
1449 1600
1450 GetOriginCallback did_get_origin_callback = 1601 GetOriginCallback did_get_origin_callback =
1451 base::Bind(&QuotaManager::DidGetEvictionOrigin, 1602 base::Bind(&QuotaManager::DidGetEvictionOrigin,
1452 weak_factory_.GetWeakPtr(), callback); 1603 weak_factory_.GetWeakPtr(), callback);
1453 1604
1454 if (!is_database_bootstrapped_ && !eviction_disabled_) { 1605 if (type == kStorageTypeTemporary && temporary_storage_eviction_policy_) {
1455 // Once bootstrapped, GetLRUOrigin will be called. 1606 std::map<GURL, int64_t> usage_map;
1456 GetGlobalUsage( 1607 // The cached origins are populated by the prior call to
1457 kStorageTypeTemporary, 1608 // GetUsageAndQuotaForEviction().
1458 base::Bind(&QuotaManager::BootstrapDatabaseForEviction, 1609 GetUsageTracker(kStorageTypeTemporary)->GetCachedOriginsUsage(&usage_map);
1459 weak_factory_.GetWeakPtr(), did_get_origin_callback)); 1610
1611 temporary_storage_eviction_policy_->GetEvictionOrigin(
1612 special_storage_policy_, GetEvictionOriginExceptions(extra_exceptions),
1613 usage_map, global_quota, did_get_origin_callback);
1614
1460 return; 1615 return;
1461 } 1616 }
1462 1617
1618 // TODO(calamity): convert LRU origin retrieval into a QuotaEvictionPolicy.
1463 GetLRUOrigin(type, did_get_origin_callback); 1619 GetLRUOrigin(type, did_get_origin_callback);
1464 } 1620 }
1465 1621
1466 void QuotaManager::EvictOriginData(const GURL& origin, 1622 void QuotaManager::EvictOriginData(const GURL& origin,
1467 StorageType type, 1623 StorageType type,
1468 const StatusCallback& callback) { 1624 const EvictOriginDataCallback& callback) {
1469 DCHECK(io_thread_->BelongsToCurrentThread()); 1625 DCHECK(io_thread_->BelongsToCurrentThread());
1470 DCHECK_EQ(type, kStorageTypeTemporary); 1626 DCHECK_EQ(type, kStorageTypeTemporary);
1471 1627
1472 eviction_context_.evicted_origin = origin; 1628 eviction_context_.evicted_origin = origin;
1473 eviction_context_.evicted_type = type; 1629 eviction_context_.evicted_type = type;
1474 eviction_context_.evict_origin_data_callback = callback; 1630 eviction_context_.evict_origin_data_callback = callback;
1475 1631
1476 DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true, 1632 DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true,
1477 base::Bind(&QuotaManager::DidOriginDataEvicted, 1633 base::Bind(&QuotaManager::DidOriginDataEvicted,
1478 weak_factory_.GetWeakPtr())); 1634 weak_factory_.GetWeakPtr()));
1479 } 1635 }
1480 1636
1481 void QuotaManager::GetEvictionRoundInfo( 1637 void QuotaManager::GetUsageAndQuotaForEviction(
1482 const EvictionRoundInfoCallback& callback) { 1638 const UsageAndQuotaCallback& callback) {
1639 // crbug.com/349708
1640 TRACE_EVENT0("io", "QuotaManager::GetUsageAndQuotaForEviction");
1641
1483 DCHECK(io_thread_->BelongsToCurrentThread()); 1642 DCHECK(io_thread_->BelongsToCurrentThread());
1484 LazyInitialize(); 1643 LazyInitialize();
1485 EvictionRoundInfoHelper* helper = new EvictionRoundInfoHelper(this, callback); 1644
1486 helper->Start(); 1645 UsageAndQuotaCallbackDispatcher* dispatcher =
1646 new UsageAndQuotaCallbackDispatcher(this);
1647 GetUsageTracker(kStorageTypeTemporary)
1648 ->GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
1649 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
1650 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
1651 dispatcher->WaitForResults(callback);
1652 }
1653
1654 void QuotaManager::AsyncGetVolumeInfo(
1655 const VolumeInfoCallback& callback) {
1656 DCHECK(io_thread_->BelongsToCurrentThread());
1657 uint64_t* available_space = new uint64_t(0);
1658 uint64_t* total_space = new uint64_t(0);
1659 PostTaskAndReplyWithResult(
1660 db_thread_.get(),
1661 FROM_HERE,
1662 base::Bind(get_volume_info_fn_,
1663 profile_path_,
1664 base::Unretained(available_space),
1665 base::Unretained(total_space)),
1666 base::Bind(&QuotaManager::DidGetVolumeInfo,
1667 weak_factory_.GetWeakPtr(),
1668 callback,
1669 base::Owned(available_space),
1670 base::Owned(total_space)));
1671 }
1672
1673 void QuotaManager::DidGetVolumeInfo(
1674 const VolumeInfoCallback& callback,
1675 uint64_t* available_space, uint64_t* total_space, bool success) {
1676 DCHECK(io_thread_->BelongsToCurrentThread());
1677 callback.Run(success, *available_space, *total_space);
1487 } 1678 }
1488 1679
1489 void QuotaManager::GetLRUOrigin(StorageType type, 1680 void QuotaManager::GetLRUOrigin(StorageType type,
1490 const GetOriginCallback& callback) { 1681 const GetOriginCallback& callback) {
1491 LazyInitialize(); 1682 LazyInitialize();
1492 // This must not be called while there's an in-flight task. 1683 // This must not be called while there's an in-flight task.
1493 DCHECK(lru_origin_callback_.is_null()); 1684 DCHECK(lru_origin_callback_.is_null());
1494 lru_origin_callback_ = callback; 1685 lru_origin_callback_ = callback;
1495 if (db_disabled_) { 1686 if (db_disabled_) {
1496 lru_origin_callback_.Run(GURL()); 1687 lru_origin_callback_.Run(GURL());
1497 lru_origin_callback_.Reset(); 1688 lru_origin_callback_.Reset();
1498 return; 1689 return;
1499 } 1690 }
1500 1691
1501 GURL* url = new GURL; 1692 GURL* url = new GURL;
1502 PostTaskAndReplyWithResultForDBThread( 1693 PostTaskAndReplyWithResultForDBThread(
1503 FROM_HERE, base::Bind(&GetLRUOriginOnDBThread, type, 1694 FROM_HERE, base::Bind(&GetLRUOriginOnDBThread, type,
1504 GetEvictionOriginExceptions(std::set<GURL>()), 1695 GetEvictionOriginExceptions(std::set<GURL>()),
1505 base::RetainedRef(special_storage_policy_), 1696 base::RetainedRef(special_storage_policy_),
1506 base::Unretained(url)), 1697 base::Unretained(url)),
1507 base::Bind(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(), 1698 base::Bind(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(),
1508 base::Owned(url))); 1699 base::Owned(url)));
1509 } 1700 }
1510 1701
1702 void QuotaManager::DidSetTemporaryGlobalOverrideQuota(
1703 const QuotaCallback& callback,
1704 const int64_t* new_quota,
1705 bool success) {
1706 QuotaStatusCode status = kQuotaErrorInvalidAccess;
1707 DidDatabaseWork(success);
1708 if (success) {
1709 temporary_quota_override_ = *new_quota;
1710 status = kQuotaStatusOk;
1711 }
1712
1713 if (callback.is_null())
1714 return;
1715
1716 callback.Run(status, *new_quota);
1717 }
1718
1511 void QuotaManager::DidGetPersistentHostQuota(const std::string& host, 1719 void QuotaManager::DidGetPersistentHostQuota(const std::string& host,
1512 const int64_t* quota, 1720 const int64_t* quota,
1513 bool success) { 1721 bool success) {
1514 DidDatabaseWork(success); 1722 DidDatabaseWork(success);
1515 persistent_host_quota_callbacks_.Run( 1723 persistent_host_quota_callbacks_.Run(host, kQuotaStatusOk, *quota);
1516 host, kQuotaStatusOk, std::min(*quota, kPerHostPersistentQuotaLimit));
1517 } 1724 }
1518 1725
1519 void QuotaManager::DidSetPersistentHostQuota(const std::string& host, 1726 void QuotaManager::DidSetPersistentHostQuota(const std::string& host,
1520 const QuotaCallback& callback, 1727 const QuotaCallback& callback,
1521 const int64_t* new_quota, 1728 const int64_t* new_quota,
1522 bool success) { 1729 bool success) {
1523 DidDatabaseWork(success); 1730 DidDatabaseWork(success);
1524 callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota); 1731 callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota);
1525 } 1732 }
1526 1733
1734 void QuotaManager::DidInitialize(int64_t* temporary_quota_override,
1735 int64_t* desired_available_space,
1736 bool success) {
1737 temporary_quota_override_ = *temporary_quota_override;
1738 desired_available_space_ = *desired_available_space;
1739 temporary_quota_initialized_ = true;
1740 DidDatabaseWork(success);
1741
1742 if (!is_incognito_) {
1743 histogram_timer_.Start(FROM_HERE,
1744 base::TimeDelta::FromMilliseconds(
1745 kReportHistogramInterval),
1746 this, &QuotaManager::ReportHistogram);
1747 }
1748
1749 db_initialization_callbacks_.Run();
1750 GetTemporaryGlobalQuota(
1751 base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota,
1752 weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
1753 }
1754
1527 void QuotaManager::DidGetLRUOrigin(const GURL* origin, 1755 void QuotaManager::DidGetLRUOrigin(const GURL* origin,
1528 bool success) { 1756 bool success) {
1529 DidDatabaseWork(success); 1757 DidDatabaseWork(success);
1530 1758
1531 lru_origin_callback_.Run(*origin); 1759 lru_origin_callback_.Run(*origin);
1532 lru_origin_callback_.Reset(); 1760 lru_origin_callback_.Reset();
1533 } 1761 }
1534 1762
1535 namespace { 1763 void QuotaManager::DidGetInitialTemporaryGlobalQuota(
1536 void DidGetSettingsThreadAdapter(base::TaskRunner* task_runner, 1764 base::TimeTicks start_ticks,
1537 const OptionalQuotaSettingsCallback& callback, 1765 QuotaStatusCode status,
1538 base::Optional<QuotaSettings> settings) { 1766 int64_t quota_unused) {
1539 task_runner->PostTask(FROM_HERE, base::Bind(callback, std::move(settings))); 1767 UMA_HISTOGRAM_LONG_TIMES(
1540 } 1768 "Quota.TimeToInitializeGlobalQuota",
1541 } // namespace 1769 base::TimeTicks::Now() - start_ticks);
1542 1770
1543 void QuotaManager::GetQuotaSettings(const QuotaSettingsCallback& callback) { 1771 if (eviction_disabled_)
1544 if (base::TimeTicks::Now() - settings_timestamp_ <
1545 settings_.refresh_interval) {
1546 callback.Run(settings_);
1547 return;
1548 }
1549
1550 if (!settings_callbacks_.Add(callback))
1551 return; 1772 return;
1552 1773
1553 // We invoke our clients GetQuotaSettingsFunc on the 1774 std::set<GURL>* origins = new std::set<GURL>;
1554 // UI thread and plumb the resulting value back to this thread. 1775 temporary_usage_tracker_->GetCachedOrigins(origins);
1555 get_settings_task_runner_->PostTask( 1776 // This will call the StartEviction() when initial origin registration
1777 // is completed.
1778 PostTaskAndReplyWithResultForDBThread(
1556 FROM_HERE, 1779 FROM_HERE,
1557 base::Bind( 1780 base::Bind(&InitializeTemporaryOriginsInfoOnDBThread,
1558 get_settings_function_, 1781 base::Owned(origins)),
1559 base::Bind( 1782 base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo,
1560 &DidGetSettingsThreadAdapter,
1561 base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
1562 base::Bind(&QuotaManager::DidGetSettings,
1563 weak_factory_.GetWeakPtr(), base::TimeTicks::Now()))));
1564 }
1565
1566 void QuotaManager::DidGetSettings(base::TimeTicks start_ticks,
1567 base::Optional<QuotaSettings> settings) {
1568 if (!settings) {
1569 settings = settings_;
1570 settings->refresh_interval = base::TimeDelta::FromMinutes(1);
1571 }
1572 SetQuotaSettings(*settings);
1573 settings_callbacks_.Run(*settings);
1574 UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", settings->pool_size);
1575 UMA_HISTOGRAM_LONG_TIMES("Quota.TimeToGetSettings",
1576 base::TimeTicks::Now() - start_ticks);
1577 LOG_IF(WARNING, settings->pool_size == 0)
1578 << "No storage quota provided in QuotaSettings.";
1579 }
1580
1581 void QuotaManager::GetStorageCapacity(const StorageCapacityCallback& callback) {
1582 if (!storage_capacity_callbacks_.Add(callback))
1583 return;
1584 if (is_incognito_) {
1585 GetQuotaSettings(
1586 base::Bind(&QuotaManager::ContinueIncognitoGetStorageCapacity,
1587 weak_factory_.GetWeakPtr()));
1588 return;
1589 }
1590 base::PostTaskAndReplyWithResult(
1591 db_thread_.get(), FROM_HERE,
1592 base::Bind(&QuotaManager::CallGetVolumeInfo, get_volume_info_fn_,
1593 profile_path_),
1594 base::Bind(&QuotaManager::DidGetStorageCapacity,
1595 weak_factory_.GetWeakPtr())); 1783 weak_factory_.GetWeakPtr()));
1596 } 1784 }
1597 1785
1598 void QuotaManager::ContinueIncognitoGetStorageCapacity( 1786 void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) {
1599 const QuotaSettings& settings) { 1787 DidDatabaseWork(success);
1600 int64_t current_usage = 1788 if (success)
1601 GetUsageTracker(kStorageTypeTemporary)->GetCachedUsage(); 1789 StartEviction();
1602 current_usage += GetUsageTracker(kStorageTypePersistent)->GetCachedUsage();
1603 int64_t available_space =
1604 std::max(INT64_C(0), settings.pool_size - current_usage);
1605 DidGetStorageCapacity(std::make_pair(settings.pool_size, available_space));
1606 } 1790 }
1607 1791
1608 void QuotaManager::DidGetStorageCapacity( 1792 void QuotaManager::DidGetAvailableSpace(int64_t space) {
1609 const std::pair<int64_t, int64_t>& total_and_available) { 1793 // crbug.com/349708
1610 storage_capacity_callbacks_.Run(total_and_available.first, 1794 TRACE_EVENT1("io", "QuotaManager::DidGetAvailableSpace",
1611 total_and_available.second); 1795 "n_callbacks", available_space_callbacks_.size());
1796
1797 available_space_callbacks_.Run(kQuotaStatusOk, space);
1612 } 1798 }
1613 1799
1614 void QuotaManager::DidDatabaseWork(bool success) { 1800 void QuotaManager::DidDatabaseWork(bool success) {
1615 db_disabled_ = !success; 1801 db_disabled_ = !success;
1616 } 1802 }
1617 1803
1618 void QuotaManager::DeleteOnCorrectThread() const { 1804 void QuotaManager::DeleteOnCorrectThread() const {
1619 if (!io_thread_->BelongsToCurrentThread() && 1805 if (!io_thread_->BelongsToCurrentThread() &&
1620 io_thread_->DeleteSoon(FROM_HERE, this)) { 1806 io_thread_->DeleteSoon(FROM_HERE, this)) {
1621 return; 1807 return;
1622 } 1808 }
1623 delete this; 1809 delete this;
1624 } 1810 }
1625 1811
1626 void QuotaManager::PostTaskAndReplyWithResultForDBThread( 1812 void QuotaManager::PostTaskAndReplyWithResultForDBThread(
1627 const tracked_objects::Location& from_here, 1813 const tracked_objects::Location& from_here,
1628 const base::Callback<bool(QuotaDatabase*)>& task, 1814 const base::Callback<bool(QuotaDatabase*)>& task,
1629 const base::Callback<void(bool)>& reply) { 1815 const base::Callback<void(bool)>& reply) {
1630 // Deleting manager will post another task to DB thread to delete 1816 // Deleting manager will post another task to DB thread to delete
1631 // |database_|, therefore we can be sure that database_ is alive when this 1817 // |database_|, therefore we can be sure that database_ is alive when this
1632 // task runs. 1818 // task runs.
1633 base::PostTaskAndReplyWithResult( 1819 base::PostTaskAndReplyWithResult(
1634 db_thread_.get(), 1820 db_thread_.get(),
1635 from_here, 1821 from_here,
1636 base::Bind(task, base::Unretained(database_.get())), 1822 base::Bind(task, base::Unretained(database_.get())),
1637 reply); 1823 reply);
1638 } 1824 }
1639 1825
1640 // static 1826 // static
1641 std::pair<int64_t, int64_t> QuotaManager::CallGetVolumeInfo( 1827 int64_t QuotaManager::CallGetAmountOfFreeDiskSpace(
1642 GetVolumeInfoFn get_volume_info_fn, 1828 GetVolumeInfoFn get_volume_info_fn,
1643 const base::FilePath& path) { 1829 const base::FilePath& profile_path) {
1644 // crbug.com/349708 1830 // crbug.com/349708
1645 TRACE_EVENT0("io", "CallGetVolumeInfo"); 1831 TRACE_EVENT0("io", "CallSystemGetAmountOfFreeDiskSpace");
1646 if (!base::CreateDirectory(path)) { 1832 if (!base::CreateDirectory(profile_path)) {
1647 LOG(WARNING) << "Create directory failed for path" << path.value(); 1833 LOG(WARNING) << "Create directory failed for path" << profile_path.value();
1648 return std::make_pair<int64_t, int64_t>(0, 0); 1834 return 0;
1649 } 1835 }
1650 std::pair<int64_t, int64_t> total_and_available = get_volume_info_fn(path); 1836 uint64_t available, total;
1651 if (total_and_available.first < 0 || total_and_available.second < 0) { 1837 if (!get_volume_info_fn(profile_path, &available, &total)) {
1652 LOG(WARNING) << "Unable to get volume info: " << path.value(); 1838 return 0;
1653 return std::make_pair<int64_t, int64_t>(0, 0);
1654 } 1839 }
1655 UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total_and_available.first); 1840 UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available);
1656 UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", total_and_available.second); 1841 UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total);
1657 return total_and_available; 1842 return static_cast<int64_t>(available);
1658 } 1843 }
1659 1844
1660 // static 1845 //static
1661 std::pair<int64_t, int64_t> QuotaManager::GetVolumeInfo( 1846 bool QuotaManager::GetVolumeInfo(const base::FilePath& path,
1662 const base::FilePath& path) { 1847 uint64_t* available_space,
1663 return std::make_pair(base::SysInfo::AmountOfTotalDiskSpace(path), 1848 uint64_t* total_size) {
1664 base::SysInfo::AmountOfFreeDiskSpace(path)); 1849 // Inspired by similar code in the base::SysInfo class.
1850 base::ThreadRestrictions::AssertIOAllowed();
1851
1852 int64_t available = base::SysInfo::AmountOfFreeDiskSpace(path);
1853 if (available < 0)
1854 return false;
1855 int64_t total = base::SysInfo::AmountOfTotalDiskSpace(path);
1856 if (total < 0)
1857 return false;
1858
1859 *available_space = static_cast<uint64_t>(available);
1860 *total_size = static_cast<uint64_t>(total);
1861 return true;
1665 } 1862 }
1666 1863
1667 } // namespace storage 1864 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/quota/quota_manager.h ('k') | storage/browser/quota/quota_manager_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698