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

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

Issue 2882823002: Moving some CPL logic to CPLH. (Closed)
Patch Set: Fixed warm-up and tests. Created 3 years, 7 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/ChildProcessLauncherHelper.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
index d810afd8769e06992db363bbacc94e45eb8ab9f5..0050f3603e612600ce132cf3665013e596fc89f0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
@@ -5,14 +5,21 @@
package org.chromium.content.browser;
import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import org.chromium.base.ContextUtils;
+import org.chromium.base.CpuFeatures;
import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.library_loader.Linker;
import org.chromium.base.process_launcher.ChildProcessCreationParams;
import org.chromium.base.process_launcher.FileDescriptorInfo;
+import org.chromium.content.app.ChromiumLinkerParams;
+import org.chromium.content.common.ContentSwitches;
import java.io.IOException;
@@ -22,14 +29,19 @@ import java.io.IOException;
* Each public or jni methods should have explicit documentation on what threads they are called.
*/
@JNINamespace("content::internal")
-class ChildProcessLauncherHelper {
+public class ChildProcessLauncherHelper {
private static final String TAG = "ChildProcLH";
// Represents an invalid process handle; same as base/process/process.h kNullProcessHandle.
private static final int NULL_PROCESS_HANDLE = 0;
+ // The IBinder provided to the created service.
+ private final IBinder mIBinderCallback;
+
// Note native pointer is only guaranteed live until nativeOnChildProcessStarted.
private long mNativeChildProcessLauncherHelper;
+
+ // The actual service connection. Set once we have connected to the service.
private ChildProcessConnection mChildProcessConnection;
@CalledByNative
@@ -51,30 +63,93 @@ class ChildProcessLauncherHelper {
return new FileDescriptorInfo(id, pFd, offset, size);
}
+ @VisibleForTesting
@CalledByNative
- private static ChildProcessLauncherHelper create(long nativePointer, int paramId,
+ public static ChildProcessLauncherHelper createAndStart(long nativePointer, int paramId,
final String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
assert LauncherThread.runningOnLauncherThread();
- return new ChildProcessLauncherHelper(nativePointer, paramId, commandLine, filesToBeMapped);
+ String processType =
+ ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
+
+ ChildProcessCreationParams params = ChildProcessCreationParams.get(paramId);
+ if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null) {
+ throw new RuntimeException("CreationParams id " + paramId + " not found");
+ }
+
+ Context context = ContextUtils.getApplicationContext();
+ boolean sandboxed = true;
+ boolean alwaysInForeground = false;
+ if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
+ if (params != null && !params.getPackageName().equals(context.getPackageName())) {
+ // WebViews and WebAPKs have renderer processes running in their applications.
+ // When launching these renderer processes, {@link ManagedChildProcessConnection}
+ // requires the package name of the application which holds the renderer process.
+ // Therefore, the package name in ChildProcessCreationParams could be the package
+ // name of WebViews, WebAPKs, or Chrome, depending on the host application.
+ // Except renderer process, all other child processes should use Chrome's package
+ // name. In WebAPK, ChildProcessCreationParams are initialized with WebAPK's
+ // package name. Make a copy of the WebAPK's params, but replace the package with
+ // Chrome's package to use when initializing a non-renderer processes.
+ // TODO(boliu): Should fold into |paramId|. Investigate why this is needed.
+ params = new ChildProcessCreationParams(context.getPackageName(),
+ params.getIsExternalService(), params.getLibraryProcessType(),
+ params.getBindToCallerCheck());
+ }
+ if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
+ sandboxed = false;
+ alwaysInForeground = true;
+ } else {
+ // We only support sandboxed utility processes now.
+ assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType);
+ }
+ }
+
+ ChildProcessLauncherHelper process_launcher =
+ new ChildProcessLauncherHelper(nativePointer, processType);
+ process_launcher.start(
+ context, commandLine, filesToBeMapped, params, sandboxed, alwaysInForeground);
+ return process_launcher;
}
- private ChildProcessLauncherHelper(long nativePointer, int paramId, final String[] commandLine,
- FileDescriptorInfo[] filesToBeMapped) {
+ private ChildProcessLauncherHelper(long nativePointer, String processType) {
assert LauncherThread.runningOnLauncherThread();
mNativeChildProcessLauncherHelper = nativePointer;
+ mIBinderCallback = ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)
+ ? new GpuProcessCallback()
+ : null;
+ initLinker();
+ }
- ChildProcessLauncher.start(ContextUtils.getApplicationContext(), paramId, commandLine,
- filesToBeMapped, new ChildProcessLauncher.LaunchCallback() {
+ private void start(Context context, String[] commandLine,
+ final FileDescriptorInfo[] filesToBeMapped, ChildProcessCreationParams params,
+ boolean sandboxed, boolean alwaysInForeground) {
+ boolean bindToCallerCheck = params == null ? false : params.getBindToCallerCheck();
+ Bundle serviceBundle = createServiceBundle(bindToCallerCheck);
+ onBeforeConnectionAllocated(serviceBundle);
+
+ Bundle connectionBundle = createConnectionBundle(commandLine, filesToBeMapped);
+ ChildProcessLauncher.start(context, serviceBundle,
+ connectionBundle, new ChildProcessLauncher.LaunchCallback() {
@Override
public void onChildProcessStarted(ChildProcessConnection connection) {
mChildProcessConnection = connection;
+
+ // Proactively close the FDs rather than waiting for the GC to do it.
+ try {
+ for (FileDescriptorInfo fileInfo : filesToBeMapped) {
+ fileInfo.fd.close();
+ }
+ } catch (IOException ioe) {
+ Log.w(TAG, "Failed to close FD.", ioe);
+ }
+
if (mNativeChildProcessLauncherHelper != 0) {
nativeOnChildProcessStarted(
mNativeChildProcessLauncherHelper, getPid());
}
mNativeChildProcessLauncherHelper = 0;
}
- });
+ }, getIBinderCallback(), sandboxed, alwaysInForeground, params);
}
private int getPid() {
@@ -130,4 +205,101 @@ class ChildProcessLauncherHelper {
// Can be called on a number of threads, including launcher, and binder.
private static native void nativeOnChildProcessStarted(
long nativeChildProcessLauncherHelper, int pid);
+
+ private static boolean sLinkerInitialized;
+ private static long sLinkerLoadAddress;
+ @VisibleForTesting
+ static void initLinker() {
+ assert LauncherThread.runningOnLauncherThread();
+ if (sLinkerInitialized) return;
+ if (Linker.isUsed()) {
+ sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
+ if (sLinkerLoadAddress == 0) {
+ Log.i(TAG, "Shared RELRO support disabled!");
+ }
+ }
+ sLinkerInitialized = true;
+ }
+
+ private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
+ assert LauncherThread.runningOnLauncherThread();
+ assert sLinkerInitialized;
+
+ if (sLinkerLoadAddress == 0) return null;
+
+ // Always wait for the shared RELROs in service processes.
+ final boolean waitForSharedRelros = true;
+ if (Linker.areTestsEnabled()) {
+ Linker linker = Linker.getInstance();
+ return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros,
+ linker.getTestRunnerClassNameForTesting(),
+ linker.getImplementationForTesting());
+ } else {
+ return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros);
+ }
+ }
+
+ /**
+ * Creates the common bundle to be passed to child processes through the service binding intent.
+ * If the service gets recreated by the framework the intent will be reused, so these parameters
+ * should be common to all processes of that type.
+ *
+ * @param commandLine Command line params to be passed to the service.
+ * @param linkerParams Linker params to start the service.
+ */
+ // TODO(jcivelli): make private once warmup connection code is move from ChildProcessLauncher to
+ // this class and remove initLinker call.
+ static Bundle createServiceBundle(boolean bindToCallerCheck) {
+ initLinker();
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCallerCheck);
+ bundle.putParcelable(
+ ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNewConnection());
+ return bundle;
+ }
+
+ @VisibleForTesting
+ public static Bundle createConnectionBundle(
+ String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
+ assert sLinkerInitialized;
+
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandLine);
+ bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMapped);
+ // content specific parameters.
+ bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
+ bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
+ bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance().getSharedRelros());
+ return bundle;
+ }
+
+ // Below are methods that will eventually be moved to a content delegate class.
+
+ private void onBeforeConnectionAllocated(Bundle commonParameters) {
+ // TODO(jcivelli): move createServiceBundle in there.
+ }
+
+ private IBinder getIBinderCallback() {
+ return mIBinderCallback;
+ }
+
+ // Testing only related methods.
+ @VisibleForTesting
+ public static ChildProcessLauncherHelper createAndStartForTesting(long nativePointer,
+ String[] commandLine, FileDescriptorInfo[] filesToBeMapped,
+ ChildProcessCreationParams creationParams, boolean sandboxed,
+ boolean alwaysInForeground) {
+ String processType =
+ ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
+ ChildProcessLauncherHelper launcherHelper =
+ new ChildProcessLauncherHelper(nativePointer, processType);
+ launcherHelper.start(ContextUtils.getApplicationContext(), commandLine, filesToBeMapped,
+ creationParams, sandboxed, alwaysInForeground);
+ return launcherHelper;
+ }
+
+ @VisibleForTesting
+ public ChildProcessConnection getChildProcessConnection() {
+ return mChildProcessConnection;
+ }
}

Powered by Google App Engine
This is Rietveld 408576698