OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/edk/system/node_channel.h" | 5 #include "mojo/edk/system/node_channel.h" |
6 | 6 |
7 #include <cstring> | 7 #include <cstring> |
8 #include <limits> | 8 #include <limits> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
| 11 #include "base/bind.h" |
| 12 #include "base/location.h" |
11 #include "base/logging.h" | 13 #include "base/logging.h" |
12 #include "mojo/edk/system/channel.h" | 14 #include "mojo/edk/system/channel.h" |
13 | 15 |
| 16 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 17 #include "mojo/edk/system/mach_port_relay.h" |
| 18 #endif |
| 19 |
14 namespace mojo { | 20 namespace mojo { |
15 namespace edk { | 21 namespace edk { |
16 | 22 |
17 namespace { | 23 namespace { |
18 | 24 |
19 template <typename T> | 25 template <typename T> |
20 T Align(T t) { | 26 T Align(T t) { |
21 const auto k = kChannelMessageAlignment; | 27 const auto k = kChannelMessageAlignment; |
22 return t + (k - (t % k)) % k; | 28 return t + (k - (t % k)) % k; |
23 } | 29 } |
24 | 30 |
25 enum class MessageType : uint32_t { | 31 enum class MessageType : uint32_t { |
26 ACCEPT_CHILD, | 32 ACCEPT_CHILD, |
27 ACCEPT_PARENT, | 33 ACCEPT_PARENT, |
28 ADD_BROKER_CLIENT, | 34 ADD_BROKER_CLIENT, |
29 BROKER_CLIENT_ADDED, | 35 BROKER_CLIENT_ADDED, |
30 ACCEPT_BROKER_CLIENT, | 36 ACCEPT_BROKER_CLIENT, |
31 PORTS_MESSAGE, | 37 PORTS_MESSAGE, |
32 REQUEST_PORT_MERGE, | 38 REQUEST_PORT_MERGE, |
33 REQUEST_INTRODUCTION, | 39 REQUEST_INTRODUCTION, |
34 INTRODUCE, | 40 INTRODUCE, |
35 #if defined(OS_WIN) | 41 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
36 RELAY_PORTS_MESSAGE, | 42 RELAY_PORTS_MESSAGE, |
37 #endif | 43 #endif |
38 }; | 44 }; |
39 | 45 |
40 struct Header { | 46 struct Header { |
41 MessageType type; | 47 MessageType type; |
42 uint32_t padding; | 48 uint32_t padding; |
43 }; | 49 }; |
44 | 50 |
45 static_assert(sizeof(Header) % kChannelMessageAlignment == 0, | 51 static_assert(sizeof(Header) % kChannelMessageAlignment == 0, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 // Used for both REQUEST_INTRODUCTION and INTRODUCE. | 97 // Used for both REQUEST_INTRODUCTION and INTRODUCE. |
92 // | 98 // |
93 // For INTRODUCE the message also includes a valid platform handle for a channel | 99 // For INTRODUCE the message also includes a valid platform handle for a channel |
94 // the receiver may use to communicate with the named node directly, or an | 100 // the receiver may use to communicate with the named node directly, or an |
95 // invalid platform handle if the node is unknown to the sender or otherwise | 101 // invalid platform handle if the node is unknown to the sender or otherwise |
96 // cannot be introduced. | 102 // cannot be introduced. |
97 struct IntroductionData { | 103 struct IntroductionData { |
98 ports::NodeName name; | 104 ports::NodeName name; |
99 }; | 105 }; |
100 | 106 |
101 #if defined(OS_WIN) | 107 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
102 // This struct is followed by the full payload of a message to be relayed. | 108 // This struct is followed by the full payload of a message to be relayed. |
103 struct RelayPortsMessageData { | 109 struct RelayPortsMessageData { |
104 ports::NodeName destination; | 110 ports::NodeName destination; |
105 }; | 111 }; |
106 #endif | 112 #endif |
107 | 113 |
108 template <typename DataType> | 114 template <typename DataType> |
109 Channel::MessagePtr CreateMessage(MessageType type, | 115 Channel::MessagePtr CreateMessage(MessageType type, |
110 size_t payload_size, | 116 size_t payload_size, |
111 size_t num_handles, | 117 size_t num_handles, |
112 DataType** out_data) { | 118 DataType** out_data) { |
113 Channel::MessagePtr message( | 119 Channel::MessagePtr message( |
114 new Channel::Message(sizeof(Header) + payload_size, num_handles)); | 120 new Channel::Message(sizeof(Header) + payload_size, num_handles)); |
115 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); | 121 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); |
116 header->type = type; | 122 header->type = type; |
117 header->padding = 0; | 123 header->padding = 0; |
118 *out_data = reinterpret_cast<DataType*>(&header[1]); | 124 *out_data = reinterpret_cast<DataType*>(&header[1]); |
119 return message; | 125 return message; |
120 }; | 126 } |
121 | 127 |
122 template <typename DataType> | 128 template <typename DataType> |
123 void GetMessagePayload(const void* bytes, DataType** out_data) { | 129 void GetMessagePayload(const void* bytes, DataType** out_data) { |
124 *out_data = reinterpret_cast<const DataType*>( | 130 *out_data = reinterpret_cast<const DataType*>( |
125 static_cast<const char*>(bytes) + sizeof(Header)); | 131 static_cast<const char*>(bytes) + sizeof(Header)); |
126 } | 132 } |
127 | 133 |
128 } // namespace | 134 } // namespace |
129 | 135 |
130 // static | 136 // static |
(...skipping 14 matching lines...) Expand all Loading... |
145 | 151 |
146 // static | 152 // static |
147 void NodeChannel::GetPortsMessageData(Channel::Message* message, | 153 void NodeChannel::GetPortsMessageData(Channel::Message* message, |
148 void** data, | 154 void** data, |
149 size_t* num_data_bytes) { | 155 size_t* num_data_bytes) { |
150 *data = reinterpret_cast<Header*>(message->mutable_payload()) + 1; | 156 *data = reinterpret_cast<Header*>(message->mutable_payload()) + 1; |
151 *num_data_bytes = message->payload_size() - sizeof(Header); | 157 *num_data_bytes = message->payload_size() - sizeof(Header); |
152 } | 158 } |
153 | 159 |
154 void NodeChannel::Start() { | 160 void NodeChannel::Start() { |
| 161 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 162 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 163 if (relay) |
| 164 relay->AddObserver(this); |
| 165 #endif |
| 166 |
155 base::AutoLock lock(channel_lock_); | 167 base::AutoLock lock(channel_lock_); |
156 DCHECK(channel_); | 168 DCHECK(channel_); |
157 channel_->Start(); | 169 channel_->Start(); |
158 } | 170 } |
159 | 171 |
160 void NodeChannel::ShutDown() { | 172 void NodeChannel::ShutDown() { |
| 173 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 174 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 175 if (relay) |
| 176 relay->RemoveObserver(this); |
| 177 #endif |
| 178 |
161 base::AutoLock lock(channel_lock_); | 179 base::AutoLock lock(channel_lock_); |
162 if (channel_) { | 180 if (channel_) { |
163 channel_->ShutDown(); | 181 channel_->ShutDown(); |
164 channel_ = nullptr; | 182 channel_ = nullptr; |
165 } | 183 } |
166 } | 184 } |
167 | 185 |
168 void NodeChannel::SetRemoteProcessHandle(base::ProcessHandle process_handle) { | 186 void NodeChannel::SetRemoteProcessHandle(base::ProcessHandle process_handle) { |
169 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 187 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
170 base::AutoLock lock(remote_process_handle_lock_); | 188 base::AutoLock lock(remote_process_handle_lock_); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); | 314 ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); |
297 if (channel_handle.is_valid()) | 315 if (channel_handle.is_valid()) |
298 handles->push_back(channel_handle.release()); | 316 handles->push_back(channel_handle.release()); |
299 Channel::MessagePtr message = CreateMessage( | 317 Channel::MessagePtr message = CreateMessage( |
300 MessageType::INTRODUCE, sizeof(IntroductionData), handles->size(), &data); | 318 MessageType::INTRODUCE, sizeof(IntroductionData), handles->size(), &data); |
301 message->SetHandles(std::move(handles)); | 319 message->SetHandles(std::move(handles)); |
302 data->name = name; | 320 data->name = name; |
303 WriteChannelMessage(std::move(message)); | 321 WriteChannelMessage(std::move(message)); |
304 } | 322 } |
305 | 323 |
306 #if defined(OS_WIN) | 324 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
307 void NodeChannel::RelayPortsMessage(const ports::NodeName& destination, | 325 void NodeChannel::RelayPortsMessage(const ports::NodeName& destination, |
308 Channel::MessagePtr message) { | 326 Channel::MessagePtr message) { |
| 327 #if defined(OS_WIN) |
309 DCHECK(message->has_handles()); | 328 DCHECK(message->has_handles()); |
310 | 329 |
311 // Note that this is only used on Windows, and on Windows all platform | 330 // Note that this is only used on Windows, and on Windows all platform |
312 // handles are included in the message data. We blindly copy all the data | 331 // handles are included in the message data. We blindly copy all the data |
313 // here and the relay node (the parent) will duplicate handles as needed. | 332 // here and the relay node (the parent) will duplicate handles as needed. |
314 size_t num_bytes = sizeof(RelayPortsMessageData) + message->data_num_bytes(); | 333 size_t num_bytes = sizeof(RelayPortsMessageData) + message->data_num_bytes(); |
315 RelayPortsMessageData* data; | 334 RelayPortsMessageData* data; |
316 Channel::MessagePtr relay_message = CreateMessage( | 335 Channel::MessagePtr relay_message = CreateMessage( |
317 MessageType::RELAY_PORTS_MESSAGE, num_bytes, 0, &data); | 336 MessageType::RELAY_PORTS_MESSAGE, num_bytes, 0, &data); |
318 data->destination = destination; | 337 data->destination = destination; |
319 memcpy(data + 1, message->data(), message->data_num_bytes()); | 338 memcpy(data + 1, message->data(), message->data_num_bytes()); |
320 | 339 |
321 // When the handles are duplicated in the parent, the source handles will | 340 // When the handles are duplicated in the parent, the source handles will |
322 // be closed. If the parent never receives this message then these handles | 341 // be closed. If the parent never receives this message then these handles |
323 // will leak, but that means something else has probably broken and the | 342 // will leak, but that means something else has probably broken and the |
324 // sending process won't likely be around much longer. | 343 // sending process won't likely be around much longer. |
325 ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); | 344 ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); |
326 handles->clear(); | 345 handles->clear(); |
327 | 346 |
| 347 #else |
| 348 DCHECK(message->has_mach_ports()); |
| 349 |
| 350 // On OSX, the handles are extracted from the relayed message and attached to |
| 351 // the wrapper. The broker then takes the handles attached to the wrapper and |
| 352 // moves them back to the relayed message. This is necessary because the |
| 353 // message may contain fds which need to be attached to the outer message so |
| 354 // that they can be transferred to the broker. |
| 355 ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); |
| 356 size_t num_bytes = sizeof(RelayPortsMessageData) + message->data_num_bytes(); |
| 357 RelayPortsMessageData* data; |
| 358 Channel::MessagePtr relay_message = CreateMessage( |
| 359 MessageType::RELAY_PORTS_MESSAGE, num_bytes, handles->size(), &data); |
| 360 data->destination = destination; |
| 361 memcpy(data + 1, message->data(), message->data_num_bytes()); |
| 362 relay_message->SetHandles(std::move(handles)); |
| 363 #endif // defined(OS_WIN) |
| 364 |
328 WriteChannelMessage(std::move(relay_message)); | 365 WriteChannelMessage(std::move(relay_message)); |
329 } | 366 } |
330 #endif | 367 #endif // defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
331 | 368 |
332 NodeChannel::NodeChannel(Delegate* delegate, | 369 NodeChannel::NodeChannel(Delegate* delegate, |
333 ScopedPlatformHandle platform_handle, | 370 ScopedPlatformHandle platform_handle, |
334 scoped_refptr<base::TaskRunner> io_task_runner) | 371 scoped_refptr<base::TaskRunner> io_task_runner) |
335 : delegate_(delegate), | 372 : delegate_(delegate), |
336 io_task_runner_(io_task_runner), | 373 io_task_runner_(io_task_runner), |
337 channel_( | 374 channel_( |
338 Channel::Create(this, std::move(platform_handle), io_task_runner_)) { | 375 Channel::Create(this, std::move(platform_handle), io_task_runner_)) { |
339 } | 376 } |
340 | 377 |
(...skipping 13 matching lines...) Expand all Loading... |
354 { | 391 { |
355 base::AutoLock lock(remote_process_handle_lock_); | 392 base::AutoLock lock(remote_process_handle_lock_); |
356 if (handles && remote_process_handle_ != base::kNullProcessHandle) { | 393 if (handles && remote_process_handle_ != base::kNullProcessHandle) { |
357 if (!Channel::Message::RewriteHandles(remote_process_handle_, | 394 if (!Channel::Message::RewriteHandles(remote_process_handle_, |
358 base::GetCurrentProcessHandle(), | 395 base::GetCurrentProcessHandle(), |
359 handles->data(), handles->size())) { | 396 handles->data(), handles->size())) { |
360 DLOG(ERROR) << "Received one or more invalid handles."; | 397 DLOG(ERROR) << "Received one or more invalid handles."; |
361 } | 398 } |
362 } | 399 } |
363 } | 400 } |
364 #endif | 401 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 402 // If we're not the root, receive any mach ports from the message. If we're |
| 403 // the root, the only message containing mach ports should be a |
| 404 // RELAY_PORTS_MESSAGE. |
| 405 { |
| 406 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 407 if (handles && !relay) { |
| 408 if (!MachPortRelay::ReceivePorts(handles.get())) { |
| 409 LOG(ERROR) << "Error receiving mach ports."; |
| 410 } |
| 411 } |
| 412 } |
| 413 #endif // defined(OS_WIN) |
365 | 414 |
366 const Header* header = static_cast<const Header*>(payload); | 415 const Header* header = static_cast<const Header*>(payload); |
367 switch (header->type) { | 416 switch (header->type) { |
368 case MessageType::ACCEPT_CHILD: { | 417 case MessageType::ACCEPT_CHILD: { |
369 const AcceptChildData* data; | 418 const AcceptChildData* data; |
370 GetMessagePayload(payload, &data); | 419 GetMessagePayload(payload, &data); |
371 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, | 420 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, |
372 data->token); | 421 data->token); |
373 break; | 422 break; |
374 } | 423 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 ScopedPlatformHandle channel_handle; | 526 ScopedPlatformHandle channel_handle; |
478 if (handles && handles->size() == 1) { | 527 if (handles && handles->size() == 1) { |
479 channel_handle = ScopedPlatformHandle(handles->at(0)); | 528 channel_handle = ScopedPlatformHandle(handles->at(0)); |
480 handles->clear(); | 529 handles->clear(); |
481 } | 530 } |
482 delegate_->OnIntroduce(remote_node_name_, data->name, | 531 delegate_->OnIntroduce(remote_node_name_, data->name, |
483 std::move(channel_handle)); | 532 std::move(channel_handle)); |
484 break; | 533 break; |
485 } | 534 } |
486 | 535 |
487 #if defined(OS_WIN) | 536 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
488 case MessageType::RELAY_PORTS_MESSAGE: { | 537 case MessageType::RELAY_PORTS_MESSAGE: { |
489 base::ProcessHandle from_process; | 538 base::ProcessHandle from_process; |
490 { | 539 { |
491 base::AutoLock lock(remote_process_handle_lock_); | 540 base::AutoLock lock(remote_process_handle_lock_); |
492 from_process = remote_process_handle_; | 541 from_process = remote_process_handle_; |
493 } | 542 } |
494 const RelayPortsMessageData* data; | 543 const RelayPortsMessageData* data; |
495 GetMessagePayload(payload, &data); | 544 GetMessagePayload(payload, &data); |
496 const void* message_start = data + 1; | 545 const void* message_start = data + 1; |
497 Channel::MessagePtr message = Channel::Message::Deserialize( | 546 Channel::MessagePtr message = Channel::Message::Deserialize( |
498 message_start, payload_size - sizeof(Header) - sizeof(*data)); | 547 message_start, payload_size - sizeof(Header) - sizeof(*data)); |
499 if (!message) { | 548 if (!message) { |
500 DLOG(ERROR) << "Dropping invalid relay message."; | 549 DLOG(ERROR) << "Dropping invalid relay message."; |
501 break; | 550 break; |
502 } | 551 } |
| 552 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 553 message->SetHandles(std::move(handles)); |
| 554 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 555 if (!relay) { |
| 556 LOG(ERROR) << "Receiving mach ports without a port relay from " |
| 557 << remote_node_name_ << ". Dropping message."; |
| 558 break; |
| 559 } |
| 560 { |
| 561 base::AutoLock lock(pending_mach_messages_lock_); |
| 562 if (relay->port_provider()->TaskForPid(from_process) == |
| 563 MACH_PORT_NULL) { |
| 564 pending_relay_messages_.push( |
| 565 std::make_pair(data->destination, std::move(message))); |
| 566 break; |
| 567 } |
| 568 } |
| 569 #endif |
503 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, | 570 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, |
504 data->destination, std::move(message)); | 571 data->destination, std::move(message)); |
505 break; | 572 break; |
506 } | 573 } |
507 #endif | 574 #endif |
508 | 575 |
509 default: | 576 default: |
510 DLOG(ERROR) << "Received unknown message type " | 577 DLOG(ERROR) << "Received unknown message type " |
511 << static_cast<uint32_t>(header->type) << " from node " | 578 << static_cast<uint32_t>(header->type) << " from node " |
512 << remote_node_name_; | 579 << remote_node_name_; |
513 delegate_->OnChannelError(remote_node_name_); | 580 delegate_->OnChannelError(remote_node_name_); |
514 break; | 581 break; |
515 } | 582 } |
516 } | 583 } |
517 | 584 |
518 void NodeChannel::OnChannelError() { | 585 void NodeChannel::OnChannelError() { |
519 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 586 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
520 | 587 |
521 ShutDown(); | 588 ShutDown(); |
522 // |OnChannelError()| may cause |this| to be destroyed, but still need access | 589 // |OnChannelError()| may cause |this| to be destroyed, but still need access |
523 // to the name name after that destruction. So may a copy of | 590 // to the name name after that destruction. So may a copy of |
524 // |remote_node_name_| so it can be used if |this| becomes destroyed. | 591 // |remote_node_name_| so it can be used if |this| becomes destroyed. |
525 ports::NodeName node_name = remote_node_name_; | 592 ports::NodeName node_name = remote_node_name_; |
526 delegate_->OnChannelError(node_name); | 593 delegate_->OnChannelError(node_name); |
527 } | 594 } |
528 | 595 |
| 596 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 597 void NodeChannel::OnProcessReady(base::ProcessHandle process) { |
| 598 io_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 599 &NodeChannel::ProcessPendingMessagesWithMachPorts, this)); |
| 600 } |
| 601 |
| 602 void NodeChannel::ProcessPendingMessagesWithMachPorts() { |
| 603 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 604 DCHECK(relay); |
| 605 |
| 606 base::ProcessHandle remote_process_handle; |
| 607 { |
| 608 base::AutoLock lock(remote_process_handle_lock_); |
| 609 remote_process_handle = remote_process_handle_; |
| 610 } |
| 611 PendingMessageQueue pending_writes; |
| 612 PendingRelayMessageQueue pending_relays; |
| 613 { |
| 614 base::AutoLock lock(pending_mach_messages_lock_); |
| 615 pending_writes.swap(pending_write_messages_); |
| 616 pending_relays.swap(pending_relay_messages_); |
| 617 } |
| 618 DCHECK(pending_writes.empty() && pending_relays.empty()); |
| 619 |
| 620 while (!pending_writes.empty()) { |
| 621 Channel::MessagePtr message = std::move(pending_writes.front()); |
| 622 pending_writes.pop(); |
| 623 if (!relay->SendPortsToProcess(message.get(), remote_process_handle)) { |
| 624 LOG(ERROR) << "Error on sending mach ports. Remote process is likely " |
| 625 << "gone. Dropping message."; |
| 626 return; |
| 627 } |
| 628 |
| 629 base::AutoLock lock(channel_lock_); |
| 630 if (!channel_) { |
| 631 DLOG(ERROR) << "Dropping message on closed channel."; |
| 632 break; |
| 633 } else { |
| 634 channel_->Write(std::move(message)); |
| 635 } |
| 636 } |
| 637 |
| 638 while (!pending_relays.empty()) { |
| 639 ports::NodeName destination = pending_relays.front().first; |
| 640 Channel::MessagePtr message = std::move(pending_relays.front().second); |
| 641 pending_relays.pop(); |
| 642 delegate_->OnRelayPortsMessage(remote_node_name_, remote_process_handle, |
| 643 destination, std::move(message)); |
| 644 } |
| 645 } |
| 646 #endif |
| 647 |
529 void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) { | 648 void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) { |
530 #if defined(OS_WIN) | 649 #if defined(OS_WIN) |
531 // Map handles to the destination process. Note: only messages from a | 650 // Map handles to the destination process. Note: only messages from a |
532 // privileged node should contain handles on Windows. If an unprivileged | 651 // privileged node should contain handles on Windows. If an unprivileged |
533 // node needs to send handles, it should do so via RelayPortsMessage which | 652 // node needs to send handles, it should do so via RelayPortsMessage which |
534 // stashes the handles in the message in such a way that they go undetected | 653 // stashes the handles in the message in such a way that they go undetected |
535 // here (they'll be unpacked and duplicated by a privileged parent.) | 654 // here (they'll be unpacked and duplicated by a privileged parent.) |
536 | 655 |
537 if (message->has_handles()) { | 656 if (message->has_handles()) { |
538 base::ProcessHandle remote_process_handle; | 657 base::ProcessHandle remote_process_handle; |
539 { | 658 { |
540 base::AutoLock lock(remote_process_handle_lock_); | 659 base::AutoLock lock(remote_process_handle_lock_); |
541 remote_process_handle = remote_process_handle_; | 660 remote_process_handle = remote_process_handle_; |
542 } | 661 } |
543 | 662 |
544 // Rewrite outgoing handles if we have a handle to the destination process. | 663 // Rewrite outgoing handles if we have a handle to the destination process. |
545 if (remote_process_handle != base::kNullProcessHandle) { | 664 if (remote_process_handle != base::kNullProcessHandle) { |
546 if (!message->RewriteHandles(base::GetCurrentProcessHandle(), | 665 if (!message->RewriteHandles(base::GetCurrentProcessHandle(), |
547 remote_process_handle, message->handles(), | 666 remote_process_handle, message->handles(), |
548 message->num_handles())) { | 667 message->num_handles())) { |
549 DLOG(ERROR) << "Failed to duplicate one or more outgoing handles."; | 668 DLOG(ERROR) << "Failed to duplicate one or more outgoing handles."; |
550 } | 669 } |
551 } | 670 } |
552 } | 671 } |
| 672 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 673 // On OSX, we need to transfer mach ports to the destination process before |
| 674 // transferring the message itself. |
| 675 if (message->has_mach_ports()) { |
| 676 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 677 if (relay) { |
| 678 base::ProcessHandle remote_process_handle; |
| 679 { |
| 680 base::AutoLock lock(remote_process_handle_lock_); |
| 681 // Expect that the receiving node is a child. |
| 682 DCHECK(remote_process_handle_ != base::kNullProcessHandle); |
| 683 remote_process_handle = remote_process_handle_; |
| 684 } |
| 685 { |
| 686 base::AutoLock lock(pending_mach_messages_lock_); |
| 687 if (relay->port_provider()->TaskForPid(remote_process_handle) == |
| 688 MACH_PORT_NULL) { |
| 689 // It is also possible for TaskForPid() to return MACH_PORT_NULL when |
| 690 // the process has started, then died. In that case, the queued |
| 691 // message will never be processed. But that's fine since we're about |
| 692 // to die anyway. |
| 693 pending_write_messages_.push(std::move(message)); |
| 694 return; |
| 695 } |
| 696 } |
| 697 |
| 698 if (!relay->SendPortsToProcess(message.get(), remote_process_handle)) { |
| 699 LOG(ERROR) << "Error on sending mach ports. Remote process is likely " |
| 700 << "gone. Dropping message."; |
| 701 return; |
| 702 } |
| 703 } |
| 704 } |
553 #endif | 705 #endif |
554 | 706 |
555 base::AutoLock lock(channel_lock_); | 707 base::AutoLock lock(channel_lock_); |
556 if (!channel_) | 708 if (!channel_) |
557 DLOG(ERROR) << "Dropping message on closed channel."; | 709 DLOG(ERROR) << "Dropping message on closed channel."; |
558 else | 710 else |
559 channel_->Write(std::move(message)); | 711 channel_->Write(std::move(message)); |
560 } | 712 } |
561 | 713 |
562 } // namespace edk | 714 } // namespace edk |
563 } // namespace mojo | 715 } // namespace mojo |
OLD | NEW |