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

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

Issue 2792093002: Clean-up in ChildProcessLauncher. (Closed)
Patch Set: Fix build. Created 3 years, 8 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
« no previous file with comments | « no previous file | content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.content.ComponentName; 7 import android.content.ComponentName;
8 import android.content.Context; 8 import android.content.Context;
9 import android.content.pm.ApplicationInfo; 9 import android.content.pm.ApplicationInfo;
10 import android.content.pm.PackageManager; 10 import android.content.pm.PackageManager;
(...skipping 25 matching lines...) Expand all
36 /** 36 /**
37 * This class provides the method to start/stop ChildProcess called by native. 37 * This class provides the method to start/stop ChildProcess called by native.
38 * 38 *
39 * Note about threading. The threading here is complicated and not well document ed. 39 * Note about threading. The threading here is complicated and not well document ed.
40 * Code can run on these threads: UI, Launcher, async thread pool, binder, and o ne-off 40 * Code can run on these threads: UI, Launcher, async thread pool, binder, and o ne-off
41 * background threads. 41 * background threads.
42 */ 42 */
43 public class ChildProcessLauncher { 43 public class ChildProcessLauncher {
44 private static final String TAG = "ChildProcLauncher"; 44 private static final String TAG = "ChildProcLauncher";
45 45
46 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0;
47 static final int CALLBACK_FOR_GPU_PROCESS = 1;
48 static final int CALLBACK_FOR_RENDERER_PROCESS = 2;
49 static final int CALLBACK_FOR_UTILITY_PROCESS = 3;
50
51 private static class ChildConnectionAllocator { 46 private static class ChildConnectionAllocator {
52 // Connections to services. Indices of the array correspond to the servi ce numbers. 47 // Connections to services. Indices of the array correspond to the servi ce numbers.
53 private final ChildProcessConnection[] mChildProcessConnections; 48 private final ChildProcessConnection[] mChildProcessConnections;
54 49
55 // The list of free (not bound) service indices. 50 // The list of free (not bound) service indices.
56 // SHOULD BE ACCESSED WITH mConnectionLock. 51 // SHOULD BE ACCESSED WITH mConnectionLock.
57 private final ArrayList<Integer> mFreeConnectionIndices; 52 private final ArrayList<Integer> mFreeConnectionIndices;
58 private final Object mConnectionLock = new Object(); 53 private final Object mConnectionLock = new Object();
59 54
60 private final String mChildClassName; 55 private final String mChildClassName;
(...skipping 10 matching lines...) Expand all
71 for (int i = 0; i < numChildServices; i++) { 66 for (int i = 0; i < numChildServices; i++) {
72 mFreeConnectionIndices.add(i); 67 mFreeConnectionIndices.add(i);
73 } 68 }
74 mChildClassName = serviceClassName; 69 mChildClassName = serviceClassName;
75 mInSandbox = inSandbox; 70 mInSandbox = inSandbox;
76 } 71 }
77 72
78 // Allocate or enqueue. If there are no free slots, return null and enqu eue the spawn data. 73 // Allocate or enqueue. If there are no free slots, return null and enqu eue the spawn data.
79 public ChildProcessConnection allocate(SpawnData spawnData, 74 public ChildProcessConnection allocate(SpawnData spawnData,
80 ChildProcessConnection.DeathCallback deathCallback, 75 ChildProcessConnection.DeathCallback deathCallback,
81 Bundle childProcessCommonParameters, boolean alwaysInForeground) { 76 Bundle childProcessCommonParameters) {
82 assert spawnData.inSandbox() == mInSandbox; 77 assert spawnData.isInSandbox() == mInSandbox;
83 synchronized (mConnectionLock) { 78 synchronized (mConnectionLock) {
84 if (mFreeConnectionIndices.isEmpty()) { 79 if (mFreeConnectionIndices.isEmpty()) {
85 Log.d(TAG, "Ran out of services to allocate."); 80 Log.d(TAG, "Ran out of services to allocate.");
86 if (!spawnData.forWarmUp()) { 81 if (!spawnData.isForWarmUp()) {
87 mPendingSpawnQueue.add(spawnData); 82 mPendingSpawnQueue.add(spawnData);
88 } 83 }
89 return null; 84 return null;
90 } 85 }
91 int slot = mFreeConnectionIndices.remove(0); 86 int slot = mFreeConnectionIndices.remove(0);
92 assert mChildProcessConnections[slot] == null; 87 assert mChildProcessConnections[slot] == null;
93 mChildProcessConnections[slot] = 88 mChildProcessConnections[slot] =
94 new ChildProcessConnectionImpl(spawnData.context(), slot , mInSandbox, 89 new ChildProcessConnectionImpl(spawnData.getContext(), s lot, mInSandbox,
95 deathCallback, mChildClassName, childProcessComm onParameters, 90 deathCallback, mChildClassName, childProcessComm onParameters,
96 alwaysInForeground, spawnData.getCreationParams( )); 91 spawnData.isAlwaysInForeground(), spawnData.getC reationParams());
97 Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mInSandbox, 92 Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mInSandbox,
98 slot); 93 slot);
99 return mChildProcessConnections[slot]; 94 return mChildProcessConnections[slot];
100 } 95 }
101 } 96 }
102 97
103 // Also return the first SpawnData in the pending queue, if any. 98 // Also return the first SpawnData in the pending queue, if any.
104 public SpawnData free(ChildProcessConnection connection) { 99 public SpawnData free(ChildProcessConnection connection) {
105 synchronized (mConnectionLock) { 100 synchronized (mConnectionLock) {
106 int slot = connection.getServiceNumber(); 101 int slot = connection.getServiceNumber();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 } 148 }
154 } 149 }
155 150
156 private static class SpawnData { 151 private static class SpawnData {
157 private final boolean mForWarmup; // Do not queue up if failed. 152 private final boolean mForWarmup; // Do not queue up if failed.
158 private final Context mContext; 153 private final Context mContext;
159 private final String[] mCommandLine; 154 private final String[] mCommandLine;
160 private final int mChildProcessId; 155 private final int mChildProcessId;
161 private final FileDescriptorInfo[] mFilesToBeMapped; 156 private final FileDescriptorInfo[] mFilesToBeMapped;
162 private final LaunchCallback mLaunchCallback; 157 private final LaunchCallback mLaunchCallback;
163 private final int mCallbackType; 158 private final IBinder mChildProcessCallback;
164 private final boolean mInSandbox; 159 private final boolean mInSandbox;
160 private final boolean mAlwaysInForeground;
165 private final ChildProcessCreationParams mCreationParams; 161 private final ChildProcessCreationParams mCreationParams;
166 162
167 private SpawnData(boolean forWarmUp, Context context, String[] commandLi ne, 163 private SpawnData(boolean forWarmUp, Context context, String[] commandLi ne,
168 int childProcessId, FileDescriptorInfo[] filesToBeMapped, 164 int childProcessId, FileDescriptorInfo[] filesToBeMapped,
169 LaunchCallback launchCallback, int callbackType, boolean inSandb ox, 165 LaunchCallback launchCallback, IBinder childProcessCallback, boo lean inSandbox,
170 ChildProcessCreationParams creationParams) { 166 boolean alwaysInForeground, ChildProcessCreationParams creationP arams) {
171 mForWarmup = forWarmUp; 167 mForWarmup = forWarmUp;
172 mContext = context; 168 mContext = context;
173 mCommandLine = commandLine; 169 mCommandLine = commandLine;
174 mChildProcessId = childProcessId; 170 mChildProcessId = childProcessId;
175 mFilesToBeMapped = filesToBeMapped; 171 mFilesToBeMapped = filesToBeMapped;
176 mLaunchCallback = launchCallback; 172 mLaunchCallback = launchCallback;
177 mCallbackType = callbackType; 173 mChildProcessCallback = childProcessCallback;
178 mInSandbox = inSandbox; 174 mInSandbox = inSandbox;
175 mAlwaysInForeground = alwaysInForeground;
179 mCreationParams = creationParams; 176 mCreationParams = creationParams;
180 } 177 }
181 178
182 private boolean forWarmUp() { 179 private boolean isForWarmUp() {
183 return mForWarmup; 180 return mForWarmup;
184 } 181 }
185 182 private Context getContext() {
186 private Context context() {
187 return mContext; 183 return mContext;
188 } 184 }
189 private String[] commandLine() { 185 private String[] getCommandLine() {
190 return mCommandLine; 186 return mCommandLine;
191 } 187 }
192 private int childProcessId() { 188 private int getChildProcessId() {
193 return mChildProcessId; 189 return mChildProcessId;
194 } 190 }
195 private FileDescriptorInfo[] filesToBeMapped() { 191 private FileDescriptorInfo[] getFilesToBeMapped() {
196 return mFilesToBeMapped; 192 return mFilesToBeMapped;
197 } 193 }
198 private LaunchCallback launchCallback() { 194 private LaunchCallback getLaunchCallback() {
199 return mLaunchCallback; 195 return mLaunchCallback;
200 } 196 }
201 private int callbackType() { 197 private IBinder getChildProcessCallback() {
202 return mCallbackType; 198 return mChildProcessCallback;
203 } 199 }
204 private boolean inSandbox() { 200 private boolean isInSandbox() {
205 return mInSandbox; 201 return mInSandbox;
206 } 202 }
203 private boolean isAlwaysInForeground() {
204 return mAlwaysInForeground;
205 }
207 private ChildProcessCreationParams getCreationParams() { 206 private ChildProcessCreationParams getCreationParams() {
208 return mCreationParams; 207 return mCreationParams;
209 } 208 }
210 } 209 }
211 210
212 /** 211 /**
213 * Implemented by ChildProcessLauncherHelper. 212 * Implemented by ChildProcessLauncherHelper.
214 */ 213 */
215 public interface LaunchCallback { void onChildProcessStarted(int pid); } 214 public interface LaunchCallback { void onChildProcessStarted(int pid); }
216 215
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 return sSandboxedChildConnectionAllocatorMap.get(packageName); 343 return sSandboxedChildConnectionAllocatorMap.get(packageName);
345 } 344 }
346 345
347 private static ChildConnectionAllocator getAllocatorForTesting( 346 private static ChildConnectionAllocator getAllocatorForTesting(
348 Context context, String packageName, boolean inSandbox) { 347 Context context, String packageName, boolean inSandbox) {
349 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); 348 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
350 return getConnectionAllocator(packageName, inSandbox); 349 return getConnectionAllocator(packageName, inSandbox);
351 } 350 }
352 351
353 private static ChildProcessConnection allocateConnection( 352 private static ChildProcessConnection allocateConnection(
354 SpawnData spawnData, Bundle childProcessCommonParams, boolean always InForeground) { 353 SpawnData spawnData, Bundle childProcessCommonParams) {
355 ChildProcessConnection.DeathCallback deathCallback = 354 ChildProcessConnection.DeathCallback deathCallback =
356 new ChildProcessConnection.DeathCallback() { 355 new ChildProcessConnection.DeathCallback() {
357 @Override 356 @Override
358 public void onChildProcessDied(ChildProcessConnection connec tion) { 357 public void onChildProcessDied(ChildProcessConnection connec tion) {
359 if (connection.getPid() != 0) { 358 if (connection.getPid() != 0) {
360 stop(connection.getPid()); 359 stop(connection.getPid());
361 } else { 360 } else {
362 freeConnection(connection); 361 freeConnection(connection);
363 } 362 }
364 } 363 }
365 }; 364 };
366 final ChildProcessCreationParams creationParams = spawnData.getCreationP arams(); 365 final ChildProcessCreationParams creationParams = spawnData.getCreationP arams();
367 final Context context = spawnData.context(); 366 final Context context = spawnData.getContext();
368 final boolean inSandbox = spawnData.inSandbox(); 367 final boolean inSandbox = spawnData.isInSandbox();
369 String packageName = 368 String packageName =
370 creationParams != null ? creationParams.getPackageName() : conte xt.getPackageName(); 369 creationParams != null ? creationParams.getPackageName() : conte xt.getPackageName();
371 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); 370 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName);
372 return getConnectionAllocator(packageName, inSandbox) 371 return getConnectionAllocator(packageName, inSandbox)
373 .allocate(spawnData, deathCallback, childProcessCommonParams, al waysInForeground); 372 .allocate(spawnData, deathCallback, childProcessCommonParams);
374 } 373 }
375 374
376 private static boolean sLinkerInitialized; 375 private static boolean sLinkerInitialized;
377 private static long sLinkerLoadAddress; 376 private static long sLinkerLoadAddress;
378 377
379 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { 378 private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
380 if (!sLinkerInitialized) { 379 if (!sLinkerInitialized) {
381 if (Linker.isUsed()) { 380 if (Linker.isUsed()) {
382 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); 381 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
383 if (sLinkerLoadAddress == 0) { 382 if (sLinkerLoadAddress == 0) {
(...skipping 12 matching lines...) Expand all
396 return new ChromiumLinkerParams(sLinkerLoadAddress, 395 return new ChromiumLinkerParams(sLinkerLoadAddress,
397 waitForSharedRelros, 396 waitForSharedRelros,
398 linker.getTestRunnerClassNameForTest ing(), 397 linker.getTestRunnerClassNameForTest ing(),
399 linker.getImplementationForTesting() ); 398 linker.getImplementationForTesting() );
400 } else { 399 } else {
401 return new ChromiumLinkerParams(sLinkerLoadAddress, 400 return new ChromiumLinkerParams(sLinkerLoadAddress,
402 waitForSharedRelros); 401 waitForSharedRelros);
403 } 402 }
404 } 403 }
405 404
406 private static ChildProcessConnection allocateBoundConnection(SpawnData spaw nData, 405 private static ChildProcessConnection allocateBoundConnection(
407 boolean alwaysInForeground, ChildProcessConnection.StartCallback sta rtCallback) { 406 SpawnData spawnData, ChildProcessConnection.StartCallback startCallb ack) {
408 final Context context = spawnData.context(); 407 final Context context = spawnData.getContext();
409 final boolean inSandbox = spawnData.inSandbox(); 408 final boolean inSandbox = spawnData.isInSandbox();
410 final ChildProcessCreationParams creationParams = spawnData.getCreationP arams(); 409 final ChildProcessCreationParams creationParams = spawnData.getCreationP arams();
411 Bundle commonParams = new Bundle(); 410 Bundle commonParams = new Bundle();
412 commonParams.putParcelable( 411 commonParams.putParcelable(
413 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew Connection()); 412 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew Connection());
414 ChildProcessConnection connection = 413 ChildProcessConnection connection = allocateConnection(spawnData, common Params);
415 allocateConnection(spawnData, commonParams, alwaysInForeground);
416 if (connection != null) { 414 if (connection != null) {
417 connection.start(startCallback); 415 connection.start(startCallback);
418 416
419 String packageName = creationParams != null ? creationParams.getPack ageName() 417 String packageName = creationParams != null ? creationParams.getPack ageName()
420 : context.getPackageName (); 418 : context.getPackageName ();
421 if (inSandbox 419 if (inSandbox
422 && !getConnectionAllocator(packageName, inSandbox) 420 && !getConnectionAllocator(packageName, inSandbox)
423 .isFreeConnectionAvailable()) { 421 .isFreeConnectionAvailable()) {
424 // Proactively releases all the moderate bindings once all the s andboxed services 422 // Proactively releases all the moderate bindings once all the s andboxed services
425 // are allocated, which will be very likely to have some of them killed by OOM 423 // are allocated, which will be very likely to have some of them killed by OOM
(...skipping 18 matching lines...) Expand all
444 // variables are set when we don't expect them to). 442 // variables are set when we don't expect them to).
445 final ChildProcessConnection conn = connection; 443 final ChildProcessConnection conn = connection;
446 ThreadUtils.postOnUiThreadDelayed(new Runnable() { 444 ThreadUtils.postOnUiThreadDelayed(new Runnable() {
447 @Override 445 @Override
448 public void run() { 446 public void run() {
449 final SpawnData pendingSpawn = freeConnectionAndDequeuePending(c onn); 447 final SpawnData pendingSpawn = freeConnectionAndDequeuePending(c onn);
450 if (pendingSpawn != null) { 448 if (pendingSpawn != null) {
451 LauncherThread.post(new Runnable() { 449 LauncherThread.post(new Runnable() {
452 @Override 450 @Override
453 public void run() { 451 public void run() {
454 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), 452 startInternal(pendingSpawn.getContext(), pendingSpaw n.getCommandLine(),
455 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), 453 pendingSpawn.getChildProcessId(),
456 pendingSpawn.launchCallback(), pendingSpawn. callbackType(), 454 pendingSpawn.getFilesToBeMapped(),
457 pendingSpawn.inSandbox(), pendingSpawn.getCr eationParams()); 455 pendingSpawn.getLaunchCallback(),
456 pendingSpawn.getChildProcessCallback(),
457 pendingSpawn.isInSandbox(), pendingSpawn.isA lwaysInForeground(),
458 pendingSpawn.getCreationParams());
458 } 459 }
459 }); 460 });
460 } 461 }
461 } 462 }
462 }, FREE_CONNECTION_DELAY_MILLIS); 463 }, FREE_CONNECTION_DELAY_MILLIS);
463 } 464 }
464 465
465 private static SpawnData freeConnectionAndDequeuePending(ChildProcessConnect ion conn) { 466 private static SpawnData freeConnectionAndDequeuePending(ChildProcessConnect ion conn) {
466 ChildConnectionAllocator allocator = getConnectionAllocator( 467 ChildConnectionAllocator allocator = getConnectionAllocator(
467 conn.getPackageName(), conn.isInSandbox()); 468 conn.getPackageName(), conn.isInSandbox());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 @Override 576 @Override
576 public void onChildStartFailed() { 577 public void onChildStartFailed() {
577 Log.e(TAG, "Failed to warm up the spare sandbox service"); 578 Log.e(TAG, "Failed to warm up the spare sandbox service");
578 synchronized (sSpareConnectionLock) { 579 synchronized (sSpareConnectionLock) {
579 sSpareSandboxedConnection = null; 580 sSpareSandboxedConnection = null;
580 sSpareConnectionStarting = false; 581 sSpareConnectionStarting = false;
581 sSpareConnectionLock.notify(); 582 sSpareConnectionLock.notify();
582 } 583 }
583 } 584 }
584 }; 585 };
585 SpawnData spawnData = new SpawnData(true /* forWarmUp*/, context , 586 SpawnData spawnData =
586 null /* commandLine */, -1 /* child process id */, 587 new SpawnData(true /* forWarmUp*/, context, null /* comm andLine */,
587 null /* filesToBeMapped */, null /* launchCallback */, 588 -1 /* child process id */, null /* filesToBeMapp ed */,
588 CALLBACK_FOR_RENDERER_PROCESS, true /* inSandbox */, par ams); 589 null /* launchCallback */, null /* child process callback */,
589 sSpareSandboxedConnection = allocateBoundConnection( 590 true /* inSandbox */, false /* alwaysInForegroun d */, params);
590 spawnData, false /* alwaysInForeground */, startCallback ); 591 sSpareSandboxedConnection = allocateBoundConnection(spawnData, s tartCallback);
591 } 592 }
592 } 593 }
593 } 594 }
594 595
595 /** 596 /**
596 * Spawns and connects to a child process. May be called on any thread. It w ill not block, but 597 * Spawns and connects to a child process. May be called on any thread. It w ill not block, but
597 * will instead callback to {@link #nativeOnChildProcessStarted} when the co nnection is 598 * will instead callback to {@link #nativeOnChildProcessStarted} when the co nnection is
598 * established. Note this callback will not necessarily be from the same thr ead (currently it 599 * established. Note this callback will not necessarily be from the same thr ead (currently it
599 * always comes from the main thread). 600 * always comes from the main thread).
600 * 601 *
601 * @param context Context used to obtain the application context. 602 * @param context Context used to obtain the application context.
602 * @param paramId Key used to retrieve ChildProcessCreationParams. 603 * @param paramId Key used to retrieve ChildProcessCreationParams.
603 * @param commandLine The child process command line argv. 604 * @param commandLine The child process command line argv.
604 * @param filesToBeMapped File IDs, FDs, offsets, and lengths to pass throug h. 605 * @param filesToBeMapped File IDs, FDs, offsets, and lengths to pass throug h.
605 */ 606 */
606 // TODO(boliu): All tests should use this over startForTesting. 607 // TODO(boliu): All tests should use this over startForTesting.
607 static void start(Context context, int paramId, final String[] commandLine, int childProcessId, 608 static void start(Context context, int paramId, final String[] commandLine, int childProcessId,
608 FileDescriptorInfo[] filesToBeMapped, LaunchCallback launchCallback) { 609 FileDescriptorInfo[] filesToBeMapped, LaunchCallback launchCallback) {
609 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; 610 IBinder childProcessCallback = null;
610 boolean inSandbox = true; 611 boolean inSandbox = true;
612 boolean alwaysInForeground = false;
611 String processType = 613 String processType =
612 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); 614 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE);
613 ChildProcessCreationParams params = ChildProcessCreationParams.get(param Id); 615 ChildProcessCreationParams params = ChildProcessCreationParams.get(param Id);
614 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null) { 616 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null) {
615 throw new RuntimeException("CreationParams id " + paramId + " not fo und"); 617 throw new RuntimeException("CreationParams id " + paramId + " not fo und");
616 } 618 }
617 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { 619 if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
618 callbackType = CALLBACK_FOR_RENDERER_PROCESS;
619 } else {
620 if (params != null && !params.getPackageName().equals(context.getPac kageName())) { 620 if (params != null && !params.getPackageName().equals(context.getPac kageName())) {
621 // WebViews and WebAPKs have renderer processes running in their applications. 621 // WebViews and WebAPKs have renderer processes running in their applications.
622 // When launching these renderer processes, {@link ChildProcessC onnectionImpl} 622 // When launching these renderer processes, {@link ChildProcessC onnectionImpl}
623 // requires the package name of the application which holds the renderer process. 623 // requires the package name of the application which holds the renderer process.
624 // Therefore, the package name in ChildProcessCreationParams cou ld be the package 624 // Therefore, the package name in ChildProcessCreationParams cou ld be the package
625 // name of WebViews, WebAPKs, or Chrome, depending on the host a pplication. 625 // name of WebViews, WebAPKs, or Chrome, depending on the host a pplication.
626 // Except renderer process, all other child processes should use Chrome's package 626 // Except renderer process, all other child processes should use Chrome's package
627 // name. In WebAPK, ChildProcessCreationParams are initialized w ith WebAPK's 627 // name. In WebAPK, ChildProcessCreationParams are initialized w ith WebAPK's
628 // package name. Make a copy of the WebAPK's params, but replace the package with 628 // package name. Make a copy of the WebAPK's params, but replace the package with
629 // Chrome's package to use when initializing a non-renderer proc esses. 629 // Chrome's package to use when initializing a non-renderer proc esses.
630 // TODO(boliu): Should fold into |paramId|. Investigate why this is needed. 630 // TODO(boliu): Should fold into |paramId|. Investigate why this is needed.
631 params = new ChildProcessCreationParams(context.getPackageName() , 631 params = new ChildProcessCreationParams(context.getPackageName() ,
632 params.getIsExternalService(), params.getLibraryProcessT ype()); 632 params.getIsExternalService(), params.getLibraryProcessT ype());
633 } 633 }
634 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { 634 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
635 callbackType = CALLBACK_FOR_GPU_PROCESS; 635 childProcessCallback = new GpuProcessCallback();
636 inSandbox = false; 636 inSandbox = false;
637 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType )) { 637 alwaysInForeground = true;
638 // We only support sandboxed right now.
639 callbackType = CALLBACK_FOR_UTILITY_PROCESS;
640 } else { 638 } else {
641 assert false; 639 // We only support sandboxed utility processes now.
640 assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType );
642 } 641 }
643 } 642 }
644 643
645 startInternal(context, commandLine, childProcessId, filesToBeMapped, lau nchCallback, 644 startInternal(context, commandLine, childProcessId, filesToBeMapped, lau nchCallback,
646 callbackType, inSandbox, params); 645 childProcessCallback, inSandbox, alwaysInForeground, params);
647 } 646 }
648 647
649 private static ChildProcessConnection startInternal(final Context context, 648 private static ChildProcessConnection startInternal(final Context context,
650 final String[] commandLine, final int childProcessId, 649 final String[] commandLine, final int childProcessId,
651 final FileDescriptorInfo[] filesToBeMapped, final LaunchCallback lau nchCallback, 650 final FileDescriptorInfo[] filesToBeMapped, final LaunchCallback lau nchCallback,
652 final int callbackType, final boolean inSandbox, 651 final IBinder childProcessCallback, final boolean inSandbox,
653 final ChildProcessCreationParams creationParams) { 652 final boolean alwaysInForeground, final ChildProcessCreationParams c reationParams) {
654 try { 653 try {
655 TraceEvent.begin("ChildProcessLauncher.startInternal"); 654 TraceEvent.begin("ChildProcessLauncher.startInternal");
656 655
657 ChildProcessConnection allocatedConnection = null; 656 ChildProcessConnection allocatedConnection = null;
658 String packageName = creationParams != null ? creationParams.getPack ageName() 657 String packageName = creationParams != null ? creationParams.getPack ageName()
659 : context.getPackageName(); 658 : context.getPackageName();
660 synchronized (sSpareConnectionLock) { 659 synchronized (sSpareConnectionLock) {
661 if (inSandbox && sSpareSandboxedConnection != null 660 if (inSandbox && sSpareSandboxedConnection != null
662 && sSpareSandboxedConnection.getPackageName().equals(pac kageName) 661 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)
663 // Object identity check for getDefault should be enough . The default is 662 // Object identity check for getDefault should be enough . The default is
664 // not supposed to change once set. 663 // not supposed to change once set.
665 && creationParams == ChildProcessCreationParams.getDefau lt()) { 664 && creationParams == ChildProcessCreationParams.getDefau lt()) {
boliu 2017/04/04 15:57:18 should check here that alwaysInForeground matches
Jay Civelli 2017/04/04 16:26:35 Good catch, done.
666 while (sSpareConnectionStarting) { 665 while (sSpareConnectionStarting) {
667 try { 666 try {
668 sSpareConnectionLock.wait(); 667 sSpareConnectionLock.wait();
669 } catch (InterruptedException ex) { 668 } catch (InterruptedException ex) {
670 } 669 }
671 } 670 }
672 allocatedConnection = sSpareSandboxedConnection; 671 allocatedConnection = sSpareSandboxedConnection;
673 sSpareSandboxedConnection = null; 672 sSpareSandboxedConnection = null;
674 } 673 }
675 } 674 }
676 if (allocatedConnection == null) { 675 if (allocatedConnection == null) {
677 boolean alwaysInForeground = false;
678 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
679 ChildProcessConnection.StartCallback startCallback = 676 ChildProcessConnection.StartCallback startCallback =
680 new ChildProcessConnection.StartCallback() { 677 new ChildProcessConnection.StartCallback() {
681 @Override 678 @Override
682 public void onChildStarted() {} 679 public void onChildStarted() {}
683 680
684 @Override 681 @Override
685 public void onChildStartFailed() { 682 public void onChildStartFailed() {
686 Log.e(TAG, "ChildProcessConnection.start failed, trying again"); 683 Log.e(TAG, "ChildProcessConnection.start failed, trying again");
687 LauncherThread.post(new Runnable() { 684 LauncherThread.post(new Runnable() {
688 @Override 685 @Override
689 public void run() { 686 public void run() {
690 // The child process may already be boun d to another client 687 // The child process may already be boun d to another client
691 // (this can happen if multi-process Web View is used in more 688 // (this can happen if multi-process Web View is used in more
692 // than one process), so try starting th e process again. 689 // than one process), so try starting th e process again.
693 // This connection that failed to start has not been freed, 690 // This connection that failed to start has not been freed,
694 // so a new bound connection will be all ocated. 691 // so a new bound connection will be all ocated.
695 startInternal(context, commandLine, chil dProcessId, 692 startInternal(context, commandLine, chil dProcessId,
696 filesToBeMapped, launchCallback, callbackType, 693 filesToBeMapped, launchCallback,
697 inSandbox, creationParams); 694 childProcessCallback, inSandbox, alwaysInForeground,
695 creationParams);
698 } 696 }
699 }); 697 });
700 } 698 }
701 }; 699 };
702 700
703 SpawnData spawnData = new SpawnData(false /* forWarmUp */, conte xt, commandLine, 701 SpawnData spawnData = new SpawnData(false /* forWarmUp */, conte xt, commandLine,
704 childProcessId, filesToBeMapped, launchCallback, callbac kType, inSandbox, 702 childProcessId, filesToBeMapped, launchCallback, childPr ocessCallback,
705 creationParams); 703 inSandbox, alwaysInForeground, creationParams);
706 allocatedConnection = 704 allocatedConnection = allocateBoundConnection(spawnData, startCa llback);
707 allocateBoundConnection(spawnData, alwaysInForeground, s tartCallback);
708 if (allocatedConnection == null) { 705 if (allocatedConnection == null) {
709 return null; 706 return null;
710 } 707 }
711 } 708 }
712 709
713 Log.d(TAG, "Setting up connection to process: slot=%d", 710 Log.d(TAG, "Setting up connection to process: slot=%d",
714 allocatedConnection.getServiceNumber()); 711 allocatedConnection.getServiceNumber());
715 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId, 712 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId,
716 filesToBeMapped, callbackType, launchCallback); 713 filesToBeMapped, childProcessCallback, launchCallback);
717 return allocatedConnection; 714 return allocatedConnection;
718 } finally { 715 } finally {
719 TraceEvent.end("ChildProcessLauncher.startInternal"); 716 TraceEvent.end("ChildProcessLauncher.startInternal");
720 } 717 }
721 } 718 }
722 719
723 /** 720 /**
724 * Create the common bundle to be passed to child processes. 721 * Create the common bundle to be passed to child processes.
725 * @param context Application context. 722 * @param context Application context.
726 * @param commandLine Command line params to be passed to the service. 723 * @param commandLine Command line params to be passed to the service.
727 * @param linkerParams Linker params to start the service. 724 * @param linkerParams Linker params to start the service.
728 */ 725 */
729 protected static Bundle createsServiceBundle( 726 protected static Bundle createsServiceBundle(
730 String[] commandLine, FileDescriptorInfo[] filesToBeMapped) { 727 String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
731 Bundle bundle = new Bundle(); 728 Bundle bundle = new Bundle();
732 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL ine); 729 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL ine);
733 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa pped); 730 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa pped);
734 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun t()); 731 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun t());
735 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get Mask()); 732 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get Mask());
736 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance() .getSharedRelros()); 733 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance() .getSharedRelros());
737 return bundle; 734 return bundle;
738 } 735 }
739 736
740 @VisibleForTesting 737 @VisibleForTesting
741 static void triggerConnectionSetup(final ChildProcessConnection connection, 738 static void triggerConnectionSetup(final ChildProcessConnection connection,
742 String[] commandLine, int childProcessId, FileDescriptorInfo[] files ToBeMapped, 739 String[] commandLine, int childProcessId, FileDescriptorInfo[] files ToBeMapped,
743 final int callbackType, final LaunchCallback launchCallback) { 740 final IBinder childProcessCallback, final LaunchCallback launchCallb ack) {
744 ChildProcessConnection.ConnectionCallback connectionCallback = 741 ChildProcessConnection.ConnectionCallback connectionCallback =
745 new ChildProcessConnection.ConnectionCallback() { 742 new ChildProcessConnection.ConnectionCallback() {
746 @Override 743 @Override
747 public void onConnected(int pid) { 744 public void onConnected(int pid) {
748 Log.d(TAG, "on connect callback, pid=%d callbackType=%d" , pid, 745 Log.d(TAG, "on connect callback, pid=%d", pid);
749 callbackType);
750 if (pid != NULL_PROCESS_HANDLE) { 746 if (pid != NULL_PROCESS_HANDLE) {
751 sBindingManager.addNewConnection(pid, connection); 747 sBindingManager.addNewConnection(pid, connection);
752 sServiceMap.put(pid, connection); 748 sServiceMap.put(pid, connection);
753 } 749 }
754 // If the connection fails and pid == 0, the Java-side c leanup was already 750 // If the connection fails and pid == 0, the Java-side c leanup was already
755 // handled by DeathCallback. We still have to call back to native for 751 // handled by DeathCallback. We still have to call back to native for
756 // cleanup there. 752 // cleanup there.
757 if (launchCallback != null) { // Will be null in Java in strumentation tests. 753 if (launchCallback != null) { // Will be null in Java in strumentation tests.
758 launchCallback.onChildProcessStarted(pid); 754 launchCallback.onChildProcessStarted(pid);
759 } 755 }
760 } 756 }
761 }; 757 };
762 758
763 assert callbackType != CALLBACK_FOR_UNKNOWN_PROCESS; 759 connection.setupConnection(
764 connection.setupConnection(commandLine, filesToBeMapped, 760 commandLine, filesToBeMapped, childProcessCallback, connectionCa llback);
765 createCallback(childProcessId, callbackType), connectionCallback );
766 } 761 }
767 762
768 /** 763 /**
769 * Terminates a child process. This may be called from any thread. 764 * Terminates a child process. This may be called from any thread.
770 * 765 *
771 * @param pid The pid (process handle) of the service connection obtained fr om {@link #start}. 766 * @param pid The pid (process handle) of the service connection obtained fr om {@link #start}.
772 */ 767 */
773 static void stop(int pid) { 768 static void stop(int pid) {
774 Log.d(TAG, "stopping child connection: pid=%d", pid); 769 Log.d(TAG, "stopping child connection: pid=%d", pid);
775 ChildProcessConnection connection = sServiceMap.remove(pid); 770 ChildProcessConnection connection = sServiceMap.remove(pid);
776 if (connection == null) { 771 if (connection == null) {
777 // Can happen for single process. 772 // Can happen for single process.
778 return; 773 return;
779 } 774 }
780 sBindingManager.clearConnection(pid); 775 sBindingManager.clearConnection(pid);
781 connection.stop(); 776 connection.stop();
782 freeConnection(connection); 777 freeConnection(connection);
783 } 778 }
784 779
785 /**
786 * This implementation is used to receive callbacks from the remote service.
787 */
788 private static IBinder createCallback(int childProcessId, int callbackType) {
789 return callbackType == CALLBACK_FOR_GPU_PROCESS ? new GpuProcessCallback () : null;
790 }
791
792 @VisibleForTesting 780 @VisibleForTesting
793 public static ChildProcessConnection startForTesting(Context context, String [] commandLine, 781 public static ChildProcessConnection startForTesting(Context context, String [] commandLine,
794 FileDescriptorInfo[] filesToMap, ChildProcessCreationParams params) { 782 FileDescriptorInfo[] filesToMap, ChildProcessCreationParams params) {
795 return startInternal(context, commandLine, 0, filesToMap, null, 783 return startInternal(context, commandLine, 0 /* childProcessId */, files ToMap,
796 CALLBACK_FOR_RENDERER_PROCESS, true, params); 784 null /* launchCallback */, null /* childProcessCallback */, true /* inSandbox */,
785 false /* alwaysInForeground */, params);
797 } 786 }
798 787
799 @VisibleForTesting 788 @VisibleForTesting
800 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext, 789 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext,
801 ChildProcessCreationParams creationParams) { 790 ChildProcessCreationParams creationParams) {
802 return allocateBoundConnection( 791 return allocateBoundConnection(
803 new SpawnData(false /* forWarmUp */, context, null /* commandLin e */, 792 new SpawnData(false /* forWarmUp */, context, null /* commandLin e */,
804 0 /* childProcessId */, null /* filesToBeMapped */, 793 0 /* childProcessId */, null /* filesToBeMapped */,
805 null /* LaunchCallback */, CALLBACK_FOR_RENDERER_PROCESS , 794 null /* LaunchCallback */, null /* childProcessCallback */,
806 true /* inSandbox */, creationParams), 795 true /* inSandbox */, false /* alwaysInForeground */, cr eationParams),
807 false /* alwaysInForeground */, null); 796 null /* startCallback */);
808 } 797 }
809 798
810 @VisibleForTesting 799 @VisibleForTesting
811 static ChildProcessConnection allocateConnectionForTesting(Context context, 800 static ChildProcessConnection allocateConnectionForTesting(Context context,
812 ChildProcessCreationParams creationParams) { 801 ChildProcessCreationParams creationParams) {
813 Bundle commonParams = new Bundle(); 802 Bundle commonParams = new Bundle();
814 commonParams.putParcelable( 803 commonParams.putParcelable(
815 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew Connection()); 804 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew Connection());
816 return allocateConnection( 805 return allocateConnection(
817 new SpawnData(false /* forWarmUp */, context, null /* commandLin e */, 806 new SpawnData(false /* forWarmUp */, context, null /* commandLin e */,
818 0 /* childProcessId */, null /* filesToBeMapped */, 807 0 /* childProcessId */, null /* filesToBeMapped */,
819 null /* LaunchCallback */, CALLBACK_FOR_RENDERER_PROCESS , 808 null /* launchCallback */, null /* childProcessCallback */,
820 true /* inSandbox */, creationParams), 809 true /* inSandbox */, false /* alwaysInForeground */, cr eationParams),
821 commonParams, false); 810 commonParams);
822 } 811 }
823 812
824 /** 813 /**
825 * Queue up a spawn requests for testing. 814 * Queue up a spawn requests for testing.
826 */ 815 */
827 @VisibleForTesting 816 @VisibleForTesting
828 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine, 817 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine,
829 ChildProcessCreationParams creationParams, boolean inSandbox) { 818 ChildProcessCreationParams creationParams, boolean inSandbox) {
830 String packageName = creationParams != null ? creationParams.getPackageN ame() 819 String packageName = creationParams != null ? creationParams.getPackageN ame()
831 : context.getPackageName(); 820 : context.getPackageName();
832 ChildConnectionAllocator allocator = 821 ChildConnectionAllocator allocator =
833 getAllocatorForTesting(context, packageName, inSandbox); 822 getAllocatorForTesting(context, packageName, inSandbox);
834 allocator.enqueuePendingQueueForTesting(new SpawnData(false /* forWarmUp */, context, 823 allocator.enqueuePendingQueueForTesting(new SpawnData(false /* forWarmUp */, context,
835 commandLine, 1, new FileDescriptorInfo[0], null, CALLBACK_FOR_RE NDERER_PROCESS, 824 commandLine, 1 /* childProcessId */, new FileDescriptorInfo[0],
836 true, creationParams)); 825 null /* launchCallback */, null /* childProcessCallback */, true /* inSandbox */,
826 false /* alwaysInForeground */, creationParams));
837 } 827 }
838 828
839 /** 829 /**
840 * @return the number of sandboxed connections of given {@link packageName} managed by the 830 * @return the number of sandboxed connections of given {@link packageName} managed by the
841 * allocator. 831 * allocator.
842 */ 832 */
843 @VisibleForTesting 833 @VisibleForTesting
844 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) { 834 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) {
845 initConnectionAllocatorsIfNecessary(context, true, packageName); 835 initConnectionAllocatorsIfNecessary(context, true, packageName);
846 return sSandboxedChildConnectionAllocatorMap.get(packageName) 836 return sSandboxedChildConnectionAllocatorMap.get(packageName)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 875
886 try { 876 try {
887 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); 877 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting();
888 } catch (RemoteException ex) { 878 } catch (RemoteException ex) {
889 return false; 879 return false;
890 } 880 }
891 881
892 return true; 882 return true;
893 } 883 }
894 } 884 }
OLDNEW
« no previous file with comments | « no previous file | content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698