| 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 |