OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "components/doodle/doodle_service.h" | 5 #include "components/doodle/doodle_service.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
11 #include "base/time/time.h" | |
12 #include "base/values.h" | 11 #include "base/values.h" |
13 #include "components/doodle/pref_names.h" | 12 #include "components/doodle/pref_names.h" |
14 #include "components/prefs/pref_registry.h" | 13 #include "components/prefs/pref_registry.h" |
15 #include "components/prefs/pref_registry_simple.h" | 14 #include "components/prefs/pref_registry_simple.h" |
16 #include "components/prefs/pref_service.h" | 15 #include "components/prefs/pref_service.h" |
17 | 16 |
18 namespace doodle { | 17 namespace doodle { |
19 | 18 |
20 namespace { | 19 namespace { |
21 | 20 |
| 21 // The maximum time-to-live we'll accept; any larger values will be clamped to |
| 22 // this one. This is a last resort in case the server sends bad data. |
22 const int64_t kMaxTimeToLiveSecs = 30 * 24 * 60 * 60; // 30 days | 23 const int64_t kMaxTimeToLiveSecs = 30 * 24 * 60 * 60; // 30 days |
23 | 24 |
| 25 // The default value for DoodleService::min_refresh_interval_. |
| 26 const int64_t kDefaultMinRefreshIntervalSecs = 15 * 60; // 15 minutes |
| 27 |
24 } // namespace | 28 } // namespace |
25 | 29 |
26 // static | 30 // static |
27 void DoodleService::RegisterProfilePrefs(PrefRegistrySimple* pref_registry) { | 31 void DoodleService::RegisterProfilePrefs(PrefRegistrySimple* pref_registry) { |
28 pref_registry->RegisterDictionaryPref(prefs::kCachedConfig, | 32 pref_registry->RegisterDictionaryPref(prefs::kCachedConfig, |
29 new base::DictionaryValue(), | 33 new base::DictionaryValue(), |
30 PrefRegistry::LOSSY_PREF); | 34 PrefRegistry::LOSSY_PREF); |
31 pref_registry->RegisterInt64Pref(prefs::kCachedConfigExpiry, 0, | 35 pref_registry->RegisterInt64Pref(prefs::kCachedConfigExpiry, 0, |
32 PrefRegistry::LOSSY_PREF); | 36 PrefRegistry::LOSSY_PREF); |
33 } | 37 } |
34 | 38 |
35 DoodleService::DoodleService(PrefService* pref_service, | 39 DoodleService::DoodleService( |
36 std::unique_ptr<DoodleFetcher> fetcher, | 40 PrefService* pref_service, |
37 std::unique_ptr<base::OneShotTimer> expiry_timer, | 41 std::unique_ptr<DoodleFetcher> fetcher, |
38 std::unique_ptr<base::Clock> clock, | 42 std::unique_ptr<base::OneShotTimer> expiry_timer, |
39 std::unique_ptr<base::TickClock> tick_clock) | 43 std::unique_ptr<base::Clock> clock, |
| 44 std::unique_ptr<base::TickClock> tick_clock, |
| 45 base::Optional<base::TimeDelta> override_min_refresh_interval) |
40 : pref_service_(pref_service), | 46 : pref_service_(pref_service), |
41 fetcher_(std::move(fetcher)), | 47 fetcher_(std::move(fetcher)), |
42 expiry_timer_(std::move(expiry_timer)), | 48 expiry_timer_(std::move(expiry_timer)), |
43 clock_(std::move(clock)), | 49 clock_(std::move(clock)), |
44 tick_clock_(std::move(tick_clock)) { | 50 tick_clock_(std::move(tick_clock)), |
| 51 min_refresh_interval_( |
| 52 override_min_refresh_interval.has_value() |
| 53 ? override_min_refresh_interval.value() |
| 54 : base::TimeDelta::FromSeconds(kDefaultMinRefreshIntervalSecs)) { |
45 DCHECK(pref_service_); | 55 DCHECK(pref_service_); |
46 DCHECK(fetcher_); | 56 DCHECK(fetcher_); |
47 DCHECK(expiry_timer_); | 57 DCHECK(expiry_timer_); |
48 DCHECK(clock_); | 58 DCHECK(clock_); |
49 DCHECK(tick_clock_); | 59 DCHECK(tick_clock_); |
50 | 60 |
51 base::Time expiry_date = base::Time::FromInternalValue( | 61 base::Time expiry_date = base::Time::FromInternalValue( |
52 pref_service_->GetInt64(prefs::kCachedConfigExpiry)); | 62 pref_service_->GetInt64(prefs::kCachedConfigExpiry)); |
53 base::Optional<DoodleConfig> config = DoodleConfig::FromDictionary( | 63 base::Optional<DoodleConfig> config = DoodleConfig::FromDictionary( |
54 *pref_service_->GetDictionary(prefs::kCachedConfig), base::nullopt); | 64 *pref_service_->GetDictionary(prefs::kCachedConfig), base::nullopt); |
55 DoodleState state = | 65 DoodleState state = |
56 config.has_value() ? DoodleState::AVAILABLE : DoodleState::NO_DOODLE; | 66 config.has_value() ? DoodleState::AVAILABLE : DoodleState::NO_DOODLE; |
57 HandleNewConfig(state, expiry_date - clock_->Now(), config); | 67 HandleNewConfig(state, expiry_date - clock_->Now(), config); |
58 } | 68 } |
59 | 69 |
60 DoodleService::~DoodleService() = default; | 70 DoodleService::~DoodleService() = default; |
61 | 71 |
62 void DoodleService::Shutdown() {} | 72 void DoodleService::Shutdown() {} |
63 | 73 |
64 void DoodleService::AddObserver(Observer* observer) { | 74 void DoodleService::AddObserver(Observer* observer) { |
65 observers_.AddObserver(observer); | 75 observers_.AddObserver(observer); |
66 } | 76 } |
67 | 77 |
68 void DoodleService::RemoveObserver(Observer* observer) { | 78 void DoodleService::RemoveObserver(Observer* observer) { |
69 observers_.RemoveObserver(observer); | 79 observers_.RemoveObserver(observer); |
70 } | 80 } |
71 | 81 |
72 void DoodleService::Refresh() { | 82 void DoodleService::Refresh() { |
| 83 base::TimeTicks now_ticks = tick_clock_->NowTicks(); |
| 84 // Check if we have passed the minimum refresh interval. |
| 85 base::TimeDelta time_since_fetch = now_ticks - last_successful_fetch_; |
| 86 if (time_since_fetch < min_refresh_interval_) { |
| 87 RecordDownloadMetrics(OUTCOME_REFRESH_INTERVAL_NOT_PASSED, |
| 88 base::TimeDelta()); |
| 89 return; |
| 90 } |
73 fetcher_->FetchDoodle(base::BindOnce(&DoodleService::DoodleFetched, | 91 fetcher_->FetchDoodle(base::BindOnce(&DoodleService::DoodleFetched, |
74 base::Unretained(this), | 92 base::Unretained(this), now_ticks)); |
75 tick_clock_->NowTicks())); | |
76 } | 93 } |
77 | 94 |
78 // static | 95 // static |
79 bool DoodleService::DownloadOutcomeIsSuccess(DownloadOutcome outcome) { | 96 bool DoodleService::DownloadOutcomeIsSuccess(DownloadOutcome outcome) { |
80 switch (outcome) { | 97 switch (outcome) { |
81 case OUTCOME_NEW_DOODLE: | 98 case OUTCOME_NEW_DOODLE: |
82 case OUTCOME_REVALIDATED_DOODLE: | 99 case OUTCOME_REVALIDATED_DOODLE: |
83 case OUTCOME_CHANGED_DOODLE: | 100 case OUTCOME_CHANGED_DOODLE: |
84 case OUTCOME_NO_DOODLE: | 101 case OUTCOME_NO_DOODLE: |
85 return true; | 102 return true; |
86 case OUTCOME_EXPIRED: | 103 case OUTCOME_EXPIRED: |
87 case OUTCOME_DOWNLOAD_ERROR: | 104 case OUTCOME_DOWNLOAD_ERROR: |
88 case OUTCOME_PARSING_ERROR: | 105 case OUTCOME_PARSING_ERROR: |
| 106 case OUTCOME_REFRESH_INTERVAL_NOT_PASSED: |
89 return false; | 107 return false; |
90 case OUTCOME_COUNT: | 108 case OUTCOME_COUNT: |
91 NOTREACHED(); | 109 NOTREACHED(); |
92 } | 110 } |
93 return false; | 111 return false; |
94 } | 112 } |
95 | 113 |
96 // static | 114 // static |
97 void DoodleService::RecordDownloadMetrics(DownloadOutcome outcome, | 115 void DoodleService::RecordDownloadMetrics(DownloadOutcome outcome, |
98 base::TimeDelta download_time) { | 116 base::TimeDelta download_time) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 return OUTCOME_CHANGED_DOODLE; | 156 return OUTCOME_CHANGED_DOODLE; |
139 } | 157 } |
140 return OUTCOME_REVALIDATED_DOODLE; | 158 return OUTCOME_REVALIDATED_DOODLE; |
141 } | 159 } |
142 | 160 |
143 void DoodleService::DoodleFetched( | 161 void DoodleService::DoodleFetched( |
144 base::TimeTicks start_time, | 162 base::TimeTicks start_time, |
145 DoodleState state, | 163 DoodleState state, |
146 base::TimeDelta time_to_live, | 164 base::TimeDelta time_to_live, |
147 const base::Optional<DoodleConfig>& doodle_config) { | 165 const base::Optional<DoodleConfig>& doodle_config) { |
148 base::TimeDelta download_time = tick_clock_->NowTicks() - start_time; | 166 base::TimeTicks now_ticks = tick_clock_->NowTicks(); |
149 DownloadOutcome outcome = HandleNewConfig(state, time_to_live, doodle_config); | 167 DownloadOutcome outcome = HandleNewConfig(state, time_to_live, doodle_config); |
| 168 if (DownloadOutcomeIsSuccess(outcome)) { |
| 169 last_successful_fetch_ = now_ticks; |
| 170 } |
| 171 base::TimeDelta download_time = now_ticks - start_time; |
150 RecordDownloadMetrics(outcome, download_time); | 172 RecordDownloadMetrics(outcome, download_time); |
151 } | 173 } |
152 | 174 |
153 DoodleService::DownloadOutcome DoodleService::HandleNewConfig( | 175 DoodleService::DownloadOutcome DoodleService::HandleNewConfig( |
154 DoodleState state, | 176 DoodleState state, |
155 base::TimeDelta time_to_live, | 177 base::TimeDelta time_to_live, |
156 const base::Optional<DoodleConfig>& doodle_config) { | 178 const base::Optional<DoodleConfig>& doodle_config) { |
157 // Clamp the time-to-live to some reasonable maximum. | 179 // Clamp the time-to-live to some reasonable maximum. |
158 if (time_to_live.InSeconds() > kMaxTimeToLiveSecs) { | 180 if (time_to_live.InSeconds() > kMaxTimeToLiveSecs) { |
159 time_to_live = base::TimeDelta::FromSeconds(kMaxTimeToLiveSecs); | 181 time_to_live = base::TimeDelta::FromSeconds(kMaxTimeToLiveSecs); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 pref_service_->ClearPref(prefs::kCachedConfigExpiry); | 232 pref_service_->ClearPref(prefs::kCachedConfigExpiry); |
211 } | 233 } |
212 } | 234 } |
213 | 235 |
214 void DoodleService::DoodleExpired() { | 236 void DoodleService::DoodleExpired() { |
215 DCHECK(cached_config_.has_value()); | 237 DCHECK(cached_config_.has_value()); |
216 HandleNewConfig(DoodleState::NO_DOODLE, base::TimeDelta(), base::nullopt); | 238 HandleNewConfig(DoodleState::NO_DOODLE, base::TimeDelta(), base::nullopt); |
217 } | 239 } |
218 | 240 |
219 } // namespace doodle | 241 } // namespace doodle |
OLD | NEW |