1 // Copyright 2014 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 "ipc/ipc_message_pipe_reader.h" 6 7 #include <stdint.h> 8 9 #include <utility> 10 11 #include "base/bind.h" 12 #include "base/bind_helpers.h" 13 #include "base/location.h" 14 #include "base/logging.h" 15 #include "base/macros.h" 16 #include "base/single_thread_task_runner.h" 17 #include "base/threading/thread_task_runner_handle.h" 18 #include "ipc/ipc_channel_mojo.h" 19 #include "mojo/public/cpp/bindings/message.h" 20 21 namespace IPC { 22 namespace internal { 23 24 MessagePipeReader::MessagePipeReader( 25 mojo::MessagePipeHandle pipe, 26 mojom::ChannelAssociatedPtr sender, 27 mojo::AssociatedInterfaceRequest<mojom::Channel> receiver, 28 MessagePipeReader::Delegate* delegate) 29 : delegate_(delegate), 30 sender_(std::move(sender)), 31 binding_(this, std::move(receiver)) { 32 sender_.set_connection_error_handler( 33 base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this), 34 MOJO_RESULT_FAILED_PRECONDITION)); 35 binding_.set_connection_error_handler( 36 base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this), 37 MOJO_RESULT_FAILED_PRECONDITION)); 38 } 39 40 MessagePipeReader::~MessagePipeReader() { 41 DCHECK(thread_checker_.CalledOnValidThread()); 42 // The pipe should be closed before deletion. 43 } 44 45 void MessagePipeReader::Close() { 46 DCHECK(thread_checker_.CalledOnValidThread()); 47 sender_.reset(); 48 if (binding_.is_bound()) 49 binding_.Close(); 50 } 51 52 bool MessagePipeReader::Send(std::unique_ptr<Message> message) { 53 CHECK(message->IsValid()); 54 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), 55 "MessagePipeReader::Send", message->flags(), 56 TRACE_EVENT_FLAG_FLOW_OUT); 57 base::Optional<std::vector<mojo::native::SerializedHandlePtr>> handles; 58 MojoResult result = MOJO_RESULT_OK; 59 result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles); 60 if (result != MOJO_RESULT_OK) 61 return false; 62 63 if (!sender_) 64 return false; 65 66 sender_->Receive(MessageView(*message, std::move(handles))); 67 DVLOG(4) << "Send " << message->type() << ": " << message->size(); 68 return true; 69 } 70 71 void MessagePipeReader::GetRemoteInterface( 72 const std::string& name, 73 mojo::ScopedInterfaceEndpointHandle handle) { 74 if (!sender_.is_bound()) 75 return; 76 sender_->GetAssociatedInterface( 77 name, mojom::GenericInterfaceAssociatedRequest(std::move(handle))); 78 } 79 80 void MessagePipeReader::SetPeerPid(int32_t peer_pid) { 81 delegate_->OnPeerPidReceived(peer_pid); 82 } 83 84 void MessagePipeReader::Receive(MessageView message_view) { 85 if (!message_view.size()) { 86 delegate_->OnBrokenDataReceived(); 87 return; 88 } 89 Message message(message_view.data(), message_view.size()); 90 if (!message.IsValid()) { 91 delegate_->OnBrokenDataReceived(); 92 return; 93 } 94 95 DVLOG(4) << "Receive " << message.type() << ": " << message.size(); 96 MojoResult write_result = ChannelMojo::WriteToMessageAttachmentSet( 97 message_view.TakeHandles(), &message); 98 if (write_result != MOJO_RESULT_OK) { 99 OnPipeError(write_result); 100 return; 101 } 102 103 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), 104 "MessagePipeReader::Receive", 105 message.flags(), 106 TRACE_EVENT_FLAG_FLOW_IN); 107 delegate_->OnMessageReceived(message); 108 } 109 110 void MessagePipeReader::GetAssociatedInterface( 111 const std::string& name, 112 mojom::GenericInterfaceAssociatedRequest request) { 113 DCHECK(thread_checker_.CalledOnValidThread()); 114 if (delegate_) 115 delegate_->OnAssociatedInterfaceRequest(name, request.PassHandle()); 116 } 117 118 void MessagePipeReader::OnPipeError(MojoResult error) { 119 DCHECK(thread_checker_.CalledOnValidThread()); 120 121 Close(); 122 123 // NOTE: The delegate call below may delete |this|. 124 if (delegate_) 125 delegate_->OnPipeError(); 126 } 127 128 } // namespace internal 129 } // namespace IPC 130