Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java

Issue 22272006: Add support for multiple asynchronous browser startups. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merged BrowserStartupConfig and BrowserStartupController. Rebased. Updated ContentShellActivity to … Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4d9e1f359357f9867839b5cc433d333a130728e
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
@@ -0,0 +1,162 @@
+// Copyright 2013 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.content.browser;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.Log;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.base.ThreadUtils;
+import org.chromium.content.common.ProcessInitException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class controls how C++ browser main loop is run and ensures it happens only once.
bulach 2013/08/15 15:09:12 s/is run/is started/
nyquist 2013/08/16 02:01:01 Done.
+ *
+ * It supports kicking of the startup sequence in an asynchronous way. Startup can be called as many
+ * times as needed, but the browser process will still only be initialized once. All requests to
bulach 2013/08/15 15:09:12 times as needed (for instance, multiple activities
nyquist 2013/08/16 02:01:01 Done.
+ * start the browser will always get their callback executed; if the browser process has already
+ * been started, the callback is called immediately, else it is called when initialization is
+ * complete.
+ *
+ * All communication with this class must happen on the main thread.
+ *
+ * This is a singleton, and stores a reference to the application context.
+ */
+@JNINamespace("content")
+public class BrowserStartupController {
+ public interface StartupCallback {
+ void run(int startupResult);
bulach 2013/08/15 15:09:12 nit: maybe "onStartupComplete" ?
nyquist 2013/08/16 02:01:01 Done. Split into two methods: onSuccess and onFail
+ }
+
+ private static final String TAG = "BrowserStartupController";
+
+ private static final Object LOCK = new Object();
+
+ private static BrowserStartupController sInstance;
+
+ private static boolean sBrowserMayStartAsynchronously = false;
+
+ @CalledByNative
+ private static boolean browserMayStartAsynchonously() {
+ return sBrowserMayStartAsynchronously;
+ }
+
+ @CalledByNative
+ private static void browserStartupComplete(int result) {
+ BrowserStartupController instance = null;
+ synchronized (LOCK) {
+ if (sInstance != null) {
+ instance = sInstance;
+ }
+ }
+ if (instance != null) {
+ instance.executeEnqueuedCallbacks(result);
+ }
+ }
+
+ // A list of callbacks that should be called when the async startup of the browser process is
+ // complete.
+ private final List<StartupCallback> mAsyncStartupCallbacks;
+
+ private final Context mContext;
bulach 2013/08/15 15:09:12 nit: I heard rumors that this can cause leaks, spe
nyquist 2013/08/16 02:01:01 Done.
+
+ // Whether the async startup of the browser process has started.
+ private boolean mHasStartedInitializingBrowserProcess;
+
+ // Whether the async startup of the browser process is complete.
+ private boolean mAsyncStartupDone;
+
+ BrowserStartupController(Context context) {
+ mContext = context;
+ mAsyncStartupCallbacks = new ArrayList<StartupCallback>();
+ }
+
+ public static BrowserStartupController get(Context context) {
+ synchronized (LOCK) {
+ if (sInstance == null) {
+ sInstance = new BrowserStartupController(context.getApplicationContext());
+ }
+ return sInstance;
+ }
+ }
+
+ /**
+ * Start the browser process asynchronously. This will set up a queue of UI thread tasks to
+ * initialize the browser process.
+ * <p/>
+ * Note that this can only be called on the UI thread.
+ *
+ * @param callback the callback to be called when browser startup is complete.
+ * @return Whether the queue of tasks was created successfully.
bulach 2013/08/15 15:09:12 hmm... would it make sense to have this method "vo
nyquist 2013/08/16 02:01:01 Done.
+ */
+ public boolean startBrowserProcessesAsync(final StartupCallback callback) {
+ assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread.";
+ if (mAsyncStartupDone) {
+ // Browser process is already fully started, so we can immediately post the callback.
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.run(-1);
bulach 2013/08/15 15:09:12 nit: maybe define -1 as public static final int of
nyquist 2013/08/16 02:01:01 Done.
+ }
+ });
+ return true;
+ }
+
+ // Browser process has not been fully started yet, so we defer executing the callback.
+ mAsyncStartupCallbacks.add(callback);
+
+ if (mHasStartedInitializingBrowserProcess) {
+ // We only want to try to initialize the browser process once, so we just return here.
+ return true;
+ } else {
+ // This is the first time we have been asked to start the browser process. We set the
+ // flag that indicates that we have kicked off starting the browser process.
+ mHasStartedInitializingBrowserProcess = true;
+
+ enableAsynchronousStartup();
+
+ // We can now try to initialize the Android browser process.
+ return initializeAndroidBrowserProcess();
+ }
+ }
+
+ @VisibleForTesting
+ void executeEnqueuedCallbacks(int startupResult) {
+ assert ThreadUtils.runningOnUiThread() : "Callback from browser startup from wrong thread.";
+ mAsyncStartupDone = true;
+ for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) {
+ asyncStartupCallback.run(startupResult);
+ }
+ // We don't want to hold on to any objects after we do not need them anymore.
+ mAsyncStartupCallbacks.clear();
+ }
+
+ /**
+ * Ensure that the browser process will be asynchronously started up. This also ensures that we
+ * get a call to {@link #browserStartupComplete} when the browser startup is complete.
+ */
+ @VisibleForTesting
+ void enableAsynchronousStartup() {
+ sBrowserMayStartAsynchronously = true;
bulach 2013/08/15 15:09:12 need to make find_bugs happy.
nyquist 2013/08/16 02:01:01 Done.
+ }
+
+ @VisibleForTesting
+ boolean initializeAndroidBrowserProcess() {
+ try {
+ AndroidBrowserProcess.init(mContext, AndroidBrowserProcess.MAX_RENDERERS_LIMIT);
bulach 2013/08/15 15:09:12 nit: Context context = mContext; mContext = null;
nyquist 2013/08/16 02:01:01 Done.
+ } catch (ProcessInitException e) {
+ Log.e(TAG, "Unable to start browser process.", e);
+ return false;
+ }
+ return true;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698