Chromium Code Reviews| 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 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <functional> | 10 #include <functional> |
| 11 #include <limits> | 11 #include <limits> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 18 #include "base/macros.h" | 18 #include "base/macros.h" |
| 19 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
| 20 #include "base/profiler/scoped_tracker.h" | 20 #include "base/profiler/scoped_tracker.h" |
| 21 #include "base/sequenced_task_runner.h" | 21 #include "base/sequenced_task_runner.h" |
| 22 #include "base/single_thread_task_runner.h" | 22 #include "base/single_thread_task_runner.h" |
| 23 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
| 24 #include "base/sys_info.h" | 24 #include "base/sys_info.h" |
| 25 #include "base/task_runner_util.h" | 25 #include "base/task_runner_util.h" |
| 26 #include "base/thread_task_runner_handle.h" | |
| 26 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 27 #include "base/trace_event/trace_event.h" | 28 #include "base/trace_event/trace_event.h" |
| 28 #include "net/base/url_util.h" | 29 #include "net/base/url_util.h" |
| 29 #include "storage/browser/quota/client_usage_tracker.h" | 30 #include "storage/browser/quota/client_usage_tracker.h" |
| 30 #include "storage/browser/quota/quota_manager_proxy.h" | 31 #include "storage/browser/quota/quota_manager_proxy.h" |
| 31 #include "storage/browser/quota/quota_temporary_storage_evictor.h" | 32 #include "storage/browser/quota/quota_temporary_storage_evictor.h" |
| 32 #include "storage/browser/quota/storage_monitor.h" | 33 #include "storage/browser/quota/storage_monitor.h" |
| 33 #include "storage/browser/quota/usage_tracker.h" | 34 #include "storage/browser/quota/usage_tracker.h" |
| 34 #include "storage/common/quota/quota_types.h" | 35 #include "storage/common/quota/quota_types.h" |
| 35 | 36 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 51 1, 10 * 1024 * 1024 /* 10TB */, 100) | 52 1, 10 * 1024 * 1024 /* 10TB */, 100) |
| 52 | 53 |
| 53 namespace storage { | 54 namespace storage { |
| 54 | 55 |
| 55 namespace { | 56 namespace { |
| 56 | 57 |
| 57 const int64_t kMBytes = 1024 * 1024; | 58 const int64_t kMBytes = 1024 * 1024; |
| 58 const int kMinutesInMilliSeconds = 60 * 1000; | 59 const int kMinutesInMilliSeconds = 60 * 1000; |
| 59 | 60 |
| 60 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour | 61 const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour |
| 61 const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0; // 33% | 62 const double kTemporaryQuotaRatio = 1.0 / 3.0; // 33% |
|
jsbell
2016/03/23 18:08:28
While you're here, can you comment on what these a
michaeln
2016/04/07 00:32:34
Done, also moved these values to where they're use
| |
| 63 | |
| 64 #if defined(OS_ANDROID) | |
| 65 const uint64_t kOsAccomodation = 250 * kMBytes; | |
|
michaeln
2016/03/22 22:23:55
these specific numbers are just placeholders, this
| |
| 66 #elif defined(OS_CHROMEOS) | |
| 67 const uint64_t kOsAccomodation = 1000 * kMBytes; | |
| 68 #else | |
| 69 const uint64_t kOsAccomodation = 10000 * kMBytes; | |
| 70 #endif | |
| 62 | 71 |
| 63 } // namespace | 72 } // namespace |
| 64 | 73 |
| 65 // Arbitrary for now, but must be reasonably small so that | 74 // Arbitrary for now, but must be reasonably small so that |
| 66 // in-memory databases can fit. | 75 // in-memory databases can fit. |
| 67 // TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this. | 76 // TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this. |
| 68 const int64_t QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes; | 77 const int64_t QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes; |
| 69 | 78 |
| 70 const int64_t QuotaManager::kNoLimit = INT64_MAX; | 79 const int64_t QuotaManager::kNoLimit = INT64_MAX; |
| 71 | 80 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 } | 245 } |
| 237 | 246 |
| 238 bool UpdateModifiedTimeOnDBThread(const GURL& origin, | 247 bool UpdateModifiedTimeOnDBThread(const GURL& origin, |
| 239 StorageType type, | 248 StorageType type, |
| 240 base::Time modified_time, | 249 base::Time modified_time, |
| 241 QuotaDatabase* database) { | 250 QuotaDatabase* database) { |
| 242 DCHECK(database); | 251 DCHECK(database); |
| 243 return database->SetOriginLastModifiedTime(origin, type, modified_time); | 252 return database->SetOriginLastModifiedTime(origin, type, modified_time); |
| 244 } | 253 } |
| 245 | 254 |
| 246 int64_t CalculateTemporaryGlobalQuota(int64_t global_limited_usage, | |
| 247 int64_t available_space) { | |
| 248 DCHECK_GE(global_limited_usage, 0); | |
| 249 int64_t avail_space = available_space; | |
| 250 if (avail_space < | |
| 251 std::numeric_limits<int64_t>::max() - global_limited_usage) { | |
| 252 // We basically calculate the temporary quota by | |
| 253 // [available_space + space_used_for_temp] * kTempQuotaRatio, | |
| 254 // but make sure we'll have no overflow. | |
| 255 avail_space += global_limited_usage; | |
| 256 } | |
| 257 int64_t pool_size = avail_space * kTemporaryQuotaRatioToAvail; | |
| 258 UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", pool_size); | |
| 259 return pool_size; | |
| 260 } | |
| 261 | |
| 262 void DispatchTemporaryGlobalQuotaCallback( | |
| 263 const QuotaCallback& callback, | |
| 264 QuotaStatusCode status, | |
| 265 const UsageAndQuota& usage_and_quota) { | |
| 266 if (status != kQuotaStatusOk) { | |
| 267 callback.Run(status, 0); | |
| 268 return; | |
| 269 } | |
| 270 | |
| 271 callback.Run(status, CalculateTemporaryGlobalQuota( | |
| 272 usage_and_quota.global_limited_usage, | |
| 273 usage_and_quota.available_disk_space)); | |
| 274 } | |
| 275 | |
| 276 int64_t CalculateQuotaWithDiskSpace(int64_t available_disk_space, | 255 int64_t CalculateQuotaWithDiskSpace(int64_t available_disk_space, |
| 277 int64_t usage, | 256 int64_t usage, |
| 278 int64_t quota) { | 257 int64_t quota) { |
| 279 if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) { | 258 if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) { |
| 280 LOG(WARNING) | 259 LOG(WARNING) |
| 281 << "Running out of disk space for profile." | 260 << "Running out of disk space for profile." |
| 282 << " QuotaManager starts forbidding further quota consumption."; | 261 << " QuotaManager starts forbidding further quota consumption."; |
| 283 return usage; | 262 return usage; |
| 284 } | 263 } |
| 285 | 264 |
| 286 if (quota < usage) { | 265 if (quota < usage) { |
| 287 // No more space; cap the quota to the current usage. | 266 // No more space; cap the quota to the current usage. |
| 288 return usage; | 267 return usage; |
| 289 } | 268 } |
| 290 | 269 |
| 291 available_disk_space -= QuotaManager::kMinimumPreserveForSystem; | 270 available_disk_space -= QuotaManager::kMinimumPreserveForSystem; |
| 292 if (available_disk_space < quota - usage) | 271 if (available_disk_space < quota - usage) |
| 293 return available_disk_space + usage; | 272 return available_disk_space + usage; |
| 294 | 273 |
| 295 return quota; | 274 return quota; |
| 296 } | 275 } |
| 297 | 276 |
| 298 int64_t CalculateTemporaryHostQuota(int64_t host_usage, | 277 int64_t CalculateTemporaryHostQuota(int64_t host_usage, |
| 299 int64_t global_quota, | 278 int64_t global_quota, |
| 300 int64_t global_limited_usage) { | 279 int64_t available_disk_space) { |
| 301 DCHECK_GE(global_limited_usage, 0); | 280 const int64_t desired_quota = global_quota / |
| 302 int64_t host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion; | 281 QuotaManager::kPerHostTemporaryPortion; |
| 303 if (global_limited_usage > global_quota) | 282 |
|
michaeln
2016/03/22 21:40:15
This used to defend against filling the device.
| |
| 304 host_quota = std::min(host_quota, host_usage); | 283 // We define "too low" as not enough room for another hosts |
| 305 return host_quota; | 284 // nominal desired amount of data. (TODO: what should this be) |
|
michaeln
2016/03/22 21:40:15
~66 MBytes for small andoid devcices and ~66GB for
jsbell
2016/03/23 18:08:29
Would the "save a bit of room for non-Chrome usage
michaeln
2016/04/07 00:32:34
This is one of the two places where logic to "save
| |
| 285 const int64_t too_low_threshold = desired_quota; | |
| 286 | |
| 287 // If disk space is too low, cap usage at current levels. | |
| 288 if (available_disk_space < too_low_threshold) | |
|
michaeln
2016/03/22 21:40:15
That defense is replaced with this.
| |
| 289 return std::min(desired_quota, host_usage); | |
| 290 | |
| 291 // If its close to being too low, cap growth to avoid it getting too low. | |
| 292 int64_t remaining_quota = std::min(INT64_C(0), desired_quota - host_usage); | |
|
jsbell
2016/03/23 18:08:28
I think this might be clearer as:
return std::min
michaeln
2016/04/07 00:32:34
I think your right. I had thought a variable named
| |
| 293 if (available_disk_space < remaining_quota + too_low_threshold) { | |
| 294 remaining_quota = available_disk_space - too_low_threshold; | |
| 295 return host_usage + remaining_quota; | |
| 296 } | |
| 297 | |
| 298 return desired_quota; | |
| 306 } | 299 } |
| 307 | 300 |
| 308 void DispatchUsageAndQuotaForWebApps( | 301 void DispatchUsageAndQuotaForWebApps( |
| 309 StorageType type, | 302 StorageType type, |
| 310 bool is_incognito, | 303 bool is_incognito, |
| 311 bool is_unlimited, | 304 bool is_unlimited, |
| 312 bool can_query_disk_size, | 305 bool can_query_disk_size, |
| 313 const QuotaManager::GetUsageAndQuotaCallback& callback, | 306 const QuotaManager::GetUsageAndQuotaCallback& callback, |
| 314 QuotaStatusCode status, | 307 QuotaStatusCode status, |
| 315 const UsageAndQuota& usage_and_quota) { | 308 const UsageAndQuota& usage_and_quota) { |
| 316 if (status != kQuotaStatusOk) { | 309 if (status != kQuotaStatusOk) { |
| 317 callback.Run(status, 0, 0); | 310 callback.Run(status, 0, 0); |
| 318 return; | 311 return; |
| 319 } | 312 } |
| 320 | 313 |
| 321 int64_t usage = usage_and_quota.usage; | 314 int64_t host_usage = usage_and_quota.usage; |
| 322 int64_t quota = usage_and_quota.quota; | 315 int64_t global_quota = usage_and_quota.quota; |
| 316 int64_t host_quota = global_quota; | |
| 323 | 317 |
| 324 if (type == kStorageTypeTemporary && !is_unlimited) { | 318 if (type == kStorageTypeTemporary && !is_unlimited) { |
| 325 quota = CalculateTemporaryHostQuota( | 319 host_quota = CalculateTemporaryHostQuota( |
| 326 usage, quota, usage_and_quota.global_limited_usage); | 320 host_usage, global_quota, usage_and_quota.available_disk_space); |
| 327 } | 321 } |
| 328 | 322 |
| 329 if (is_incognito) { | 323 if (is_incognito) { |
| 330 quota = std::min(quota, QuotaManager::kIncognitoDefaultQuotaLimit); | 324 host_quota = std::min(host_quota, |
| 331 callback.Run(status, usage, quota); | 325 QuotaManager::kIncognitoDefaultQuotaLimit); |
| 326 callback.Run(status, host_usage, host_quota); | |
| 332 return; | 327 return; |
| 333 } | 328 } |
| 334 | 329 |
| 335 // For apps with unlimited permission or can_query_disk_size is true (and not | 330 // For apps with unlimited permission or can_query_disk_size is true (and not |
| 336 // in incognito mode). | 331 // in incognito mode). |
| 337 // We assume we can expose the actual disk size for them and cap the quota by | 332 // We assume we can expose the actual disk size for them and cap the quota by |
| 338 // the available disk space. | 333 // the available disk space. |
| 339 if (is_unlimited || can_query_disk_size) { | 334 if (is_unlimited || can_query_disk_size) { |
| 340 callback.Run( | 335 callback.Run( |
| 341 status, usage, | 336 status, host_usage, |
| 342 CalculateQuotaWithDiskSpace( | 337 CalculateQuotaWithDiskSpace( |
| 343 usage_and_quota.available_disk_space, | 338 usage_and_quota.available_disk_space, |
| 344 usage, quota)); | 339 host_usage, host_quota)); |
| 345 return; | 340 return; |
| 346 } | 341 } |
| 347 | 342 |
| 348 callback.Run(status, usage, quota); | 343 callback.Run(status, host_usage, host_quota); |
| 349 } | 344 } |
| 350 | 345 |
| 351 } // namespace | 346 } // namespace |
| 352 | 347 |
| 353 UsageAndQuota::UsageAndQuota() | 348 UsageAndQuota::UsageAndQuota() |
| 354 : usage(0), | 349 : usage(0), |
| 355 global_limited_usage(0), | 350 global_limited_usage(0), |
| 356 quota(0), | 351 quota(0), |
| 357 available_disk_space(0) { | 352 available_disk_space(0) { |
| 358 } | 353 } |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 918 bool unlimited = IsStorageUnlimited(origin, type); | 913 bool unlimited = IsStorageUnlimited(origin, type); |
| 919 bool can_query_disk_size = CanQueryDiskSize(origin); | 914 bool can_query_disk_size = CanQueryDiskSize(origin); |
| 920 | 915 |
| 921 UsageAndQuotaCallbackDispatcher* dispatcher = | 916 UsageAndQuotaCallbackDispatcher* dispatcher = |
| 922 new UsageAndQuotaCallbackDispatcher(this); | 917 new UsageAndQuotaCallbackDispatcher(this); |
| 923 | 918 |
| 924 if (unlimited) { | 919 if (unlimited) { |
| 925 dispatcher->set_quota(kNoLimit); | 920 dispatcher->set_quota(kNoLimit); |
| 926 } else { | 921 } else { |
| 927 if (type == kStorageTypeTemporary) { | 922 if (type == kStorageTypeTemporary) { |
| 928 GetUsageTracker(type)->GetGlobalLimitedUsage( | |
| 929 dispatcher->GetGlobalLimitedUsageCallback()); | |
| 930 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); | 923 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); |
| 931 } else if (type == kStorageTypePersistent) { | 924 } else if (type == kStorageTypePersistent) { |
| 932 GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin), | 925 GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin), |
| 933 dispatcher->GetQuotaCallback()); | 926 dispatcher->GetQuotaCallback()); |
| 934 } else { | 927 } else { |
| 935 dispatcher->set_quota(kSyncableStorageDefaultHostQuota); | 928 dispatcher->set_quota(kSyncableStorageDefaultHostQuota); |
| 936 } | 929 } |
| 937 } | 930 } |
| 938 | 931 |
| 939 DCHECK(GetUsageTracker(type)); | 932 DCHECK(GetUsageTracker(type)); |
| 940 GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin), | 933 GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin), |
| 941 dispatcher->GetHostUsageCallback()); | 934 dispatcher->GetHostUsageCallback()); |
| 942 | 935 |
| 943 if (!is_incognito_ && (unlimited || can_query_disk_size)) | 936 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); |
|
jsbell
2016/03/23 18:08:29
Can we avoid this if is_incognito_ like we used to
michaeln
2016/04/07 00:32:34
that's a good question, the system is currently us
| |
| 944 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); | |
| 945 | 937 |
| 946 dispatcher->WaitForResults(base::Bind( | 938 dispatcher->WaitForResults(base::Bind( |
| 947 &DispatchUsageAndQuotaForWebApps, | 939 &DispatchUsageAndQuotaForWebApps, |
| 948 type, is_incognito_, unlimited, can_query_disk_size, | 940 type, is_incognito_, unlimited, can_query_disk_size, |
| 949 callback)); | 941 callback)); |
| 950 } | 942 } |
| 951 | 943 |
| 952 void QuotaManager::GetUsageAndQuota( | 944 void QuotaManager::GetUsageAndQuota( |
| 953 const GURL& origin, StorageType type, | 945 const GURL& origin, StorageType type, |
| 954 const GetUsageAndQuotaCallback& callback) { | 946 const GetUsageAndQuotaCallback& callback) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1050 &QuotaManager::GetTemporaryGlobalQuota, | 1042 &QuotaManager::GetTemporaryGlobalQuota, |
| 1051 weak_factory_.GetWeakPtr(), callback)); | 1043 weak_factory_.GetWeakPtr(), callback)); |
| 1052 return; | 1044 return; |
| 1053 } | 1045 } |
| 1054 | 1046 |
| 1055 if (temporary_quota_override_ > 0) { | 1047 if (temporary_quota_override_ > 0) { |
| 1056 callback.Run(kQuotaStatusOk, temporary_quota_override_); | 1048 callback.Run(kQuotaStatusOk, temporary_quota_override_); |
| 1057 return; | 1049 return; |
| 1058 } | 1050 } |
| 1059 | 1051 |
| 1060 UsageAndQuotaCallbackDispatcher* dispatcher = | 1052 db_thread_->PostTask( |
| 1061 new UsageAndQuotaCallbackDispatcher(this); | 1053 FROM_HERE, |
| 1062 GetUsageTracker(kStorageTypeTemporary)-> | 1054 base::Bind(&QuotaManager::CalculateTemporaryPoolSize, |
| 1063 GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback()); | 1055 get_volume_info_fn_, profile_path_, callback, |
| 1064 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); | 1056 base::ThreadTaskRunnerHandle::Get())); |
| 1065 dispatcher->WaitForResults( | |
| 1066 base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback)); | |
| 1067 } | 1057 } |
| 1068 | 1058 |
| 1069 void QuotaManager::SetTemporaryGlobalOverrideQuota( | 1059 void QuotaManager::SetTemporaryGlobalOverrideQuota( |
| 1070 int64_t new_quota, | 1060 int64_t new_quota, |
| 1071 const QuotaCallback& callback) { | 1061 const QuotaCallback& callback) { |
| 1072 LazyInitialize(); | 1062 LazyInitialize(); |
| 1073 | 1063 |
| 1074 if (new_quota < 0) { | 1064 if (new_quota < 0) { |
| 1075 if (!callback.is_null()) | 1065 if (!callback.is_null()) |
| 1076 callback.Run(kQuotaErrorInvalidModification, -1); | 1066 callback.Run(kQuotaErrorInvalidModification, -1); |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1789 // |database_|, therefore we can be sure that database_ is alive when this | 1779 // |database_|, therefore we can be sure that database_ is alive when this |
| 1790 // task runs. | 1780 // task runs. |
| 1791 base::PostTaskAndReplyWithResult( | 1781 base::PostTaskAndReplyWithResult( |
| 1792 db_thread_.get(), | 1782 db_thread_.get(), |
| 1793 from_here, | 1783 from_here, |
| 1794 base::Bind(task, base::Unretained(database_.get())), | 1784 base::Bind(task, base::Unretained(database_.get())), |
| 1795 reply); | 1785 reply); |
| 1796 } | 1786 } |
| 1797 | 1787 |
| 1798 // static | 1788 // static |
| 1789 void QuotaManager::CalculateTemporaryPoolSize( | |
| 1790 GetVolumeInfoFn get_volume_info_fn, | |
| 1791 const base::FilePath& profile_path, | |
| 1792 const QuotaCallback& callback, | |
| 1793 const scoped_refptr<base::TaskRunner>& reply_runner) { | |
| 1794 QuotaStatusCode status_code = kQuotaStatusUnknown; | |
| 1795 int64_t pool_size = 0; | |
| 1796 uint64_t available, total; | |
| 1797 if (get_volume_info_fn(profile_path, &available, &total)) { | |
| 1798 status_code = kQuotaStatusOk; | |
| 1799 if (total > kOsAccomodation) | |
| 1800 total -= kOsAccomodation; // todo: what if total is super small??? | |
|
jsbell
2016/03/23 18:08:28
Maybe we want a threshold, e.g. os_reserve = min(k
michaeln
2016/04/07 00:32:34
Done
| |
| 1801 pool_size = static_cast<int64_t>(total * kTemporaryQuotaRatio); | |
| 1802 UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", pool_size); | |
| 1803 } | |
| 1804 reply_runner->PostTask( | |
| 1805 FROM_HERE, base::Bind(callback, status_code, pool_size)); | |
| 1806 } | |
| 1807 | |
| 1808 // static | |
| 1799 int64_t QuotaManager::CallGetAmountOfFreeDiskSpace( | 1809 int64_t QuotaManager::CallGetAmountOfFreeDiskSpace( |
| 1800 GetVolumeInfoFn get_volume_info_fn, | 1810 GetVolumeInfoFn get_volume_info_fn, |
| 1801 const base::FilePath& profile_path) { | 1811 const base::FilePath& profile_path) { |
| 1802 // crbug.com/349708 | 1812 // crbug.com/349708 |
| 1803 TRACE_EVENT0("io", "CallSystemGetAmountOfFreeDiskSpace"); | 1813 TRACE_EVENT0("io", "CallSystemGetAmountOfFreeDiskSpace"); |
| 1804 if (!base::CreateDirectory(profile_path)) { | 1814 if (!base::CreateDirectory(profile_path)) { |
| 1805 LOG(WARNING) << "Create directory failed for path" << profile_path.value(); | 1815 LOG(WARNING) << "Create directory failed for path" << profile_path.value(); |
| 1806 return 0; | 1816 return 0; |
| 1807 } | 1817 } |
| 1808 uint64_t available, total; | 1818 uint64_t available, total; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1832 return false; | 1842 return false; |
| 1833 *available_space = static_cast<uint64_t>(stats.f_bavail) * stats.f_frsize; | 1843 *available_space = static_cast<uint64_t>(stats.f_bavail) * stats.f_frsize; |
| 1834 *total_size = static_cast<uint64_t>(stats.f_blocks) * stats.f_frsize; | 1844 *total_size = static_cast<uint64_t>(stats.f_blocks) * stats.f_frsize; |
| 1835 #else | 1845 #else |
| 1836 #error Not implemented | 1846 #error Not implemented |
| 1837 #endif | 1847 #endif |
| 1838 return true; | 1848 return true; |
| 1839 } | 1849 } |
| 1840 | 1850 |
| 1841 } // namespace storage | 1851 } // namespace storage |
| OLD | NEW |