Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ipc / mojo / ipc_channel_mojo_readers.cc
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_channel_mojo_readers.h"
6
7 #include "ipc/mojo/ipc_channel_mojo.h"
8 #include "mojo/embedder/embedder.h"
9
10 #if defined(OS_POSIX) && !defined(OS_NACL)
11 #include "ipc/file_descriptor_set_posix.h"
12 #endif
13
14 namespace IPC {
15 namespace internal {
16
17 namespace {
18
19 // TODO(morrita): This should be built using higher-level Mojo construct
20 // for clarity and extensibility.
21 class HelloMessage {
22  public:
23   static Pickle CreateRequest(int32 pid) {
24     Pickle request;
25     request.WriteString(kHelloRequestMagic);
26     request.WriteInt(pid);
27     return request;
28   }
29
30   static bool ReadRequest(Pickle& pickle, int32* pid) {
31     PickleIterator iter(pickle);
32     std::string hello;
33     if (!iter.ReadString(&hello)) {
34       DLOG(WARNING) << "Failed to Read magic string.";
35       return false;
36     }
37
38     if (hello != kHelloRequestMagic) {
39       DLOG(WARNING) << "Magic mismatch:" << hello;
40       return false;
41     }
42
43     int read_pid;
44     if (!iter.ReadInt(&read_pid)) {
45       DLOG(WARNING) << "Failed to Read PID.";
46       return false;
47     }
48
49     *pid = read_pid;
50     return true;
51   }
52
53   static Pickle CreateResponse(int32 pid) {
54     Pickle request;
55     request.WriteString(kHelloResponseMagic);
56     request.WriteInt(pid);
57     return request;
58   }
59
60   static bool ReadResponse(Pickle& pickle, int32* pid) {
61     PickleIterator iter(pickle);
62     std::string hello;
63     if (!iter.ReadString(&hello)) {
64       DLOG(WARNING) << "Failed to read magic string.";
65       return false;
66     }
67
68     if (hello != kHelloResponseMagic) {
69       DLOG(WARNING) << "Magic mismatch:" << hello;
70       return false;
71     }
72
73     int read_pid;
74     if (!iter.ReadInt(&read_pid)) {
75       DLOG(WARNING) << "Failed to read PID.";
76       return false;
77     }
78
79     *pid = read_pid;
80     return true;
81   }
82
83  private:
84   static const char* kHelloRequestMagic;
85   static const char* kHelloResponseMagic;
86 };
87
88 const char* HelloMessage::kHelloRequestMagic = "MREQ";
89 const char* HelloMessage::kHelloResponseMagic = "MRES";
90
91 }  // namespace
92
93 //------------------------------------------------------------------------------
94
95 MessageReader::MessageReader(mojo::ScopedMessagePipeHandle pipe,
96                              ChannelMojo* owner)
97     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
98 }
99
100 void MessageReader::OnMessageReceived() {
101   Message message(data_buffer().empty() ? "" : &data_buffer()[0],
102                   static_cast<uint32>(data_buffer().size()));
103
104   std::vector<MojoHandle> handle_buffer;
105   TakeHandleBuffer(&handle_buffer);
106 #if defined(OS_POSIX) && !defined(OS_NACL)
107   MojoResult write_result =
108       ChannelMojo::WriteToFileDescriptorSet(handle_buffer, &message);
109   if (write_result != MOJO_RESULT_OK) {
110     CloseWithError(write_result);
111     return;
112   }
113 #else
114   DCHECK(handle_buffer.empty());
115 #endif
116
117   message.TraceMessageEnd();
118   owner_->OnMessageReceived(message);
119 }
120
121 void MessageReader::OnPipeClosed() {
122   if (!owner_)
123     return;
124   owner_->OnPipeClosed(this);
125   owner_ = NULL;
126 }
127
128 void MessageReader::OnPipeError(MojoResult error) {
129   if (!owner_)
130     return;
131   owner_->OnPipeError(this);
132 }
133
134 bool MessageReader::Send(scoped_ptr<Message> message) {
135   DCHECK(IsValid());
136
137   message->TraceMessageBegin();
138   std::vector<MojoHandle> handles;
139 #if defined(OS_POSIX) && !defined(OS_NACL)
140   MojoResult read_result =
141       ChannelMojo::ReadFromFileDescriptorSet(message.get(), &handles);
142   if (read_result != MOJO_RESULT_OK) {
143     std::for_each(handles.begin(), handles.end(), &MojoClose);
144     CloseWithError(read_result);
145     return false;
146   }
147 #endif
148   MojoResult write_result =
149       MojoWriteMessage(handle(),
150                        message->data(),
151                        static_cast<uint32>(message->size()),
152                        handles.empty() ? NULL : &handles[0],
153                        static_cast<uint32>(handles.size()),
154                        MOJO_WRITE_MESSAGE_FLAG_NONE);
155   if (MOJO_RESULT_OK != write_result) {
156     std::for_each(handles.begin(), handles.end(), &MojoClose);
157     CloseWithError(write_result);
158     return false;
159   }
160
161   return true;
162 }
163
164 //------------------------------------------------------------------------------
165
166 ControlReader::ControlReader(mojo::ScopedMessagePipeHandle pipe,
167                              ChannelMojo* owner)
168     : internal::MessagePipeReader(pipe.Pass()), owner_(owner) {
169 }
170
171 void ControlReader::OnPipeClosed() {
172   if (!owner_)
173     return;
174   owner_->OnPipeClosed(this);
175   owner_ = NULL;
176 }
177
178 void ControlReader::OnPipeError(MojoResult error) {
179   if (!owner_)
180     return;
181   owner_->OnPipeError(this);
182 }
183
184 bool ControlReader::Connect() {
185   return true;
186 }
187
188 //------------------------------------------------------------------------------
189
190 ServerControlReader::ServerControlReader(mojo::ScopedMessagePipeHandle pipe,
191                                          ChannelMojo* owner)
192     : ControlReader(pipe.Pass(), owner) {
193 }
194
195 ServerControlReader::~ServerControlReader() {
196 }
197
198 bool ServerControlReader::Connect() {
199   MojoResult result = SendHelloRequest();
200   if (result != MOJO_RESULT_OK) {
201     CloseWithError(result);
202     return false;
203   }
204
205   return true;
206 }
207
208 MojoResult ServerControlReader::SendHelloRequest() {
209   DCHECK(IsValid());
210   DCHECK(!message_pipe_.is_valid());
211
212   mojo::ScopedMessagePipeHandle self;
213   mojo::ScopedMessagePipeHandle peer;
214   MojoResult create_result =
215       mojo::CreateMessagePipe(NULL, &message_pipe_, &peer);
216   if (MOJO_RESULT_OK != create_result) {
217     DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
218     return create_result;
219   }
220
221   MojoHandle peer_to_send = peer.get().value();
222   Pickle request = HelloMessage::CreateRequest(owner_->GetSelfPID());
223   MojoResult write_result =
224       MojoWriteMessage(handle(),
225                        request.data(),
226                        static_cast<uint32>(request.size()),
227                        &peer_to_send,
228                        1,
229                        MOJO_WRITE_MESSAGE_FLAG_NONE);
230   if (MOJO_RESULT_OK != write_result) {
231     DLOG(WARNING) << "Writing Hello request failed: " << create_result;
232     return write_result;
233   }
234
235   // |peer| is sent and no longer owned by |this|.
236   (void)peer.release();
237   return MOJO_RESULT_OK;
238 }
239
240 MojoResult ServerControlReader::RespondHelloResponse() {
241   Pickle request(data_buffer().empty() ? "" : &data_buffer()[0],
242                  static_cast<uint32>(data_buffer().size()));
243
244   int32 read_pid = 0;
245   if (!HelloMessage::ReadResponse(request, &read_pid)) {
246     DLOG(ERROR) << "Failed to parse Hello response.";
247     return MOJO_RESULT_UNKNOWN;
248   }
249
250   base::ProcessId pid = static_cast<base::ProcessId>(read_pid);
251   owner_->set_peer_pid(pid);
252   owner_->OnConnected(message_pipe_.Pass());
253   return MOJO_RESULT_OK;
254 }
255
256 void ServerControlReader::OnMessageReceived() {
257   MojoResult result = RespondHelloResponse();
258   if (result != MOJO_RESULT_OK)
259     CloseWithError(result);
260 }
261
262 //------------------------------------------------------------------------------
263
264 ClientControlReader::ClientControlReader(mojo::ScopedMessagePipeHandle pipe,
265                                          ChannelMojo* owner)
266     : ControlReader(pipe.Pass(), owner) {
267 }
268
269 MojoResult ClientControlReader::RespondHelloRequest(
270     MojoHandle message_channel) {
271   DCHECK(IsValid());
272
273   mojo::ScopedMessagePipeHandle received_pipe(
274       (mojo::MessagePipeHandle(message_channel)));
275
276   int32 read_request = 0;
277   Pickle request(data_buffer().empty() ? "" : &data_buffer()[0],
278                  static_cast<uint32>(data_buffer().size()));
279   if (!HelloMessage::ReadRequest(request, &read_request)) {
280     DLOG(ERROR) << "Hello request has wrong magic.";
281     return MOJO_RESULT_UNKNOWN;
282   }
283
284   base::ProcessId pid = read_request;
285   Pickle response = HelloMessage::CreateResponse(owner_->GetSelfPID());
286   MojoResult write_result =
287       MojoWriteMessage(handle(),
288                        response.data(),
289                        static_cast<uint32>(response.size()),
290                        NULL,
291                        0,
292                        MOJO_WRITE_MESSAGE_FLAG_NONE);
293   if (MOJO_RESULT_OK != write_result) {
294     DLOG(ERROR) << "Writing Hello response failed: " << write_result;
295     return write_result;
296   }
297
298   owner_->set_peer_pid(pid);
299   owner_->OnConnected(received_pipe.Pass());
300   return MOJO_RESULT_OK;
301 }
302
303 void ClientControlReader::OnMessageReceived() {
304   std::vector<MojoHandle> handle_buffer;
305   TakeHandleBuffer(&handle_buffer);
306   if (handle_buffer.size() != 1) {
307     DLOG(ERROR) << "Hello request doesn't contains required handle: "
308                 << handle_buffer.size();
309     CloseWithError(MOJO_RESULT_UNKNOWN);
310     return;
311   }
312
313   MojoResult result = RespondHelloRequest(handle_buffer[0]);
314   if (result != MOJO_RESULT_OK) {
315     DLOG(ERROR) << "Failed to respond Hello request. Closing: " << result;
316     CloseWithError(result);
317   }
318 }
319
320 }  // namespace internal
321 }  // namespace IPC