Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: mojo/public/cpp/bindings/lib/message.cc

Issue 2660733002: Mojo C++ bindings: introduce an optional array to store transferred interface IDs in messages. (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/lib/interface_ptr_state.h ('k') | mojo/public/cpp/bindings/lib/message_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698