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

Side by Side 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 the assumption that ChildProcessCreationParams is always non null. 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser; 5 package org.chromium.content.browser;
6 6
7 import android.annotation.SuppressLint; 7 import android.annotation.SuppressLint;
8 import android.content.Context; 8 import android.content.Context;
9 import android.content.Intent; 9 import android.content.Intent;
10 import android.content.pm.ApplicationInfo; 10 import android.content.pm.ApplicationInfo;
(...skipping 20 matching lines...) Expand all
31 import org.chromium.content.app.ChromiumLinkerParams; 31 import org.chromium.content.app.ChromiumLinkerParams;
32 import org.chromium.content.app.DownloadProcessService; 32 import org.chromium.content.app.DownloadProcessService;
33 import org.chromium.content.app.PrivilegedProcessService; 33 import org.chromium.content.app.PrivilegedProcessService;
34 import org.chromium.content.app.SandboxedProcessService; 34 import org.chromium.content.app.SandboxedProcessService;
35 import org.chromium.content.common.ContentSwitches; 35 import org.chromium.content.common.ContentSwitches;
36 import org.chromium.content.common.IChildProcessCallback; 36 import org.chromium.content.common.IChildProcessCallback;
37 import org.chromium.content.common.SurfaceWrapper; 37 import org.chromium.content.common.SurfaceWrapper;
38 38
39 import java.io.IOException; 39 import java.io.IOException;
40 import java.util.ArrayList; 40 import java.util.ArrayList;
41 import java.util.HashMap;
41 import java.util.LinkedList; 42 import java.util.LinkedList;
42 import java.util.Map; 43 import java.util.Map;
43 import java.util.Queue; 44 import java.util.Queue;
44 import java.util.concurrent.ConcurrentHashMap; 45 import java.util.concurrent.ConcurrentHashMap;
45 46
46 /** 47 /**
47 * This class provides the method to start/stop ChildProcess called by native. 48 * This class provides the method to start/stop ChildProcess called by native.
48 */ 49 */
49 @JNINamespace("content") 50 @JNINamespace("content")
50 public class ChildProcessLauncher { 51 public class ChildProcessLauncher {
51 private static final String TAG = "ChildProcLauncher"; 52 private static final String TAG = "ChildProcLauncher";
52 53
53 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0; 54 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0;
54 static final int CALLBACK_FOR_GPU_PROCESS = 1; 55 static final int CALLBACK_FOR_GPU_PROCESS = 1;
55 static final int CALLBACK_FOR_RENDERER_PROCESS = 2; 56 static final int CALLBACK_FOR_RENDERER_PROCESS = 2;
56 static final int CALLBACK_FOR_UTILITY_PROCESS = 3; 57 static final int CALLBACK_FOR_UTILITY_PROCESS = 3;
57 static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4; 58 static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4;
58 59
59 private static class ChildConnectionAllocator { 60 private static class ChildConnectionAllocator {
60 // Connections to services. Indices of the array correspond to the servi ce numbers. 61 // Connections to services. Indices of the array correspond to the servi ce numbers.
61 private final ChildProcessConnection[] mChildProcessConnections; 62 private final ChildProcessConnection[] mChildProcessConnections;
62 63
63 // The list of free (not bound) service indices. 64 // The list of free (not bound) service indices.
64 // SHOULD BE ACCESSED WITH mConnectionLock. 65 // SHOULD BE ACCESSED WITH mConnectionLock.
65 private final ArrayList<Integer> mFreeConnectionIndices; 66 private final ArrayList<Integer> mFreeConnectionIndices;
66 private final Object mConnectionLock = new Object(); 67 private final Object mConnectionLock = new Object();
67 68
68 private Class<? extends ChildProcessService> mChildClass; 69 private Class<? extends ChildProcessService> mChildClass;
69 private final boolean mInSandbox; 70 private final boolean mInSandbox;
71 // Each Allocator keeps an queue for the pending spawn data. Once a conn ection is free, we
72 // dequeue the pending spawn data from the same allocator as the connect ion.
73 private PendingSpawnQueue mPendingSpawnQueue = new PendingSpawnQueue();
Maria 2016/06/07 17:20:17 final? an queue -> a queue.
Xi Han 2016/06/07 18:50:00 Done.
70 74
71 public ChildConnectionAllocator(boolean inSandbox, int numChildServices) { 75 public ChildConnectionAllocator(boolean inSandbox, int numChildServices) {
72 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices]; 76 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices];
73 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); 77 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices);
74 for (int i = 0; i < numChildServices; i++) { 78 for (int i = 0; i < numChildServices; i++) {
75 mFreeConnectionIndices.add(i); 79 mFreeConnectionIndices.add(i);
76 } 80 }
77 mChildClass = 81 mChildClass =
78 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class; 82 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class;
79 mInSandbox = inSandbox; 83 mInSandbox = inSandbox;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 122 }
119 } 123 }
120 } 124 }
121 125
122 public boolean isFreeConnectionAvailable() { 126 public boolean isFreeConnectionAvailable() {
123 synchronized (mConnectionLock) { 127 synchronized (mConnectionLock) {
124 return !mFreeConnectionIndices.isEmpty(); 128 return !mFreeConnectionIndices.isEmpty();
125 } 129 }
126 } 130 }
127 131
132 public PendingSpawnQueue getPendingSpawnQueue() {
133 return mPendingSpawnQueue;
134 }
135
128 /** @return the count of connections managed by the allocator */ 136 /** @return the count of connections managed by the allocator */
129 @VisibleForTesting 137 @VisibleForTesting
130 int allocatedConnectionsCountForTesting() { 138 int allocatedConnectionsCountForTesting() {
131 return mChildProcessConnections.length - mFreeConnectionIndices.size (); 139 return mChildProcessConnections.length - mFreeConnectionIndices.size ();
132 } 140 }
133 } 141 }
134 142
135 private static class PendingSpawnData { 143 private static class PendingSpawnData {
136 private final Context mContext; 144 private final Context mContext;
137 private final String[] mCommandLine; 145 private final String[] mCommandLine;
138 private final int mChildProcessId; 146 private final int mChildProcessId;
139 private final FileDescriptorInfo[] mFilesToBeMapped; 147 private final FileDescriptorInfo[] mFilesToBeMapped;
140 private final long mClientContext; 148 private final long mClientContext;
141 private final int mCallbackType; 149 private final int mCallbackType;
142 private final boolean mInSandbox; 150 private final boolean mInSandbox;
151 private final ChildProcessCreationParams mCreationParams;
143 152
144 private PendingSpawnData( 153 private PendingSpawnData(
145 Context context, 154 Context context,
146 String[] commandLine, 155 String[] commandLine,
147 int childProcessId, 156 int childProcessId,
148 FileDescriptorInfo[] filesToBeMapped, 157 FileDescriptorInfo[] filesToBeMapped,
149 long clientContext, 158 long clientContext,
150 int callbackType, 159 int callbackType,
151 boolean inSandbox) { 160 boolean inSandbox,
161 ChildProcessCreationParams creationParams) {
152 mContext = context; 162 mContext = context;
153 mCommandLine = commandLine; 163 mCommandLine = commandLine;
154 mChildProcessId = childProcessId; 164 mChildProcessId = childProcessId;
155 mFilesToBeMapped = filesToBeMapped; 165 mFilesToBeMapped = filesToBeMapped;
156 mClientContext = clientContext; 166 mClientContext = clientContext;
157 mCallbackType = callbackType; 167 mCallbackType = callbackType;
158 mInSandbox = inSandbox; 168 mInSandbox = inSandbox;
169 mCreationParams = creationParams;
159 } 170 }
160 171
161 private Context context() { 172 private Context context() {
162 return mContext; 173 return mContext;
163 } 174 }
164 private String[] commandLine() { 175 private String[] commandLine() {
165 return mCommandLine; 176 return mCommandLine;
166 } 177 }
167 private int childProcessId() { 178 private int childProcessId() {
168 return mChildProcessId; 179 return mChildProcessId;
169 } 180 }
170 private FileDescriptorInfo[] filesToBeMapped() { 181 private FileDescriptorInfo[] filesToBeMapped() {
171 return mFilesToBeMapped; 182 return mFilesToBeMapped;
172 } 183 }
173 private long clientContext() { 184 private long clientContext() {
174 return mClientContext; 185 return mClientContext;
175 } 186 }
176 private int callbackType() { 187 private int callbackType() {
177 return mCallbackType; 188 return mCallbackType;
178 } 189 }
179 private boolean inSandbox() { 190 private boolean inSandbox() {
180 return mInSandbox; 191 return mInSandbox;
181 } 192 }
193 private ChildProcessCreationParams getCreationParams() {
194 return mCreationParams;
195 }
182 } 196 }
183 197
184 private static class PendingSpawnQueue { 198 private static class PendingSpawnQueue {
185 // The list of pending process spawn requests and its lock. 199 // The list of pending process spawn requests and its lock.
186 // Operations on this queue must be atomical w.r.t. free connections upd ates. 200 // Operations on this queue must be atomical w.r.t. free connections upd ates.
187 private static Queue<PendingSpawnData> sPendingSpawns = 201 private Queue<PendingSpawnData> mPendingSpawns =
188 new LinkedList<PendingSpawnData>(); 202 new LinkedList<PendingSpawnData>();
Maria 2016/06/07 17:20:17 fits on one line
Xi Han 2016/06/07 18:49:59 Done.
189 static final Object sPendingSpawnsLock = new Object(); 203 final Object mPendingSpawnsLock = new Object();
Maria 2016/06/07 17:20:17 Now that the queue of spawns isn't static, do we s
Xi Han 2016/06/07 18:50:00 Good catch. Remove the lock.
190 204
191 /** 205 /**
192 * Queue up a spawn requests to be processed once a free service is avai lable. 206 * Queue up a spawn requests to be processed once a free service is avai lable.
193 * Called when a spawn is requested while we are at the capacity. 207 * Called when a spawn is requested while we are at the capacity.
194 */ 208 */
195 public void enqueueLocked(final PendingSpawnData pendingSpawn) { 209 public void enqueueLocked(final PendingSpawnData pendingSpawn) {
196 assert Thread.holdsLock(sPendingSpawnsLock); 210 assert Thread.holdsLock(mPendingSpawnsLock);
197 sPendingSpawns.add(pendingSpawn); 211 mPendingSpawns.add(pendingSpawn);
198 } 212 }
199 213
200 /** 214 /**
201 * Pop the next request from the queue. Called when a free service is av ailable. 215 * Pop the next request from the queue. Called when a free service is av ailable.
202 * @return the next spawn request waiting in the queue. 216 * @return the next spawn request waiting in the queue.
203 */ 217 */
204 public PendingSpawnData dequeueLocked() { 218 public PendingSpawnData dequeueLocked() {
205 assert Thread.holdsLock(sPendingSpawnsLock); 219 assert Thread.holdsLock(mPendingSpawnsLock);
206 return sPendingSpawns.poll(); 220 return mPendingSpawns.poll();
207 } 221 }
208 222
209 /** @return the count of pending spawns in the queue */ 223 /** @return the count of pending spawns in the queue */
210 public int sizeLocked() { 224 public int sizeLocked() {
211 assert Thread.holdsLock(sPendingSpawnsLock); 225 assert Thread.holdsLock(mPendingSpawnsLock);
212 return sPendingSpawns.size(); 226 return mPendingSpawns.size();
213 } 227 }
214 } 228 }
215 229
216 private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawn Queue(); 230 // Service class for child process.
217 231 // Map from package name to ChildConnectionAllocator;
Maria 2016/06/07 17:20:17 ; -> .
Xi Han 2016/06/07 18:50:00 Done.
218 // Service class for child process. As the default value it uses SandboxedPr ocessService0 and 232 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti onAllocatorMap;
219 // PrivilegedProcessService0. 233 // As the default value it uses PrivilegedProcessService0.
220 private static ChildConnectionAllocator sSandboxedChildConnectionAllocator;
221 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; 234 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator;
222 235
223 private static final String NUM_SANDBOXED_SERVICES_KEY = 236 private static final String NUM_SANDBOXED_SERVICES_KEY =
224 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; 237 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES";
225 private static final String NUM_PRIVILEGED_SERVICES_KEY = 238 private static final String NUM_PRIVILEGED_SERVICES_KEY =
226 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; 239 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES";
227 // Overrides the number of available sandboxed services. 240 // Overrides the number of available sandboxed services.
228 @VisibleForTesting 241 @VisibleForTesting
229 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services"; 242 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services";
230 243
231 private static int getNumberOfServices(Context context, boolean inSandbox) { 244 private static int getNumberOfServices(Context context, boolean inSandbox, S tring packageName) {
232 try { 245 try {
233 PackageManager packageManager = context.getPackageManager(); 246 PackageManager packageManager = context.getPackageManager();
234 ChildProcessCreationParams childProcessCreationParams =
235 ChildProcessCreationParams.get();
236 final String packageName = childProcessCreationParams != null
237 ? childProcessCreationParams.getPackageName() : context.getP ackageName();
238 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame, 247 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame,
239 PackageManager.GET_META_DATA); 248 PackageManager.GET_META_DATA);
240 int numServices = appInfo.metaData.getInt(inSandbox ? NUM_SANDBOXED_ SERVICES_KEY 249 int numServices = -1;
241 : NUM_PRIVILEGED_SERVICES_KEY, -1); 250 if (appInfo.metaData != null) {
251 numServices = appInfo.metaData.getInt(
252 inSandbox ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_ SERVICES_KEY, -1);
253 }
242 if (inSandbox 254 if (inSandbox
243 && CommandLine.getInstance().hasSwitch( 255 && CommandLine.getInstance().hasSwitch(
244 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { 256 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) {
245 String value = CommandLine.getInstance().getSwitchValue( 257 String value = CommandLine.getInstance().getSwitchValue(
246 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); 258 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING);
247 if (!TextUtils.isEmpty(value)) { 259 if (!TextUtils.isEmpty(value)) {
248 try { 260 try {
249 numServices = Integer.parseInt(value); 261 numServices = Integer.parseInt(value);
250 } catch (NumberFormatException e) { 262 } catch (NumberFormatException e) {
251 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " 263 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: "
252 + value); 264 + value);
253 } 265 }
254 } 266 }
255 } 267 }
256 if (numServices < 0) { 268 if (numServices < 0) {
257 throw new RuntimeException("Illegal meta data value for number o f child services"); 269 throw new RuntimeException("Illegal meta data value for number o f child services");
258 } 270 }
259 return numServices; 271 return numServices;
260 } catch (PackageManager.NameNotFoundException e) { 272 } catch (PackageManager.NameNotFoundException e) {
261 throw new RuntimeException("Could not get application info"); 273 throw new RuntimeException("Could not get application info");
262 } 274 }
263 } 275 }
264 276
265 private static void initConnectionAllocatorsIfNecessary(Context context) { 277 private static void initConnectionAllocatorsIfNecessary(
278 Context context, boolean inSandbox, String packageName) {
Maria 2016/06/07 17:20:17 it seems like previously this method allocated bot
Xi Han 2016/06/07 18:49:59 Yes, we can prevent the privileged process (GPU) i
266 synchronized (ChildProcessLauncher.class) { 279 synchronized (ChildProcessLauncher.class) {
267 if (sSandboxedChildConnectionAllocator == null) { 280 if (inSandbox) {
268 sSandboxedChildConnectionAllocator = 281 if (sSandboxedChildConnectionAllocatorMap == null) {
269 new ChildConnectionAllocator(true, getNumberOfServices(c ontext, true)); 282 sSandboxedChildConnectionAllocatorMap =
283 new HashMap<String, ChildConnectionAllocator>();
284 }
285 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) {
286 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s,"
287 + " inSandbox = true",
288 packageName);
289 sSandboxedChildConnectionAllocatorMap.put(packageName,
290 new ChildConnectionAllocator(true,
291 getNumberOfServices(context, true, packageNa me)));
292 }
293 } else if (sPrivilegedChildConnectionAllocator == null) {
294 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or(
295 false, getNumberOfServices(context, false, packageName)) ;
270 } 296 }
271 if (sPrivilegedChildConnectionAllocator == null) { 297 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from
272 sPrivilegedChildConnectionAllocator = 298 // {@code sSandboxedChildConnectionAllocatorMap}.
273 new ChildConnectionAllocator(false, getNumberOfServices( context, false));
274 }
275 } 299 }
276 } 300 }
277 301
278 private static ChildConnectionAllocator getConnectionAllocator(boolean inSan dbox) { 302 /**
279 return inSandbox 303 * Note: please make sure that the Allocator has been initialized before cal ling this function.
280 ? sSandboxedChildConnectionAllocator : sPrivilegedChildConnectio nAllocator; 304 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first .
305 */
306 private static ChildConnectionAllocator getConnectionAllocator(
307 String packageName, boolean inSandbox) {
308 if (!inSandbox) {
309 return sPrivilegedChildConnectionAllocator;
310 }
311 return sSandboxedChildConnectionAllocatorMap.get(packageName);
312 }
313
314 /**
315 * Get the PendingSpawnQueue of the Allocator. Initialize the Allocator if n eeded.
316 */
317 private static PendingSpawnQueue getPendingSpawnQueue(Context context, Strin g packageName,
318 boolean inSandbox) {
319 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
320 return getConnectionAllocator(packageName, inSandbox).getPendingSpawnQue ue();
281 } 321 }
282 322
283 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, 323 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox,
284 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d) { 324 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d,
325 ChildProcessCreationParams creationParams) {
285 ChildProcessConnection.DeathCallback deathCallback = 326 ChildProcessConnection.DeathCallback deathCallback =
286 new ChildProcessConnection.DeathCallback() { 327 new ChildProcessConnection.DeathCallback() {
287 @Override 328 @Override
288 public void onChildProcessDied(ChildProcessConnection connec tion) { 329 public void onChildProcessDied(ChildProcessConnection connec tion) {
289 if (connection.getPid() != 0) { 330 if (connection.getPid() != 0) {
290 stop(connection.getPid()); 331 stop(connection.getPid());
291 } else { 332 } else {
292 freeConnection(connection); 333 freeConnection(connection);
293 } 334 }
294 } 335 }
295 }; 336 };
296 initConnectionAllocatorsIfNecessary(context); 337 String packageName = creationParams != null ? creationParams.getPackageN ame()
297 return getConnectionAllocator(inSandbox).allocate(context, deathCallback , 338 : context.getPackageName();
298 chromiumLinkerParams, alwaysInForeground, ChildProcessCreationPa rams.get()); 339 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
340 return getConnectionAllocator(packageName, inSandbox)
341 .allocate(context, deathCallback, chromiumLinkerParams, alwaysIn Foreground,
342 creationParams);
299 } 343 }
300 344
301 private static boolean sLinkerInitialized = false; 345 private static boolean sLinkerInitialized = false;
302 private static long sLinkerLoadAddress = 0; 346 private static long sLinkerLoadAddress = 0;
303 347
304 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { 348 private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
305 if (!sLinkerInitialized) { 349 if (!sLinkerInitialized) {
306 if (Linker.isUsed()) { 350 if (Linker.isUsed()) {
307 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); 351 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
308 if (sLinkerLoadAddress == 0) { 352 if (sLinkerLoadAddress == 0) {
(...skipping 13 matching lines...) Expand all
322 waitForSharedRelros, 366 waitForSharedRelros,
323 linker.getTestRunnerClassNameForTest ing(), 367 linker.getTestRunnerClassNameForTest ing(),
324 linker.getImplementationForTesting() ); 368 linker.getImplementationForTesting() );
325 } else { 369 } else {
326 return new ChromiumLinkerParams(sLinkerLoadAddress, 370 return new ChromiumLinkerParams(sLinkerLoadAddress,
327 waitForSharedRelros); 371 waitForSharedRelros);
328 } 372 }
329 } 373 }
330 374
331 private static ChildProcessConnection allocateBoundConnection(Context contex t, 375 private static ChildProcessConnection allocateBoundConnection(Context contex t,
332 String[] commandLine, boolean inSandbox, boolean alwaysInForeground) { 376 String[] commandLine, boolean inSandbox, boolean alwaysInForeground,
377 ChildProcessCreationParams creationParams) {
333 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); 378 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion();
334 ChildProcessConnection connection = allocateConnection(context, inSandbo x, 379 ChildProcessConnection connection = allocateConnection(
335 chromiumLinkerParams, alwaysInForeground); 380 context, inSandbox, chromiumLinkerParams, alwaysInForeground, cr eationParams);
336 if (connection != null) { 381 if (connection != null) {
337 connection.start(commandLine); 382 connection.start(commandLine);
338 383
339 if (inSandbox && !sSandboxedChildConnectionAllocator.isFreeConnectio nAvailable()) { 384 String packageName = creationParams != null ? creationParams.getPack ageName()
385 : context.getPackageName();
386 if (inSandbox && !getConnectionAllocator(packageName, inSandbox)
387 .isFreeConnectionAvailable()) {
340 // Proactively releases all the moderate bindings once all the s andboxed services 388 // Proactively releases all the moderate bindings once all the s andboxed services
341 // are allocated, which will be very likely to have some of them killed by OOM 389 // are allocated, which will be very likely to have some of them killed by OOM
342 // killer. 390 // killer.
343 sBindingManager.releaseAllModerateBindings(); 391 sBindingManager.releaseAllModerateBindings();
344 } 392 }
345 } 393 }
346 return connection; 394 return connection;
347 } 395 }
348 396
349 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; 397 private static final long FREE_CONNECTION_DELAY_MILLIS = 1;
(...skipping 13 matching lines...) Expand all
363 @Override 411 @Override
364 public void run() { 412 public void run() {
365 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn); 413 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn);
366 if (pendingSpawn != null) { 414 if (pendingSpawn != null) {
367 new Thread(new Runnable() { 415 new Thread(new Runnable() {
368 @Override 416 @Override
369 public void run() { 417 public void run() {
370 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), 418 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(),
371 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), 419 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(),
372 pendingSpawn.clientContext(), pendingSpawn.c allbackType(), 420 pendingSpawn.clientContext(), pendingSpawn.c allbackType(),
373 pendingSpawn.inSandbox()); 421 pendingSpawn.inSandbox(), pendingSpawn.getCr eationParams());
374 } 422 }
375 }).start(); 423 }).start();
376 } 424 }
377 } 425 }
378 }, FREE_CONNECTION_DELAY_MILLIS); 426 }, FREE_CONNECTION_DELAY_MILLIS);
379 } 427 }
380 428
381 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) { 429 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) {
382 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { 430 ChildConnectionAllocator allocator = getConnectionAllocator(
383 getConnectionAllocator(conn.isInSandbox()).free(conn); 431 conn.getPackageName(), conn.isInSandbox());
384 return sPendingSpawnQueue.dequeueLocked(); 432 assert allocator != null;
433 PendingSpawnQueue pendingSpawnQueue = allocator.getPendingSpawnQueue();
434 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
435 allocator.free(conn);
436 return pendingSpawnQueue.dequeueLocked();
385 } 437 }
386 } 438 }
387 439
388 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. 440 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle.
389 private static final int NULL_PROCESS_HANDLE = 0; 441 private static final int NULL_PROCESS_HANDLE = 0;
390 442
391 // Map from pid to ChildService connection. 443 // Map from pid to ChildService connection.
392 private static Map<Integer, ChildProcessConnection> sServiceMap = 444 private static Map<Integer, ChildProcessConnection> sServiceMap =
393 new ConcurrentHashMap<Integer, ChildProcessConnection>(); 445 new ConcurrentHashMap<Integer, ChildProcessConnection>();
394 446
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 /** 558 /**
507 * Called when the embedding application is sent to background. 559 * Called when the embedding application is sent to background.
508 */ 560 */
509 public static void onSentToBackground() { 561 public static void onSentToBackground() {
510 sApplicationInForeground = false; 562 sApplicationInForeground = false;
511 sBindingManager.onSentToBackground(); 563 sBindingManager.onSentToBackground();
512 } 564 }
513 565
514 /** 566 /**
515 * Starts moderate binding management. 567 * Starts moderate binding management.
568 * Note: WebAPKs and non WebAPKs share the same moderate binding pool, so th e size of the
569 * shared moderate binding pool is always set based on the number of sandbox es processes
570 * used by Chrome.
516 * @param context Android's context. 571 * @param context Android's context.
517 * @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate 572 * @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate
518 * binding to a render process when it is created and remove the moderate bi nding when Chrome is 573 * binding to a render process when it is created and remove the moderate bi nding when Chrome is
519 * sent to the background. 574 * sent to the background.
520 */ 575 */
521 public static void startModerateBindingManagement( 576 public static void startModerateBindingManagement(
522 Context context, boolean moderateBindingTillBackgrounded) { 577 Context context, boolean moderateBindingTillBackgrounded) {
523 sBindingManager.startModerateBindingManagement( 578 sBindingManager.startModerateBindingManagement(context,
524 context, getNumberOfServices(context, true), moderateBindingTill Backgrounded); 579 getNumberOfServices(context, true, context.getPackageName()),
580 moderateBindingTillBackgrounded);
525 } 581 }
526 582
527 /** 583 /**
528 * Called when the embedding application is brought to foreground. 584 * Called when the embedding application is brought to foreground.
529 */ 585 */
530 public static void onBroughtToForeground() { 586 public static void onBroughtToForeground() {
531 sApplicationInForeground = true; 587 sApplicationInForeground = true;
532 sBindingManager.onBroughtToForeground(); 588 sBindingManager.onBroughtToForeground();
533 } 589 }
534 590
535 /** 591 /**
536 * Returns whether the application is currently in the foreground. 592 * Returns whether the application is currently in the foreground.
537 */ 593 */
538 static boolean isApplicationInForeground() { 594 static boolean isApplicationInForeground() {
539 return sApplicationInForeground; 595 return sApplicationInForeground;
540 } 596 }
541 597
542 /** 598 /**
543 * Should be called early in startup so the work needed to spawn the child p rocess can be done 599 * Should be called early in startup so the work needed to spawn the child p rocess can be done
544 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is 600 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is
545 * created in sandboxed child process. 601 * created in sandboxed child process.
546 * @param context the application context used for the connection. 602 * @param context the application context used for the connection.
547 * @param params child process creation params.
548 */ 603 */
549 public static void warmUp(Context context, ChildProcessCreationParams params ) { 604 public static void warmUp(Context context) {
550 ChildProcessCreationParams.set(params);
551 synchronized (ChildProcessLauncher.class) { 605 synchronized (ChildProcessLauncher.class) {
552 assert !ThreadUtils.runningOnUiThread(); 606 assert !ThreadUtils.runningOnUiThread();
553 if (sSpareSandboxedConnection == null) { 607 if (sSpareSandboxedConnection == null) {
554 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false); 608 ChildProcessCreationParams params = ChildProcessCreationParams.g et();
609 if (params != null) {
610 params = params.copy();
611 }
612 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false,
613 params);
555 } 614 }
556 } 615 }
557 } 616 }
558 617
559 @CalledByNative 618 @CalledByNative
560 private static FileDescriptorInfo makeFdInfo( 619 private static FileDescriptorInfo makeFdInfo(
561 int id, int fd, boolean autoClose, long offset, long size) { 620 int id, int fd, boolean autoClose, long offset, long size) {
562 ParcelFileDescriptor pFd; 621 ParcelFileDescriptor pFd;
563 if (autoClose) { 622 if (autoClose) {
564 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. 623 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor.
(...skipping 22 matching lines...) Expand all
587 */ 646 */
588 @CalledByNative 647 @CalledByNative
589 private static void start(Context context, final String[] commandLine, int c hildProcessId, 648 private static void start(Context context, final String[] commandLine, int c hildProcessId,
590 FileDescriptorInfo[] filesToBeMapped, long clientContext) { 649 FileDescriptorInfo[] filesToBeMapped, long clientContext) {
591 assert clientContext != 0; 650 assert clientContext != 0;
592 651
593 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; 652 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS;
594 boolean inSandbox = true; 653 boolean inSandbox = true;
595 String processType = 654 String processType =
596 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); 655 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE);
656 ChildProcessCreationParams params = null;
597 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { 657 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
598 callbackType = CALLBACK_FOR_RENDERER_PROCESS; 658 callbackType = CALLBACK_FOR_RENDERER_PROCESS;
659 if (ChildProcessCreationParams.get() != null) {
660 params = ChildProcessCreationParams.get().copy();
661 }
599 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { 662 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
600 callbackType = CALLBACK_FOR_GPU_PROCESS; 663 callbackType = CALLBACK_FOR_GPU_PROCESS;
601 inSandbox = false; 664 inSandbox = false;
602 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) { 665 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) {
603 // We only support sandboxed right now. 666 // We only support sandboxed right now.
604 callbackType = CALLBACK_FOR_UTILITY_PROCESS; 667 callbackType = CALLBACK_FOR_UTILITY_PROCESS;
605 } else { 668 } else {
606 assert false; 669 assert false;
607 } 670 }
pkotwicz 2016/06/02 02:16:30 michaelbai@ would it be acceptable to set {@link p
michaelbai 2016/06/03 17:38:46 It is fine.
Xi Han 2016/06/03 18:03:36 Since I already added these checks, will leave the
608 671
609 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, 672 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext,
610 callbackType, inSandbox); 673 callbackType, inSandbox, params);
611 } 674 }
612 675
613 /** 676 /**
614 * Spawns a background download process if it hasn't been started. The downl oad process will 677 * Spawns a background download process if it hasn't been started. The downl oad process will
615 * manage its own lifecyle and can outlive chrome. 678 * manage its own lifecyle and can outlive chrome.
616 * 679 *
617 * @param context Context used to obtain the application context. 680 * @param context Context used to obtain the application context.
618 * @param commandLine The child process command line argv. 681 * @param commandLine The child process command line argv.
619 */ 682 */
620 @SuppressLint("NewApi") 683 @SuppressLint("NewApi")
(...skipping 22 matching lines...) Expand all
643 context.startService(intent); 706 context.startService(intent);
644 } 707 }
645 708
646 private static void startInternal( 709 private static void startInternal(
647 Context context, 710 Context context,
648 final String[] commandLine, 711 final String[] commandLine,
649 int childProcessId, 712 int childProcessId,
650 FileDescriptorInfo[] filesToBeMapped, 713 FileDescriptorInfo[] filesToBeMapped,
651 long clientContext, 714 long clientContext,
652 int callbackType, 715 int callbackType,
653 boolean inSandbox) { 716 boolean inSandbox,
717 ChildProcessCreationParams creationParams) {
654 try { 718 try {
655 TraceEvent.begin("ChildProcessLauncher.startInternal"); 719 TraceEvent.begin("ChildProcessLauncher.startInternal");
656 720
657 ChildProcessConnection allocatedConnection = null; 721 ChildProcessConnection allocatedConnection = null;
722 String packageName = creationParams != null ? creationParams.getPack ageName()
723 : context.getPackageName();
658 synchronized (ChildProcessLauncher.class) { 724 synchronized (ChildProcessLauncher.class) {
659 if (inSandbox) { 725 if (inSandbox && sSpareSandboxedConnection != null
726 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) {
660 allocatedConnection = sSpareSandboxedConnection; 727 allocatedConnection = sSpareSandboxedConnection;
661 sSpareSandboxedConnection = null; 728 sSpareSandboxedConnection = null;
662 } 729 }
663 } 730 }
664 if (allocatedConnection == null) { 731 if (allocatedConnection == null) {
665 boolean alwaysInForeground = false; 732 boolean alwaysInForeground = false;
666 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; 733 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
667 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { 734 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(
735 context, packageName, inSandbox);
736 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
668 allocatedConnection = allocateBoundConnection( 737 allocatedConnection = allocateBoundConnection(
669 context, commandLine, inSandbox, alwaysInForeground) ; 738 context, commandLine, inSandbox, alwaysInForeground, creationParams);
670 if (allocatedConnection == null) { 739 if (allocatedConnection == null) {
671 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); 740 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
672 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(co ntext, commandLine, 741 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine,
673 childProcessId, filesToBeMapped, clientContext, 742 childProcessId, filesToBeMapped, clientContext,
674 callbackType, inSandbox)); 743 callbackType, inSandbox, creationParams));
675 return; 744 return;
676 } 745 }
677 } 746 }
678 } 747 }
679 748
680 Log.d(TAG, "Setting up connection to process: slot=%d", 749 Log.d(TAG, "Setting up connection to process: slot=%d",
681 allocatedConnection.getServiceNumber()); 750 allocatedConnection.getServiceNumber());
682 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId, 751 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId,
683 filesToBeMapped, callbackType, clientContext); 752 filesToBeMapped, callbackType, clientContext);
684 } finally { 753 } finally {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 } 910 }
842 911
843 static void logPidWarning(int pid, String message) { 912 static void logPidWarning(int pid, String message) {
844 // This class is effectively a no-op in single process mode, so don't lo g warnings there. 913 // This class is effectively a no-op in single process mode, so don't lo g warnings there.
845 if (pid > 0 && !nativeIsSingleProcess()) { 914 if (pid > 0 && !nativeIsSingleProcess()) {
846 Log.w(TAG, "%s, pid=%d", message, pid); 915 Log.w(TAG, "%s, pid=%d", message, pid);
847 } 916 }
848 } 917 }
849 918
850 @VisibleForTesting 919 @VisibleForTesting
851 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext) { 920 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext,
852 return allocateBoundConnection(context, null, true, false); 921 ChildProcessCreationParams creationParams) {
922 return allocateBoundConnection(context, null, true, false, creationParam s);
853 } 923 }
854 924
855 /** 925 /**
856 * Queue up a spawn requests for testing. 926 * Queue up a spawn requests for testing.
857 */ 927 */
858 @VisibleForTesting 928 @VisibleForTesting
859 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine) { 929 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine,
860 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { 930 ChildProcessCreationParams creationParams, boolean inSandbox) {
861 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comma ndLine, 1, 931 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context,
862 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true)); 932 creationParams.getPackageName(), inSandbox);
933 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
934 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1,
935 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true,
936 creationParams));
863 } 937 }
864 } 938 }
865 939
866 /** @return the count of sandboxed connections managed by the allocator */ 940 /**
941 * @return the number of sandboxed connections of given {@link packageName} managed by the
942 * allocator.
943 */
867 @VisibleForTesting 944 @VisibleForTesting
868 static int allocatedConnectionsCountForTesting(Context context) { 945 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) {
869 initConnectionAllocatorsIfNecessary(context); 946 initConnectionAllocatorsIfNecessary(context, true, packageName);
870 return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTe sting(); 947 return sSandboxedChildConnectionAllocatorMap.get(packageName)
948 .allocatedConnectionsCountForTesting();
871 } 949 }
872 950
873 /** @return the count of services set up and working */ 951 /** @return the count of services set up and working */
874 @VisibleForTesting 952 @VisibleForTesting
875 static int connectedServicesCountForTesting() { 953 static int connectedServicesCountForTesting() {
876 return sServiceMap.size(); 954 return sServiceMap.size();
877 } 955 }
878 956
879 /** @return the count of pending spawns in the queue */ 957 /**
958 * @param context The context.
959 * @param packageName The package name of the {@link ChildProcessAlocator}.
960 * @param inSandbox Whether the connection is sandboxed.
961 * @return the count of pending spawns in the queue.
962 */
880 @VisibleForTesting 963 @VisibleForTesting
881 static int pendingSpawnsCountForTesting() { 964 static int pendingSpawnsCountForTesting(Context context, String packageName,
882 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { 965 boolean inSandbox) {
883 return sPendingSpawnQueue.sizeLocked(); 966 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, pack ageName, inSandbox);
967 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
968 return pendingSpawnQueue.sizeLocked();
884 } 969 }
885 } 970 }
886 971
887 /** 972 /**
888 * Kills the child process for testing. 973 * Kills the child process for testing.
889 * @return true iff the process was killed as expected 974 * @return true iff the process was killed as expected
890 */ 975 */
891 @VisibleForTesting 976 @VisibleForTesting
892 public static boolean crashProcessForTesting(int pid) { 977 public static boolean crashProcessForTesting(int pid) {
893 if (sServiceMap.get(pid) == null) return false; 978 if (sServiceMap.get(pid) == null) return false;
894 979
895 try { 980 try {
896 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); 981 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting();
897 } catch (RemoteException ex) { 982 } catch (RemoteException ex) {
898 return false; 983 return false;
899 } 984 }
900 985
901 return true; 986 return true;
902 } 987 }
903 988
904 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); 989 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid);
905 private static native void nativeEstablishSurfacePeer( 990 private static native void nativeEstablishSurfacePeer(
906 int pid, Surface surface, int primaryID, int secondaryID); 991 int pid, Surface surface, int primaryID, int secondaryID);
907 private static native boolean nativeIsSingleProcess(); 992 private static native boolean nativeIsSingleProcess();
908 } 993 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698