OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.background_task_scheduler; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.support.annotation.IntDef; |
| 9 |
| 10 import org.chromium.base.Log; |
| 11 import org.chromium.base.ThreadUtils; |
| 12 import org.chromium.base.library_loader.LibraryProcessType; |
| 13 import org.chromium.base.library_loader.ProcessInitException; |
| 14 import org.chromium.chrome.browser.init.BrowserParts; |
| 15 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
| 16 import org.chromium.chrome.browser.init.EmptyBrowserParts; |
| 17 import org.chromium.components.background_task_scheduler.BackgroundTask; |
| 18 import org.chromium.components.background_task_scheduler.TaskParameters; |
| 19 import org.chromium.content.browser.BrowserStartupController; |
| 20 |
| 21 import java.lang.annotation.Retention; |
| 22 import java.lang.annotation.RetentionPolicy; |
| 23 |
| 24 /** |
| 25 * Base class implementing {@link BackgroundTask} that adds native initializatio
n, ensuring that |
| 26 * tasks are run after Chrome is successfully started. |
| 27 */ |
| 28 public abstract class NativeBackgroundTask implements BackgroundTask { |
| 29 private static final String TAG = "BTS_NativeBkgrdTask"; |
| 30 |
| 31 /** Specifies which action to take following onStartTaskBeforeNativeLoaded.
*/ |
| 32 @Retention(RetentionPolicy.SOURCE) |
| 33 @IntDef({LOAD_NATIVE, RESCHEDULE, DONE}) |
| 34 public @interface StartBeforeNativeResult {} |
| 35 /** Task should continue to load native parts of browser. */ |
| 36 public static final int LOAD_NATIVE = 0; |
| 37 /** Task should request rescheduling, without loading native parts of browse
r. */ |
| 38 public static final int RESCHEDULE = 1; |
| 39 /** Task should neither load native parts of browser nor reschedule. */ |
| 40 public static final int DONE = 2; |
| 41 |
| 42 protected NativeBackgroundTask() {} |
| 43 |
| 44 /** Indicates that the task has already been stopped. Should only be accesse
d on UI Thread. */ |
| 45 private boolean mTaskStopped; |
| 46 |
| 47 @Override |
| 48 public final boolean onStartTask( |
| 49 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback) { |
| 50 ThreadUtils.assertOnUiThread(); |
| 51 @StartBeforeNativeResult |
| 52 int beforeNativeResult = onStartTaskBeforeNativeLoaded(context, taskPara
meters, callback); |
| 53 |
| 54 if (beforeNativeResult == DONE) return false; |
| 55 |
| 56 if (beforeNativeResult == RESCHEDULE) { |
| 57 ThreadUtils.postOnUiThread(buildRescheduleRunnable(callback)); |
| 58 return true; |
| 59 } |
| 60 |
| 61 assert beforeNativeResult == LOAD_NATIVE; |
| 62 runWithNative(context, buildStartWithNativeRunnable(context, taskParamet
ers, callback), |
| 63 buildRescheduleRunnable(callback)); |
| 64 return true; |
| 65 } |
| 66 |
| 67 @Override |
| 68 public final boolean onStopTask(Context context, TaskParameters taskParamete
rs) { |
| 69 ThreadUtils.assertOnUiThread(); |
| 70 mTaskStopped = true; |
| 71 if (isNativeLoaded()) { |
| 72 return onStopTaskWithNative(context, taskParameters); |
| 73 } else { |
| 74 return onStopTaskBeforeNativeLoaded(context, taskParameters); |
| 75 } |
| 76 } |
| 77 |
| 78 /** |
| 79 * Ensure that native is started before running the task. If native fails to
start, the task is |
| 80 * going to be rescheduled, by issuing a {@see TaskFinishedCallback} with pa
rameter set to |
| 81 * <c>true</c>. |
| 82 * |
| 83 * @param context the current context |
| 84 * @param startWithNativeRunnable A runnable that will execute #onStartTaskW
ithNative, after the |
| 85 * native is loaded. |
| 86 * @param rescheduleRunnable A runnable that will be called to reschedule th
e task in case |
| 87 * native initialization fails. |
| 88 */ |
| 89 protected final void runWithNative(final Context context, |
| 90 final Runnable startWithNativeRunnable, final Runnable rescheduleRun
nable) { |
| 91 if (isNativeLoaded()) { |
| 92 ThreadUtils.postOnUiThread(startWithNativeRunnable); |
| 93 return; |
| 94 } |
| 95 |
| 96 final BrowserParts parts = new EmptyBrowserParts() { |
| 97 @Override |
| 98 public void finishNativeInitialization() { |
| 99 ThreadUtils.postOnUiThread(startWithNativeRunnable); |
| 100 } |
| 101 @Override |
| 102 public void onStartupFailure() { |
| 103 ThreadUtils.postOnUiThread(rescheduleRunnable); |
| 104 } |
| 105 }; |
| 106 |
| 107 ThreadUtils.postOnUiThread(new Runnable() { |
| 108 @Override |
| 109 public void run() { |
| 110 // If task was stopped before we got here, don't start native in
itialization. |
| 111 if (mTaskStopped) return; |
| 112 try { |
| 113 ChromeBrowserInitializer.getInstance(context).handlePreNativ
eStartup(parts); |
| 114 |
| 115 ChromeBrowserInitializer.getInstance(context).handlePostNati
veStartup( |
| 116 true /* isAsync */, parts); |
| 117 } catch (ProcessInitException e) { |
| 118 Log.e(TAG, "ProcessInitException while starting the browser
process."); |
| 119 rescheduleRunnable.run(); |
| 120 return; |
| 121 } |
| 122 } |
| 123 }); |
| 124 } |
| 125 |
| 126 /** |
| 127 * Method that should be implemented in derived classes to provide implement
ation of {@link |
| 128 * BackgroundTask#onStartTask(Context, TaskParameters, TaskFinishedCallback)
} run before native |
| 129 * is loaded. Task implementing the method may decide to not load native if
it hasn't been |
| 130 * loaded yet, by returning DONE, meaning no more work is required for the t
ask, or RESCHEDULE, |
| 131 * meaning task needs to be immediately rescheduled. |
| 132 * This method is guaranteed to be called before {@link #onStartTaskWithNati
ve}. |
| 133 */ |
| 134 @StartBeforeNativeResult |
| 135 protected abstract int onStartTaskBeforeNativeLoaded( |
| 136 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback); |
| 137 |
| 138 /** |
| 139 * Method that should be implemented in derived classes to provide implement
ation of {@link |
| 140 * BackgroundTask#onStartTask(Context, TaskParameters, TaskFinishedCallback)
} when native is |
| 141 * loaded. |
| 142 * This method will not be called unless {@link #onStartTaskBeforeNativeLoad
ed} returns |
| 143 * LOAD_NATIVE. |
| 144 */ |
| 145 protected abstract void onStartTaskWithNative( |
| 146 Context context, TaskParameters taskParameters, TaskFinishedCallback
callback); |
| 147 |
| 148 /** Called by {@link #onStopTask} if native part of browser was not loaded.
*/ |
| 149 protected abstract boolean onStopTaskBeforeNativeLoaded( |
| 150 Context context, TaskParameters taskParameters); |
| 151 |
| 152 /** Called by {@link #onStopTask} if native part of browser was loaded. */ |
| 153 protected abstract boolean onStopTaskWithNative(Context context, TaskParamet
ers taskParameters); |
| 154 |
| 155 /** Builds a runnable rescheduling task. */ |
| 156 private Runnable buildRescheduleRunnable(final TaskFinishedCallback callback
) { |
| 157 return new Runnable() { |
| 158 @Override |
| 159 public void run() { |
| 160 ThreadUtils.assertOnUiThread(); |
| 161 if (mTaskStopped) return; |
| 162 callback.taskFinished(true); |
| 163 } |
| 164 }; |
| 165 } |
| 166 |
| 167 /** Builds a runnable starting task with native portion. */ |
| 168 private Runnable buildStartWithNativeRunnable(final Context context, |
| 169 final TaskParameters taskParameters, final TaskFinishedCallback call
back) { |
| 170 return new Runnable() { |
| 171 @Override |
| 172 public void run() { |
| 173 ThreadUtils.assertOnUiThread(); |
| 174 if (mTaskStopped) return; |
| 175 onStartTaskWithNative(context, taskParameters, callback); |
| 176 } |
| 177 }; |
| 178 } |
| 179 |
| 180 /** Whether the native part of the browser is loaded. */ |
| 181 private boolean isNativeLoaded() { |
| 182 return BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) |
| 183 .isStartupSuccessfullyCompleted(); |
| 184 } |
| 185 } |
OLD | NEW |