Chromium Code Reviews| Index: chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc |
| diff --git a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc |
| index 17870fc266aa912de6ec434630e4ae561a8aa7a7..df4db84ff12939af4449e79c4d2588c054b508c3 100644 |
| --- a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc |
| +++ b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc |
| @@ -4,18 +4,34 @@ |
| #include "chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h" |
| +#include "base/time/time.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_android.h" |
| +#include "chrome/common/pref_names.h" |
| #include "components/offline_pages/content/prefetch_service_factory.h" |
| #include "components/offline_pages/core/prefetch/prefetch_service.h" |
| +#include "components/prefs/pref_registry_simple.h" |
| +#include "components/prefs/pref_service.h" |
| #include "content/public/browser/browser_context.h" |
| #include "jni/PrefetchBackgroundTask_jni.h" |
| +#include "net/base/backoff_entry_serializer.h" |
| using base::android::JavaParamRef; |
| using base::android::ScopedJavaGlobalRef; |
| using base::android::ScopedJavaLocalRef; |
| namespace offline_pages { |
| + |
| +const net::BackoffEntry::Policy kBackoffPolicy = { |
| + 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 prefetch { |
| // JNI call to start request processing in scheduled mode. |
| @@ -31,16 +47,22 @@ static jboolean StartPrefetchTask(JNIEnv* env, |
| return false; |
| prefetch_service->GetDispatcher()->BeginBackgroundTask( |
| - base::MakeUnique<PrefetchBackgroundTask>(env, jcaller, prefetch_service)); |
| - return true; |
| + base::MakeUnique<PrefetchBackgroundTask>(env, jcaller, prefetch_service, |
| + profile)); |
| + return false; // true; |
| } |
| } // namespace prefetch |
| +void RegisterPrefetchBackgroundTaskPrefs(PrefRegistrySimple* registry) { |
| + registry->RegisterListPref(prefs::kOfflinePrefetchBackoff); |
| +} |
| + |
| // static |
| -void PrefetchBackgroundTask::Schedule() { |
| +void PrefetchBackgroundTask::Schedule(int additional_delay_seconds) { |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| - return prefetch::Java_PrefetchBackgroundTask_scheduleTask(env); |
| + return prefetch::Java_PrefetchBackgroundTask_scheduleTask( |
| + env, additional_delay_seconds); |
| } |
| // static |
| @@ -52,29 +74,87 @@ void PrefetchBackgroundTask::Cancel() { |
| PrefetchBackgroundTask::PrefetchBackgroundTask( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& java_prefetch_background_task, |
| - PrefetchService* service) |
| + PrefetchService* service, |
| + Profile* profile) |
| : java_prefetch_background_task_(java_prefetch_background_task), |
| - service_(service) { |
| + service_(service), |
| + profile_(profile) { |
| // Give the Java side a pointer to the new background task object. |
| prefetch::Java_PrefetchBackgroundTask_setNativeTask( |
| env, java_prefetch_background_task_, reinterpret_cast<jlong>(this)); |
| + |
| + SetupBackOff(); |
| } |
| PrefetchBackgroundTask::~PrefetchBackgroundTask() { |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| prefetch::Java_PrefetchBackgroundTask_doneProcessing( |
| env, java_prefetch_background_task_.obj(), needs_reschedule_); |
| + |
| + if (!task_killed_by_system_ && needs_reschedule_) |
| + Schedule(GetAdditionalBackoffSeconds()); |
| +} |
| + |
| +void PrefetchBackgroundTask::SetupBackOff() { |
| + const base::ListValue* value = |
| + profile_->GetPrefs()->GetList(prefs::kOfflinePrefetchBackoff); |
| + if (value) { |
| + backoff_ = net::BackoffEntrySerializer::DeserializeFromValue( |
| + *value, &kBackoffPolicy, nullptr, base::Time::Now()); |
| + } |
| + |
| + if (!backoff_) |
| + backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); |
| } |
| bool PrefetchBackgroundTask::OnStopTask(JNIEnv* env, |
| const JavaParamRef<jobject>& jcaller) { |
| DCHECK(jcaller.obj() == java_prefetch_background_task_.obj()); |
| - service_->GetDispatcher()->StopBackgroundTask(this); |
| - return needs_reschedule_; |
| + task_killed_by_system_ = true; |
| + service_->GetDispatcher()->StopBackgroundTask(); |
| + |
| + // Reschedules our task since the system decides to kill it before it is |
| + // finished. Notes that we should reschedule without backoff even when it is |
| + // in effect because we want to rerun the task asap. |
| + if (GetAdditionalBackoffSeconds()) { |
| + Schedule(0); |
|
dewittj
2017/06/01 00:22:27
Should we always Schedule(0) instead of sometimes
jianli
2017/06/02 00:48:37
Done.
|
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +void PrefetchBackgroundTask::SetTaskRescheduling( |
| + JNIEnv* env, |
| + const base::android::JavaParamRef<jobject>& jcaller, |
| + jboolean reschedule, |
| + jboolean backoff) { |
| + DCHECK(jcaller.obj() == java_prefetch_background_task_.obj()); |
| + SetNeedsReschedule(static_cast<bool>(reschedule), static_cast<bool>(backoff)); |
| +} |
| + |
| +void PrefetchBackgroundTask::SignalTaskFinishedForTesting( |
| + JNIEnv* env, |
| + const base::android::JavaParamRef<jobject>& jcaller) { |
| + DCHECK(jcaller.obj() == java_prefetch_background_task_.obj()); |
| + service_->GetDispatcher()->RequestFinishBackgroundTaskForTest(); |
| } |
| -void PrefetchBackgroundTask::SetNeedsReschedule(bool reschedule) { |
| +void PrefetchBackgroundTask::SetNeedsReschedule(bool reschedule, bool backoff) { |
| needs_reschedule_ = reschedule; |
| + |
| + if (reschedule && backoff) |
| + backoff_->InformOfRequest(false); |
| + else |
| + backoff_->Reset(); |
| + |
| + std::unique_ptr<base::Value> value = |
| + net::BackoffEntrySerializer::SerializeToValue(*backoff_, |
| + base::Time::Now()); |
| + profile_->GetPrefs()->Set(prefs::kOfflinePrefetchBackoff, *value); |
| +} |
| + |
| +int PrefetchBackgroundTask::GetAdditionalBackoffSeconds() const { |
| + return static_cast<int>(backoff_->GetTimeUntilRelease().InSeconds()); |
| } |
| bool RegisterPrefetchBackgroundTask(JNIEnv* env) { |