Chromium Code Reviews| Index: mojo/public/cpp/bindings/lib/message.cc |
| diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc |
| index 0018a03bcd7909b9b9657f5d66b6c750b1941485..c60692781e8ad4fc0420a2b9ae4cef7ea4debcf6 100644 |
| --- a/mojo/public/cpp/bindings/lib/message.cc |
| +++ b/mojo/public/cpp/bindings/lib/message.cc |
| @@ -16,6 +16,8 @@ |
| #include "base/logging.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/threading/thread_local.h" |
| +#include "mojo/public/cpp/bindings/associated_group_controller.h" |
| +#include "mojo/public/cpp/bindings/lib/array_internal.h" |
| namespace mojo { |
| @@ -37,8 +39,10 @@ Message::Message() { |
| } |
| Message::Message(Message&& other) |
| - : buffer_(std::move(other.buffer_)), handles_(std::move(other.handles_)) { |
| -} |
| + : buffer_(std::move(other.buffer_)), |
| + handles_(std::move(other.handles_)), |
| + associated_endpoint_handles_( |
| + std::move(other.associated_endpoint_handles_)) {} |
| Message::~Message() { |
| CloseHandles(); |
| @@ -48,12 +52,14 @@ Message& Message::operator=(Message&& other) { |
| Reset(); |
| std::swap(other.buffer_, buffer_); |
| std::swap(other.handles_, handles_); |
| + std::swap(other.associated_endpoint_handles_, associated_endpoint_handles_); |
| return *this; |
| } |
| void Message::Reset() { |
| CloseHandles(); |
| handles_.clear(); |
| + associated_endpoint_handles_.clear(); |
| buffer_.reset(); |
| } |
| @@ -70,7 +76,52 @@ void Message::InitializeFromMojoMessage(ScopedMessageHandle message, |
| handles_.swap(*handles); |
| } |
| +const uint8_t* Message::payload() const { |
| + if (version() < 2) |
| + return data() + header()->num_bytes; |
| + |
| + return static_cast<const uint8_t*>(header_v2()->payload.Get()); |
| +} |
| + |
| +uint32_t Message::payload_num_bytes() const { |
| + DCHECK(data_num_bytes() >= header()->num_bytes); |
|
Ken Rockot(use gerrit already)
2017/01/31 18:33:42
nit: Can we DCHECK_GE?
yzshen1
2017/01/31 19:26:05
Done.
|
| + size_t num_bytes; |
| + if (version() < 2) { |
| + num_bytes = data_num_bytes() - header()->num_bytes; |
| + } else { |
| + auto payload = reinterpret_cast<uintptr_t>(header_v2()->payload.Get()); |
| + if (!payload) { |
| + num_bytes = 0; |
| + } else { |
| + auto payload_end = |
| + reinterpret_cast<uintptr_t>(header_v2()->payload_interface_ids.Get()); |
| + if (!payload_end) |
| + payload_end = reinterpret_cast<uintptr_t>(data() + data_num_bytes()); |
| + DCHECK_GE(payload_end, payload); |
| + num_bytes = payload_end - payload; |
| + } |
| + } |
| + DCHECK(num_bytes <= std::numeric_limits<uint32_t>::max()); |
| + return static_cast<uint32_t>(num_bytes); |
| +} |
| + |
| +uint32_t Message::payload_num_interface_ids() const { |
| + auto array_pointer = |
| + version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); |
| + return array_pointer ? static_cast<uint32_t>(array_pointer->size()) : 0; |
| +} |
| + |
| +const uint32_t* Message::payload_interface_ids() const { |
| + auto array_pointer = |
| + version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); |
| + return array_pointer ? array_pointer->storage() : nullptr; |
| +} |
| + |
| ScopedMessageHandle Message::TakeMojoMessage() { |
| + // If there are associated endpoints transferred, |
| + // SerializeAssociatedEndpointHandles() must be called before this method. |
| + DCHECK(associated_endpoint_handles_.empty()); |
| + |
| if (handles_.empty()) // Fast path for the common case: No handles. |
| return buffer_->TakeMessage(); |
| @@ -114,6 +165,55 @@ void Message::CloseHandles() { |
| } |
| } |
| +void Message::SerializeAssociatedEndpointHandles( |
| + AssociatedGroupController* group_controller) { |
| + if (associated_endpoint_handles_.empty()) |
| + return; |
| + |
| + DCHECK_GE(version(), 2u); |
| + DCHECK(header_v2()->payload_interface_ids.is_null()); |
| + |
| + size_t size = associated_endpoint_handles_.size(); |
| + auto data = internal::Array_Data<uint32_t>::New(size, buffer()); |
| + header_v2()->payload_interface_ids.Set(data); |
| + |
| + for (size_t i = 0; i < size; ++i) { |
| + ScopedInterfaceEndpointHandle& handle = associated_endpoint_handles_[i]; |
| + |
| + DCHECK(handle.is_valid()); |
| + DCHECK(!handle.is_local()); |
| + DCHECK_EQ(group_controller, handle.group_controller()); |
| + data->storage()[i] = handle.release(); |
| + } |
| + associated_endpoint_handles_.clear(); |
| +} |
| + |
| +bool Message::DeserializeAssociatedEndpointHandles( |
| + AssociatedGroupController* group_controller) { |
| + associated_endpoint_handles_.clear(); |
| + |
| + uint32_t num_ids = payload_num_interface_ids(); |
| + if (num_ids == 0) |
| + return true; |
| + |
| + associated_endpoint_handles_.reserve(num_ids); |
| + uint32_t* ids = header_v2()->payload_interface_ids.Get()->storage(); |
| + bool result = true; |
| + for (uint32_t i = 0; i < num_ids; ++i) { |
| + auto handle = group_controller->CreateLocalEndpointHandle(ids[i]); |
| + if (IsValidInterfaceId(ids[i]) && !handle.is_valid()) { |
| + // |ids[i]| itself is valid but handle creation failed. In that case, mark |
| + // deserialization as failed but continue to deserialize the rest of |
| + // handles. |
| + result = false; |
| + } |
| + |
| + associated_endpoint_handles_.push_back(std::move(handle)); |
| + ids[i] = kInvalidInterfaceId; |
| + } |
| + return result; |
| +} |
| + |
| PassThroughFilter::PassThroughFilter() {} |
| PassThroughFilter::~PassThroughFilter() {} |
| @@ -195,6 +295,8 @@ ReportBadMessageCallback GetBadMessageCallback() { |
| namespace internal { |
| +MessageHeaderV2::MessageHeaderV2() = default; |
| + |
| MessageDispatchContext::MessageDispatchContext(Message* message) |
| : outer_context_(current()), message_(message) { |
| g_tls_message_dispatch_context.Get().Set(this); |