blob: c30c9ea7d2ec0f5dcb0d850756e82713369787cd [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "chrome/browser/offline_pages/prefetch/prefetch_background_task_scheduler.h"
#include "chrome/common/pref_names.h"
#include "components/offline_pages/core/offline_clock.h"
#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/prefetch/prefetch_prefs.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "net/base/backoff_entry_serializer.h"
namespace offline_pages {
namespace {
const int kDefaultSuspensionDays = 1;
const net::BackoffEntry::Policy kPrefetchBackoffPolicy = {
0, // Number of initial errors to ignore without backoff.
30 * 1000, // Initial delay for backoff in ms: 30 seconds.
2, // Factor to multiply for exponential backoff.
0.33, // Fuzzing percentage.
24 * 3600 * 1000, // Maximum time to delay requests in ms: 1 day.
-1, // Don't discard entry even if unused.
false // Don't use initial delay unless the last was an error.
};
} // namespace
PrefetchBackgroundTaskHandlerImpl::PrefetchBackgroundTaskHandlerImpl(
PrefService* prefs)
: prefs_(prefs), tick_clock_(base::DefaultTickClock::GetInstance()) {}
PrefetchBackgroundTaskHandlerImpl::~PrefetchBackgroundTaskHandlerImpl() =
default;
void PrefetchBackgroundTaskHandlerImpl::CancelBackgroundTask() {
PrefetchBackgroundTaskScheduler::Cancel();
}
void PrefetchBackgroundTaskHandlerImpl::EnsureTaskScheduled() {
if (IsLimitlessPrefetchingEnabled()) {
PrefetchBackgroundTaskScheduler::ScheduleLimitless(
GetAdditionalBackoffSeconds());
} else {
PrefetchBackgroundTaskScheduler::Schedule(GetAdditionalBackoffSeconds());
}
}
int PrefetchBackgroundTaskHandlerImpl::GetAdditionalBackoffSeconds() const {
return static_cast<int>(
GetCurrentBackoff()->GetTimeUntilRelease().InSeconds());
}
std::unique_ptr<net::BackoffEntry>
PrefetchBackgroundTaskHandlerImpl::GetCurrentBackoff() const {
const base::ListValue* value = prefs_->GetList(prefetch_prefs::kBackoff);
std::unique_ptr<net::BackoffEntry> result;
if (value) {
result = net::BackoffEntrySerializer::DeserializeFromValue(
*value, &kPrefetchBackoffPolicy, tick_clock_, OfflineTimeNow());
}
if (!result)
return std::make_unique<net::BackoffEntry>(&kPrefetchBackoffPolicy,
tick_clock_);
return result;
}
void PrefetchBackgroundTaskHandlerImpl::Backoff() {
std::unique_ptr<net::BackoffEntry> current = GetCurrentBackoff();
current->InformOfRequest(false);
UpdateBackoff(current.get());
}
void PrefetchBackgroundTaskHandlerImpl::ResetBackoff() {
std::unique_ptr<net::BackoffEntry> current = GetCurrentBackoff();
current->Reset();
UpdateBackoff(current.get());
}
void PrefetchBackgroundTaskHandlerImpl::PauseBackoffUntilNextRun() {
std::unique_ptr<net::BackoffEntry> current = GetCurrentBackoff();
// Erase the existing delay but retain the failure count so that the next
// time we run if backoff is requested again we will continue the exponential
// backoff from where we left off.
current->SetCustomReleaseTime(tick_clock_->NowTicks());
UpdateBackoff(current.get());
}
void PrefetchBackgroundTaskHandlerImpl::Suspend() {
std::unique_ptr<net::BackoffEntry> current = GetCurrentBackoff();
// Set the failure count to 0.
current->Reset();
// Set a custom delay to be a 1 day interval. After the day passes, the next
// backoff value will be back to the initial 30s delay.
current->SetCustomReleaseTime(
tick_clock_->NowTicks() +
base::TimeDelta::FromDays(kDefaultSuspensionDays));
UpdateBackoff(current.get());
}
void PrefetchBackgroundTaskHandlerImpl::RemoveSuspension() {
std::unique_ptr<net::BackoffEntry> current = GetCurrentBackoff();
// Reset the backoff completely, but only if the failure count is 0 and there
// is a custom delay. This should only happen after Suspend() has been called.
if (current->failure_count() == 0 && !current->GetReleaseTime().is_null())
current->Reset();
UpdateBackoff(current.get());
}
void PrefetchBackgroundTaskHandlerImpl::SetTickClockForTesting(
const base::TickClock* tick_clock) {
tick_clock_ = tick_clock;
}
void PrefetchBackgroundTaskHandlerImpl::UpdateBackoff(
net::BackoffEntry* backoff) {
std::unique_ptr<base::Value> value =
net::BackoffEntrySerializer::SerializeToValue(*backoff, OfflineTimeNow());
prefs_->Set(prefetch_prefs::kBackoff, *value);
}
} // namespace offline_pages