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

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

Issue 2774663002: [Remote suggestions] Refactor the scheduler (Closed)
Patch Set: Marc's nits #2 Created 3 years, 8 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/ntp_snippets/remote/scheduling_remote_suggestions_provider. h" 5 #include "components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h"
6 6
7 #include <random> 7 #include <random>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/metrics/field_trial_params.h" 13 #include "base/metrics/field_trial_params.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
16 #include "base/time/clock.h" 16 #include "base/time/clock.h"
17 #include "components/ntp_snippets/features.h" 17 #include "components/ntp_snippets/features.h"
18 #include "components/ntp_snippets/pref_names.h" 18 #include "components/ntp_snippets/pref_names.h"
19 #include "components/ntp_snippets/remote/persistent_scheduler.h" 19 #include "components/ntp_snippets/remote/persistent_scheduler.h"
20 #include "components/ntp_snippets/remote/remote_suggestions_provider.h"
20 #include "components/ntp_snippets/status.h" 21 #include "components/ntp_snippets/status.h"
21 #include "components/ntp_snippets/user_classifier.h" 22 #include "components/ntp_snippets/user_classifier.h"
22 #include "components/prefs/pref_registry_simple.h" 23 #include "components/prefs/pref_registry_simple.h"
23 #include "components/prefs/pref_service.h" 24 #include "components/prefs/pref_service.h"
24 25
25 namespace ntp_snippets { 26 namespace ntp_snippets {
26 27
27 namespace { 28 namespace {
28 29
29 // The FetchingInterval enum specifies overlapping time intervals that are used 30 // The FetchingInterval enum specifies overlapping time intervals that are used
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 } 166 }
166 167
167 private: 168 private:
168 std::unique_ptr<web_resource::EulaAcceptedNotifier> eula_notifier_; 169 std::unique_ptr<web_resource::EulaAcceptedNotifier> eula_notifier_;
169 RemoteSuggestionsScheduler* scheduler_; 170 RemoteSuggestionsScheduler* scheduler_;
170 171
171 DISALLOW_COPY_AND_ASSIGN(EulaState); 172 DISALLOW_COPY_AND_ASSIGN(EulaState);
172 }; 173 };
173 174
174 // static 175 // static
175 SchedulingRemoteSuggestionsProvider::FetchingSchedule 176 RemoteSuggestionsSchedulerImpl::FetchingSchedule
176 SchedulingRemoteSuggestionsProvider::FetchingSchedule::Empty() { 177 RemoteSuggestionsSchedulerImpl::FetchingSchedule::Empty() {
177 return FetchingSchedule{base::TimeDelta(), base::TimeDelta(), 178 return FetchingSchedule{base::TimeDelta(), base::TimeDelta(),
178 base::TimeDelta(), base::TimeDelta()}; 179 base::TimeDelta(), base::TimeDelta()};
179 } 180 }
180 181
181 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator==( 182 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::operator==(
182 const FetchingSchedule& other) const { 183 const FetchingSchedule& other) const {
183 return interval_persistent_wifi == other.interval_persistent_wifi && 184 return interval_persistent_wifi == other.interval_persistent_wifi &&
184 interval_persistent_fallback == other.interval_persistent_fallback && 185 interval_persistent_fallback == other.interval_persistent_fallback &&
185 interval_soft_on_usage_event == other.interval_soft_on_usage_event && 186 interval_soft_on_usage_event == other.interval_soft_on_usage_event &&
186 interval_soft_on_ntp_opened == other.interval_soft_on_ntp_opened; 187 interval_soft_on_ntp_opened == other.interval_soft_on_ntp_opened;
187 } 188 }
188 189
189 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator!=( 190 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::operator!=(
190 const FetchingSchedule& other) const { 191 const FetchingSchedule& other) const {
191 return !operator==(other); 192 return !operator==(other);
192 } 193 }
193 194
194 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const { 195 bool RemoteSuggestionsSchedulerImpl::FetchingSchedule::is_empty() const {
195 return interval_persistent_wifi.is_zero() && 196 return interval_persistent_wifi.is_zero() &&
196 interval_persistent_fallback.is_zero() && 197 interval_persistent_fallback.is_zero() &&
197 interval_soft_on_usage_event.is_zero() && 198 interval_soft_on_usage_event.is_zero() &&
198 interval_soft_on_ntp_opened.is_zero(); 199 interval_soft_on_ntp_opened.is_zero();
199 } 200 }
200 201
201 // The TriggerType enum specifies values for the events that can trigger 202 // The TriggerType enum specifies values for the events that can trigger
202 // fetching remote suggestions. These values are written to logs. New enum 203 // fetching remote suggestions. These values are written to logs. New enum
203 // values can be added, but existing enums must never be renumbered or deleted 204 // values can be added, but existing enums must never be renumbered or deleted
204 // and reused. When adding new entries, also update the array 205 // and reused. When adding new entries, also update the array
205 // |kTriggerTypeNames| above. 206 // |kTriggerTypeNames| above.
206 enum class SchedulingRemoteSuggestionsProvider::TriggerType { 207 enum class RemoteSuggestionsSchedulerImpl::TriggerType {
207 PERSISTENT_SCHEDULER_WAKE_UP = 0, 208 PERSISTENT_SCHEDULER_WAKE_UP = 0,
208 NTP_OPENED = 1, 209 NTP_OPENED = 1,
209 BROWSER_FOREGROUNDED = 2, 210 BROWSER_FOREGROUNDED = 2,
210 BROWSER_COLD_START = 3, 211 BROWSER_COLD_START = 3,
211 COUNT 212 COUNT
212 }; 213 };
213 214
214 SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider( 215 RemoteSuggestionsSchedulerImpl::RemoteSuggestionsSchedulerImpl(
215 Observer* observer,
216 std::unique_ptr<RemoteSuggestionsProvider> provider,
217 PersistentScheduler* persistent_scheduler, 216 PersistentScheduler* persistent_scheduler,
218 const UserClassifier* user_classifier, 217 const UserClassifier* user_classifier,
219 PrefService* profile_prefs, 218 PrefService* profile_prefs,
220 PrefService* local_state_prefs, 219 PrefService* local_state_prefs,
221 std::unique_ptr<base::Clock> clock) 220 std::unique_ptr<base::Clock> clock)
222 : RemoteSuggestionsProvider(observer), 221 : persistent_scheduler_(persistent_scheduler),
223 RemoteSuggestionsScheduler(),
224 provider_(std::move(provider)),
225 persistent_scheduler_(persistent_scheduler),
226 background_fetch_in_progress_(false), 222 background_fetch_in_progress_(false),
227 user_classifier_(user_classifier), 223 user_classifier_(user_classifier),
228 request_throttler_rare_ntp_user_( 224 request_throttler_rare_ntp_user_(
229 profile_prefs, 225 profile_prefs,
230 RequestThrottler::RequestType:: 226 RequestThrottler::RequestType::
231 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER), 227 CONTENT_SUGGESTION_FETCHER_RARE_NTP_USER),
232 request_throttler_active_ntp_user_( 228 request_throttler_active_ntp_user_(
233 profile_prefs, 229 profile_prefs,
234 RequestThrottler::RequestType:: 230 RequestThrottler::RequestType::
235 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER), 231 CONTENT_SUGGESTION_FETCHER_ACTIVE_NTP_USER),
236 request_throttler_active_suggestions_consumer_( 232 request_throttler_active_suggestions_consumer_(
237 profile_prefs, 233 profile_prefs,
238 RequestThrottler::RequestType:: 234 RequestThrottler::RequestType::
239 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER), 235 CONTENT_SUGGESTION_FETCHER_ACTIVE_SUGGESTIONS_CONSUMER),
240 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)), 236 eula_state_(base::MakeUnique<EulaState>(local_state_prefs, this)),
241 profile_prefs_(profile_prefs), 237 profile_prefs_(profile_prefs),
242 clock_(std::move(clock)), 238 clock_(std::move(clock)),
243 enabled_triggers_(GetEnabledTriggerTypes()) { 239 enabled_triggers_(GetEnabledTriggerTypes()) {
244 DCHECK(user_classifier); 240 DCHECK(user_classifier);
245 DCHECK(profile_prefs); 241 DCHECK(profile_prefs);
246 242
247 LoadLastFetchingSchedule(); 243 LoadLastFetchingSchedule();
248 } 244 }
249 245
250 SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() = 246 RemoteSuggestionsSchedulerImpl::~RemoteSuggestionsSchedulerImpl() = default;
251 default;
252 247
253 // static 248 // static
254 void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( 249 void RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs(
255 PrefRegistrySimple* registry) { 250 PrefRegistrySimple* registry) {
256 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0); 251 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0);
257 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback, 252 registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback,
258 0); 253 0);
259 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent, 254 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
260 0); 255 0);
261 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0); 256 registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0);
262 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened, 257 registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened,
263 0); 258 0);
264 } 259 }
265 260
266 void SchedulingRemoteSuggestionsProvider::OnProviderActivated() { 261 void RemoteSuggestionsSchedulerImpl::SetProvider(
262 RemoteSuggestionsProvider* provider) {
263 DCHECK(provider);
264 provider_ = provider;
265 }
266
267 void RemoteSuggestionsSchedulerImpl::OnProviderActivated() {
267 StartScheduling(); 268 StartScheduling();
268 } 269 }
269 270
270 void SchedulingRemoteSuggestionsProvider::OnProviderDeactivated() { 271 void RemoteSuggestionsSchedulerImpl::OnProviderDeactivated() {
271 StopScheduling(); 272 StopScheduling();
272 } 273 }
273 274
274 void SchedulingRemoteSuggestionsProvider::OnSuggestionsCleared() { 275 void RemoteSuggestionsSchedulerImpl::OnSuggestionsCleared() {
276 // This should be called by |provider_| so it should exist.
277 DCHECK(provider_);
275 // Some user action causes suggestions to be cleared, fetch now (as an 278 // Some user action causes suggestions to be cleared, fetch now (as an
276 // interactive request). 279 // interactive request).
277 ReloadSuggestions(); 280 provider_->ReloadSuggestions();
278 } 281 }
279 282
280 void SchedulingRemoteSuggestionsProvider::OnHistoryCleared() { 283 void RemoteSuggestionsSchedulerImpl::OnHistoryCleared() {
281 // Due to privacy, we should not fetch for a while (unless the user explicitly 284 // Due to privacy, we should not fetch for a while (unless the user explicitly
282 // asks for new suggestions) to give sync the time to propagate the changes in 285 // asks for new suggestions) to give sync the time to propagate the changes in
283 // history to the server. 286 // history to the server.
284 background_fetches_allowed_after_ = 287 background_fetches_allowed_after_ =
285 clock_->Now() + base::TimeDelta::FromMinutes( 288 clock_->Now() + base::TimeDelta::FromMinutes(
286 kBlockBackgroundFetchesMinutesAfterClearingHistory); 289 kBlockBackgroundFetchesMinutesAfterClearingHistory);
287 // After that time elapses, we should fetch as soon as possible. 290 // After that time elapses, we should fetch as soon as possible.
288 ClearLastFetchAttemptTime(); 291 ClearLastFetchAttemptTime();
289 } 292 }
290 293
291 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() { 294 void RemoteSuggestionsSchedulerImpl::RescheduleFetching() {
292 // Force the reschedule by stopping and starting it again. 295 // Force the reschedule by stopping and starting it again.
293 StopScheduling(); 296 StopScheduling();
294 StartScheduling(); 297 StartScheduling();
295 } 298 }
296 299
297 void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() { 300 bool RemoteSuggestionsSchedulerImpl::AcquireQuotaForInteractiveFetch() {
301 return AcquireQuota(/*interactive_request=*/true);
302 }
303
304 void RemoteSuggestionsSchedulerImpl::OnInteractiveFetchFinished(
305 Status fetch_status) {
306 OnFetchCompleted(fetch_status);
307 }
308
309 void RemoteSuggestionsSchedulerImpl::OnPersistentSchedulerWakeUp() {
298 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP); 310 RefetchInTheBackgroundIfEnabled(TriggerType::PERSISTENT_SCHEDULER_WAKE_UP);
299 } 311 }
300 312
301 void SchedulingRemoteSuggestionsProvider::OnBrowserForegrounded() { 313 void RemoteSuggestionsSchedulerImpl::OnBrowserForegrounded() {
302 // TODO(jkrcal): Consider that this is called whenever we open or return to an 314 // TODO(jkrcal): Consider that this is called whenever we open or return to an
303 // Activity. Therefore, keep work light for fast start up calls. 315 // Activity. Therefore, keep work light for fast start up calls.
304 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_FOREGROUNDED)) { 316 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_FOREGROUNDED)) {
305 return; 317 return;
306 } 318 }
307 319
308 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_FOREGROUNDED); 320 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_FOREGROUNDED);
309 } 321 }
310 322
311 void SchedulingRemoteSuggestionsProvider::OnBrowserColdStart() { 323 void RemoteSuggestionsSchedulerImpl::OnBrowserColdStart() {
312 // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast 324 // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast
313 // cold start ups. 325 // cold start ups.
314 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_COLD_START)) { 326 if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_COLD_START)) {
315 return; 327 return;
316 } 328 }
317 329
318 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_COLD_START); 330 RefetchInTheBackgroundIfEnabled(TriggerType::BROWSER_COLD_START);
319 } 331 }
320 332
321 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() { 333 void RemoteSuggestionsSchedulerImpl::OnNTPOpened() {
322 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) { 334 if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) {
323 return; 335 return;
324 } 336 }
325 337
326 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED); 338 RefetchInTheBackgroundIfEnabled(TriggerType::NTP_OPENED);
327 } 339 }
328 340
329 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground( 341 void RemoteSuggestionsSchedulerImpl::StartScheduling() {
330 std::unique_ptr<FetchStatusCallback> callback) {
331 if (background_fetch_in_progress_) {
332 if (callback) {
333 callback->Run(
334 Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress"));
335 }
336 return;
337 }
338
339 if (!AcquireQuota(/*interactive_request=*/false)) {
340 if (callback) {
341 callback->Run(Status(StatusCode::TEMPORARY_ERROR,
342 "Non-interactive quota exceeded"));
343 }
344 return;
345 }
346
347 background_fetch_in_progress_ = true;
348 RemoteSuggestionsProvider::FetchStatusCallback wrapper_callback = base::Bind(
349 &SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished,
350 base::Unretained(this), base::Passed(&callback));
351 provider_->RefetchInTheBackground(
352 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>(
353 std::move(wrapper_callback)));
354 }
355
356 const RemoteSuggestionsFetcher*
357 SchedulingRemoteSuggestionsProvider::suggestions_fetcher_for_debugging() const {
358 return provider_->suggestions_fetcher_for_debugging();
359 }
360
361 CategoryStatus SchedulingRemoteSuggestionsProvider::GetCategoryStatus(
362 Category category) {
363 return provider_->GetCategoryStatus(category);
364 }
365
366 CategoryInfo SchedulingRemoteSuggestionsProvider::GetCategoryInfo(
367 Category category) {
368 return provider_->GetCategoryInfo(category);
369 }
370
371 void SchedulingRemoteSuggestionsProvider::DismissSuggestion(
372 const ContentSuggestion::ID& suggestion_id) {
373 provider_->DismissSuggestion(suggestion_id);
374 }
375
376 void SchedulingRemoteSuggestionsProvider::FetchSuggestionImage(
377 const ContentSuggestion::ID& suggestion_id,
378 const ImageFetchedCallback& callback) {
379 provider_->FetchSuggestionImage(suggestion_id, callback);
380 }
381
382 void SchedulingRemoteSuggestionsProvider::Fetch(
383 const Category& category,
384 const std::set<std::string>& known_suggestion_ids,
385 const FetchDoneCallback& callback) {
386 if (!AcquireQuota(/*interactive_request=*/true)) {
387 if (callback) {
388 callback.Run(
389 Status(StatusCode::TEMPORARY_ERROR, "Interactive quota exceeded"),
390 std::vector<ContentSuggestion>());
391 }
392 return;
393 }
394
395 provider_->Fetch(
396 category, known_suggestion_ids,
397 base::Bind(&SchedulingRemoteSuggestionsProvider::FetchFinished,
398 base::Unretained(this), callback));
399 }
400
401 void SchedulingRemoteSuggestionsProvider::ReloadSuggestions() {
402 if (!AcquireQuota(/*interactive_request=*/true)) {
403 return;
404 }
405
406 provider_->ReloadSuggestions();
407 }
408
409 void SchedulingRemoteSuggestionsProvider::ClearHistory(
410 base::Time begin,
411 base::Time end,
412 const base::Callback<bool(const GURL& url)>& filter) {
413 provider_->ClearHistory(begin, end, filter);
414 }
415
416 void SchedulingRemoteSuggestionsProvider::ClearCachedSuggestions(
417 Category category) {
418 provider_->ClearCachedSuggestions(category);
419 }
420
421 void SchedulingRemoteSuggestionsProvider::OnSignInStateChanged() {
422 provider_->OnSignInStateChanged();
423 }
424
425 void SchedulingRemoteSuggestionsProvider::GetDismissedSuggestionsForDebugging(
426 Category category,
427 const DismissedSuggestionsCallback& callback) {
428 provider_->GetDismissedSuggestionsForDebugging(category, callback);
429 }
430
431 void SchedulingRemoteSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
432 Category category) {
433 provider_->ClearDismissedSuggestionsForDebugging(category);
434 }
435
436 void SchedulingRemoteSuggestionsProvider::StartScheduling() {
437 FetchingSchedule new_schedule = GetDesiredFetchingSchedule(); 342 FetchingSchedule new_schedule = GetDesiredFetchingSchedule();
438 343
439 if (schedule_ == new_schedule) { 344 if (schedule_ == new_schedule) {
440 // Do not schedule if nothing has changed; 345 // Do not schedule if nothing has changed;
441 return; 346 return;
442 } 347 }
443 348
444 schedule_ = new_schedule; 349 schedule_ = new_schedule;
445 StoreFetchingSchedule(); 350 StoreFetchingSchedule();
446 ApplyPersistentFetchingSchedule(); 351 ApplyPersistentFetchingSchedule();
447 } 352 }
448 353
449 void SchedulingRemoteSuggestionsProvider::StopScheduling() { 354 void RemoteSuggestionsSchedulerImpl::StopScheduling() {
450 if (schedule_.is_empty()) { 355 if (schedule_.is_empty()) {
451 // Do not unschedule if already switched off. 356 // Do not unschedule if already switched off.
452 return; 357 return;
453 } 358 }
454 359
455 schedule_ = FetchingSchedule::Empty(); 360 schedule_ = FetchingSchedule::Empty();
456 StoreFetchingSchedule(); 361 StoreFetchingSchedule();
457 ApplyPersistentFetchingSchedule(); 362 ApplyPersistentFetchingSchedule();
458 } 363 }
459 364
460 void SchedulingRemoteSuggestionsProvider::ApplyPersistentFetchingSchedule() { 365 void RemoteSuggestionsSchedulerImpl::ApplyPersistentFetchingSchedule() {
461 // The scheduler only exists on Android so far, it's null on other platforms. 366 // The scheduler only exists on Android so far, it's null on other platforms.
462 if (persistent_scheduler_) { 367 if (persistent_scheduler_) {
463 if (schedule_.is_empty()) { 368 if (schedule_.is_empty()) {
464 persistent_scheduler_->Unschedule(); 369 persistent_scheduler_->Unschedule();
465 } else { 370 } else {
466 persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi, 371 persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi,
467 schedule_.interval_persistent_fallback); 372 schedule_.interval_persistent_fallback);
468 } 373 }
469 } 374 }
470 } 375 }
471 376
472 SchedulingRemoteSuggestionsProvider::FetchingSchedule 377 RemoteSuggestionsSchedulerImpl::FetchingSchedule
473 SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const { 378 RemoteSuggestionsSchedulerImpl::GetDesiredFetchingSchedule() const {
474 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); 379 UserClassifier::UserClass user_class = user_classifier_->GetUserClass();
475 380
476 FetchingSchedule schedule; 381 FetchingSchedule schedule;
477 schedule.interval_persistent_wifi = 382 schedule.interval_persistent_wifi =
478 GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class); 383 GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class);
479 schedule.interval_persistent_fallback = GetDesiredFetchingInterval( 384 schedule.interval_persistent_fallback = GetDesiredFetchingInterval(
480 FetchingInterval::PERSISTENT_FALLBACK, user_class); 385 FetchingInterval::PERSISTENT_FALLBACK, user_class);
481 schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval( 386 schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval(
482 FetchingInterval::SOFT_ON_USAGE_EVENT, user_class); 387 FetchingInterval::SOFT_ON_USAGE_EVENT, user_class);
483 schedule.interval_soft_on_ntp_opened = GetDesiredFetchingInterval( 388 schedule.interval_soft_on_ntp_opened = GetDesiredFetchingInterval(
484 FetchingInterval::SOFT_ON_NTP_OPENED, user_class); 389 FetchingInterval::SOFT_ON_NTP_OPENED, user_class);
485 390
486 return schedule; 391 return schedule;
487 } 392 }
488 393
489 void SchedulingRemoteSuggestionsProvider::LoadLastFetchingSchedule() { 394 void RemoteSuggestionsSchedulerImpl::LoadLastFetchingSchedule() {
490 schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue( 395 schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue(
491 profile_prefs_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi)); 396 profile_prefs_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi));
492 schedule_.interval_persistent_fallback = 397 schedule_.interval_persistent_fallback =
493 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( 398 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64(
494 prefs::kSnippetPersistentFetchingIntervalFallback)); 399 prefs::kSnippetPersistentFetchingIntervalFallback));
495 schedule_.interval_soft_on_usage_event = 400 schedule_.interval_soft_on_usage_event =
496 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64( 401 base::TimeDelta::FromInternalValue(profile_prefs_->GetInt64(
497 prefs::kSnippetSoftFetchingIntervalOnUsageEvent)); 402 prefs::kSnippetSoftFetchingIntervalOnUsageEvent));
498 schedule_.interval_soft_on_ntp_opened = base::TimeDelta::FromInternalValue( 403 schedule_.interval_soft_on_ntp_opened = base::TimeDelta::FromInternalValue(
499 profile_prefs_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnNtpOpened)); 404 profile_prefs_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnNtpOpened));
500 } 405 }
501 406
502 void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() { 407 void RemoteSuggestionsSchedulerImpl::StoreFetchingSchedule() {
503 profile_prefs_->SetInt64( 408 profile_prefs_->SetInt64(
504 prefs::kSnippetPersistentFetchingIntervalWifi, 409 prefs::kSnippetPersistentFetchingIntervalWifi,
505 schedule_.interval_persistent_wifi.ToInternalValue()); 410 schedule_.interval_persistent_wifi.ToInternalValue());
506 profile_prefs_->SetInt64( 411 profile_prefs_->SetInt64(
507 prefs::kSnippetPersistentFetchingIntervalFallback, 412 prefs::kSnippetPersistentFetchingIntervalFallback,
508 schedule_.interval_persistent_fallback.ToInternalValue()); 413 schedule_.interval_persistent_fallback.ToInternalValue());
509 profile_prefs_->SetInt64( 414 profile_prefs_->SetInt64(
510 prefs::kSnippetSoftFetchingIntervalOnUsageEvent, 415 prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
511 schedule_.interval_soft_on_usage_event.ToInternalValue()); 416 schedule_.interval_soft_on_usage_event.ToInternalValue());
512 profile_prefs_->SetInt64( 417 profile_prefs_->SetInt64(
513 prefs::kSnippetSoftFetchingIntervalOnNtpOpened, 418 prefs::kSnippetSoftFetchingIntervalOnNtpOpened,
514 schedule_.interval_soft_on_ntp_opened.ToInternalValue()); 419 schedule_.interval_soft_on_ntp_opened.ToInternalValue());
515 } 420 }
516 421
517 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundIfEnabled( 422 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundIfEnabled(
518 SchedulingRemoteSuggestionsProvider::TriggerType trigger) { 423 TriggerType trigger) {
519 if (BackgroundFetchesDisabled(trigger)) { 424 if (BackgroundFetchesDisabled(trigger)) {
520 return; 425 return;
521 } 426 }
522 427
523 UMA_HISTOGRAM_ENUMERATION( 428 UMA_HISTOGRAM_ENUMERATION(
524 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger", 429 "NewTabPage.ContentSuggestions.BackgroundFetchTrigger",
525 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT)); 430 static_cast<int>(trigger), static_cast<int>(TriggerType::COUNT));
526 431
527 RefetchInTheBackground(/*callback=*/nullptr); 432 RefetchInTheBackground();
528 } 433 }
529 434
530 bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow( 435 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackground() {
531 SchedulingRemoteSuggestionsProvider::TriggerType trigger) { 436 if (background_fetch_in_progress_) {
437 return;
438 }
439
440 if (!AcquireQuota(/*interactive_request=*/false)) {
441 return;
442 }
443
444 background_fetch_in_progress_ = true;
445 provider_->RefetchInTheBackground(
446 base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>(
447 base::Bind(
448 &RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished,
449 base::Unretained(this))));
450 }
451
452 bool RemoteSuggestionsSchedulerImpl::ShouldRefetchInTheBackgroundNow(
453 TriggerType trigger) {
532 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue( 454 const base::Time last_fetch_attempt_time = base::Time::FromInternalValue(
533 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt)); 455 profile_prefs_->GetInt64(prefs::kSnippetLastFetchAttempt));
534 base::Time first_allowed_fetch_time; 456 base::Time first_allowed_fetch_time;
535 switch (trigger) { 457 switch (trigger) {
536 case TriggerType::NTP_OPENED: 458 case TriggerType::NTP_OPENED:
537 first_allowed_fetch_time = 459 first_allowed_fetch_time =
538 last_fetch_attempt_time + schedule_.interval_soft_on_ntp_opened; 460 last_fetch_attempt_time + schedule_.interval_soft_on_ntp_opened;
539 break; 461 break;
540 case TriggerType::BROWSER_FOREGROUNDED: 462 case TriggerType::BROWSER_FOREGROUNDED:
541 case TriggerType::BROWSER_COLD_START: 463 case TriggerType::BROWSER_COLD_START:
542 first_allowed_fetch_time = 464 first_allowed_fetch_time =
543 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event; 465 last_fetch_attempt_time + schedule_.interval_soft_on_usage_event;
544 break; 466 break;
545 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP: 467 case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP:
546 case TriggerType::COUNT: 468 case TriggerType::COUNT:
547 NOTREACHED(); 469 NOTREACHED();
548 break; 470 break;
549 } 471 }
550 base::Time now = clock_->Now(); 472 base::Time now = clock_->Now();
551 473
552 return background_fetches_allowed_after_ <= now && 474 return background_fetches_allowed_after_ <= now &&
553 first_allowed_fetch_time <= now; 475 first_allowed_fetch_time <= now;
554 } 476 }
555 477
556 bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled( 478 bool RemoteSuggestionsSchedulerImpl::BackgroundFetchesDisabled(
557 SchedulingRemoteSuggestionsProvider::TriggerType trigger) const { 479 TriggerType trigger) const {
480 if (!provider_) {
481 return true; // Cannot fetch as remote suggestions provider does not exist.
482 }
483
558 if (schedule_.is_empty()) { 484 if (schedule_.is_empty()) {
559 return true; // Background fetches are disabled in general. 485 return true; // Background fetches are disabled in general.
560 } 486 }
561 487
562 if (enabled_triggers_.count(trigger) == 0) { 488 if (enabled_triggers_.count(trigger) == 0) {
563 return true; // Background fetches for |trigger| are not enabled. 489 return true; // Background fetches for |trigger| are not enabled.
564 } 490 }
565 491
566 if (!eula_state_->IsEulaAccepted()) { 492 if (!eula_state_->IsEulaAccepted()) {
567 return true; // No background fetches are allowed before EULA is accepted. 493 return true; // No background fetches are allowed before EULA is accepted.
568 } 494 }
569 495
570 return false; 496 return false;
571 } 497 }
572 498
573 bool SchedulingRemoteSuggestionsProvider::AcquireQuota( 499 bool RemoteSuggestionsSchedulerImpl::AcquireQuota(bool interactive_request) {
574 bool interactive_request) {
575 switch (user_classifier_->GetUserClass()) { 500 switch (user_classifier_->GetUserClass()) {
576 case UserClassifier::UserClass::RARE_NTP_USER: 501 case UserClassifier::UserClass::RARE_NTP_USER:
577 return request_throttler_rare_ntp_user_.DemandQuotaForRequest( 502 return request_throttler_rare_ntp_user_.DemandQuotaForRequest(
578 interactive_request); 503 interactive_request);
579 case UserClassifier::UserClass::ACTIVE_NTP_USER: 504 case UserClassifier::UserClass::ACTIVE_NTP_USER:
580 return request_throttler_active_ntp_user_.DemandQuotaForRequest( 505 return request_throttler_active_ntp_user_.DemandQuotaForRequest(
581 interactive_request); 506 interactive_request);
582 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: 507 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER:
583 return request_throttler_active_suggestions_consumer_ 508 return request_throttler_active_suggestions_consumer_
584 .DemandQuotaForRequest(interactive_request); 509 .DemandQuotaForRequest(interactive_request);
585 } 510 }
586 NOTREACHED(); 511 NOTREACHED();
587 return false; 512 return false;
588 } 513 }
589 514
590 void SchedulingRemoteSuggestionsProvider::FetchFinished( 515 void RemoteSuggestionsSchedulerImpl::RefetchInTheBackgroundFinished(
591 const FetchDoneCallback& callback,
592 Status fetch_status,
593 std::vector<ContentSuggestion> suggestions) {
594 OnFetchCompleted(fetch_status);
595 if (callback) {
596 callback.Run(fetch_status, std::move(suggestions));
597 }
598 }
599
600 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished(
601 std::unique_ptr<FetchStatusCallback> callback,
602 Status fetch_status) { 516 Status fetch_status) {
603 background_fetch_in_progress_ = false; 517 background_fetch_in_progress_ = false;
604 OnFetchCompleted(fetch_status); 518 OnFetchCompleted(fetch_status);
605 if (callback) {
606 callback->Run(fetch_status);
607 }
608 } 519 }
609 520
610 void SchedulingRemoteSuggestionsProvider::OnFetchCompleted( 521 void RemoteSuggestionsSchedulerImpl::OnFetchCompleted(Status fetch_status) {
611 Status fetch_status) {
612 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt, 522 profile_prefs_->SetInt64(prefs::kSnippetLastFetchAttempt,
613 clock_->Now().ToInternalValue()); 523 clock_->Now().ToInternalValue());
614 524
615 // Reschedule after a fetch. The persistent schedule is applied only after a 525 // Reschedule after a fetch. The persistent schedule is applied only after a
616 // successful fetch. After a failed fetch, we want to keep the previous 526 // successful fetch. After a failed fetch, we want to keep the previous
617 // persistent schedule intact so that we eventually get a persistent 527 // persistent schedule intact so that we eventually get a persistent
618 // fallback fetch (if the wifi persistent fetches keep failing). 528 // fallback fetch (if the wifi persistent fetches keep failing).
619 if (fetch_status.code != StatusCode::SUCCESS) { 529 if (fetch_status.code != StatusCode::SUCCESS) {
620 return; 530 return;
621 } 531 }
622 ApplyPersistentFetchingSchedule(); 532 ApplyPersistentFetchingSchedule();
623 } 533 }
624 534
625 void SchedulingRemoteSuggestionsProvider::ClearLastFetchAttemptTime() { 535 void RemoteSuggestionsSchedulerImpl::ClearLastFetchAttemptTime() {
626 profile_prefs_->ClearPref(prefs::kSnippetLastFetchAttempt); 536 profile_prefs_->ClearPref(prefs::kSnippetLastFetchAttempt);
627 } 537 }
628 538
629 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> 539 std::set<RemoteSuggestionsSchedulerImpl::TriggerType>
630 SchedulingRemoteSuggestionsProvider::GetEnabledTriggerTypes() { 540 RemoteSuggestionsSchedulerImpl::GetEnabledTriggerTypes() {
631 static_assert(static_cast<unsigned int>(TriggerType::COUNT) == 541 static_assert(static_cast<unsigned int>(TriggerType::COUNT) ==
632 arraysize(kTriggerTypeNames), 542 arraysize(kTriggerTypeNames),
633 "Fill in names for trigger types."); 543 "Fill in names for trigger types.");
634 544
635 std::string param_value = base::GetFieldTrialParamValueByFeature( 545 std::string param_value = base::GetFieldTrialParamValueByFeature(
636 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName); 546 ntp_snippets::kArticleSuggestionsFeature, kTriggerTypesParamName);
637 if (param_value == kTriggerTypesParamValueForEmptyList) { 547 if (param_value == kTriggerTypesParamValueForEmptyList) {
638 return std::set<TriggerType>(); 548 return std::set<TriggerType>();
639 } 549 }
640 550
(...skipping 17 matching lines...) Expand all
658 return GetDefaultEnabledTriggerTypes(); 568 return GetDefaultEnabledTriggerTypes();
659 } 569 }
660 570
661 // Add the enabled type represented by |token| into the result set. 571 // Add the enabled type represented by |token| into the result set.
662 enabled_types.insert( 572 enabled_types.insert(
663 static_cast<TriggerType>(it - std::begin(kTriggerTypeNames))); 573 static_cast<TriggerType>(it - std::begin(kTriggerTypeNames)));
664 } 574 }
665 return enabled_types; 575 return enabled_types;
666 } 576 }
667 577
668 std::set<SchedulingRemoteSuggestionsProvider::TriggerType> 578 std::set<RemoteSuggestionsSchedulerImpl::TriggerType>
669 SchedulingRemoteSuggestionsProvider::GetDefaultEnabledTriggerTypes() { 579 RemoteSuggestionsSchedulerImpl::GetDefaultEnabledTriggerTypes() {
670 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED, 580 return {TriggerType::PERSISTENT_SCHEDULER_WAKE_UP, TriggerType::NTP_OPENED,
671 TriggerType::BROWSER_FOREGROUNDED}; 581 TriggerType::BROWSER_FOREGROUNDED};
672 } 582 }
673 583
674 } // namespace ntp_snippets 584 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698