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