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

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: Rebase 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 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698