Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 final 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> serviceClass) { | |
| 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 mChildClass = serviceClass; |
| 81 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class; | |
| 82 mInSandbox = inSandbox; | 82 mInSandbox = inSandbox; |
| 83 } | 83 } |
| 84 | 84 |
| 85 public ChildProcessConnection allocate( | 85 public ChildProcessConnection allocate( |
| 86 Context context, ChildProcessConnection.DeathCallback deathCallb ack, | 86 Context context, ChildProcessConnection.DeathCallback deathCallb ack, |
| 87 ChromiumLinkerParams chromiumLinkerParams, | 87 ChromiumLinkerParams chromiumLinkerParams, |
| 88 boolean alwaysInForeground, | 88 boolean alwaysInForeground, |
| 89 ChildProcessCreationParams creationParams) { | 89 ChildProcessCreationParams creationParams) { |
| 90 synchronized (mConnectionLock) { | 90 synchronized (mConnectionLock) { |
| 91 if (mFreeConnectionIndices.isEmpty()) { | 91 if (mFreeConnectionIndices.isEmpty()) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 // Service class for child process. | 228 // Service class for child process. |
| 229 // Map from package name to ChildConnectionAllocator. | 229 // Map from package name to ChildConnectionAllocator. |
| 230 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti onAllocatorMap; | 230 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti onAllocatorMap; |
| 231 // As the default value it uses PrivilegedProcessService0. | 231 // As the default value it uses PrivilegedProcessService0. |
| 232 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; | 232 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; |
| 233 | 233 |
| 234 private static final String NUM_SANDBOXED_SERVICES_KEY = | 234 private static final String NUM_SANDBOXED_SERVICES_KEY = |
| 235 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; | 235 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; |
| 236 private static final String NUM_PRIVILEGED_SERVICES_KEY = | 236 private static final String NUM_PRIVILEGED_SERVICES_KEY = |
| 237 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; | 237 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; |
| 238 private static final String SANDBOXED_SERVICES_NAME_KEY = | |
| 239 "org.chromium.content.browser.SANDBOXED_SERVICES_NAME"; | |
| 238 // Overrides the number of available sandboxed services. | 240 // Overrides the number of available sandboxed services. |
| 239 @VisibleForTesting | 241 @VisibleForTesting |
| 240 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"; |
| 243 public static final String SWITCH_SANDBOXED_SERVICES_NAME_FOR_TESTING = | |
| 244 "sandboxed-services-name"; | |
| 241 | 245 |
| 242 private static int getNumberOfServices(Context context, boolean inSandbox, S tring packageName) { | 246 private static int getNumberOfServices(Context context, boolean inSandbox, S tring packageName) { |
| 243 try { | 247 int numServices = -1; |
| 244 PackageManager packageManager = context.getPackageManager(); | 248 if (inSandbox |
| 245 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame, | 249 && CommandLine.getInstance().hasSwitch( |
| 246 PackageManager.GET_META_DATA); | 250 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { |
| 247 int numServices = -1; | 251 String value = CommandLine.getInstance().getSwitchValue( |
| 248 if (appInfo.metaData != null) { | 252 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); |
| 249 numServices = appInfo.metaData.getInt( | 253 if (!TextUtils.isEmpty(value)) { |
| 250 inSandbox ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_ SERVICES_KEY, -1); | 254 try { |
| 251 } | 255 numServices = Integer.parseInt(value); |
| 252 if (inSandbox | 256 } catch (NumberFormatException e) { |
| 253 && CommandLine.getInstance().hasSwitch( | 257 Log.w(TAG, "The value of --num-sandboxed-services is formatt ed wrongly: " |
| 254 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { | 258 + value); |
| 255 String value = CommandLine.getInstance().getSwitchValue( | |
| 256 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); | |
| 257 if (!TextUtils.isEmpty(value)) { | |
| 258 try { | |
| 259 numServices = Integer.parseInt(value); | |
| 260 } catch (NumberFormatException e) { | |
| 261 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " | |
| 262 + value); | |
| 263 } | |
| 264 } | 259 } |
| 265 } | 260 } |
| 266 if (numServices < 0) { | 261 } else { |
| 267 throw new RuntimeException("Illegal meta data value for number o f child services"); | 262 try { |
| 263 PackageManager packageManager = context.getPackageManager(); | |
| 264 ApplicationInfo appInfo = packageManager.getApplicationInfo(pack ageName, | |
| 265 PackageManager.GET_META_DATA); | |
| 266 if (appInfo.metaData != null) { | |
| 267 numServices = appInfo.metaData.getInt(inSandbox | |
| 268 ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_SERVIC ES_KEY, -1); | |
| 269 } | |
| 270 } catch (PackageManager.NameNotFoundException e) { | |
| 271 throw new RuntimeException("Could not get application info"); | |
| 268 } | 272 } |
| 269 return numServices; | |
| 270 } catch (PackageManager.NameNotFoundException e) { | |
| 271 throw new RuntimeException("Could not get application info"); | |
| 272 } | 273 } |
| 274 if (numServices < 0) { | |
| 275 throw new RuntimeException("Illegal meta data value for number of ch ild services"); | |
| 276 } | |
| 277 return numServices; | |
| 278 } | |
| 279 | |
| 280 private static Class<? extends Service> getClassOfService(Context context, b oolean inSandbox, | |
| 281 String packageName) { | |
| 282 if (!inSandbox) { | |
| 283 return PrivilegedProcessService.class; | |
| 284 } | |
| 285 String serviceName = null; | |
| 286 if (CommandLine.getInstance().hasSwitch(SWITCH_SANDBOXED_SERVICES_NAME_F OR_TESTING)) { | |
| 287 serviceName = CommandLine.getInstance().getSwitchValue( | |
| 288 SWITCH_SANDBOXED_SERVICES_NAME_FOR_TESTING); | |
| 289 } else { | |
| 290 try { | |
| 291 PackageManager packageManager = context.getPackageManager(); | |
| 292 ApplicationInfo appInfo = packageManager.getApplicationInfo(pack ageName, | |
| 293 PackageManager.GET_META_DATA); | |
| 294 if (appInfo.metaData != null) { | |
| 295 serviceName = appInfo.metaData.getString(SANDBOXED_SERVICES_ NAME_KEY); | |
| 296 } | |
| 297 } catch (PackageManager.NameNotFoundException e) { | |
| 298 throw new RuntimeException("Could not get application info."); | |
| 299 } | |
| 300 } | |
| 301 if (serviceName != null) { | |
| 302 try { | |
| 303 Class<? extends Service> service = | |
| 304 (Class<? extends Service>) Class.forName(serviceName); | |
| 305 return service; | |
| 306 } catch (ClassNotFoundException e) { | |
| 307 throw new RuntimeException( | |
| 308 "Illegal meta data value: the child service class doesn' t exist"); | |
| 309 } | |
| 310 } | |
| 311 return SandboxedProcessService.class; | |
|
no sievers
2016/06/24 21:33:40
This should probably return PrivilegedProcessServi
Xi Han
2016/06/24 21:57:06
The first check is |!inSandbox|, and already retur
| |
| 273 } | 312 } |
| 274 | 313 |
| 275 private static void initConnectionAllocatorsIfNecessary( | 314 private static void initConnectionAllocatorsIfNecessary( |
| 276 Context context, boolean inSandbox, String packageName) { | 315 Context context, boolean inSandbox, String packageName) { |
| 277 // TODO(mariakhomenko): Uses an Object to lock the access. | 316 // TODO(mariakhomenko): Uses an Object to lock the access. |
| 278 synchronized (ChildProcessLauncher.class) { | 317 synchronized (ChildProcessLauncher.class) { |
| 279 if (inSandbox) { | 318 if (inSandbox) { |
| 280 if (sSandboxedChildConnectionAllocatorMap == null) { | 319 if (sSandboxedChildConnectionAllocatorMap == null) { |
| 281 sSandboxedChildConnectionAllocatorMap = | 320 sSandboxedChildConnectionAllocatorMap = |
| 282 new ConcurrentHashMap<String, ChildConnectionAllocat or>(); | 321 new ConcurrentHashMap<String, ChildConnectionAllocat or>(); |
| 283 } | 322 } |
| 284 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) { | 323 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) { |
| 285 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s," | 324 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s," |
| 286 + " inSandbox = true", | 325 + " inSandbox = true", |
| 287 packageName); | 326 packageName); |
| 288 sSandboxedChildConnectionAllocatorMap.put(packageName, | 327 sSandboxedChildConnectionAllocatorMap.put(packageName, |
| 289 new ChildConnectionAllocator(true, | 328 new ChildConnectionAllocator(true, |
| 290 getNumberOfServices(context, true, packageNa me))); | 329 getNumberOfServices(context, true, packageNa me), |
| 330 getClassOfService(context, true, packageName ))); | |
| 291 } | 331 } |
| 292 } else if (sPrivilegedChildConnectionAllocator == null) { | 332 } else if (sPrivilegedChildConnectionAllocator == null) { |
| 293 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or( | 333 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or( |
| 294 false, getNumberOfServices(context, false, packageName)) ; | 334 false, getNumberOfServices(context, false, packageName), |
| 335 getClassOfService(context, false, packageName)); | |
| 295 } | 336 } |
| 296 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from | 337 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from |
| 297 // {@code sSandboxedChildConnectionAllocatorMap}. | 338 // {@code sSandboxedChildConnectionAllocatorMap}. |
| 298 } | 339 } |
| 299 } | 340 } |
| 300 | 341 |
| 301 /** | 342 /** |
| 302 * Note: please make sure that the Allocator has been initialized before cal ling this function. | 343 * Note: please make sure that the Allocator has been initialized before cal ling this function. |
| 303 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first . | 344 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first . |
| 304 */ | 345 */ |
| (...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 ChildProcessCreationParams creationParams) { | 978 ChildProcessCreationParams creationParams) { |
| 938 return allocateBoundConnection(context, null, true, false, creationParam s); | 979 return allocateBoundConnection(context, null, true, false, creationParam s); |
| 939 } | 980 } |
| 940 | 981 |
| 941 /** | 982 /** |
| 942 * Queue up a spawn requests for testing. | 983 * Queue up a spawn requests for testing. |
| 943 */ | 984 */ |
| 944 @VisibleForTesting | 985 @VisibleForTesting |
| 945 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine, | 986 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine, |
| 946 ChildProcessCreationParams creationParams, boolean inSandbox) { | 987 ChildProcessCreationParams creationParams, boolean inSandbox) { |
| 988 String packageName = creationParams != null ? creationParams.getPackageN ame() | |
| 989 : context.getPackageName(); | |
| 947 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, | 990 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, |
| 948 creationParams.getPackageName(), inSandbox); | 991 packageName, inSandbox); |
| 949 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { | 992 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { |
| 950 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1, | 993 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1, |
| 951 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true, | 994 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true, |
| 952 creationParams)); | 995 creationParams)); |
| 953 } | 996 } |
| 954 } | 997 } |
| 955 | 998 |
| 956 /** | 999 /** |
| 957 * @return the number of sandboxed connections of given {@link packageName} managed by the | 1000 * @return the number of sandboxed connections of given {@link packageName} managed by the |
| 958 * allocator. | 1001 * allocator. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1000 } | 1043 } |
| 1001 | 1044 |
| 1002 return true; | 1045 return true; |
| 1003 } | 1046 } |
| 1004 | 1047 |
| 1005 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); | 1048 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); |
| 1006 private static native void nativeEstablishSurfacePeer( | 1049 private static native void nativeEstablishSurfacePeer( |
| 1007 int pid, Surface surface, int primaryID, int secondaryID); | 1050 int pid, Surface surface, int primaryID, int secondaryID); |
| 1008 private static native boolean nativeIsSingleProcess(); | 1051 private static native boolean nativeIsSingleProcess(); |
| 1009 } | 1052 } |
| OLD | NEW |