Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.Intent; | 9 import android.content.Intent; |
| 10 import android.content.ServiceConnection; | 10 import android.content.ServiceConnection; |
| 11 import android.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
| 12 import android.content.pm.ServiceInfo; | 12 import android.content.pm.ServiceInfo; |
| 13 import android.os.Build; | 13 import android.os.Build; |
| 14 import android.os.Bundle; | 14 import android.os.Bundle; |
| 15 import android.os.IBinder; | 15 import android.os.IBinder; |
| 16 import android.os.RemoteException; | 16 import android.os.RemoteException; |
| 17 | 17 |
| 18 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
| 19 import org.chromium.base.TraceEvent; | 19 import org.chromium.base.TraceEvent; |
| 20 import org.chromium.base.VisibleForTesting; | 20 import org.chromium.base.VisibleForTesting; |
| 21 import org.chromium.base.process_launcher.ChildProcessCreationParams; | 21 import org.chromium.base.process_launcher.ChildProcessCreationParams; |
| 22 import org.chromium.base.process_launcher.FileDescriptorInfo; | |
| 23 import org.chromium.base.process_launcher.ICallbackInt; | 22 import org.chromium.base.process_launcher.ICallbackInt; |
| 24 import org.chromium.base.process_launcher.IChildProcessService; | 23 import org.chromium.base.process_launcher.IChildProcessService; |
| 25 | 24 |
| 26 import java.io.IOException; | |
| 27 import java.util.HashMap; | 25 import java.util.HashMap; |
| 28 import java.util.Map; | 26 import java.util.Map; |
| 29 | 27 |
| 30 import javax.annotation.Nullable; | 28 import javax.annotation.Nullable; |
| 31 | 29 |
| 32 /** | 30 /** |
| 33 * Manages a connection between the browser activity and a child service. | 31 * Manages a connection between the browser activity and a child service. |
| 34 */ | 32 */ |
| 35 public class ChildProcessConnection { | 33 public class ChildProcessConnection { |
| 36 private static final String TAG = "ChildProcessConn"; | 34 private static final String TAG = "ChildProcessConn"; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 private final ComponentName mServiceName; | 157 private final ComponentName mServiceName; |
| 160 | 158 |
| 161 // Parameters passed to the child process through the service binding intent . | 159 // Parameters passed to the child process through the service binding intent . |
| 162 // If the service gets recreated by the framework the intent will be reused, so these parameters | 160 // If the service gets recreated by the framework the intent will be reused, so these parameters |
| 163 // should be common to all processes of that type. | 161 // should be common to all processes of that type. |
| 164 private final Bundle mChildProcessCommonParameters; | 162 private final Bundle mChildProcessCommonParameters; |
| 165 | 163 |
| 166 private final ChildProcessCreationParams mCreationParams; | 164 private final ChildProcessCreationParams mCreationParams; |
| 167 | 165 |
| 168 private static class ConnectionParams { | 166 private static class ConnectionParams { |
| 169 final String[] mCommandLine; | 167 final Bundle mBundle; |
|
boliu
2017/05/15 21:38:22
name this mConnectionBundle
Jay Civelli
2017/05/17 16:42:50
Done.
| |
| 170 final FileDescriptorInfo[] mFilesToBeMapped; | |
| 171 final IBinder mCallback; | 168 final IBinder mCallback; |
| 172 | 169 |
| 173 ConnectionParams( | 170 ConnectionParams(Bundle bundle, IBinder callback) { |
| 174 String[] commandLine, FileDescriptorInfo[] filesToBeMapped, IBin der callback) { | 171 mBundle = bundle; |
| 175 mCommandLine = commandLine; | |
| 176 mFilesToBeMapped = filesToBeMapped; | |
| 177 mCallback = callback; | 172 mCallback = callback; |
| 178 } | 173 } |
| 179 } | 174 } |
| 180 | 175 |
| 181 // This is set in start() and is used in onServiceConnected(). | 176 // This is set in start() and is used in onServiceConnected(). |
| 182 private StartCallback mStartCallback; | 177 private StartCallback mStartCallback; |
| 183 | 178 |
| 184 // This is set in setupConnection() and is later used in doConnectionSetupLo cked(), after which | 179 // This is set in setupConnection() and is later used in doConnectionSetup() , after which the |
| 185 // the variable is cleared. Therefore this is only valid while the connectio n is being set up. | 180 // variable is cleared. Therefore this is only valid while the connection is being set up. |
| 186 private ConnectionParams mConnectionParams; | 181 private ConnectionParams mConnectionParams; |
| 187 | 182 |
| 188 // Callback provided in setupConnection() that will communicate the result t o the caller. This | 183 // Callback provided in setupConnection() that will communicate the result t o the caller. This |
| 189 // has to be called exactly once after setupConnection(), even if setup fail s, so that the | 184 // has to be called exactly once after setupConnection(), even if setup fail s, so that the |
| 190 // caller can free up resources associated with the setup attempt. This is s et to null after the | 185 // caller can free up resources associated with the setup attempt. This is s et to null after the |
| 191 // call. | 186 // call. |
| 192 private ConnectionCallback mConnectionCallback; | 187 private ConnectionCallback mConnectionCallback; |
| 193 | 188 |
| 194 private IChildProcessService mService; | 189 private IChildProcessService mService; |
| 195 | 190 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 * Starts a connection to an IChildProcessService. This must be followed by a call to | 283 * Starts a connection to an IChildProcessService. This must be followed by a call to |
| 289 * setupConnection() to setup the connection parameters. start() and setupCo nnection() are | 284 * setupConnection() to setup the connection parameters. start() and setupCo nnection() are |
| 290 * separate to allow to pass whatever parameters are available in start(), a nd complete the | 285 * separate to allow to pass whatever parameters are available in start(), a nd complete the |
| 291 * remainder addStrongBinding while reducing the connection setup latency. | 286 * remainder addStrongBinding while reducing the connection setup latency. |
| 292 * @param useStrongBinding whether a strong binding should be bound by defau lt. If false, an | 287 * @param useStrongBinding whether a strong binding should be bound by defau lt. If false, an |
| 293 * initial moderate binding is used. | 288 * initial moderate binding is used. |
| 294 * @param startCallback (optional) callback when the child process starts or fails to start. | 289 * @param startCallback (optional) callback when the child process starts or fails to start. |
| 295 */ | 290 */ |
| 296 public void start(boolean useStrongBinding, StartCallback startCallback) { | 291 public void start(boolean useStrongBinding, StartCallback startCallback) { |
| 297 assert LauncherThread.runningOnLauncherThread(); | 292 assert LauncherThread.runningOnLauncherThread(); |
| 293 | |
| 298 try { | 294 try { |
| 299 TraceEvent.begin("ChildProcessConnection.start"); | 295 TraceEvent.begin("ChildProcessConnection.start"); |
| 300 assert LauncherThread.runningOnLauncherThread(); | 296 assert LauncherThread.runningOnLauncherThread(); |
| 301 assert mConnectionParams | 297 assert mConnectionParams |
| 302 == null : "setupConnection() called before start() in ChildP rocessConnection."; | 298 == null : "setupConnection() called before start() in ChildP rocessConnection."; |
| 303 | 299 |
| 304 mStartCallback = startCallback; | 300 mStartCallback = startCallback; |
| 305 | 301 |
| 306 if (!bind(useStrongBinding)) { | 302 if (!bind(useStrongBinding)) { |
| 307 Log.e(TAG, "Failed to establish the service connection."); | 303 Log.e(TAG, "Failed to establish the service connection."); |
| 308 // We have to notify the caller so that they can free-up associa ted resources. | 304 // We have to notify the caller so that they can free-up associa ted resources. |
| 309 // TODO(ppi): Can we hard-fail here? | 305 // TODO(ppi): Can we hard-fail here? |
| 310 mDeathCallback.onChildProcessDied(ChildProcessConnection.this); | 306 mDeathCallback.onChildProcessDied(ChildProcessConnection.this); |
| 311 } | 307 } |
| 312 } finally { | 308 } finally { |
| 313 TraceEvent.end("ChildProcessConnection.start"); | 309 TraceEvent.end("ChildProcessConnection.start"); |
| 314 } | 310 } |
| 315 } | 311 } |
| 316 | 312 |
| 317 /** | 313 /** |
| 318 * Setups the connection after it was started with start(). | 314 * Sets-up the connection after it was started with start(). |
| 319 * @param commandLine (optional) will be ignored if the command line was alr eady sent in start() | 315 * @param connectionBundle a bundle passed to the service that can be used t o pass various |
| 320 * @param filesToBeMapped a list of file descriptors that should be register ed | 316 * parameters to the service |
| 321 * @param callback optional client specified callbacks that the child can us e to communicate | 317 * @param callback optional client specified callbacks that the child can us e to communicate |
| 322 * with the parent process | 318 * with the parent process |
| 323 * @param connectionCallback will be called exactly once after the connectio n is set up or the | 319 * @param connectionCallback will be called exactly once after the connectio n is set up or the |
| 324 * setup fails | 320 * setup fails |
| 325 */ | 321 */ |
| 326 public void setupConnection(String[] commandLine, FileDescriptorInfo[] files ToBeMapped, | 322 public void setupConnection(Bundle connectionBundle, @Nullable IBinder callb ack, |
| 327 @Nullable IBinder callback, ConnectionCallback connectionCallback) { | 323 ConnectionCallback connectionCallback) { |
| 328 assert LauncherThread.runningOnLauncherThread(); | 324 assert LauncherThread.runningOnLauncherThread(); |
| 329 assert mConnectionParams == null; | 325 assert mConnectionParams == null; |
| 330 if (mServiceDisconnected) { | 326 if (mServiceDisconnected) { |
| 331 Log.w(TAG, "Tried to setup a connection that already disconnected.") ; | 327 Log.w(TAG, "Tried to setup a connection that already disconnected.") ; |
| 332 connectionCallback.onConnected(null); | 328 connectionCallback.onConnected(null); |
| 333 return; | 329 return; |
| 334 } | 330 } |
| 335 try { | 331 try { |
| 336 TraceEvent.begin("ChildProcessConnection.setupConnection"); | 332 TraceEvent.begin("ChildProcessConnection.setupConnection"); |
| 337 mConnectionCallback = connectionCallback; | 333 mConnectionCallback = connectionCallback; |
| 338 mConnectionParams = new ConnectionParams(commandLine, filesToBeMappe d, callback); | 334 mConnectionParams = new ConnectionParams(connectionBundle, callback) ; |
| 339 // Run the setup if the service is already connected. If not, | 335 // Run the setup if the service is already connected. If not, doConn ectionSetup() will |
| 340 // doConnectionSetupLocked() will be called from onServiceConnected( ). | 336 // be called from onServiceConnected(). |
| 341 if (mServiceConnectComplete) { | 337 if (mServiceConnectComplete) { |
| 342 doConnectionSetupLocked(); | 338 doConnectionSetup(); |
| 343 } | 339 } |
| 344 } finally { | 340 } finally { |
| 345 TraceEvent.end("ChildProcessConnection.setupConnection"); | 341 TraceEvent.end("ChildProcessConnection.setupConnection"); |
| 346 } | 342 } |
| 347 } | 343 } |
| 348 | 344 |
| 349 /** | 345 /** |
| 350 * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call | 346 * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call |
| 351 * this multiple times. | 347 * this multiple times. |
| 352 */ | 348 */ |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 } | 388 } |
| 393 } | 389 } |
| 394 | 390 |
| 395 if (!boundToUs) { | 391 if (!boundToUs) { |
| 396 return; | 392 return; |
| 397 } | 393 } |
| 398 | 394 |
| 399 mServiceConnectComplete = true; | 395 mServiceConnectComplete = true; |
| 400 | 396 |
| 401 // Run the setup if the connection parameters have already been prov ided. If | 397 // Run the setup if the connection parameters have already been prov ided. If |
| 402 // not, doConnectionSetupLocked() will be called from setupConnectio n(). | 398 // not, doConnectionSetup() will be called from setupConnection(). |
| 403 if (mConnectionParams != null) { | 399 if (mConnectionParams != null) { |
| 404 doConnectionSetupLocked(); | 400 doConnectionSetup(); |
| 405 } | 401 } |
| 406 } finally { | 402 } finally { |
| 407 TraceEvent.end("ChildProcessConnection.ChildServiceConnection.onServ iceConnected"); | 403 TraceEvent.end("ChildProcessConnection.ChildServiceConnection.onServ iceConnected"); |
| 408 } | 404 } |
| 409 } | 405 } |
| 410 | 406 |
| 411 private void onServiceDisconnectedOnLauncherThread() { | 407 private void onServiceDisconnectedOnLauncherThread() { |
| 412 assert LauncherThread.runningOnLauncherThread(); | 408 assert LauncherThread.runningOnLauncherThread(); |
| 413 // Ensure that the disconnection logic runs only once (instead of once p er each | 409 // Ensure that the disconnection logic runs only once (instead of once p er each |
| 414 // ChildServiceConnection). | 410 // ChildServiceConnection). |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 433 | 429 |
| 434 if (mConnectionCallback != null) { | 430 if (mConnectionCallback != null) { |
| 435 mConnectionCallback.onConnected(this); | 431 mConnectionCallback.onConnected(this); |
| 436 } | 432 } |
| 437 mConnectionCallback = null; | 433 mConnectionCallback = null; |
| 438 } | 434 } |
| 439 | 435 |
| 440 /** | 436 /** |
| 441 * Called after the connection parameters have been set (in setupConnection( )) *and* a | 437 * Called after the connection parameters have been set (in setupConnection( )) *and* a |
| 442 * connection has been established (as signaled by onServiceConnected()). Th ese two events can | 438 * connection has been established (as signaled by onServiceConnected()). Th ese two events can |
| 443 * happen in any order. Has to be called with mLock. | 439 * happen in any order. |
| 444 */ | 440 */ |
| 445 private void doConnectionSetupLocked() { | 441 private void doConnectionSetup() { |
| 446 try { | 442 try { |
| 447 TraceEvent.begin("ChildProcessConnection.doConnectionSetupLocked"); | 443 TraceEvent.begin("ChildProcessConnection.doConnectionSetup"); |
| 448 assert mServiceConnectComplete && mService != null; | 444 assert mServiceConnectComplete && mService != null; |
| 449 assert mConnectionParams != null; | 445 assert mConnectionParams != null; |
| 450 | 446 |
| 451 Bundle bundle = ChildProcessLauncher.createsServiceBundle( | |
| 452 mConnectionParams.mCommandLine, mConnectionParams.mFilesToBe Mapped); | |
| 453 ICallbackInt pidCallback = new ICallbackInt.Stub() { | 447 ICallbackInt pidCallback = new ICallbackInt.Stub() { |
| 454 @Override | 448 @Override |
| 455 public void call(final int pid) { | 449 public void call(final int pid) { |
| 456 LauncherThread.post(new Runnable() { | 450 LauncherThread.post(new Runnable() { |
| 457 @Override | 451 @Override |
| 458 public void run() { | 452 public void run() { |
| 459 onSetupConnectionResult(pid); | 453 onSetupConnectionResult(pid); |
| 460 } | 454 } |
| 461 }); | 455 }); |
| 462 } | 456 } |
| 463 }; | 457 }; |
| 464 try { | 458 try { |
| 465 mService.setupConnection(bundle, pidCallback, mConnectionParams. mCallback); | 459 mService.setupConnection( |
| 460 mConnectionParams.mBundle, pidCallback, mConnectionParam s.mCallback); | |
| 466 } catch (RemoteException re) { | 461 } catch (RemoteException re) { |
| 467 Log.e(TAG, "Failed to setup connection.", re); | 462 Log.e(TAG, "Failed to setup connection.", re); |
| 468 } | 463 } |
| 469 // We proactively close the FDs rather than wait for GC & finalizer. | |
| 470 try { | |
| 471 for (FileDescriptorInfo fileInfo : mConnectionParams.mFilesToBeM apped) { | |
| 472 fileInfo.fd.close(); | |
| 473 } | |
| 474 } catch (IOException ioe) { | |
| 475 Log.w(TAG, "Failed to close FD.", ioe); | |
| 476 } | |
| 477 mConnectionParams = null; | 464 mConnectionParams = null; |
| 478 } finally { | 465 } finally { |
| 479 TraceEvent.end("ChildProcessConnection.doConnectionSetupLocked"); | 466 TraceEvent.end("ChildProcessConnection.doConnectionSetup"); |
| 480 } | 467 } |
| 481 } | 468 } |
| 482 | 469 |
| 483 private boolean bind(boolean useStrongBinding) { | 470 private boolean bind(boolean useStrongBinding) { |
| 484 assert LauncherThread.runningOnLauncherThread(); | 471 assert LauncherThread.runningOnLauncherThread(); |
| 485 assert !mUnbound; | 472 assert !mUnbound; |
| 486 | 473 |
| 487 boolean success = useStrongBinding ? mStrongBinding.bind() : mInitialBin ding.bind(); | 474 boolean success = useStrongBinding ? mStrongBinding.bind() : mInitialBin ding.bind(); |
| 488 if (!success) return false; | 475 if (!success) return false; |
| 489 | 476 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 636 protected ChildServiceConnection createServiceConnection(int bindFlags) { | 623 protected ChildServiceConnection createServiceConnection(int bindFlags) { |
| 637 assert LauncherThread.runningOnLauncherThread(); | 624 assert LauncherThread.runningOnLauncherThread(); |
| 638 return new ChildServiceConnectionImpl(bindFlags); | 625 return new ChildServiceConnectionImpl(bindFlags); |
| 639 } | 626 } |
| 640 | 627 |
| 641 @VisibleForTesting | 628 @VisibleForTesting |
| 642 public void crashServiceForTesting() throws RemoteException { | 629 public void crashServiceForTesting() throws RemoteException { |
| 643 mService.crashIntentionallyForTesting(); | 630 mService.crashIntentionallyForTesting(); |
| 644 } | 631 } |
| 645 } | 632 } |
| OLD | NEW |