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 |