| 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) \ | 41 #define UMA_HISTOGRAM_MBYTES(name, sample) \ |
| 40 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 42 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 41 (name), static_cast<int>((sample) / kMBytes), \ | 43 (name), static_cast<int>((sample) / kMBytes), \ |
| 42 1, 10 * 1024 * 1024 /* 10TB */, 100) | 44 1, 10 * 1024 * 1024 /* 10TB */, 100) |
| 43 | 45 |
| 44 namespace storage { | 46 namespace storage { |
| 45 | 47 |
| 46 namespace { | 48 namespace { |
| 47 | 49 |
| 48 const int64_t kMBytes = 1024 * 1024; | 50 const int64_t kMBytes = 1024 * 1024; |
| 49 const int kMinutesInMilliSeconds = 60 * 1000; | 51 const int kMinutesInMilliSeconds = 60 * 1000; |
| 50 | |
| 51 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour | 52 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour |
| 52 const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0; // 33% | |
| 53 | 53 |
| 54 } // namespace | 54 } // namespace |
| 55 | 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 | |
| 61 const int64_t QuotaManager::kNoLimit = INT64_MAX; | 56 const int64_t QuotaManager::kNoLimit = INT64_MAX; |
| 62 | 57 |
| 63 const int QuotaManager::kPerHostTemporaryPortion = 5; // 20% | |
| 64 | |
| 65 // Cap size for per-host persistent quota determined by the histogram. | 58 // 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 | 59 // 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 | 60 // persistent storage usage and we determined by global persistent storage |
| 68 // usage that is less than 10GB for almost all users. | 61 // usage that is less than 10GB for almost all users. |
| 69 const int64_t QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes; | 62 const int64_t QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes; |
| 70 | 63 |
| 64 // Heuristics: assuming average cloud server allows a few Gigs storage |
| 65 // on the server side and the storage needs to be shared for user data |
| 66 // and by multiple apps. |
| 67 int64_t QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; |
| 68 |
| 71 const char QuotaManager::kDatabaseName[] = "QuotaManager"; | 69 const char QuotaManager::kDatabaseName[] = "QuotaManager"; |
| 72 | 70 |
| 73 const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3; | 71 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 = | 72 const int QuotaManager::kEvictionIntervalInMilliSeconds = |
| 83 30 * kMinutesInMilliSeconds; | 73 30 * kMinutesInMilliSeconds; |
| 84 | 74 |
| 85 const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] = | 75 const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] = |
| 86 "Quota.TimeBetweenRepeatedOriginEvictions"; | 76 "Quota.TimeBetweenRepeatedOriginEvictions"; |
| 87 const char QuotaManager::kEvictedOriginAccessedCountHistogram[] = | 77 const char QuotaManager::kEvictedOriginAccessedCountHistogram[] = |
| 88 "Quota.EvictedOriginAccessCount"; | 78 "Quota.EvictedOriginAccessCount"; |
| 89 const char QuotaManager::kEvictedOriginTimeSinceAccessHistogram[] = | 79 const char QuotaManager::kEvictedOriginTimeSinceAccessHistogram[] = |
| 90 "Quota.EvictedOriginTimeSinceAccess"; | 80 "Quota.EvictedOriginTimeSinceAccess"; |
| 91 | 81 |
| 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 | |
| 97 namespace { | 82 namespace { |
| 98 | 83 |
| 99 void CountOriginType(const std::set<GURL>& origins, | 84 void CountOriginType(const std::set<GURL>& origins, |
| 100 SpecialStoragePolicy* policy, | 85 SpecialStoragePolicy* policy, |
| 101 size_t* protected_origins, | 86 size_t* protected_origins, |
| 102 size_t* unlimited_origins) { | 87 size_t* unlimited_origins) { |
| 103 DCHECK(protected_origins); | 88 DCHECK(protected_origins); |
| 104 DCHECK(unlimited_origins); | 89 DCHECK(unlimited_origins); |
| 105 *protected_origins = 0; | 90 *protected_origins = 0; |
| 106 *unlimited_origins = 0; | 91 *unlimited_origins = 0; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 } | 212 } |
| 228 | 213 |
| 229 bool UpdateModifiedTimeOnDBThread(const GURL& origin, | 214 bool UpdateModifiedTimeOnDBThread(const GURL& origin, |
| 230 StorageType type, | 215 StorageType type, |
| 231 base::Time modified_time, | 216 base::Time modified_time, |
| 232 QuotaDatabase* database) { | 217 QuotaDatabase* database) { |
| 233 DCHECK(database); | 218 DCHECK(database); |
| 234 return database->SetOriginLastModifiedTime(origin, type, modified_time); | 219 return database->SetOriginLastModifiedTime(origin, type, modified_time); |
| 235 } | 220 } |
| 236 | 221 |
| 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 | 222 } // namespace |
| 343 | 223 |
| 344 UsageAndQuota::UsageAndQuota() | 224 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: | 225 public: |
| 364 explicit UsageAndQuotaCallbackDispatcher(QuotaManager* manager) | 226 UsageAndQuotaHelper( |
| 227 QuotaManager* manager, |
| 228 const GURL& origin, |
| 229 StorageType type, |
| 230 bool is_unlimited, |
| 231 bool is_incognito, |
| 232 const UsageAndQuotaCallback& callback) |
| 365 : QuotaTask(manager), | 233 : QuotaTask(manager), |
| 366 has_usage_(false), | 234 origin_(origin), |
| 367 has_global_limited_usage_(false), | 235 type_(type), |
| 368 has_quota_(false), | 236 is_unlimited_(is_unlimited), |
| 369 has_available_disk_space_(false), | 237 is_incognito_(is_incognito), |
| 370 status_(kQuotaStatusUnknown), | 238 callback_(callback), |
| 371 usage_and_quota_(-1, -1, -1, -1), | 239 weak_factory_(this) {} |
| 372 waiting_callbacks_(1) {} | 240 |
| 373 | 241 protected: |
| 374 ~UsageAndQuotaCallbackDispatcher() override {} | 242 // Start the async process of gathering the info we need. |
| 375 | 243 void Run() override { |
| 376 void WaitForResults(const QuotaManager::UsageAndQuotaCallback& callback) { | 244 // Gather 4 pieces of info before computing an answer: |
| 377 callback_ = callback; | 245 // config, device_storage_capacity, host_usage, and host_quota. |
| 378 Start(); | 246 base::Closure barrier = base::BarrierClosure(4, |
| 379 } | 247 base::Bind(&UsageAndQuotaHelper::OnBarrierComplete, |
| 380 | 248 weak_factory_.GetWeakPtr())); |
| 381 void set_usage(int64_t usage) { | 249 |
| 382 usage_and_quota_.usage = usage; | 250 std::string host = net::GetHostOrSpecFromURL(origin_); |
| 383 has_usage_ = true; | 251 |
| 384 } | 252 manager()->GetTemporaryStorageConfig( |
| 385 | 253 base::Bind(&UsageAndQuotaHelper::OnGotConfigInfo, |
| 386 void set_global_limited_usage(int64_t global_limited_usage) { | 254 weak_factory_.GetWeakPtr(), barrier)); |
| 387 usage_and_quota_.global_limited_usage = global_limited_usage; | 255 manager()->GetDeviceStorageCapacity( |
| 388 has_global_limited_usage_ = true; | 256 base::Bind(&UsageAndQuotaHelper::OnGotCapacity, |
| 389 } | 257 weak_factory_.GetWeakPtr(), barrier)); |
| 390 | 258 manager()->GetHostUsage( |
| 391 void set_quota(int64_t quota) { | 259 host, type_, |
| 392 usage_and_quota_.quota = quota; | 260 base::Bind(&UsageAndQuotaHelper::OnGotHostUsage, |
| 393 has_quota_ = true; | 261 weak_factory_.GetWeakPtr(), barrier)); |
| 394 } | 262 |
| 395 | 263 // Determine host_quota differently depending on type. |
| 396 void set_available_disk_space(int64_t available_disk_space) { | 264 if (is_unlimited_) { |
| 397 usage_and_quota_.available_disk_space = available_disk_space; | 265 SetDesiredHostQuota(barrier, kQuotaStatusOk, |
| 398 has_available_disk_space_ = true; | 266 kNoLimit); |
| 399 } | 267 } else if (type_ == kStorageTypeSyncable) { |
| 400 | 268 SetDesiredHostQuota(barrier, kQuotaStatusOk, |
| 401 UsageCallback GetHostUsageCallback() { | 269 kSyncableStorageDefaultHostQuota); |
| 402 ++waiting_callbacks_; | 270 } else if (type_ == kStorageTypePersistent) { |
| 403 has_usage_ = true; | 271 manager()->GetPersistentHostQuota( |
| 404 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage, | 272 host, |
| 405 AsWeakPtr()); | 273 base::Bind(&UsageAndQuotaHelper::SetDesiredHostQuota, |
| 406 } | 274 weak_factory_.GetWeakPtr(), barrier)); |
| 407 | 275 } else { |
| 408 UsageCallback GetGlobalLimitedUsageCallback() { | 276 DCHECK_EQ(kStorageTypeTemporary, type_); |
| 409 ++waiting_callbacks_; | 277 // For temporary storge, OnGetConfig will set the host quota. |
| 410 has_global_limited_usage_ = true; | 278 } |
| 411 return base::Bind( | 279 } |
| 412 &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage, | 280 |
| 413 AsWeakPtr()); | 281 void Aborted() override { |
| 414 } | 282 weak_factory_.InvalidateWeakPtrs(); |
| 415 | 283 callback_.Run(kQuotaErrorAbort, 0, 0); |
| 416 QuotaCallback GetQuotaCallback() { | 284 DeleteSoon(); |
| 417 ++waiting_callbacks_; | 285 } |
| 418 has_quota_ = true; | 286 |
| 419 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota, | 287 void Completed() override { |
| 420 AsWeakPtr()); | 288 weak_factory_.InvalidateWeakPtrs(); |
| 421 } | 289 // Constrain the desired |host_quota| to something that fits. |
| 422 | 290 // If available space is too low, cap usage at current levels. |
| 423 QuotaCallback GetAvailableSpaceCallback() { | 291 // If it's close to being too low, cap growth to avoid it getting too low. |
| 424 ++waiting_callbacks_; | 292 int64_t host_quota = std::min( |
| 425 has_available_disk_space_ = true; | 293 desired_host_quota_, |
| 426 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace, | 294 host_usage_ + |
| 427 AsWeakPtr()); | 295 std::max(INT64_C(0), |
| 296 available_space_ - config_.must_remain_available)); |
| 297 callback_.Run(kQuotaStatusOk, host_usage_, host_quota); |
| 298 if (type_ == kStorageTypeTemporary && !is_incognito_ && !is_unlimited_) |
| 299 UMA_HISTOGRAM_MBYTES("Quota.QuotaForOrigin", host_quota); |
| 300 DeleteSoon(); |
| 428 } | 301 } |
| 429 | 302 |
| 430 private: | 303 private: |
| 431 void DidGetHostUsage(int64_t usage) { | 304 QuotaManager* manager() const { |
| 432 if (status_ == kQuotaStatusUnknown) | 305 return static_cast<QuotaManager*>(observer()); |
| 433 status_ = kQuotaStatusOk; | 306 } |
| 434 usage_and_quota_.usage = usage; | 307 |
| 435 CheckCompleted(); | 308 void OnGotConfigInfo(const base::Closure& barrier_closure, |
| 436 } | 309 const TemporaryStorageConfiguration& config) { |
| 437 | 310 config_ = config; |
| 438 void DidGetGlobalLimitedUsage(int64_t limited_usage) { | 311 barrier_closure.Run(); |
| 439 if (status_ == kQuotaStatusUnknown) | 312 if (type_ == kStorageTypeTemporary && !is_unlimited_) { |
| 440 status_ = kQuotaStatusOk; | 313 SetDesiredHostQuota(barrier_closure, kQuotaStatusOk, |
| 441 usage_and_quota_.global_limited_usage = limited_usage; | 314 config.per_host_quota); |
| 442 CheckCompleted(); | 315 } |
| 443 } | 316 } |
| 444 | 317 |
| 445 void DidGetQuota(QuotaStatusCode status, int64_t quota) { | 318 void OnGotCapacity(const base::Closure& barrier_closure, |
| 446 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) | 319 int64_t total_space, int64_t available_space) { |
| 447 status_ = status; | 320 total_space_ = total_space; |
| 448 usage_and_quota_.quota = quota; | 321 available_space_ = available_space; |
| 449 CheckCompleted(); | 322 barrier_closure.Run(); |
| 450 } | 323 } |
| 451 | 324 |
| 452 void DidGetAvailableSpace(QuotaStatusCode status, int64_t space) { | 325 void OnGotHostUsage(const base::Closure& barrier_closure, int64_t usage) { |
| 453 // crbug.com/349708 | 326 host_usage_ = usage; |
| 454 TRACE_EVENT0( | 327 barrier_closure.Run(); |
| 455 "io", "UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace"); | 328 } |
| 456 | 329 |
| 457 DCHECK_GE(space, 0); | 330 void SetDesiredHostQuota(const base::Closure& barrier_closure, |
| 458 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) | 331 QuotaStatusCode status, int64_t quota) { |
| 459 status_ = status; | 332 desired_host_quota_ = quota; |
| 460 usage_and_quota_.available_disk_space = space; | 333 barrier_closure.Run(); |
| 461 CheckCompleted(); | 334 } |
| 462 } | 335 |
| 463 | 336 void OnBarrierComplete() { |
| 337 CallCompleted(); |
| 338 } |
| 339 |
| 340 GURL origin_; |
| 341 QuotaManager::UsageAndQuotaCallback callback_; |
| 342 StorageType type_; |
| 343 bool is_unlimited_; |
| 344 bool is_incognito_; |
| 345 int64_t available_space_ = 0; |
| 346 int64_t total_space_ = 0; |
| 347 int64_t desired_host_quota_ = 0; |
| 348 int64_t host_usage_ = 0; |
| 349 TemporaryStorageConfiguration config_; |
| 350 base::WeakPtrFactory<UsageAndQuotaHelper> weak_factory_; |
| 351 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaHelper); |
| 352 }; |
| 353 |
| 354 // Helper to asychronously gather information needed at the start of an |
| 355 // eviction round. |
| 356 class QuotaManager::EvictionRoundInfoHelper : public QuotaTask { |
| 357 public: |
| 358 EvictionRoundInfoHelper( |
| 359 QuotaManager* manager, |
| 360 const EvictionRoundInfoCallback& callback) |
| 361 : QuotaTask(manager), |
| 362 callback_(callback), |
| 363 weak_factory_(this) {} |
| 364 |
| 365 protected: |
| 464 void Run() override { | 366 void Run() override { |
| 465 // We initialize waiting_callbacks to 1 so that we won't run | 367 // Gather 2 pieces of info before deciding if we need to get GlobalUsage: |
| 466 // the completion callback until here even some of the callbacks | 368 // config, device_storage_capacity. |
| 467 // are dispatched synchronously. | 369 base::Closure barrier = base::BarrierClosure(2, |
| 468 CheckCompleted(); | 370 base::Bind(&EvictionRoundInfoHelper::OnBarrierComplete, |
| 371 weak_factory_.GetWeakPtr())); |
| 372 |
| 373 manager()->GetTemporaryStorageConfig( |
| 374 base::Bind(&EvictionRoundInfoHelper::OnGotConfigInfo, |
| 375 weak_factory_.GetWeakPtr(), barrier)); |
| 376 manager()->GetDeviceStorageCapacity( |
| 377 base::Bind(&EvictionRoundInfoHelper::OnGotCapacity, |
| 378 weak_factory_.GetWeakPtr(), barrier)); |
| 469 } | 379 } |
| 470 | 380 |
| 471 void Aborted() override { | 381 void Aborted() override { |
| 472 callback_.Run(kQuotaErrorAbort, UsageAndQuota()); | 382 weak_factory_.InvalidateWeakPtrs(); |
| 383 callback_.Run( |
| 384 kQuotaErrorAbort, TemporaryStorageConfiguration(), 0, 0, 0, false); |
| 473 DeleteSoon(); | 385 DeleteSoon(); |
| 474 } | 386 } |
| 475 | 387 |
| 476 void Completed() override { | 388 void Completed() override { |
| 477 // crbug.com/349708 | 389 weak_factory_.InvalidateWeakPtrs(); |
| 478 TRACE_EVENT0("io", "UsageAndQuotaCallbackDispatcher::Completed"); | 390 callback_.Run( |
| 479 | 391 kQuotaStatusOk, config_, available_space_, total_space_, |
| 480 DCHECK(!has_usage_ || usage_and_quota_.usage >= 0); | 392 global_usage_, global_usage_is_complete_); |
| 481 DCHECK(!has_global_limited_usage_ || | 393 DeleteSoon(); |
| 482 usage_and_quota_.global_limited_usage >= 0); | 394 } |
| 483 DCHECK(!has_quota_ || usage_and_quota_.quota >= 0); | 395 |
| 484 DCHECK(!has_available_disk_space_ || | 396 private: |
| 485 usage_and_quota_.available_disk_space >= 0); | 397 QuotaManager* manager() const { |
| 486 | 398 return static_cast<QuotaManager*>(observer()); |
| 487 callback_.Run(status_, usage_and_quota_); | 399 } |
| 488 DeleteSoon(); | 400 |
| 489 } | 401 void OnGotConfigInfo(const base::Closure& barrier_closure, |
| 490 | 402 const TemporaryStorageConfiguration& config) { |
| 491 void CheckCompleted() { | 403 config_ = config; |
| 492 if (--waiting_callbacks_ <= 0) | 404 barrier_closure.Run(); |
| 405 } |
| 406 |
| 407 void OnGotCapacity(const base::Closure& barrier_closure, |
| 408 int64_t total_space, int64_t available_space) { |
| 409 total_space_ = total_space; |
| 410 available_space_ = available_space; |
| 411 barrier_closure.Run(); |
| 412 } |
| 413 |
| 414 void OnBarrierComplete() { |
| 415 // Avoid computing the full current_usage when there's no pressure. |
| 416 int64_t consumed_space = total_space_ - available_space_; |
| 417 if (consumed_space < config_.pool_size && |
| 418 available_space_ > config_.must_remain_available) { |
| 419 DCHECK(!global_usage_is_complete_); |
| 420 global_usage_ = |
| 421 manager()->GetUsageTracker(kStorageTypeTemporary)->GetCachedUsage(); |
| 493 CallCompleted(); | 422 CallCompleted(); |
| 494 } | 423 return; |
| 495 | 424 } |
| 496 // For sanity checks, they're checked only when DCHECK is on. | 425 manager()->GetGlobalUsage( |
| 497 bool has_usage_; | 426 kStorageTypeTemporary, |
| 498 bool has_global_limited_usage_; | 427 base::Bind( |
| 499 bool has_quota_; | 428 &EvictionRoundInfoHelper::OnGotGlobalUsage, |
| 500 bool has_available_disk_space_; | 429 weak_factory_.GetWeakPtr())); |
| 501 | 430 } |
| 502 QuotaStatusCode status_; | 431 |
| 503 UsageAndQuota usage_and_quota_; | 432 void OnGotGlobalUsage(int64_t usage, int64_t unlimited_usage) { |
| 504 QuotaManager::UsageAndQuotaCallback callback_; | 433 global_usage_ = std::max(INT64_C(0), usage - unlimited_usage); |
| 505 int waiting_callbacks_; | 434 global_usage_is_complete_ = true; |
| 506 | 435 CallCompleted(); |
| 507 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher); | 436 } |
| 437 |
| 438 EvictionRoundInfoCallback callback_; |
| 439 TemporaryStorageConfiguration config_; |
| 440 int64_t available_space_ = 0; |
| 441 int64_t total_space_ = 0; |
| 442 int64_t global_usage_ = 0; |
| 443 bool global_usage_is_complete_ = false; |
| 444 base::WeakPtrFactory<EvictionRoundInfoHelper> weak_factory_; |
| 445 DISALLOW_COPY_AND_ASSIGN(EvictionRoundInfoHelper); |
| 508 }; | 446 }; |
| 509 | 447 |
| 510 class QuotaManager::GetUsageInfoTask : public QuotaTask { | 448 class QuotaManager::GetUsageInfoTask : public QuotaTask { |
| 511 public: | 449 public: |
| 512 GetUsageInfoTask( | 450 GetUsageInfoTask( |
| 513 QuotaManager* manager, | 451 QuotaManager* manager, |
| 514 const GetUsageInfoCallback& callback) | 452 const GetUsageInfoCallback& callback) |
| 515 : QuotaTask(manager), | 453 : QuotaTask(manager), |
| 516 callback_(callback), | 454 callback_(callback), |
| 517 weak_factory_(this) { | 455 weak_factory_(this) { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 OriginInfoTableEntries entries_; | 797 OriginInfoTableEntries entries_; |
| 860 }; | 798 }; |
| 861 | 799 |
| 862 // QuotaManager --------------------------------------------------------------- | 800 // QuotaManager --------------------------------------------------------------- |
| 863 | 801 |
| 864 QuotaManager::QuotaManager( | 802 QuotaManager::QuotaManager( |
| 865 bool is_incognito, | 803 bool is_incognito, |
| 866 const base::FilePath& profile_path, | 804 const base::FilePath& profile_path, |
| 867 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, | 805 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, |
| 868 const scoped_refptr<base::SequencedTaskRunner>& db_thread, | 806 const scoped_refptr<base::SequencedTaskRunner>& db_thread, |
| 869 const scoped_refptr<SpecialStoragePolicy>& special_storage_policy) | 807 const scoped_refptr<SpecialStoragePolicy>& special_storage_policy, |
| 808 const GetTemporaryStorageConfigurationFunc& get_config_function) |
| 870 : is_incognito_(is_incognito), | 809 : is_incognito_(is_incognito), |
| 871 profile_path_(profile_path), | 810 profile_path_(profile_path), |
| 872 proxy_(new QuotaManagerProxy(this, io_thread)), | 811 proxy_(new QuotaManagerProxy(this, io_thread)), |
| 873 db_disabled_(false), | 812 db_disabled_(false), |
| 874 eviction_disabled_(false), | 813 eviction_disabled_(false), |
| 814 get_config_function_(get_config_function), |
| 875 io_thread_(io_thread), | 815 io_thread_(io_thread), |
| 876 db_thread_(db_thread), | 816 db_thread_(db_thread), |
| 877 is_getting_eviction_origin_(false), | 817 is_getting_eviction_origin_(false), |
| 878 temporary_quota_initialized_(false), | |
| 879 temporary_quota_override_(-1), | |
| 880 special_storage_policy_(special_storage_policy), | 818 special_storage_policy_(special_storage_policy), |
| 881 get_volume_info_fn_(&QuotaManager::GetVolumeInfo), | 819 get_volume_info_fn_(&QuotaManager::GetVolumeInfo), |
| 882 storage_monitor_(new StorageMonitor(this)), | 820 storage_monitor_(new StorageMonitor(this)), |
| 883 weak_factory_(this) {} | 821 weak_factory_(this) { |
| 822 DCHECK_EQ(storage_config_.refresh_interval, base::TimeDelta::Max()); |
| 823 if (!get_config_function.is_null()) { |
| 824 // Reset the interval to ensure we use the get_config_function |
| 825 // the first times storage_config_ is needed. |
| 826 storage_config_.refresh_interval = base::TimeDelta(); |
| 827 get_config_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 828 } |
| 829 } |
| 830 |
| 831 void QuotaManager::SetTemporaryStorageConfiguration( |
| 832 const TemporaryStorageConfiguration& config) { |
| 833 storage_config_ = config; |
| 834 storage_config_timestamp_ = base::TimeTicks::Now(); |
| 835 } |
| 884 | 836 |
| 885 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) { | 837 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) { |
| 886 LazyInitialize(); | 838 LazyInitialize(); |
| 887 GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback); | 839 GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback); |
| 888 get_usage_info->Start(); | 840 get_usage_info->Start(); |
| 889 } | 841 } |
| 890 | 842 |
| 891 void QuotaManager::GetUsageAndQuotaForWebApps( | 843 void QuotaManager::GetUsageAndQuotaForWebApps( |
| 892 const GURL& origin, | 844 const GURL& origin, |
| 893 StorageType type, | 845 StorageType type, |
| 894 const GetUsageAndQuotaCallback& callback) { | 846 const UsageAndQuotaCallback& callback) { |
| 895 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed. | 847 DCHECK(origin == origin.GetOrigin()); |
| 896 tracked_objects::ScopedTracker tracking_profile( | |
| 897 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 898 "477117 QuotaManager::GetUsageAndQuotaForWebApps")); | |
| 899 if (type != kStorageTypeTemporary && | 848 if (type != kStorageTypeTemporary && |
| 900 type != kStorageTypePersistent && | 849 type != kStorageTypePersistent && |
| 901 type != kStorageTypeSyncable) { | 850 type != kStorageTypeSyncable) { |
| 902 callback.Run(kQuotaErrorNotSupported, 0, 0); | 851 callback.Run(kQuotaErrorNotSupported, 0, 0); |
| 903 return; | 852 return; |
| 904 } | 853 } |
| 905 | 854 if (is_incognito_ && type != kStorageTypeTemporary) { |
| 906 DCHECK(origin == origin.GetOrigin()); | 855 callback.Run(kQuotaErrorNotSupported, 0, 0); |
| 856 return; |
| 857 } |
| 907 LazyInitialize(); | 858 LazyInitialize(); |
| 908 | 859 UsageAndQuotaHelper* helper = new UsageAndQuotaHelper( |
| 909 bool unlimited = IsStorageUnlimited(origin, type); | 860 this, origin, type, IsStorageUnlimited(origin, type), |
| 910 bool can_query_disk_size = CanQueryDiskSize(origin); | 861 is_incognito_, callback); |
| 911 | 862 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 } | 863 } |
| 942 | 864 |
| 943 void QuotaManager::GetUsageAndQuota( | 865 void QuotaManager::GetUsageAndQuota( |
| 944 const GURL& origin, StorageType type, | 866 const GURL& origin, StorageType type, |
| 945 const GetUsageAndQuotaCallback& callback) { | 867 const UsageAndQuotaCallback& callback) { |
| 946 DCHECK(origin == origin.GetOrigin()); | 868 DCHECK(origin == origin.GetOrigin()); |
| 947 | 869 |
| 948 if (IsStorageUnlimited(origin, type)) { | 870 if (IsStorageUnlimited(origin, type)) { |
| 871 // TODO: This seems like a non-obvious odd behavior. |
| 949 callback.Run(kQuotaStatusOk, 0, kNoLimit); | 872 callback.Run(kQuotaStatusOk, 0, kNoLimit); |
| 950 return; | 873 return; |
| 951 } | 874 } |
| 952 | 875 |
| 953 GetUsageAndQuotaForWebApps(origin, type, callback); | 876 GetUsageAndQuotaForWebApps(origin, type, callback); |
| 954 } | 877 } |
| 955 | 878 |
| 956 void QuotaManager::NotifyStorageAccessed( | 879 void QuotaManager::NotifyStorageAccessed( |
| 957 QuotaClient::ID client_id, | 880 QuotaClient::ID client_id, |
| 958 const GURL& origin, StorageType type) { | 881 const GURL& origin, StorageType type) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 if (host.empty() || clients_.empty()) { | 935 if (host.empty() || clients_.empty()) { |
| 1013 callback.Run(kQuotaStatusOk); | 936 callback.Run(kQuotaStatusOk); |
| 1014 return; | 937 return; |
| 1015 } | 938 } |
| 1016 | 939 |
| 1017 HostDataDeleter* deleter = | 940 HostDataDeleter* deleter = |
| 1018 new HostDataDeleter(this, host, type, quota_client_mask, callback); | 941 new HostDataDeleter(this, host, type, quota_client_mask, callback); |
| 1019 deleter->Start(); | 942 deleter->Start(); |
| 1020 } | 943 } |
| 1021 | 944 |
| 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, | 945 void QuotaManager::GetPersistentHostQuota(const std::string& host, |
| 1089 const QuotaCallback& callback) { | 946 const QuotaCallback& callback) { |
| 1090 LazyInitialize(); | 947 LazyInitialize(); |
| 1091 if (host.empty()) { | 948 if (host.empty()) { |
| 1092 // This could happen if we are called on file:///. | 949 // This could happen if we are called on file:///. |
| 1093 // TODO(kinuko) We may want to respect --allow-file-access-from-files | 950 // TODO(kinuko) We may want to respect --allow-file-access-from-files |
| 1094 // command line switch. | 951 // command line switch. |
| 1095 callback.Run(kQuotaStatusOk, 0); | 952 callback.Run(kQuotaStatusOk, 0); |
| 1096 return; | 953 return; |
| 1097 } | 954 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1119 // This could happen if we are called on file:///. | 976 // This could happen if we are called on file:///. |
| 1120 callback.Run(kQuotaErrorNotSupported, 0); | 977 callback.Run(kQuotaErrorNotSupported, 0); |
| 1121 return; | 978 return; |
| 1122 } | 979 } |
| 1123 | 980 |
| 1124 if (new_quota < 0) { | 981 if (new_quota < 0) { |
| 1125 callback.Run(kQuotaErrorInvalidModification, -1); | 982 callback.Run(kQuotaErrorInvalidModification, -1); |
| 1126 return; | 983 return; |
| 1127 } | 984 } |
| 1128 | 985 |
| 1129 if (kPerHostPersistentQuotaLimit < new_quota) { | 986 // Cap the requested size at the per-host quota limit. |
| 1130 // Cap the requested size at the per-host quota limit. | 987 new_quota = std::min(new_quota, kPerHostPersistentQuotaLimit); |
| 1131 new_quota = kPerHostPersistentQuotaLimit; | |
| 1132 } | |
| 1133 | 988 |
| 1134 if (db_disabled_) { | 989 if (db_disabled_) { |
| 1135 callback.Run(kQuotaErrorInvalidAccess, -1); | 990 callback.Run(kQuotaErrorInvalidAccess, -1); |
| 1136 return; | 991 return; |
| 1137 } | 992 } |
| 1138 | 993 |
| 1139 int64_t* new_quota_ptr = new int64_t(new_quota); | 994 int64_t* new_quota_ptr = new int64_t(new_quota); |
| 1140 PostTaskAndReplyWithResultForDBThread( | 995 PostTaskAndReplyWithResultForDBThread( |
| 1141 FROM_HERE, | 996 FROM_HERE, |
| 1142 base::Bind(&SetPersistentHostQuotaOnDBThread, | 997 base::Bind(&SetPersistentHostQuotaOnDBThread, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1178 } | 1033 } |
| 1179 tracker->GetHostUsage(host, callback); | 1034 tracker->GetHostUsage(host, callback); |
| 1180 } | 1035 } |
| 1181 | 1036 |
| 1182 bool QuotaManager::IsTrackingHostUsage(StorageType type, | 1037 bool QuotaManager::IsTrackingHostUsage(StorageType type, |
| 1183 QuotaClient::ID client_id) const { | 1038 QuotaClient::ID client_id) const { |
| 1184 UsageTracker* tracker = GetUsageTracker(type); | 1039 UsageTracker* tracker = GetUsageTracker(type); |
| 1185 return tracker && tracker->GetClientTracker(client_id); | 1040 return tracker && tracker->GetClientTracker(client_id); |
| 1186 } | 1041 } |
| 1187 | 1042 |
| 1188 void QuotaManager::GetStatistics( | 1043 void QuotaManager::GetStatistics( // GetEvictionStatistics |
| 1189 std::map<std::string, std::string>* statistics) { | 1044 std::map<std::string, std::string>* statistics) { |
| 1190 DCHECK(statistics); | 1045 DCHECK(statistics); |
| 1191 if (temporary_storage_evictor_) { | 1046 if (temporary_storage_evictor_) { |
| 1192 std::map<std::string, int64_t> stats; | 1047 std::map<std::string, int64_t> stats; |
| 1193 temporary_storage_evictor_->GetStatistics(&stats); | 1048 temporary_storage_evictor_->GetStatistics(&stats); |
| 1194 for (std::map<std::string, int64_t>::iterator p = stats.begin(); | 1049 for (std::map<std::string, int64_t>::iterator p = stats.begin(); |
| 1195 p != stats.end(); ++p) { | 1050 p != stats.end(); ++p) { |
| 1196 (*statistics)[p->first] = base::Int64ToString(p->second); | 1051 (*statistics)[p->first] = base::Int64ToString(p->second); |
| 1197 } | 1052 } |
| 1198 } | 1053 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1282 QuotaManager::EvictionContext::EvictionContext() | 1137 QuotaManager::EvictionContext::EvictionContext() |
| 1283 : evicted_type(kStorageTypeUnknown) { | 1138 : evicted_type(kStorageTypeUnknown) { |
| 1284 } | 1139 } |
| 1285 | 1140 |
| 1286 QuotaManager::EvictionContext::~EvictionContext() { | 1141 QuotaManager::EvictionContext::~EvictionContext() { |
| 1287 } | 1142 } |
| 1288 | 1143 |
| 1289 void QuotaManager::LazyInitialize() { | 1144 void QuotaManager::LazyInitialize() { |
| 1290 DCHECK(io_thread_->BelongsToCurrentThread()); | 1145 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1291 if (database_) { | 1146 if (database_) { |
| 1292 // Initialization seems to be done already. | 1147 // Already initialized. |
| 1293 return; | 1148 return; |
| 1294 } | 1149 } |
| 1295 | 1150 |
| 1296 // Use an empty path to open an in-memory only databse for incognito. | 1151 // Use an empty path to open an in-memory only databse for incognito. |
| 1297 database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : | 1152 database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : |
| 1298 profile_path_.AppendASCII(kDatabaseName))); | 1153 profile_path_.AppendASCII(kDatabaseName))); |
| 1299 | 1154 |
| 1300 temporary_usage_tracker_.reset(new UsageTracker( | 1155 temporary_usage_tracker_.reset(new UsageTracker( |
| 1301 clients_, kStorageTypeTemporary, special_storage_policy_.get(), | 1156 clients_, kStorageTypeTemporary, special_storage_policy_.get(), |
| 1302 storage_monitor_.get())); | 1157 storage_monitor_.get())); |
| 1303 persistent_usage_tracker_.reset(new UsageTracker( | 1158 persistent_usage_tracker_.reset(new UsageTracker( |
| 1304 clients_, kStorageTypePersistent, special_storage_policy_.get(), | 1159 clients_, kStorageTypePersistent, special_storage_policy_.get(), |
| 1305 storage_monitor_.get())); | 1160 storage_monitor_.get())); |
| 1306 syncable_usage_tracker_.reset(new UsageTracker( | 1161 syncable_usage_tracker_.reset(new UsageTracker( |
| 1307 clients_, kStorageTypeSyncable, special_storage_policy_.get(), | 1162 clients_, kStorageTypeSyncable, special_storage_policy_.get(), |
| 1308 storage_monitor_.get())); | 1163 storage_monitor_.get())); |
| 1309 | 1164 |
| 1310 int64_t* temporary_quota_override = new int64_t(-1); | 1165 if (!is_incognito_) { |
| 1311 int64_t* desired_available_space = new int64_t(-1); | 1166 histogram_timer_.Start( |
| 1312 PostTaskAndReplyWithResultForDBThread( | 1167 FROM_HERE, |
| 1313 FROM_HERE, | 1168 base::TimeDelta::FromMilliseconds(kReportHistogramInterval), |
| 1314 base::Bind(&InitializeOnDBThread, | 1169 this, &QuotaManager::ReportHistogram); |
| 1315 base::Unretained(temporary_quota_override), | 1170 } |
| 1316 base::Unretained(desired_available_space)), | 1171 |
| 1317 base::Bind(&QuotaManager::DidInitialize, | 1172 //// TODO??? |
| 1318 weak_factory_.GetWeakPtr(), | 1173 //std::set<GURL>* origins = new std::set<GURL>; |
| 1319 base::Owned(temporary_quota_override), | 1174 //temporary_usage_tracker_->GetCachedOrigins(origins); |
| 1320 base::Owned(desired_available_space))); | 1175 //// This will call the StartEviction() when initial origin registration |
| 1176 //// is completed. |
| 1177 //PostTaskAndReplyWithResultForDBThread( |
| 1178 // FROM_HERE, |
| 1179 // base::Bind(&InitializeTemporaryOriginsInfoOnDBThread, |
| 1180 // base::Owned(origins)), |
| 1181 // base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo, |
| 1182 // weak_factory_.GetWeakPtr())); |
| 1321 } | 1183 } |
| 1322 | 1184 |
| 1323 void QuotaManager::RegisterClient(QuotaClient* client) { | 1185 void QuotaManager::RegisterClient(QuotaClient* client) { |
| 1324 DCHECK(!database_.get()); | 1186 DCHECK(!database_.get()); |
| 1325 clients_.push_back(client); | 1187 clients_.push_back(client); |
| 1326 } | 1188 } |
| 1327 | 1189 |
| 1328 UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { | 1190 UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { |
| 1329 switch (type) { | 1191 switch (type) { |
| 1330 case kStorageTypeTemporary: | 1192 case kStorageTypeTemporary: |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable, | 1269 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable, |
| 1408 base::Owned(helper), | 1270 base::Owned(helper), |
| 1409 weak_factory_.GetWeakPtr(), | 1271 weak_factory_.GetWeakPtr(), |
| 1410 callback)); | 1272 callback)); |
| 1411 } | 1273 } |
| 1412 | 1274 |
| 1413 void QuotaManager::StartEviction() { | 1275 void QuotaManager::StartEviction() { |
| 1414 DCHECK(!temporary_storage_evictor_.get()); | 1276 DCHECK(!temporary_storage_evictor_.get()); |
| 1415 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( | 1277 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( |
| 1416 this, kEvictionIntervalInMilliSeconds)); | 1278 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(); | 1279 temporary_storage_evictor_->Start(); |
| 1421 } | 1280 } |
| 1422 | 1281 |
| 1423 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin, | 1282 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin, |
| 1424 StorageType type, | 1283 StorageType type, |
| 1425 bool is_eviction) { | 1284 bool is_eviction) { |
| 1426 LazyInitialize(); | 1285 LazyInitialize(); |
| 1427 if (db_disabled_) | 1286 if (db_disabled_) |
| 1428 return; | 1287 return; |
| 1429 | 1288 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 | 1473 |
| 1615 return; | 1474 return; |
| 1616 } | 1475 } |
| 1617 | 1476 |
| 1618 // TODO(calamity): convert LRU origin retrieval into a QuotaEvictionPolicy. | 1477 // TODO(calamity): convert LRU origin retrieval into a QuotaEvictionPolicy. |
| 1619 GetLRUOrigin(type, did_get_origin_callback); | 1478 GetLRUOrigin(type, did_get_origin_callback); |
| 1620 } | 1479 } |
| 1621 | 1480 |
| 1622 void QuotaManager::EvictOriginData(const GURL& origin, | 1481 void QuotaManager::EvictOriginData(const GURL& origin, |
| 1623 StorageType type, | 1482 StorageType type, |
| 1624 const EvictOriginDataCallback& callback) { | 1483 const StatusCallback& callback) { |
| 1625 DCHECK(io_thread_->BelongsToCurrentThread()); | 1484 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1626 DCHECK_EQ(type, kStorageTypeTemporary); | 1485 DCHECK_EQ(type, kStorageTypeTemporary); |
| 1627 | 1486 |
| 1628 eviction_context_.evicted_origin = origin; | 1487 eviction_context_.evicted_origin = origin; |
| 1629 eviction_context_.evicted_type = type; | 1488 eviction_context_.evicted_type = type; |
| 1630 eviction_context_.evict_origin_data_callback = callback; | 1489 eviction_context_.evict_origin_data_callback = callback; |
| 1631 | 1490 |
| 1632 DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true, | 1491 DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true, |
| 1633 base::Bind(&QuotaManager::DidOriginDataEvicted, | 1492 base::Bind(&QuotaManager::DidOriginDataEvicted, |
| 1634 weak_factory_.GetWeakPtr())); | 1493 weak_factory_.GetWeakPtr())); |
| 1635 } | 1494 } |
| 1636 | 1495 |
| 1637 void QuotaManager::GetUsageAndQuotaForEviction( | 1496 void QuotaManager::GetEvictionRoundInfo( |
| 1638 const UsageAndQuotaCallback& callback) { | 1497 const EvictionRoundInfoCallback& callback) { |
| 1639 // crbug.com/349708 | |
| 1640 TRACE_EVENT0("io", "QuotaManager::GetUsageAndQuotaForEviction"); | |
| 1641 | |
| 1642 DCHECK(io_thread_->BelongsToCurrentThread()); | 1498 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1643 LazyInitialize(); | 1499 LazyInitialize(); |
| 1644 | 1500 EvictionRoundInfoHelper* helper = |
| 1645 UsageAndQuotaCallbackDispatcher* dispatcher = | 1501 new EvictionRoundInfoHelper(this, callback); |
| 1646 new UsageAndQuotaCallbackDispatcher(this); | 1502 helper->Start(); |
| 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 } | 1503 } |
| 1679 | 1504 |
| 1680 void QuotaManager::GetLRUOrigin(StorageType type, | 1505 void QuotaManager::GetLRUOrigin(StorageType type, |
| 1681 const GetOriginCallback& callback) { | 1506 const GetOriginCallback& callback) { |
| 1682 LazyInitialize(); | 1507 LazyInitialize(); |
| 1683 // This must not be called while there's an in-flight task. | 1508 // This must not be called while there's an in-flight task. |
| 1684 DCHECK(lru_origin_callback_.is_null()); | 1509 DCHECK(lru_origin_callback_.is_null()); |
| 1685 lru_origin_callback_ = callback; | 1510 lru_origin_callback_ = callback; |
| 1686 if (db_disabled_) { | 1511 if (db_disabled_) { |
| 1687 lru_origin_callback_.Run(GURL()); | 1512 lru_origin_callback_.Run(GURL()); |
| 1688 lru_origin_callback_.Reset(); | 1513 lru_origin_callback_.Reset(); |
| 1689 return; | 1514 return; |
| 1690 } | 1515 } |
| 1691 | 1516 |
| 1692 GURL* url = new GURL; | 1517 GURL* url = new GURL; |
| 1693 PostTaskAndReplyWithResultForDBThread( | 1518 PostTaskAndReplyWithResultForDBThread( |
| 1694 FROM_HERE, base::Bind(&GetLRUOriginOnDBThread, type, | 1519 FROM_HERE, base::Bind(&GetLRUOriginOnDBThread, type, |
| 1695 GetEvictionOriginExceptions(std::set<GURL>()), | 1520 GetEvictionOriginExceptions(std::set<GURL>()), |
| 1696 base::RetainedRef(special_storage_policy_), | 1521 base::RetainedRef(special_storage_policy_), |
| 1697 base::Unretained(url)), | 1522 base::Unretained(url)), |
| 1698 base::Bind(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(), | 1523 base::Bind(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(), |
| 1699 base::Owned(url))); | 1524 base::Owned(url))); |
| 1700 } | 1525 } |
| 1701 | 1526 |
| 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, | 1527 void QuotaManager::DidGetPersistentHostQuota(const std::string& host, |
| 1720 const int64_t* quota, | 1528 const int64_t* quota, |
| 1721 bool success) { | 1529 bool success) { |
| 1722 DidDatabaseWork(success); | 1530 DidDatabaseWork(success); |
| 1723 persistent_host_quota_callbacks_.Run(host, kQuotaStatusOk, *quota); | 1531 persistent_host_quota_callbacks_.Run( |
| 1532 host, kQuotaStatusOk, |
| 1533 std::min(*quota, kPerHostPersistentQuotaLimit)); |
| 1724 } | 1534 } |
| 1725 | 1535 |
| 1726 void QuotaManager::DidSetPersistentHostQuota(const std::string& host, | 1536 void QuotaManager::DidSetPersistentHostQuota(const std::string& host, |
| 1727 const QuotaCallback& callback, | 1537 const QuotaCallback& callback, |
| 1728 const int64_t* new_quota, | 1538 const int64_t* new_quota, |
| 1729 bool success) { | 1539 bool success) { |
| 1730 DidDatabaseWork(success); | 1540 DidDatabaseWork(success); |
| 1731 callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota); | 1541 callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota); |
| 1732 } | 1542 } |
| 1733 | 1543 |
| 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, | 1544 void QuotaManager::DidGetLRUOrigin(const GURL* origin, |
| 1756 bool success) { | 1545 bool success) { |
| 1757 DidDatabaseWork(success); | 1546 DidDatabaseWork(success); |
| 1758 | 1547 |
| 1759 lru_origin_callback_.Run(*origin); | 1548 lru_origin_callback_.Run(*origin); |
| 1760 lru_origin_callback_.Reset(); | 1549 lru_origin_callback_.Reset(); |
| 1761 } | 1550 } |
| 1762 | 1551 |
| 1763 void QuotaManager::DidGetInitialTemporaryGlobalQuota( | |
| 1764 base::TimeTicks start_ticks, | |
| 1765 QuotaStatusCode status, | |
| 1766 int64_t quota_unused) { | |
| 1767 UMA_HISTOGRAM_LONG_TIMES( | |
| 1768 "Quota.TimeToInitializeGlobalQuota", | |
| 1769 base::TimeTicks::Now() - start_ticks); | |
| 1770 | |
| 1771 if (eviction_disabled_) | |
| 1772 return; | |
| 1773 | |
| 1774 std::set<GURL>* origins = new std::set<GURL>; | |
| 1775 temporary_usage_tracker_->GetCachedOrigins(origins); | |
| 1776 // This will call the StartEviction() when initial origin registration | |
| 1777 // is completed. | |
| 1778 PostTaskAndReplyWithResultForDBThread( | |
| 1779 FROM_HERE, | |
| 1780 base::Bind(&InitializeTemporaryOriginsInfoOnDBThread, | |
| 1781 base::Owned(origins)), | |
| 1782 base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo, | |
| 1783 weak_factory_.GetWeakPtr())); | |
| 1784 } | |
| 1785 | |
| 1786 void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) { | 1552 void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) { |
| 1787 DidDatabaseWork(success); | 1553 DidDatabaseWork(success); |
| 1788 if (success) | 1554 if (success) |
| 1789 StartEviction(); | 1555 StartEviction(); |
| 1790 } | 1556 } |
| 1791 | 1557 |
| 1792 void QuotaManager::DidGetAvailableSpace(int64_t space) { | 1558 namespace { |
| 1793 // crbug.com/349708 | 1559 void DidGetTempStorageConfigThreadAdapter( |
| 1794 TRACE_EVENT1("io", "QuotaManager::DidGetAvailableSpace", | 1560 base::TaskRunner* task_runner, |
| 1795 "n_callbacks", available_space_callbacks_.size()); | 1561 const TemporaryStorageConfigurationCallback& callback, |
| 1562 const TemporaryStorageConfiguration& storage_config) { |
| 1563 task_runner->PostTask(FROM_HERE, base::Bind(callback, storage_config)); |
| 1564 } |
| 1565 } // namespace |
| 1796 | 1566 |
| 1797 available_space_callbacks_.Run(kQuotaStatusOk, space); | 1567 void QuotaManager::GetTemporaryStorageConfig( |
| 1568 const TemporaryStorageConfigurationCallback& callback) { |
| 1569 if (base::TimeTicks::Now() - storage_config_timestamp_ < |
| 1570 storage_config_.refresh_interval) { |
| 1571 callback.Run(storage_config_); |
| 1572 return; |
| 1573 } |
| 1574 |
| 1575 if (!storage_config_callbacks_.Add(callback)) |
| 1576 return; |
| 1577 |
| 1578 // We invoke our clients GetTemporaryPoolConfigurationFunc on the |
| 1579 // UI thread and plumb the resulting value back to this thread. |
| 1580 get_config_task_runner_->PostTask( |
| 1581 FROM_HERE, |
| 1582 base::Bind( |
| 1583 get_config_function_, |
| 1584 profile_path_, is_incognito_, |
| 1585 base::Bind( |
| 1586 &DidGetTempStorageConfigThreadAdapter, |
| 1587 base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), |
| 1588 base::Bind( |
| 1589 &QuotaManager::DidGetTemporaryStorageConfig, |
| 1590 weak_factory_.GetWeakPtr())))); |
| 1591 } |
| 1592 |
| 1593 void QuotaManager::DidGetTemporaryStorageConfig( |
| 1594 const TemporaryStorageConfiguration& config) { |
| 1595 SetTemporaryStorageConfiguration(config); |
| 1596 storage_config_callbacks_.Run(config); |
| 1597 } |
| 1598 |
| 1599 void QuotaManager::GetDeviceStorageCapacity( |
| 1600 const StorageCapacityCallback& callback) { |
| 1601 if (!storage_capacity_callbacks_.Add(callback)) |
| 1602 return; |
| 1603 if (is_incognito_) { |
| 1604 GetTemporaryStorageConfig( |
| 1605 base::Bind( |
| 1606 &QuotaManager::ContinueIncognitoGetStorageCapacity, |
| 1607 weak_factory_.GetWeakPtr())); |
| 1608 return; |
| 1609 } |
| 1610 base::PostTaskAndReplyWithResult( |
| 1611 db_thread_.get(), |
| 1612 FROM_HERE, |
| 1613 base::Bind( |
| 1614 &QuotaManager::CallGetVolumeInfo, get_volume_info_fn_, profile_path_), |
| 1615 base::Bind( |
| 1616 &QuotaManager::DidGetDeviceStorageCapacity, |
| 1617 weak_factory_.GetWeakPtr())); |
| 1618 } |
| 1619 |
| 1620 void QuotaManager::ContinueIncognitoGetStorageCapacity( |
| 1621 const TemporaryStorageConfiguration& config) { |
| 1622 int64_t current_usage = |
| 1623 GetUsageTracker(kStorageTypeTemporary)->GetCachedUsage(); |
| 1624 int64_t available_space = std::max( |
| 1625 INT64_C(0), config.pool_size - current_usage); |
| 1626 DidGetDeviceStorageCapacity( |
| 1627 std::make_pair(config.pool_size, available_space)); |
| 1628 } |
| 1629 |
| 1630 void QuotaManager::DidGetDeviceStorageCapacity( |
| 1631 const std::pair<int64_t, int64_t>& total_and_available) { |
| 1632 storage_capacity_callbacks_.Run( |
| 1633 total_and_available.first, total_and_available.second); |
| 1798 } | 1634 } |
| 1799 | 1635 |
| 1800 void QuotaManager::DidDatabaseWork(bool success) { | 1636 void QuotaManager::DidDatabaseWork(bool success) { |
| 1801 db_disabled_ = !success; | 1637 db_disabled_ = !success; |
| 1802 } | 1638 } |
| 1803 | 1639 |
| 1804 void QuotaManager::DeleteOnCorrectThread() const { | 1640 void QuotaManager::DeleteOnCorrectThread() const { |
| 1805 if (!io_thread_->BelongsToCurrentThread() && | 1641 if (!io_thread_->BelongsToCurrentThread() && |
| 1806 io_thread_->DeleteSoon(FROM_HERE, this)) { | 1642 io_thread_->DeleteSoon(FROM_HERE, this)) { |
| 1807 return; | 1643 return; |
| 1808 } | 1644 } |
| 1809 delete this; | 1645 delete this; |
| 1810 } | 1646 } |
| 1811 | 1647 |
| 1812 void QuotaManager::PostTaskAndReplyWithResultForDBThread( | 1648 void QuotaManager::PostTaskAndReplyWithResultForDBThread( |
| 1813 const tracked_objects::Location& from_here, | 1649 const tracked_objects::Location& from_here, |
| 1814 const base::Callback<bool(QuotaDatabase*)>& task, | 1650 const base::Callback<bool(QuotaDatabase*)>& task, |
| 1815 const base::Callback<void(bool)>& reply) { | 1651 const base::Callback<void(bool)>& reply) { |
| 1816 // Deleting manager will post another task to DB thread to delete | 1652 // Deleting manager will post another task to DB thread to delete |
| 1817 // |database_|, therefore we can be sure that database_ is alive when this | 1653 // |database_|, therefore we can be sure that database_ is alive when this |
| 1818 // task runs. | 1654 // task runs. |
| 1819 base::PostTaskAndReplyWithResult( | 1655 base::PostTaskAndReplyWithResult( |
| 1820 db_thread_.get(), | 1656 db_thread_.get(), |
| 1821 from_here, | 1657 from_here, |
| 1822 base::Bind(task, base::Unretained(database_.get())), | 1658 base::Bind(task, base::Unretained(database_.get())), |
| 1823 reply); | 1659 reply); |
| 1824 } | 1660 } |
| 1825 | 1661 |
| 1826 // static | 1662 // static |
| 1827 int64_t QuotaManager::CallGetAmountOfFreeDiskSpace( | 1663 std::pair<int64_t, int64_t> QuotaManager::CallGetVolumeInfo( |
| 1828 GetVolumeInfoFn get_volume_info_fn, | 1664 GetVolumeInfoFn get_volume_info_fn, |
| 1829 const base::FilePath& profile_path) { | 1665 const base::FilePath& path) { |
| 1830 // crbug.com/349708 | 1666 // crbug.com/349708 |
| 1831 TRACE_EVENT0("io", "CallSystemGetAmountOfFreeDiskSpace"); | 1667 TRACE_EVENT0("io", "CallGetVolumeInfo"); |
| 1832 if (!base::CreateDirectory(profile_path)) { | 1668 if (!base::CreateDirectory(path)) { |
| 1833 LOG(WARNING) << "Create directory failed for path" << profile_path.value(); | 1669 LOG(WARNING) << "Create directory failed for path" << path.value(); |
| 1834 return 0; | 1670 return std::make_pair<int64_t, int64_t>(0, 0); |
| 1835 } | 1671 } |
| 1836 uint64_t available, total; | 1672 std::pair<int64_t, int64_t> total_and_available = get_volume_info_fn(path); |
| 1837 if (!get_volume_info_fn(profile_path, &available, &total)) { | 1673 UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total_and_available.first); |
| 1838 return 0; | 1674 UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", total_and_available.second); |
| 1839 } | 1675 return total_and_available; |
| 1840 UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available); | |
| 1841 UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total); | |
| 1842 return static_cast<int64_t>(available); | |
| 1843 } | 1676 } |
| 1844 | 1677 |
| 1678 |
| 1845 //static | 1679 //static |
| 1846 bool QuotaManager::GetVolumeInfo(const base::FilePath& path, | 1680 std::pair<int64_t,int64_t> |
| 1847 uint64_t* available_space, | 1681 QuotaManager::GetVolumeInfo(const base::FilePath& path) { |
| 1848 uint64_t* total_size) { | 1682 return std::make_pair( |
| 1849 // Inspired by similar code in the base::SysInfo class. | 1683 base::SysInfo::AmountOfTotalDiskSpace(path), |
| 1850 base::ThreadRestrictions::AssertIOAllowed(); | 1684 base::SysInfo::AmountOfFreeDiskSpace(path)); |
| 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 } | 1685 } |
| 1863 | 1686 |
| 1864 } // namespace storage | 1687 } // namespace storage |
| 1688 |
| OLD | NEW |