| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 const base::FilePath& app_path) | 42 const base::FilePath& app_path) |
| 43 : launch_process_runner_(launch_process_runner), | 43 : launch_process_runner_(launch_process_runner), |
| 44 delegate_(delegate), | 44 delegate_(delegate), |
| 45 start_sandboxed_(start_sandboxed), | 45 start_sandboxed_(start_sandboxed), |
| 46 target_(target), | 46 target_(target), |
| 47 app_path_(app_path), | 47 app_path_(app_path), |
| 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 factory_.Bind(InterfacePtrInfo<mojom::ShellClientFactory>( |
| 53 InterfacePtrInfo<mojom::ChildController>( | 53 edk::CreateParentMessagePipe(primordial_pipe_token_), 0u)); |
| 54 edk::CreateParentMessagePipe(primordial_pipe_token_), 0u)); | |
| 55 } | 54 } |
| 56 | 55 |
| 57 ChildProcessHost::ChildProcessHost(ScopedHandle channel) | 56 ChildProcessHost::ChildProcessHost(mojom::ShellClientFactoryPtr factory) |
| 58 : external_process_(true), | 57 : external_process_(true), |
| 59 launch_process_runner_(nullptr), | 58 factory_(std::move(factory)), |
| 60 delegate_(nullptr), | |
| 61 start_sandboxed_(false), | |
| 62 start_child_process_event_(false, false), | 59 start_child_process_event_(false, false), |
| 63 weak_factory_(this) { | 60 weak_factory_(this) {} |
| 64 CHECK(channel.is_valid()); | |
| 65 ScopedMessagePipeHandle handle(MessagePipeHandle(channel.release().value())); | |
| 66 controller_.Bind( | |
| 67 InterfacePtrInfo<mojom::ChildController>(std::move(handle), 0u)); | |
| 68 } | |
| 69 | 61 |
| 70 ChildProcessHost::~ChildProcessHost() { | 62 ChildProcessHost::~ChildProcessHost() { |
| 71 if (!app_path_.empty()) | 63 if (!app_path_.empty()) |
| 72 CHECK(!controller_) << "Destroying ChildProcessHost before calling Join"; | 64 CHECK(!factory_) << "Destroying ChildProcessHost before calling Join"; |
| 73 } | 65 } |
| 74 | 66 |
| 75 void ChildProcessHost::Start(const ProcessReadyCallback& callback) { | 67 void ChildProcessHost::Start(const ProcessReadyCallback& callback) { |
| 76 DCHECK(!external_process_); | 68 DCHECK(!external_process_); |
| 77 DCHECK(!child_process_.IsValid()); | 69 DCHECK(!child_process_.IsValid()); |
| 78 launch_process_runner_->PostTaskAndReply( | 70 launch_process_runner_->PostTaskAndReply( |
| 79 FROM_HERE, | 71 FROM_HERE, |
| 80 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), | 72 base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), |
| 81 base::Bind(&ChildProcessHost::DidStart, | 73 base::Bind(&ChildProcessHost::DidStart, |
| 82 weak_factory_.GetWeakPtr(), callback)); | 74 weak_factory_.GetWeakPtr(), callback)); |
| 83 } | 75 } |
| 84 | 76 |
| 85 int ChildProcessHost::Join() { | 77 void ChildProcessHost::Join() { |
| 86 if (controller_ && !external_process_) | 78 if (factory_ && !external_process_) |
| 87 start_child_process_event_.Wait(); | 79 start_child_process_event_.Wait(); |
| 88 | 80 |
| 89 controller_ = mojom::ChildControllerPtr(); | 81 factory_.reset(); |
| 90 | 82 |
| 91 // This host may be hosting a child process whose lifetime is controlled | 83 // This host may be hosting a child process whose lifetime is controlled |
| 92 // elsewhere. In this case we have no known process handle to wait on. | 84 // elsewhere. In this case we have no known process handle to wait on. |
| 93 if (child_process_.IsValid()) { | 85 if (child_process_.IsValid()) { |
| 94 int rv = -1; | 86 int rv = -1; |
| 95 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) | 87 LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) |
| 96 << "Failed to wait for child process"; | 88 << "Failed to wait for child process"; |
| 97 | 89 |
| 98 child_process_.Close(); | 90 child_process_.Close(); |
| 99 return rv; | |
| 100 } | 91 } |
| 101 | |
| 102 return 0; | |
| 103 } | 92 } |
| 104 | 93 |
| 105 void ChildProcessHost::StartApp( | 94 void ChildProcessHost::StartChild(mojom::ShellClientRequest request, |
| 106 InterfaceRequest<mojom::ShellClient> request, | 95 const String& name, |
| 107 const mojom::ChildController::StartAppCallback& on_app_complete) { | 96 const base::Closure& quit_closure) { |
| 108 DCHECK(controller_); | 97 DCHECK(factory_); |
| 109 on_app_complete_ = on_app_complete; | 98 factory_->CreateShellClient(std::move(request), name); |
| 110 controller_->StartApp( | 99 factory_.set_connection_error_handler(quit_closure); |
| 111 std::move(request), | |
| 112 base::Bind(&ChildProcessHost::AppCompleted, weak_factory_.GetWeakPtr())); | |
| 113 } | |
| 114 | |
| 115 void ChildProcessHost::ExitNow(int32_t exit_code) { | |
| 116 DCHECK(controller_); | |
| 117 | |
| 118 controller_->ExitNow(exit_code); | |
| 119 } | 100 } |
| 120 | 101 |
| 121 void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) { | 102 void ChildProcessHost::DidStart(const ProcessReadyCallback& callback) { |
| 122 DVLOG(2) << "ChildProcessHost::DidStart()"; | |
| 123 | |
| 124 if (child_process_.IsValid()) { | 103 if (child_process_.IsValid()) { |
| 125 callback.Run(child_process_.Pid()); | 104 callback.Run(child_process_.Pid()); |
| 126 } else { | 105 } else { |
| 127 LOG(ERROR) << "Failed to start child process"; | 106 LOG(ERROR) << "Failed to start child process"; |
| 128 AppCompleted(MOJO_RESULT_UNKNOWN); | 107 factory_.reset(); |
| 129 } | 108 } |
| 130 } | 109 } |
| 131 | 110 |
| 132 void ChildProcessHost::DoLaunch() { | 111 void ChildProcessHost::DoLaunch() { |
| 133 DCHECK(!external_process_); | 112 DCHECK(!external_process_); |
| 134 | 113 |
| 135 const base::CommandLine* parent_command_line = | 114 const base::CommandLine* parent_command_line = |
| 136 base::CommandLine::ForCurrentProcess(); | 115 base::CommandLine::ForCurrentProcess(); |
| 137 base::FilePath target_path = parent_command_line->GetProgram(); | 116 base::FilePath target_path = parent_command_line->GetProgram(); |
| 138 // |app_path_| can be empty in tests. | 117 // |app_path_| can be empty in tests. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 node_channel_->ChildProcessLaunched(); | 201 node_channel_->ChildProcessLaunched(); |
| 223 mojo::edk::ChildProcessLaunched( | 202 mojo::edk::ChildProcessLaunched( |
| 224 child_process_.Handle(), | 203 child_process_.Handle(), |
| 225 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( | 204 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle( |
| 226 node_channel_->PassServerHandle().release().handle))); | 205 node_channel_->PassServerHandle().release().handle))); |
| 227 } | 206 } |
| 228 } | 207 } |
| 229 start_child_process_event_.Signal(); | 208 start_child_process_event_.Signal(); |
| 230 } | 209 } |
| 231 | 210 |
| 232 void ChildProcessHost::AppCompleted(int32_t result) { | |
| 233 if (!on_app_complete_.is_null()) { | |
| 234 auto on_app_complete = on_app_complete_; | |
| 235 on_app_complete_.reset(); | |
| 236 on_app_complete.Run(result); | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 } // namespace shell | 211 } // namespace shell |
| 241 } // namespace mojo | 212 } // namespace mojo |
| OLD | NEW |