OLD | NEW |
| (Empty) |
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/mojo/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/mojo/ipc_channel_mojo.h" | |
19 #include "mojo/public/cpp/bindings/message.h" | |
20 | |
21 namespace IPC { | |
22 namespace internal { | |
23 | |
24 namespace { | |
25 | |
26 // Used by Send() to capture a serialized Channel::Receive message. | |
27 class MessageSerializer : public mojo::MessageReceiverWithResponder { | |
28 public: | |
29 MessageSerializer() {} | |
30 ~MessageSerializer() override {} | |
31 | |
32 mojo::Message* message() { return &message_; } | |
33 | |
34 private: | |
35 // mojo::MessageReceiverWithResponder | |
36 bool Accept(mojo::Message* message) override { | |
37 message->MoveTo(&message_); | |
38 return true; | |
39 } | |
40 | |
41 bool AcceptWithResponder(mojo::Message* message, | |
42 mojo::MessageReceiver* responder) override { | |
43 NOTREACHED(); | |
44 return false; | |
45 } | |
46 | |
47 mojo::Message message_; | |
48 | |
49 DISALLOW_COPY_AND_ASSIGN(MessageSerializer); | |
50 }; | |
51 | |
52 } // namespace | |
53 | |
54 MessagePipeReader::MessagePipeReader( | |
55 mojo::MessagePipeHandle pipe, | |
56 mojom::ChannelAssociatedPtr sender, | |
57 mojo::AssociatedInterfaceRequest<mojom::Channel> receiver, | |
58 base::ProcessId peer_pid, | |
59 MessagePipeReader::Delegate* delegate) | |
60 : delegate_(delegate), | |
61 peer_pid_(peer_pid), | |
62 sender_(std::move(sender)), | |
63 binding_(this, std::move(receiver)), | |
64 sender_interface_id_(sender_.interface_id()), | |
65 sender_pipe_(pipe) { | |
66 sender_.set_connection_error_handler( | |
67 base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this), | |
68 MOJO_RESULT_FAILED_PRECONDITION)); | |
69 binding_.set_connection_error_handler( | |
70 base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this), | |
71 MOJO_RESULT_FAILED_PRECONDITION)); | |
72 } | |
73 | |
74 MessagePipeReader::~MessagePipeReader() { | |
75 DCHECK(thread_checker_.CalledOnValidThread()); | |
76 // The pipe should be closed before deletion. | |
77 } | |
78 | |
79 void MessagePipeReader::Close() { | |
80 DCHECK(thread_checker_.CalledOnValidThread()); | |
81 sender_.reset(); | |
82 if (binding_.is_bound()) | |
83 binding_.Close(); | |
84 } | |
85 | |
86 bool MessagePipeReader::Send(std::unique_ptr<Message> message) { | |
87 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | |
88 "MessagePipeReader::Send", | |
89 message->flags(), | |
90 TRACE_EVENT_FLAG_FLOW_OUT); | |
91 mojo::Array<mojom::SerializedHandlePtr> handles(nullptr); | |
92 MojoResult result = MOJO_RESULT_OK; | |
93 result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles); | |
94 if (result != MOJO_RESULT_OK) | |
95 return false; | |
96 | |
97 mojo::Array<uint8_t> data(message->size()); | |
98 std::copy(reinterpret_cast<const uint8_t*>(message->data()), | |
99 reinterpret_cast<const uint8_t*>(message->data()) + message->size(), | |
100 &data[0]); | |
101 | |
102 MessageSerializer serializer; | |
103 mojom::ChannelProxy proxy(&serializer); | |
104 proxy.Receive(std::move(data), std::move(handles)); | |
105 mojo::Message* mojo_message = serializer.message(); | |
106 | |
107 size_t num_handles = mojo_message->handles()->size(); | |
108 DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max()); | |
109 | |
110 mojo_message->set_interface_id(sender_interface_id_); | |
111 result = mojo::WriteMessageNew(sender_pipe_, mojo_message->TakeMojoMessage(), | |
112 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
113 | |
114 DVLOG(4) << "Send " << message->type() << ": " << message->size(); | |
115 return result == MOJO_RESULT_OK; | |
116 } | |
117 | |
118 void MessagePipeReader::Receive( | |
119 mojo::Array<uint8_t> data, | |
120 mojo::Array<mojom::SerializedHandlePtr> handles) { | |
121 Message message( | |
122 data.size() == 0 ? "" : reinterpret_cast<const char*>(&data[0]), | |
123 static_cast<uint32_t>(data.size())); | |
124 message.set_sender_pid(peer_pid_); | |
125 | |
126 DVLOG(4) << "Receive " << message.type() << ": " << message.size(); | |
127 MojoResult write_result = | |
128 ChannelMojo::WriteToMessageAttachmentSet(std::move(handles), &message); | |
129 if (write_result != MOJO_RESULT_OK) { | |
130 OnPipeError(write_result); | |
131 return; | |
132 } | |
133 | |
134 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | |
135 "MessagePipeReader::Receive", | |
136 message.flags(), | |
137 TRACE_EVENT_FLAG_FLOW_IN); | |
138 delegate_->OnMessageReceived(message); | |
139 } | |
140 | |
141 void MessagePipeReader::OnPipeError(MojoResult error) { | |
142 DCHECK(thread_checker_.CalledOnValidThread()); | |
143 if (delegate_) | |
144 delegate_->OnPipeError(); | |
145 Close(); | |
146 } | |
147 | |
148 void MessagePipeReader::DelayedDeleter::operator()( | |
149 MessagePipeReader* ptr) const { | |
150 ptr->Close(); | |
151 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
152 base::Bind(&DeleteNow, ptr)); | |
153 } | |
154 | |
155 } // namespace internal | |
156 } // namespace IPC | |
OLD | NEW |