| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "mojo/shell/runner/host/child_process_host.h" | 5 #include "mojo/shell/runner/host/child_process_host.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 start_child_process_event_(false, false), | 48 start_child_process_event_(false, false), |
| 49 weak_factory_(this) { | 49 weak_factory_(this) { |
| 50 node_channel_.reset(new edk::PlatformChannelPair); | 50 node_channel_.reset(new edk::PlatformChannelPair); |
| 51 primordial_pipe_token_ = edk::GenerateRandomToken(); | 51 primordial_pipe_token_ = edk::GenerateRandomToken(); |
| 52 controller_.Bind( | 52 controller_.Bind( |
| 53 InterfacePtrInfo<mojom::ChildController>( | 53 InterfacePtrInfo<mojom::ChildController>( |
| 54 edk::CreateParentMessagePipe(primordial_pipe_token_), 0u)); | 54 edk::CreateParentMessagePipe(primordial_pipe_token_), 0u)); |
| 55 } | 55 } |
| 56 | 56 |
| 57 ChildProcessHost::ChildProcessHost(ScopedHandle channel) | 57 ChildProcessHost::ChildProcessHost(ScopedHandle channel) |
| 58 : launch_process_runner_(nullptr), | 58 : external_process_(true), |
| 59 launch_process_runner_(nullptr), |
| 59 delegate_(nullptr), | 60 delegate_(nullptr), |
| 60 start_sandboxed_(false), | 61 start_sandboxed_(false), |
| 61 start_child_process_event_(false, false), | 62 start_child_process_event_(false, false), |
| 62 weak_factory_(this) { | 63 weak_factory_(this) { |
| 63 CHECK(channel.is_valid()); | 64 CHECK(channel.is_valid()); |
| 64 ScopedMessagePipeHandle handle(MessagePipeHandle(channel.release().value())); | 65 ScopedMessagePipeHandle handle(MessagePipeHandle(channel.release().value())); |
| 65 controller_.Bind( | 66 controller_.Bind( |
| 66 InterfacePtrInfo<mojom::ChildController>(std::move(handle), 0u)); | 67 InterfacePtrInfo<mojom::ChildController>(std::move(handle), 0u)); |
| 67 } | 68 } |
| 68 | 69 |
| 69 ChildProcessHost::~ChildProcessHost() { | 70 ChildProcessHost::~ChildProcessHost() { |
| 70 if (!app_path_.empty()) | 71 if (!app_path_.empty()) |
| 71 CHECK(!controller_) << "Destroying ChildProcessHost before calling Join"; | 72 CHECK(!controller_) << "Destroying ChildProcessHost before calling Join"; |
| 72 } | 73 } |
| 73 | 74 |
| 74 void ChildProcessHost::Start(const ProcessReadyCallback& callback) { | 75 void ChildProcessHost::Start(const ProcessReadyCallback& callback) { |
| 76 DCHECK(!external_process_); |
| 75 DCHECK(!child_process_.IsValid()); | 77 DCHECK(!child_process_.IsValid()); |
| 76 launch_process_runner_->PostTaskAndReply( | 78 launch_process_runner_->PostTaskAndReply( |
| 77 FROM_HERE, | 79 FROM_HERE, |
| 78 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), | 80 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), |
| 79 base::Bind(&ChildProcessHost::DidStart, | 81 base::Bind(&ChildProcessHost::DidStart, |
| 80 weak_factory_.GetWeakPtr(), callback)); | 82 weak_factory_.GetWeakPtr(), callback)); |
| 81 } | 83 } |
| 82 | 84 |
| 83 int ChildProcessHost::Join() { | 85 int ChildProcessHost::Join() { |
| 84 if (controller_) // We use this as a signal that Start was called. | 86 if (controller_ && !external_process_) |
| 85 start_child_process_event_.Wait(); | 87 start_child_process_event_.Wait(); |
| 86 | 88 |
| 87 controller_ = mojom::ChildControllerPtr(); | 89 controller_ = mojom::ChildControllerPtr(); |
| 90 |
| 88 // This host may be hosting a child process whose lifetime is controlled | 91 // This host may be hosting a child process whose lifetime is controlled |
| 89 // elsewhere. In this case we have no known process handle to wait on. | 92 // elsewhere. In this case we have no known process handle to wait on. |
| 90 if (child_process_.IsValid()) { | 93 if (child_process_.IsValid()) { |
| 91 int rv = -1; | 94 int rv = -1; |
| 92 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) | 95 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) |
| 93 << "Failed to wait for child process"; | 96 << "Failed to wait for child process"; |
| 94 | 97 |
| 95 child_process_.Close(); | 98 child_process_.Close(); |
| 96 return rv; | 99 return rv; |
| 97 } | 100 } |
| 98 | 101 |
| 99 return 0; | 102 return 0; |
| 100 } | 103 } |
| 101 | 104 |
| 102 void ChildProcessHost::StartApp( | 105 void ChildProcessHost::StartApp( |
| 103 InterfaceRequest<mojom::ShellClient> request, | 106 InterfaceRequest<mojom::ShellClient> request, |
| 104 const mojom::ChildController::StartAppCallback& on_app_complete) { | 107 const mojom::ChildController::StartAppCallback& on_app_complete) { |
| 105 DCHECK(controller_); | 108 DCHECK(controller_); |
| 106 | |
| 107 // In this case the process must have already been launched. | |
| 108 start_child_process_event_.Signal(); | |
| 109 | |
| 110 on_app_complete_ = on_app_complete; | 109 on_app_complete_ = on_app_complete; |
| 111 controller_->StartApp( | 110 controller_->StartApp( |
| 112 std::move(request), | 111 std::move(request), |
| 113 base::Bind(&ChildProcessHost::AppCompleted, weak_factory_.GetWeakPtr())); | 112 base::Bind(&ChildProcessHost::AppCompleted, weak_factory_.GetWeakPtr())); |
| 114 } | 113 } |
| 115 | 114 |
| 116 void ChildProcessHost::ExitNow(int32_t exit_code) { | 115 void ChildProcessHost::ExitNow(int32_t exit_code) { |
| 117 DCHECK(controller_); | 116 DCHECK(controller_); |
| 118 | 117 |
| 119 controller_->ExitNow(exit_code); | 118 controller_->ExitNow(exit_code); |
| 120 } | 119 } |
| 121 | 120 |
| 122 void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) { | 121 void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) { |
| 123 DVLOG(2) << "ChildProcessHost::DidStart()"; | 122 DVLOG(2) << "ChildProcessHost::DidStart()"; |
| 124 | 123 |
| 125 if (child_process_.IsValid()) { | 124 if (child_process_.IsValid()) { |
| 126 callback.Run(child_process_.Pid()); | 125 callback.Run(child_process_.Pid()); |
| 127 } else { | 126 } else { |
| 128 LOG(ERROR) << "Failed to start child process"; | 127 LOG(ERROR) << "Failed to start child process"; |
| 129 AppCompleted(MOJO_RESULT_UNKNOWN); | 128 AppCompleted(MOJO_RESULT_UNKNOWN); |
| 130 } | 129 } |
| 131 } | 130 } |
| 132 | 131 |
| 133 void ChildProcessHost::DoLaunch() { | 132 void ChildProcessHost::DoLaunch() { |
| 133 DCHECK(!external_process_); |
| 134 |
| 134 const base::CommandLine* parent_command_line = | 135 const base::CommandLine* parent_command_line = |
| 135 base::CommandLine::ForCurrentProcess(); | 136 base::CommandLine::ForCurrentProcess(); |
| 136 base::FilePath target_path = parent_command_line->GetProgram(); | 137 base::FilePath target_path = parent_command_line->GetProgram(); |
| 137 // |app_path_| can be empty in tests. | 138 // |app_path_| can be empty in tests. |
| 138 if (!app_path_.MatchesExtension(FILE_PATH_LITERAL(".mojo")) && | 139 if (!app_path_.MatchesExtension(FILE_PATH_LITERAL(".mojo")) && |
| 139 !app_path_.empty()) { | 140 !app_path_.empty()) { |
| 140 target_path = app_path_; | 141 target_path = app_path_; |
| 141 } | 142 } |
| 142 | 143 |
| 143 base::CommandLine child_command_line(target_path); | 144 base::CommandLine child_command_line(target_path); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 void ChildProcessHost::AppCompleted(int32_t result) { | 232 void ChildProcessHost::AppCompleted(int32_t result) { |
| 232 if (!on_app_complete_.is_null()) { | 233 if (!on_app_complete_.is_null()) { |
| 233 auto on_app_complete = on_app_complete_; | 234 auto on_app_complete = on_app_complete_; |
| 234 on_app_complete_.reset(); | 235 on_app_complete_.reset(); |
| 235 on_app_complete.Run(result); | 236 on_app_complete.Run(result); |
| 236 } | 237 } |
| 237 } | 238 } |
| 238 | 239 |
| 239 } // namespace shell | 240 } // namespace shell |
| 240 } // namespace mojo | 241 } // namespace mojo |
| OLD | NEW |