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

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

Issue 2626413004: Bind Android ChildProcessServices to a specific client PID. (Closed)
Patch Set: '' Created 3 years, 11 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.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;
11 import android.os.AsyncTask;
11 import android.os.Bundle; 12 import android.os.Bundle;
12 import android.os.ParcelFileDescriptor; 13 import android.os.ParcelFileDescriptor;
13 import android.os.RemoteException; 14 import android.os.RemoteException;
14 import android.text.TextUtils; 15 import android.text.TextUtils;
15 import android.view.Surface; 16 import android.view.Surface;
16 17
17 import org.chromium.base.CommandLine; 18 import org.chromium.base.CommandLine;
18 import org.chromium.base.CpuFeatures; 19 import org.chromium.base.CpuFeatures;
19 import org.chromium.base.Log; 20 import org.chromium.base.Log;
20 import org.chromium.base.ThreadUtils; 21 import org.chromium.base.ThreadUtils;
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 linker.getTestRunnerClassNameForTest ing(), 407 linker.getTestRunnerClassNameForTest ing(),
407 linker.getImplementationForTesting() ); 408 linker.getImplementationForTesting() );
408 } else { 409 } else {
409 return new ChromiumLinkerParams(sLinkerLoadAddress, 410 return new ChromiumLinkerParams(sLinkerLoadAddress,
410 waitForSharedRelros); 411 waitForSharedRelros);
411 } 412 }
412 } 413 }
413 414
414 private static ChildProcessConnection allocateBoundConnection(Context contex t, 415 private static ChildProcessConnection allocateBoundConnection(Context contex t,
415 String[] commandLine, boolean inSandbox, boolean alwaysInForeground, 416 String[] commandLine, boolean inSandbox, boolean alwaysInForeground,
416 ChildProcessCreationParams creationParams) { 417 ChildProcessCreationParams creationParams,
418 ChildProcessConnection.StartCallback startCallback) {
417 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); 419 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion();
418 ChildProcessConnection connection = allocateConnection( 420 ChildProcessConnection connection = allocateConnection(
419 context, inSandbox, chromiumLinkerParams, alwaysInForeground, cr eationParams); 421 context, inSandbox, chromiumLinkerParams, alwaysInForeground, cr eationParams);
420 if (connection != null) { 422 if (connection != null) {
421 connection.start(commandLine); 423 connection.start(commandLine, startCallback);
422 424
423 String packageName = creationParams != null ? creationParams.getPack ageName() 425 String packageName = creationParams != null ? creationParams.getPack ageName()
424 : context.getPackageName(); 426 : context.getPackageName();
425 if (inSandbox && !getConnectionAllocator(packageName, inSandbox) 427 if (inSandbox && !getConnectionAllocator(packageName, inSandbox)
426 .isFreeConnectionAvailable()) { 428 .isFreeConnectionAvailable()) {
427 // Proactively releases all the moderate bindings once all the s andboxed services 429 // Proactively releases all the moderate bindings once all the s andboxed services
428 // are allocated, which will be very likely to have some of them killed by OOM 430 // are allocated, which will be very likely to have some of them killed by OOM
429 // killer. 431 // killer.
430 sBindingManager.releaseAllModerateBindings(); 432 sBindingManager.releaseAllModerateBindings();
431 } 433 }
432 } 434 }
433 return connection; 435 return connection;
434 } 436 }
435 437
436 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; 438 private static final long FREE_CONNECTION_DELAY_MILLIS = 1;
437 439
438 private static void freeConnection(ChildProcessConnection connection) { 440 private static void freeConnection(ChildProcessConnection connection) {
439 synchronized (ChildProcessLauncher.class) { 441 synchronized (sSpareConnectionLock) {
440 if (connection.equals(sSpareSandboxedConnection)) sSpareSandboxedCon nection = null; 442 if (connection.equals(sSpareSandboxedConnection)) sSpareSandboxedCon nection = null;
441 } 443 }
442 444
443 // Freeing a service should be delayed. This is so that we avoid immedia tely reusing the 445 // Freeing a service should be delayed. This is so that we avoid immedia tely reusing the
444 // freed service (see http://crbug.com/164069): the framework might keep a service process 446 // freed service (see http://crbug.com/164069): the framework might keep a service process
445 // alive when it's been unbound for a short time. If a new connection to the same service 447 // alive when it's been unbound for a short time. If a new connection to the same service
446 // is bound at that point, the process is reused and bad things happen ( mostly static 448 // is bound at that point, the process is reused and bad things happen ( mostly static
447 // variables are set when we don't expect them to). 449 // variables are set when we don't expect them to).
448 final ChildProcessConnection conn = connection; 450 final ChildProcessConnection conn = connection;
449 ThreadUtils.postOnUiThreadDelayed(new Runnable() { 451 ThreadUtils.postOnUiThreadDelayed(new Runnable() {
(...skipping 26 matching lines...) Expand all
476 } 478 }
477 } 479 }
478 480
479 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. 481 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle.
480 private static final int NULL_PROCESS_HANDLE = 0; 482 private static final int NULL_PROCESS_HANDLE = 0;
481 483
482 // Map from pid to ChildService connection. 484 // Map from pid to ChildService connection.
483 private static Map<Integer, ChildProcessConnection> sServiceMap = 485 private static Map<Integer, ChildProcessConnection> sServiceMap =
484 new ConcurrentHashMap<Integer, ChildProcessConnection>(); 486 new ConcurrentHashMap<Integer, ChildProcessConnection>();
485 487
488 // Lock and monitor for these members {{{
489 private static final Object sSpareConnectionLock = new Object();
486 // A pre-allocated and pre-bound connection ready for connection setup, or n ull. 490 // A pre-allocated and pre-bound connection ready for connection setup, or n ull.
487 private static ChildProcessConnection sSpareSandboxedConnection; 491 private static ChildProcessConnection sSpareSandboxedConnection;
492 // If sSpareSandboxedConnection is not null, this indicates whether the serv ice is
493 // ready for connection setup. Wait on the monitor lock to be notified when this
494 // state changes. sSpareSandboxedConnection may be null after waiting, if st arting
495 // the service failed.
496 private static boolean sSpareConnectionStarting;
497 // }}}
488 498
489 // Manages oom bindings used to bind chind services. 499 // Manages oom bindings used to bind chind services.
490 private static BindingManager sBindingManager = BindingManagerImpl.createBin dingManager(); 500 private static BindingManager sBindingManager = BindingManagerImpl.createBin dingManager();
491 501
492 // Whether the main application is currently brought to the foreground. 502 // Whether the main application is currently brought to the foreground.
493 private static boolean sApplicationInForeground = true; 503 private static boolean sApplicationInForeground = true;
494 504
495 @VisibleForTesting 505 @VisibleForTesting
496 public static void setBindingManagerForTesting(BindingManager manager) { 506 public static void setBindingManagerForTesting(BindingManager manager) {
497 sBindingManager = manager; 507 sBindingManager = manager;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 return sApplicationInForeground; 570 return sApplicationInForeground;
561 } 571 }
562 572
563 /** 573 /**
564 * Should be called early in startup so the work needed to spawn the child p rocess can be done 574 * Should be called early in startup so the work needed to spawn the child p rocess can be done
565 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is 575 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is
566 * created in sandboxed child process. 576 * created in sandboxed child process.
567 * @param context the application context used for the connection. 577 * @param context the application context used for the connection.
568 */ 578 */
569 public static void warmUp(Context context) { 579 public static void warmUp(Context context) {
570 synchronized (ChildProcessLauncher.class) { 580 synchronized (sSpareConnectionLock) {
571 assert !ThreadUtils.runningOnUiThread(); 581 assert !ThreadUtils.runningOnUiThread();
572 if (sSpareSandboxedConnection == null) { 582 if (sSpareSandboxedConnection == null) {
573 ChildProcessCreationParams params = ChildProcessCreationParams.g et(); 583 ChildProcessCreationParams params = ChildProcessCreationParams.g et();
574 if (params != null) { 584 if (params != null) {
575 params = params.copy(); 585 params = params.copy();
576 } 586 }
587
Tobias Sargeant 2017/01/14 23:24:58 Presumably the fact that warmUp doesn't retry mean
Robert Sesek 2017/01/17 19:51:22 Since warmUp is only used for the first connection
588 sSpareConnectionStarting = true;
589
590 ChildProcessConnection.StartCallback startCallback =
591 new ChildProcessConnection.StartCallback() {
592 @Override
593 public void onChildStarted() {
594 synchronized (sSpareConnectionLock) {
595 sSpareConnectionStarting = false;
596 sSpareConnectionLock.notify();
597 }
598 }
599
600 @Override
601 public void onChildStartFailed() {
602 Log.e(TAG, "Failed to warm up the spare sandbox service");
603 synchronized (sSpareConnectionLock) {
604 sSpareSandboxedConnection = null;
605 sSpareConnectionStarting = false;
606 sSpareConnectionLock.notify();
607 }
608 }
609 };
577 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false, 610 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false,
578 params); 611 params, startCallback);
579 } 612 }
580 } 613 }
581 } 614 }
582 615
583 @CalledByNative 616 @CalledByNative
584 private static FileDescriptorInfo makeFdInfo( 617 private static FileDescriptorInfo makeFdInfo(
585 int id, int fd, boolean autoClose, long offset, long size) { 618 int id, int fd, boolean autoClose, long offset, long size) {
586 ParcelFileDescriptor pFd; 619 ParcelFileDescriptor pFd;
587 if (autoClose) { 620 if (autoClose) {
588 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. 621 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 } else { 680 } else {
648 assert false; 681 assert false;
649 } 682 }
650 } 683 }
651 684
652 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, 685 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext,
653 callbackType, inSandbox, params); 686 callbackType, inSandbox, params);
654 } 687 }
655 688
656 private static void startInternal( 689 private static void startInternal(
657 Context context, 690 final Context context,
658 final String[] commandLine, 691 final String[] commandLine,
659 int childProcessId, 692 final int childProcessId,
660 FileDescriptorInfo[] filesToBeMapped, 693 final FileDescriptorInfo[] filesToBeMapped,
661 long clientContext, 694 final long clientContext,
662 int callbackType, 695 final int callbackType,
663 boolean inSandbox, 696 final boolean inSandbox,
664 ChildProcessCreationParams creationParams) { 697 final ChildProcessCreationParams creationParams) {
665 try { 698 try {
666 TraceEvent.begin("ChildProcessLauncher.startInternal"); 699 TraceEvent.begin("ChildProcessLauncher.startInternal");
667 700
668 ChildProcessConnection allocatedConnection = null; 701 ChildProcessConnection allocatedConnection = null;
669 String packageName = creationParams != null ? creationParams.getPack ageName() 702 String packageName = creationParams != null ? creationParams.getPack ageName()
670 : context.getPackageName(); 703 : context.getPackageName();
671 synchronized (ChildProcessLauncher.class) { 704 synchronized (sSpareConnectionLock) {
672 if (inSandbox && sSpareSandboxedConnection != null 705 if (inSandbox && sSpareSandboxedConnection != null
673 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) { 706 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) {
707 while (sSpareConnectionStarting) {
708 try {
709 sSpareConnectionLock.wait();
710 } catch (InterruptedException ex) {
711 }
712 }
674 allocatedConnection = sSpareSandboxedConnection; 713 allocatedConnection = sSpareSandboxedConnection;
675 sSpareSandboxedConnection = null; 714 sSpareSandboxedConnection = null;
676 } 715 }
677 } 716 }
678 if (allocatedConnection == null) { 717 if (allocatedConnection == null) {
679 boolean alwaysInForeground = false; 718 boolean alwaysInForeground = false;
680 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; 719 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
681 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue( 720 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(
682 context, packageName, inSandbox); 721 context, packageName, inSandbox);
722 ChildProcessConnection.StartCallback startCallback =
723 new ChildProcessConnection.StartCallback() {
724 @Override
725 public void onChildStarted() {}
726
727 @Override
728 public void onChildStartFailed() {
729 Log.e(TAG, "ChildProcessConnection.start failed, trying again");
730 new AsyncTask<Void, Void, Void>() {
Torne 2017/01/16 12:44:43 If the asynctask only has a doInBackground and is
Robert Sesek 2017/01/17 19:51:22 Done.
731 @Override
732 protected Void doInBackground(Void... params ) {
733 startInternal(context, commandLine, chil dProcessId,
734 filesToBeMapped, clientContext, callbackType,
735 inSandbox, creationParams);
736 return null;
737 }
738 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUT OR);
739 }
740 };
683 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { 741 synchronized (pendingSpawnQueue.mPendingSpawnsLock) {
684 allocatedConnection = allocateBoundConnection( 742 allocatedConnection = allocateBoundConnection(
685 context, commandLine, inSandbox, alwaysInForeground, creationParams); 743 context, commandLine, inSandbox, alwaysInForeground, creationParams,
744 startCallback);
686 if (allocatedConnection == null) { 745 if (allocatedConnection == null) {
687 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); 746 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
688 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine, 747 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine,
689 childProcessId, filesToBeMapped, clientContext, 748 childProcessId, filesToBeMapped, clientContext,
690 callbackType, inSandbox, creationParams)); 749 callbackType, inSandbox, creationParams));
691 return; 750 return;
692 } 751 }
693 } 752 }
694 } 753 }
695 754
696 Log.d(TAG, "Setting up connection to process: slot=%d", 755 Log.d(TAG, "Setting up connection to process: slot=%d",
697 allocatedConnection.getServiceNumber()); 756 allocatedConnection.getServiceNumber());
698 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId, 757 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId,
Tobias Sargeant 2017/01/14 23:24:57 I'm not sure that I understand this code, but in t
Torne 2017/01/16 12:44:43 I think it will have early returned on line 750 ab
Robert Sesek 2017/01/17 19:51:22 Right. allocatedConnection will be null so it will
699 filesToBeMapped, callbackType, clientContext); 758 filesToBeMapped, callbackType, clientContext);
700 } finally { 759 } finally {
701 TraceEvent.end("ChildProcessLauncher.startInternal"); 760 TraceEvent.end("ChildProcessLauncher.startInternal");
702 } 761 }
703 } 762 }
704 763
705 /** 764 /**
706 * Create the common bundle to be passed to child processes. 765 * Create the common bundle to be passed to child processes.
707 * @param context Application context. 766 * @param context Application context.
708 * @param commandLine Command line params to be passed to the service. 767 * @param commandLine Command line params to be passed to the service.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 static void logPidWarning(int pid, String message) { 888 static void logPidWarning(int pid, String message) {
830 // This class is effectively a no-op in single process mode, so don't lo g warnings there. 889 // This class is effectively a no-op in single process mode, so don't lo g warnings there.
831 if (pid > 0 && !nativeIsSingleProcess()) { 890 if (pid > 0 && !nativeIsSingleProcess()) {
832 Log.w(TAG, "%s, pid=%d", message, pid); 891 Log.w(TAG, "%s, pid=%d", message, pid);
833 } 892 }
834 } 893 }
835 894
836 @VisibleForTesting 895 @VisibleForTesting
837 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext, 896 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext,
838 ChildProcessCreationParams creationParams) { 897 ChildProcessCreationParams creationParams) {
839 return allocateBoundConnection(context, null, true, false, creationParam s); 898 return allocateBoundConnection(context, null, true, false, creationParam s, null);
840 } 899 }
841 900
842 @VisibleForTesting 901 @VisibleForTesting
843 static ChildProcessConnection allocateConnectionForTesting(Context context, 902 static ChildProcessConnection allocateConnectionForTesting(Context context,
844 ChildProcessCreationParams creationParams) { 903 ChildProcessCreationParams creationParams) {
845 return allocateConnection( 904 return allocateConnection(
846 context, true, getLinkerParamsForNewConnection(), false, creatio nParams); 905 context, true, getLinkerParamsForNewConnection(), false, creatio nParams);
847 } 906 }
848 907
849 /** 908 /**
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 } 972 }
914 973
915 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); 974 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid);
916 private static native void nativeEstablishSurfacePeer( 975 private static native void nativeEstablishSurfacePeer(
917 int pid, Surface surface, int primaryID, int secondaryID); 976 int pid, Surface surface, int primaryID, int secondaryID);
918 private static native void nativeCompleteScopedSurfaceRequest( 977 private static native void nativeCompleteScopedSurfaceRequest(
919 UnguessableToken requestToken, Surface surface); 978 UnguessableToken requestToken, Surface surface);
920 private static native boolean nativeIsSingleProcess(); 979 private static native boolean nativeIsSingleProcess();
921 private static native Surface nativeGetViewSurface(int surfaceId); 980 private static native Surface nativeGetViewSurface(int surfaceId);
922 } 981 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698