| 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/remote_suggestions_scheduler_impl.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 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 break; | 138 break; |
| 139 } | 139 } |
| 140 | 140 |
| 141 double value_hours = base::GetFieldTrialParamByFeatureAsDouble( | 141 double value_hours = base::GetFieldTrialParamByFeatureAsDouble( |
| 142 ntp_snippets::kArticleSuggestionsFeature, param_name, | 142 ntp_snippets::kArticleSuggestionsFeature, param_name, |
| 143 default_value_hours); | 143 default_value_hours); |
| 144 | 144 |
| 145 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); | 145 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void ReportTimeUntilFirstSoftTrigger(UserClassifier::UserClass user_class, |
| 149 base::TimeDelta time_until_first_trigger) { |
| 150 switch (user_class) { |
| 151 case UserClassifier::UserClass::RARE_NTP_USER: |
| 152 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 153 "NewTabPage.ContentSuggestions.TimeUntilFirstSoftTrigger.RareNTPUser", |
| 154 time_until_first_trigger, base::TimeDelta::FromSeconds(1), |
| 155 base::TimeDelta::FromDays(7), |
| 156 /*bucket_count=*/50); |
| 157 break; |
| 158 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 159 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 160 "NewTabPage.ContentSuggestions.TimeUntilFirstSoftTrigger." |
| 161 "ActiveNTPUser", |
| 162 time_until_first_trigger, base::TimeDelta::FromSeconds(1), |
| 163 base::TimeDelta::FromDays(7), |
| 164 /*bucket_count=*/50); |
| 165 break; |
| 166 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 167 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 168 "NewTabPage.ContentSuggestions.TimeUntilFirstSoftTrigger." |
| 169 "ActiveSuggestionsConsumer", |
| 170 time_until_first_trigger, base::TimeDelta::FromSeconds(1), |
| 171 base::TimeDelta::FromDays(7), |
| 172 /*bucket_count=*/50); |
| 173 break; |
| 174 } |
| 175 } |
| 176 |
| 177 void ReportTimeUntilSoftFetch(UserClassifier::UserClass user_class, |
| 178 base::TimeDelta time_until_soft_fetch) { |
| 179 switch (user_class) { |
| 180 case UserClassifier::UserClass::RARE_NTP_USER: |
| 181 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 182 "NewTabPage.ContentSuggestions.TimeUntilSoftFetch." |
| 183 "RareNTPUser", |
| 184 time_until_soft_fetch, base::TimeDelta::FromSeconds(1), |
| 185 base::TimeDelta::FromDays(7), |
| 186 /*bucket_count=*/50); |
| 187 break; |
| 188 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 189 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 190 "NewTabPage.ContentSuggestions.TimeUntilSoftFetch." |
| 191 "ActiveNTPUser", |
| 192 time_until_soft_fetch, base::TimeDelta::FromSeconds(1), |
| 193 base::TimeDelta::FromDays(7), |
| 194 /*bucket_count=*/50); |
| 195 break; |
| 196 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 197 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 198 "NewTabPage.ContentSuggestions.TimeUntilSoftFetch." |
| 199 "ActiveSuggestionsConsumer", |
| 200 time_until_soft_fetch, base::TimeDelta::FromSeconds(1), |
| 201 base::TimeDelta::FromDays(7), |
| 202 /*bucket_count=*/50); |
| 203 break; |
| 204 } |
| 205 } |
| 206 |
| 207 void ReportTimeUntilPersistentFetch( |
| 208 UserClassifier::UserClass user_class, |
| 209 base::TimeDelta time_until_persistent_fetch) { |
| 210 switch (user_class) { |
| 211 case UserClassifier::UserClass::RARE_NTP_USER: |
| 212 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 213 "NewTabPage.ContentSuggestions.TimeUntilPersistentFetch." |
| 214 "RareNTPUser", |
| 215 time_until_persistent_fetch, base::TimeDelta::FromSeconds(1), |
| 216 base::TimeDelta::FromDays(7), |
| 217 /*bucket_count=*/50); |
| 218 break; |
| 219 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 220 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 221 "NewTabPage.ContentSuggestions.TimeUntilPersistentFetch." |
| 222 "ActiveNTPUser", |
| 223 time_until_persistent_fetch, base::TimeDelta::FromSeconds(1), |
| 224 base::TimeDelta::FromDays(7), |
| 225 /*bucket_count=*/50); |
| 226 break; |
| 227 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 228 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 229 "NewTabPage.ContentSuggestions.TimeUntilPersistentFetch." |
| 230 "ActiveSuggestionsConsumer", |
| 231 time_until_persistent_fetch, base::TimeDelta::FromSeconds(1), |
| 232 base::TimeDelta::FromDays(7), |
| 233 /*bucket_count=*/50); |
| 234 break; |
| 235 } |
| 236 } |
| 237 |
| 148 } // namespace | 238 } // namespace |
| 149 | 239 |
| 150 class EulaState : public web_resource::EulaAcceptedNotifier::Observer { | 240 class EulaState : public web_resource::EulaAcceptedNotifier::Observer { |
| 151 public: | 241 public: |
| 152 EulaState(PrefService* local_state_prefs, | 242 EulaState(PrefService* local_state_prefs, |
| 153 RemoteSuggestionsScheduler* scheduler) | 243 RemoteSuggestionsScheduler* scheduler) |
| 154 : eula_notifier_( | 244 : eula_notifier_( |
| 155 web_resource::EulaAcceptedNotifier::Create(local_state_prefs)), | 245 web_resource::EulaAcceptedNotifier::Create(local_state_prefs)), |
| 156 scheduler_(scheduler) { | 246 scheduler_(scheduler) { |
| 157 // EulaNotifier is not constructed on some platforms (such as desktop). | 247 // EulaNotifier is not constructed on some platforms (such as desktop). |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 RequestThrottler::RequestType:: | 329 RequestThrottler::RequestType:: |
| 240 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), | 330 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), |
| 241 request_throttler_active_ntp_user_( | 331 request_throttler_active_ntp_user_( |
| 242 profile_prefs, | 332 profile_prefs, |
| 243 RequestThrottler::RequestType:: | 333 RequestThrottler::RequestType:: |
| 244 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), | 334 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), |
| 245 request_throttler_active_suggestions_consumer_( | 335 request_throttler_active_suggestions_consumer_( |
| 246 profile_prefs, | 336 profile_prefs, |
| 247 RequestThrottler::RequestType:: | 337 RequestThrottler::RequestType:: |
| 248 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), | 338 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), |
| 339 time_until_first_trigger_reported_(false), |
| 249 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), | 340 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), |
| 250 profile_prefs_(profile_prefs), | 341 profile_prefs_(profile_prefs), |
| 251 clock_(std::move(clock)), | 342 clock_(std::move(clock)), |
| 252 enabled_triggers_(GetEnabledTriggerTypes()) { | 343 enabled_triggers_(GetEnabledTriggerTypes()) { |
| 253 DCHECK(user_classifier); | 344 DCHECK(user_classifier); |
| 254 DCHECK(profile_prefs); | 345 DCHECK(profile_prefs); |
| 255 | 346 |
| 256 // Cleanup procedure in M59. Remove for M62. | 347 // Cleanup procedure in M59. Remove for M62. |
| 257 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnUsageEventDeprecated); | 348 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnUsageEventDeprecated); |
| 258 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnNtpOpenedDeprecated); | 349 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnNtpOpenedDeprecated); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfAppropriate( | 522 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfAppropriate( |
| 432 TriggerType trigger) { | 523 TriggerType trigger) { |
| 433 if (background_fetch_in_progress_) { | 524 if (background_fetch_in_progress_) { |
| 434 return; | 525 return; |
| 435 } | 526 } |
| 436 | 527 |
| 437 if (BackgroundFetchesDisabled(trigger)) { | 528 if (BackgroundFetchesDisabled(trigger)) { |
| 438 return; | 529 return; |
| 439 } | 530 } |
| 440 | 531 |
| 441 if (trigger != TriggerType::PERSISTENT_SCHEDULER_WAKE_UP && | 532 bool is_soft = trigger != TriggerType::PERSISTENT_SCHEDULER_WAKE_UP; |
| 442 !ShouldRefetchInTheBackgroundNow()) { | 533 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( |
| 534 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); |
| 535 |
| 536 if (is_soft && !time_until_first_trigger_reported_) { |
| 537 time_until_first_trigger_reported_ = true; |
| 538 ReportTimeUntilFirstSoftTrigger(user_classifier_->GetUserClass(), |
| 539 clock_->Now() - last_fetch_attempt_time); |
| 540 } |
| 541 |
| 542 if (is_soft && !ShouldRefetchInTheBackgroundNow(last_fetch_attempt_time)) { |
| 443 return; | 543 return; |
| 444 } | 544 } |
| 445 | 545 |
| 446 if (!AcquireQuota(/*interactive_request=*/false)) { | 546 if (!AcquireQuota(/*interactive_request=*/false)) { |
| 447 return; | 547 return; |
| 448 } | 548 } |
| 449 | 549 |
| 550 if (is_soft) { |
| 551 ReportTimeUntilSoftFetch(user_classifier_->GetUserClass(), |
| 552 clock_->Now() - last_fetch_attempt_time); |
| 553 } else { |
| 554 ReportTimeUntilPersistentFetch(user_classifier_->GetUserClass(), |
| 555 clock_->Now() - last_fetch_attempt_time); |
| 556 } |
| 557 |
| 450 UMA_HISTOGRAM_ENUMERATION( | 558 UMA_HISTOGRAM_ENUMERATION( |
| 451 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", | 559 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", |
| 452 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); | 560 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); |
| 453 | 561 |
| 454 background_fetch_in_progress_ = true; | 562 background_fetch_in_progress_ = true; |
| 455 provider_->RefetchInTheBackground(base::Bind( | 563 provider_->RefetchInTheBackground(base::Bind( |
| 456 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished, | 564 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished, |
| 457 base::Unretained(this))); | 565 base::Unretained(this))); |
| 458 } | 566 } |
| 459 | 567 |
| 460 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow() { | 568 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow( |
| 461 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( | 569 base::Time last_fetch_attempt_time) { |
| 462 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); | |
| 463 | |
| 464 // If we have no persistent scheduler to ask, err on the side of caution. | 570 // If we have no persistent scheduler to ask, err on the side of caution. |
| 465 bool wifi = false; | 571 bool wifi = false; |
| 466 if (persistent_scheduler_) { | 572 if (persistent_scheduler_) { |
| 467 wifi = persistent_scheduler_->IsOnUnmeteredConnection(); | 573 wifi = persistent_scheduler_->IsOnUnmeteredConnection(); |
| 468 } | 574 } |
| 469 | 575 |
| 470 base::Time first_allowed_fetch_time = | 576 base::Time first_allowed_fetch_time = |
| 471 last_fetch_attempt_time + | 577 last_fetch_attempt_time + |
| 472 (wifi ? schedule_.interval_soft_wifi : schedule_.interval_soft_fallback); | 578 (wifi ? schedule_.interval_soft_wifi : schedule_.interval_soft_fallback); |
| 473 base::Time now = clock_->Now(); | 579 base::Time now = clock_->Now(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 | 620 |
| 515 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished( | 621 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished( |
| 516 Status fetch_status) { | 622 Status fetch_status) { |
| 517 background_fetch_in_progress_ = false; | 623 background_fetch_in_progress_ = false; |
| 518 OnFetchCompleted(fetch_status); | 624 OnFetchCompleted(fetch_status); |
| 519 } | 625 } |
| 520 | 626 |
| 521 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) { | 627 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) { |
| 522 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, | 628 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, |
| 523 clock_->Now().ToInternalValue()); | 629 clock_->Now().ToInternalValue()); |
| 630 time_until_first_trigger_reported_ = false; |
| 524 | 631 |
| 525 // Reschedule after a fetch. The persistent schedule is applied only after a | 632 // Reschedule after a fetch. The persistent schedule is applied only after a |
| 526 // successful fetch. After a failed fetch, we want to keep the previous | 633 // successful fetch. After a failed fetch, we want to keep the previous |
| 527 // persistent schedule intact so that we eventually get a persistent | 634 // persistent schedule intact so that we eventually get a persistent |
| 528 // fallback fetch (if the wifi persistent fetches keep failing). | 635 // fallback fetch (if the wifi persistent fetches keep failing). |
| 529 if (fetch_status.code != StatusCode::SUCCESS) { | 636 if (fetch_status.code != StatusCode::SUCCESS) { |
| 530 return; | 637 return; |
| 531 } | 638 } |
| 532 ApplyPersistentFetchingSchedule(); | 639 ApplyPersistentFetchingSchedule(); |
| 533 } | 640 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 return enabled_types; | 682 return enabled_types; |
| 576 } | 683 } |
| 577 | 684 |
| 578 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> | 685 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> |
| 579 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { | 686 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { |
| 580 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, | 687 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, |
| 581 TriggerType::BROWSER_FOREGROUNDED}; | 688 TriggerType::BROWSER_FOREGROUNDED}; |
| 582 } | 689 } |
| 583 | 690 |
| 584 } // namespace ntp_snippets | 691 } // namespace ntp_snippets |
| OLD | NEW |