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

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

Issue 2049843004: Upstream: Renderers are running in WebAPKs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nits. 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.app.Service;
8 import android.content.Context; 9 import android.content.Context;
9 import android.content.Intent; 10 import android.content.Intent;
10 import android.content.pm.ApplicationInfo; 11 import android.content.pm.ApplicationInfo;
11 import android.content.pm.PackageManager; 12 import android.content.pm.PackageManager;
12 import android.graphics.SurfaceTexture; 13 import android.graphics.SurfaceTexture;
13 import android.os.Build; 14 import android.os.Build;
14 import android.os.Bundle; 15 import android.os.Bundle;
15 import android.os.ParcelFileDescriptor; 16 import android.os.ParcelFileDescriptor;
16 import android.os.RemoteException; 17 import android.os.RemoteException;
17 import android.text.TextUtils; 18 import android.text.TextUtils;
18 import android.util.Pair; 19 import android.util.Pair;
19 import android.view.Surface; 20 import android.view.Surface;
20 21
21 import org.chromium.base.CommandLine; 22 import org.chromium.base.CommandLine;
22 import org.chromium.base.CpuFeatures; 23 import org.chromium.base.CpuFeatures;
23 import org.chromium.base.Log; 24 import org.chromium.base.Log;
24 import org.chromium.base.ThreadUtils; 25 import org.chromium.base.ThreadUtils;
25 import org.chromium.base.TraceEvent; 26 import org.chromium.base.TraceEvent;
26 import org.chromium.base.VisibleForTesting; 27 import org.chromium.base.VisibleForTesting;
27 import org.chromium.base.annotations.CalledByNative; 28 import org.chromium.base.annotations.CalledByNative;
28 import org.chromium.base.annotations.JNINamespace; 29 import org.chromium.base.annotations.JNINamespace;
29 import org.chromium.base.library_loader.Linker; 30 import org.chromium.base.library_loader.Linker;
30 import org.chromium.content.app.ChildProcessService;
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;
(...skipping 17 matching lines...) Expand all
58 58
59 private static class ChildConnectionAllocator { 59 private static class ChildConnectionAllocator {
60 // Connections to services. Indices of the array correspond to the servi ce numbers. 60 // Connections to services. Indices of the array correspond to the servi ce numbers.
61 private final ChildProcessConnection[] mChildProcessConnections; 61 private final ChildProcessConnection[] mChildProcessConnections;
62 62
63 // The list of free (not bound) service indices. 63 // The list of free (not bound) service indices.
64 // SHOULD BE ACCESSED WITH mConnectionLock. 64 // SHOULD BE ACCESSED WITH mConnectionLock.
65 private final ArrayList<Integer> mFreeConnectionIndices; 65 private final ArrayList<Integer> mFreeConnectionIndices;
66 private final Object mConnectionLock = new Object(); 66 private final Object mConnectionLock = new Object();
67 67
68 private Class<? extends ChildProcessService> mChildClass; 68 private Class<? extends Service> mChildClass;
69 private final boolean mInSandbox; 69 private final boolean mInSandbox;
70 // Each Allocator keeps a queue for the pending spawn data. Once a conne ction is free, we 70 // Each Allocator keeps a queue for the pending spawn data. Once a conne ction is free, we
71 // dequeue the pending spawn data from the same allocator as the connect ion. 71 // dequeue the pending spawn data from the same allocator as the connect ion.
72 private final PendingSpawnQueue mPendingSpawnQueue = new PendingSpawnQue ue(); 72 private final PendingSpawnQueue mPendingSpawnQueue = new PendingSpawnQue ue();
73 73
74 public ChildConnectionAllocator(boolean inSandbox, int numChildServices) { 74 public ChildConnectionAllocator(boolean inSandbox, int numChildServices,
75 Class<? extends Service> serviceName) {
pkotwicz 2016/06/15 14:13:51 Does {@link serviceName} need to be passed into th
Xi Han 2016/06/15 17:10:40 I understand why you suggest this, but I am feelin
pkotwicz 2016/06/15 17:51:00 I agree, it is good to remove ChildConnectionAlloc
75 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices]; 76 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices];
76 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); 77 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices);
77 for (int i = 0; i < numChildServices; i++) { 78 for (int i = 0; i < numChildServices; i++) {
78 mFreeConnectionIndices.add(i); 79 mFreeConnectionIndices.add(i);
79 } 80 }
80 mChildClass = 81 if (serviceName == null) {
81 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class; 82 mChildClass = inSandbox ? SandboxedProcessService.class
83 : PrivilegedProcessService.class;
84 } else {
85 mChildClass = serviceName;
86 }
82 mInSandbox = inSandbox; 87 mInSandbox = inSandbox;
83 } 88 }
84 89
85 public ChildProcessConnection allocate( 90 public ChildProcessConnection allocate(
86 Context context, ChildProcessConnection.DeathCallback deathCallb ack, 91 Context context, ChildProcessConnection.DeathCallback deathCallb ack,
87 ChromiumLinkerParams chromiumLinkerParams, 92 ChromiumLinkerParams chromiumLinkerParams,
88 boolean alwaysInForeground, 93 boolean alwaysInForeground,
89 ChildProcessCreationParams creationParams) { 94 ChildProcessCreationParams creationParams) {
90 synchronized (mConnectionLock) { 95 synchronized (mConnectionLock) {
91 if (mFreeConnectionIndices.isEmpty()) { 96 if (mFreeConnectionIndices.isEmpty()) {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 if (numServices < 0) { 271 if (numServices < 0) {
267 throw new RuntimeException("Illegal meta data value for number o f child services"); 272 throw new RuntimeException("Illegal meta data value for number o f child services");
268 } 273 }
269 return numServices; 274 return numServices;
270 } catch (PackageManager.NameNotFoundException e) { 275 } catch (PackageManager.NameNotFoundException e) {
271 throw new RuntimeException("Could not get application info"); 276 throw new RuntimeException("Could not get application info");
272 } 277 }
273 } 278 }
274 279
275 private static void initConnectionAllocatorsIfNecessary( 280 private static void initConnectionAllocatorsIfNecessary(
276 Context context, boolean inSandbox, String packageName) { 281 Context context, boolean inSandbox, String packageName,
282 Class<? extends Service> serviceName) {
277 // TODO(mariakhomenko): Uses an Object to lock the access. 283 // TODO(mariakhomenko): Uses an Object to lock the access.
278 synchronized (ChildProcessLauncher.class) { 284 synchronized (ChildProcessLauncher.class) {
279 if (inSandbox) { 285 if (inSandbox) {
280 if (sSandboxedChildConnectionAllocatorMap == null) { 286 if (sSandboxedChildConnectionAllocatorMap == null) {
281 sSandboxedChildConnectionAllocatorMap = 287 sSandboxedChildConnectionAllocatorMap =
282 new ConcurrentHashMap<String, ChildConnectionAllocat or>(); 288 new ConcurrentHashMap<String, ChildConnectionAllocat or>();
283 } 289 }
284 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) { 290 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) {
285 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s," 291 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s,"
286 + " inSandbox = true", 292 + " inSandbox = true",
287 packageName); 293 packageName);
288 sSandboxedChildConnectionAllocatorMap.put(packageName, 294 sSandboxedChildConnectionAllocatorMap.put(packageName,
289 new ChildConnectionAllocator(true, 295 new ChildConnectionAllocator(true,
290 getNumberOfServices(context, true, packageNa me))); 296 getNumberOfServices(context, true, packageNa me), serviceName));
291 } 297 }
292 } else if (sPrivilegedChildConnectionAllocator == null) { 298 } else if (sPrivilegedChildConnectionAllocator == null) {
293 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or( 299 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or(
294 false, getNumberOfServices(context, false, packageName)) ; 300 false, getNumberOfServices(context, false, packageName), null);
295 } 301 }
296 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from 302 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from
297 // {@code sSandboxedChildConnectionAllocatorMap}. 303 // {@code sSandboxedChildConnectionAllocatorMap}.
298 } 304 }
299 } 305 }
300 306
301 /** 307 /**
302 * Note: please make sure that the Allocator has been initialized before cal ling this function. 308 * Note: please make sure that the Allocator has been initialized before cal ling this function.
303 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first . 309 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first .
304 */ 310 */
305 private static ChildConnectionAllocator getConnectionAllocator( 311 private static ChildConnectionAllocator getConnectionAllocator(
306 String packageName, boolean inSandbox) { 312 String packageName, boolean inSandbox) {
307 if (!inSandbox) { 313 if (!inSandbox) {
308 return sPrivilegedChildConnectionAllocator; 314 return sPrivilegedChildConnectionAllocator;
309 } 315 }
310 return sSandboxedChildConnectionAllocatorMap.get(packageName); 316 return sSandboxedChildConnectionAllocatorMap.get(packageName);
311 } 317 }
312 318
313 /** 319 /**
314 * Get the PendingSpawnQueue of the Allocator. Initialize the Allocator if n eeded. 320 * Get the PendingSpawnQueue of the Allocator. Initialize the Allocator if n eeded.
315 */ 321 */
316 private static PendingSpawnQueue getPendingSpawnQueue(Context context, Strin g packageName, 322 private static PendingSpawnQueue getPendingSpawnQueue(Context context, Strin g packageName,
317 boolean inSandbox) { 323 boolean inSandbox, Class<? extends Service> serviceName) {
318 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); 324 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName, ser viceName);
319 return getConnectionAllocator(packageName, inSandbox).getPendingSpawnQue ue(); 325 return getConnectionAllocator(packageName, inSandbox).getPendingSpawnQue ue();
320 } 326 }
321 327
322 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, 328 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox,
323 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d, 329 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d,
324 ChildProcessCreationParams creationParams) { 330 ChildProcessCreationParams creationParams) {
325 ChildProcessConnection.DeathCallback deathCallback = 331 ChildProcessConnection.DeathCallback deathCallback =
326 new ChildProcessConnection.DeathCallback() { 332 new ChildProcessConnection.DeathCallback() {
327 @Override 333 @Override
328 public void onChildProcessDied(ChildProcessConnection connec tion) { 334 public void onChildProcessDied(ChildProcessConnection connec tion) {
329 if (connection.getPid() != 0) { 335 if (connection.getPid() != 0) {
330 stop(connection.getPid()); 336 stop(connection.getPid());
331 } else { 337 } else {
332 freeConnection(connection); 338 freeConnection(connection);
333 } 339 }
334 } 340 }
335 }; 341 };
336 String packageName = creationParams != null ? creationParams.getPackageN ame() 342 String packageName = creationParams != null ? creationParams.getPackageN ame()
337 : context.getPackageName(); 343 : context.getPackageName();
338 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); 344 Class<? extends Service> serviceName = creationParams != null
339 return getConnectionAllocator(packageName, inSandbox) 345 ? creationParams.getServiceName() : null;
340 .allocate(context, deathCallback, chromiumLinkerParams, alwaysIn Foreground, 346 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName, ser viceName);
341 creationParams); 347 return getConnectionAllocator(packageName, inSandbox).allocate(
348 context, deathCallback, chromiumLinkerParams, alwaysInForeground ,
349 creationParams);
342 } 350 }
343 351
344 private static boolean sLinkerInitialized = false; 352 private static boolean sLinkerInitialized = false;
345 private static long sLinkerLoadAddress = 0; 353 private static long sLinkerLoadAddress = 0;
346 354
347 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { 355 private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
348 if (!sLinkerInitialized) { 356 if (!sLinkerInitialized) {
349 if (Linker.isUsed()) { 357 if (Linker.isUsed()) {
350 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); 358 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
351 if (sLinkerLoadAddress == 0) { 359 if (sLinkerLoadAddress == 0) {
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 synchronized (ChildProcessLauncher.class) { 731 synchronized (ChildProcessLauncher.class) {
724 if (inSandbox && sSpareSandboxedConnection != null 732 if (inSandbox && sSpareSandboxedConnection != null
725 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) { 733 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) {
726 allocatedConnection = sSpareSandboxedConnection; 734 allocatedConnection = sSpareSandboxedConnection;
727 sSpareSandboxedConnection = null; 735 sSpareSandboxedConnection = null;
728 } 736 }
729 } 737 }
730 if (allocatedConnection == null) { 738 if (allocatedConnection == null) {
731 boolean alwaysInForeground = false; 739 boolean alwaysInForeground = false;
732 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; 740 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
741 Class<? extends Service> serviceName = creationParams != null
742 ? creationParams.getServiceName() : null;
733 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue( 743 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(
734 context, packageName, inSandbox); 744 context, packageName, inSandbox, serviceName);
735 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { 745 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
736 allocatedConnection = allocateBoundConnection( 746 allocatedConnection = allocateBoundConnection(
737 context, commandLine, inSandbox, alwaysInForeground, creationParams); 747 context, commandLine, inSandbox, alwaysInForeground, creationParams);
738 if (allocatedConnection == null) { 748 if (allocatedConnection == null) {
739 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); 749 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
740 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine, 750 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine,
741 childProcessId, filesToBeMapped, clientContext, 751 childProcessId, filesToBeMapped, clientContext,
742 callbackType, inSandbox, creationParams)); 752 callbackType, inSandbox, creationParams));
743 return; 753 return;
744 } 754 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 ChildProcessCreationParams creationParams) { 930 ChildProcessCreationParams creationParams) {
921 return allocateBoundConnection(context, null, true, false, creationParam s); 931 return allocateBoundConnection(context, null, true, false, creationParam s);
922 } 932 }
923 933
924 /** 934 /**
925 * Queue up a spawn requests for testing. 935 * Queue up a spawn requests for testing.
926 */ 936 */
927 @VisibleForTesting 937 @VisibleForTesting
928 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine, 938 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine,
929 ChildProcessCreationParams creationParams, boolean inSandbox) { 939 ChildProcessCreationParams creationParams, boolean inSandbox) {
940 String packageName = creationParams != null ? creationParams.getPackageN ame()
941 : context.getPackageName();
942 Class<? extends Service> serviceName = creationParams != null
943 ? creationParams.getServiceName() : null;
930 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, 944 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context,
931 creationParams.getPackageName(), inSandbox); 945 packageName, inSandbox, serviceName);
932 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { 946 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
933 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1, 947 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1,
934 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true, 948 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true,
935 creationParams)); 949 creationParams));
936 } 950 }
937 } 951 }
938 952
939 /** 953 /**
940 * @return the number of sandboxed connections of given {@link packageName} managed by the 954 * @return the number of sandboxed connections of given {@link packageName} managed by the
941 * allocator. 955 * allocator.
942 */ 956 */
943 @VisibleForTesting 957 @VisibleForTesting
944 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) { 958 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) {
945 initConnectionAllocatorsIfNecessary(context, true, packageName); 959 initConnectionAllocatorsIfNecessary(context, true, packageName, null);
946 return sSandboxedChildConnectionAllocatorMap.get(packageName) 960 return sSandboxedChildConnectionAllocatorMap.get(packageName)
947 .allocatedConnectionsCountForTesting(); 961 .allocatedConnectionsCountForTesting();
948 } 962 }
949 963
950 /** @return the count of services set up and working */ 964 /** @return the count of services set up and working */
951 @VisibleForTesting 965 @VisibleForTesting
952 static int connectedServicesCountForTesting() { 966 static int connectedServicesCountForTesting() {
953 return sServiceMap.size(); 967 return sServiceMap.size();
954 } 968 }
955 969
956 /** 970 /**
957 * @param context The context. 971 * @param context The context.
958 * @param packageName The package name of the {@link ChildProcessAlocator}. 972 * @param packageName The package name of the {@link ChildProcessAlocator}.
959 * @param inSandbox Whether the connection is sandboxed. 973 * @param inSandbox Whether the connection is sandboxed.
960 * @return the count of pending spawns in the queue. 974 * @return the count of pending spawns in the queue.
961 */ 975 */
962 @VisibleForTesting 976 @VisibleForTesting
963 static int pendingSpawnsCountForTesting(Context context, String packageName, 977 static int pendingSpawnsCountForTesting(Context context, String packageName,
964 boolean inSandbox) { 978 boolean inSandbox) {
965 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, pack ageName, inSandbox); 979 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, pack ageName, inSandbox,
980 null);
966 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { 981 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
967 return pendingSpawnQueue.sizeLocked(); 982 return pendingSpawnQueue.sizeLocked();
968 } 983 }
969 } 984 }
970 985
971 /** 986 /**
972 * Kills the child process for testing. 987 * Kills the child process for testing.
973 * @return true iff the process was killed as expected 988 * @return true iff the process was killed as expected
974 */ 989 */
975 @VisibleForTesting 990 @VisibleForTesting
976 public static boolean crashProcessForTesting(int pid) { 991 public static boolean crashProcessForTesting(int pid) {
977 if (sServiceMap.get(pid) == null) return false; 992 if (sServiceMap.get(pid) == null) return false;
978 993
979 try { 994 try {
980 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); 995 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting();
981 } catch (RemoteException ex) { 996 } catch (RemoteException ex) {
982 return false; 997 return false;
983 } 998 }
984 999
985 return true; 1000 return true;
986 } 1001 }
987 1002
988 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); 1003 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid);
989 private static native void nativeEstablishSurfacePeer( 1004 private static native void nativeEstablishSurfacePeer(
990 int pid, Surface surface, int primaryID, int secondaryID); 1005 int pid, Surface surface, int primaryID, int secondaryID);
991 private static native boolean nativeIsSingleProcess(); 1006 private static native boolean nativeIsSingleProcess();
992 } 1007 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698