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 <random> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
88 arraysize(kFetchingIntervalParamNameActiveSuggestionsConsumer), | 88 arraysize(kFetchingIntervalParamNameActiveSuggestionsConsumer), |
89 "Fill in all the info for fetching intervals."); | 89 "Fill in all the info for fetching intervals."); |
90 | 90 |
91 const char* kTriggerTypeNames[] = {"persistent_scheduler_wake_up", "ntp_opened", | 91 const char* kTriggerTypeNames[] = {"persistent_scheduler_wake_up", "ntp_opened", |
92 "browser_foregrounded", | 92 "browser_foregrounded", |
93 "browser_cold_start"}; | 93 "browser_cold_start"}; |
94 | 94 |
95 const char* kTriggerTypesParamName = "scheduler_trigger_types"; | 95 const char* kTriggerTypesParamName = "scheduler_trigger_types"; |
96 const char* kTriggerTypesParamValueForEmptyList = "-"; | 96 const char* kTriggerTypesParamValueForEmptyList = "-"; |
97 | 97 |
98 const int kBlockBackgroundFetchesMinutesAfterClearingHistory = 30; | |
99 | |
98 // Returns the time interval to use for scheduling remote suggestion fetches for | 100 // Returns the time interval to use for scheduling remote suggestion fetches for |
99 // the given interval and user_class. | 101 // the given interval and user_class. |
100 base::TimeDelta GetDesiredFetchingInterval( | 102 base::TimeDelta GetDesiredFetchingInterval( |
101 FetchingInterval interval, | 103 FetchingInterval interval, |
102 UserClassifier::UserClass user_class) { | 104 UserClassifier::UserClass user_class) { |
103 DCHECK(interval != FetchingInterval::COUNT); | 105 DCHECK(interval != FetchingInterval::COUNT); |
104 const unsigned int index = static_cast<unsigned int>(interval); | 106 const unsigned int index = static_cast<unsigned int>(interval); |
105 DCHECK(index < arraysize(kDefaultFetchingIntervalHoursRareNtpUser)); | 107 DCHECK(index < arraysize(kDefaultFetchingIntervalHoursRareNtpUser)); |
106 | 108 |
107 double default_value_hours = 0.0; | 109 double default_value_hours = 0.0; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 background_fetch_in_progress_(false), | 187 background_fetch_in_progress_(false), |
186 user_classifier_(user_classifier), | 188 user_classifier_(user_classifier), |
187 pref_service_(pref_service), | 189 pref_service_(pref_service), |
188 clock_(std::move(clock)), | 190 clock_(std::move(clock)), |
189 enabled_triggers_(GetEnabledTriggerTypes()) { | 191 enabled_triggers_(GetEnabledTriggerTypes()) { |
190 DCHECK(user_classifier); | 192 DCHECK(user_classifier); |
191 DCHECK(pref_service); | 193 DCHECK(pref_service); |
192 | 194 |
193 LoadLastFetchingSchedule(); | 195 LoadLastFetchingSchedule(); |
194 | 196 |
195 provider_->SetProviderStatusCallback( | 197 provider_->SetRemoteSuggestionsScheduler(this); |
196 base::MakeUnique<RemoteSuggestionsProvider::ProviderStatusCallback>( | |
197 base::BindRepeating( | |
198 &SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged, | |
199 base::Unretained(this)))); | |
200 } | 198 } |
201 | 199 |
202 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = | 200 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = |
203 default; | 201 default; |
204 | 202 |
205 // static | 203 // static |
206 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( | 204 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( |
207 PrefRegistrySimple* registry) { | 205 PrefRegistrySimple* registry) { |
208 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); | 206 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); |
209 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, | 207 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, |
210 0); | 208 0); |
211 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, | 209 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, |
212 0); | 210 0); |
213 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); | 211 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); |
214 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened, | 212 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened, |
215 0); | 213 0); |
216 } | 214 } |
217 | 215 |
216 void SchedulingRemoteSuggestionsProvider::OnProviderActivated() { | |
217 StartScheduling(); | |
218 } | |
219 | |
220 void SchedulingRemoteSuggestionsProvider::OnProviderInactivated() { | |
221 StopScheduling(); | |
222 } | |
223 | |
224 void SchedulingRemoteSuggestionsProvider::OnSuggestionsCleared() { | |
225 // There are no suggestions, be as eager to fetch as possible. | |
226 ClearLastFetchAttemptTime(); | |
227 } | |
228 | |
229 void SchedulingRemoteSuggestionsProvider::OnHistoryCleared() { | |
230 // Due to privacy, we should not fetch for a while (unless the user explicitly | |
231 // asks for new suggestions) do give sync the time to propagate the changes in | |
232 // history to the server. | |
233 background_fetches_allowed_after_ = | |
234 clock_->Now() + base::TimeDelta::FromMinutes( | |
235 kBlockBackgroundFetchesMinutesAfterClearingHistory); | |
236 // After that time elapses, we should fetch as soon as possible. | |
237 ClearLastFetchAttemptTime(); | |
238 } | |
239 | |
218 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { | 240 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { |
219 // Force the reschedule by stopping and starting it again. | 241 // Force the reschedule by stopping and starting it again. |
220 StopScheduling(); | 242 StopScheduling(); |
221 StartScheduling(); | 243 StartScheduling(); |
222 } | 244 } |
223 | 245 |
224 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { | 246 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { |
225 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); | 247 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); |
226 } | 248 } |
227 | 249 |
(...skipping 18 matching lines...) Expand all Loading... | |
246 } | 268 } |
247 | 269 |
248 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { | 270 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { |
249 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) { | 271 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) { |
250 return; | 272 return; |
251 } | 273 } |
252 | 274 |
253 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); | 275 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); |
254 } | 276 } |
255 | 277 |
256 void SchedulingRemoteSuggestionsProvider::SetProviderStatusCallback( | 278 void SchedulingRemoteSuggestionsProvider::SetRemoteSuggestionsScheduler( |
257 std::unique_ptr<ProviderStatusCallback> callback) { | 279 RemoteSuggestionsScheduler* scheduler) { |
258 provider_->SetProviderStatusCallback(std::move(callback)); | 280 provider_->SetRemoteSuggestionsScheduler(scheduler); |
259 } | 281 } |
260 | 282 |
261 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( | 283 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( |
262 std::unique_ptr<FetchStatusCallback> callback) { | 284 std::unique_ptr<FetchStatusCallback> callback) { |
263 if (background_fetch_in_progress_) { | 285 if (background_fetch_in_progress_) { |
264 if (callback) { | 286 if (callback) { |
265 callback->Run( | 287 callback->Run( |
266 Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress")); | 288 Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress")); |
267 } | 289 } |
268 return; | 290 return; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 Category category, | 359 Category category, |
338 const DismissedSuggestionsCallback& callback) { | 360 const DismissedSuggestionsCallback& callback) { |
339 provider_->GetDismissedSuggestionsForDebugging(category, callback); | 361 provider_->GetDismissedSuggestionsForDebugging(category, callback); |
340 } | 362 } |
341 | 363 |
342 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging( | 364 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging( |
343 Category category) { | 365 Category category) { |
344 provider_->ClearDismissedSuggestionsForDebugging(category); | 366 provider_->ClearDismissedSuggestionsForDebugging(category); |
345 } | 367 } |
346 | 368 |
347 void SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged( | |
348 RemoteSuggestionsProvider::ProviderStatus status) { | |
349 switch (status) { | |
350 case RemoteSuggestionsProvider::ProviderStatus::ACTIVE: | |
351 StartScheduling(); | |
352 return; | |
353 case RemoteSuggestionsProvider::ProviderStatus::INACTIVE: | |
354 StopScheduling(); | |
355 return; | |
356 } | |
357 NOTREACHED(); | |
358 } | |
359 | |
360 void SchedulingRemoteSuggestionsProvider::StartScheduling() { | 369 void SchedulingRemoteSuggestionsProvider::StartScheduling() { |
361 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); | 370 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); |
362 | 371 |
363 if (schedule_ == new_schedule) { | 372 if (schedule_ == new_schedule) { |
364 // Do not schedule if nothing has changed; | 373 // Do not schedule if nothing has changed; |
365 return; | 374 return; |
366 } | 375 } |
367 | 376 |
368 schedule_ = new_schedule; | 377 schedule_ = new_schedule; |
369 StoreFetchingSchedule(); | 378 StoreFetchingSchedule(); |
370 ApplyPersistentFetchingSchedule(); | 379 ApplyPersistentFetchingSchedule(); |
380 ClearLastFetchAttemptTime(); | |
tschumann
2017/02/22 20:46:04
This change is unexpected. Why is this needed now?
jkrcal
2017/02/23 12:20:13
Not a bug, not strictly needed. Okay, I remove it
| |
371 } | 381 } |
372 | 382 |
373 void SchedulingRemoteSuggestionsProvider::StopScheduling() { | 383 void SchedulingRemoteSuggestionsProvider::StopScheduling() { |
374 if (schedule_.is_empty()) { | 384 if (schedule_.is_empty()) { |
375 // Do not unschedule if already switched off. | 385 // Do not unschedule if already switched off. |
376 return; | 386 return; |
377 } | 387 } |
378 | 388 |
379 schedule_ = FetchingSchedule::Empty(); | 389 schedule_ = FetchingSchedule::Empty(); |
380 StoreFetchingSchedule(); | 390 StoreFetchingSchedule(); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 case TriggerType::BROWSER_FOREGROUNDED: | 472 case TriggerType::BROWSER_FOREGROUNDED: |
463 case TriggerType::BROWSER_COLD_START: | 473 case TriggerType::BROWSER_COLD_START: |
464 first_allowed_fetch_time = | 474 first_allowed_fetch_time = |
465 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event; | 475 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event; |
466 break; | 476 break; |
467 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP: | 477 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP: |
468 case TriggerType::COUNT: | 478 case TriggerType::COUNT: |
469 NOTREACHED(); | 479 NOTREACHED(); |
470 break; | 480 break; |
471 } | 481 } |
472 return first_allowed_fetch_time <= clock_->Now(); | 482 base::Time now = clock_->Now(); |
483 | |
484 return background_fetches_allowed_after_ <= now && | |
485 first_allowed_fetch_time <= now; | |
473 } | 486 } |
474 | 487 |
475 bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled( | 488 bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled( |
476 SchedulingRemoteSuggestionsProvider::TriggerType trigger) const { | 489 SchedulingRemoteSuggestionsProvider::TriggerType trigger) const { |
477 if (schedule_.is_empty()) { | 490 if (schedule_.is_empty()) { |
478 return true; // Background fetches are disabled in general. | 491 return true; // Background fetches are disabled in general. |
479 } | 492 } |
480 | 493 |
481 if (enabled_triggers_.count(trigger) == 0) { | 494 if (enabled_triggers_.count(trigger) == 0) { |
482 return true; // Background fetches for |trigger| are not enabled. | 495 return true; // Background fetches for |trigger| are not enabled. |
(...skipping 29 matching lines...) Expand all Loading... | |
512 // Reschedule after a fetch. The persistent schedule is applied only after a | 525 // Reschedule after a fetch. The persistent schedule is applied only after a |
513 // successful fetch. After a failed fetch, we want to keep the previous | 526 // successful fetch. After a failed fetch, we want to keep the previous |
514 // persistent schedule intact so that we eventually get a persistent | 527 // persistent schedule intact so that we eventually get a persistent |
515 // fallback fetch (if the wifi persistent fetches keep failing). | 528 // fallback fetch (if the wifi persistent fetches keep failing). |
516 if (fetch_status.code != StatusCode::SUCCESS) { | 529 if (fetch_status.code != StatusCode::SUCCESS) { |
517 return; | 530 return; |
518 } | 531 } |
519 ApplyPersistentFetchingSchedule(); | 532 ApplyPersistentFetchingSchedule(); |
520 } | 533 } |
521 | 534 |
535 void SchedulingRemoteSuggestionsProvider::ClearLastFetchAttemptTime() { | |
536 pref_service_->ClearPref(prefs::kSnippetLastFetchAttempt); | |
537 } | |
538 | |
522 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> | 539 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> |
523 SchedulingRemoteSuggestionsProvider::GetEnabledTriggerTypes() { | 540 SchedulingRemoteSuggestionsProvider::GetEnabledTriggerTypes() { |
524 static_assert(static_cast<unsigned int>(TriggerType::COUNT) == | 541 static_assert(static_cast<unsigned int>(TriggerType::COUNT) == |
525 arraysize(kTriggerTypeNames), | 542 arraysize(kTriggerTypeNames), |
526 "Fill in names for trigger types."); | 543 "Fill in names for trigger types."); |
527 | 544 |
528 std::string param_value = base::GetFieldTrialParamValueByFeature( | 545 std::string param_value = base::GetFieldTrialParamValueByFeature( |
529 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); | 546 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); |
530 if (param_value == kTriggerTypesParamValueForEmptyList) { | 547 if (param_value == kTriggerTypesParamValueForEmptyList) { |
531 return std::set<TriggerType>(); | 548 return std::set<TriggerType>(); |
(...skipping 26 matching lines...) Expand all Loading... | |
558 return enabled_types; | 575 return enabled_types; |
559 } | 576 } |
560 | 577 |
561 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> | 578 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> |
562 SchedulingRemoteSuggestionsProvider::GetDefaultEnabledTriggerTypes() { | 579 SchedulingRemoteSuggestionsProvider::GetDefaultEnabledTriggerTypes() { |
563 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, | 580 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, |
564 TriggerType::BROWSER_FOREGROUNDED}; | 581 TriggerType::BROWSER_FOREGROUNDED}; |
565 } | 582 } |
566 | 583 |
567 } // namespace ntp_snippets | 584 } // namespace ntp_snippets |
OLD | NEW |