1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/core/user_message_impl.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/atomicops.h" 11 #include "base/memory/ptr_util.h" 12 #include "base/metrics/histogram_macros_local.h" 13 #include "base/no_destructor.h" 14 #include "base/numerics/safe_conversions.h" 15 #include "base/numerics/safe_math.h" 16 // #include "base/trace_event/memory_allocator_dump.h" 17 // #include "base/trace_event/memory_dump_manager.h" 18 // #include "base/trace_event/memory_dump_provider.h" 19 // #include "base/trace_event/trace_event.h" 20 #include "mojo/core/core.h" 21 #include "mojo/core/node_channel.h" 22 #include "mojo/core/node_controller.h" 23 #include "mojo/core/ports/event.h" 24 #include "mojo/core/ports/message_filter.h" 25 #include "mojo/core/ports/node.h" 26 #include "mojo/public/c/system/types.h" 27 28 namespace mojo { 29 namespace core { 30 31 namespace { 32 33 // The minimum amount of memory to allocate for a new serialized message buffer. 34 // This should be sufficiently large such that most seiralized messages do not 35 // incur any reallocations as they're expanded to full size. 36 const uint32_t kMinimumPayloadBufferSize = 128; 37 38 // Indicates whether handle serialization failure should be emulated in testing. 39 bool g_always_fail_handle_serialization = false; 40 41 #pragma pack(push, 1) 42 // Header attached to every message. 43 struct MessageHeader { 44 // The number of serialized dispatchers included in this header. 45 uint32_t num_dispatchers; 46 47 // Total size of the header, including serialized dispatcher data. 48 uint32_t header_size; 49 }; 50 51 // Header for each dispatcher in a message, immediately following the message 52 // header. 53 struct DispatcherHeader { 54 // The type of the dispatcher, correpsonding to the Dispatcher::Type enum. 55 int32_t type; 56 57 // The size of the serialized dispatcher, not including this header. 58 uint32_t num_bytes; 59 60 // The number of ports needed to deserialize this dispatcher. 61 uint32_t num_ports; 62 63 // The number of platform handles needed to deserialize this dispatcher. 64 uint32_t num_platform_handles; 65 }; 66 #pragma pack(pop) 67 68 static_assert(sizeof(MessageHeader) % 8 == 0, "Invalid MessageHeader size."); 69 static_assert(sizeof(DispatcherHeader) % 8 == 0, 70 "Invalid DispatcherHeader size."); 71 72 // Creates a new Channel message with sufficient storage for |num_bytes| user 73 // message payload and all |dispatchers| given. If |original_message| is not 74 // null, its contents are copied and extended by the other parameters given 75 // here. 76 MojoResult CreateOrExtendSerializedEventMessage( 77 ports::UserMessageEvent* event, 78 size_t payload_size, 79 size_t payload_buffer_size, 80 const Dispatcher::DispatcherInTransit* new_dispatchers, 81 size_t num_new_dispatchers, 82 Channel::MessagePtr* out_message, 83 void** out_header, 84 size_t* out_header_size, 85 void** out_user_payload) { 86 // A structure for tracking information about every Dispatcher that will be 87 // serialized into the message. This is NOT part of the message itself. 88 struct DispatcherInfo { 89 uint32_t num_bytes; 90 uint32_t num_ports; 91 uint32_t num_handles; 92 }; 93 94 size_t original_header_size = sizeof(MessageHeader); 95 size_t original_num_ports = 0; 96 size_t original_num_handles = 0; 97 size_t original_payload_size = 0; 98 MessageHeader* original_header = nullptr; 99 void* original_user_payload = nullptr; 100 Channel::MessagePtr original_message; 101 if (*out_message) { 102 original_message = std::move(*out_message); 103 original_header = static_cast<MessageHeader*>(*out_header); 104 original_header_size = *out_header_size; 105 original_num_ports = event->num_ports(); 106 original_num_handles = original_message->num_handles(); 107 original_user_payload = *out_user_payload; 108 original_payload_size = 109 original_message->payload_size() - 110 (static_cast<char*>(original_user_payload) - 111 static_cast<char*>(original_message->mutable_payload())); 112 } 113 114 // This is only the base header size. It will grow as we accumulate the 115 // size of serialized state for each dispatcher. 116 base::CheckedNumeric<size_t> safe_header_size = num_new_dispatchers; 117 safe_header_size *= sizeof(DispatcherHeader); 118 safe_header_size += original_header_size; 119 size_t header_size = safe_header_size.ValueOrDie(); 120 size_t num_new_ports = 0; 121 size_t num_new_handles = 0; 122 std::vector<DispatcherInfo> new_dispatcher_info(num_new_dispatchers); 123 for (size_t i = 0; i < num_new_dispatchers; ++i) { 124 Dispatcher* d = new_dispatchers[i].dispatcher.get(); 125 d->StartSerialize(&new_dispatcher_info[i].num_bytes, 126 &new_dispatcher_info[i].num_ports, 127 &new_dispatcher_info[i].num_handles); 128 header_size += new_dispatcher_info[i].num_bytes; 129 num_new_ports += new_dispatcher_info[i].num_ports; 130 num_new_handles += new_dispatcher_info[i].num_handles; 131 } 132 133 size_t num_ports = original_num_ports + num_new_ports; 134 size_t num_handles = original_num_handles + num_new_handles; 135 136 // We now have enough information to fully allocate the message storage. 137 if (num_ports > event->num_ports()) 138 event->ReservePorts(num_ports); 139 const size_t event_size = event->GetSerializedSize(); 140 const size_t total_size = event_size + header_size + payload_size; 141 const size_t total_buffer_size = 142 event_size + header_size + payload_buffer_size; 143 void* data; 144 Channel::MessagePtr message = NodeChannel::CreateEventMessage( 145 total_buffer_size, total_size, &data, num_handles); 146 auto* header = reinterpret_cast<MessageHeader*>(static_cast<uint8_t*>(data) + 147 event_size); 148 149 // Populate the message header with information about serialized dispatchers. 150 // The front of the message is always a MessageHeader followed by a 151 // DispatcherHeader for each dispatcher to be sent. 152 DispatcherHeader* new_dispatcher_headers; 153 char* new_dispatcher_data; 154 size_t total_num_dispatchers = num_new_dispatchers; 155 std::vector<PlatformHandle> handles; 156 if (original_message) { 157 DCHECK(original_header); 158 size_t original_dispatcher_headers_size = 159 original_header->num_dispatchers * sizeof(DispatcherHeader); 160 memcpy(header, original_header, 161 original_dispatcher_headers_size + sizeof(MessageHeader)); 162 new_dispatcher_headers = reinterpret_cast<DispatcherHeader*>( 163 reinterpret_cast<uint8_t*>(header + 1) + 164 original_dispatcher_headers_size); 165 total_num_dispatchers += original_header->num_dispatchers; 166 size_t total_dispatcher_headers_size = 167 total_num_dispatchers * sizeof(DispatcherHeader); 168 char* original_dispatcher_data = 169 reinterpret_cast<char*>(original_header + 1) + 170 original_dispatcher_headers_size; 171 char* dispatcher_data = 172 reinterpret_cast<char*>(header + 1) + total_dispatcher_headers_size; 173 size_t original_dispatcher_data_size = original_header_size - 174 sizeof(MessageHeader) - 175 original_dispatcher_headers_size; 176 memcpy(dispatcher_data, original_dispatcher_data, 177 original_dispatcher_data_size); 178 new_dispatcher_data = dispatcher_data + original_dispatcher_data_size; 179 auto handles_in_transit = original_message->TakeHandles(); 180 if (!handles_in_transit.empty()) { 181 handles.resize(num_handles); 182 for (size_t i = 0; i < handles_in_transit.size(); ++i) 183 handles[i] = handles_in_transit[i].TakeHandle(); 184 } 185 memcpy(reinterpret_cast<char*>(header) + header_size, 186 reinterpret_cast<char*>(original_header) + original_header_size, 187 original_payload_size); 188 } else { 189 new_dispatcher_headers = reinterpret_cast<DispatcherHeader*>(header + 1); 190 // Serialized dispatcher state immediately follows the series of 191 // DispatcherHeaders. 192 new_dispatcher_data = 193 reinterpret_cast<char*>(new_dispatcher_headers + num_new_dispatchers); 194 } 195 196 if (handles.empty() && num_new_handles) 197 handles.resize(num_new_handles); 198 199 header->num_dispatchers = 200 base::CheckedNumeric<uint32_t>(total_num_dispatchers).ValueOrDie(); 201 202 // |header_size| is the total number of bytes preceding the message payload, 203 // including all dispatcher headers and serialized dispatcher state. 204 if (!base::IsValueInRangeForNumericType<uint32_t>(header_size)) 205 return MOJO_RESULT_OUT_OF_RANGE; 206 207 header->header_size = static_cast<uint32_t>(header_size); 208 209 if (num_new_dispatchers > 0) { 210 size_t port_index = original_num_ports; 211 size_t handle_index = original_num_handles; 212 bool fail = false; 213 for (size_t i = 0; i < num_new_dispatchers; ++i) { 214 Dispatcher* d = new_dispatchers[i].dispatcher.get(); 215 DispatcherHeader* dh = &new_dispatcher_headers[i]; 216 const DispatcherInfo& info = new_dispatcher_info[i]; 217 218 // Fill in the header for this dispatcher. 219 dh->type = static_cast<int32_t>(d->GetType()); 220 dh->num_bytes = info.num_bytes; 221 dh->num_ports = info.num_ports; 222 dh->num_platform_handles = info.num_handles; 223 224 // Fill in serialized state, ports, and platform handles. We'll cancel 225 // the send if the dispatcher implementation rejects for some reason. 226 if (g_always_fail_handle_serialization || 227 !d->EndSerialize( 228 static_cast<void*>(new_dispatcher_data), 229 event->ports() + port_index, 230 !handles.empty() ? handles.data() + handle_index : nullptr)) { 231 fail = true; 232 break; 233 } 234 235 new_dispatcher_data += info.num_bytes; 236 port_index += info.num_ports; 237 handle_index += info.num_handles; 238 } 239 240 if (fail) { 241 // Release any platform handles we've accumulated. Their dispatchers 242 // retain ownership when message creation fails, so these are not actually 243 // leaking. 244 for (auto& handle : handles) 245 handle.release(); 246 247 // Leave the original message in place on failure if applicable. 248 if (original_message) 249 *out_message = std::move(original_message); 250 return MOJO_RESULT_INVALID_ARGUMENT; 251 } 252 253 // Take ownership of all the handles and move them into message storage. 254 message->SetHandles(std::move(handles)); 255 } 256 257 *out_message = std::move(message); 258 *out_header = header; 259 *out_header_size = header_size; 260 *out_user_payload = reinterpret_cast<uint8_t*>(header) + header_size; 261 return MOJO_RESULT_OK; 262 } 263 264 base::subtle::Atomic32 g_message_count = 0; 265 266 void IncrementMessageCount() { 267 base::subtle::NoBarrier_AtomicIncrement(&g_message_count, 1); 268 } 269 270 void DecrementMessageCount() { 271 base::subtle::NoBarrier_AtomicIncrement(&g_message_count, -1); 272 } 273 274 // class MessageMemoryDumpProvider : public base::trace_event::MemoryDumpProvider { 275 // public: 276 // MessageMemoryDumpProvider() { 277 // base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( 278 // this, "MojoMessages", nullptr); 279 // } 280 281 // ~MessageMemoryDumpProvider() override { 282 // base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( 283 // this); 284 // } 285 286 // private: 287 // // base::trace_event::MemoryDumpProvider: 288 // bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, 289 // base::trace_event::ProcessMemoryDump* pmd) override { 290 // auto* dump = pmd->CreateAllocatorDump("mojo/messages"); 291 // dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount, 292 // base::trace_event::MemoryAllocatorDump::kUnitsObjects, 293 // base::subtle::NoBarrier_Load(&g_message_count)); 294 // return true; 295 // } 296 297 // DISALLOW_COPY_AND_ASSIGN(MessageMemoryDumpProvider); 298 // }; 299 300 // void EnsureMemoryDumpProviderExists() { 301 // static base::NoDestructor<MessageMemoryDumpProvider> provider; 302 // ALLOW_UNUSED_LOCAL(provider); 303 // } 304 305 } // namespace 306 307 // static 308 const ports::UserMessage::TypeInfo UserMessageImpl::kUserMessageTypeInfo = {}; 309 310 UserMessageImpl::~UserMessageImpl() { 311 if (HasContext() && context_destructor_) { 312 DCHECK(!channel_message_); 313 DCHECK(!has_serialized_handles_); 314 context_destructor_(context_); 315 } else if (IsSerialized() && has_serialized_handles_) { 316 // Ensure that any handles still serialized within this message are 317 // extracted and closed so they don't leak. 318 std::vector<MojoHandle> handles(num_handles()); 319 MojoResult result = 320 ExtractSerializedHandles(ExtractBadHandlePolicy::kSkip, handles.data()); 321 if (result == MOJO_RESULT_OK) { 322 for (auto handle : handles) { 323 if (handle != MOJO_HANDLE_INVALID) 324 Core::Get()->Close(handle); 325 } 326 } 327 328 if (!pending_handle_attachments_.empty()) { 329 Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_, 330 false); 331 for (const auto& dispatcher : pending_handle_attachments_) 332 Core::Get()->Close(dispatcher.local_handle); 333 } 334 } 335 336 DecrementMessageCount(); 337 } 338 339 // static 340 std::unique_ptr<ports::UserMessageEvent> 341 UserMessageImpl::CreateEventForNewMessage() { 342 auto message_event = std::make_unique<ports::UserMessageEvent>(0); 343 message_event->AttachMessage( 344 base::WrapUnique(new UserMessageImpl(message_event.get()))); 345 return message_event; 346 } 347 348 // static 349 MojoResult UserMessageImpl::CreateEventForNewSerializedMessage( 350 uint32_t num_bytes, 351 const Dispatcher::DispatcherInTransit* dispatchers, 352 uint32_t num_dispatchers, 353 std::unique_ptr<ports::UserMessageEvent>* out_event) { 354 Channel::MessagePtr channel_message; 355 void* header = nullptr; 356 void* user_payload = nullptr; 357 auto event = std::make_unique<ports::UserMessageEvent>(0); 358 size_t header_size = 0; 359 MojoResult rv = CreateOrExtendSerializedEventMessage( 360 event.get(), num_bytes, num_bytes, dispatchers, num_dispatchers, 361 &channel_message, &header, &header_size, &user_payload); 362 if (rv != MOJO_RESULT_OK) 363 return rv; 364 event->AttachMessage(base::WrapUnique( 365 new UserMessageImpl(event.get(), std::move(channel_message), header, 366 header_size, user_payload, num_bytes))); 367 *out_event = std::move(event); 368 return MOJO_RESULT_OK; 369 } 370 371 // static 372 std::unique_ptr<UserMessageImpl> UserMessageImpl::CreateFromChannelMessage( 373 ports::UserMessageEvent* message_event, 374 Channel::MessagePtr channel_message, 375 void* payload, 376 size_t payload_size) { 377 DCHECK(channel_message); 378 if (payload_size < sizeof(MessageHeader)) 379 return nullptr; 380 381 auto* header = static_cast<MessageHeader*>(payload); 382 const size_t header_size = header->header_size; 383 if (header_size > payload_size) 384 return nullptr; 385 386 void* user_payload = static_cast<uint8_t*>(payload) + header_size; 387 const size_t user_payload_size = payload_size - header_size; 388 return base::WrapUnique( 389 new UserMessageImpl(message_event, std::move(channel_message), header, 390 header_size, user_payload, user_payload_size)); 391 } 392 393 // static 394 Channel::MessagePtr UserMessageImpl::FinalizeEventMessage( 395 std::unique_ptr<ports::UserMessageEvent> message_event) { 396 auto* message = message_event->GetMessage<UserMessageImpl>(); 397 DCHECK(message->IsSerialized()); 398 399 if (!message->is_committed_) 400 return nullptr; 401 402 Channel::MessagePtr channel_message = std::move(message->channel_message_); 403 message->user_payload_ = nullptr; 404 message->user_payload_size_ = 0; 405 406 // Serialize the UserMessageEvent into the front of the message payload where 407 // there is already space reserved for it. 408 if (channel_message) { 409 void* data; 410 size_t size; 411 NodeChannel::GetEventMessageData(channel_message.get(), &data, &size); 412 message_event->Serialize(data); 413 } 414 415 return channel_message; 416 } 417 418 size_t UserMessageImpl::user_payload_capacity() const { 419 DCHECK(IsSerialized()); 420 const size_t user_payload_offset = 421 static_cast<uint8_t*>(user_payload_) - 422 static_cast<const uint8_t*>(channel_message_->payload()); 423 const size_t message_capacity = channel_message_->capacity(); 424 DCHECK_LE(user_payload_offset, message_capacity); 425 return message_capacity - user_payload_offset; 426 } 427 428 size_t UserMessageImpl::num_handles() const { 429 DCHECK(IsSerialized()); 430 DCHECK(header_); 431 return static_cast<const MessageHeader*>(header_)->num_dispatchers; 432 } 433 434 MojoResult UserMessageImpl::SetContext( 435 uintptr_t context, 436 MojoMessageContextSerializer serializer, 437 MojoMessageContextDestructor destructor) { 438 if (!context && (serializer || destructor)) 439 return MOJO_RESULT_INVALID_ARGUMENT; 440 if (context && HasContext()) 441 return MOJO_RESULT_ALREADY_EXISTS; 442 if (IsSerialized()) 443 return MOJO_RESULT_FAILED_PRECONDITION; 444 context_ = context; 445 context_serializer_ = serializer; 446 context_destructor_ = destructor; 447 return MOJO_RESULT_OK; 448 } 449 450 MojoResult UserMessageImpl::AppendData(uint32_t additional_payload_size, 451 const MojoHandle* handles, 452 uint32_t num_handles) { 453 if (HasContext()) 454 return MOJO_RESULT_FAILED_PRECONDITION; 455 456 std::vector<Dispatcher::DispatcherInTransit> dispatchers; 457 if (num_handles > 0) { 458 MojoResult acquire_result = Core::Get()->AcquireDispatchersForTransit( 459 handles, num_handles, &dispatchers); 460 if (acquire_result != MOJO_RESULT_OK) 461 return acquire_result; 462 } 463 464 if (!IsSerialized()) { 465 // First data for this message. 466 Channel::MessagePtr channel_message; 467 MojoResult rv = CreateOrExtendSerializedEventMessage( 468 message_event_, additional_payload_size, 469 std::max(additional_payload_size, kMinimumPayloadBufferSize), 470 dispatchers.data(), num_handles, &channel_message, &header_, 471 &header_size_, &user_payload_); 472 if (num_handles > 0) { 473 Core::Get()->ReleaseDispatchersForTransit(dispatchers, 474 rv == MOJO_RESULT_OK); 475 } 476 if (rv != MOJO_RESULT_OK) 477 return MOJO_RESULT_ABORTED; 478 479 user_payload_size_ = additional_payload_size; 480 channel_message_ = std::move(channel_message); 481 has_serialized_handles_ = true; 482 } else { 483 // Extend the existing message payload. 484 485 // In order to avoid rather expensive message resizing on every handle 486 // attachment operation, we merely lock and prepare the handle for transit 487 // here, deferring serialization until |CommitSize()|. 488 std::copy(dispatchers.begin(), dispatchers.end(), 489 std::back_inserter(pending_handle_attachments_)); 490 491 if (additional_payload_size) { 492 size_t header_offset = 493 static_cast<uint8_t*>(header_) - 494 static_cast<const uint8_t*>(channel_message_->payload()); 495 size_t user_payload_offset = 496 static_cast<uint8_t*>(user_payload_) - 497 static_cast<const uint8_t*>(channel_message_->payload()); 498 channel_message_->ExtendPayload(user_payload_offset + user_payload_size_ + 499 additional_payload_size); 500 header_ = static_cast<uint8_t*>(channel_message_->mutable_payload()) + 501 header_offset; 502 user_payload_ = 503 static_cast<uint8_t*>(channel_message_->mutable_payload()) + 504 user_payload_offset; 505 user_payload_size_ += additional_payload_size; 506 } 507 } 508 509 return MOJO_RESULT_OK; 510 } 511 512 MojoResult UserMessageImpl::CommitSize() { 513 if (!IsSerialized()) 514 return MOJO_RESULT_FAILED_PRECONDITION; 515 516 if (is_committed_) 517 return MOJO_RESULT_OK; 518 519 if (!pending_handle_attachments_.empty()) { 520 CreateOrExtendSerializedEventMessage( 521 message_event_, user_payload_size_, user_payload_size_, 522 pending_handle_attachments_.data(), pending_handle_attachments_.size(), 523 &channel_message_, &header_, &header_size_, &user_payload_); 524 Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_, 525 true); 526 pending_handle_attachments_.clear(); 527 } 528 529 is_committed_ = true; 530 return MOJO_RESULT_OK; 531 } 532 533 MojoResult UserMessageImpl::SerializeIfNecessary() { 534 if (IsSerialized()) 535 return MOJO_RESULT_FAILED_PRECONDITION; 536 537 DCHECK(HasContext()); 538 DCHECK(!has_serialized_handles_); 539 if (!context_serializer_) 540 return MOJO_RESULT_NOT_FOUND; 541 542 uintptr_t context = context_; 543 context_ = 0; 544 context_serializer_(reinterpret_cast<MojoMessageHandle>(message_event_), 545 context); 546 547 if (context_destructor_) 548 context_destructor_(context); 549 550 has_serialized_handles_ = true; 551 return MOJO_RESULT_OK; 552 } 553 554 MojoResult UserMessageImpl::ExtractSerializedHandles( 555 ExtractBadHandlePolicy bad_handle_policy, 556 MojoHandle* handles) { 557 if (!IsSerialized()) 558 return MOJO_RESULT_FAILED_PRECONDITION; 559 560 if (!has_serialized_handles_) 561 return MOJO_RESULT_NOT_FOUND; 562 563 const MessageHeader* header = static_cast<const MessageHeader*>(header_); 564 const DispatcherHeader* dispatcher_headers = 565 reinterpret_cast<const DispatcherHeader*>(header + 1); 566 567 if (header->num_dispatchers > std::numeric_limits<uint16_t>::max()) 568 return MOJO_RESULT_ABORTED; 569 570 if (header->num_dispatchers == 0) 571 return MOJO_RESULT_OK; 572 573 has_serialized_handles_ = false; 574 575 std::vector<Dispatcher::DispatcherInTransit> dispatchers( 576 header->num_dispatchers); 577 578 size_t data_payload_index = 579 sizeof(MessageHeader) + 580 header->num_dispatchers * sizeof(DispatcherHeader); 581 if (data_payload_index > header->header_size) 582 return MOJO_RESULT_ABORTED; 583 const char* dispatcher_data = reinterpret_cast<const char*>( 584 dispatcher_headers + header->num_dispatchers); 585 size_t port_index = 0; 586 size_t platform_handle_index = 0; 587 std::vector<PlatformHandleInTransit> handles_in_transit = 588 channel_message_->TakeHandles(); 589 std::vector<PlatformHandle> msg_handles(handles_in_transit.size()); 590 for (size_t i = 0; i < handles_in_transit.size(); ++i) { 591 DCHECK(!handles_in_transit[i].owning_process().is_valid()); 592 msg_handles[i] = handles_in_transit[i].TakeHandle(); 593 } 594 for (size_t i = 0; i < header->num_dispatchers; ++i) { 595 const DispatcherHeader& dh = dispatcher_headers[i]; 596 auto type = static_cast<Dispatcher::Type>(dh.type); 597 598 base::CheckedNumeric<size_t> next_payload_index = data_payload_index; 599 next_payload_index += dh.num_bytes; 600 if (!next_payload_index.IsValid() || 601 header->header_size < next_payload_index.ValueOrDie()) { 602 return MOJO_RESULT_ABORTED; 603 } 604 605 base::CheckedNumeric<size_t> next_port_index = port_index; 606 next_port_index += dh.num_ports; 607 if (!next_port_index.IsValid() || 608 message_event_->num_ports() < next_port_index.ValueOrDie()) { 609 return MOJO_RESULT_ABORTED; 610 } 611 612 base::CheckedNumeric<size_t> next_platform_handle_index = 613 platform_handle_index; 614 next_platform_handle_index += dh.num_platform_handles; 615 if (!next_platform_handle_index.IsValid() || 616 msg_handles.size() < next_platform_handle_index.ValueOrDie()) { 617 return MOJO_RESULT_ABORTED; 618 } 619 620 PlatformHandle* out_handles = 621 !msg_handles.empty() ? msg_handles.data() + platform_handle_index 622 : nullptr; 623 dispatchers[i].dispatcher = Dispatcher::Deserialize( 624 type, dispatcher_data, dh.num_bytes, 625 message_event_->ports() + port_index, dh.num_ports, out_handles, 626 dh.num_platform_handles); 627 if (!dispatchers[i].dispatcher && 628 bad_handle_policy == ExtractBadHandlePolicy::kAbort) { 629 return MOJO_RESULT_ABORTED; 630 } 631 632 dispatcher_data += dh.num_bytes; 633 data_payload_index = next_payload_index.ValueOrDie(); 634 port_index = next_port_index.ValueOrDie(); 635 platform_handle_index = next_platform_handle_index.ValueOrDie(); 636 } 637 638 if (!Core::Get()->AddDispatchersFromTransit(dispatchers, handles)) 639 return MOJO_RESULT_ABORTED; 640 641 return MOJO_RESULT_OK; 642 } 643 644 // static 645 void UserMessageImpl::FailHandleSerializationForTesting(bool fail) { 646 g_always_fail_handle_serialization = fail; 647 } 648 649 UserMessageImpl::UserMessageImpl(ports::UserMessageEvent* message_event) 650 : ports::UserMessage(&kUserMessageTypeInfo), message_event_(message_event) { 651 // EnsureMemoryDumpProviderExists(); 652 IncrementMessageCount(); 653 } 654 655 UserMessageImpl::UserMessageImpl(ports::UserMessageEvent* message_event, 656 Channel::MessagePtr channel_message, 657 void* header, 658 size_t header_size, 659 void* user_payload, 660 size_t user_payload_size) 661 : ports::UserMessage(&kUserMessageTypeInfo), 662 message_event_(message_event), 663 channel_message_(std::move(channel_message)), 664 has_serialized_handles_(true), 665 is_committed_(true), 666 header_(header), 667 header_size_(header_size), 668 user_payload_(user_payload), 669 user_payload_size_(user_payload_size) { 670 // EnsureMemoryDumpProviderExists(); 671 IncrementMessageCount(); 672 } 673 674 bool UserMessageImpl::WillBeRoutedExternally() { 675 MojoResult result = SerializeIfNecessary(); 676 return result == MOJO_RESULT_OK || result == MOJO_RESULT_FAILED_PRECONDITION; 677 } 678 679 size_t UserMessageImpl::GetSizeIfSerialized() const { 680 if (!IsSerialized()) 681 return 0; 682 return user_payload_size_; 683 } 684 685 } // namespace core 686 } // namespace mojo 687