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

Unified Diff: components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc

Issue 2611523004: [Background fetching] Background fetching when opening an NTP. (Closed)
Patch Set: Rebase Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
index 7387410d8cc7b624f27103882229b4c152fd2094..315126ec56fbb95ff6f77a819902d5eaa4d0fe27 100644
--- a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
+++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
@@ -4,10 +4,12 @@
#include "components/ntp_snippets/remote/scheduling_remote_suggestions_provider.h"
+#include <random>
#include <string>
#include <utility>
#include "base/memory/ptr_util.h"
+#include "base/time/clock.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/persistent_scheduler.h"
@@ -21,28 +23,57 @@ namespace ntp_snippets {
namespace {
+enum class FetchingInterval {
+ PERSISTENT_FALLBACK,
+ PERSISTENT_WIFI,
+ SOFT_ON_USAGE_EVENT,
+ COUNT
+};
+
// Default values for fetching intervals, fallback and wifi.
-const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0};
-const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0};
-const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0};
+const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0, 12.0};
+const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0, 2.0};
+const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0,
+ 2.0};
// Variation parameters than can the default fetching intervals.
const char* kFetchingIntervalParamNameRareNtpUser[] = {
"fetching_interval_hours-fallback-rare_ntp_user",
- "fetching_interval_hours-wifi-rare_ntp_user"};
+ "fetching_interval_hours-wifi-rare_ntp_user",
+ "soft_fetching_interval_hours-active-rare_ntp_user"};
const char* kFetchingIntervalParamNameActiveNtpUser[] = {
"fetching_interval_hours-fallback-active_ntp_user",
- "fetching_interval_hours-wifi-active_ntp_user"};
+ "fetching_interval_hours-wifi-active_ntp_user",
+ "soft_fetching_interval_hours-active-active_ntp_user"};
const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = {
"fetching_interval_hours-fallback-active_suggestions_consumer",
- "fetching_interval_hours-wifi-active_suggestions_consumer"};
-
-base::TimeDelta GetDesiredUpdateInterval(
- bool is_wifi,
+ "fetching_interval_hours-wifi-active_suggestions_consumer",
+ "soft_fetching_interval_hours-active-active_suggestions_consumer"};
+
+static_assert(
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kDefaultFetchingIntervalRareNtpUser) &&
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kDefaultFetchingIntervalActiveNtpUser) &&
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kDefaultFetchingIntervalActiveSuggestionsConsumer) &&
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kFetchingIntervalParamNameRareNtpUser) &&
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kFetchingIntervalParamNameActiveNtpUser) &&
+ static_cast<unsigned int>(FetchingInterval::COUNT) ==
+ arraysize(kFetchingIntervalParamNameActiveSuggestionsConsumer),
+ "Fill in all the info for fetching intervals.");
+
+base::TimeDelta GetDesiredFetchingInterval(
+ FetchingInterval interval,
UserClassifier::UserClass user_class) {
double default_value_hours = 0.0;
- const int index = is_wifi ? 1 : 0;
+ DCHECK(interval != FetchingInterval::COUNT);
+ const unsigned int index = static_cast<unsigned int>(interval);
+ DCHECK(index < arraysize(kDefaultFetchingIntervalRareNtpUser));
+
const char* param_name = nullptr;
switch (user_class) {
case UserClassifier::UserClass::RARE_NTP_USER:
@@ -69,44 +100,51 @@ base::TimeDelta GetDesiredUpdateInterval(
} // namespace
-struct SchedulingRemoteSuggestionsProvider::FetchingSchedule {
- base::TimeDelta interval_wifi;
- base::TimeDelta interval_fallback;
-
- static FetchingSchedule Empty() {
- return FetchingSchedule{base::TimeDelta(),
- base::TimeDelta()};
- }
+// static
+SchedulingRemoteSuggestionsProvider::FetchingSchedule
+SchedulingRemoteSuggestionsProvider::FetchingSchedule::Empty() {
+ return FetchingSchedule{base::TimeDelta(), base::TimeDelta(),
+ base::TimeDelta()};
+}
- bool operator==(const FetchingSchedule& other) const {
- return interval_wifi == other.interval_wifi &&
- interval_fallback == other.interval_fallback;
- }
+bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator==(
+ const FetchingSchedule& other) const {
+ return interval_persistent_wifi == other.interval_persistent_wifi &&
+ interval_persistent_fallback == other.interval_persistent_fallback &&
+ interval_soft_on_usage_event == other.interval_soft_on_usage_event;
+}
- bool operator!=(const FetchingSchedule& other) const {
- return !operator==(other);
- }
+bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator!=(
+ const FetchingSchedule& other) const {
+ return !operator==(other);
+}
- bool is_empty() const {
- return interval_wifi.is_zero() && interval_fallback.is_zero();
- }
-};
+bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const {
+ return interval_persistent_wifi.is_zero() &&
+ interval_persistent_fallback.is_zero() &&
+ interval_soft_on_usage_event.is_zero();
+}
SchedulingRemoteSuggestionsProvider::SchedulingRemoteSuggestionsProvider(
Observer* observer,
std::unique_ptr<RemoteSuggestionsProvider> provider,
PersistentScheduler* persistent_scheduler,
const UserClassifier* user_classifier,
- PrefService* pref_service)
+ PrefService* pref_service,
+ std::unique_ptr<base::Clock> clock)
: RemoteSuggestionsProvider(observer),
RemoteSuggestionsScheduler(),
provider_(std::move(provider)),
persistent_scheduler_(persistent_scheduler),
+ background_fetch_in_progress_(false),
user_classifier_(user_classifier),
- pref_service_(pref_service) {
+ pref_service_(pref_service),
+ clock_(std::move(clock)) {
DCHECK(user_classifier);
DCHECK(pref_service);
+ LoadLastFetchingSchedule();
+
provider_->SetProviderStatusCallback(
base::MakeUnique<RemoteSuggestionsProvider::ProviderStatusCallback>(
base::BindRepeating(
@@ -120,9 +158,12 @@ SchedulingRemoteSuggestionsProvider::~SchedulingRemoteSuggestionsProvider() =
// static
void SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
- registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0);
- registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback,
+ registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalWifi, 0);
+ registry->RegisterInt64Pref(prefs::kSnippetPersistentFetchingIntervalFallback,
+ 0);
+ registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
0);
+ registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0);
}
void SchedulingRemoteSuggestionsProvider::RescheduleFetching() {
@@ -132,10 +173,11 @@ void SchedulingRemoteSuggestionsProvider::RescheduleFetching() {
}
void SchedulingRemoteSuggestionsProvider::OnPersistentSchedulerWakeUp() {
- provider_->RefetchInTheBackground(
- base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>(
- base::Bind(&SchedulingRemoteSuggestionsProvider::OnFetchCompleted,
- base::Unretained(this))));
+ if (BackgroundFetchesDisabled()) {
+ return;
+ }
+
+ RefetchInTheBackground(/*callback=*/nullptr);
}
void SchedulingRemoteSuggestionsProvider::OnBrowserStartup() {
@@ -143,17 +185,35 @@ void SchedulingRemoteSuggestionsProvider::OnBrowserStartup() {
}
void SchedulingRemoteSuggestionsProvider::OnNTPOpened() {
- // TODO(jkrcal): Implement.
+ if (BackgroundFetchesDisabled() || !ShouldRefetchInTheBackgroundNow()) {
+ return;
+ }
+
+ RefetchInTheBackground(/*callback=*/nullptr);
}
void SchedulingRemoteSuggestionsProvider::SetProviderStatusCallback(
- std::unique_ptr<ProviderStatusCallback> callback) {
+ std::unique_ptr<ProviderStatusCallback> callback) {
provider_->SetProviderStatusCallback(std::move(callback));
}
void SchedulingRemoteSuggestionsProvider::RefetchInTheBackground(
std::unique_ptr<FetchStatusCallback> callback) {
- provider_->RefetchInTheBackground(std::move(callback));
+ if (background_fetch_in_progress_) {
+ if (callback) {
+ callback->Run(
+ Status(StatusCode::TEMPORARY_ERROR, "Background fetch in progress"));
+ }
+ return;
+ }
+
+ background_fetch_in_progress_ = true;
+ RemoteSuggestionsProvider::FetchStatusCallback wrapper_callback = base::Bind(
+ &SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished,
+ base::Unretained(this), base::Passed(&callback));
+ provider_->RefetchInTheBackground(
+ base::MakeUnique<RemoteSuggestionsProvider::FetchStatusCallback>(
+ std::move(wrapper_callback)));
}
const NTPSnippetsFetcher* SchedulingRemoteSuggestionsProvider::
@@ -237,43 +297,39 @@ void SchedulingRemoteSuggestionsProvider::OnProviderStatusChanged(
}
void SchedulingRemoteSuggestionsProvider::StartScheduling() {
- // The scheduler only exists on Android so far, it's null on other platforms.
- if (!persistent_scheduler_) {
+ FetchingSchedule new_schedule = GetDesiredFetchingSchedule();
+
+ if (schedule_ == new_schedule) {
+ // Do not schedule if nothing has changed;
return;
}
- FetchingSchedule last_schedule = GetLastFetchingSchedule();
- FetchingSchedule schedule = GetDesiredFetchingSchedule();
-
- // Reset the schedule only if the parameters have changed.
- if (last_schedule != schedule) {
- ApplyFetchingSchedule(schedule);
- }
+ schedule_ = new_schedule;
+ StoreFetchingSchedule();
+ ApplyPersistentFetchingSchedule();
}
void SchedulingRemoteSuggestionsProvider::StopScheduling() {
- // The scheduler only exists on Android so far, it's null on other platforms.
- if (!persistent_scheduler_) {
+ if (schedule_.is_empty()) {
+ // Do not unschedule if already switched off.
return;
}
- // Do not unschedule if already switched off
- FetchingSchedule last_schedule = GetLastFetchingSchedule();
- if (last_schedule.is_empty()) {
- return;
- }
-
- persistent_scheduler_->Unschedule();
-
- StoreLastFetchingSchedule(FetchingSchedule::Empty());
+ schedule_ = FetchingSchedule::Empty();
+ StoreFetchingSchedule();
+ ApplyPersistentFetchingSchedule();
}
-void SchedulingRemoteSuggestionsProvider::ApplyFetchingSchedule(
- const FetchingSchedule& schedule) {
- persistent_scheduler_->Schedule(schedule.interval_wifi,
- schedule.interval_fallback);
-
- StoreLastFetchingSchedule(schedule);
+void SchedulingRemoteSuggestionsProvider::ApplyPersistentFetchingSchedule() {
+ // The scheduler only exists on Android so far, it's null on other platforms.
+ if (persistent_scheduler_) {
+ if (schedule_.is_empty()) {
+ persistent_scheduler_->Unschedule();
+ } else {
+ persistent_scheduler_->Schedule(schedule_.interval_persistent_wifi,
+ schedule_.interval_persistent_fallback);
+ }
+ }
}
SchedulingRemoteSuggestionsProvider::FetchingSchedule
@@ -281,58 +337,82 @@ SchedulingRemoteSuggestionsProvider::GetDesiredFetchingSchedule() const {
UserClassifier::UserClass user_class = user_classifier_->GetUserClass();
FetchingSchedule schedule;
- schedule.interval_wifi =
- GetDesiredUpdateInterval(/*is_wifi=*/true, user_class);
- schedule.interval_fallback =
- GetDesiredUpdateInterval(/*is_wifi=*/false, user_class);
+ schedule.interval_persistent_wifi =
+ GetDesiredFetchingInterval(FetchingInterval::PERSISTENT_WIFI, user_class);
+ schedule.interval_persistent_fallback = GetDesiredFetchingInterval(
+ FetchingInterval::PERSISTENT_FALLBACK, user_class);
+ schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval(
+ FetchingInterval::SOFT_ON_USAGE_EVENT, user_class);
+
return schedule;
}
-SchedulingRemoteSuggestionsProvider::FetchingSchedule
-SchedulingRemoteSuggestionsProvider::GetLastFetchingSchedule() const {
- FetchingSchedule schedule;
- schedule.interval_wifi = base::TimeDelta::FromInternalValue(
- pref_service_->GetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi));
- schedule.interval_fallback =
+void SchedulingRemoteSuggestionsProvider::LoadLastFetchingSchedule() {
+ schedule_.interval_persistent_wifi = base::TimeDelta::FromInternalValue(
+ pref_service_->GetInt64(prefs::kSnippetPersistentFetchingIntervalWifi));
+ schedule_.interval_persistent_fallback =
base::TimeDelta::FromInternalValue(pref_service_->GetInt64(
- prefs::kSnippetBackgroundFetchingIntervalFallback));
- return schedule;
+ prefs::kSnippetPersistentFetchingIntervalFallback));
+ schedule_.interval_soft_on_usage_event = base::TimeDelta::FromInternalValue(
+ pref_service_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnUsageEvent));
}
-void SchedulingRemoteSuggestionsProvider::StoreLastFetchingSchedule(
- const FetchingSchedule& schedule) {
+void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() {
+ pref_service_->SetInt64(prefs::kSnippetPersistentFetchingIntervalWifi,
+ schedule_.interval_persistent_wifi.ToInternalValue());
pref_service_->SetInt64(
- prefs::kSnippetBackgroundFetchingIntervalWifi,
- schedule.interval_wifi.ToInternalValue());
+ prefs::kSnippetPersistentFetchingIntervalFallback,
+ schedule_.interval_persistent_fallback.ToInternalValue());
pref_service_->SetInt64(
- prefs::kSnippetBackgroundFetchingIntervalFallback,
- schedule.interval_fallback.ToInternalValue());
+ prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
+ schedule_.interval_soft_on_usage_event.ToInternalValue());
+}
+
+bool SchedulingRemoteSuggestionsProvider::BackgroundFetchesDisabled() const {
+ return schedule_.is_empty();
+}
+
+bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow() {
+ base::Time first_allowed_fetch_time =
+ base::Time::FromInternalValue(
+ pref_service_->GetInt64(prefs::kSnippetLastFetchAttempt)) +
+ schedule_.interval_soft_on_usage_event;
+ return first_allowed_fetch_time <= clock_->Now();
}
void SchedulingRemoteSuggestionsProvider::FetchFinished(
const FetchDoneCallback& callback,
- Status status_code,
+ Status fetch_status,
std::vector<ContentSuggestion> suggestions) {
- OnFetchCompleted(status_code);
- callback.Run(status_code, std::move(suggestions));
+ OnFetchCompleted(fetch_status);
+ if (callback) {
+ callback.Run(fetch_status, std::move(suggestions));
+ }
}
-void SchedulingRemoteSuggestionsProvider::OnFetchCompleted(
+void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundFinished(
+ std::unique_ptr<FetchStatusCallback> callback,
Status fetch_status) {
- // The scheduler only exists on Android so far, it's null on other platforms.
- if (!persistent_scheduler_) {
- return;
+ background_fetch_in_progress_ = false;
+ OnFetchCompleted(fetch_status);
+ if (callback) {
+ callback->Run(fetch_status);
}
+}
+void SchedulingRemoteSuggestionsProvider::OnFetchCompleted(
+ Status fetch_status) {
+ pref_service_->SetInt64(prefs::kSnippetLastFetchAttempt,
+ clock_->Now().ToInternalValue());
+
+ // Reschedule after a fetch. The persistent schedule is applied only after a
+ // successful fetch. After a failed fetch, we want to keep the previous
+ // persistent schedule intact so that we eventually get a persistent
+ // fallback fetch (if the wifi persistent fetches keep failing).
if (fetch_status.code != StatusCode::SUCCESS) {
return;
}
-
- // Reschedule after a successful fetch. This resets all currently scheduled
- // fetches, to make sure the fallback interval triggers only if no wifi fetch
- // succeeded, and also that we don't do a background fetch immediately after
- // a user-initiated one.
- ApplyFetchingSchedule(GetLastFetchingSchedule());
+ ApplyPersistentFetchingSchedule();
}
} // namespace ntp_snippets

Powered by Google App Engine
This is Rietveld 408576698