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" | |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |