michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "storage/browser/quota/quota_settings.h" |
| 6 | |
| 7 | #include <algorithm> |
| 8 | |
| 9 | #include "base/metrics/histogram_macros.h" |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 10 | #include "base/rand_util.h" |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 11 | #include "base/sys_info.h" |
tapted | e6d878e | 2017-06-24 01:53:45 | [diff] [blame^] | 12 | #include "base/task_scheduler/post_task.h" |
| 13 | #include "base/threading/thread_restrictions.h" |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 14 | |
| 15 | #define UMA_HISTOGRAM_MBYTES(name, sample) \ |
| 16 | UMA_HISTOGRAM_CUSTOM_COUNTS((name), static_cast<int>((sample) / kMBytes), 1, \ |
| 17 | 10 * 1024 * 1024 /* 10TB */, 100) |
| 18 | |
| 19 | namespace storage { |
| 20 | |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 21 | namespace { |
| 22 | |
| 23 | // Skews |value| by +/- |percent|. |
| 24 | int64_t RandomizeByPercent(int64_t value, int percent) { |
| 25 | double random_percent = (base::RandDouble() - 0.5) * percent * 2; |
| 26 | return value + (value * (random_percent / 100.0)); |
| 27 | } |
| 28 | |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 29 | base::Optional<storage::QuotaSettings> CalculateNominalDynamicSettings( |
| 30 | const base::FilePath& partition_path, |
| 31 | bool is_incognito) { |
tapted | e6d878e | 2017-06-24 01:53:45 | [diff] [blame^] | 32 | base::ThreadRestrictions::AssertIOAllowed(); |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 33 | const int64_t kMBytes = 1024 * 1024; |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 34 | const int kRandomizedPercentage = 10; |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 35 | |
| 36 | if (is_incognito) { |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 37 | // The incognito pool size is a fraction of the amount of system memory, |
| 38 | // and the amount is capped to a hard limit. |
| 39 | const double kIncognitoPoolSizeRatio = 0.1; // 10% |
| 40 | const int64_t kMaxIncognitoPoolSize = 300 * kMBytes; |
| 41 | |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 42 | storage::QuotaSettings settings; |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 43 | settings.pool_size = std::min( |
| 44 | RandomizeByPercent(kMaxIncognitoPoolSize, kRandomizedPercentage), |
| 45 | static_cast<int64_t>(base::SysInfo::AmountOfPhysicalMemory() * |
| 46 | kIncognitoPoolSizeRatio)); |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 47 | settings.per_host_quota = settings.pool_size / 3; |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 48 | settings.session_only_per_host_quota = settings.per_host_quota; |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 49 | settings.refresh_interval = base::TimeDelta::Max(); |
| 50 | return settings; |
| 51 | } |
| 52 | |
| 53 | // The fraction of the device's storage the browser is willing to |
| 54 | // use for temporary storage, this is applied after adjusting the |
| 55 | // total to take os_accomodation into account. |
| 56 | const double kTemporaryPoolSizeRatio = 1.0 / 3.0; // 33% |
| 57 | |
| 58 | // The fraction of the device's storage the browser attempts to |
| 59 | // keep free. |
| 60 | const double kShouldRemainAvailableRatio = 0.1; // 10% |
| 61 | |
| 62 | // The fraction of the device's storage the browser attempts to |
| 63 | // keep free at all costs. |
| 64 | const double kMustRemainAvailableRatio = 0.01; // 1% |
| 65 | |
| 66 | // Determines the portion of the temp pool that can be |
| 67 | // utilized by a single host (ie. 5 for 20%). |
| 68 | const int kPerHostTemporaryPortion = 5; |
| 69 | |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 70 | // SessionOnly (or ephemeral) origins are allotted a fraction of what |
| 71 | // normal origins are provided, and the amount is capped to a hard limit. |
| 72 | const double kSessionOnlyHostQuotaRatio = 0.1; // 10% |
| 73 | const int64_t kMaxSessionOnlyHostQuota = 300 * kMBytes; |
| 74 | |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 75 | // os_accomodation is an estimate of how much storage is needed for |
| 76 | // the os and essential application code outside of the browser. |
| 77 | const int64_t kDefaultOSAccomodation = |
| 78 | #if defined(OS_ANDROID) |
| 79 | 1000 * kMBytes; |
| 80 | #elif defined(OS_CHROMEOS) |
| 81 | 1000 * kMBytes; |
| 82 | #elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) |
| 83 | 10000 * kMBytes; |
| 84 | #else |
| 85 | #error "Port: Need to define an OS accomodation value for unknown OS." |
| 86 | #endif |
| 87 | |
| 88 | storage::QuotaSettings settings; |
| 89 | |
| 90 | int64_t total = base::SysInfo::AmountOfTotalDiskSpace(partition_path); |
| 91 | if (total == -1) { |
| 92 | LOG(ERROR) << "Unable to compute QuotaSettings."; |
| 93 | return base::nullopt; |
| 94 | } |
| 95 | |
| 96 | // If our hardcoded OS accomodation is too large for the volume size, define |
| 97 | // the value as a fraction of the total volume size instead. |
| 98 | int64_t os_accomodation = |
| 99 | std::min(kDefaultOSAccomodation, static_cast<int64_t>(total * 0.8)); |
| 100 | UMA_HISTOGRAM_MBYTES("Quota.OSAccomodationDelta", |
| 101 | kDefaultOSAccomodation - os_accomodation); |
| 102 | |
| 103 | int64_t adjusted_total = total - os_accomodation; |
| 104 | int64_t pool_size = adjusted_total * kTemporaryPoolSizeRatio; |
| 105 | |
| 106 | settings.pool_size = pool_size; |
| 107 | settings.should_remain_available = total * kShouldRemainAvailableRatio; |
| 108 | settings.must_remain_available = total * kMustRemainAvailableRatio; |
| 109 | settings.per_host_quota = pool_size / kPerHostTemporaryPortion; |
michaeln | fa4c8940 | 2017-04-11 02:36:20 | [diff] [blame] | 110 | settings.session_only_per_host_quota = std::min( |
| 111 | RandomizeByPercent(kMaxSessionOnlyHostQuota, kRandomizedPercentage), |
| 112 | static_cast<int64_t>(settings.per_host_quota * |
| 113 | kSessionOnlyHostQuotaRatio)); |
michaeln | 10e5fc35 | 2017-02-07 02:07:58 | [diff] [blame] | 114 | settings.refresh_interval = base::TimeDelta::FromSeconds(60); |
| 115 | return settings; |
| 116 | } |
| 117 | |
| 118 | } // namespace |
tapted | e6d878e | 2017-06-24 01:53:45 | [diff] [blame^] | 119 | |
| 120 | void GetNominalDynamicSettings(const base::FilePath& partition_path, |
| 121 | bool is_incognito, |
| 122 | OptionalQuotaSettingsCallback callback) { |
| 123 | base::PostTaskWithTraitsAndReplyWithResult( |
| 124 | FROM_HERE, |
| 125 | {base::MayBlock(), base::TaskPriority::BACKGROUND, |
| 126 | base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, |
| 127 | base::BindOnce(&CalculateNominalDynamicSettings, partition_path, |
| 128 | is_incognito), |
| 129 | std::move(callback)); |
| 130 | } |
| 131 | |
| 132 | } // namespace storage |