This source file includes following definitions.
- JNINamespace
- onSuccess
- onFailure
- setAsynchronousStartup
- browserMayStartAsynchonously
- browserStartupComplete
- get
- overrideInstanceForTest
- startBrowserProcessesAsync
- startBrowserProcessesSync
- contentStart
- addStartupCompletedObserver
- executeEnqueuedCallbacks
- enqueueCallbackExecution
- postStartupCompleted
- prepareToStartBrowserProcess
- initChromiumBrowserProcessForTests
- getPlugins
- nativeSetCommandLineFlags
- nativeIsOfficialBuild
- nativeIsPluginEnabled
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.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LoaderErrors;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.content.app.ContentMain;
import java.util.ArrayList;
import java.util.List;
@JNINamespace("content")
public class BrowserStartupController {
public interface StartupCallback {
void onSuccess(boolean alreadyStarted);
void onFailure();
}
private static final String TAG = "BrowserStartupController";
private static final boolean ALREADY_STARTED = true;
private static final boolean NOT_ALREADY_STARTED = false;
@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);
}
}
private final List<StartupCallback> mAsyncStartupCallbacks;
private final Context mContext;
private boolean mHasStartedInitializingBrowserProcess;
private boolean mStartupDone;
public static final int MAX_RENDERERS_SINGLE_PROCESS = 0;
public static final int MAX_RENDERERS_LIMIT =
ChildProcessLauncher.MAX_REGISTERED_SANDBOXED_SERVICES - 4;
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;
}
public void startBrowserProcessesAsync(final StartupCallback callback)
throws ProcessInitException {
assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread.";
if (mStartupDone) {
postStartupCompleted(callback);
return;
}
mAsyncStartupCallbacks.add(callback);
if (!mHasStartedInitializingBrowserProcess) {
mHasStartedInitializingBrowserProcess = true;
prepareToStartBrowserProcess(MAX_RENDERERS_LIMIT);
setAsynchronousStartup(true);
if (contentStart() > 0) {
enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED);
}
}
}
public void startBrowserProcessesSync(int maxRenderers) throws ProcessInitException {
if (!mStartupDone) {
if (!mHasStartedInitializingBrowserProcess) {
prepareToStartBrowserProcess(maxRenderers);
}
setAsynchronousStartup(false);
if (contentStart() > 0) {
enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED);
}
}
assert mStartupDone;
if (!mStartupSuccess) {
throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_STARTUP_FAILED);
}
}
@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();
}
}
mAsyncStartupCallbacks.clear();
}
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);
ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext);
resourceExtractor.startExtractingResources();
LibraryLoader.ensureInitialized(mContext, true);
DeviceUtils.addDeviceSpecificUserAgentSwitch(mContext);
Context appContext = mContext.getApplicationContext();
resourceExtractor.waitForCompletion();
nativeSetCommandLineFlags(maxRendererProcesses,
nativeIsPluginEnabled() ? getPlugins() : null);
ContentMain.initApplicationContext(appContext);
}
public void initChromiumBrowserProcessForTests() {
ResourceExtractor resourceExtractor = ResourceExtractor.get(mContext);
resourceExtractor.startExtractingResources();
resourceExtractor.waitForCompletion();
nativeSetCommandLineFlags(1 , null);
}
private String getPlugins() {
return PepperPluginManager.getPlugins(mContext);
}
private static native void nativeSetCommandLineFlags(int maxRenderProcesses,
String pluginDescriptor);
private static native boolean nativeIsOfficialBuild();
private static native boolean nativeIsPluginEnabled();
}