Home | History | Annotate | Download | only in ipc
      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