Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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/remote/scheduling_remote_suggestions_provider. h" | 5 #include "components/ntp_snippets/remote/scheduling_remote_suggestions_provider. h" |
| 6 | 6 |
| 7 #include <random> | |
| 7 #include <string> | 8 #include <string> |
| 8 #include <utility> | 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/time/default_clock.h" | |
| 11 #include "components/ntp_snippets/features.h" | 13 #include "components/ntp_snippets/features.h" |
| 12 #include "components/ntp_snippets/pref_names.h" | 14 #include "components/ntp_snippets/pref_names.h" |
| 13 #include "components/ntp_snippets/remote/persistent_scheduler.h" | 15 #include "components/ntp_snippets/remote/persistent_scheduler.h" |
| 14 #include "components/ntp_snippets/status.h" | 16 #include "components/ntp_snippets/status.h" |
| 15 #include "components/ntp_snippets/user_classifier.h" | 17 #include "components/ntp_snippets/user_classifier.h" |
| 16 #include "components/prefs/pref_registry_simple.h" | 18 #include "components/prefs/pref_registry_simple.h" |
| 17 #include "components/prefs/pref_service.h" | 19 #include "components/prefs/pref_service.h" |
| 18 #include "components/variations/variations_associated_data.h" | 20 #include "components/variations/variations_associated_data.h" |
| 19 | 21 |
| 20 namespace ntp_snippets { | 22 namespace ntp_snippets { |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 26 enum class FetchingInterval { | |
| 27 PERSISTENT_FALLBACK, | |
| 28 PERSISTENT_WIFI, | |
| 29 SOFT_ON_USAGE_EVENT, | |
| 30 COUNT | |
| 31 }; | |
| 32 | |
| 24 // Default values for fetching intervals, fallback and wifi. | 33 // Default values for fetching intervals, fallback and wifi. |
| 25 const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0}; | 34 const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0, 12.0}; |
| 26 const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0}; | 35 const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0, 2.0}; |
| 27 const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0}; | 36 const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0, |
| 37 2.0}; | |
| 28 | 38 |
| 29 // Variation parameters than can the default fetching intervals. | 39 // Variation parameters than can the default fetching intervals. |
| 30 const char* kFetchingIntervalParamNameRareNtpUser[] = { | 40 const char* kFetchingIntervalParamNameRareNtpUser[] = { |
| 31 "fetching_interval_hours-fallback-rare_ntp_user", | 41 "fetching_interval_hours-fallback-rare_ntp_user", |
| 32 "fetching_interval_hours-wifi-rare_ntp_user"}; | 42 "fetching_interval_hours-wifi-rare_ntp_user", |
| 43 "soft_fetching_interval_hours-active-rare_ntp_user"}; | |
| 33 const char* kFetchingIntervalParamNameActiveNtpUser[] = { | 44 const char* kFetchingIntervalParamNameActiveNtpUser[] = { |
| 34 "fetching_interval_hours-fallback-active_ntp_user", | 45 "fetching_interval_hours-fallback-active_ntp_user", |
| 35 "fetching_interval_hours-wifi-active_ntp_user"}; | 46 "fetching_interval_hours-wifi-active_ntp_user", |
| 47 "soft_fetching_interval_hours-active-active_ntp_user"}; | |
| 36 const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = { | 48 const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = { |
| 37 "fetching_interval_hours-fallback-active_suggestions_consumer", | 49 "fetching_interval_hours-fallback-active_suggestions_consumer", |
| 38 "fetching_interval_hours-wifi-active_suggestions_consumer"}; | 50 "fetching_interval_hours-wifi-active_suggestions_consumer", |
| 51 "soft_fetching_interval_hours-active-active_suggestions_consumer"}; | |
| 39 | 52 |
| 40 base::TimeDelta GetDesiredUpdateInterval( | 53 static_assert( |
| 41 bool is_wifi, | 54 static_cast<unsigned int>(FetchingInterval::COUNT) == |
| 55 arraysize(kDefaultFetchingIntervalRareNtpUser) && | |
| 56 static_cast<unsigned int>(FetchingInterval::COUNT) == | |
| 57 arraysize(kDefaultFetchingIntervalActiveNtpUser) && | |
| 58 static_cast<unsigned int>(FetchingInterval::COUNT) == | |
| 59 arraysize(kDefaultFetchingIntervalActiveSuggestionsConsumer) && | |
| 60 static_cast<unsigned int>(FetchingInterval::COUNT) == | |
| 61 arraysize(kFetchingIntervalParamNameRareNtpUser) && | |
| 62 static_cast<unsigned int>(FetchingInterval::COUNT) == | |
| 63 arraysize(kFetchingIntervalParamNameActiveNtpUser) && | |
| 64 static_cast<unsigned int>(FetchingInterval::COUNT) == | |
| 65 arraysize(kFetchingIntervalParamNameActiveSuggestionsConsumer), | |
| 66 "Fill in all the info for fetching intervals."); | |
| 67 | |
| 68 base::TimeDelta GetDesiredFetchingInterval( | |
| 69 FetchingInterval interval, | |
| 42 UserClassifier::UserClass user_class) { | 70 UserClassifier::UserClass user_class) { |
| 43 double default_value_hours = 0.0; | 71 double default_value_hours = 0.0; |
| 44 | 72 |
| 45 const int index = is_wifi ? 1 : 0; | 73 DCHECK(interval != FetchingInterval::COUNT); |
| 74 const unsigned int index = static_cast<unsigned int>(interval); | |
| 75 DCHECK(index < arraysize(kDefaultFetchingIntervalRareNtpUser)); | |
| 76 | |
| 46 const char* param_name = nullptr; | 77 const char* param_name = nullptr; |
| 47 switch (user_class) { | 78 switch (user_class) { |
| 48 case UserClassifier::UserClass::RARE_NTP_USER: | 79 case UserClassifier::UserClass::RARE_NTP_USER: |
| 49 default_value_hours = kDefaultFetchingIntervalRareNtpUser[index]; | 80 default_value_hours = kDefaultFetchingIntervalRareNtpUser[index]; |
| 50 param_name = kFetchingIntervalParamNameRareNtpUser[index]; | 81 param_name = kFetchingIntervalParamNameRareNtpUser[index]; |
| 51 break; | 82 break; |
| 52 case UserClassifier::UserClass::ACTIVE_NTP_USER: | 83 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 53 default_value_hours = kDefaultFetchingIntervalActiveNtpUser[index]; | 84 default_value_hours = kDefaultFetchingIntervalActiveNtpUser[index]; |
| 54 param_name = kFetchingIntervalParamNameActiveNtpUser[index]; | 85 param_name = kFetchingIntervalParamNameActiveNtpUser[index]; |
| 55 break; | 86 break; |
| 56 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: | 87 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 57 default_value_hours = | 88 default_value_hours = |
| 58 kDefaultFetchingIntervalActiveSuggestionsConsumer[index]; | 89 kDefaultFetchingIntervalActiveSuggestionsConsumer[index]; |
| 59 param_name = kFetchingIntervalParamNameActiveSuggestionsConsumer[index]; | 90 param_name = kFetchingIntervalParamNameActiveSuggestionsConsumer[index]; |
| 60 break; | 91 break; |
| 61 } | 92 } |
| 62 | 93 |
| 63 double value_hours = variations::GetVariationParamByFeatureAsDouble( | 94 double value_hours = variations::GetVariationParamByFeatureAsDouble( |
| 64 ntp_snippets::kArticleSuggestionsFeature, param_name, | 95 ntp_snippets::kArticleSuggestionsFeature, param_name, |
| 65 default_value_hours); | 96 default_value_hours); |
| 66 | 97 |
| 67 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); | 98 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); |
| 68 } | 99 } |
| 69 | 100 |
| 70 } // namespace | 101 } // namespace |
| 71 | 102 |
| 72 struct SchedulingRemoteSuggestionsProvider::FetchingSchedule { | 103 // static |
| 73 base::TimeDelta interval_wifi; | 104 SchedulingRemoteSuggestionsProvider::FetchingSchedule |
| 74 base::TimeDelta interval_fallback; | 105 SchedulingRemoteSuggestionsProvider::FetchingSchedule::Empty() { |
| 106 return FetchingSchedule{base::TimeDelta(), base::TimeDelta(), | |
| 107 base::TimeDelta()}; | |
| 108 } | |
| 75 | 109 |
| 76 static FetchingSchedule Empty() { | 110 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator==( |
| 77 return FetchingSchedule{base::TimeDelta(), | 111 const FetchingSchedule& other) const { |
| 78 base::TimeDelta()}; | 112 return interval_persistent_wifi == other.interval_persistent_wifi && |
| 79 } | 113 interval_persistent_fallback == other.interval_persistent_fallback && |
| 114 interval_soft_on_usage_event == other.interval_soft_on_usage_event; | |
| 115 } | |
| 80 | 116 |
| 81 bool operator==(const FetchingSchedule& other) const { | 117 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator!=( |
| 82 return interval_wifi == other.interval_wifi && | 118 const FetchingSchedule& other) const { |
| 83 interval_fallback == other.interval_fallback; | 119 return !operator==(other); |
| 84 } | 120 } |
| 85 | 121 |
| 86 bool operator!=(const FetchingSchedule& other) const { | 122 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const { |
| 87 return !operator==(other); | 123 return interval_persistent_wifi.is_zero() && |
| 88 } | 124 interval_persistent_fallback.is_zero() && |
| 89 | 125 interval_soft_on_usage_event.is_zero(); |
| 90 bool is_empty() const { | 126 } |
| 91 return interval_wifi.is_zero() && interval_fallback.is_zero(); | |
| 92 } | |
| 93 }; | |
| 94 | 127 |
| 95 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( | 128 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( |
| 96 Observer* observer, | 129 Observer* observer, |
| 97 std::unique_ptr<RemoteSuggestionsProvider> provider, | 130 std::unique_ptr<RemoteSuggestionsProvider> provider, |
| 98 PersistentScheduler* persistent_scheduler, | 131 PersistentScheduler* persistent_scheduler, |
| 99 const UserClassifier* user_classifier, | 132 const UserClassifier* user_classifier, |
| 100 PrefService* pref_service) | 133 PrefService* pref_service) |
| 101 : RemoteSuggestionsProvider(observer), | 134 : RemoteSuggestionsProvider(observer), |
| 102 RemoteSuggestionsScheduler(), | 135 RemoteSuggestionsScheduler(), |
| 103 provider_(std::move(provider)), | 136 provider_(std::move(provider)), |
| 104 persistent_scheduler_(persistent_scheduler), | 137 persistent_scheduler_(persistent_scheduler), |
| 138 background_fetch_in_progress_(false), | |
| 105 user_classifier_(user_classifier), | 139 user_classifier_(user_classifier), |
| 106 pref_service_(pref_service) { | 140 pref_service_(pref_service), |
| 141 clock_(base::MakeUnique<base::DefaultClock>()) { | |
| 107 DCHECK(user_classifier); | 142 DCHECK(user_classifier); |
| 108 DCHECK(pref_service); | 143 DCHECK(pref_service); |
| 109 | 144 |
| 145 LoadLastFetchingSchedule(); | |
| 146 | |
| 110 provider_->SetProviderStatusCallback( | 147 provider_->SetProviderStatusCallback( |
| 111 base::MakeUnique<RemoteSuggestionsProvider::ProviderStatusCallback>( | 148 base::MakeUnique<RemoteSuggestionsProvider::ProviderStatusCallback>( |
| 112 base::BindRepeating( | 149 base::BindRepeating( |
| 113 &SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged, | 150 &SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged, |
| 114 base::Unretained(this)))); | 151 base::Unretained(this)))); |
| 115 } | 152 } |
| 116 | 153 |
| 117 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = | 154 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = |
| 118 default; | 155 default; |
| 119 | 156 |
| 120 // static | 157 // static |
| 121 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( | 158 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( |
| 122 PrefRegistrySimple* registry) { | 159 PrefRegistrySimple* registry) { |
| 123 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0); | 160 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); |
| 124 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback, | 161 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, |
| 125 0); | 162 0); |
| 163 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, | |
| 164 0); | |
| 165 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); | |
| 126 } | 166 } |
| 127 | 167 |
| 128 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { | 168 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { |
|
tschumann
2017/01/04 10:43:52
ultimatively, this method should go away, right? (
jkrcal
2017/01/04 14:19:03
No. This needs to be called when Chrome is updated
tschumann
2017/01/04 15:15:24
I see. Maybe we should rename this function then t
| |
| 129 // Force the reschedule by stopping and starting it again. | 169 // Force the reschedule by stopping and starting it again. |
| 130 StopScheduling(); | 170 StopScheduling(); |
| 131 StartScheduling(); | 171 StartScheduling(); |
| 132 } | 172 } |
| 133 | 173 |
| 134 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { | 174 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { |
| 135 provider_->RefetchInTheBackground( | 175 if (schedule_.is_empty()) { |
|
tschumann
2017/01/04 10:43:52
can we wrap this in a helper method BackgroundFetc
jkrcal
2017/01/04 14:19:03
Done.
| |
| 136 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>( | 176 return; // Persistent background fetches are switched off. |
| 137 base::Bind(&SchedulingRemoteSuggestionsProvider::OnFetchCompleted, | 177 } |
| 138 base::Unretained(this)))); | 178 |
| 179 RefetchInTheBackground(/*callback=*/nullptr); | |
| 139 } | 180 } |
| 140 | 181 |
| 141 void SchedulingRemoteSuggestionsProvider::OnBrowserStartup() { | 182 void SchedulingRemoteSuggestionsProvider::OnBrowserStartup() { |
| 142 // TODO(jkrcal): Implement. | 183 // TODO(jkrcal): Implement. |
| 143 } | 184 } |
| 144 | 185 |
| 145 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { | 186 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { |
| 146 // TODO(jkrcal): Implement. | 187 if (schedule_.is_empty()) { |
| 188 return; // Soft background fetches are switched off. | |
| 189 } | |
| 190 | |
| 191 if (!ShouldRefetchInTheBackgroundNow()) { | |
| 192 return; // Not enough time has elapsed since last fetch attempt. | |
|
tschumann
2017/01/04 10:43:52
nit: let's remove this comment as it duplicates lo
jkrcal
2017/01/04 14:19:03
Good point, done.
| |
| 193 } | |
| 194 | |
| 195 RefetchInTheBackground(/*callback=*/nullptr); | |
| 147 } | 196 } |
| 148 | 197 |
| 149 void SchedulingRemoteSuggestionsProvider::SetProviderStatusCallback( | 198 void SchedulingRemoteSuggestionsProvider::SetProviderStatusCallback( |
| 150 std::unique_ptr<ProviderStatusCallback> callback) { | 199 std::unique_ptr<ProviderStatusCallback> callback) { |
| 151 provider_->SetProviderStatusCallback(std::move(callback)); | 200 provider_->SetProviderStatusCallback(std::move(callback)); |
| 152 } | 201 } |
| 153 | 202 |
| 154 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( | 203 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( |
| 155 std::unique_ptr<FetchStatusCallback> callback) { | 204 std::unique_ptr<FetchStatusCallback> callback) { |
| 156 provider_->RefetchInTheBackground(std::move(callback)); | 205 if (background_fetch_in_progress_) { |
| 206 if (callback) { | |
| 207 callback->Run( | |
| 208 Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress")); | |
| 209 } | |
| 210 return; | |
| 211 } | |
| 212 | |
| 213 RemoteSuggestionsProvider::FetchStatusCallback wrapper_callback = base::Bind( | |
| 214 &SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished, | |
| 215 base::Unretained(this), base::Passed(&callback)); | |
| 216 provider_->RefetchInTheBackground( | |
| 217 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>( | |
| 218 std::move(wrapper_callback))); | |
| 157 } | 219 } |
| 158 | 220 |
| 159 const NTPSnippetsFetcher* SchedulingRemoteSuggestionsProvider:: | 221 const NTPSnippetsFetcher* SchedulingRemoteSuggestionsProvider:: |
| 160 snippets_fetcher_for_testing_and_debugging() const { | 222 snippets_fetcher_for_testing_and_debugging() const { |
| 161 return provider_->snippets_fetcher_for_testing_and_debugging(); | 223 return provider_->snippets_fetcher_for_testing_and_debugging(); |
| 162 } | 224 } |
| 163 | 225 |
| 164 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus( | 226 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus( |
| 165 Category category) { | 227 Category category) { |
| 166 return provider_->GetCategoryStatus(category); | 228 return provider_->GetCategoryStatus(category); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 StartScheduling(); | 292 StartScheduling(); |
| 231 return; | 293 return; |
| 232 case RemoteSuggestionsProvider::ProviderStatus::INACTIVE: | 294 case RemoteSuggestionsProvider::ProviderStatus::INACTIVE: |
| 233 StopScheduling(); | 295 StopScheduling(); |
| 234 return; | 296 return; |
| 235 } | 297 } |
| 236 NOTREACHED(); | 298 NOTREACHED(); |
| 237 } | 299 } |
| 238 | 300 |
| 239 void SchedulingRemoteSuggestionsProvider::StartScheduling() { | 301 void SchedulingRemoteSuggestionsProvider::StartScheduling() { |
| 240 // The scheduler only exists on Android so far, it's null on other platforms. | 302 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); |
| 241 if (!persistent_scheduler_) { | 303 |
| 304 if (schedule_ == new_schedule) { | |
| 305 // Do not schedule if nothing has changed; | |
| 242 return; | 306 return; |
| 243 } | 307 } |
| 244 | 308 |
| 245 FetchingSchedule last_schedule = GetLastFetchingSchedule(); | 309 schedule_ = new_schedule; |
| 246 FetchingSchedule schedule = GetDesiredFetchingSchedule(); | 310 StoreFetchingSchedule(); |
| 311 ApplyFetchingSchedule(/*also_apply_persistent_schedule=*/true); | |
| 312 } | |
| 247 | 313 |
| 248 // Reset the schedule only if the parameters have changed. | 314 void SchedulingRemoteSuggestionsProvider::StopScheduling() { |
| 249 if (last_schedule != schedule) { | 315 if (schedule_.is_empty()) { |
| 250 ApplyFetchingSchedule(schedule); | 316 // Do not unschedule if already switched off. |
| 317 return; | |
| 318 } | |
| 319 | |
| 320 schedule_ = FetchingSchedule::Empty(); | |
| 321 StoreFetchingSchedule(); | |
| 322 ApplyFetchingSchedule(/*also_apply_persistent_schedule=*/true); | |
| 323 } | |
| 324 | |
| 325 void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule( | |
|
tschumann
2017/01/04 10:43:52
Rename to ApplyPersistentFetchingSchedule and get
jkrcal
2017/01/04 14:19:03
Done.
| |
| 326 bool also_apply_persistent_schedule) { | |
| 327 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 328 if (persistent_scheduler_ && also_apply_persistent_schedule) { | |
| 329 if (schedule_.is_empty()) { | |
| 330 persistent_scheduler_->Unschedule(); | |
| 331 } else { | |
| 332 persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi, | |
| 333 schedule_.interval_persistent_fallback); | |
| 334 } | |
| 251 } | 335 } |
| 252 } | 336 } |
| 253 | 337 |
| 254 void SchedulingRemoteSuggestionsProvider::StopScheduling() { | |
| 255 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 256 if (!persistent_scheduler_) { | |
| 257 return; | |
| 258 } | |
| 259 | |
| 260 // Do not unschedule if already switched off | |
| 261 FetchingSchedule last_schedule = GetLastFetchingSchedule(); | |
| 262 if (last_schedule.is_empty()) { | |
| 263 return; | |
| 264 } | |
| 265 | |
| 266 persistent_scheduler_->Unschedule(); | |
| 267 | |
| 268 StoreLastFetchingSchedule(FetchingSchedule::Empty()); | |
| 269 } | |
| 270 | |
| 271 void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule( | |
| 272 const FetchingSchedule& schedule) { | |
| 273 persistent_scheduler_->Schedule(schedule.interval_wifi, | |
| 274 schedule.interval_fallback); | |
| 275 | |
| 276 StoreLastFetchingSchedule(schedule); | |
| 277 } | |
| 278 | |
| 279 SchedulingRemoteSuggestionsProvider::FetchingSchedule | 338 SchedulingRemoteSuggestionsProvider::FetchingSchedule |
| 280 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const { | 339 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const { |
| 281 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); | 340 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); |
| 282 | 341 |
| 283 FetchingSchedule schedule; | 342 FetchingSchedule schedule; |
| 284 schedule.interval_wifi = | 343 schedule.interval_persistent_wifi = |
| 285 GetDesiredUpdateInterval(/*is_wifi=*/true, user_class); | 344 GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class); |
| 286 schedule.interval_fallback = | 345 schedule.interval_persistent_fallback = GetDesiredFetchingInterval( |
| 287 GetDesiredUpdateInterval(/*is_wifi=*/false, user_class); | 346 FetchingInterval::PERSISTENT_FALLBACK, user_class); |
| 347 schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval( | |
| 348 FetchingInterval::SOFT_ON_USAGE_EVENT, user_class); | |
| 349 | |
| 288 return schedule; | 350 return schedule; |
| 289 } | 351 } |
| 290 | 352 |
| 291 SchedulingRemoteSuggestionsProvider::FetchingSchedule | 353 void SchedulingRemoteSuggestionsProvider::LoadLastFetchingSchedule() { |
| 292 SchedulingRemoteSuggestionsProvider::GetLastFetchingSchedule() const { | 354 schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue( |
| 293 FetchingSchedule schedule; | 355 pref_service_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi)); |
| 294 schedule.interval_wifi = base::TimeDelta::FromInternalValue( | 356 schedule_.interval_persistent_fallback = |
| 295 pref_service_->GetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi)); | |
| 296 schedule.interval_fallback = | |
| 297 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( | 357 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( |
| 298 prefs::kSnippetBackgroundFetchingIntervalFallback)); | 358 prefs::kSnippetPersistentFetchingIntervalFallback)); |
| 299 return schedule; | 359 schedule_.interval_soft_on_usage_event = base::TimeDelta::FromInternalValue( |
| 360 pref_service_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnUsageEvent)); | |
| 300 } | 361 } |
| 301 | 362 |
| 302 void SchedulingRemoteSuggestionsProvider::StoreLastFetchingSchedule( | 363 void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() { |
| 303 const FetchingSchedule& schedule) { | 364 pref_service_->SetInt64(prefs::kSnippetPersistentFetchingIntervalWifi, |
| 365 schedule_.interval_persistent_wifi.ToInternalValue()); | |
| 304 pref_service_->SetInt64( | 366 pref_service_->SetInt64( |
| 305 prefs::kSnippetBackgroundFetchingIntervalWifi, | 367 prefs::kSnippetPersistentFetchingIntervalFallback, |
| 306 schedule.interval_wifi.ToInternalValue()); | 368 schedule_.interval_persistent_fallback.ToInternalValue()); |
| 307 pref_service_->SetInt64( | 369 pref_service_->SetInt64( |
| 308 prefs::kSnippetBackgroundFetchingIntervalFallback, | 370 prefs::kSnippetSoftFetchingIntervalOnUsageEvent, |
| 309 schedule.interval_fallback.ToInternalValue()); | 371 schedule_.interval_soft_on_usage_event.ToInternalValue()); |
| 372 } | |
| 373 | |
| 374 bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow() { | |
| 375 base::Time first_allowed_fetch_time = | |
| 376 base::Time::FromInternalValue( | |
| 377 pref_service_->GetInt64(prefs::kSnippetLastFetchAttempt)) + | |
| 378 schedule_.interval_soft_on_usage_event; | |
| 379 return first_allowed_fetch_time <= clock_->Now(); | |
| 310 } | 380 } |
| 311 | 381 |
| 312 void SchedulingRemoteSuggestionsProvider::FetchFinished( | 382 void SchedulingRemoteSuggestionsProvider::FetchFinished( |
| 313 const FetchDoneCallback& callback, | 383 const FetchDoneCallback& callback, |
| 314 Status status_code, | 384 Status fetch_status, |
| 315 std::vector<ContentSuggestion> suggestions) { | 385 std::vector<ContentSuggestion> suggestions) { |
| 316 OnFetchCompleted(status_code); | 386 OnFetchCompleted(fetch_status); |
| 317 callback.Run(status_code, std::move(suggestions)); | 387 callback.Run(fetch_status, std::move(suggestions)); |
|
tschumann
2017/01/04 10:43:52
should we also check for the empty callback?
jkrcal
2017/01/04 14:19:03
Done.
| |
| 388 } | |
| 389 | |
| 390 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished( | |
| 391 std::unique_ptr<FetchStatusCallback> callback, | |
| 392 Status fetch_status) { | |
| 393 background_fetch_in_progress_ = false; | |
| 394 OnFetchCompleted(fetch_status); | |
| 395 | |
| 396 if (callback) { | |
| 397 callback->Run(fetch_status); | |
| 398 } | |
| 318 } | 399 } |
| 319 | 400 |
| 320 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted( | 401 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted( |
| 321 Status fetch_status) { | 402 Status fetch_status) { |
| 322 // The scheduler only exists on Android so far, it's null on other platforms. | 403 pref_service_->SetInt64(prefs::kSnippetLastFetchAttempt, |
| 323 if (!persistent_scheduler_) { | 404 clock_->Now().ToInternalValue()); |
| 324 return; | |
| 325 } | |
| 326 | 405 |
| 327 if (fetch_status.code != StatusCode::SUCCESS) { | 406 // Reschedule after a fetch. The persistent schedule is applied only after a |
| 328 return; | 407 // successful fetch. After a failed fetch, we want to keep the previous |
| 329 } | 408 // persistent schedule intact so that we eventually get a persistent fallback |
| 330 | 409 // fetch (if the wifi persistent fetches keep failing). |
| 331 // Reschedule after a successful fetch. This resets all currently scheduled | 410 ApplyFetchingSchedule(/*also_apply_persistent_schedule=*/fetch_status.code == |
| 332 // fetches, to make sure the fallback interval triggers only if no wifi fetch | 411 StatusCode::SUCCESS); |
| 333 // succeeded, and also that we don't do a background fetch immediately after | |
| 334 // a user-initiated one. | |
| 335 ApplyFetchingSchedule(GetLastFetchingSchedule()); | |
| 336 } | 412 } |
| 337 | 413 |
| 338 } // namespace ntp_snippets | 414 } // namespace ntp_snippets |
| OLD | NEW |