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 |