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

Side by Side Diff: mojo/edk/system/child_broker.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.h ('k') | mojo/edk/system/child_broker_host.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.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/logging.h"
14 #include "mojo/edk/embedder/embedder_internal.h"
15 #include "mojo/edk/embedder/platform_channel_pair.h"
16 #include "mojo/edk/system/broker_messages.h"
17 #include "mojo/edk/system/message_pipe_dispatcher.h"
18
19 namespace mojo {
20 namespace edk {
21
22 ChildBroker* ChildBroker::GetInstance() {
23 return base::Singleton<
24 ChildBroker, base::LeakySingletonTraits<ChildBroker>>::get();
25 }
26
27 void ChildBroker::SetChildBrokerHostHandle(ScopedPlatformHandle handle) {
28 ScopedPlatformHandle parent_async_channel_handle;
29 #if defined(OS_POSIX)
30 parent_async_channel_handle = std::move(handle);
31 #else
32 // On Windows we have two pipes to the parent. The first is for the token
33 // exchange for creating and passing handles, since the child needs the
34 // parent's help if it is sandboxed. The second is the same as POSIX, which is
35 // used for multiplexing related messages. So on Windows, we send the second
36 // pipe as the first string over the first one.
37 parent_sync_channel_ = std::move(handle);
38
39 HANDLE parent_handle = INVALID_HANDLE_VALUE;
40 DWORD bytes_read = 0;
41 BOOL rv = ReadFile(parent_sync_channel_.get().handle, &parent_handle,
42 sizeof(parent_handle), &bytes_read, NULL);
43 CHECK(rv);
44 parent_async_channel_handle.reset(PlatformHandle(parent_handle));
45 sync_channel_lock_.Unlock();
46 #endif
47
48 internal::g_io_thread_task_runner->PostTask(
49 FROM_HERE,
50 base::Bind(&ChildBroker::InitAsyncChannel, base::Unretained(this),
51 base::Passed(&parent_async_channel_handle)));
52 }
53
54 #if defined(OS_WIN)
55 void ChildBroker::CreatePlatformChannelPair(
56 ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
57 sync_channel_lock_.Lock();
58 CreatePlatformChannelPairNoLock(server, client);
59 sync_channel_lock_.Unlock();
60 }
61
62 void ChildBroker::HandleToToken(const PlatformHandle* platform_handles,
63 size_t count,
64 uint64_t* tokens) {
65 uint32_t size = kBrokerMessageHeaderSize +
66 static_cast<int>(count) * sizeof(HANDLE);
67 std::vector<char> message_buffer(size);
68 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(&message_buffer[0]);
69 message->size = size;
70 message->id = HANDLE_TO_TOKEN;
71 for (size_t i = 0; i < count; ++i)
72 message->handles[i] = platform_handles[i].handle;
73
74 uint32_t response_size = static_cast<int>(count) * sizeof(uint64_t);
75 sync_channel_lock_.Lock();
76 WriteAndReadResponse(message, tokens, response_size);
77 sync_channel_lock_.Unlock();
78 }
79
80 void ChildBroker::TokenToHandle(const uint64_t* tokens,
81 size_t count,
82 PlatformHandle* handles) {
83 uint32_t size = kBrokerMessageHeaderSize +
84 static_cast<int>(count) * sizeof(uint64_t);
85 std::vector<char> message_buffer(size);
86 BrokerMessage* message =
87 reinterpret_cast<BrokerMessage*>(&message_buffer[0]);
88 message->size = size;
89 message->id = TOKEN_TO_HANDLE;
90 memcpy(&message->tokens[0], tokens, count * sizeof(uint64_t));
91
92 std::vector<HANDLE> handles_temp(count);
93 uint32_t response_size =
94 static_cast<uint32_t>(handles_temp.size()) * sizeof(HANDLE);
95 sync_channel_lock_.Lock();
96 if (WriteAndReadResponse(message, &handles_temp[0], response_size)) {
97 for (uint32_t i = 0; i < count; ++i)
98 handles[i].handle = handles_temp[i];
99 sync_channel_lock_.Unlock();
100 }
101 }
102 #endif
103
104 void ChildBroker::ConnectMessagePipe(uint64_t pipe_id,
105 MessagePipeDispatcher* message_pipe) {
106 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
107
108 ConnectMessagePipeMessage data;
109 memset(&data, 0, sizeof(data));
110 data.pipe_id = pipe_id;
111 if (pending_connects_.find(pipe_id) != pending_connects_.end()) {
112 if (!parent_async_channel_) {
113 // On Windows, we can't create the local RoutedRawChannel yet because we
114 // don't have parent_sync_channel_. Treat all platforms the same and just
115 // queue this.
116 CHECK(pending_inprocess_connects_.find(pipe_id) ==
117 pending_inprocess_connects_.end());
118 pending_inprocess_connects_[pipe_id] = message_pipe;
119 return;
120 }
121 // Both ends of the message pipe are in the same process.
122 // First, tell the browser side that to remove its bookkeeping for a pending
123 // connect, since it'll never get the other side.
124
125 data.type = CANCEL_CONNECT_MESSAGE_PIPE;
126 scoped_ptr<MessageInTransit> message(new MessageInTransit(
127 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
128 WriteAsyncMessage(std::move(message));
129
130 if (!in_process_pipes_channel1_) {
131 ScopedPlatformHandle server_handle, client_handle;
132 #if defined(OS_WIN)
133 CreatePlatformChannelPairNoLock(&server_handle, &client_handle);
134 #else
135 PlatformChannelPair channel_pair;
136 server_handle = channel_pair.PassServerHandle();
137 client_handle = channel_pair.PassClientHandle();
138 #endif
139 in_process_pipes_channel1_ = new RoutedRawChannel(
140 std::move(server_handle),
141 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
142 in_process_pipes_channel2_ = new RoutedRawChannel(
143 std::move(client_handle),
144 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
145 }
146
147 AttachMessagePipe(pending_connects_[pipe_id], pipe_id,
148 in_process_pipes_channel1_);
149 AttachMessagePipe(message_pipe, pipe_id, in_process_pipes_channel2_);
150 pending_connects_.erase(pipe_id);
151 return;
152 }
153
154 data.type = CONNECT_MESSAGE_PIPE;
155 scoped_ptr<MessageInTransit> message(new MessageInTransit(
156 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
157 pending_connects_[pipe_id] = message_pipe;
158 WriteAsyncMessage(std::move(message));
159 }
160
161 void ChildBroker::CloseMessagePipe(
162 uint64_t pipe_id, MessagePipeDispatcher* message_pipe) {
163 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
164 CHECK(connected_pipes_.find(message_pipe) != connected_pipes_.end());
165 connected_pipes_[message_pipe]->RemoveRoute(pipe_id);
166 connected_pipes_.erase(message_pipe);
167 }
168
169 ChildBroker::ChildBroker()
170 : parent_async_channel_(nullptr),
171 in_process_pipes_channel1_(nullptr),
172 in_process_pipes_channel2_(nullptr) {
173 DCHECK(!internal::g_broker);
174 internal::g_broker = this;
175 #if defined(OS_WIN)
176 // Block any threads from calling this until we have a pipe to the parent.
177 sync_channel_lock_.Lock();
178 #endif
179 }
180
181 ChildBroker::~ChildBroker() {
182 }
183
184 void ChildBroker::OnReadMessage(
185 const MessageInTransit::View& message_view,
186 ScopedPlatformHandleVectorPtr platform_handles) {
187 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
188 MultiplexMessages type =
189 *static_cast<const MultiplexMessages*>(message_view.bytes());
190 if (type == CONNECT_TO_PROCESS) {
191 DCHECK_EQ(platform_handles->size(), 1u);
192 ScopedPlatformHandle handle((*platform_handles.get())[0]);
193 (*platform_handles.get())[0] = PlatformHandle();
194
195 const ConnectToProcessMessage* message =
196 static_cast<const ConnectToProcessMessage*>(message_view.bytes());
197
198 CHECK(channels_.find(message->process_id) == channels_.end());
199 channels_[message->process_id] = new RoutedRawChannel(
200 std::move(handle),
201 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
202 } else if (type == PEER_PIPE_CONNECTED) {
203 DCHECK(!platform_handles);
204 const PeerPipeConnectedMessage* message =
205 static_cast<const PeerPipeConnectedMessage*>(message_view.bytes());
206
207 uint64_t pipe_id = message->pipe_id;
208 uint64_t peer_pid = message->process_id;
209
210 CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
211 MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
212 pending_connects_.erase(pipe_id);
213 if (peer_pid == 0) {
214 // The other side is in the parent process.
215 AttachMessagePipe(pipe, pipe_id, parent_async_channel_);
216 } else if (channels_.find(peer_pid) == channels_.end()) {
217 // We saw the peer process die before we got the reply from the parent.
218 pipe->OnError(ERROR_READ_SHUTDOWN);
219 } else {
220 CHECK(connected_pipes_.find(pipe) == connected_pipes_.end());
221 AttachMessagePipe(pipe, pipe_id, channels_[peer_pid]);
222 }
223 } else if (type == PEER_DIED) {
224 DCHECK(!platform_handles);
225 const PeerDiedMessage* message =
226 static_cast<const PeerDiedMessage*>(message_view.bytes());
227
228 uint64_t pipe_id = message->pipe_id;
229
230 CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
231 MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
232 pending_connects_.erase(pipe_id);
233 pipe->OnError(ERROR_READ_SHUTDOWN);
234 } else {
235 NOTREACHED();
236 }
237 }
238
239 void ChildBroker::OnError(Error error) {
240 // The parent process shut down.
241 }
242
243 void ChildBroker::ChannelDestructed(RoutedRawChannel* channel) {
244 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
245 for (auto it : channels_) {
246 if (it.second == channel) {
247 channels_.erase(it.first);
248 break;
249 }
250 }
251 }
252
253 void ChildBroker::WriteAsyncMessage(scoped_ptr<MessageInTransit> message) {
254 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
255 message->set_route_id(kBrokerRouteId);
256 if (parent_async_channel_) {
257 parent_async_channel_->channel()->WriteMessage(std::move(message));
258 } else {
259 async_channel_queue_.AddMessage(std::move(message));
260 }
261 }
262
263 void ChildBroker::InitAsyncChannel(
264 ScopedPlatformHandle parent_async_channel_handle) {
265 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
266
267 parent_async_channel_ = new RoutedRawChannel(
268 std::move(parent_async_channel_handle),
269 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
270 parent_async_channel_->AddRoute(kBrokerRouteId, this);
271 while (!async_channel_queue_.IsEmpty()) {
272 parent_async_channel_->channel()->WriteMessage(
273 async_channel_queue_.GetMessage());
274 }
275
276 while (!pending_inprocess_connects_.empty()) {
277 ConnectMessagePipe(pending_inprocess_connects_.begin()->first,
278 pending_inprocess_connects_.begin()->second);
279 pending_inprocess_connects_.erase(pending_inprocess_connects_.begin());
280 }
281 }
282
283 void ChildBroker::AttachMessagePipe(MessagePipeDispatcher* message_pipe,
284 uint64_t pipe_id,
285 RoutedRawChannel* raw_channel) {
286 connected_pipes_[message_pipe] = raw_channel;
287 // Note: we must call GotNonTransferableChannel before AddRoute because there
288 // could be race conditions if the pipe got queued messages in |AddRoute| but
289 // then when it's read it returns no messages because it doesn't have the
290 // channel yet.
291 message_pipe->GotNonTransferableChannel(raw_channel->channel());
292 // The above call could have caused |CloseMessagePipe| to be called.
293 if (connected_pipes_.find(message_pipe) != connected_pipes_.end())
294 raw_channel->AddRoute(pipe_id, message_pipe);
295 }
296
297 #if defined(OS_WIN)
298
299 bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
300 void* response,
301 uint32_t response_size) {
302 CHECK(parent_sync_channel_.is_valid());
303
304 bool result = true;
305 DWORD bytes_written = 0;
306 // This will always write in one chunk per
307 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150.aspx.
308 BOOL rv = WriteFile(parent_sync_channel_.get().handle, message, message->size,
309 &bytes_written, NULL);
310 if (!rv || bytes_written != message->size) {
311 LOG(ERROR) << "Child token serializer couldn't write message.";
312 result = false;
313 } else {
314 while (response_size) {
315 DWORD bytes_read = 0;
316 rv = ReadFile(parent_sync_channel_.get().handle, response, response_size,
317 &bytes_read, NULL);
318 if (!rv) {
319 LOG(ERROR) << "Child token serializer couldn't read result.";
320 result = false;
321 break;
322 }
323 response_size -= bytes_read;
324 response = static_cast<char*>(response) + bytes_read;
325 }
326 }
327
328 return result;
329 }
330
331 void ChildBroker::CreatePlatformChannelPairNoLock(
332 ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
333 BrokerMessage message;
334 message.size = kBrokerMessageHeaderSize;
335 message.id = CREATE_PLATFORM_CHANNEL_PAIR;
336
337 uint32_t response_size = 2 * sizeof(HANDLE);
338 HANDLE handles[2];
339 if (WriteAndReadResponse(&message, handles, response_size)) {
340 server->reset(PlatformHandle(handles[0]));
341 client->reset(PlatformHandle(handles[1]));
342 }
343 }
344
345 #endif
346
347 } // namespace edk
348 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/child_broker.h ('k') | mojo/edk/system/child_broker_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698