Chromium Code Reviews| 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..827952f006569f183e9b54e0799ae7e5008e1c08 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java |
| @@ -0,0 +1,181 @@ |
| +// 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. |
| + * Background tasks that require native parts of browser to be started should extend this class |
| + * instead of implementing the interface directly. {@link #onStartTaskWithNative(Context, |
| + * TaskParameters, TaskFinishedCallback)} method should be implemented instead of {@link |
| + * #onStartTask(Context, TaskParameters, TaskFinishedCallback)}. |
|
Ted C
2017/05/23 20:52:55
I'd argue the last sentence isn't necessary, onSta
fgorski
2017/05/23 21:35:02
Done.
|
| + */ |
| +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() {} |
| + |
| + private boolean mTaskStopped; |
|
nyquist
2017/05/23 20:14:28
Nit: Could you add a comment that this must only e
fgorski
2017/05/23 21:35:02
Done.
|
| + |
| + @Override |
| + public final boolean onStartTask( |
| + Context context, TaskParameters taskParameters, TaskFinishedCallback callback) { |
| + @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) { |
| + 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() { |
| + startWithNativeRunnable.run(); |
| + } |
| + @Override |
| + public void onStartupFailure() { |
| + rescheduleRunnable.run(); |
| + } |
| + }; |
| + |
| + ThreadUtils.postOnUiThread(new Runnable() { |
| + @Override |
| + public void run() { |
| + try { |
| + ChromeBrowserInitializer.getInstance(context).handlePreNativeStartup(parts); |
|
Ted C
2017/05/23 20:52:55
Should this do:
if (mTaskStopped) return;
fgorski
2017/05/23 21:35:02
I am putting it before the try, presuming you didn
Ted C
2017/05/23 22:06:43
Nope, that's right
|
| + ChromeBrowserInitializer.getInstance(context).handlePostNativeStartup( |
| + true /* isAsync */, parts); |
| + } catch (ProcessInitException e) { |
| + Log.e(TAG, "ProcessInitException while starting the browser process."); |
| + if (!mTaskStopped) { |
| + 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() { |
| + callback.taskFinished(true); |
|
Ted C
2017/05/23 20:52:55
Same question as above. Should this do:
if (mTas
fgorski
2017/05/23 21:35:02
Done.
Good point. I went ahead and added checks in
|
| + } |
| + }; |
| + } |
| + |
| + /** 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() { |
| + onStartTaskWithNative(context, taskParameters, callback); |
|
Ted C
2017/05/23 20:52:55
same about mTaskStopped?
fgorski
2017/05/23 21:35:02
Done.
|
| + } |
| + }; |
| + } |
| + |
| + /** Whether the native part of the browser is loaded. */ |
| + private boolean isNativeLoaded() { |
| + return BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) |
| + .isStartupSuccessfullyCompleted(); |
| + } |
| +} |