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/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 ReportTimeUntilFirstTrigger( | |
| 149 UserClassifier::UserClass user_class, | |
| 150 const base::TimeDelta& time_until_first_failed_trigger) { | |
|
Marc Treib
2017/04/12 12:48:31
s/time_until_first_failed_trigger/time_until_first
jkrcal
2017/04/12 13:26:44
Done.
| |
| 151 switch (user_class) { | |
| 152 case UserClassifier::UserClass::RARE_NTP_USER: | |
| 153 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 154 "NewTabPage.ContentSuggestions.TimeUntilFirstTrigger_RareNTPUser", | |
| 155 time_until_first_failed_trigger, base::TimeDelta::FromSeconds(1), | |
| 156 base::TimeDelta::FromDays(7), | |
| 157 /*bucket_count=*/100); | |
| 158 break; | |
| 159 case UserClassifier::UserClass::ACTIVE_NTP_USER: | |
| 160 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 161 "NewTabPage.ContentSuggestions.TimeUntilFirstTrigger_ActiveNTPUser", | |
| 162 time_until_first_failed_trigger, base::TimeDelta::FromSeconds(1), | |
| 163 base::TimeDelta::FromDays(7), | |
| 164 /*bucket_count=*/100); | |
| 165 break; | |
| 166 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: | |
| 167 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 168 "NewTabPage.ContentSuggestions.TimeUntilFirstTrigger_" | |
| 169 "ActiveSuggestionsConsumer", | |
| 170 time_until_first_failed_trigger, base::TimeDelta::FromSeconds(1), | |
| 171 base::TimeDelta::FromDays(7), | |
| 172 /*bucket_count=*/100); | |
| 173 break; | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 void ReportTimeUntilFirstSuccessfulTrigger( | |
| 178 UserClassifier::UserClass user_class, | |
| 179 const base::TimeDelta& time_until_first_successful_trigger) { | |
| 180 switch (user_class) { | |
| 181 case UserClassifier::UserClass::RARE_NTP_USER: | |
| 182 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 183 "NewTabPage.ContentSuggestions.TimeUntilFirstSuccessfulTrigger_" | |
| 184 "RareNTPUser", | |
| 185 time_until_first_successful_trigger, base::TimeDelta::FromSeconds(1), | |
| 186 base::TimeDelta::FromDays(7), | |
| 187 /*bucket_count=*/100); | |
| 188 break; | |
| 189 case UserClassifier::UserClass::ACTIVE_NTP_USER: | |
| 190 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 191 "NewTabPage.ContentSuggestions.TimeUntilFirstSuccessfulTrigger_" | |
| 192 "ActiveNTPUser", | |
| 193 time_until_first_successful_trigger, base::TimeDelta::FromSeconds(1), | |
| 194 base::TimeDelta::FromDays(7), | |
| 195 /*bucket_count=*/100); | |
| 196 break; | |
| 197 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: | |
| 198 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 199 "NewTabPage.ContentSuggestions.TimeUntilFirstSuccessfulTrigger_" | |
| 200 "ActiveSuggestionsConsumer", | |
| 201 time_until_first_successful_trigger, base::TimeDelta::FromSeconds(1), | |
| 202 base::TimeDelta::FromDays(7), | |
| 203 /*bucket_count=*/100); | |
| 204 break; | |
| 205 } | |
| 206 } | |
| 207 | |
| 148 } // namespace | 208 } // namespace |
| 149 | 209 |
| 150 class EulaState : public web_resource::EulaAcceptedNotifier::Observer { | 210 class EulaState : public web_resource::EulaAcceptedNotifier::Observer { |
| 151 public: | 211 public: |
| 152 EulaState(PrefService* local_state_prefs, | 212 EulaState(PrefService* local_state_prefs, |
| 153 RemoteSuggestionsScheduler* scheduler) | 213 RemoteSuggestionsScheduler* scheduler) |
| 154 : eula_notifier_( | 214 : eula_notifier_( |
| 155 web_resource::EulaAcceptedNotifier::Create(local_state_prefs)), | 215 web_resource::EulaAcceptedNotifier::Create(local_state_prefs)), |
| 156 scheduler_(scheduler) { | 216 scheduler_(scheduler) { |
| 157 // EulaNotifier is not constructed on some platforms (such as desktop). | 217 // 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:: | 299 RequestThrottler::RequestType:: |
| 240 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), | 300 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), |
| 241 request_throttler_active_ntp_user_( | 301 request_throttler_active_ntp_user_( |
| 242 profile_prefs, | 302 profile_prefs, |
| 243 RequestThrottler::RequestType:: | 303 RequestThrottler::RequestType:: |
| 244 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), | 304 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), |
| 245 request_throttler_active_suggestions_consumer_( | 305 request_throttler_active_suggestions_consumer_( |
| 246 profile_prefs, | 306 profile_prefs, |
| 247 RequestThrottler::RequestType:: | 307 RequestThrottler::RequestType:: |
| 248 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), | 308 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), |
| 309 time_until_first_trigger_reported_(false), | |
| 249 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), | 310 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), |
| 250 profile_prefs_(profile_prefs), | 311 profile_prefs_(profile_prefs), |
| 251 clock_(std::move(clock)), | 312 clock_(std::move(clock)), |
| 252 enabled_triggers_(GetEnabledTriggerTypes()) { | 313 enabled_triggers_(GetEnabledTriggerTypes()) { |
| 253 DCHECK(user_classifier); | 314 DCHECK(user_classifier); |
| 254 DCHECK(profile_prefs); | 315 DCHECK(profile_prefs); |
| 255 | 316 |
| 256 // Cleanup procedure in M59. Remove for M62. | 317 // Cleanup procedure in M59. Remove for M62. |
| 257 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnUsageEventDeprecated); | 318 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnUsageEventDeprecated); |
| 258 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnNtpOpenedDeprecated); | 319 profile_prefs_->ClearPref(kSnippetSoftFetchingIntervalOnNtpOpenedDeprecated); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfAppropriate( | 492 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfAppropriate( |
| 432 TriggerType trigger) { | 493 TriggerType trigger) { |
| 433 if (background_fetch_in_progress_) { | 494 if (background_fetch_in_progress_) { |
| 434 return; | 495 return; |
| 435 } | 496 } |
| 436 | 497 |
| 437 if (BackgroundFetchesDisabled(trigger)) { | 498 if (BackgroundFetchesDisabled(trigger)) { |
| 438 return; | 499 return; |
| 439 } | 500 } |
| 440 | 501 |
| 502 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( | |
|
Marc Treib
2017/04/12 12:48:31
What exactly does fetch *attempt* mean? (Does it m
jkrcal
2017/04/12 13:26:44
It is the last time we sent a request to the serve
| |
| 503 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); | |
| 504 if (!time_until_first_trigger_reported_) { | |
|
Marc Treib
2017/04/12 12:48:31
Should we exclude PERSISTENT_SCHEDULER_WAKE_UP her
jkrcal
2017/04/12 13:26:44
Good point, done!
| |
| 505 time_until_first_trigger_reported_ = true; | |
| 506 ReportTimeUntilFirstTrigger(user_classifier_->GetUserClass(), | |
| 507 clock_->Now() - last_fetch_attempt_time); | |
| 508 } | |
| 509 | |
| 441 if (trigger != TriggerType::PERSISTENT_SCHEDULER_WAKE_UP && | 510 if (trigger != TriggerType::PERSISTENT_SCHEDULER_WAKE_UP && |
| 442 !ShouldRefetchInTheBackgroundNow()) { | 511 !ShouldRefetchInTheBackgroundNow(last_fetch_attempt_time)) { |
| 443 return; | 512 return; |
| 444 } | 513 } |
| 445 | 514 |
| 446 if (!AcquireQuota(/*interactive_request=*/false)) { | 515 if (!AcquireQuota(/*interactive_request=*/false)) { |
| 447 return; | 516 return; |
| 448 } | 517 } |
| 449 | 518 |
| 519 ReportTimeUntilFirstSuccessfulTrigger( | |
|
Marc Treib
2017/04/12 12:48:31
and here?
jkrcal
2017/04/12 13:26:44
Good point! I've introduced another histogram for
| |
| 520 user_classifier_->GetUserClass(), | |
| 521 clock_->Now() - last_fetch_attempt_time); | |
| 522 | |
| 450 UMA_HISTOGRAM_ENUMERATION( | 523 UMA_HISTOGRAM_ENUMERATION( |
| 451 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", | 524 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", |
| 452 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); | 525 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); |
| 453 | 526 |
| 454 background_fetch_in_progress_ = true; | 527 background_fetch_in_progress_ = true; |
| 455 provider_->RefetchInTheBackground(base::Bind( | 528 provider_->RefetchInTheBackground(base::Bind( |
| 456 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished, | 529 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished, |
| 457 base::Unretained(this))); | 530 base::Unretained(this))); |
| 458 } | 531 } |
| 459 | 532 |
| 460 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow() { | 533 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow( |
| 461 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( | 534 const 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. | 535 // If we have no persistent scheduler to ask, err on the side of caution. |
| 465 bool wifi = false; | 536 bool wifi = false; |
| 466 if (persistent_scheduler_) { | 537 if (persistent_scheduler_) { |
| 467 wifi = persistent_scheduler_->IsOnUnmeteredConnection(); | 538 wifi = persistent_scheduler_->IsOnUnmeteredConnection(); |
| 468 } | 539 } |
| 469 | 540 |
| 470 base::Time first_allowed_fetch_time = | 541 base::Time first_allowed_fetch_time = |
| 471 last_fetch_attempt_time + | 542 last_fetch_attempt_time + |
| 472 (wifi ? schedule_.interval_soft_wifi : schedule_.interval_soft_fallback); | 543 (wifi ? schedule_.interval_soft_wifi : schedule_.interval_soft_fallback); |
| 473 base::Time now = clock_->Now(); | 544 base::Time now = clock_->Now(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 | 585 |
| 515 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished( | 586 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished( |
| 516 Status fetch_status) { | 587 Status fetch_status) { |
| 517 background_fetch_in_progress_ = false; | 588 background_fetch_in_progress_ = false; |
| 518 OnFetchCompleted(fetch_status); | 589 OnFetchCompleted(fetch_status); |
| 519 } | 590 } |
| 520 | 591 |
| 521 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) { | 592 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) { |
| 522 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, | 593 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, |
| 523 clock_->Now().ToInternalValue()); | 594 clock_->Now().ToInternalValue()); |
| 595 time_until_first_trigger_reported_ = false; | |
| 524 | 596 |
| 525 // Reschedule after a fetch. The persistent schedule is applied only after a | 597 // 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 | 598 // successful fetch. After a failed fetch, we want to keep the previous |
| 527 // persistent schedule intact so that we eventually get a persistent | 599 // persistent schedule intact so that we eventually get a persistent |
| 528 // fallback fetch (if the wifi persistent fetches keep failing). | 600 // fallback fetch (if the wifi persistent fetches keep failing). |
| 529 if (fetch_status.code != StatusCode::SUCCESS) { | 601 if (fetch_status.code != StatusCode::SUCCESS) { |
| 530 return; | 602 return; |
| 531 } | 603 } |
| 532 ApplyPersistentFetchingSchedule(); | 604 ApplyPersistentFetchingSchedule(); |
| 533 } | 605 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 return enabled_types; | 647 return enabled_types; |
| 576 } | 648 } |
| 577 | 649 |
| 578 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> | 650 std::set<RemoteSuggestionsSchedulerImpl::TriggerType> |
| 579 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { | 651 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() { |
| 580 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, | 652 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, |
| 581 TriggerType::BROWSER_FOREGROUNDED}; | 653 TriggerType::BROWSER_FOREGROUNDED}; |
| 582 } | 654 } |
| 583 | 655 |
| 584 } // namespace ntp_snippets | 656 } // namespace ntp_snippets |
| OLD | NEW |