Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/ntp_snippets/remote/scheduling_remote_suggestions_provider. h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "components/ntp_snippets/features.h" | |
| 11 #include "components/ntp_snippets/pref_names.h" | |
| 12 #include "components/ntp_snippets/remote/persistent_scheduler.h" | |
| 13 #include "components/ntp_snippets/user_classifier.h" | |
| 14 #include "components/prefs/pref_registry_simple.h" | |
| 15 #include "components/prefs/pref_service.h" | |
| 16 #include "components/variations/variations_associated_data.h" | |
| 17 | |
| 18 namespace ntp_snippets { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 // Default values for fetching intervals, fallback and wifi. | |
| 23 const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0}; | |
| 24 const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0}; | |
| 25 const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0}; | |
| 26 | |
| 27 // Variation parameters than can the default fetching intervals. | |
| 28 const char* kFetchingIntervalParamNameRareNtpUser[] = { | |
| 29 "fetching_interval_hours-fallback-rare_ntp_user", | |
| 30 "fetching_interval_hours-wifi-rare_ntp_user"}; | |
| 31 const char* kFetchingIntervalParamNameActiveNtpUser[] = { | |
| 32 "fetching_interval_hours-fallback-active_ntp_user", | |
| 33 "fetching_interval_hours-wifi-active_ntp_user"}; | |
| 34 const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = { | |
| 35 "fetching_interval_hours-fallback-active_suggestions_consumer", | |
| 36 "fetching_interval_hours-wifi-active_suggestions_consumer"}; | |
| 37 | |
| 38 base::TimeDelta GetCurrentUpdateInterval( | |
| 39 bool is_wifi, | |
| 40 UserClassifier::UserClass user_class) { | |
| 41 double default_value_hours = 0.0; | |
| 42 | |
| 43 const int index = is_wifi ? 1 : 0; | |
| 44 const char* param_name = nullptr; | |
| 45 switch (user_class) { | |
| 46 case UserClassifier::UserClass::RARE_NTP_USER: | |
| 47 default_value_hours = kDefaultFetchingIntervalRareNtpUser[index]; | |
| 48 param_name = kFetchingIntervalParamNameRareNtpUser[index]; | |
| 49 break; | |
| 50 case UserClassifier::UserClass::ACTIVE_NTP_USER: | |
| 51 default_value_hours = kDefaultFetchingIntervalActiveNtpUser[index]; | |
| 52 param_name = kFetchingIntervalParamNameActiveNtpUser[index]; | |
| 53 break; | |
| 54 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: | |
| 55 default_value_hours = | |
| 56 kDefaultFetchingIntervalActiveSuggestionsConsumer[index]; | |
| 57 param_name = kFetchingIntervalParamNameActiveSuggestionsConsumer[index]; | |
| 58 break; | |
| 59 } | |
| 60 | |
| 61 double value_hours = variations::GetVariationParamByFeatureAsDouble( | |
| 62 ntp_snippets::kArticleSuggestionsFeature, param_name, | |
| 63 default_value_hours); | |
| 64 | |
| 65 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); | |
| 66 } | |
| 67 | |
| 68 } // namespace | |
| 69 | |
| 70 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( | |
| 71 Observer* observer, | |
| 72 CategoryFactory* category_factory, | |
| 73 std::unique_ptr<RemoteSuggestionsProvider> provider, | |
| 74 PersistentScheduler* persistent_scheduler, | |
| 75 const UserClassifier* user_classifier, | |
| 76 PrefService* pref_service) | |
| 77 : ContentSuggestionsProvider(observer, category_factory), | |
| 78 provider_(std::move(provider)), | |
| 79 persistent_scheduler_(persistent_scheduler), | |
| 80 user_classifier_(user_classifier), | |
| 81 pref_service_(pref_service) { | |
| 82 DCHECK(user_classifier) << "non-null UserClassifier must be provided"; | |
| 83 DCHECK(pref_service) << "non-null pref service is needed"; | |
| 84 | |
| 85 provider->RegisterActivenessObserver(base::BindRepeating( | |
|
tschumann
2016/12/15 19:27:00
doing this in the constructor is tricky -- we migh
jkrcal
2016/12/19 09:40:24
Added the TODO.
| |
| 86 &SchedulingRemoteSuggestionsProvider::OnProviderActivenessChanged, | |
| 87 base::Unretained(this))); | |
| 88 } | |
| 89 | |
| 90 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = | |
| 91 default; | |
| 92 | |
| 93 // static | |
| 94 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( | |
| 95 PrefRegistrySimple* registry) { | |
| 96 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0); | |
| 97 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback, | |
| 98 0); | |
| 99 } | |
| 100 | |
| 101 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { | |
| 102 // Force the reschedule by stopping and starting it again. | |
| 103 StopScheduling(); | |
| 104 StartScheduling(); | |
| 105 } | |
| 106 | |
| 107 void SchedulingRemoteSuggestionsProvider::OnFetchDue() { | |
| 108 provider_->RefetchInTheBackground( | |
| 109 base::Bind(&SchedulingRemoteSuggestionsProvider::OnFetchCompleted, | |
| 110 base::Unretained(this))); | |
| 111 } | |
| 112 | |
| 113 | |
| 114 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus( | |
| 115 Category category) { | |
| 116 return provider_->GetCategoryStatus(category); | |
| 117 } | |
| 118 | |
| 119 CategoryInfo SchedulingRemoteSuggestionsProvider::GetCategoryInfo( | |
| 120 Category category) { | |
| 121 return provider_->GetCategoryInfo(category); | |
| 122 } | |
| 123 | |
| 124 void SchedulingRemoteSuggestionsProvider::DismissSuggestion( | |
| 125 const ContentSuggestion::ID& suggestion_id) { | |
| 126 provider_->DismissSuggestion(suggestion_id); | |
| 127 } | |
| 128 | |
| 129 void SchedulingRemoteSuggestionsProvider::FetchSuggestionImage( | |
| 130 const ContentSuggestion::ID& suggestion_id, | |
| 131 const ImageFetchedCallback& callback) { | |
| 132 provider_->FetchSuggestionImage(suggestion_id, callback); | |
| 133 } | |
| 134 | |
| 135 void SchedulingRemoteSuggestionsProvider::Fetch( | |
| 136 const Category& category, | |
| 137 const std::set<std::string>& known_suggestion_ids, | |
| 138 const FetchDoneCallback& callback) { | |
| 139 provider_->Fetch( | |
| 140 category, known_suggestion_ids, | |
| 141 base::Bind(&SchedulingRemoteSuggestionsProvider::FetchFinished, | |
| 142 base::Unretained(this), callback)); | |
| 143 } | |
| 144 | |
| 145 void SchedulingRemoteSuggestionsProvider::ReloadSuggestions() { | |
| 146 provider_->ReloadSuggestions(); | |
| 147 } | |
| 148 | |
| 149 void SchedulingRemoteSuggestionsProvider::ClearHistory( | |
| 150 base::Time begin, | |
| 151 base::Time end, | |
| 152 const base::Callback<bool(const GURL& url)>& filter) { | |
| 153 provider_->ClearHistory(begin, end, filter); | |
| 154 } | |
| 155 | |
| 156 void SchedulingRemoteSuggestionsProvider::ClearCachedSuggestions( | |
| 157 Category category) { | |
| 158 provider_->ClearCachedSuggestions(category); | |
| 159 } | |
| 160 | |
| 161 void SchedulingRemoteSuggestionsProvider::OnSignInStateChanged() { | |
| 162 provider_->OnSignInStateChanged(); | |
| 163 } | |
| 164 | |
| 165 void SchedulingRemoteSuggestionsProvider::GetDismissedSuggestionsForDebugging( | |
| 166 Category category, | |
| 167 const DismissedSuggestionsCallback& callback) { | |
| 168 provider_->GetDismissedSuggestionsForDebugging(category, callback); | |
| 169 } | |
| 170 | |
| 171 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging( | |
| 172 Category category) { | |
| 173 provider_->ClearDismissedSuggestionsForDebugging(category); | |
| 174 } | |
| 175 | |
| 176 void SchedulingRemoteSuggestionsProvider::OnProviderActivenessChanged( | |
| 177 bool active) { | |
| 178 if (active) { | |
| 179 StartScheduling(); | |
| 180 } else { | |
| 181 StopScheduling(); | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 void SchedulingRemoteSuggestionsProvider::StartScheduling() { | |
| 186 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 187 if (!persistent_scheduler_) { | |
| 188 return; | |
| 189 } | |
| 190 | |
| 191 FetchingSchedule last_schedule = GetLastFetchingSchedule(); | |
| 192 FetchingSchedule schedule = GetDesiredFetchingSchedule(); | |
| 193 | |
| 194 // Reset the schedule only if the parameters have changed. | |
| 195 if (last_schedule != schedule) { | |
| 196 ApplyFetchingSchedule(schedule); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 void SchedulingRemoteSuggestionsProvider::StopScheduling() { | |
| 201 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 202 if (!persistent_scheduler_) { | |
| 203 return; | |
| 204 } | |
| 205 | |
| 206 // Do not unschedule if already switched off | |
| 207 FetchingSchedule last_schedule = GetLastFetchingSchedule(); | |
| 208 if (last_schedule.is_empty()) { | |
| 209 return; | |
| 210 } | |
| 211 | |
| 212 persistent_scheduler_->Unschedule(); | |
| 213 | |
| 214 StoreLastFetchingSchedule(FetchingSchedule::Empty()); | |
| 215 } | |
| 216 | |
| 217 void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule( | |
| 218 FetchingSchedule schedule) { | |
| 219 persistent_scheduler_->Schedule(schedule.interval_wifi, | |
| 220 schedule.interval_fallback); | |
| 221 | |
| 222 StoreLastFetchingSchedule(schedule); | |
| 223 } | |
| 224 | |
| 225 SchedulingRemoteSuggestionsProvider::FetchingSchedule | |
| 226 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() { | |
| 227 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); | |
| 228 | |
| 229 FetchingSchedule schedule; | |
| 230 schedule.interval_wifi = | |
| 231 GetCurrentUpdateInterval(/*is_wifi=*/true, user_class); | |
| 232 schedule.interval_fallback = | |
| 233 GetCurrentUpdateInterval(/*is_wifi=*/false, user_class); | |
| 234 return schedule; | |
| 235 } | |
| 236 | |
| 237 SchedulingRemoteSuggestionsProvider::FetchingSchedule | |
| 238 SchedulingRemoteSuggestionsProvider::GetLastFetchingSchedule() const { | |
| 239 FetchingSchedule schedule; | |
| 240 schedule.interval_wifi = base::TimeDelta::FromInternalValue( | |
| 241 pref_service_->GetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi)); | |
| 242 schedule.interval_fallback = | |
| 243 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( | |
| 244 prefs::kSnippetBackgroundFetchingIntervalFallback)); | |
| 245 return schedule; | |
| 246 } | |
| 247 | |
| 248 void SchedulingRemoteSuggestionsProvider::StoreLastFetchingSchedule( | |
| 249 FetchingSchedule schedule) { | |
| 250 pref_service_->SetInt64( | |
| 251 prefs::kSnippetBackgroundFetchingIntervalWifi, | |
| 252 schedule.interval_wifi.ToInternalValue()); | |
| 253 pref_service_->SetInt64( | |
| 254 prefs::kSnippetBackgroundFetchingIntervalFallback, | |
| 255 schedule.interval_fallback.ToInternalValue()); | |
| 256 } | |
| 257 | |
| 258 void SchedulingRemoteSuggestionsProvider::FetchFinished( | |
| 259 const FetchDoneCallback& callback, | |
| 260 Status status_code, | |
| 261 std::vector<ContentSuggestion> suggestions) { | |
| 262 // Intercept |status_code| before calling the provided |callback|. | |
|
tschumann
2016/12/15 19:27:00
no need for the comment -- it's quite obvious :-)
jkrcal
2016/12/19 09:40:24
Done.
| |
| 263 OnFetchCompleted(status_code); | |
| 264 callback.Run(status_code, std::move(suggestions)); | |
| 265 } | |
| 266 | |
| 267 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted(Status status_code) { | |
| 268 // The scheduler only exists on Android so far, it's null on other platforms. | |
| 269 if (!persistent_scheduler_) { | |
| 270 return; | |
| 271 } | |
| 272 | |
| 273 if (status_code.status != StatusCode::SUCCESS) { | |
| 274 return; | |
| 275 } | |
| 276 | |
| 277 // Reschedule after a successful fetch. This resets all currently scheduled | |
| 278 // fetches, to make sure the fallback interval triggers only if no wifi fetch | |
| 279 // succeeded, and also that we don't do a background fetch immediately after | |
| 280 // a user-initiated one. | |
| 281 ApplyFetchingSchedule(GetLastFetchingSchedule()); | |
| 282 } | |
| 283 | |
| 284 } // namespace ntp_snippets | |
| OLD | NEW |