| Index: chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e4db6141e79e7496e2b2f98e9b07a4549f845176
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
|
| @@ -0,0 +1,185 @@
|
| +// 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.
|
| +
|
| +package org.chromium.chrome.browser.background_task_scheduler;
|
| +
|
| +import android.content.Context;
|
| +import android.support.annotation.IntDef;
|
| +
|
| +import org.chromium.base.Log;
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.base.library_loader.LibraryProcessType;
|
| +import org.chromium.base.library_loader.ProcessInitException;
|
| +import org.chromium.chrome.browser.init.BrowserParts;
|
| +import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
|
| +import org.chromium.chrome.browser.init.EmptyBrowserParts;
|
| +import org.chromium.components.background_task_scheduler.BackgroundTask;
|
| +import org.chromium.components.background_task_scheduler.TaskParameters;
|
| +import org.chromium.content.browser.BrowserStartupController;
|
| +
|
| +import java.lang.annotation.Retention;
|
| +import java.lang.annotation.RetentionPolicy;
|
| +
|
| +/**
|
| + * Base class implementing {@link BackgroundTask} that adds native initialization, ensuring that
|
| + * tasks are run after Chrome is successfully started.
|
| + */
|
| +public abstract class NativeBackgroundTask implements BackgroundTask {
|
| + private static final String TAG = "BTS_NativeBkgrdTask";
|
| +
|
| + /** Specifies which action to take following onStartTaskBeforeNativeLoaded. */
|
| + @Retention(RetentionPolicy.SOURCE)
|
| + @IntDef({LOAD_NATIVE, RESCHEDULE, DONE})
|
| + public @interface StartBeforeNativeResult {}
|
| + /** Task should continue to load native parts of browser. */
|
| + public static final int LOAD_NATIVE = 0;
|
| + /** Task should request rescheduling, without loading native parts of browser. */
|
| + public static final int RESCHEDULE = 1;
|
| + /** Task should neither load native parts of browser nor reschedule. */
|
| + public static final int DONE = 2;
|
| +
|
| + protected NativeBackgroundTask() {}
|
| +
|
| + /** Indicates that the task has already been stopped. Should only be accessed on UI Thread. */
|
| + private boolean mTaskStopped;
|
| +
|
| + @Override
|
| + public final boolean onStartTask(
|
| + Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
|
| + ThreadUtils.assertOnUiThread();
|
| + @StartBeforeNativeResult
|
| + int beforeNativeResult = onStartTaskBeforeNativeLoaded(context, taskParameters, callback);
|
| +
|
| + if (beforeNativeResult == DONE) return false;
|
| +
|
| + if (beforeNativeResult == RESCHEDULE) {
|
| + ThreadUtils.postOnUiThread(buildRescheduleRunnable(callback));
|
| + return true;
|
| + }
|
| +
|
| + assert beforeNativeResult == LOAD_NATIVE;
|
| + runWithNative(context, buildStartWithNativeRunnable(context, taskParameters, callback),
|
| + buildRescheduleRunnable(callback));
|
| + return true;
|
| + }
|
| +
|
| + @Override
|
| + public final boolean onStopTask(Context context, TaskParameters taskParameters) {
|
| + ThreadUtils.assertOnUiThread();
|
| + mTaskStopped = true;
|
| + if (isNativeLoaded()) {
|
| + return onStopTaskWithNative(context, taskParameters);
|
| + } else {
|
| + return onStopTaskBeforeNativeLoaded(context, taskParameters);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Ensure that native is started before running the task. If native fails to start, the task is
|
| + * going to be rescheduled, by issuing a {@see TaskFinishedCallback} with parameter set to
|
| + * <c>true</c>.
|
| + *
|
| + * @param context the current context
|
| + * @param startWithNativeRunnable A runnable that will execute #onStartTaskWithNative, after the
|
| + * native is loaded.
|
| + * @param rescheduleRunnable A runnable that will be called to reschedule the task in case
|
| + * native initialization fails.
|
| + */
|
| + protected final void runWithNative(final Context context,
|
| + final Runnable startWithNativeRunnable, final Runnable rescheduleRunnable) {
|
| + if (isNativeLoaded()) {
|
| + ThreadUtils.postOnUiThread(startWithNativeRunnable);
|
| + return;
|
| + }
|
| +
|
| + final BrowserParts parts = new EmptyBrowserParts() {
|
| + @Override
|
| + public void finishNativeInitialization() {
|
| + ThreadUtils.postOnUiThread(startWithNativeRunnable);
|
| + }
|
| + @Override
|
| + public void onStartupFailure() {
|
| + ThreadUtils.postOnUiThread(rescheduleRunnable);
|
| + }
|
| + };
|
| +
|
| + ThreadUtils.postOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + // If task was stopped before we got here, don't start native initialization.
|
| + if (mTaskStopped) return;
|
| + try {
|
| + ChromeBrowserInitializer.getInstance(context).handlePreNativeStartup(parts);
|
| +
|
| + ChromeBrowserInitializer.getInstance(context).handlePostNativeStartup(
|
| + true /* isAsync */, parts);
|
| + } catch (ProcessInitException e) {
|
| + Log.e(TAG, "ProcessInitException while starting the browser process.");
|
| + rescheduleRunnable.run();
|
| + return;
|
| + }
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Method that should be implemented in derived classes to provide implementation of {@link
|
| + * BackgroundTask#onStartTask(Context, TaskParameters, TaskFinishedCallback)} run before native
|
| + * is loaded. Task implementing the method may decide to not load native if it hasn't been
|
| + * loaded yet, by returning DONE, meaning no more work is required for the task, or RESCHEDULE,
|
| + * meaning task needs to be immediately rescheduled.
|
| + * This method is guaranteed to be called before {@link #onStartTaskWithNative}.
|
| + */
|
| + @StartBeforeNativeResult
|
| + protected abstract int onStartTaskBeforeNativeLoaded(
|
| + Context context, TaskParameters taskParameters, TaskFinishedCallback callback);
|
| +
|
| + /**
|
| + * Method that should be implemented in derived classes to provide implementation of {@link
|
| + * BackgroundTask#onStartTask(Context, TaskParameters, TaskFinishedCallback)} when native is
|
| + * loaded.
|
| + * This method will not be called unless {@link #onStartTaskBeforeNativeLoaded} returns
|
| + * LOAD_NATIVE.
|
| + */
|
| + protected abstract void onStartTaskWithNative(
|
| + Context context, TaskParameters taskParameters, TaskFinishedCallback callback);
|
| +
|
| + /** Called by {@link #onStopTask} if native part of browser was not loaded. */
|
| + protected abstract boolean onStopTaskBeforeNativeLoaded(
|
| + Context context, TaskParameters taskParameters);
|
| +
|
| + /** Called by {@link #onStopTask} if native part of browser was loaded. */
|
| + protected abstract boolean onStopTaskWithNative(Context context, TaskParameters taskParameters);
|
| +
|
| + /** Builds a runnable rescheduling task. */
|
| + private Runnable buildRescheduleRunnable(final TaskFinishedCallback callback) {
|
| + return new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + ThreadUtils.assertOnUiThread();
|
| + if (mTaskStopped) return;
|
| + callback.taskFinished(true);
|
| + }
|
| + };
|
| + }
|
| +
|
| + /** Builds a runnable starting task with native portion. */
|
| + private Runnable buildStartWithNativeRunnable(final Context context,
|
| + final TaskParameters taskParameters, final TaskFinishedCallback callback) {
|
| + return new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + ThreadUtils.assertOnUiThread();
|
| + if (mTaskStopped) return;
|
| + onStartTaskWithNative(context, taskParameters, callback);
|
| + }
|
| + };
|
| + }
|
| +
|
| + /** Whether the native part of the browser is loaded. */
|
| + private boolean isNativeLoaded() {
|
| + return BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
|
| + .isStartupSuccessfullyCompleted();
|
| + }
|
| +}
|
|
|