Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ntp_snippets/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 using suggestions::SuggestionsService; | 28 using suggestions::SuggestionsService; |
| 29 | 29 |
| 30 namespace ntp_snippets { | 30 namespace ntp_snippets { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 const int kFetchingIntervalWifiChargingSeconds = 30 * 60; | 34 const int kFetchingIntervalWifiChargingSeconds = 30 * 60; |
| 35 const int kFetchingIntervalWifiSeconds = 2 * 60 * 60; | 35 const int kFetchingIntervalWifiSeconds = 2 * 60 * 60; |
| 36 const int kFetchingIntervalFallbackSeconds = 24 * 60 * 60; | 36 const int kFetchingIntervalFallbackSeconds = 24 * 60 * 60; |
| 37 | 37 |
| 38 // These define the times of day during which we will fetch via Wifi (without | |
| 39 // charging) - 6 AM to 10 PM. | |
| 40 const int kWifiFetchingHourMin = 6; | |
| 41 const int kWifiFetchingHourMax = 22; | |
| 42 | |
| 38 const int kDefaultExpiryTimeMins = 24 * 60; | 43 const int kDefaultExpiryTimeMins = 24 * 60; |
| 39 | 44 |
| 40 base::TimeDelta GetFetchingInterval(const char* switch_name, | 45 base::TimeDelta GetFetchingInterval(const char* switch_name, |
| 41 int default_value_seconds) { | 46 int default_value_seconds) { |
| 42 int value_seconds = default_value_seconds; | 47 int value_seconds = default_value_seconds; |
| 43 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); | 48 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); |
| 44 if (cmdline.HasSwitch(switch_name)) { | 49 if (cmdline.HasSwitch(switch_name)) { |
| 45 std::string str = cmdline.GetSwitchValueASCII(switch_name); | 50 std::string str = cmdline.GetSwitchValueASCII(switch_name); |
| 46 int switch_value_seconds = 0; | 51 int switch_value_seconds = 0; |
| 47 if (base::StringToInt(str, &switch_value_seconds)) | 52 if (base::StringToInt(str, &switch_value_seconds)) |
| 48 value_seconds = switch_value_seconds; | 53 value_seconds = switch_value_seconds; |
| 49 else | 54 else |
| 50 LOG(WARNING) << "Invalid value for switch " << switch_name; | 55 LOG(WARNING) << "Invalid value for switch " << switch_name; |
| 51 } | 56 } |
| 52 return base::TimeDelta::FromSeconds(value_seconds); | 57 return base::TimeDelta::FromSeconds(value_seconds); |
| 53 } | 58 } |
| 54 | 59 |
| 55 base::TimeDelta GetFetchingIntervalWifiCharging() { | 60 base::TimeDelta GetFetchingIntervalWifiCharging() { |
| 56 return GetFetchingInterval(switches::kFetchingIntervalWifiChargingSeconds, | 61 return GetFetchingInterval(switches::kFetchingIntervalWifiChargingSeconds, |
| 57 kFetchingIntervalWifiChargingSeconds); | 62 kFetchingIntervalWifiChargingSeconds); |
| 58 } | 63 } |
| 59 | 64 |
| 60 base::TimeDelta GetFetchingIntervalWifi() { | 65 base::TimeDelta GetFetchingIntervalWifi(const base::Time& now) { |
| 61 return GetFetchingInterval(switches::kFetchingIntervalWifiSeconds, | 66 // Only fetch via Wifi (without charging) during the proper times of day. |
| 62 kFetchingIntervalWifiSeconds); | 67 base::Time::Exploded exploded; |
| 68 now.LocalExplode(&exploded); | |
| 69 if (kWifiFetchingHourMin <= exploded.hour && | |
| 70 exploded.hour < kWifiFetchingHourMax) { | |
| 71 return GetFetchingInterval(switches::kFetchingIntervalWifiSeconds, | |
| 72 kFetchingIntervalWifiSeconds); | |
| 73 } | |
| 74 return base::TimeDelta(); | |
|
Bernhard Bauer
2016/04/11 13:00:58
Would it make sense to use the fallback value here
Marc Treib
2016/04/11 13:25:26
No, the "Fallback" wakeup would still trigger even
| |
| 63 } | 75 } |
| 64 | 76 |
| 65 base::TimeDelta GetFetchingIntervalFallback() { | 77 base::TimeDelta GetFetchingIntervalFallback() { |
| 66 return GetFetchingInterval(switches::kFetchingIntervalFallbackSeconds, | 78 return GetFetchingInterval(switches::kFetchingIntervalFallbackSeconds, |
| 67 kFetchingIntervalFallbackSeconds); | 79 kFetchingIntervalFallbackSeconds); |
| 68 } | 80 } |
| 69 | 81 |
| 82 base::TimeDelta GetRescheduleDelay(const base::Time& now) { | |
| 83 base::Time::Exploded exploded; | |
| 84 now.LocalExplode(&exploded); | |
| 85 // The scheduling changes at both |kWifiFetchingHourMin| and | |
| 86 // |kWifiFetchingHourMax|. Find the time of the next one that we'll hit. | |
| 87 bool next_day = false; | |
| 88 if (exploded.hour < kWifiFetchingHourMin) { | |
| 89 exploded.hour = kWifiFetchingHourMin; | |
| 90 } else if (exploded.hour < kWifiFetchingHourMax) { | |
| 91 exploded.hour = kWifiFetchingHourMax; | |
| 92 } else { | |
| 93 next_day = true; | |
| 94 exploded.hour = kWifiFetchingHourMin; | |
| 95 } | |
| 96 // In any case, reschedule at the full hour. Add some fudge to avoid being | |
| 97 // called back before it's actually time to reschedule, due to clock skew | |
| 98 // or other shenanigans. | |
|
Bernhard Bauer
2016/04/18 08:03:00
Wouldn't this just mean we'd reschedule for a coup
Marc Treib
2016/04/19 11:32:13
Yup, which would mean one extra pointless wakeup t
Bernhard Bauer
2016/04/19 15:45:35
Yeah, because in that minute (or actually less tha
Marc Treib
2016/04/19 16:18:44
Alright. Done.
| |
| 99 exploded.minute = 1; | |
| 100 exploded.second = 0; | |
| 101 exploded.millisecond = 0; | |
| 102 base::Time reschedule = base::Time::FromLocalExploded(exploded); | |
| 103 if (next_day) | |
| 104 reschedule += base::TimeDelta::FromDays(1); | |
| 105 | |
| 106 return reschedule - now; | |
| 107 } | |
| 108 | |
| 70 // Extracts the hosts from |suggestions| and returns them in a set. | 109 // Extracts the hosts from |suggestions| and returns them in a set. |
| 71 std::set<std::string> GetSuggestionsHosts( | 110 std::set<std::string> GetSuggestionsHosts( |
| 72 const SuggestionsProfile& suggestions) { | 111 const SuggestionsProfile& suggestions) { |
| 73 std::set<std::string> hosts; | 112 std::set<std::string> hosts; |
| 74 for (int i = 0; i < suggestions.suggestions_size(); ++i) { | 113 for (int i = 0; i < suggestions.suggestions_size(); ++i) { |
| 75 const ChromeSuggestion& suggestion = suggestions.suggestions(i); | 114 const ChromeSuggestion& suggestion = suggestions.suggestions(i); |
| 76 GURL url(suggestion.url()); | 115 GURL url(suggestion.url()); |
| 77 if (url.is_valid()) | 116 if (url.is_valid()) |
| 78 hosts.insert(url.host()); | 117 hosts.insert(url.host()); |
| 79 } | 118 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 } // namespace | 156 } // namespace |
| 118 | 157 |
| 119 NTPSnippetsService::NTPSnippetsService( | 158 NTPSnippetsService::NTPSnippetsService( |
| 120 PrefService* pref_service, | 159 PrefService* pref_service, |
| 121 SuggestionsService* suggestions_service, | 160 SuggestionsService* suggestions_service, |
| 122 scoped_refptr<base::SequencedTaskRunner> file_task_runner, | 161 scoped_refptr<base::SequencedTaskRunner> file_task_runner, |
| 123 const std::string& application_language_code, | 162 const std::string& application_language_code, |
| 124 NTPSnippetsScheduler* scheduler, | 163 NTPSnippetsScheduler* scheduler, |
| 125 scoped_ptr<NTPSnippetsFetcher> snippets_fetcher, | 164 scoped_ptr<NTPSnippetsFetcher> snippets_fetcher, |
| 126 const ParseJSONCallback& parse_json_callback) | 165 const ParseJSONCallback& parse_json_callback) |
| 127 : pref_service_(pref_service), | 166 : enabled_(false), |
| 167 pref_service_(pref_service), | |
| 128 suggestions_service_(suggestions_service), | 168 suggestions_service_(suggestions_service), |
| 129 file_task_runner_(file_task_runner), | 169 file_task_runner_(file_task_runner), |
| 130 application_language_code_(application_language_code), | 170 application_language_code_(application_language_code), |
| 131 scheduler_(scheduler), | 171 scheduler_(scheduler), |
| 132 snippets_fetcher_(std::move(snippets_fetcher)), | 172 snippets_fetcher_(std::move(snippets_fetcher)), |
| 133 parse_json_callback_(parse_json_callback), | 173 parse_json_callback_(parse_json_callback), |
| 134 weak_ptr_factory_(this) { | 174 weak_ptr_factory_(this) { |
| 135 snippets_fetcher_subscription_ = snippets_fetcher_->AddCallback(base::Bind( | 175 snippets_fetcher_subscription_ = snippets_fetcher_->AddCallback(base::Bind( |
| 136 &NTPSnippetsService::OnSnippetsDownloaded, base::Unretained(this))); | 176 &NTPSnippetsService::OnSnippetsDownloaded, base::Unretained(this))); |
| 137 } | 177 } |
| 138 | 178 |
| 139 NTPSnippetsService::~NTPSnippetsService() {} | 179 NTPSnippetsService::~NTPSnippetsService() {} |
| 140 | 180 |
| 141 // static | 181 // static |
| 142 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { | 182 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { |
| 143 registry->RegisterListPref(prefs::kSnippets); | 183 registry->RegisterListPref(prefs::kSnippets); |
| 144 registry->RegisterListPref(prefs::kDiscardedSnippets); | 184 registry->RegisterListPref(prefs::kDiscardedSnippets); |
| 145 registry->RegisterListPref(prefs::kSnippetHosts); | 185 registry->RegisterListPref(prefs::kSnippetHosts); |
| 146 } | 186 } |
| 147 | 187 |
| 148 void NTPSnippetsService::Init(bool enabled) { | 188 void NTPSnippetsService::Init(bool enabled) { |
| 149 if (enabled) { | 189 enabled_ = enabled; |
| 190 if (enabled_) { | |
| 150 // |suggestions_service_| can be null in tests. | 191 // |suggestions_service_| can be null in tests. |
| 151 if (suggestions_service_) { | 192 if (suggestions_service_) { |
| 152 suggestions_service_subscription_ = suggestions_service_->AddCallback( | 193 suggestions_service_subscription_ = suggestions_service_->AddCallback( |
| 153 base::Bind(&NTPSnippetsService::OnSuggestionsChanged, | 194 base::Bind(&NTPSnippetsService::OnSuggestionsChanged, |
| 154 base::Unretained(this))); | 195 base::Unretained(this))); |
| 155 } | 196 } |
| 156 | 197 |
| 157 // Get any existing snippets immediately from prefs. | 198 // Get any existing snippets immediately from prefs. |
| 158 LoadDiscardedSnippetsFromPrefs(); | 199 LoadDiscardedSnippetsFromPrefs(); |
| 159 LoadSnippetsFromPrefs(); | 200 LoadSnippetsFromPrefs(); |
| 160 | 201 |
| 161 // If we don't have any snippets yet, start a fetch. | 202 // If we don't have any snippets yet, start a fetch. |
| 162 if (snippets_.empty()) | 203 if (snippets_.empty()) |
| 163 FetchSnippets(); | 204 FetchSnippets(); |
| 164 } | 205 } |
| 165 | 206 |
| 166 // The scheduler only exists on Android so far, it's null on other platforms. | 207 RescheduleFetching(); |
| 167 if (!scheduler_) | |
| 168 return; | |
| 169 | |
| 170 if (enabled) { | |
| 171 scheduler_->Schedule(GetFetchingIntervalWifiCharging(), | |
| 172 GetFetchingIntervalWifi(), | |
| 173 GetFetchingIntervalFallback()); | |
| 174 } else { | |
| 175 scheduler_->Unschedule(); | |
| 176 } | |
| 177 } | 208 } |
| 178 | 209 |
| 179 void NTPSnippetsService::Shutdown() { | 210 void NTPSnippetsService::Shutdown() { |
| 180 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | 211 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
| 181 NTPSnippetsServiceShutdown()); | 212 NTPSnippetsServiceShutdown()); |
| 213 enabled_ = false; | |
| 182 } | 214 } |
| 183 | 215 |
| 184 void NTPSnippetsService::FetchSnippets() { | 216 void NTPSnippetsService::FetchSnippets() { |
| 185 // |suggestions_service_| can be null in tests. | 217 // |suggestions_service_| can be null in tests. |
| 186 if (!suggestions_service_) | 218 if (!suggestions_service_) |
| 187 return; | 219 return; |
| 188 | 220 |
| 189 FetchSnippetsImpl(GetSuggestionsHosts( | 221 FetchSnippetsImpl(GetSuggestionsHosts( |
| 190 suggestions_service_->GetSuggestionsDataFromCache())); | 222 suggestions_service_->GetSuggestionsDataFromCache())); |
| 191 } | 223 } |
| 192 | 224 |
| 193 bool NTPSnippetsService::DiscardSnippet(const GURL& url) { | 225 bool NTPSnippetsService::DiscardSnippet(const GURL& url) { |
| 194 auto it = std::find_if(snippets_.begin(), snippets_.end(), | 226 auto it = std::find_if(snippets_.begin(), snippets_.end(), |
| 195 [&url](const scoped_ptr<NTPSnippet>& snippet) { | 227 [&url](const scoped_ptr<NTPSnippet>& snippet) { |
| 196 return snippet->url() == url; | 228 return snippet->url() == url; |
| 197 }); | 229 }); |
| 198 if (it == snippets_.end()) | 230 if (it == snippets_.end()) |
| 199 return false; | 231 return false; |
| 200 discarded_snippets_.push_back(std::move(*it)); | 232 discarded_snippets_.push_back(std::move(*it)); |
| 201 snippets_.erase(it); | 233 snippets_.erase(it); |
| 202 StoreDiscardedSnippetsToPrefs(); | 234 StoreDiscardedSnippetsToPrefs(); |
| 203 StoreSnippetsToPrefs(); | 235 StoreSnippetsToPrefs(); |
| 204 return true; | 236 return true; |
| 205 } | 237 } |
| 206 | 238 |
| 239 void NTPSnippetsService::RescheduleFetching() { | |
| 240 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 241 if (!scheduler_) | |
| 242 return; | |
| 243 | |
| 244 if (enabled_) { | |
| 245 base::Time now = base::Time::Now(); | |
| 246 scheduler_->Schedule( | |
| 247 GetFetchingIntervalWifiCharging(), GetFetchingIntervalWifi(now), | |
| 248 GetFetchingIntervalFallback(), GetRescheduleDelay(now)); | |
| 249 } else { | |
| 250 scheduler_->Unschedule(); | |
| 251 } | |
| 252 } | |
| 253 | |
| 207 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { | 254 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { |
| 208 observers_.AddObserver(observer); | 255 observers_.AddObserver(observer); |
| 209 observer->NTPSnippetsServiceLoaded(); | 256 observer->NTPSnippetsServiceLoaded(); |
| 210 } | 257 } |
| 211 | 258 |
| 212 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { | 259 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { |
| 213 observers_.RemoveObserver(observer); | 260 observers_.RemoveObserver(observer); |
| 214 } | 261 } |
| 215 | 262 |
| 216 void NTPSnippetsService::OnSuggestionsChanged( | 263 void NTPSnippetsService::OnSuggestionsChanged( |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 if (snippet->expiry_date() < next_expiry) | 449 if (snippet->expiry_date() < next_expiry) |
| 403 next_expiry = snippet->expiry_date(); | 450 next_expiry = snippet->expiry_date(); |
| 404 } | 451 } |
| 405 DCHECK_GT(next_expiry, expiry); | 452 DCHECK_GT(next_expiry, expiry); |
| 406 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, | 453 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, |
| 407 base::Bind(&NTPSnippetsService::RemoveExpiredSnippets, | 454 base::Bind(&NTPSnippetsService::RemoveExpiredSnippets, |
| 408 base::Unretained(this))); | 455 base::Unretained(this))); |
| 409 } | 456 } |
| 410 | 457 |
| 411 } // namespace ntp_snippets | 458 } // namespace ntp_snippets |
| OLD | NEW |