Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/public/cpp/bindings/message.h" | 5 #include "mojo/public/cpp/bindings/message.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/threading/thread_local.h" | 18 #include "base/threading/thread_local.h" |
| 19 #include "mojo/public/cpp/bindings/associated_group_controller.h" | |
| 20 #include "mojo/public/cpp/bindings/lib/array_internal.h" | |
| 19 | 21 |
| 20 namespace mojo { | 22 namespace mojo { |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 base::LazyInstance<base::ThreadLocalPointer<internal::MessageDispatchContext>> | 26 base::LazyInstance<base::ThreadLocalPointer<internal::MessageDispatchContext>> |
| 25 g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER; | 27 g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER; |
| 26 | 28 |
| 27 base::LazyInstance<base::ThreadLocalPointer<SyncMessageResponseContext>> | 29 base::LazyInstance<base::ThreadLocalPointer<SyncMessageResponseContext>> |
| 28 g_tls_sync_response_context = LAZY_INSTANCE_INITIALIZER; | 30 g_tls_sync_response_context = LAZY_INSTANCE_INITIALIZER; |
| 29 | 31 |
| 30 void DoNotifyBadMessage(Message message, const std::string& error) { | 32 void DoNotifyBadMessage(Message message, const std::string& error) { |
| 31 message.NotifyBadMessage(error); | 33 message.NotifyBadMessage(error); |
| 32 } | 34 } |
| 33 | 35 |
| 34 } // namespace | 36 } // namespace |
| 35 | 37 |
| 36 Message::Message() { | 38 Message::Message() { |
| 37 } | 39 } |
| 38 | 40 |
| 39 Message::Message(Message&& other) | 41 Message::Message(Message&& other) |
| 40 : buffer_(std::move(other.buffer_)), handles_(std::move(other.handles_)) { | 42 : buffer_(std::move(other.buffer_)), |
| 41 } | 43 handles_(std::move(other.handles_)), |
| 44 associated_endpoint_handles_( | |
| 45 std::move(other.associated_endpoint_handles_)) {} | |
| 42 | 46 |
| 43 Message::~Message() { | 47 Message::~Message() { |
| 44 CloseHandles(); | 48 CloseHandles(); |
| 45 } | 49 } |
| 46 | 50 |
| 47 Message& Message::operator=(Message&& other) { | 51 Message& Message::operator=(Message&& other) { |
| 48 Reset(); | 52 Reset(); |
| 49 std::swap(other.buffer_, buffer_); | 53 std::swap(other.buffer_, buffer_); |
| 50 std::swap(other.handles_, handles_); | 54 std::swap(other.handles_, handles_); |
| 55 std::swap(other.associated_endpoint_handles_, associated_endpoint_handles_); | |
| 51 return *this; | 56 return *this; |
| 52 } | 57 } |
| 53 | 58 |
| 54 void Message::Reset() { | 59 void Message::Reset() { |
| 55 CloseHandles(); | 60 CloseHandles(); |
| 56 handles_.clear(); | 61 handles_.clear(); |
| 62 associated_endpoint_handles_.clear(); | |
| 57 buffer_.reset(); | 63 buffer_.reset(); |
| 58 } | 64 } |
| 59 | 65 |
| 60 void Message::Initialize(size_t capacity, bool zero_initialized) { | 66 void Message::Initialize(size_t capacity, bool zero_initialized) { |
| 61 DCHECK(!buffer_); | 67 DCHECK(!buffer_); |
| 62 buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); | 68 buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); |
| 63 } | 69 } |
| 64 | 70 |
| 65 void Message::InitializeFromMojoMessage(ScopedMessageHandle message, | 71 void Message::InitializeFromMojoMessage(ScopedMessageHandle message, |
| 66 uint32_t num_bytes, | 72 uint32_t num_bytes, |
| 67 std::vector<Handle>* handles) { | 73 std::vector<Handle>* handles) { |
| 68 DCHECK(!buffer_); | 74 DCHECK(!buffer_); |
| 69 buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); | 75 buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); |
| 70 handles_.swap(*handles); | 76 handles_.swap(*handles); |
| 71 } | 77 } |
| 72 | 78 |
| 79 const uint8_t* Message::payload() const { | |
| 80 if (version() < 2) | |
| 81 return data() + header()->num_bytes; | |
| 82 | |
| 83 return static_cast<const uint8_t*>(header_v2()->payload.Get()); | |
| 84 } | |
| 85 | |
| 86 uint32_t Message::payload_num_bytes() const { | |
| 87 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.
| |
| 88 size_t num_bytes; | |
| 89 if (version() < 2) { | |
| 90 num_bytes = data_num_bytes() - header()->num_bytes; | |
| 91 } else { | |
| 92 auto payload = reinterpret_cast<uintptr_t>(header_v2()->payload.Get()); | |
| 93 if (!payload) { | |
| 94 num_bytes = 0; | |
| 95 } else { | |
| 96 auto payload_end = | |
| 97 reinterpret_cast<uintptr_t>(header_v2()->payload_interface_ids.Get()); | |
| 98 if (!payload_end) | |
| 99 payload_end = reinterpret_cast<uintptr_t>(data() + data_num_bytes()); | |
| 100 DCHECK_GE(payload_end, payload); | |
| 101 num_bytes = payload_end - payload; | |
| 102 } | |
| 103 } | |
| 104 DCHECK(num_bytes <= std::numeric_limits<uint32_t>::max()); | |
| 105 return static_cast<uint32_t>(num_bytes); | |
| 106 } | |
| 107 | |
| 108 uint32_t Message::payload_num_interface_ids() const { | |
| 109 auto array_pointer = | |
| 110 version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); | |
| 111 return array_pointer ? static_cast<uint32_t>(array_pointer->size()) : 0; | |
| 112 } | |
| 113 | |
| 114 const uint32_t* Message::payload_interface_ids() const { | |
| 115 auto array_pointer = | |
| 116 version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); | |
| 117 return array_pointer ? array_pointer->storage() : nullptr; | |
| 118 } | |
| 119 | |
| 73 ScopedMessageHandle Message::TakeMojoMessage() { | 120 ScopedMessageHandle Message::TakeMojoMessage() { |
| 121 // If there are associated endpoints transferred, | |
| 122 // SerializeAssociatedEndpointHandles() must be called before this method. | |
| 123 DCHECK(associated_endpoint_handles_.empty()); | |
| 124 | |
| 74 if (handles_.empty()) // Fast path for the common case: No handles. | 125 if (handles_.empty()) // Fast path for the common case: No handles. |
| 75 return buffer_->TakeMessage(); | 126 return buffer_->TakeMessage(); |
| 76 | 127 |
| 77 // Allocate a new message with space for the handles, then copy the buffer | 128 // Allocate a new message with space for the handles, then copy the buffer |
| 78 // contents into it. | 129 // contents into it. |
| 79 // | 130 // |
| 80 // TODO(rockot): We could avoid this copy by extending GetSerializedSize() | 131 // TODO(rockot): We could avoid this copy by extending GetSerializedSize() |
| 81 // behavior to collect handles. It's unoptimized for now because it's much | 132 // behavior to collect handles. It's unoptimized for now because it's much |
| 82 // more common to have messages with no handles. | 133 // more common to have messages with no handles. |
| 83 ScopedMessageHandle new_message; | 134 ScopedMessageHandle new_message; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 107 } | 158 } |
| 108 | 159 |
| 109 void Message::CloseHandles() { | 160 void Message::CloseHandles() { |
| 110 for (std::vector<Handle>::iterator it = handles_.begin(); | 161 for (std::vector<Handle>::iterator it = handles_.begin(); |
| 111 it != handles_.end(); ++it) { | 162 it != handles_.end(); ++it) { |
| 112 if (it->is_valid()) | 163 if (it->is_valid()) |
| 113 CloseRaw(*it); | 164 CloseRaw(*it); |
| 114 } | 165 } |
| 115 } | 166 } |
| 116 | 167 |
| 168 void Message::SerializeAssociatedEndpointHandles( | |
| 169 AssociatedGroupController* group_controller) { | |
| 170 if (associated_endpoint_handles_.empty()) | |
| 171 return; | |
| 172 | |
| 173 DCHECK_GE(version(), 2u); | |
| 174 DCHECK(header_v2()->payload_interface_ids.is_null()); | |
| 175 | |
| 176 size_t size = associated_endpoint_handles_.size(); | |
| 177 auto data = internal::Array_Data<uint32_t>::New(size, buffer()); | |
| 178 header_v2()->payload_interface_ids.Set(data); | |
| 179 | |
| 180 for (size_t i = 0; i < size; ++i) { | |
| 181 ScopedInterfaceEndpointHandle& handle = associated_endpoint_handles_[i]; | |
| 182 | |
| 183 DCHECK(handle.is_valid()); | |
| 184 DCHECK(!handle.is_local()); | |
| 185 DCHECK_EQ(group_controller, handle.group_controller()); | |
| 186 data->storage()[i] = handle.release(); | |
| 187 } | |
| 188 associated_endpoint_handles_.clear(); | |
| 189 } | |
| 190 | |
| 191 bool Message::DeserializeAssociatedEndpointHandles( | |
| 192 AssociatedGroupController* group_controller) { | |
| 193 associated_endpoint_handles_.clear(); | |
| 194 | |
| 195 uint32_t num_ids = payload_num_interface_ids(); | |
| 196 if (num_ids == 0) | |
| 197 return true; | |
| 198 | |
| 199 associated_endpoint_handles_.reserve(num_ids); | |
| 200 uint32_t* ids = header_v2()->payload_interface_ids.Get()->storage(); | |
| 201 bool result = true; | |
| 202 for (uint32_t i = 0; i < num_ids; ++i) { | |
| 203 auto handle = group_controller->CreateLocalEndpointHandle(ids[i]); | |
| 204 if (IsValidInterfaceId(ids[i]) && !handle.is_valid()) { | |
| 205 // |ids[i]| itself is valid but handle creation failed. In that case, mark | |
| 206 // deserialization as failed but continue to deserialize the rest of | |
| 207 // handles. | |
| 208 result = false; | |
| 209 } | |
| 210 | |
| 211 associated_endpoint_handles_.push_back(std::move(handle)); | |
| 212 ids[i] = kInvalidInterfaceId; | |
| 213 } | |
| 214 return result; | |
| 215 } | |
| 216 | |
| 117 PassThroughFilter::PassThroughFilter() {} | 217 PassThroughFilter::PassThroughFilter() {} |
| 118 | 218 |
| 119 PassThroughFilter::~PassThroughFilter() {} | 219 PassThroughFilter::~PassThroughFilter() {} |
| 120 | 220 |
| 121 bool PassThroughFilter::Accept(Message* message) { return true; } | 221 bool PassThroughFilter::Accept(Message* message) { return true; } |
| 122 | 222 |
| 123 SyncMessageResponseContext::SyncMessageResponseContext() | 223 SyncMessageResponseContext::SyncMessageResponseContext() |
| 124 : outer_context_(current()) { | 224 : outer_context_(current()) { |
| 125 g_tls_sync_response_context.Get().Set(this); | 225 g_tls_sync_response_context.Get().Set(this); |
| 126 } | 226 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 | 288 |
| 189 ReportBadMessageCallback GetBadMessageCallback() { | 289 ReportBadMessageCallback GetBadMessageCallback() { |
| 190 internal::MessageDispatchContext* context = | 290 internal::MessageDispatchContext* context = |
| 191 internal::MessageDispatchContext::current(); | 291 internal::MessageDispatchContext::current(); |
| 192 DCHECK(context); | 292 DCHECK(context); |
| 193 return context->GetBadMessageCallback(); | 293 return context->GetBadMessageCallback(); |
| 194 } | 294 } |
| 195 | 295 |
| 196 namespace internal { | 296 namespace internal { |
| 197 | 297 |
| 298 MessageHeaderV2::MessageHeaderV2() = default; | |
| 299 | |
| 198 MessageDispatchContext::MessageDispatchContext(Message* message) | 300 MessageDispatchContext::MessageDispatchContext(Message* message) |
| 199 : outer_context_(current()), message_(message) { | 301 : outer_context_(current()), message_(message) { |
| 200 g_tls_message_dispatch_context.Get().Set(this); | 302 g_tls_message_dispatch_context.Get().Set(this); |
| 201 } | 303 } |
| 202 | 304 |
| 203 MessageDispatchContext::~MessageDispatchContext() { | 305 MessageDispatchContext::~MessageDispatchContext() { |
| 204 DCHECK_EQ(current(), this); | 306 DCHECK_EQ(current(), this); |
| 205 g_tls_message_dispatch_context.Get().Set(outer_context_); | 307 g_tls_message_dispatch_context.Get().Set(outer_context_); |
| 206 } | 308 } |
| 207 | 309 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 222 // static | 324 // static |
| 223 void SyncMessageResponseSetup::SetCurrentSyncResponseMessage(Message* message) { | 325 void SyncMessageResponseSetup::SetCurrentSyncResponseMessage(Message* message) { |
| 224 SyncMessageResponseContext* context = SyncMessageResponseContext::current(); | 326 SyncMessageResponseContext* context = SyncMessageResponseContext::current(); |
| 225 if (context) | 327 if (context) |
| 226 context->response_ = std::move(*message); | 328 context->response_ = std::move(*message); |
| 227 } | 329 } |
| 228 | 330 |
| 229 } // namespace internal | 331 } // namespace internal |
| 230 | 332 |
| 231 } // namespace mojo | 333 } // namespace mojo |
| OLD | NEW |