Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Side by Side Diff: components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc

Issue 2557363002: [NTP Snippets] Refactor background scheduling for remote suggestions (Closed)
Patch Set: Changes to make unit-tests pass Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 std::unique_ptr<RemoteSuggestionsProvider> provider,
97 PersistentScheduler* persistent_scheduler,
98 const UserClassifier* user_classifier,
99 PrefService* pref_service)
100 : ContentSuggestionsProvider(observer),
101 RemoteSuggestionsScheduler(),
102 provider_(std::move(provider)),
103 persistent_scheduler_(persistent_scheduler),
104 user_classifier_(user_classifier),
105 pref_service_(pref_service) {
106 DCHECK(user_classifier);
107 DCHECK(pref_service);
108
109 provider_->SetProviderStatusCallback(
110 base::MakeUnique<RemoteSuggestionsProvider::ProviderStatusCallback>(
111 base::BindRepeating(
112 &SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged,
113 base::Unretained(this))));
114 }
115
116 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() =
117 default;
118
119 // static
120 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs(
121 PrefRegistrySimple* registry) {
122 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0);
123 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback,
124 0);
125 }
126
127 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() {
128 // Force the reschedule by stopping and starting it again.
129 StopScheduling();
130 StartScheduling();
131 }
132
133 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() {
134 provider_->RefetchInTheBackground(
135 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>(
136 base::Bind(&SchedulingRemoteSuggestionsProvider::OnFetchCompleted,
137 base::Unretained(this))));
138 }
139
140
141 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus(
142 Category category) {
143 return provider_->GetCategoryStatus(category);
144 }
145
146 CategoryInfo SchedulingRemoteSuggestionsProvider::GetCategoryInfo(
147 Category category) {
148 return provider_->GetCategoryInfo(category);
149 }
150
151 void SchedulingRemoteSuggestionsProvider::DismissSuggestion(
152 const ContentSuggestion::ID& suggestion_id) {
153 provider_->DismissSuggestion(suggestion_id);
154 }
155
156 void SchedulingRemoteSuggestionsProvider::FetchSuggestionImage(
157 const ContentSuggestion::ID& suggestion_id,
158 const ImageFetchedCallback& callback) {
159 provider_->FetchSuggestionImage(suggestion_id, callback);
160 }
161
162 void SchedulingRemoteSuggestionsProvider::Fetch(
163 const Category& category,
164 const std::set<std::string>& known_suggestion_ids,
165 const FetchDoneCallback& callback) {
166 provider_->Fetch(
167 category, known_suggestion_ids,
168 base::Bind(&SchedulingRemoteSuggestionsProvider::FetchFinished,
169 base::Unretained(this), callback));
170 }
171
172 void SchedulingRemoteSuggestionsProvider::ReloadSuggestions() {
173 provider_->ReloadSuggestions();
174 }
175
176 void SchedulingRemoteSuggestionsProvider::ClearHistory(
177 base::Time begin,
178 base::Time end,
179 const base::Callback<bool(const GURL& url)>& filter) {
180 provider_->ClearHistory(begin, end, filter);
181 }
182
183 void SchedulingRemoteSuggestionsProvider::ClearCachedSuggestions(
184 Category category) {
185 provider_->ClearCachedSuggestions(category);
186 }
187
188 void SchedulingRemoteSuggestionsProvider::OnSignInStateChanged() {
189 provider_->OnSignInStateChanged();
190 }
191
192 void SchedulingRemoteSuggestionsProvider::GetDismissedSuggestionsForDebugging(
193 Category category,
194 const DismissedSuggestionsCallback& callback) {
195 provider_->GetDismissedSuggestionsForDebugging(category, callback);
196 }
197
198 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
199 Category category) {
200 provider_->ClearDismissedSuggestionsForDebugging(category);
201 }
202
203 void SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged(
204 RemoteSuggestionsProvider::ProviderStatus status) {
205 switch (status) {
206 case RemoteSuggestionsProvider::ProviderStatus::ACTIVE:
207 StartScheduling();
208 return;
209 case RemoteSuggestionsProvider::ProviderStatus::INACTIVE:
210 StopScheduling();
211 return;
212 }
213 NOTREACHED();
214 }
215
216 void SchedulingRemoteSuggestionsProvider::StartScheduling() {
217 // The scheduler only exists on Android so far, it's null on other platforms.
218 if (!persistent_scheduler_) {
219 return;
220 }
221
222 FetchingSchedule last_schedule = GetLastFetchingSchedule();
223 FetchingSchedule schedule = GetDesiredFetchingSchedule();
224
225 // Reset the schedule only if the parameters have changed.
226 if (last_schedule != schedule) {
227 ApplyFetchingSchedule(schedule);
228 }
229 }
230
231 void SchedulingRemoteSuggestionsProvider::StopScheduling() {
232 // The scheduler only exists on Android so far, it's null on other platforms.
233 if (!persistent_scheduler_) {
234 return;
235 }
236
237 // Do not unschedule if already switched off
238 FetchingSchedule last_schedule = GetLastFetchingSchedule();
239 if (last_schedule.is_empty()) {
240 return;
241 }
242
243 persistent_scheduler_->Unschedule();
244
245 StoreLastFetchingSchedule(FetchingSchedule::Empty());
246 }
247
248 void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule(
249 const FetchingSchedule& schedule) {
250 persistent_scheduler_->Schedule(schedule.interval_wifi,
251 schedule.interval_fallback);
252
253 StoreLastFetchingSchedule(schedule);
254 }
255
256 SchedulingRemoteSuggestionsProvider::FetchingSchedule
257 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const {
258 UserClassifier::UserClass user_class = user_classifier_->GetUserClass();
259
260 FetchingSchedule schedule;
261 schedule.interval_wifi =
262 GetDesiredUpdateInterval(/*is_wifi=*/true, user_class);
263 schedule.interval_fallback =
264 GetDesiredUpdateInterval(/*is_wifi=*/false, user_class);
265 return schedule;
266 }
267
268 SchedulingRemoteSuggestionsProvider::FetchingSchedule
269 SchedulingRemoteSuggestionsProvider::GetLastFetchingSchedule() const {
270 FetchingSchedule schedule;
271 schedule.interval_wifi = base::TimeDelta::FromInternalValue(
272 pref_service_->GetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi));
273 schedule.interval_fallback =
274 base::TimeDelta::FromInternalValue(pref_service_->GetInt64(
275 prefs::kSnippetBackgroundFetchingIntervalFallback));
276 return schedule;
277 }
278
279 void SchedulingRemoteSuggestionsProvider::StoreLastFetchingSchedule(
280 const FetchingSchedule& schedule) {
281 pref_service_->SetInt64(
282 prefs::kSnippetBackgroundFetchingIntervalWifi,
283 schedule.interval_wifi.ToInternalValue());
284 pref_service_->SetInt64(
285 prefs::kSnippetBackgroundFetchingIntervalFallback,
286 schedule.interval_fallback.ToInternalValue());
287 }
288
289 void SchedulingRemoteSuggestionsProvider::FetchFinished(
290 const FetchDoneCallback& callback,
291 Status status_code,
292 std::vector<ContentSuggestion> suggestions) {
293 OnFetchCompleted(status_code);
294 callback.Run(status_code, std::move(suggestions));
295 }
296
297 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted(
298 Status fetch_status) {
299 // The scheduler only exists on Android so far, it's null on other platforms.
300 if (!persistent_scheduler_) {
301 return;
302 }
303
304 if (fetch_status.code != StatusCode::SUCCESS) {
305 return;
306 }
307
308 // Reschedule after a successful fetch. This resets all currently scheduled
309 // fetches, to make sure the fallback interval triggers only if no wifi fetch
310 // succeeded, and also that we don't do a background fetch immediately after
311 // a user-initiated one.
312 ApplyFetchingSchedule(GetLastFetchingSchedule());
313 }
314
315 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698