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

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

Issue 2017963003: Upstream: ChildProcessLauncher connects renderer processes of WebAPKs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove PROCESS_WEBAPK_CHILD. Created 4 years, 6 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 caf965ae8c36f030844bc39ee94d2f180067bc6a..daa8aef6caa8d07814f24bbe61e1f2349597d96e 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
@@ -67,6 +67,9 @@ public class ChildProcessLauncher {
private Class<? extends ChildProcessService> mChildClass;
private final boolean mInSandbox;
+ // Each Allocator keeps a queue for the pending spawn data. Once a connection is free, we
+ // dequeue the pending spawn data from the same allocator as the connection.
+ private final PendingSpawnQueue mPendingSpawnQueue = new PendingSpawnQueue();
public ChildConnectionAllocator(boolean inSandbox, int numChildServices) {
mChildProcessConnections = new ChildProcessConnectionImpl[numChildServices];
@@ -125,6 +128,10 @@ public class ChildProcessLauncher {
}
}
+ public PendingSpawnQueue getPendingSpawnQueue() {
+ return mPendingSpawnQueue;
+ }
+
/** @return the count of connections managed by the allocator */
@VisibleForTesting
int allocatedConnectionsCountForTesting() {
@@ -140,6 +147,7 @@ public class ChildProcessLauncher {
private final long mClientContext;
private final int mCallbackType;
private final boolean mInSandbox;
+ private final ChildProcessCreationParams mCreationParams;
private PendingSpawnData(
Context context,
@@ -148,7 +156,8 @@ public class ChildProcessLauncher {
FileDescriptorInfo[] filesToBeMapped,
long clientContext,
int callbackType,
- boolean inSandbox) {
+ boolean inSandbox,
+ ChildProcessCreationParams creationParams) {
mContext = context;
mCommandLine = commandLine;
mChildProcessId = childProcessId;
@@ -156,6 +165,7 @@ public class ChildProcessLauncher {
mClientContext = clientContext;
mCallbackType = callbackType;
mInSandbox = inSandbox;
+ mCreationParams = creationParams;
}
private Context context() {
@@ -179,22 +189,24 @@ public class ChildProcessLauncher {
private boolean inSandbox() {
return mInSandbox;
}
+ private ChildProcessCreationParams getCreationParams() {
+ return mCreationParams;
+ }
}
private static class PendingSpawnQueue {
// The list of pending process spawn requests and its lock.
// Operations on this queue must be atomical w.r.t. free connections updates.
- private static Queue<PendingSpawnData> sPendingSpawns =
- new LinkedList<PendingSpawnData>();
- static final Object sPendingSpawnsLock = new Object();
+ private Queue<PendingSpawnData> mPendingSpawns = new LinkedList<PendingSpawnData>();
+ final Object mPendingSpawnsLock = new Object();
/**
* Queue up a spawn requests to be processed once a free service is available.
* Called when a spawn is requested while we are at the capacity.
*/
public void enqueueLocked(final PendingSpawnData pendingSpawn) {
- assert Thread.holdsLock(sPendingSpawnsLock);
- sPendingSpawns.add(pendingSpawn);
+ assert Thread.holdsLock(mPendingSpawnsLock);
+ mPendingSpawns.add(pendingSpawn);
}
/**
@@ -202,22 +214,21 @@ public class ChildProcessLauncher {
* @return the next spawn request waiting in the queue.
*/
public PendingSpawnData dequeueLocked() {
- assert Thread.holdsLock(sPendingSpawnsLock);
- return sPendingSpawns.poll();
+ assert Thread.holdsLock(mPendingSpawnsLock);
+ return mPendingSpawns.poll();
}
/** @return the count of pending spawns in the queue */
public int sizeLocked() {
- assert Thread.holdsLock(sPendingSpawnsLock);
- return sPendingSpawns.size();
+ assert Thread.holdsLock(mPendingSpawnsLock);
+ return mPendingSpawns.size();
}
}
- private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawnQueue();
-
- // Service class for child process. As the default value it uses SandboxedProcessService0 and
- // PrivilegedProcessService0.
- private static ChildConnectionAllocator sSandboxedChildConnectionAllocator;
+ // Service class for child process.
+ // Map from package name to ChildConnectionAllocator.
+ private static Map<String, ChildConnectionAllocator> sSandboxedChildConnectionAllocatorMap;
+ // As the default value it uses PrivilegedProcessService0.
private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator;
private static final String NUM_SANDBOXED_SERVICES_KEY =
@@ -228,17 +239,16 @@ public class ChildProcessLauncher {
@VisibleForTesting
public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num-sandboxed-services";
- private static int getNumberOfServices(Context context, boolean inSandbox) {
+ private static int getNumberOfServices(Context context, boolean inSandbox, String packageName) {
try {
PackageManager packageManager = context.getPackageManager();
- ChildProcessCreationParams childProcessCreationParams =
- ChildProcessCreationParams.get();
- final String packageName = childProcessCreationParams != null
- ? childProcessCreationParams.getPackageName() : context.getPackageName();
ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName,
PackageManager.GET_META_DATA);
- int numServices = appInfo.metaData.getInt(inSandbox ? NUM_SANDBOXED_SERVICES_KEY
- : NUM_PRIVILEGED_SERVICES_KEY, -1);
+ int numServices = -1;
+ if (appInfo.metaData != null) {
+ numServices = appInfo.metaData.getInt(
+ inSandbox ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_SERVICES_KEY, -1);
+ }
if (inSandbox
&& CommandLine.getInstance().hasSwitch(
SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) {
@@ -262,26 +272,56 @@ public class ChildProcessLauncher {
}
}
- private static void initConnectionAllocatorsIfNecessary(Context context) {
+ private static void initConnectionAllocatorsIfNecessary(
+ Context context, boolean inSandbox, String packageName) {
+ // TODO(mariakhomenko): Uses an Object to lock the access.
synchronized (ChildProcessLauncher.class) {
- if (sSandboxedChildConnectionAllocator == null) {
- sSandboxedChildConnectionAllocator =
- new ChildConnectionAllocator(true, getNumberOfServices(context, true));
- }
- if (sPrivilegedChildConnectionAllocator == null) {
- sPrivilegedChildConnectionAllocator =
- new ChildConnectionAllocator(false, getNumberOfServices(context, false));
+ if (inSandbox) {
+ if (sSandboxedChildConnectionAllocatorMap == null) {
+ sSandboxedChildConnectionAllocatorMap =
+ new ConcurrentHashMap<String, ChildConnectionAllocator>();
+ }
+ if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) {
+ Log.w(TAG, "Create a new ChildConnectionAllocator with package name = %s,"
+ + " inSandbox = true",
+ packageName);
+ sSandboxedChildConnectionAllocatorMap.put(packageName,
+ new ChildConnectionAllocator(true,
+ getNumberOfServices(context, true, packageName)));
+ }
+ } else if (sPrivilegedChildConnectionAllocator == null) {
+ sPrivilegedChildConnectionAllocator = new ChildConnectionAllocator(
+ false, getNumberOfServices(context, false, packageName));
}
+ // TODO(pkotwicz|hanxi): Figure out when old allocators should be removed from
+ // {@code sSandboxedChildConnectionAllocatorMap}.
}
}
- private static ChildConnectionAllocator getConnectionAllocator(boolean inSandbox) {
- return inSandbox
- ? sSandboxedChildConnectionAllocator : sPrivilegedChildConnectionAllocator;
+ /**
+ * Note: please make sure that the Allocator has been initialized before calling this function.
+ * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first.
+ */
+ private static ChildConnectionAllocator getConnectionAllocator(
+ String packageName, boolean inSandbox) {
+ if (!inSandbox) {
+ return sPrivilegedChildConnectionAllocator;
+ }
+ return sSandboxedChildConnectionAllocatorMap.get(packageName);
+ }
+
+ /**
+ * Get the PendingSpawnQueue of the Allocator. Initialize the Allocator if needed.
+ */
+ private static PendingSpawnQueue getPendingSpawnQueue(Context context, String packageName,
+ boolean inSandbox) {
+ initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
+ return getConnectionAllocator(packageName, inSandbox).getPendingSpawnQueue();
}
private static ChildProcessConnection allocateConnection(Context context, boolean inSandbox,
- ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForeground) {
+ ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForeground,
+ ChildProcessCreationParams creationParams) {
ChildProcessConnection.DeathCallback deathCallback =
new ChildProcessConnection.DeathCallback() {
@Override
@@ -293,9 +333,12 @@ public class ChildProcessLauncher {
}
}
};
- initConnectionAllocatorsIfNecessary(context);
- return getConnectionAllocator(inSandbox).allocate(context, deathCallback,
- chromiumLinkerParams, alwaysInForeground, ChildProcessCreationParams.get());
+ String packageName = creationParams != null ? creationParams.getPackageName()
+ : context.getPackageName();
+ initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
+ return getConnectionAllocator(packageName, inSandbox)
+ .allocate(context, deathCallback, chromiumLinkerParams, alwaysInForeground,
+ creationParams);
}
private static boolean sLinkerInitialized = false;
@@ -329,14 +372,18 @@ public class ChildProcessLauncher {
}
private static ChildProcessConnection allocateBoundConnection(Context context,
- String[] commandLine, boolean inSandbox, boolean alwaysInForeground) {
+ String[] commandLine, boolean inSandbox, boolean alwaysInForeground,
+ ChildProcessCreationParams creationParams) {
ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnection();
- ChildProcessConnection connection = allocateConnection(context, inSandbox,
- chromiumLinkerParams, alwaysInForeground);
+ ChildProcessConnection connection = allocateConnection(
+ context, inSandbox, chromiumLinkerParams, alwaysInForeground, creationParams);
if (connection != null) {
connection.start(commandLine);
- if (inSandbox && !sSandboxedChildConnectionAllocator.isFreeConnectionAvailable()) {
+ String packageName = creationParams != null ? creationParams.getPackageName()
+ : context.getPackageName();
+ if (inSandbox && !getConnectionAllocator(packageName, inSandbox)
+ .isFreeConnectionAvailable()) {
// Proactively releases all the moderate bindings once all the sandboxed services
// are allocated, which will be very likely to have some of them killed by OOM
// killer.
@@ -370,7 +417,7 @@ public class ChildProcessLauncher {
startInternal(pendingSpawn.context(), pendingSpawn.commandLine(),
pendingSpawn.childProcessId(), pendingSpawn.filesToBeMapped(),
pendingSpawn.clientContext(), pendingSpawn.callbackType(),
- pendingSpawn.inSandbox());
+ pendingSpawn.inSandbox(), pendingSpawn.getCreationParams());
}
}).start();
}
@@ -379,9 +426,13 @@ public class ChildProcessLauncher {
}
private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcessConnection conn) {
- synchronized (PendingSpawnQueue.sPendingSpawnsLock) {
- getConnectionAllocator(conn.isInSandbox()).free(conn);
- return sPendingSpawnQueue.dequeueLocked();
+ ChildConnectionAllocator allocator = getConnectionAllocator(
+ conn.getPackageName(), conn.isInSandbox());
+ assert allocator != null;
+ PendingSpawnQueue pendingSpawnQueue = allocator.getPendingSpawnQueue();
+ synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
+ allocator.free(conn);
+ return pendingSpawnQueue.dequeueLocked();
}
}
@@ -513,6 +564,9 @@ public class ChildProcessLauncher {
/**
* Starts moderate binding management.
+ * Note: WebAPKs and non WebAPKs share the same moderate binding pool, so the size of the
+ * shared moderate binding pool is always set based on the number of sandboxes processes
+ * used by Chrome.
* @param context Android's context.
* @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate
* binding to a render process when it is created and remove the moderate binding when Chrome is
@@ -520,8 +574,9 @@ public class ChildProcessLauncher {
*/
public static void startModerateBindingManagement(
Context context, boolean moderateBindingTillBackgrounded) {
- sBindingManager.startModerateBindingManagement(
- context, getNumberOfServices(context, true), moderateBindingTillBackgrounded);
+ sBindingManager.startModerateBindingManagement(context,
+ getNumberOfServices(context, true, context.getPackageName()),
+ moderateBindingTillBackgrounded);
}
/**
@@ -544,14 +599,17 @@ public class ChildProcessLauncher {
* in parallel to other startup work. Must not be called on the UI thread. Spare connection is
* created in sandboxed child process.
* @param context the application context used for the connection.
- * @param params child process creation params.
*/
- public static void warmUp(Context context, ChildProcessCreationParams params) {
- ChildProcessCreationParams.set(params);
+ public static void warmUp(Context context) {
synchronized (ChildProcessLauncher.class) {
assert !ThreadUtils.runningOnUiThread();
if (sSpareSandboxedConnection == null) {
- sSpareSandboxedConnection = allocateBoundConnection(context, null, true, false);
+ ChildProcessCreationParams params = ChildProcessCreationParams.get();
+ if (params != null) {
+ params = params.copy();
+ }
+ sSpareSandboxedConnection = allocateBoundConnection(context, null, true, false,
+ params);
}
}
}
@@ -594,8 +652,12 @@ public class ChildProcessLauncher {
boolean inSandbox = true;
String processType =
ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);
+ ChildProcessCreationParams params = null;
if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
callbackType = CALLBACK_FOR_RENDERER_PROCESS;
+ if (ChildProcessCreationParams.get() != null) {
+ params = ChildProcessCreationParams.get().copy();
+ }
} else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
callbackType = CALLBACK_FOR_GPU_PROCESS;
inSandbox = false;
@@ -607,7 +669,7 @@ public class ChildProcessLauncher {
}
startInternal(context, commandLine, childProcessId, filesToBeMapped, clientContext,
- callbackType, inSandbox);
+ callbackType, inSandbox, params);
}
/**
@@ -650,13 +712,17 @@ public class ChildProcessLauncher {
FileDescriptorInfo[] filesToBeMapped,
long clientContext,
int callbackType,
- boolean inSandbox) {
+ boolean inSandbox,
+ ChildProcessCreationParams creationParams) {
try {
TraceEvent.begin("ChildProcessLauncher.startInternal");
ChildProcessConnection allocatedConnection = null;
+ String packageName = creationParams != null ? creationParams.getPackageName()
+ : context.getPackageName();
synchronized (ChildProcessLauncher.class) {
- if (inSandbox) {
+ if (inSandbox && sSpareSandboxedConnection != null
+ && sSpareSandboxedConnection.getPackageName().equals(packageName)) {
allocatedConnection = sSpareSandboxedConnection;
sSpareSandboxedConnection = null;
}
@@ -664,14 +730,16 @@ public class ChildProcessLauncher {
if (allocatedConnection == null) {
boolean alwaysInForeground = false;
if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
- synchronized (PendingSpawnQueue.sPendingSpawnsLock) {
+ PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(
+ context, packageName, inSandbox);
+ synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
allocatedConnection = allocateBoundConnection(
- context, commandLine, inSandbox, alwaysInForeground);
+ context, commandLine, inSandbox, alwaysInForeground, creationParams);
if (allocatedConnection == null) {
Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
- sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, commandLine,
+ pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, commandLine,
childProcessId, filesToBeMapped, clientContext,
- callbackType, inSandbox));
+ callbackType, inSandbox, creationParams));
return;
}
}
@@ -848,26 +916,35 @@ public class ChildProcessLauncher {
}
@VisibleForTesting
- static ChildProcessConnection allocateBoundConnectionForTesting(Context context) {
- return allocateBoundConnection(context, null, true, false);
+ static ChildProcessConnection allocateBoundConnectionForTesting(Context context,
+ ChildProcessCreationParams creationParams) {
+ return allocateBoundConnection(context, null, true, false, creationParams);
}
/**
* Queue up a spawn requests for testing.
*/
@VisibleForTesting
- static void enqueuePendingSpawnForTesting(Context context, String[] commandLine) {
- synchronized (PendingSpawnQueue.sPendingSpawnsLock) {
- sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, commandLine, 1,
- new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true));
+ static void enqueuePendingSpawnForTesting(Context context, String[] commandLine,
+ ChildProcessCreationParams creationParams, boolean inSandbox) {
+ PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context,
+ creationParams.getPackageName(), inSandbox);
+ synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
+ pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, commandLine, 1,
+ new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true,
+ creationParams));
}
}
- /** @return the count of sandboxed connections managed by the allocator */
+ /**
+ * @return the number of sandboxed connections of given {@link packageName} managed by the
+ * allocator.
+ */
@VisibleForTesting
- static int allocatedConnectionsCountForTesting(Context context) {
- initConnectionAllocatorsIfNecessary(context);
- return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTesting();
+ static int allocatedSandboxedConnectionsCountForTesting(Context context, String packageName) {
+ initConnectionAllocatorsIfNecessary(context, true, packageName);
+ return sSandboxedChildConnectionAllocatorMap.get(packageName)
+ .allocatedConnectionsCountForTesting();
}
/** @return the count of services set up and working */
@@ -876,11 +953,18 @@ public class ChildProcessLauncher {
return sServiceMap.size();
}
- /** @return the count of pending spawns in the queue */
+ /**
+ * @param context The context.
+ * @param packageName The package name of the {@link ChildProcessAlocator}.
+ * @param inSandbox Whether the connection is sandboxed.
+ * @return the count of pending spawns in the queue.
+ */
@VisibleForTesting
- static int pendingSpawnsCountForTesting() {
- synchronized (PendingSpawnQueue.sPendingSpawnsLock) {
- return sPendingSpawnQueue.sizeLocked();
+ static int pendingSpawnsCountForTesting(Context context, String packageName,
+ boolean inSandbox) {
+ PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, packageName, inSandbox);
+ synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
+ return pendingSpawnQueue.sizeLocked();
}
}

Powered by Google App Engine
This is Rietveld 408576698