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

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

Issue 2650013003: Bind Android ChildProcessServices to a specific client PID. (Closed)
Patch Set: Created 3 years, 11 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/ChildProcessLauncher.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index aed55c3f5328b61e80ea44f357b26f3418a24258..3ae8def576b792254f5e7a6df9383ab1dbdbbd96 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -8,6 +8,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -413,12 +414,13 @@ public class ChildProcessLauncher {
private static ChildProcessConnection allocateBoundConnection(Context context,
String[] commandLine, boolean inSandbox, boolean alwaysInForeground,
- ChildProcessCreationParams creationParams) {
+ ChildProcessCreationParams creationParams,
+ ChildProcessConnection.StartCallback startCallback) {
ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnection();
ChildProcessConnection connection = allocateConnection(
context, inSandbox, chromiumLinkerParams, alwaysInForeground, creationParams);
if (connection != null) {
- connection.start(commandLine);
+ connection.start(commandLine, startCallback);
String packageName = creationParams != null ? creationParams.getPackageName()
: context.getPackageName();
@@ -436,7 +438,7 @@ public class ChildProcessLauncher {
private static final long FREE_CONNECTION_DELAY_MILLIS = 1;
private static void freeConnection(ChildProcessConnection connection) {
- synchronized (ChildProcessLauncher.class) {
+ synchronized (sSpareConnectionLock) {
if (connection.equals(sSpareSandboxedConnection)) sSpareSandboxedConnection = null;
}
@@ -483,8 +485,16 @@ public class ChildProcessLauncher {
private static Map<Integer, ChildProcessConnection> sServiceMap =
new ConcurrentHashMap<Integer, ChildProcessConnection>();
+ // Lock and monitor for these members {{{
+ private static final Object sSpareConnectionLock = new Object();
// A pre-allocated and pre-bound connection ready for connection setup, or null.
private static ChildProcessConnection sSpareSandboxedConnection;
+ // If sSpareSandboxedConnection is not null, this indicates whether the service is
+ // ready for connection setup. Wait on the monitor lock to be notified when this
+ // state changes. sSpareSandboxedConnection may be null after waiting, if starting
+ // the service failed.
+ private static boolean sSpareConnectionStarting;
+ // }}}
// Manages oom bindings used to bind chind services.
private static BindingManager sBindingManager = BindingManagerImpl.createBindingManager();
@@ -567,15 +577,38 @@ public class ChildProcessLauncher {
* @param context the application context used for the connection.
*/
public static void warmUp(Context context) {
- synchronized (ChildProcessLauncher.class) {
+ synchronized (sSpareConnectionLock) {
assert !ThreadUtils.runningOnUiThread();
if (sSpareSandboxedConnection == null) {
ChildProcessCreationParams params = ChildProcessCreationParams.get();
if (params != null) {
params = params.copy();
}
+
+ sSpareConnectionStarting = true;
+
+ ChildProcessConnection.StartCallback startCallback =
+ new ChildProcessConnection.StartCallback() {
+ @Override
+ public void onChildStarted() {
+ synchronized (sSpareConnectionLock) {
+ sSpareConnectionStarting = false;
+ sSpareConnectionLock.notify();
+ }
+ }
+
+ @Override
+ public void onChildStartFailed() {
+ Log.e(TAG, "Failed to warm up the spare sandbox service");
+ synchronized (sSpareConnectionLock) {
+ sSpareSandboxedConnection = null;
+ sSpareConnectionStarting = false;
+ sSpareConnectionLock.notify();
+ }
+ }
+ };
sSpareSandboxedConnection = allocateBoundConnection(context, null, true, false,
- params);
+ params, startCallback);
}
}
}
@@ -653,24 +686,30 @@ public class ChildProcessLauncher {
callbackType, inSandbox, params);
}
- private static void startInternal(
- Context context,
+ private static ChildProcessConnection startInternal(
+ final Context context,
final String[] commandLine,
- int childProcessId,
- FileDescriptorInfo[] filesToBeMapped,
- long clientContext,
- int callbackType,
- boolean inSandbox,
- ChildProcessCreationParams creationParams) {
+ final int childProcessId,
+ final FileDescriptorInfo[] filesToBeMapped,
+ final long clientContext,
+ final int callbackType,
+ final boolean inSandbox,
+ final ChildProcessCreationParams creationParams) {
try {
TraceEvent.begin("ChildProcessLauncher.startInternal");
ChildProcessConnection allocatedConnection = null;
String packageName = creationParams != null ? creationParams.getPackageName()
: context.getPackageName();
- synchronized (ChildProcessLauncher.class) {
+ synchronized (sSpareConnectionLock) {
if (inSandbox && sSpareSandboxedConnection != null
&& sSpareSandboxedConnection.getPackageName().equals(packageName)) {
+ while (sSpareConnectionStarting) {
+ try {
+ sSpareConnectionLock.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
allocatedConnection = sSpareSandboxedConnection;
sSpareSandboxedConnection = null;
}
@@ -680,15 +719,39 @@ public class ChildProcessLauncher {
if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(
context, packageName, inSandbox);
+ ChildProcessConnection.StartCallback startCallback =
+ new ChildProcessConnection.StartCallback() {
+ @Override
+ public void onChildStarted() {}
+
+ @Override
+ public void onChildStartFailed() {
+ Log.e(TAG, "ChildProcessConnection.start failed, trying again");
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
+ @Override
+ public void run() {
+ // The child process may already be bound to another client
+ // (this can happen if multi-process WebView is used in more
+ // than one process), so try starting the process again.
+ // This connection that failed to start has not been freed,
+ // so a new bound connection will be allocated.
+ startInternal(context, commandLine, childProcessId,
+ filesToBeMapped, clientContext, callbackType,
+ inSandbox, creationParams);
+ }
+ });
+ }
+ };
synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
allocatedConnection = allocateBoundConnection(
- context, commandLine, inSandbox, alwaysInForeground, creationParams);
+ context, commandLine, inSandbox, alwaysInForeground, creationParams,
+ startCallback);
if (allocatedConnection == null) {
Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, commandLine,
childProcessId, filesToBeMapped, clientContext,
callbackType, inSandbox, creationParams));
- return;
+ return null;
}
}
}
@@ -697,6 +760,7 @@ public class ChildProcessLauncher {
allocatedConnection.getServiceNumber());
triggerConnectionSetup(allocatedConnection, commandLine, childProcessId,
filesToBeMapped, callbackType, clientContext);
+ return allocatedConnection;
} finally {
TraceEvent.end("ChildProcessLauncher.startInternal");
}
@@ -834,9 +898,16 @@ public class ChildProcessLauncher {
}
@VisibleForTesting
+ public static ChildProcessConnection startForTesting(Context context, String[] commandLine,
+ FileDescriptorInfo[] filesToMap, ChildProcessCreationParams params) {
+ return startInternal(context, commandLine, 0, filesToMap, 0,
+ CALLBACK_FOR_RENDERER_PROCESS, true, params);
+ }
+
+ @VisibleForTesting
static ChildProcessConnection allocateBoundConnectionForTesting(Context context,
ChildProcessCreationParams creationParams) {
- return allocateBoundConnection(context, null, true, false, creationParams);
+ return allocateBoundConnection(context, null, true, false, creationParams, null);
}
@VisibleForTesting
@@ -874,6 +945,14 @@ public class ChildProcessLauncher {
.allocatedConnectionsCountForTesting();
}
+ /**
+ * @return the service map of connected services
+ */
+ @VisibleForTesting
+ static Map<Integer, ChildProcessConnection> getServiceMapForTesting() {
+ return sServiceMap;
+ }
+
/** @return the count of services set up and working */
@VisibleForTesting
static int connectedServicesCountForTesting() {

Powered by Google App Engine
This is Rietveld 408576698