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