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

Side by Side Diff: mojo/edk/system/child_broker_host.cc

Issue 1649633002: Remove files that are no longer used in the Port EDK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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
« no previous file with comments | « mojo/edk/system/child_broker_host.h ('k') | mojo/edk/system/message_in_transit.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/edk/system/child_broker_host.h"
6
7 #include <stdint.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/lazy_instance.h"
13 #include "mojo/edk/embedder/embedder_internal.h"
14 #include "mojo/edk/embedder/platform_channel_pair.h"
15 #include "mojo/edk/system/broker_messages.h"
16 #include "mojo/edk/system/broker_state.h"
17 #include "mojo/edk/system/configuration.h"
18 #include "mojo/edk/system/core.h"
19 #include "mojo/edk/system/platform_handle_dispatcher.h"
20
21 namespace mojo {
22 namespace edk {
23
24 namespace {
25 #if defined(OS_WIN)
26 static const int kDefaultReadBufferSize = 256;
27 #endif
28 }
29
30 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process,
31 ScopedPlatformHandle pipe)
32 : process_id_(base::GetProcId(child_process)), child_channel_(nullptr) {
33 ScopedPlatformHandle parent_async_channel_handle;
34 #if defined(OS_POSIX)
35 parent_async_channel_handle = std::move(pipe);
36 #else
37 DuplicateHandle(GetCurrentProcess(), child_process,
38 GetCurrentProcess(), &child_process,
39 0, FALSE, DUPLICATE_SAME_ACCESS);
40 child_process_ = base::Process(child_process);
41 sync_channel_ = std::move(pipe);
42 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
43 read_context_.handler = this;
44 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
45 write_context_.handler = this;
46 read_data_.resize(kDefaultReadBufferSize);
47 num_bytes_read_ = 0;
48
49 // See comment in ChildBroker::SetChildBrokerHostHandle. Summary is we need
50 // two pipes on Windows, so send the second one over the first one.
51 PlatformChannelPair parent_pipe;
52 parent_async_channel_handle = parent_pipe.PassServerHandle();
53
54 HANDLE duplicated_child_handle =
55 DuplicateToChild(parent_pipe.PassClientHandle().release().handle);
56 BOOL rv = WriteFile(sync_channel_.get().handle,
57 &duplicated_child_handle, sizeof(duplicated_child_handle),
58 NULL, &write_context_.overlapped);
59 DCHECK(rv || GetLastError() == ERROR_IO_PENDING);
60 #endif
61
62 internal::g_io_thread_task_runner->PostTask(
63 FROM_HERE,
64 base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this),
65 base::Passed(&parent_async_channel_handle)));
66 }
67
68 base::ProcessId ChildBrokerHost::GetProcessId() {
69 return process_id_;
70 }
71
72 void ChildBrokerHost::ConnectToProcess(base::ProcessId process_id,
73 ScopedPlatformHandle pipe) {
74 if (!child_channel_)
75 return; // Can happen at process shutdown on Windows.
76 ConnectToProcessMessage data;
77 memset(&data, 0, sizeof(data));
78 data.type = CONNECT_TO_PROCESS;
79 data.process_id = process_id;
80 scoped_ptr<MessageInTransit> message(new MessageInTransit(
81 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
82 scoped_refptr<Dispatcher> dispatcher =
83 PlatformHandleDispatcher::Create(std::move(pipe));
84 internal::g_core->AddDispatcher(dispatcher);
85 scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector);
86 dispatchers->push_back(dispatcher);
87 message->SetDispatchers(std::move(dispatchers));
88 message->SerializeAndCloseDispatchers();
89 message->set_route_id(kBrokerRouteId);
90 child_channel_->channel()->WriteMessage(std::move(message));
91 }
92
93 void ChildBrokerHost::ConnectMessagePipe(uint64_t pipe_id,
94 base::ProcessId process_id) {
95 if (!child_channel_)
96 return; // Can happen at process shutdown on Windows.
97 PeerPipeConnectedMessage data;
98 memset(&data, 0, sizeof(data));
99 data.type = PEER_PIPE_CONNECTED;
100 data.pipe_id = pipe_id;
101 data.process_id = process_id;
102 scoped_ptr<MessageInTransit> message(new MessageInTransit(
103 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
104 message->set_route_id(kBrokerRouteId);
105 child_channel_->channel()->WriteMessage(std::move(message));
106 }
107
108 void ChildBrokerHost::PeerDied(uint64_t pipe_id) {
109 if (!child_channel_)
110 return; // Can happen at process shutdown on Windows.
111 PeerDiedMessage data;
112 memset(&data, 0, sizeof(data));
113 data.type = PEER_DIED;
114 data.pipe_id = pipe_id;
115 scoped_ptr<MessageInTransit> message(new MessageInTransit(
116 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
117 message->set_route_id(kBrokerRouteId);
118 child_channel_->channel()->WriteMessage(std::move(message));
119 }
120
121 ChildBrokerHost::~ChildBrokerHost() {
122 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
123 BrokerState::GetInstance()->ChildBrokerHostDestructed(this);
124 if (child_channel_)
125 child_channel_->RemoveRoute(kBrokerRouteId);
126 }
127
128 void ChildBrokerHost::InitOnIO(
129 ScopedPlatformHandle parent_async_channel_handle) {
130 child_channel_ = new RoutedRawChannel(
131 std::move(parent_async_channel_handle),
132 base::Bind(&ChildBrokerHost::ChannelDestructed, base::Unretained(this)));
133 child_channel_->AddRoute(kBrokerRouteId, this);
134
135 BrokerState::GetInstance()->ChildBrokerHostCreated(this);
136
137 #if defined(OS_WIN)
138 // Call this after RoutedRawChannel calls its RawChannel::Init because this
139 // call could cause us to get notified that the child has gone away and to
140 // delete this class and shut down child_channel_ before Init() has run.
141 base::MessageLoopForIO::current()->RegisterIOHandler(
142 sync_channel_.get().handle, this);
143 BeginRead();
144 #endif
145 }
146
147 void ChildBrokerHost::OnReadMessage(
148 const MessageInTransit::View& message_view,
149 ScopedPlatformHandleVectorPtr platform_handles) {
150 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
151 CHECK(!platform_handles);
152 if (message_view.num_bytes() !=
153 static_cast<uint32_t>(sizeof(ConnectMessagePipeMessage))) {
154 NOTREACHED();
155 delete this;
156 }
157
158 const ConnectMessagePipeMessage* message =
159 static_cast<const ConnectMessagePipeMessage*>(message_view.bytes());
160 switch(message->type) {
161 case CONNECT_MESSAGE_PIPE:
162 BrokerState::GetInstance()->HandleConnectMessagePipe(this,
163 message->pipe_id);
164 break;
165 case CANCEL_CONNECT_MESSAGE_PIPE:
166 BrokerState::GetInstance()->HandleCancelConnectMessagePipe(
167 message->pipe_id);
168 break;
169 default:
170 NOTREACHED();
171 delete this;
172 }
173 }
174
175 void ChildBrokerHost::OnError(Error error) {
176 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
177 child_channel_->RemoveRoute(kBrokerRouteId);
178 child_channel_ = nullptr;
179 }
180
181 void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) {
182 // On Windows, we have two pipes to the child process. It's easier to wait
183 // until we get the error from the pipe that is used for synchronous I/O.
184 #if !defined(OS_WIN)
185 delete this;
186 #endif
187 }
188
189 #if defined(OS_WIN)
190 void ChildBrokerHost::BeginRead() {
191 BOOL rv = ReadFile(sync_channel_.get().handle,
192 &read_data_[num_bytes_read_],
193 static_cast<int>(read_data_.size() - num_bytes_read_),
194 nullptr, &read_context_.overlapped);
195 if (rv || GetLastError() == ERROR_IO_PENDING)
196 return;
197
198 if (GetLastError() == ERROR_BROKEN_PIPE) {
199 delete this;
200 return;
201 }
202
203 NOTREACHED() << "Unknown error in ChildBrokerHost " << rv;
204 }
205
206 void ChildBrokerHost::OnIOCompleted(base::MessageLoopForIO::IOContext* context,
207 DWORD bytes_transferred,
208 DWORD error) {
209 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
210 if (error == ERROR_BROKEN_PIPE) {
211 delete this;
212 return; // Child process exited or crashed.
213 }
214
215 if (error != ERROR_SUCCESS) {
216 NOTREACHED() << "Error " << error << " in ChildBrokerHost.";
217 delete this;
218 return;
219 }
220
221 if (context == &write_context_) {
222 write_data_.clear();
223 return;
224 }
225
226 num_bytes_read_ += bytes_transferred;
227 CHECK_GE(num_bytes_read_, sizeof(uint32_t));
228 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(&read_data_[0]);
229 if (num_bytes_read_ < message->size) {
230 read_data_.resize(message->size);
231 BeginRead();
232 return;
233 }
234
235 // This should never fire because we only get new requests from a child
236 // process after it has read all the previous data we wrote.
237 if (!write_data_.empty()) {
238 NOTREACHED() << "ChildBrokerHost shouldn't have data to write when it gets "
239 << " a new request";
240 delete this;
241 return;
242 }
243
244 if (message->id == CREATE_PLATFORM_CHANNEL_PAIR) {
245 PlatformChannelPair channel_pair;
246 uint32_t response_size = 2 * sizeof(HANDLE);
247 write_data_.resize(response_size);
248 HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]);
249 handles[0] = DuplicateToChild(
250 channel_pair.PassServerHandle().release().handle);
251 handles[1] = DuplicateToChild(
252 channel_pair.PassClientHandle().release().handle);
253 } else if (message->id == HANDLE_TO_TOKEN) {
254 uint32_t count =
255 (message->size - kBrokerMessageHeaderSize) / sizeof(HANDLE);
256 if (count > GetConfiguration().max_message_num_handles) {
257 NOTREACHED() << "Too many handles from child process. Closing channel.";
258 delete this;
259 return;
260 }
261 uint32_t response_size = count * sizeof(uint64_t);
262 write_data_.resize(response_size);
263 uint64_t* tokens = reinterpret_cast<uint64_t*>(&write_data_[0]);
264 std::vector<PlatformHandle> duplicated_handles(count);
265 for (uint32_t i = 0; i < count; ++i) {
266 duplicated_handles[i] =
267 PlatformHandle(DuplicateFromChild(message->handles[i]));
268 }
269 BrokerState::GetInstance()->HandleToToken(
270 &duplicated_handles[0], count, tokens);
271 } else if (message->id == TOKEN_TO_HANDLE) {
272 uint32_t count =
273 (message->size - kBrokerMessageHeaderSize) / sizeof(uint64_t);
274 if (count > GetConfiguration().max_message_num_handles) {
275 NOTREACHED() << "Too many tokens from child process. Closing channel.";
276 delete this;
277 return;
278 }
279 uint32_t response_size = count * sizeof(HANDLE);
280 write_data_.resize(response_size);
281 HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]);
282 std::vector<PlatformHandle> temp_handles(count);
283 BrokerState::GetInstance()->TokenToHandle(
284 &message->tokens[0], count, &temp_handles[0]);
285 for (uint32_t i = 0; i < count; ++i) {
286 if (temp_handles[i].is_valid()) {
287 handles[i] = DuplicateToChild(temp_handles[i].handle);
288 } else {
289 NOTREACHED() << "Unknown token";
290 handles[i] = INVALID_HANDLE_VALUE;
291 }
292 }
293 } else {
294 NOTREACHED() << "Unknown command. Stopping reading.";
295 delete this;
296 return;
297 }
298
299 BOOL rv = WriteFile(sync_channel_.get().handle, &write_data_[0],
300 static_cast<int>(write_data_.size()), NULL,
301 &write_context_.overlapped);
302 DCHECK(rv || GetLastError() == ERROR_IO_PENDING);
303
304 // Start reading again.
305 num_bytes_read_ = 0;
306 BeginRead();
307 }
308
309 HANDLE ChildBrokerHost::DuplicateToChild(HANDLE handle) {
310 HANDLE rv = INVALID_HANDLE_VALUE;
311 BOOL result = DuplicateHandle(base::GetCurrentProcessHandle(), handle,
312 child_process_.Handle(), &rv, 0, FALSE,
313 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
314 DCHECK(result);
315 return rv;
316 }
317
318 HANDLE ChildBrokerHost::DuplicateFromChild(HANDLE handle) {
319 HANDLE rv = INVALID_HANDLE_VALUE;
320 BOOL result = DuplicateHandle(child_process_.Handle(), handle,
321 base::GetCurrentProcessHandle(), &rv, 0, FALSE,
322 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
323 DCHECK(result);
324 return rv;
325 }
326 #endif
327
328 } // namespace edk
329 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/child_broker_host.h ('k') | mojo/edk/system/message_in_transit.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698