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 |
deleted file mode 100644 |
index 403c9065588a62fbb315440b07cb903991f77c36..0000000000000000000000000000000000000000 |
--- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java |
+++ /dev/null |
@@ -1,310 +0,0 @@ |
-// 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.app.ContentMain; |
-import org.chromium.content.app.LibraryLoader; |
-import org.chromium.content.common.ProcessInitException; |
-import org.chromium.content.common.ResultCodes; |
- |
-import java.util.ArrayList; |
-import java.util.List; |
- |
-/** |
- * This class controls how C++ browser main loop is started and ensures it happens only once. |
- * |
- * It supports kicking off the startup sequence in an asynchronous way. Startup can be called as |
- * many times as needed (for instance, multiple activities for the same application), but the |
- * browser process will still only be initialized once. All requests to 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 onSuccess(boolean alreadyStarted); |
- void onFailure(); |
- } |
- |
- private static final String TAG = "BrowserStartupController"; |
- |
- // Helper constants for {@link StartupCallback#onSuccess}. |
- private static final boolean ALREADY_STARTED = true; |
- private static final boolean NOT_ALREADY_STARTED = false; |
- |
- // Helper constants for {@link #executeEnqueuedCallbacks(int, boolean)}. |
- @VisibleForTesting |
- static final int STARTUP_SUCCESS = -1; |
- @VisibleForTesting |
- static final int STARTUP_FAILURE = 1; |
- |
- private static BrowserStartupController sInstance; |
- |
- private static boolean sBrowserMayStartAsynchronously = false; |
- |
- private static void setAsynchronousStartup(boolean enable) { |
- sBrowserMayStartAsynchronously = enable; |
- } |
- |
- @VisibleForTesting |
- @CalledByNative |
- static boolean browserMayStartAsynchonously() { |
- return sBrowserMayStartAsynchronously; |
- } |
- |
- @VisibleForTesting |
- @CalledByNative |
- static void browserStartupComplete(int result) { |
- if (sInstance != null) { |
- sInstance.executeEnqueuedCallbacks(result, NOT_ALREADY_STARTED); |
- } |
- } |
- |
- // A list of callbacks that should be called when the async startup of the browser process is |
- // complete. |
- private final List<StartupCallback> mAsyncStartupCallbacks; |
- |
- // The context is set on creation, but the reference is cleared after the browser process |
- // initialization has been started, since it is not needed anymore. This is to ensure the |
- // context is not leaked. |
- private final Context mContext; |
- |
- // 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 mStartupDone; |
- |
- // Use single-process mode that runs the renderer on a separate thread in |
- // the main application. |
- public static final int MAX_RENDERERS_SINGLE_PROCESS = 0; |
- |
- // Cap on the maximum number of renderer processes that can be requested. |
- // This is currently set to account for: |
- // 13: The maximum number of sandboxed processes we have available |
- // - 1: The regular New Tab Page |
- // - 1: The incognito New Tab Page |
- // - 1: A regular incognito tab |
- // - 1: Safety buffer (http://crbug.com/251279) |
- public static final int MAX_RENDERERS_LIMIT = |
- ChildProcessLauncher.MAX_REGISTERED_SANDBOXED_SERVICES - 4; |
- |
- // This field is set after startup has been completed based on whether the startup was a success |
- // or not. It is used when later requests to startup come in that happen after the initial set |
- // of enqueued callbacks have been executed. |
- private boolean mStartupSuccess; |
- |
- BrowserStartupController(Context context) { |
- mContext = context; |
- mAsyncStartupCallbacks = new ArrayList<StartupCallback>(); |
- } |
- |
- public static BrowserStartupController get(Context context) { |
- assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread."; |
- ThreadUtils.assertOnUiThread(); |
- if (sInstance == null) { |
- sInstance = new BrowserStartupController(context.getApplicationContext()); |
- } |
- return sInstance; |
- } |
- |
- @VisibleForTesting |
- static BrowserStartupController overrideInstanceForTest(BrowserStartupController controller) { |
- if (sInstance == null) { |
- sInstance = controller; |
- } |
- 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. |
- */ |
- public void startBrowserProcessesAsync(final StartupCallback callback) |
- throws ProcessInitException { |
- assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread."; |
- if (mStartupDone) { |
- // Browser process initialization has already been completed, so we can immediately post |
- // the callback. |
- postStartupCompleted(callback); |
- return; |
- } |
- |
- // Browser process has not been fully started yet, so we defer executing the callback. |
- mAsyncStartupCallbacks.add(callback); |
- |
- if (!mHasStartedInitializingBrowserProcess) { |
- // 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; |
- |
- prepareToStartBrowserProcess(MAX_RENDERERS_LIMIT); |
- |
- setAsynchronousStartup(true); |
- if (contentStart() > 0) { |
- // Failed. The callbacks may not have run, so run them. |
- enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); |
- } |
- } |
- } |
- |
- /** |
- * Start the browser process synchronously. If the browser is already being started |
- * asynchronously then complete startup synchronously |
- * |
- * <p/> |
- * Note that this can only be called on the UI thread. |
- * |
- * @param maxRenderers The maximum number of renderer processes the browser may |
- * create. Zero for single process mode. |
- * @throws ProcessInitException |
- */ |
- public void startBrowserProcessesSync(int maxRenderers) throws ProcessInitException { |
- // If already started skip to checking the result |
- if (!mStartupDone) { |
- if (!mHasStartedInitializingBrowserProcess) { |
- prepareToStartBrowserProcess(maxRenderers); |
- } |
- |
- setAsynchronousStartup(false); |
- if (contentStart() > 0) { |
- // Failed. The callbacks may not have run, so run them. |
- enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); |
- } |
- } |
- |
- // Startup should now be complete |
- assert mStartupDone; |
- if (!mStartupSuccess) { |
- throw new ProcessInitException(ResultCodes.RESULT_CODE_NATIVE_STARTUP_FAILED); |
- } |
- } |
- |
- /** |
- * Wrap ContentMain.start() for testing. |
- */ |
- @VisibleForTesting |
- int contentStart() { |
- return ContentMain.start(); |
- } |
- |
- public void addStartupCompletedObserver(StartupCallback callback) { |
- ThreadUtils.assertOnUiThread(); |
- if (mStartupDone) { |
- postStartupCompleted(callback); |
- } else { |
- mAsyncStartupCallbacks.add(callback); |
- } |
- } |
- |
- private void executeEnqueuedCallbacks(int startupResult, boolean alreadyStarted) { |
- assert ThreadUtils.runningOnUiThread() : "Callback from browser startup from wrong thread."; |
- mStartupDone = true; |
- mStartupSuccess = (startupResult <= 0); |
- for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) { |
- if (mStartupSuccess) { |
- asyncStartupCallback.onSuccess(alreadyStarted); |
- } else { |
- asyncStartupCallback.onFailure(); |
- } |
- } |
- // We don't want to hold on to any objects after we do not need them anymore. |
- mAsyncStartupCallbacks.clear(); |
- } |
- |
- // Queue the callbacks to run. Since running the callbacks clears the list it is safe to call |
- // this more than once. |
- private void enqueueCallbackExecution(final int startupFailure, final boolean alreadyStarted) { |
- new Handler().post(new Runnable() { |
- @Override |
- public void run() { |
- executeEnqueuedCallbacks(startupFailure, alreadyStarted); |
- } |
- }); |
- } |
- |
- private void postStartupCompleted(final StartupCallback callback) { |
- new Handler().post(new Runnable() { |
- @Override |
- public void run() { |
- if (mStartupSuccess) { |
- callback.onSuccess(ALREADY_STARTED); |
- } else { |
- callback.onFailure(); |
- } |
- } |
- }); |
- } |
- |
- @VisibleForTesting |
- void prepareToStartBrowserProcess(int maxRendererProcesses) throws ProcessInitException { |
- Log.i(TAG, "Initializing chromium process, renderers=" + maxRendererProcesses); |
- |
- // Normally Main.java will have kicked this off asynchronously for Chrome. But other |
- // ContentView apps like tests also need them so we make sure we've extracted resources |
- // here. We can still make it a little async (wait until the library is loaded). |
- ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext); |
- resourceExtractor.startExtractingResources(); |
- |
- // Normally Main.java will have already loaded the library asynchronously, we only need |
- // to load it here if we arrived via another flow, e.g. bookmark access & sync setup. |
- LibraryLoader.ensureInitialized(); |
- |
- // TODO(yfriedman): Remove dependency on a command line flag for this. |
- DeviceUtils.addDeviceSpecificUserAgentSwitch(mContext); |
- |
- Context appContext = mContext.getApplicationContext(); |
- // Now we really need to have the resources ready. |
- resourceExtractor.waitForCompletion(); |
- |
- nativeSetCommandLineFlags(maxRendererProcesses, |
- nativeIsPluginEnabled() ? getPlugins() : null); |
- ContentMain.initApplicationContext(appContext); |
- } |
- |
- /** |
- * Initialization needed for tests. Mainly used by content browsertests. |
- */ |
- public void initChromiumBrowserProcessForTests() { |
- ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext); |
- resourceExtractor.startExtractingResources(); |
- resourceExtractor.waitForCompletion(); |
- |
- // Having a single renderer should be sufficient for tests. We can't have more than |
- // MAX_RENDERERS_LIMIT. |
- nativeSetCommandLineFlags(1 /* maxRenderers */, null); |
- } |
- |
- private String getPlugins() { |
- return PepperPluginManager.getPlugins(mContext); |
- } |
- |
- private static native void nativeSetCommandLineFlags(int maxRenderProcesses, |
- String pluginDescriptor); |
- |
- // Is this an official build of Chrome? Only native code knows for sure. Official build |
- // knowledge is needed very early in process startup. |
- private static native boolean nativeIsOfficialBuild(); |
- |
- private static native boolean nativeIsPluginEnabled(); |
-} |