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

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: Tim's comments and splitting RemoteSuggestionsProvider and RemoteSuggestionsProviderImpl Created 4 years 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 GetCurrentUpdateInterval(
Marc Treib 2016/12/19 12:59:24 GetDesiredUpdateInterval
jkrcal 2016/12/20 16:39:47 Yep, thanks!
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::FromHours(0),
77 base::TimeDelta::FromHours(0)};
Marc Treib 2016/12/19 12:59:23 Just use the default ctor of TimeDelta. (In fact,
jkrcal 2016/12/20 16:39:47 Done.
78 }
79
80 bool operator!=(const FetchingSchedule& other) const {
Marc Treib 2016/12/19 12:59:23 nit: If it has !=, it should probably also have ==
jkrcal 2016/12/20 16:39:47 Done.
81 return interval_wifi != other.interval_wifi ||
82 interval_fallback != other.interval_fallback;
83 }
84
85 bool is_empty() const {
86 return interval_wifi.is_zero() && interval_fallback.is_zero();
87 }
88 };
89
90 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider(
91 Observer* observer,
92 CategoryFactory* category_factory,
93 std::unique_ptr<RemoteSuggestionsProvider> provider,
94 PersistentScheduler* persistent_scheduler,
95 const UserClassifier* user_classifier,
96 PrefService* pref_service)
97 : ContentSuggestionsProvider(observer, category_factory),
98 provider_(std::move(provider)),
99 persistent_scheduler_(persistent_scheduler),
100 user_classifier_(user_classifier),
101 pref_service_(pref_service) {
102 DCHECK(user_classifier) << "non-null UserClassifier must be provided";
103 DCHECK(pref_service) << "non-null pref service is needed";
Marc Treib 2016/12/19 12:59:23 nit: Comments aren't really necessary; they're obv
jkrcal 2016/12/20 16:39:47 Done.
104
105 provider->SetProviderStatusCallback(base::BindRepeating(
106 &SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged,
107 base::Unretained(this)));
108 }
109
110 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() =
111 default;
112
113 // static
114 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs(
115 PrefRegistrySimple* registry) {
116 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0);
117 registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback,
118 0);
119 }
120
121 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() {
122 // Force the reschedule by stopping and starting it again.
123 StopScheduling();
124 StartScheduling();
125 }
126
127 void SchedulingRemoteSuggestionsProvider::OnFetchDue() {
128 provider_->RefetchInTheBackground(
129 base::Bind(&SchedulingRemoteSuggestionsProvider::OnFetchCompleted,
130 base::Unretained(this)));
131 }
132
133
134 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus(
135 Category category) {
136 return provider_->GetCategoryStatus(category);
137 }
138
139 CategoryInfo SchedulingRemoteSuggestionsProvider::GetCategoryInfo(
140 Category category) {
141 return provider_->GetCategoryInfo(category);
142 }
143
144 void SchedulingRemoteSuggestionsProvider::DismissSuggestion(
145 const ContentSuggestion::ID& suggestion_id) {
146 provider_->DismissSuggestion(suggestion_id);
147 }
148
149 void SchedulingRemoteSuggestionsProvider::FetchSuggestionImage(
150 const ContentSuggestion::ID& suggestion_id,
151 const ImageFetchedCallback& callback) {
152 provider_->FetchSuggestionImage(suggestion_id, callback);
153 }
154
155 void SchedulingRemoteSuggestionsProvider::Fetch(
156 const Category& category,
157 const std::set<std::string>& known_suggestion_ids,
158 const FetchDoneCallback& callback) {
159 provider_->Fetch(
160 category, known_suggestion_ids,
161 base::Bind(&SchedulingRemoteSuggestionsProvider::FetchFinished,
162 base::Unretained(this), callback));
163 }
164
165 void SchedulingRemoteSuggestionsProvider::ReloadSuggestions() {
166 provider_->ReloadSuggestions();
167 }
168
169 void SchedulingRemoteSuggestionsProvider::ClearHistory(
170 base::Time begin,
171 base::Time end,
172 const base::Callback<bool(const GURL& url)>& filter) {
173 provider_->ClearHistory(begin, end, filter);
174 }
175
176 void SchedulingRemoteSuggestionsProvider::ClearCachedSuggestions(
177 Category category) {
178 provider_->ClearCachedSuggestions(category);
179 }
180
181 void SchedulingRemoteSuggestionsProvider::OnSignInStateChanged() {
182 provider_->OnSignInStateChanged();
183 }
184
185 void SchedulingRemoteSuggestionsProvider::GetDismissedSuggestionsForDebugging(
186 Category category,
187 const DismissedSuggestionsCallback& callback) {
188 provider_->GetDismissedSuggestionsForDebugging(category, callback);
189 }
190
191 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
192 Category category) {
193 provider_->ClearDismissedSuggestionsForDebugging(category);
194 }
195
196 void SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged(
197 RemoteSuggestionsProvider::ProviderStatus status) {
198 switch (status) {
199 case RemoteSuggestionsProvider::ProviderStatus::ACTIVE:
200 StartScheduling();
201 return;
202 case RemoteSuggestionsProvider::ProviderStatus::INACTIVE:
203 StopScheduling();
204 return;
205 }
Marc Treib 2016/12/19 12:59:23 NOTREACHED();
jkrcal 2016/12/20 16:39:47 Done. Is this really needed? Does not the compiler
206 }
207
208 void SchedulingRemoteSuggestionsProvider::StartScheduling() {
209 // The scheduler only exists on Android so far, it's null on other platforms.
210 if (!persistent_scheduler_) {
211 return;
212 }
213
214 FetchingSchedule last_schedule = GetLastFetchingSchedule();
215 FetchingSchedule schedule = GetDesiredFetchingSchedule();
216
217 // Reset the schedule only if the parameters have changed.
218 if (last_schedule != schedule) {
219 ApplyFetchingSchedule(schedule);
220 }
221 }
222
223 void SchedulingRemoteSuggestionsProvider::StopScheduling() {
224 // The scheduler only exists on Android so far, it's null on other platforms.
225 if (!persistent_scheduler_) {
226 return;
227 }
228
229 // Do not unschedule if already switched off
230 FetchingSchedule last_schedule = GetLastFetchingSchedule();
231 if (last_schedule.is_empty()) {
232 return;
233 }
234
235 persistent_scheduler_->Unschedule();
236
237 StoreLastFetchingSchedule(FetchingSchedule::Empty());
238 }
239
240 void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule(
241 const FetchingSchedule& schedule) {
242 persistent_scheduler_->Schedule(schedule.interval_wifi,
243 schedule.interval_fallback);
244
245 StoreLastFetchingSchedule(schedule);
246 }
247
248 SchedulingRemoteSuggestionsProvider::FetchingSchedule
249 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() {
250 UserClassifier::UserClass user_class = user_classifier_->GetUserClass();
251
252 FetchingSchedule schedule;
253 schedule.interval_wifi =
254 GetCurrentUpdateInterval(/*is_wifi=*/true, user_class);
255 schedule.interval_fallback =
256 GetCurrentUpdateInterval(/*is_wifi=*/false, user_class);
257 return schedule;
258 }
259
260 SchedulingRemoteSuggestionsProvider::FetchingSchedule
261 SchedulingRemoteSuggestionsProvider::GetLastFetchingSchedule() const {
262 FetchingSchedule schedule;
263 schedule.interval_wifi = base::TimeDelta::FromInternalValue(
264 pref_service_->GetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi));
265 schedule.interval_fallback =
266 base::TimeDelta::FromInternalValue(pref_service_->GetInt64(
267 prefs::kSnippetBackgroundFetchingIntervalFallback));
268 return schedule;
269 }
270
271 void SchedulingRemoteSuggestionsProvider::StoreLastFetchingSchedule(
272 const FetchingSchedule& schedule) {
273 pref_service_->SetInt64(
274 prefs::kSnippetBackgroundFetchingIntervalWifi,
275 schedule.interval_wifi.ToInternalValue());
276 pref_service_->SetInt64(
277 prefs::kSnippetBackgroundFetchingIntervalFallback,
278 schedule.interval_fallback.ToInternalValue());
279 }
280
281 void SchedulingRemoteSuggestionsProvider::FetchFinished(
282 const FetchDoneCallback& callback,
283 Status status_code,
284 std::vector<ContentSuggestion> suggestions) {
285 OnFetchCompleted(status_code);
286 callback.Run(status_code, std::move(suggestions));
287 }
288
289 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted(
290 Status fetch_status) {
291 // The scheduler only exists on Android so far, it's null on other platforms.
292 if (!persistent_scheduler_) {
293 return;
294 }
295
296 if (fetch_status.code != StatusCode::SUCCESS) {
297 return;
298 }
299
300 // Reschedule after a successful fetch. This resets all currently scheduled
301 // fetches, to make sure the fallback interval triggers only if no wifi fetch
302 // succeeded, and also that we don't do a background fetch immediately after
303 // a user-initiated one.
304 ApplyFetchingSchedule(GetLastFetchingSchedule());
Marc Treib 2016/12/19 12:59:23 Just call RescheduleFetching?
jkrcal 2016/12/20 16:39:47 I prefer it this way because RescheduleFetching()
305 }
306
307 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698