| 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/channel.h" | 5 #include "mojo/edk/system/channel.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <deque> | 11 #include <deque> |
| 12 #include <limits> | 12 #include <limits> |
| 13 #include <memory> | 13 #include <memory> |
| 14 | 14 |
| 15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/location.h" | 16 #include "base/location.h" |
| 17 #include "base/macros.h" | 17 #include "base/macros.h" |
| 18 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
| 19 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
| 20 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 21 #include "base/task_runner.h" | 21 #include "base/task_runner.h" |
| 22 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | 22 #include "mojo/edk/embedder/platform_channel_utils_posix.h" |
| 23 #include "mojo/edk/embedder/platform_handle_vector.h" | 23 #include "mojo/edk/embedder/platform_handle_vector.h" |
| 24 | 24 |
| 25 #if !defined(OS_NACL) | 25 #if !defined(OS_NACL) |
| 26 #include <sys/uio.h> | 26 #include <sys/uio.h> |
| 27 #endif | 27 #endif |
| 28 | 28 |
| 29 #if defined(OS_ANDROID) |
| 30 #include "base/android/parcelable_channel_client.h" |
| 31 #include "base/android/scoped_java_ref.h" |
| 32 #endif |
| 33 |
| 29 namespace mojo { | 34 namespace mojo { |
| 30 namespace edk { | 35 namespace edk { |
| 31 | 36 |
| 32 namespace { | 37 namespace { |
| 33 | 38 |
| 34 const size_t kMaxBatchReadCapacity = 256 * 1024; | 39 const size_t kMaxBatchReadCapacity = 256 * 1024; |
| 35 | 40 |
| 36 // A view over a Channel::Message object. The write queue uses these since | 41 // A view over a Channel::Message object. The write queue uses these since |
| 37 // large messages may need to be sent in chunks. | 42 // large messages may need to be sent in chunks. |
| 38 class MessageView { | 43 class MessageView { |
| 39 public: | 44 public: |
| 40 // Owns |message|. |offset| indexes the first unsent byte in the message. | 45 // Owns |message|. |offset| indexes the first unsent byte in the message. |
| 41 MessageView(Channel::MessagePtr message, size_t offset) | 46 MessageView(Channel::MessagePtr message, size_t offset) |
| 42 : message_(std::move(message)), | 47 : message_(std::move(message)), offset_(offset) { |
| 43 offset_(offset), | |
| 44 handles_(message_->TakeHandlesForTransport()) { | |
| 45 DCHECK_GT(message_->data_num_bytes(), offset_); | 48 DCHECK_GT(message_->data_num_bytes(), offset_); |
| 49 #if defined(OS_ANDROID) |
| 50 // Parcelables must be retrieved before Handles. |
| 51 ids_and_parcelables_ = message_->TakeParcelablesForTransport(); |
| 52 #endif |
| 53 handles_ = message_->TakeHandlesForTransport(); |
| 46 } | 54 } |
| 47 | 55 |
| 48 MessageView(MessageView&& other) { *this = std::move(other); } | 56 MessageView(MessageView&& other) { *this = std::move(other); } |
| 49 | 57 |
| 50 MessageView& operator=(MessageView&& other) { | 58 MessageView& operator=(MessageView&& other) { |
| 51 message_ = std::move(other.message_); | 59 message_ = std::move(other.message_); |
| 52 offset_ = other.offset_; | 60 offset_ = other.offset_; |
| 53 handles_ = std::move(other.handles_); | 61 handles_ = std::move(other.handles_); |
| 54 return *this; | 62 return *this; |
| 55 } | 63 } |
| 56 | 64 |
| 57 ~MessageView() {} | 65 ~MessageView() {} |
| 58 | 66 |
| 59 const void* data() const { | 67 const void* data() const { |
| 60 return static_cast<const char*>(message_->data()) + offset_; | 68 return static_cast<const char*>(message_->data()) + offset_; |
| 61 } | 69 } |
| 62 | 70 |
| 63 size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; } | 71 size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; } |
| 64 | 72 |
| 65 size_t data_offset() const { return offset_; } | 73 size_t data_offset() const { return offset_; } |
| 66 void advance_data_offset(size_t num_bytes) { | 74 void advance_data_offset(size_t num_bytes) { |
| 67 DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes); | 75 DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes); |
| 68 offset_ += num_bytes; | 76 offset_ += num_bytes; |
| 69 } | 77 } |
| 70 | 78 |
| 71 ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } | 79 ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } |
| 72 Channel::MessagePtr TakeMessage() { return std::move(message_); } | 80 Channel::MessagePtr TakeMessage() { return std::move(message_); } |
| 81 #if defined(OS_ANDROID) |
| 82 Channel::Message::IDAndParcelableVector TakeParcelables() { |
| 83 return std::move(ids_and_parcelables_); |
| 84 } |
| 85 |
| 86 #endif |
| 73 | 87 |
| 74 void SetHandles(ScopedPlatformHandleVectorPtr handles) { | 88 void SetHandles(ScopedPlatformHandleVectorPtr handles) { |
| 75 handles_ = std::move(handles); | 89 handles_ = std::move(handles); |
| 76 } | 90 } |
| 77 | 91 |
| 78 private: | 92 private: |
| 79 Channel::MessagePtr message_; | 93 Channel::MessagePtr message_; |
| 80 size_t offset_; | 94 size_t offset_; |
| 81 ScopedPlatformHandleVectorPtr handles_; | 95 ScopedPlatformHandleVectorPtr handles_; |
| 96 #if defined(OS_ANDROID) |
| 97 Channel::Message::IDAndParcelableVector ids_and_parcelables_; |
| 98 #endif |
| 82 | 99 |
| 83 DISALLOW_COPY_AND_ASSIGN(MessageView); | 100 DISALLOW_COPY_AND_ASSIGN(MessageView); |
| 84 }; | 101 }; |
| 85 | 102 |
| 86 class ChannelPosix : public Channel, | 103 class ChannelPosix : public Channel, |
| 87 public base::MessageLoop::DestructionObserver, | 104 public base::MessageLoop::DestructionObserver, |
| 88 public base::MessageLoopForIO::Watcher { | 105 public base::MessageLoopForIO::Watcher { |
| 89 public: | 106 public: |
| 90 ChannelPosix(Delegate* delegate, | 107 ChannelPosix(Delegate* delegate, |
| 91 ScopedPlatformHandle handle, | 108 ConnectionParam connection_param, |
| 92 scoped_refptr<base::TaskRunner> io_task_runner) | 109 scoped_refptr<base::TaskRunner> io_task_runner) |
| 93 : Channel(delegate), | 110 : Channel(delegate), |
| 94 self_(this), | 111 self_(this), |
| 95 handle_(std::move(handle)), | 112 handle_(connection_param.TakeChannelHandle()), |
| 113 #if defined(OS_ANDROID) |
| 114 parcelable_channel_client_( |
| 115 connection_param.TakeParcelableChannelClient()), |
| 116 parcelable_channel_server_( |
| 117 connection_param.TakeParcelableChannelServer()), |
| 118 #endif |
| 96 io_task_runner_(io_task_runner) | 119 io_task_runner_(io_task_runner) |
| 97 #if defined(OS_MACOSX) | 120 #if defined(OS_MACOSX) |
| 98 , | 121 , |
| 99 handles_to_close_(new PlatformHandleVector) | 122 handles_to_close_(new PlatformHandleVector) |
| 100 #endif | 123 #endif |
| 101 { | 124 { |
| 125 CHECK(handle_.is_valid()); |
| 126 // We can't DCHECK because the BrokerHost has a channel used for sync |
| 127 // messages with not parcelable channels. |
| 128 // CHECK(parcelable_channel_client_.is_valid()); |
| 129 // CHECK(parcelable_channel_server_.is_valid()); |
| 102 } | 130 } |
| 103 | 131 |
| 104 void Start() override { | 132 void Start() override { |
| 105 if (io_task_runner_->RunsTasksOnCurrentThread()) { | 133 if (io_task_runner_->RunsTasksOnCurrentThread()) { |
| 106 StartOnIOThread(); | 134 StartOnIOThread(); |
| 107 } else { | 135 } else { |
| 108 io_task_runner_->PostTask( | 136 io_task_runner_->PostTask( |
| 109 FROM_HERE, base::Bind(&ChannelPosix::StartOnIOThread, this)); | 137 FROM_HERE, base::Bind(&ChannelPosix::StartOnIOThread, this)); |
| 110 } | 138 } |
| 111 } | 139 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 142 leak_handle_ = true; | 170 leak_handle_ = true; |
| 143 } | 171 } |
| 144 | 172 |
| 145 bool GetReadPlatformHandles( | 173 bool GetReadPlatformHandles( |
| 146 size_t num_handles, | 174 size_t num_handles, |
| 147 const void* extra_header, | 175 const void* extra_header, |
| 148 size_t extra_header_size, | 176 size_t extra_header_size, |
| 149 ScopedPlatformHandleVectorPtr* handles) override { | 177 ScopedPlatformHandleVectorPtr* handles) override { |
| 150 if (num_handles > std::numeric_limits<uint16_t>::max()) | 178 if (num_handles > std::numeric_limits<uint16_t>::max()) |
| 151 return false; | 179 return false; |
| 180 |
| 152 #if defined(OS_MACOSX) && !defined(OS_IOS) | 181 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 153 // On OSX, we can have mach ports which are located in the extra header | 182 // On OSX, we can have mach ports which are located in the extra header |
| 154 // section. | 183 // section. |
| 155 using MachPortsEntry = Channel::Message::MachPortsEntry; | 184 using MachPortsEntry = Channel::Message::MachPortsEntry; |
| 156 using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader; | 185 using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader; |
| 157 CHECK(extra_header_size >= | 186 CHECK(extra_header_size >= |
| 158 sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry)); | 187 sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry)); |
| 159 const MachPortsExtraHeader* mach_ports_header = | 188 const MachPortsExtraHeader* mach_ports_header = |
| 160 reinterpret_cast<const MachPortsExtraHeader*>(extra_header); | 189 reinterpret_cast<const MachPortsExtraHeader*>(extra_header); |
| 161 size_t num_mach_ports = mach_ports_header->num_ports; | 190 size_t num_mach_ports = mach_ports_header->num_ports; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 176 // These are actually just Mach port names until they're resolved from | 205 // These are actually just Mach port names until they're resolved from |
| 177 // the remote process. | 206 // the remote process. |
| 178 (*handles)->at(i).type = PlatformHandle::Type::MACH_NAME; | 207 (*handles)->at(i).type = PlatformHandle::Type::MACH_NAME; |
| 179 mach_port_index++; | 208 mach_port_index++; |
| 180 } else { | 209 } else { |
| 181 CHECK(!incoming_platform_handles_.empty()); | 210 CHECK(!incoming_platform_handles_.empty()); |
| 182 (*handles)->at(i) = incoming_platform_handles_.front(); | 211 (*handles)->at(i) = incoming_platform_handles_.front(); |
| 183 incoming_platform_handles_.pop_front(); | 212 incoming_platform_handles_.pop_front(); |
| 184 } | 213 } |
| 185 } | 214 } |
| 215 #elif defined(OS_ANDROID) |
| 216 using ParcelableEntry = Channel::Message::ParcelableEntry; |
| 217 using ParcelableExtraHeader = Channel::Message::ParcelableExtraHeader; |
| 218 CHECK(extra_header_size >= sizeof(ParcelableExtraHeader) + |
| 219 num_handles * sizeof(ParcelableEntry)); |
| 220 const ParcelableExtraHeader* parcelable_header = |
| 221 reinterpret_cast<const ParcelableExtraHeader*>(extra_header); |
| 222 size_t num_parcelables = parcelable_header->num_parcelables; |
| 223 CHECK(num_parcelables <= num_handles); |
| 224 if (incoming_platform_handles_.size() + num_parcelables < num_handles) { |
| 225 handles->reset(); |
| 226 return true; |
| 227 } |
| 228 |
| 229 handles->reset(new PlatformHandleVector(num_handles)); |
| 230 const ParcelableEntry* parcelables = parcelable_header->entries; |
| 231 for (size_t i = 0, parcelable_index = 0; i < num_handles; ++i) { |
| 232 if (parcelable_index < num_parcelables && |
| 233 parcelables[parcelable_index].index == i) { |
| 234 (*handles)->at(i) = |
| 235 PlatformHandle(parcelable_channel_server_.TakeParcelable( |
| 236 parcelables[parcelable_index].id)); |
| 237 parcelable_index++; |
| 238 } else { |
| 239 CHECK(!incoming_platform_handles_.empty()); |
| 240 (*handles)->at(i) = incoming_platform_handles_.front(); |
| 241 incoming_platform_handles_.pop_front(); |
| 242 } |
| 243 } |
| 186 #else | 244 #else |
| 187 if (incoming_platform_handles_.size() < num_handles) { | 245 if (incoming_platform_handles_.size() < num_handles) { |
| 188 handles->reset(); | 246 handles->reset(); |
| 189 return true; | 247 return true; |
| 190 } | 248 } |
| 191 | 249 |
| 192 handles->reset(new PlatformHandleVector(num_handles)); | 250 handles->reset(new PlatformHandleVector(num_handles)); |
| 193 for (size_t i = 0; i < num_handles; ++i) { | 251 for (size_t i = 0; i < num_handles; ++i) { |
| 194 (*handles)->at(i) = incoming_platform_handles_.front(); | 252 (*handles)->at(i) = incoming_platform_handles_.front(); |
| 195 incoming_platform_handles_.pop_front(); | 253 incoming_platform_handles_.pop_front(); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 bool WriteNoLock(MessageView message_view) { | 409 bool WriteNoLock(MessageView message_view) { |
| 352 if (handle_.get().needs_connection) { | 410 if (handle_.get().needs_connection) { |
| 353 outgoing_messages_.emplace_front(std::move(message_view)); | 411 outgoing_messages_.emplace_front(std::move(message_view)); |
| 354 return true; | 412 return true; |
| 355 } | 413 } |
| 356 size_t bytes_written = 0; | 414 size_t bytes_written = 0; |
| 357 do { | 415 do { |
| 358 message_view.advance_data_offset(bytes_written); | 416 message_view.advance_data_offset(bytes_written); |
| 359 | 417 |
| 360 ssize_t result; | 418 ssize_t result; |
| 419 #if defined(OS_ANDROID) |
| 420 Channel::Message::IDAndParcelableVector ids_and_parcelables = |
| 421 std::move(message_view.TakeParcelables()); |
| 422 if (!ids_and_parcelables.empty()) { |
| 423 for (auto iter = ids_and_parcelables.begin(); |
| 424 iter != ids_and_parcelables.end(); ++iter) { |
| 425 DCHECK(!iter->second.is_null()); |
| 426 parcelable_channel_client_.SendParcelable(iter->first, iter->second); |
| 427 } |
| 428 } |
| 429 #endif |
| 361 ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); | 430 ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); |
| 362 if (handles && handles->size()) { | 431 if (handles && handles->size()) { |
| 363 iovec iov = { | 432 iovec iov = { |
| 364 const_cast<void*>(message_view.data()), | 433 const_cast<void*>(message_view.data()), |
| 365 message_view.data_num_bytes() | 434 message_view.data_num_bytes() |
| 366 }; | 435 }; |
| 367 // TODO: Handle lots of handles. | 436 // TODO: Handle lots of handles. |
| 368 result = PlatformChannelSendmsgWithHandles( | 437 result = PlatformChannelSendmsgWithHandles( |
| 369 handle_.get(), &iov, 1, handles->data(), handles->size()); | 438 handle_.get(), &iov, 1, handles->data(), handles->size()); |
| 370 if (result >= 0) { | 439 if (result >= 0) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 | 594 |
| 526 handles_to_close_->erase(start, it); | 595 handles_to_close_->erase(start, it); |
| 527 return true; | 596 return true; |
| 528 } | 597 } |
| 529 #endif // defined(OS_MACOSX) | 598 #endif // defined(OS_MACOSX) |
| 530 | 599 |
| 531 // Keeps the Channel alive at least until explicit shutdown on the IO thread. | 600 // Keeps the Channel alive at least until explicit shutdown on the IO thread. |
| 532 scoped_refptr<Channel> self_; | 601 scoped_refptr<Channel> self_; |
| 533 | 602 |
| 534 ScopedPlatformHandle handle_; | 603 ScopedPlatformHandle handle_; |
| 604 #if defined(OS_ANDROID) |
| 605 base::android::ParcelableChannelClient parcelable_channel_client_; |
| 606 base::android::ParcelableChannelServer parcelable_channel_server_; |
| 607 #endif |
| 535 scoped_refptr<base::TaskRunner> io_task_runner_; | 608 scoped_refptr<base::TaskRunner> io_task_runner_; |
| 536 | 609 |
| 537 // These watchers must only be accessed on the IO thread. | 610 // These watchers must only be accessed on the IO thread. |
| 538 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; | 611 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; |
| 539 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; | 612 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; |
| 540 | 613 |
| 541 std::deque<PlatformHandle> incoming_platform_handles_; | 614 std::deque<PlatformHandle> incoming_platform_handles_; |
| 542 | 615 |
| 543 // Protects |pending_write_| and |outgoing_messages_|. | 616 // Protects |pending_write_| and |outgoing_messages_|. |
| 544 base::Lock write_lock_; | 617 base::Lock write_lock_; |
| 545 bool pending_write_ = false; | 618 bool pending_write_ = false; |
| 546 bool reject_writes_ = false; | 619 bool reject_writes_ = false; |
| 547 std::deque<MessageView> outgoing_messages_; | 620 std::deque<MessageView> outgoing_messages_; |
| 548 | 621 |
| 549 bool leak_handle_ = false; | 622 bool leak_handle_ = false; |
| 550 | 623 |
| 551 #if defined(OS_MACOSX) | 624 #if defined(OS_MACOSX) |
| 552 base::Lock handles_to_close_lock_; | 625 base::Lock handles_to_close_lock_; |
| 553 ScopedPlatformHandleVectorPtr handles_to_close_; | 626 ScopedPlatformHandleVectorPtr handles_to_close_; |
| 554 #endif | 627 #endif |
| 555 | 628 |
| 556 DISALLOW_COPY_AND_ASSIGN(ChannelPosix); | 629 DISALLOW_COPY_AND_ASSIGN(ChannelPosix); |
| 557 }; | 630 }; |
| 558 | 631 |
| 559 } // namespace | 632 } // namespace |
| 560 | 633 |
| 561 // static | 634 // static |
| 562 scoped_refptr<Channel> Channel::Create( | 635 scoped_refptr<Channel> Channel::Create( |
| 563 Delegate* delegate, | 636 Delegate* delegate, |
| 564 ScopedPlatformHandle platform_handle, | 637 ConnectionParam connection_param, |
| 565 scoped_refptr<base::TaskRunner> io_task_runner) { | 638 scoped_refptr<base::TaskRunner> io_task_runner) { |
| 566 return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner); | 639 return new ChannelPosix(delegate, std::move(connection_param), |
| 640 io_task_runner); |
| 567 } | 641 } |
| 568 | 642 |
| 569 } // namespace edk | 643 } // namespace edk |
| 570 } // namespace mojo | 644 } // namespace mojo |
| OLD | NEW |