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/remote_suggestions_scheduler_impl.h" |
| 6 | 6 |
| 7 #include <random> | 7 #include <random> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/metrics/field_trial_params.h" | 13 #include "base/metrics/field_trial_params.h" |
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 } | 165 } |
| 166 | 166 |
| 167 private: | 167 private: |
| 168 std::unique_ptr<web_resource::EulaAcceptedNotifier> eula_notifier_; | 168 std::unique_ptr<web_resource::EulaAcceptedNotifier> eula_notifier_; |
| 169 RemoteSuggestionsScheduler* scheduler_; | 169 RemoteSuggestionsScheduler* scheduler_; |
| 170 | 170 |
| 171 DISALLOW_COPY_AND_ASSIGN(EulaState); | 171 DISALLOW_COPY_AND_ASSIGN(EulaState); |
| 172 }; | 172 }; |
| 173 | 173 |
| 174 // static | 174 // static |
| 175 SchedulingRemoteSuggestionsProvider::FetchingSchedule | 175 RemoteSuggestionsSchedulerImpl::FetchingSchedule |
| 176 SchedulingRemoteSuggestionsProvider::FetchingSchedule::Empty() { | 176 RemoteSuggestionsSchedulerImpl::FetchingSchedule::Empty() { |
| 177 return FetchingSchedule{base::TimeDelta(), base::TimeDelta(), | 177 return FetchingSchedule{base::TimeDelta(), base::TimeDelta(), |
| 178 base::TimeDelta(), base::TimeDelta()}; | 178 base::TimeDelta(), base::TimeDelta()}; |
| 179 } | 179 } |
| 180 | 180 |
| 181 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator==( | 181 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::operator==( |
| 182 const FetchingSchedule& other) const { | 182 const FetchingSchedule& other) const { |
| 183 return interval_persistent_wifi == other.interval_persistent_wifi && | 183 return interval_persistent_wifi == other.interval_persistent_wifi && |
| 184 interval_persistent_fallback == other.interval_persistent_fallback && | 184 interval_persistent_fallback == other.interval_persistent_fallback && |
| 185 interval_soft_on_usage_event == other.interval_soft_on_usage_event && | 185 interval_soft_on_usage_event == other.interval_soft_on_usage_event && |
| 186 interval_soft_on_ntp_opened == other.interval_soft_on_ntp_opened; | 186 interval_soft_on_ntp_opened == other.interval_soft_on_ntp_opened; |
| 187 } | 187 } |
| 188 | 188 |
| 189 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator!=( | 189 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::operator!=( |
| 190 const FetchingSchedule& other) const { | 190 const FetchingSchedule& other) const { |
| 191 return !operator==(other); | 191 return !operator==(other); |
| 192 } | 192 } |
| 193 | 193 |
| 194 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const { | 194 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::is_empty() const { |
| 195 return interval_persistent_wifi.is_zero() && | 195 return interval_persistent_wifi.is_zero() && |
| 196 interval_persistent_fallback.is_zero() && | 196 interval_persistent_fallback.is_zero() && |
| 197 interval_soft_on_usage_event.is_zero() && | 197 interval_soft_on_usage_event.is_zero() && |
| 198 interval_soft_on_ntp_opened.is_zero(); | 198 interval_soft_on_ntp_opened.is_zero(); |
| 199 } | 199 } |
| 200 | 200 |
| 201 // The TriggerType enum specifies values for the events that can trigger | 201 // The TriggerType enum specifies values for the events that can trigger |
| 202 // fetching remote suggestions. These values are written to logs. New enum | 202 // fetching remote suggestions. These values are written to logs. New enum |
| 203 // values can be added, but existing enums must never be renumbered or deleted | 203 // values can be added, but existing enums must never be renumbered or deleted |
| 204 // and reused. When adding new entries, also update the array | 204 // and reused. When adding new entries, also update the array |
| 205 // |kTriggerTypeNames| above. | 205 // |kTriggerTypeNames| above. |
| 206 enum class SchedulingRemoteSuggestionsProvider::TriggerType { | 206 enum class RemoteSuggestionsSchedulerImpl::TriggerType { |
| 207 PERSISTENT_SCHEDULER_WAKE_UP = 0, | 207 PERSISTENT_SCHEDULER_WAKE_UP = 0, |
| 208 NTP_OPENED = 1, | 208 NTP_OPENED = 1, |
| 209 BROWSER_FOREGROUNDED = 2, | 209 BROWSER_FOREGROUNDED = 2, |
| 210 BROWSER_COLD_START = 3, | 210 BROWSER_COLD_START = 3, |
| 211 COUNT | 211 COUNT |
| 212 }; | 212 }; |
| 213 | 213 |
| 214 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( | 214 RemoteSuggestionsSchedulerImpl::RemoteSuggestionsSchedulerImpl( |
| 215 Observer* observer, | |
| 216 std::unique_ptr<RemoteSuggestionsProvider> provider, | |
| 217 PersistentScheduler* persistent_scheduler, | 215 PersistentScheduler* persistent_scheduler, |
| 218 const UserClassifier* user_classifier, | 216 const UserClassifier* user_classifier, |
| 219 PrefService* profile_prefs, | 217 PrefService* profile_prefs, |
| 220 PrefService* local_state_prefs, | 218 PrefService* local_state_prefs, |
| 221 std::unique_ptr<base::Clock> clock) | 219 std::unique_ptr<base::Clock> clock) |
| 222 : RemoteSuggestionsProvider(observer), | 220 : RemoteSuggestionsScheduler(), |
|
Marc Treib
2017/03/27 11:31:01
Not needed
jkrcal
2017/03/27 14:09:31
Done.
| |
| 223 RemoteSuggestionsScheduler(), | |
| 224 provider_(std::move(provider)), | |
| 225 persistent_scheduler_(persistent_scheduler), | 221 persistent_scheduler_(persistent_scheduler), |
| 226 background_fetch_in_progress_(false), | 222 background_fetch_in_progress_(false), |
| 227 user_classifier_(user_classifier), | 223 user_classifier_(user_classifier), |
| 228 request_throttler_rare_ntp_user_( | 224 request_throttler_rare_ntp_user_( |
| 229 profile_prefs, | 225 profile_prefs, |
| 230 RequestThrottler::RequestType:: | 226 RequestThrottler::RequestType:: |
| 231 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), | 227 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), |
| 232 request_throttler_active_ntp_user_( | 228 request_throttler_active_ntp_user_( |
| 233 profile_prefs, | 229 profile_prefs, |
| 234 RequestThrottler::RequestType:: | 230 RequestThrottler::RequestType:: |
| 235 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), | 231 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), |
| 236 request_throttler_active_suggestions_consumer_( | 232 request_throttler_active_suggestions_consumer_( |
| 237 profile_prefs, | 233 profile_prefs, |
| 238 RequestThrottler::RequestType:: | 234 RequestThrottler::RequestType:: |
| 239 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), | 235 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), |
| 240 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), | 236 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), |
| 241 profile_prefs_(profile_prefs), | 237 profile_prefs_(profile_prefs), |
| 242 clock_(std::move(clock)), | 238 clock_(std::move(clock)), |
| 243 enabled_triggers_(GetEnabledTriggerTypes()) { | 239 enabled_triggers_(GetEnabledTriggerTypes()) { |
| 244 DCHECK(user_classifier); | 240 DCHECK(user_classifier); |
| 245 DCHECK(profile_prefs); | 241 DCHECK(profile_prefs); |
| 246 | 242 |
| 247 LoadLastFetchingSchedule(); | 243 LoadLastFetchingSchedule(); |
| 248 } | 244 } |
| 249 | 245 |
| 250 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = | 246 RemoteSuggestionsSchedulerImpl::~RemoteSuggestionsSchedulerImpl() = default; |
| 251 default; | |
| 252 | 247 |
| 253 // static | 248 // static |
| 254 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( | 249 void RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs( |
| 255 PrefRegistrySimple* registry) { | 250 PrefRegistrySimple* registry) { |
| 256 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); | 251 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); |
| 257 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, | 252 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, |
| 258 0); | 253 0); |
| 259 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, | 254 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, |
| 260 0); | 255 0); |
| 261 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); | 256 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); |
| 262 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened, | 257 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened, |
| 263 0); | 258 0); |
| 264 } | 259 } |
| 265 | 260 |
| 266 void SchedulingRemoteSuggestionsProvider::OnProviderActivated() { | 261 void RemoteSuggestionsSchedulerImpl::OnProviderActivated() { |
| 267 StartScheduling(); | 262 StartScheduling(); |
| 268 } | 263 } |
| 269 | 264 |
| 270 void SchedulingRemoteSuggestionsProvider::OnProviderDeactivated() { | 265 void RemoteSuggestionsSchedulerImpl::OnProviderDeactivated() { |
| 271 StopScheduling(); | 266 StopScheduling(); |
| 272 } | 267 } |
| 273 | 268 |
| 274 void SchedulingRemoteSuggestionsProvider::OnSuggestionsCleared() { | 269 void RemoteSuggestionsSchedulerImpl::OnSuggestionsCleared() { |
| 270 // This should be called by |provider_| so it should exist. | |
| 271 DCHECK(provider_); | |
| 275 // Some user action causes suggestions to be cleared, fetch now (as an | 272 // Some user action causes suggestions to be cleared, fetch now (as an |
| 276 // interactive request). | 273 // interactive request). |
| 277 ReloadSuggestions(); | 274 provider_->ReloadSuggestions(); |
| 278 } | 275 } |
| 279 | 276 |
| 280 void SchedulingRemoteSuggestionsProvider::OnHistoryCleared() { | 277 void RemoteSuggestionsSchedulerImpl::OnHistoryCleared() { |
| 281 // Due to privacy, we should not fetch for a while (unless the user explicitly | 278 // Due to privacy, we should not fetch for a while (unless the user explicitly |
| 282 // asks for new suggestions) to give sync the time to propagate the changes in | 279 // asks for new suggestions) to give sync the time to propagate the changes in |
| 283 // history to the server. | 280 // history to the server. |
| 284 background_fetches_allowed_after_ = | 281 background_fetches_allowed_after_ = |
| 285 clock_->Now() + base::TimeDelta::FromMinutes( | 282 clock_->Now() + base::TimeDelta::FromMinutes( |
| 286 kBlockBackgroundFetchesMinutesAfterClearingHistory); | 283 kBlockBackgroundFetchesMinutesAfterClearingHistory); |
| 287 // After that time elapses, we should fetch as soon as possible. | 284 // After that time elapses, we should fetch as soon as possible. |
| 288 ClearLastFetchAttemptTime(); | 285 ClearLastFetchAttemptTime(); |
| 289 } | 286 } |
| 290 | 287 |
| 291 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { | 288 void RemoteSuggestionsSchedulerImpl::RescheduleFetching() { |
| 292 // Force the reschedule by stopping and starting it again. | 289 // Force the reschedule by stopping and starting it again. |
| 293 StopScheduling(); | 290 StopScheduling(); |
| 294 StartScheduling(); | 291 StartScheduling(); |
| 295 } | 292 } |
| 296 | 293 |
| 297 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { | 294 bool RemoteSuggestionsSchedulerImpl::AcquireQuotaForInteractiveFetch() { |
| 295 return AcquireQuota(/*interactive_request=*/true); | |
| 296 } | |
| 297 | |
| 298 void RemoteSuggestionsSchedulerImpl::OnInteractiveFetchFinished( | |
| 299 Status fetch_status) { | |
| 300 OnFetchCompleted(fetch_status); | |
| 301 } | |
| 302 | |
| 303 void RemoteSuggestionsSchedulerImpl::OnPersistentSchedulerWakeUp() { | |
| 298 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); | 304 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); |
| 299 } | 305 } |
| 300 | 306 |
| 301 void SchedulingRemoteSuggestionsProvider::OnBrowserForegrounded() { | 307 void RemoteSuggestionsSchedulerImpl::OnBrowserForegrounded() { |
| 302 // TODO(jkrcal): Consider that this is called whenever we open or return to an | 308 // TODO(jkrcal): Consider that this is called whenever we open or return to an |
| 303 // Activity. Therefore, keep work light for fast start up calls. | 309 // Activity. Therefore, keep work light for fast start up calls. |
| 304 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_FOREGROUNDED)) { | 310 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_FOREGROUNDED)) { |
| 305 return; | 311 return; |
| 306 } | 312 } |
| 307 | 313 |
| 308 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_FOREGROUNDED); | 314 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_FOREGROUNDED); |
| 309 } | 315 } |
| 310 | 316 |
| 311 void SchedulingRemoteSuggestionsProvider::OnBrowserColdStart() { | 317 void RemoteSuggestionsSchedulerImpl::OnBrowserColdStart() { |
| 312 // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast | 318 // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast |
| 313 // cold start ups. | 319 // cold start ups. |
| 314 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_COLD_START)) { | 320 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_COLD_START)) { |
| 315 return; | 321 return; |
| 316 } | 322 } |
| 317 | 323 |
| 318 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_COLD_START); | 324 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_COLD_START); |
| 319 } | 325 } |
| 320 | 326 |
| 321 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { | 327 void RemoteSuggestionsSchedulerImpl::OnNTPOpened() { |
| 322 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) { | 328 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) { |
| 323 return; | 329 return; |
| 324 } | 330 } |
| 325 | 331 |
| 326 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); | 332 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); |
| 327 } | 333 } |
| 328 | 334 |
| 329 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( | 335 void RemoteSuggestionsSchedulerImpl::StartScheduling() { |
| 330 std::unique_ptr<FetchStatusCallback> callback) { | |
| 331 if (background_fetch_in_progress_) { | |
| 332 if (callback) { | |
| 333 callback->Run( | |
| 334 Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress")); | |
| 335 } | |
| 336 return; | |
| 337 } | |
| 338 | |
| 339 if (!AcquireQuota(/*interactive_request=*/false)) { | |
| 340 if (callback) { | |
| 341 callback->Run(Status(StatusCode::TEMPORARY_ERROR, | |
| 342 "Non-interactive quota exceeded")); | |
| 343 } | |
| 344 return; | |
| 345 } | |
| 346 | |
| 347 background_fetch_in_progress_ = true; | |
| 348 RemoteSuggestionsProvider::FetchStatusCallback wrapper_callback = base::Bind( | |
| 349 &SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished, | |
| 350 base::Unretained(this), base::Passed(&callback)); | |
| 351 provider_->RefetchInTheBackground( | |
| 352 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>( | |
| 353 std::move(wrapper_callback))); | |
| 354 } | |
| 355 | |
| 356 const RemoteSuggestionsFetcher* | |
| 357 SchedulingRemoteSuggestionsProvider::suggestions_fetcher_for_debugging() const { | |
| 358 return provider_->suggestions_fetcher_for_debugging(); | |
| 359 } | |
| 360 | |
| 361 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus( | |
| 362 Category category) { | |
| 363 return provider_->GetCategoryStatus(category); | |
| 364 } | |
| 365 | |
| 366 CategoryInfo SchedulingRemoteSuggestionsProvider::GetCategoryInfo( | |
| 367 Category category) { | |
| 368 return provider_->GetCategoryInfo(category); | |
| 369 } | |
| 370 | |
| 371 void SchedulingRemoteSuggestionsProvider::DismissSuggestion( | |
| 372 const ContentSuggestion::ID& suggestion_id) { | |
| 373 provider_->DismissSuggestion(suggestion_id); | |
| 374 } | |
| 375 | |
| 376 void SchedulingRemoteSuggestionsProvider::FetchSuggestionImage( | |
| 377 const ContentSuggestion::ID& suggestion_id, | |
| 378 const ImageFetchedCallback& callback) { | |
| 379 provider_->FetchSuggestionImage(suggestion_id, callback); | |
| 380 } | |
| 381 | |
| 382 void SchedulingRemoteSuggestionsProvider::Fetch( | |
| 383 const Category& category, | |
| 384 const std::set<std::string>& known_suggestion_ids, | |
| 385 const FetchDoneCallback& callback) { | |
| 386 if (!AcquireQuota(/*interactive_request=*/true)) { | |
| 387 if (callback) { | |
| 388 callback.Run( | |
| 389 Status(StatusCode::TEMPORARY_ERROR, "Interactive quota exceeded"), | |
| 390 std::vector<ContentSuggestion>()); | |
| 391 } | |
| 392 return; | |
| 393 } | |
| 394 | |
| 395 provider_->Fetch( | |
| 396 category, known_suggestion_ids, | |
| 397 base::Bind(&SchedulingRemoteSuggestionsProvider::FetchFinished, | |
| 398 base::Unretained(this), callback)); | |
| 399 } | |
| 400 | |
| 401 void SchedulingRemoteSuggestionsProvider::ReloadSuggestions() { | |
| 402 if (!AcquireQuota(/*interactive_request=*/true)) { | |
| 403 return; | |
| 404 } | |
| 405 | |
| 406 provider_->ReloadSuggestions(); | |
| 407 } | |
| 408 | |
| 409 void SchedulingRemoteSuggestionsProvider::ClearHistory( | |
| 410 base::Time begin, | |
| 411 base::Time end, | |
| 412 const base::Callback<bool(const GURL& url)>& filter) { | |
| 413 provider_->ClearHistory(begin, end, filter); | |
| 414 } | |
| 415 | |
| 416 void SchedulingRemoteSuggestionsProvider::ClearCachedSuggestions( | |
| 417 Category category) { | |
| 418 provider_->ClearCachedSuggestions(category); | |
| 419 } | |
| 420 | |
| 421 void SchedulingRemoteSuggestionsProvider::OnSignInStateChanged() { | |
| 422 provider_->OnSignInStateChanged(); | |
| 423 } | |
| 424 | |
| 425 void SchedulingRemoteSuggestionsProvider::GetDismissedSuggestionsForDebugging( | |
| 426 Category category, | |
| 427 const DismissedSuggestionsCallback& callback) { | |
| 428 provider_->GetDismissedSuggestionsForDebugging(category, callback); | |
| 429 } | |
| 430 | |
| 431 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging( | |
| 432 Category category) { | |
| 433 provider_->ClearDismissedSuggestionsForDebugging(category); | |
| 434 } | |
| 435 | |
| 436 void SchedulingRemoteSuggestionsProvider::StartScheduling() { | |
| 437 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); | 336 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); |
| 438 | 337 |
| 439 if (schedule_ == new_schedule) { | 338 if (schedule_ == new_schedule) { |
| 440 // Do not schedule if nothing has changed; | 339 // Do not schedule if nothing has changed; |
| 441 return; | 340 return; |
| 442 } | 341 } |
| 443 | 342 |
| 444 schedule_ = new_schedule; | 343 schedule_ = new_schedule; |
| 445 StoreFetchingSchedule(); | 344 StoreFetchingSchedule(); |
| 446 ApplyPersistentFetchingSchedule(); | 345 ApplyPersistentFetchingSchedule(); |
| 447 } | 346 } |
| 448 | 347 |
| 449 void SchedulingRemoteSuggestionsProvider::StopScheduling() { | 348 void RemoteSuggestionsSchedulerImpl::StopScheduling() { |
| 450 if (schedule_.is_empty()) { | 349 if (schedule_.is_empty()) { |
| 451 // Do not unschedule if already switched off. | 350 // Do not unschedule if already switched off. |
| 452 return; | 351 return; |
| 453 } | 352 } |
| 454 | 353 |
| 455 schedule_ = FetchingSchedule::Empty(); | 354 schedule_ = FetchingSchedule::Empty(); |
| 456 StoreFetchingSchedule(); | 355 StoreFetchingSchedule(); |
| 457 ApplyPersistentFetchingSchedule(); | 356 ApplyPersistentFetchingSchedule(); |
| 458 } | 357 } |
| 459 | 358 |
| 460 void SchedulingRemoteSuggestionsProvider::ApplyPersistentFetchingSchedule() { | 359 void RemoteSuggestionsSchedulerImpl::ApplyPersistentFetchingSchedule() { |
| 461 // The scheduler only exists on Android so far, it's null on other platforms. | 360 // The scheduler only exists on Android so far, it's null on other platforms. |
| 462 if (persistent_scheduler_) { | 361 if (persistent_scheduler_) { |
| 463 if (schedule_.is_empty()) { | 362 if (schedule_.is_empty()) { |
| 464 persistent_scheduler_->Unschedule(); | 363 persistent_scheduler_->Unschedule(); |
| 465 } else { | 364 } else { |
| 466 persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi, | 365 persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi, |
| 467 schedule_.interval_persistent_fallback); | 366 schedule_.interval_persistent_fallback); |
| 468 } | 367 } |
| 469 } | 368 } |
| 470 } | 369 } |
| 471 | 370 |
| 472 SchedulingRemoteSuggestionsProvider::FetchingSchedule | 371 RemoteSuggestionsSchedulerImpl::FetchingSchedule |
| 473 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const { | 372 RemoteSuggestionsSchedulerImpl::GetDesiredFetchingSchedule() const { |
| 474 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); | 373 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); |
| 475 | 374 |
| 476 FetchingSchedule schedule; | 375 FetchingSchedule schedule; |
| 477 schedule.interval_persistent_wifi = | 376 schedule.interval_persistent_wifi = |
| 478 GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class); | 377 GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class); |
| 479 schedule.interval_persistent_fallback = GetDesiredFetchingInterval( | 378 schedule.interval_persistent_fallback = GetDesiredFetchingInterval( |
| 480 FetchingInterval::PERSISTENT_FALLBACK, user_class); | 379 FetchingInterval::PERSISTENT_FALLBACK, user_class); |
| 481 schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval( | 380 schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval( |
| 482 FetchingInterval::SOFT_ON_USAGE_EVENT, user_class); | 381 FetchingInterval::SOFT_ON_USAGE_EVENT, user_class); |
| 483 schedule.interval_soft_on_ntp_opened = GetDesiredFetchingInterval( | 382 schedule.interval_soft_on_ntp_opened = GetDesiredFetchingInterval( |
| 484 FetchingInterval::SOFT_ON_NTP_OPENED, user_class); | 383 FetchingInterval::SOFT_ON_NTP_OPENED, user_class); |
| 485 | 384 |
| 486 return schedule; | 385 return schedule; |
| 487 } | 386 } |
| 488 | 387 |
| 489 void SchedulingRemoteSuggestionsProvider::LoadLastFetchingSchedule() { | 388 void RemoteSuggestionsSchedulerImpl::LoadLastFetchingSchedule() { |
| 490 schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue( | 389 schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue( |
| 491 profile_prefs_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi)); | 390 profile_prefs_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi)); |
| 492 schedule_.interval_persistent_fallback = | 391 schedule_.interval_persistent_fallback = |
| 493 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( | 392 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( |
| 494 prefs::kSnippetPersistentFetchingIntervalFallback)); | 393 prefs::kSnippetPersistentFetchingIntervalFallback)); |
| 495 schedule_.interval_soft_on_usage_event = | 394 schedule_.interval_soft_on_usage_event = |
| 496 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( | 395 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( |
| 497 prefs::kSnippetSoftFetchingIntervalOnUsageEvent)); | 396 prefs::kSnippetSoftFetchingIntervalOnUsageEvent)); |
| 498 schedule_.interval_soft_on_ntp_opened = base::TimeDelta::FromInternalValue( | 397 schedule_.interval_soft_on_ntp_opened = base::TimeDelta::FromInternalValue( |
| 499 profile_prefs_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnNtpOpened)); | 398 profile_prefs_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnNtpOpened)); |
| 500 } | 399 } |
| 501 | 400 |
| 502 void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() { | 401 void RemoteSuggestionsSchedulerImpl::StoreFetchingSchedule() { |
| 503 profile_prefs_->SetInt64( | 402 profile_prefs_->SetInt64( |
| 504 prefs::kSnippetPersistentFetchingIntervalWifi, | 403 prefs::kSnippetPersistentFetchingIntervalWifi, |
| 505 schedule_.interval_persistent_wifi.ToInternalValue()); | 404 schedule_.interval_persistent_wifi.ToInternalValue()); |
| 506 profile_prefs_->SetInt64( | 405 profile_prefs_->SetInt64( |
| 507 prefs::kSnippetPersistentFetchingIntervalFallback, | 406 prefs::kSnippetPersistentFetchingIntervalFallback, |
| 508 schedule_.interval_persistent_fallback.ToInternalValue()); | 407 schedule_.interval_persistent_fallback.ToInternalValue()); |
| 509 profile_prefs_->SetInt64( | 408 profile_prefs_->SetInt64( |
| 510 prefs::kSnippetSoftFetchingIntervalOnUsageEvent, | 409 prefs::kSnippetSoftFetchingIntervalOnUsageEvent, |
| 511 schedule_.interval_soft_on_usage_event.ToInternalValue()); | 410 schedule_.interval_soft_on_usage_event.ToInternalValue()); |
| 512 profile_prefs_->SetInt64( | 411 profile_prefs_->SetInt64( |
| 513 prefs::kSnippetSoftFetchingIntervalOnNtpOpened, | 412 prefs::kSnippetSoftFetchingIntervalOnNtpOpened, |
| 514 schedule_.interval_soft_on_ntp_opened.ToInternalValue()); | 413 schedule_.interval_soft_on_ntp_opened.ToInternalValue()); |
| 515 } | 414 } |
| 516 | 415 |
| 517 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundIfEnabled( | 416 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfEnabled( |
| 518 SchedulingRemoteSuggestionsProvider::TriggerType trigger) { | 417 RemoteSuggestionsSchedulerImpl::TriggerType trigger) { |
|
Marc Treib
2017/03/27 11:31:00
"RemoteSuggestionsSchedulerImpl::" not required
jkrcal
2017/03/27 14:09:31
Done.
| |
| 519 if (BackgroundFetchesDisabled(trigger)) { | 418 if (BackgroundFetchesDisabled(trigger)) { |
| 520 return; | 419 return; |
| 521 } | 420 } |
| 522 | 421 |
| 523 UMA_HISTOGRAM_ENUMERATION( | 422 UMA_HISTOGRAM_ENUMERATION( |
| 524 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", | 423 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", |
| 525 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); | 424 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); |
| 526 | 425 |
| 527 RefetchInTheBackground(/*callback=*/nullptr); | 426 RefetchInTheBackground(); |
| 528 } | 427 } |
| 529 | 428 |
| 530 bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow( | 429 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackground() { |
| 531 SchedulingRemoteSuggestionsProvider::TriggerType trigger) { | 430 if (background_fetch_in_progress_) { |
| 431 return; | |
| 432 } | |
| 433 | |
| 434 if (!AcquireQuota(/*interactive_request=*/false)) { | |
| 435 return; | |
| 436 } | |
| 437 | |
| 438 background_fetch_in_progress_ = true; | |
| 439 RemoteSuggestionsProvider::FetchStatusCallback callback = base::Bind( | |
| 440 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished, | |
| 441 base::Unretained(this)); | |
| 442 provider_->RefetchInTheBackground( | |
| 443 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>( | |
| 444 std::move(callback))); | |
|
Marc Treib
2017/03/27 11:31:00
nit: Inline the Bind() call here? Then the move is
jkrcal
2017/03/27 14:09:31
Done.
| |
| 445 } | |
| 446 | |
| 447 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow( | |
| 448 RemoteSuggestionsSchedulerImpl::TriggerType trigger) { | |
|
Marc Treib
2017/03/27 11:31:01
"RemoteSuggestionsSchedulerImpl::" not required
jkrcal
2017/03/27 14:09:31
Done.
| |
| 532 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( | 449 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( |
| 533 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); | 450 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); |
| 534 base::Time first_allowed_fetch_time; | 451 base::Time first_allowed_fetch_time; |
| 535 switch (trigger) { | 452 switch (trigger) { |
| 536 case TriggerType::NTP_OPENED: | 453 case TriggerType::NTP_OPENED: |
| 537 first_allowed_fetch_time = | 454 first_allowed_fetch_time = |
| 538 last_fetch_attempt_time + schedule_.interval_soft_on_ntp_opened; | 455 last_fetch_attempt_time + schedule_.interval_soft_on_ntp_opened; |
| 539 break; | 456 break; |
| 540 case TriggerType::BROWSER_FOREGROUNDED: | 457 case TriggerType::BROWSER_FOREGROUNDED: |
| 541 case TriggerType::BROWSER_COLD_START: | 458 case TriggerType::BROWSER_COLD_START: |
| 542 first_allowed_fetch_time = | 459 first_allowed_fetch_time = |
| 543 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event; | 460 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event; |
| 544 break; | 461 break; |
| 545 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP: | 462 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP: |
| 546 case TriggerType::COUNT: | 463 case TriggerType::COUNT: |
| 547 NOTREACHED(); | 464 NOTREACHED(); |
| 548 break; | 465 break; |
| 549 } | 466 } |
| 550 base::Time now = clock_->Now(); | 467 base::Time now = clock_->Now(); |
| 551 | 468 |
| 552 return background_fetches_allowed_after_ <= now && | 469 return background_fetches_allowed_after_ <= now && |
| 553 first_allowed_fetch_time <= now; | 470 first_allowed_fetch_time <= now; |
| 554 } | 471 } |
| 555 | 472 |
| 556 bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled( | 473 bool RemoteSuggestionsSchedulerImpl::BackgroundFetchesDisabled( |
| 557 SchedulingRemoteSuggestionsProvider::TriggerType trigger) const { | 474 RemoteSuggestionsSchedulerImpl::TriggerType trigger) const { |
|
Marc Treib
2017/03/27 11:31:01
Also here
jkrcal
2017/03/27 14:09:31
Done.
| |
| 475 if (!provider_) { | |
| 476 return true; // Cannot fetch as remote suggestions provider does not exist. | |
| 477 } | |
| 478 | |
| 558 if (schedule_.is_empty()) { | 479 if (schedule_.is_empty()) { |
| 559 return true; // Background fetches are disabled in general. | 480 return true; // Background fetches are disabled in general. |
| 560 } | 481 } |
| 561 | 482 |
| 562 if (enabled_triggers_.count(trigger) == 0) { | 483 if (enabled_triggers_.count(trigger) == 0) { |
| 563 return true; // Background fetches for |trigger| are not enabled. | 484 return true; // Background fetches for |trigger| are not enabled. |
| 564 } | 485 } |
| 565 | 486 |
| 566 if (!eula_state_->IsEulaAccepted()) { | 487 if (!eula_state_->IsEulaAccepted()) { |
| 567 return true; // No background fetches are allowed before EULA is accepted. | 488 return true; // No background fetches are allowed before EULA is accepted. |
| 568 } | 489 } |
| 569 | 490 |
| 570 return false; | 491 return false; |
| 571 } | 492 } |
| 572 | 493 |
| 573 bool SchedulingRemoteSuggestionsProvider::AcquireQuota( | 494 bool RemoteSuggestionsSchedulerImpl::AcquireQuota(bool interactive_request) { |
| 574 bool interactive_request) { | |
| 575 switch (user_classifier_->GetUserClass()) { | 495 switch (user_classifier_->GetUserClass()) { |
| 576 case UserClassifier::UserClass::RARE_NTP_USER: | 496 case UserClassifier::UserClass::RARE_NTP_USER: |
| 577 return request_throttler_rare_ntp_user_.DemandQuotaForRequest( | 497 return request_throttler_rare_ntp_user_.DemandQuotaForRequest( |
| 578 interactive_request); | 498 interactive_request); |
| 579 case UserClassifier::UserClass::ACTIVE_NTP_USER: | 499 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 580 return request_throttler_active_ntp_user_.DemandQuotaForRequest( | 500 return request_throttler_active_ntp_user_.DemandQuotaForRequest( |
| 581 interactive_request); | 501 interactive_request); |
| 582 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: | 502 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 583 return request_throttler_active_suggestions_consumer_ | 503 return request_throttler_active_suggestions_consumer_ |
| 584 .DemandQuotaForRequest(interactive_request); | 504 .DemandQuotaForRequest(interactive_request); |
| 585 } | 505 } |
| 586 NOTREACHED(); | 506 NOTREACHED(); |
| 587 return false; | 507 return false; |
| 588 } | 508 } |
| 589 | 509 |
| 590 void SchedulingRemoteSuggestionsProvider::FetchFinished( | 510 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished( |
| 591 const FetchDoneCallback& callback, | |
| 592 Status fetch_status, | |
| 593 std::vector<ContentSuggestion> suggestions) { | |
| 594 OnFetchCompleted(fetch_status); | |
| 595 if (callback) { | |
| 596 callback.Run(fetch_status, std::move(suggestions)); | |
| 597 } | |
| 598 } | |
| 599 | |
| 600 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished( | |
| 601 std::unique_ptr<FetchStatusCallback> callback, | |
| 602 Status fetch_status) { | 511 Status fetch_status) { |
| 603 background_fetch_in_progress_ = false; | 512 background_fetch_in_progress_ = false; |
| 604 OnFetchCompleted(fetch_status); | 513 OnFetchCompleted(fetch_status); |
| 605 if (callback) { | |
| 606 callback->Run(fetch_status); | |
| 607 } | |
| 608 } | 514 } |
| 609 | 515 |
| 610 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted( | 516 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) { |
| 611 Status fetch_status) { | |
| 612 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, | 517 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, |
| 613 clock_->Now().ToInternalValue()); | 518 clock_->Now().ToInternalValue()); |
| 614 | 519 |
| 615 // Reschedule after a fetch. The persistent schedule is applied only after a | 520 // Reschedule after a fetch. The persistent schedule is applied only after a |
| 616 // successful fetch. After a failed fetch, we want to keep the previous | 521 // successful fetch. After a failed fetch, we want to keep the previous |
| 617 // persistent schedule intact so that we eventually get a persistent | 522 // persistent schedule intact so that we eventually get a persistent |
| 618 // fallback fetch (if the wifi persistent fetches keep failing). | 523 // fallback fetch (if the wifi persistent fetches keep failing). |
| 619 if (fetch_status.code != StatusCode::SUCCESS) { | 524 if (fetch_status.code != StatusCode::SUCCESS) { |
| 620 return; | 525 return; |
| 621 } | 526 } |
| 622 ApplyPersistentFetchingSchedule(); | 527 ApplyPersistentFetchingSchedule(); |
| 623 } | 528 } |
| 624 | 529 |
| 625 void SchedulingRemoteSuggestionsProvider::ClearLastFetchAttemptTime() { | 530 void RemoteSuggestionsSchedulerImpl::ClearLastFetchAttemptTime() { |
| 626 profile_prefs_->ClearPref(prefs::kSnippetLastFetchAttempt); | 531 profile_prefs_->ClearPref(prefs::kSnippetLastFetchAttempt); |
| 627 } | 532 } |
| 628 | 533 |
| 629 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> | 534 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> |
| 630 SchedulingRemoteSuggestionsProvider::GetEnabledTriggerTypes() { | 535 RemoteSuggestionsSchedulerImpl::GetEnabledTriggerTypes() { |
| 631 static_assert(static_cast<unsigned int>(TriggerType::COUNT) == | 536 static_assert(static_cast<unsigned int>(TriggerType::COUNT) == |
| 632 arraysize(kTriggerTypeNames), | 537 arraysize(kTriggerTypeNames), |
| 633 "Fill in names for trigger types."); | 538 "Fill in names for trigger types."); |
| 634 | 539 |
| 635 std::string param_value = base::GetFieldTrialParamValueByFeature( | 540 std::string param_value = base::GetFieldTrialParamValueByFeature( |
| 636 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); | 541 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); |
| 637 if (param_value == kTriggerTypesParamValueForEmptyList) { | 542 if (param_value == kTriggerTypesParamValueForEmptyList) { |
| 638 return std::set<TriggerType>(); | 543 return std::set<TriggerType>(); |
| 639 } | 544 } |
| 640 | 545 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 658 return GetDefaultEnabledTriggerTypes(); | 563 return GetDefaultEnabledTriggerTypes(); |
| 659 } | 564 } |
| 660 | 565 |
| 661 // Add the enabled type represented by |token| into the result set. | 566 // Add the enabled type represented by |token| into the result set. |
| 662 enabled_types.insert( | 567 enabled_types.insert( |
| 663 static_cast<TriggerType>(it - std::begin(kTriggerTypeNames))); | 568 static_cast<TriggerType>(it - std::begin(kTriggerTypeNames))); |
| 664 } | 569 } |
| 665 return enabled_types; | 570 return enabled_types; |
| 666 } | 571 } |
| 667 | 572 |
| 668 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> | 573 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> |
| 669 SchedulingRemoteSuggestionsProvider::GetDefaultEnabledTriggerTypes() { | 574 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { |
| 670 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, | 575 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, |
| 671 TriggerType::BROWSER_FOREGROUNDED}; | 576 TriggerType::BROWSER_FOREGROUNDED}; |
| 672 } | 577 } |
| 673 | 578 |
| 674 } // namespace ntp_snippets | 579 } // namespace ntp_snippets |
| OLD | NEW |