Chromium Code Reviews| Index: components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc |
| diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc |
| index da41c57c2008cba6287bb1f4b89684c8a79e956e..a746e7b02b297d01f0ce284f10b832aab7b9e3f8 100644 |
| --- a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc |
| +++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc |
| @@ -9,6 +9,8 @@ |
| #include <utility> |
| #include "base/memory/ptr_util.h" |
| +#include "base/metrics/histogram_macros.h" |
| +#include "base/strings/string_split.h" |
| #include "base/time/clock.h" |
| #include "components/ntp_snippets/features.h" |
| #include "components/ntp_snippets/pref_names.h" |
| @@ -65,6 +67,13 @@ static_assert( |
| arraysize(kFetchingIntervalParamNameActiveSuggestionsConsumer), |
| "Fill in all the info for fetching intervals."); |
| +const char* kTriggerTypeNames[] = {"persistent_scheduler_wake_up", "ntp_opened", |
| + "browser_foregrounded", |
| + "browser_cold_start"}; |
| + |
| +const char* kTriggerTypesParamName = "scheduler_trigger_types"; |
| +const char* kTriggerTypesParamValueForEmptyList = "-"; |
|
tschumann
2017/01/12 12:44:20
would be curious to understand why the empty strin
jkrcal
2017/01/12 15:35:28
No, there is no way. This is something to fix, in
|
| + |
| base::TimeDelta GetDesiredFetchingInterval( |
| FetchingInterval interval, |
| UserClassifier::UserClass user_class) { |
| @@ -125,6 +134,17 @@ bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const { |
| interval_soft_on_usage_event.is_zero(); |
| } |
| +// These values are written to logs. New enum values can be added, but existing |
| +// enums must never be renumbered or deleted and reused. When adding new |
| +// entries, also update the array |kTriggerTypeNames| above. |
| +enum class SchedulingRemoteSuggestionsProvider::TriggerType { |
| + PERSISTENT_SCHEDULER_WAKE_UP = 0, |
| + NTP_OPENED = 1, |
| + BROWSER_FOREGROUNDED = 2, |
| + BROWSER_COLD_START = 3, |
| + COUNT |
| +}; |
| + |
| SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( |
| Observer* observer, |
| std::unique_ptr<RemoteSuggestionsProvider> provider, |
| @@ -139,7 +159,8 @@ SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( |
| background_fetch_in_progress_(false), |
| user_classifier_(user_classifier), |
| pref_service_(pref_service), |
| - clock_(std::move(clock)) { |
| + clock_(std::move(clock)), |
| + enabled_triggers_(GetEnabledTriggerTypes()) { |
| DCHECK(user_classifier); |
| DCHECK(pref_service); |
| @@ -173,31 +194,35 @@ void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { |
| } |
| void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { |
| - if (BackgroundFetchesDisabled()) { |
| - return; |
| - } |
| - |
| - RefetchInTheBackground(/*callback=*/nullptr); |
| + RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); |
| } |
| void SchedulingRemoteSuggestionsProvider::OnBrowserForegrounded() { |
| // TODO(jkrcal): Consider that this is called whenever we open or return to an |
| // Activity. Therefore, keep work light for fast start up calls. |
| - // TODO(jkrcal): Implement. |
| + if (!ShouldRefetchInTheBackgroundNow()) { |
| + return; |
| + } |
| + |
| + RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_FOREGROUNDED); |
| } |
| void SchedulingRemoteSuggestionsProvider::OnBrowserColdStart() { |
| // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast |
| // cold start ups. |
| - // TODO(jkrcal): Implement. |
| + if (!ShouldRefetchInTheBackgroundNow()) { |
| + return; |
| + } |
| + |
| + RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_COLD_START); |
| } |
| void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { |
| - if (BackgroundFetchesDisabled() || !ShouldRefetchInTheBackgroundNow()) { |
| + if (!ShouldRefetchInTheBackgroundNow()) { |
| return; |
| } |
| - RefetchInTheBackground(/*callback=*/nullptr); |
| + RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); |
| } |
| void SchedulingRemoteSuggestionsProvider::SetProviderStatusCallback( |
| @@ -376,8 +401,17 @@ void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() { |
| schedule_.interval_soft_on_usage_event.ToInternalValue()); |
| } |
| -bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled() const { |
| - return schedule_.is_empty(); |
| +void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundIfEnabled( |
| + SchedulingRemoteSuggestionsProvider::TriggerType trigger) { |
| + if (BackgroundFetchesDisabled(trigger)) { |
| + return; |
| + } |
| + |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", |
| + static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); |
| + |
| + RefetchInTheBackground(/*callback=*/nullptr); |
| } |
| bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow() { |
| @@ -388,6 +422,18 @@ bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow() { |
| return first_allowed_fetch_time <= clock_->Now(); |
| } |
| +bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled( |
| + SchedulingRemoteSuggestionsProvider::TriggerType trigger) const { |
| + if (schedule_.is_empty()) { |
| + return true; // Background fetches are disabled in general. |
| + } |
| + |
| + if (enabled_triggers_.count(trigger) == 0) { |
| + return true; // Background fetches for |trigger| are not enabled. |
| + } |
| + return false; |
| +} |
| + |
| void SchedulingRemoteSuggestionsProvider::FetchFinished( |
| const FetchDoneCallback& callback, |
| Status fetch_status, |
| @@ -423,4 +469,49 @@ void SchedulingRemoteSuggestionsProvider::OnFetchCompleted( |
| ApplyPersistentFetchingSchedule(); |
| } |
| +std::set<SchedulingRemoteSuggestionsProvider::TriggerType> |
| +SchedulingRemoteSuggestionsProvider::GetEnabledTriggerTypes() { |
| + static_assert(static_cast<unsigned int>(TriggerType::COUNT) == |
| + arraysize(kTriggerTypeNames), |
| + "Fill in names for trigger types."); |
| + |
| + std::string param_value = variations::GetVariationParamValueByFeature( |
| + ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); |
| + if (param_value == kTriggerTypesParamValueForEmptyList) { |
| + return std::set<TriggerType>(); |
| + } |
| + |
| + std::vector<std::string> tokens = base::SplitString( |
| + param_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| + if (tokens.empty()) { |
| + return GetDefaultEnabledTriggerTypes(); |
| + } |
| + |
| + std::set<TriggerType> enabled_types; |
| + for (const auto& token : tokens) { |
| + auto it = std::find(std::begin(kTriggerTypeNames), |
| + std::end(kTriggerTypeNames), token); |
| + if (it == std::end(kTriggerTypeNames)) { |
| + DLOG(WARNING) << "Failed to parse variation param " |
| + << kTriggerTypesParamName << " with string value " |
| + << param_value |
| + << " into a comma-separated list of keywords. " |
| + << "Unknown token " << token |
| + << " found. Falling back to default value."; |
| + return GetDefaultEnabledTriggerTypes(); |
| + } |
| + |
| + // Add the enabled type represented by |token| into the result set. |
| + enabled_types.insert( |
| + static_cast<TriggerType>(it - std::begin(kTriggerTypeNames))); |
| + } |
| + return enabled_types; |
| +} |
| + |
| +std::set<SchedulingRemoteSuggestionsProvider::TriggerType> |
| +SchedulingRemoteSuggestionsProvider::GetDefaultEnabledTriggerTypes() { |
| + return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, |
| + TriggerType::BROWSER_FOREGROUNDED}; |
| +} |
| + |
| } // namespace ntp_snippets |