BrowserStartupController.java revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)package org.chromium.content.browser; 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import android.content.Context; 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import android.os.Handler; 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import android.util.Log; 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import com.google.common.annotations.VisibleForTesting; 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import org.chromium.base.CalledByNative; 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import org.chromium.base.JNINamespace; 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import org.chromium.base.ThreadUtils; 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)import org.chromium.content.app.ContentMain; 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)import org.chromium.content.app.LibraryLoader; 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import org.chromium.content.common.ProcessInitException; 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import java.util.ArrayList; 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import java.util.List; 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * This class controls how C++ browser main loop is started and ensures it happens only once. 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * It supports kicking off the startup sequence in an asynchronous way. Startup can be called as 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * many times as needed (for instance, multiple activities for the same application), but the 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * browser process will still only be initialized once. All requests to start the browser will 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * always get their callback executed; if the browser process has already been started, the callback 303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * is called immediately, else it is called when initialization is complete. 313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * All communication with this class must happen on the main thread. 333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * This is a singleton, and stores a reference to the application context. 353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)@JNINamespace("content") 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)public class BrowserStartupController { 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public interface StartupCallback { 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void onSuccess(boolean alreadyStarted); 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void onFailure(); 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static final String TAG = "BrowserStartupController"; 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Helper constants for {@link StartupCallback#onSuccess}. 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static final boolean ALREADY_STARTED = true; 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static final boolean NOT_ALREADY_STARTED = false; 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Helper constants for {@link #executeEnqueuedCallbacks(int, boolean)}. 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @VisibleForTesting 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) static final int STARTUP_SUCCESS = -1; 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @VisibleForTesting 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) static final int STARTUP_FAILURE = 1; 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static BrowserStartupController sInstance; 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static boolean sBrowserMayStartAsynchronously = false; 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private static void setAsynchronousStartup(boolean enable) { 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) sBrowserMayStartAsynchronously = enable; 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) @VisibleForTesting 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @CalledByNative 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) static boolean browserMayStartAsynchonously() { 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return sBrowserMayStartAsynchronously; 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @VisibleForTesting 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @CalledByNative 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) static void browserStartupComplete(int result) { 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (sInstance != null) { 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sInstance.executeEnqueuedCallbacks(result, NOT_ALREADY_STARTED); 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // A list of callbacks that should be called when the async startup of the browser process is 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // complete. 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private final List<StartupCallback> mAsyncStartupCallbacks; 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The context is set on creation, but the reference is cleared after the browser process 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // initialization has been started, since it is not needed anymore. This is to ensure the 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // context is not leaked. 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private final Context mContext; 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Whether the async startup of the browser process has started. 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private boolean mHasStartedInitializingBrowserProcess; 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Whether the async startup of the browser process is complete. 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private boolean mStartupDone; 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Use single-process mode that runs the renderer on a separate thread in 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the main application. 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public static final int MAX_RENDERERS_SINGLE_PROCESS = 0; 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Cap on the maximum number of renderer processes that can be requested. 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // This is currently set to account for: 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 13: The maximum number of sandboxed processes we have available 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // - 1: The regular New Tab Page 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // - 1: The incognito New Tab Page 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // - 1: A regular incognito tab 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // - 1: Safety buffer (http://crbug.com/251279) 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public static final int MAX_RENDERERS_LIMIT = 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ChildProcessLauncher.MAX_REGISTERED_SANDBOXED_SERVICES - 4; 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // This field is set after startup has been completed based on whether the startup was a success 1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or not. It is used when later requests to startup come in that happen after the initial set 1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // of enqueued callbacks have been executed. 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private boolean mStartupSuccess; 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BrowserStartupController(Context context) { 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mContext = context; 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mAsyncStartupCallbacks = new ArrayList<StartupCallback>(); 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public static BrowserStartupController get(Context context) { 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread."; 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ThreadUtils.assertOnUiThread(); 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (sInstance == null) { 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sInstance = new BrowserStartupController(context.getApplicationContext()); 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return sInstance; 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @VisibleForTesting 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) static BrowserStartupController overrideInstanceForTest(BrowserStartupController controller) { 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (sInstance == null) { 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sInstance = controller; 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return sInstance; 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) /** 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Start the browser process asynchronously. This will set up a queue of UI thread tasks to 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * initialize the browser process. 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * <p/> 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Note that this can only be called on the UI thread. 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param callback the callback to be called when browser startup is complete. 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public void startBrowserProcessesAsync(final StartupCallback callback) { 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread."; 144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mStartupDone) { 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Browser process initialization has already been completed, so we can immediately post 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the callback. 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) postStartupCompleted(callback); 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Browser process has not been fully started yet, so we defer executing the callback. 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mAsyncStartupCallbacks.add(callback); 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!mHasStartedInitializingBrowserProcess) { 1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // This is the first time we have been asked to start the browser process. We set the 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // flag that indicates that we have kicked off starting the browser process. 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mHasStartedInitializingBrowserProcess = true; 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!tryPrepareToStartBrowserProcess(MAX_RENDERERS_LIMIT)) return; 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) setAsynchronousStartup(true); 162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (contentStart() > 0) { 163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Failed. The callbacks may not have run, so run them. 164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); 165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private boolean tryPrepareToStartBrowserProcess(int maxRenderers) { 170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Make sure that everything is in place to initialize the Android browser process. 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) try { 172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) prepareToStartBrowserProcess(maxRenderers); 173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } catch (ProcessInitException e) { 175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Log.e(TAG, "Unable to load native library.", e); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); 177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) /** 182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Start the browser process synchronously. If the browser is already being started 183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * asynchronously then complete startup synchronously 184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * 185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * <p/> 186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Note that this can only be called on the UI thread. 187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * 188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @param max_renderers The maximum number of renderer processes the browser may 189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * create. Zero for single process mode. 190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @return true if successfully started, false otherwise. 191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) */ 192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public boolean startBrowserProcessesSync(int maxRenderers) { 193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mStartupDone) { 194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Nothing to do 195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return mStartupSuccess; 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!mHasStartedInitializingBrowserProcess) { 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!tryPrepareToStartBrowserProcess(maxRenderers)) return false; 199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) setAsynchronousStartup(false); 202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (contentStart() > 0) { 203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Failed. The callbacks may not have run, so run them. 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); 205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Startup should now be complete 208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) assert mStartupDone; 209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return mStartupSuccess; 210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) /** 213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Wrap ContentMain.start() for testing. 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) */ 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) @VisibleForTesting 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int contentStart() { 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return ContentMain.start(); 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public void addStartupCompletedObserver(StartupCallback callback) { 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ThreadUtils.assertOnUiThread(); 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mStartupDone) { 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) postStartupCompleted(callback); 224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mAsyncStartupCallbacks.add(callback); 226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private void executeEnqueuedCallbacks(int startupResult, boolean alreadyStarted) { 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assert ThreadUtils.runningOnUiThread() : "Callback from browser startup from wrong thread."; 231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) mStartupDone = true; 232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) mStartupSuccess = (startupResult <= 0); 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) { 234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mStartupSuccess) { 2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) asyncStartupCallback.onSuccess(alreadyStarted); 236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) asyncStartupCallback.onFailure(); 2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We don't want to hold on to any objects after we do not need them anymore. 2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mAsyncStartupCallbacks.clear(); 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Queue the callbacks to run. Since running the callbacks clears the list it is safe to call 245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // this more than once. 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private void enqueueCallbackExecution(final int startupFailure, final boolean alreadyStarted) { 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new Handler().post(new Runnable() { 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @Override 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public void run() { 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) executeEnqueuedCallbacks(startupFailure, alreadyStarted); 2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }); 2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private void postStartupCompleted(final StartupCallback callback) { 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new Handler().post(new Runnable() { 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @Override 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public void run() { 259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mStartupSuccess) { 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.onSuccess(ALREADY_STARTED); 261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.onFailure(); 263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }); 2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) @VisibleForTesting 269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) void prepareToStartBrowserProcess(int maxRendererProcesses) throws ProcessInitException { 270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Log.i(TAG, "Initializing chromium process, renderers=" + maxRendererProcesses); 271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Normally Main.java will have kicked this off asynchronously for Chrome. But other 273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // ContentView apps like tests also need them so we make sure we've extracted resources 274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // here. We can still make it a little async (wait until the library is loaded). 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext); 276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resourceExtractor.startExtractingResources(); 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Normally Main.java will have already loaded the library asynchronously, we only need 279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // to load it here if we arrived via another flow, e.g. bookmark access & sync setup. 280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LibraryLoader.ensureInitialized(); 281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(yfriedman): Remove dependency on a command line flag for this. 283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DeviceUtils.addDeviceSpecificUserAgentSwitch(mContext); 284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Context appContext = mContext.getApplicationContext(); 286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Now we really need to have the resources ready. 287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resourceExtractor.waitForCompletion(); 288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) nativeSetCommandLineFlags(maxRendererProcesses, 290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) nativeIsPluginEnabled() ? getPlugins() : null); 291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ContentMain.initApplicationContext(appContext); 2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) /** 295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Initialization needed for tests. Mainly used by content browsertests. 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public void initChromiumBrowserProcessForTests() { 298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext); 299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resourceExtractor.startExtractingResources(); 300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resourceExtractor.waitForCompletion(); 301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Having a single renderer should be sufficient for tests. We can't have more than 303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // MAX_RENDERERS_LIMIT. 304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) nativeSetCommandLineFlags(1 /* maxRenderers */, null); 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private String getPlugins() { 308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return PepperPluginManager.getPlugins(mContext); 309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private static native void nativeSetCommandLineFlags(int maxRenderProcesses, 312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) String pluginDescriptor); 313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Is this an official build of Chrome? Only native code knows for sure. Official build 315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // knowledge is needed very early in process startup. 316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private static native boolean nativeIsOfficialBuild(); 317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private static native boolean nativeIsPluginEnabled(); 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 320