Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: ppapi/proxy/handle_converter.cc

Issue 11894003: PPAPI/NaCl: Move handle extraction code to ppapi/proxy (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/handle_converter.h ('k') | ppapi/proxy/ppapi_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/nacl/nacl_ipc_adapter.h" 5 #include "ppapi/proxy/handle_converter.h"
6 6
7 #include <limits.h> 7 #include "ipc/ipc_message.h"
8 #include <string.h>
9
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/shared_memory.h"
15 #include "build/build_config.h"
16 #include "ipc/ipc_channel.h"
17 #include "ipc/ipc_message_macros.h" 8 #include "ipc/ipc_message_macros.h"
18 #include "ipc/ipc_platform_file.h"
19 #include "native_client/src/trusted/desc/nacl_desc_custom.h"
20 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
21 #include "ppapi/proxy/ppapi_messages.h" 9 #include "ppapi/proxy/ppapi_messages.h"
22 #include "ppapi/proxy/resource_message_params.h" 10 #include "ppapi/proxy/resource_message_params.h"
11 #include "ppapi/proxy/serialized_handle.h"
12
13 namespace IPC {
14 class Message;
15 }
23 16
24 namespace { 17 namespace {
25 18
26 enum BufferSizeStatus {
27 // The buffer contains a full message with no extra bytes.
28 MESSAGE_IS_COMPLETE,
29
30 // The message doesn't fit and the buffer contains only some of it.
31 MESSAGE_IS_TRUNCATED,
32
33 // The buffer contains a full message + extra data.
34 MESSAGE_HAS_EXTRA_DATA
35 };
36
37 BufferSizeStatus GetBufferStatus(const char* data, size_t len) {
38 if (len < sizeof(NaClIPCAdapter::NaClMessageHeader))
39 return MESSAGE_IS_TRUNCATED;
40
41 const NaClIPCAdapter::NaClMessageHeader* header =
42 reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(data);
43 uint32 message_size =
44 sizeof(NaClIPCAdapter::NaClMessageHeader) + header->payload_size;
45
46 if (len == message_size)
47 return MESSAGE_IS_COMPLETE;
48 if (len > message_size)
49 return MESSAGE_HAS_EXTRA_DATA;
50 return MESSAGE_IS_TRUNCATED;
51 }
52
53 // This object allows the NaClDesc to hold a reference to a NaClIPCAdapter and
54 // forward calls to it.
55 struct DescThunker {
56 explicit DescThunker(NaClIPCAdapter* adapter_param)
57 : adapter(adapter_param) {
58 }
59 scoped_refptr<NaClIPCAdapter> adapter;
60 };
61
62 NaClIPCAdapter* ToAdapter(void* handle) {
63 return static_cast<DescThunker*>(handle)->adapter.get();
64 }
65
66 // NaClDescCustom implementation.
67 void NaClDescCustomDestroy(void* handle) {
68 delete static_cast<DescThunker*>(handle);
69 }
70
71 ssize_t NaClDescCustomSendMsg(void* handle, const NaClImcTypedMsgHdr* msg,
72 int /* flags */) {
73 return static_cast<ssize_t>(ToAdapter(handle)->Send(msg));
74 }
75
76 ssize_t NaClDescCustomRecvMsg(void* handle, NaClImcTypedMsgHdr* msg,
77 int /* flags */) {
78 return static_cast<ssize_t>(ToAdapter(handle)->BlockingReceive(msg));
79 }
80
81 NaClDesc* MakeNaClDescCustom(NaClIPCAdapter* adapter) {
82 NaClDescCustomFuncs funcs = NACL_DESC_CUSTOM_FUNCS_INITIALIZER;
83 funcs.Destroy = NaClDescCustomDestroy;
84 funcs.SendMsg = NaClDescCustomSendMsg;
85 funcs.RecvMsg = NaClDescCustomRecvMsg;
86 // NaClDescMakeCustomDesc gives us a reference on the returned NaClDesc.
87 return NaClDescMakeCustomDesc(new DescThunker(adapter), &funcs);
88 }
89
90 void DeleteChannel(IPC::Channel* channel) {
91 delete channel;
92 }
93
94 // TODO(dmichael): Move all this handle conversion code to ppapi/proxy.
95 // crbug.com/165201
96 void WriteHandle(int handle_index, 19 void WriteHandle(int handle_index,
97 const ppapi::proxy::SerializedHandle& handle, 20 const ppapi::proxy::SerializedHandle& handle,
98 IPC::Message* message) { 21 IPC::Message* message) {
99 ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message); 22 ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message);
100 23
101 // Now write the handle itself in POSIX style. 24 // Now write the handle itself in POSIX style.
102 message->WriteBool(true); // valid == true 25 message->WriteBool(true); // valid == true
103 message->WriteInt(handle_index); 26 message->WriteInt(handle_index);
104 } 27 }
105 28
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles, 112 void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles,
190 IPC::Message* msg) { 113 IPC::Message* msg) {
191 int handle_index = 0; 114 int handle_index = 0;
192 ConvertHandlesInParam(t1.a, handles, msg, &handle_index); 115 ConvertHandlesInParam(t1.a, handles, msg, &handle_index);
193 ConvertHandlesInParam(t1.b, handles, msg, &handle_index); 116 ConvertHandlesInParam(t1.b, handles, msg, &handle_index);
194 ConvertHandlesInParam(t1.c, handles, msg, &handle_index); 117 ConvertHandlesInParam(t1.c, handles, msg, &handle_index);
195 ConvertHandlesInParam(t1.d, handles, msg, &handle_index); 118 ConvertHandlesInParam(t1.d, handles, msg, &handle_index);
196 } 119 }
197 120
198 template <class MessageType> 121 template <class MessageType>
199 class HandleConverter { 122 class HandleConverterImpl {
200 public: 123 public:
201 explicit HandleConverter(const IPC::Message* msg) 124 explicit HandleConverterImpl(const IPC::Message* msg)
202 : msg_(static_cast<const MessageType*>(msg)) { 125 : msg_(static_cast<const MessageType*>(msg)) {
203 } 126 }
204 bool ConvertMessage(Handles* handles, IPC::Message* out_msg) { 127 bool ConvertMessage(Handles* handles, IPC::Message* out_msg) {
205 typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params; 128 typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params;
206 if (!MessageType::Read(msg_, &params)) 129 if (!MessageType::Read(msg_, &params))
207 return false; 130 return false;
208 ConvertHandlesImpl(params, handles, out_msg); 131 ConvertHandlesImpl(params, handles, out_msg);
209 return true; 132 return true;
210 } 133 }
211 134
(...skipping 14 matching lines...) Expand all
226 } 149 }
227 // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we 150 // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we
228 // ever pass handles in one of those. 151 // ever pass handles in one of those.
229 152
230 private: 153 private:
231 const MessageType* msg_; 154 const MessageType* msg_;
232 }; 155 };
233 156
234 } // namespace 157 } // namespace
235 158
236 class NaClIPCAdapter::RewrittenMessage
237 : public base::RefCounted<RewrittenMessage> {
238 public:
239 RewrittenMessage();
240
241 bool is_consumed() const { return data_read_cursor_ == data_len_; }
242
243 void SetData(const NaClIPCAdapter::NaClMessageHeader& header,
244 const void* payload, size_t payload_length);
245
246 int Read(NaClImcTypedMsgHdr* msg);
247
248 void AddDescriptor(nacl::DescWrapper* desc) { descs_.push_back(desc); }
249
250 size_t desc_count() const { return descs_.size(); }
251
252 private:
253 friend class base::RefCounted<RewrittenMessage>;
254 ~RewrittenMessage() {}
255
256 scoped_array<char> data_;
257 size_t data_len_;
258
259 // Offset into data where the next read will happen. This will be equal to
260 // data_len_ when all data has been consumed.
261 size_t data_read_cursor_;
262
263 // Wrapped descriptors for transfer to untrusted code.
264 ScopedVector<nacl::DescWrapper> descs_;
265 };
266
267 NaClIPCAdapter::RewrittenMessage::RewrittenMessage()
268 : data_len_(0),
269 data_read_cursor_(0) {
270 }
271
272 void NaClIPCAdapter::RewrittenMessage::SetData(
273 const NaClIPCAdapter::NaClMessageHeader& header,
274 const void* payload,
275 size_t payload_length) {
276 DCHECK(!data_.get() && data_len_ == 0);
277 size_t header_len = sizeof(NaClIPCAdapter::NaClMessageHeader);
278 data_len_ = header_len + payload_length;
279 data_.reset(new char[data_len_]);
280
281 memcpy(data_.get(), &header, sizeof(NaClIPCAdapter::NaClMessageHeader));
282 memcpy(&data_[header_len], payload, payload_length);
283 }
284
285 int NaClIPCAdapter::RewrittenMessage::Read(NaClImcTypedMsgHdr* msg) {
286 CHECK(data_len_ >= data_read_cursor_);
287 char* dest_buffer = static_cast<char*>(msg->iov[0].base);
288 size_t dest_buffer_size = msg->iov[0].length;
289 size_t bytes_to_write = std::min(dest_buffer_size,
290 data_len_ - data_read_cursor_);
291 if (bytes_to_write == 0)
292 return 0;
293
294 memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write);
295 data_read_cursor_ += bytes_to_write;
296
297 // Once all data has been consumed, transfer any file descriptors.
298 if (is_consumed()) {
299 nacl_abi_size_t desc_count = static_cast<nacl_abi_size_t>(descs_.size());
300 CHECK(desc_count <= msg->ndesc_length);
301 msg->ndesc_length = desc_count;
302 for (nacl_abi_size_t i = 0; i < desc_count; i++) {
303 // Copy the NaClDesc to the buffer and add a ref so it won't be freed
304 // when we clear our ScopedVector.
305 msg->ndescv[i] = descs_[i]->desc();
306 NaClDescRef(descs_[i]->desc());
307 }
308 descs_.clear();
309 } else {
310 msg->ndesc_length = 0;
311 }
312 return static_cast<int>(bytes_to_write);
313 }
314
315 NaClIPCAdapter::LockedData::LockedData()
316 : channel_closed_(false) {
317 }
318
319 NaClIPCAdapter::LockedData::~LockedData() {
320 }
321
322 NaClIPCAdapter::IOThreadData::IOThreadData() {
323 }
324
325 NaClIPCAdapter::IOThreadData::~IOThreadData() {
326 }
327
328 NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle,
329 base::TaskRunner* runner)
330 : lock_(),
331 cond_var_(&lock_),
332 task_runner_(runner),
333 locked_data_() {
334 io_thread_data_.channel_.reset(
335 new IPC::Channel(handle, IPC::Channel::MODE_SERVER, this));
336 // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did,
337 // and that task ran before this constructor completes, the reference count
338 // would go to 1 and then to 0 because of the Task, before we've been returned
339 // to the owning scoped_refptr, which is supposed to give us our first
340 // ref-count.
341 }
342
343 NaClIPCAdapter::NaClIPCAdapter(scoped_ptr<IPC::Channel> channel,
344 base::TaskRunner* runner)
345 : lock_(),
346 cond_var_(&lock_),
347 task_runner_(runner),
348 locked_data_() {
349 io_thread_data_.channel_ = channel.Pass();
350 }
351
352 void NaClIPCAdapter::ConnectChannel() {
353 task_runner_->PostTask(FROM_HERE,
354 base::Bind(&NaClIPCAdapter::ConnectChannelOnIOThread, this));
355 }
356
357 // Note that this message is controlled by the untrusted code. So we should be
358 // skeptical of anything it contains and quick to give up if anything is fishy.
359 int NaClIPCAdapter::Send(const NaClImcTypedMsgHdr* msg) {
360 if (msg->iov_length != 1)
361 return -1;
362
363 base::AutoLock lock(lock_);
364
365 const char* input_data = static_cast<char*>(msg->iov[0].base);
366 size_t input_data_len = msg->iov[0].length;
367 if (input_data_len > IPC::Channel::kMaximumMessageSize) {
368 ClearToBeSent();
369 return -1;
370 }
371
372 // current_message[_len] refers to the total input data received so far.
373 const char* current_message;
374 size_t current_message_len;
375 bool did_append_input_data;
376 if (locked_data_.to_be_sent_.empty()) {
377 // No accumulated data, we can avoid a copy by referring to the input
378 // buffer (the entire message fitting in one call is the common case).
379 current_message = input_data;
380 current_message_len = input_data_len;
381 did_append_input_data = false;
382 } else {
383 // We've already accumulated some data, accumulate this new data and
384 // point to the beginning of the buffer.
385
386 // Make sure our accumulated message size doesn't overflow our max. Since
387 // we know that data_len < max size (checked above) and our current
388 // accumulated value is also < max size, we just need to make sure that
389 // 2x max size can never overflow.
390 COMPILE_ASSERT(IPC::Channel::kMaximumMessageSize < (UINT_MAX / 2),
391 MaximumMessageSizeWillOverflow);
392 size_t new_size = locked_data_.to_be_sent_.size() + input_data_len;
393 if (new_size > IPC::Channel::kMaximumMessageSize) {
394 ClearToBeSent();
395 return -1;
396 }
397
398 locked_data_.to_be_sent_.append(input_data, input_data_len);
399 current_message = &locked_data_.to_be_sent_[0];
400 current_message_len = locked_data_.to_be_sent_.size();
401 did_append_input_data = true;
402 }
403
404 // Check the total data we've accumulated so far to see if it contains a full
405 // message.
406 switch (GetBufferStatus(current_message, current_message_len)) {
407 case MESSAGE_IS_COMPLETE: {
408 // Got a complete message, can send it out. This will be the common case.
409 bool success = SendCompleteMessage(current_message, current_message_len);
410 ClearToBeSent();
411 return success ? static_cast<int>(input_data_len) : -1;
412 }
413 case MESSAGE_IS_TRUNCATED:
414 // For truncated messages, just accumulate the new data (if we didn't
415 // already do so above) and go back to waiting for more.
416 if (!did_append_input_data)
417 locked_data_.to_be_sent_.append(input_data, input_data_len);
418 return static_cast<int>(input_data_len);
419 case MESSAGE_HAS_EXTRA_DATA:
420 default:
421 // When the plugin gives us too much data, it's an error.
422 ClearToBeSent();
423 return -1;
424 }
425 }
426
427 int NaClIPCAdapter::BlockingReceive(NaClImcTypedMsgHdr* msg) {
428 if (msg->iov_length != 1)
429 return -1;
430
431 int retval = 0;
432 {
433 base::AutoLock lock(lock_);
434 while (locked_data_.to_be_received_.empty() &&
435 !locked_data_.channel_closed_)
436 cond_var_.Wait();
437 if (locked_data_.channel_closed_) {
438 retval = -1;
439 } else {
440 retval = LockedReceive(msg);
441 DCHECK(retval > 0);
442 }
443 }
444 cond_var_.Signal();
445 return retval;
446 }
447
448 void NaClIPCAdapter::CloseChannel() {
449 {
450 base::AutoLock lock(lock_);
451 locked_data_.channel_closed_ = true;
452 }
453 cond_var_.Signal();
454
455 task_runner_->PostTask(FROM_HERE,
456 base::Bind(&NaClIPCAdapter::CloseChannelOnIOThread, this));
457 }
458
459 NaClDesc* NaClIPCAdapter::MakeNaClDesc() {
460 return MakeNaClDescCustom(this);
461 }
462
463 #if defined(OS_POSIX)
464 int NaClIPCAdapter::TakeClientFileDescriptor() {
465 return io_thread_data_.channel_->TakeClientFileDescriptor();
466 }
467 #endif
468
469 #define CASE_FOR_MESSAGE(MESSAGE_TYPE) \ 159 #define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
470 case MESSAGE_TYPE::ID: { \ 160 case MESSAGE_TYPE::ID: { \
471 HandleConverter<MESSAGE_TYPE> extractor(&msg); \ 161 HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \
472 if (!extractor.ConvertMessage(&handles, new_msg_ptr)) \ 162 if (!extractor.ConvertMessage(handles, new_msg_ptr->get())) \
473 return false; \ 163 return false; \
474 break; \ 164 break; \
475 } 165 }
476 #define CASE_FOR_REPLY(MESSAGE_TYPE) \ 166 #define CASE_FOR_REPLY(MESSAGE_TYPE) \
477 case MESSAGE_TYPE::ID: { \ 167 case MESSAGE_TYPE::ID: { \
478 HandleConverter<MESSAGE_TYPE> extractor(&msg); \ 168 HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \
479 if (!extractor.ConvertReply( \ 169 if (!extractor.ConvertReply( \
480 &handles, \ 170 handles, \
481 static_cast<IPC::SyncMessage*>(new_msg_ptr))) \ 171 static_cast<IPC::SyncMessage*>(new_msg_ptr->get()))) \
482 return false; \ 172 return false; \
483 break; \ 173 break; \
484 } 174 }
485 175
486 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { 176 namespace ppapi {
487 { 177 namespace proxy {
488 base::AutoLock lock(lock_);
489 178
490 scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage); 179 class SerializedHandle;
491 180
492 // Pointer to the "new" message we will rewrite on Windows. On posix, this 181 HandleConverter::HandleConverter() {
493 // isn't necessary, so it will stay NULL. 182 }
494 IPC::Message* new_msg_ptr = NULL; 183
495 IPC::Message new_msg(msg.routing_id(), msg.type(), msg.priority()); 184 bool HandleConverter::ConvertNativeHandlesToPosix(
185 const IPC::Message& msg,
186 std::vector<SerializedHandle>* handles,
187 scoped_ptr<IPC::Message>* new_msg_ptr) {
188 DCHECK(handles);
189 DCHECK(new_msg_ptr);
190 DCHECK(!new_msg_ptr->get());
191
192 // In Windows, we need to re-write the contents of the message. This is
193 // because in Windows IPC code, native HANDLE values are serialized in the
194 // body of the message.
195 //
196 // In POSIX, we only serialize an index in to a FileDescriptorSet, and the
197 // actual file descriptors are sent out-of-band. So on Windows, to make a
198 // message that's compatible with Windows, we need to write a new message that
199 // has simple indices in the message body instead of the HANDLEs.
200 //
201 // NOTE: This means on Windows, new_msg_ptr's serialized contents are not
202 // compatible with Windows IPC deserialization code; it is intended to be
203 // passed to NaCl.
496 #if defined(OS_WIN) 204 #if defined(OS_WIN)
497 new_msg_ptr = &new_msg; 205 new_msg_ptr->reset(
206 new IPC::Message(msg.routing_id(), msg.type(), msg.priority()));
498 #else 207 #else
499 // Even on POSIX, we have to rewrite messages to create channels, because 208 // Even on POSIX, we have to rewrite messages to create channels, because
500 // these contain a handle with an invalid (place holder) descriptor. The 209 // these contain a handle with an invalid (place holder) descriptor. The
501 // message sending code sees this and doesn't pass the descriptor over 210 // message sending code sees this and doesn't pass the descriptor over
502 // correctly. 211 // correctly.
503 if (msg.type() == PpapiMsg_CreateNaClChannel::ID) 212 if (msg.type() == PpapiMsg_CreateNaClChannel::ID) {
504 new_msg_ptr = &new_msg; 213 new_msg_ptr->reset(
214 new IPC::Message(msg.routing_id(), msg.type(), msg.priority()));
215 }
505 #endif 216 #endif
506 217
507 Handles handles; 218 switch (msg.type()) {
508 switch (msg.type()) { 219 CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel)
509 CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) 220 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
510 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) 221 CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
511 CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) 222 case IPC_REPLY_ID: {
512 case IPC_REPLY_ID: { 223 int id = IPC::SyncMessage::GetMessageId(msg);
513 int id = IPC::SyncMessage::GetMessageId(msg); 224 PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id));
514 LockedData::PendingSyncMsgMap::iterator iter( 225 if (iter == pending_sync_msgs_.end()) {
515 locked_data_.pending_sync_msgs_.find(id)); 226 NOTREACHED();
516 if (iter == locked_data_.pending_sync_msgs_.end()) { 227 return false;
517 NOTREACHED();
518 return false;
519 }
520 uint32_t type = iter->second;
521 locked_data_.pending_sync_msgs_.erase(iter);
522 switch (type) {
523 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
524 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl)
525 CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
526 default:
527 // Do nothing for messages we don't know.
528 break;
529 }
530 break;
531 } 228 }
532 default: 229 uint32_t type = iter->second;
533 // Do nothing for messages we don't know. 230 pending_sync_msgs_.erase(iter);
534 break; 231 switch (type) {
232 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
233 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl)
234 CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
235 default:
236 // Do nothing for messages we don't know.
237 break;
238 }
239 break;
535 } 240 }
536 // Now add any descriptors we found to rewritten_msg. |handles| is usually 241 default:
537 // empty, unless we read a message containing a FD or handle. 242 // Do nothing for messages we don't know.
538 nacl::DescWrapperFactory factory; 243 break;
539 for (Handles::const_iterator iter = handles.begin();
540 iter != handles.end();
541 ++iter) {
542 scoped_ptr<nacl::DescWrapper> nacl_desc;
543 switch (iter->type()) {
544 case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
545 const base::SharedMemoryHandle& shm_handle = iter->shmem();
546 uint32_t size = iter->size();
547 nacl_desc.reset(factory.ImportShmHandle(
548 #if defined(OS_WIN)
549 reinterpret_cast<const NaClHandle>(shm_handle),
550 #else
551 shm_handle.fd,
552 #endif
553 static_cast<size_t>(size)));
554 break;
555 }
556 case ppapi::proxy::SerializedHandle::SOCKET: {
557 nacl_desc.reset(factory.ImportSyncSocketHandle(
558 #if defined(OS_WIN)
559 reinterpret_cast<const NaClHandle>(iter->descriptor())
560 #else
561 iter->descriptor().fd
562 #endif
563 ));
564 break;
565 }
566 case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: {
567 // Check that this came from a PpapiMsg_CreateNaClChannel message.
568 // This code here is only appropriate for that message.
569 DCHECK(msg.type() == PpapiMsg_CreateNaClChannel::ID);
570 IPC::ChannelHandle channel_handle =
571 IPC::Channel::GenerateVerifiedChannelID("nacl");
572 scoped_refptr<NaClIPCAdapter> ipc_adapter(
573 new NaClIPCAdapter(channel_handle, task_runner_));
574 ipc_adapter->ConnectChannel();
575 #if defined(OS_POSIX)
576 channel_handle.socket = base::FileDescriptor(
577 ipc_adapter->TakeClientFileDescriptor(), true);
578 #endif
579 nacl_desc.reset(factory.MakeGeneric(ipc_adapter->MakeNaClDesc()));
580 // Send back a message that the channel was created.
581 scoped_ptr<IPC::Message> response(
582 new PpapiHostMsg_ChannelCreated(channel_handle));
583 task_runner_->PostTask(FROM_HERE,
584 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
585 base::Passed(&response)));
586 break;
587 }
588 case ppapi::proxy::SerializedHandle::FILE:
589 // TODO(raymes): Handle file handles for NaCl.
590 NOTIMPLEMENTED();
591 break;
592 case ppapi::proxy::SerializedHandle::INVALID: {
593 // Nothing to do. TODO(dmichael): Should we log this? Or is it
594 // sometimes okay to pass an INVALID handle?
595 break;
596 }
597 // No default, so the compiler will warn us if new types get added.
598 }
599 if (nacl_desc.get())
600 rewritten_msg->AddDescriptor(nacl_desc.release());
601 }
602 if (new_msg_ptr && !handles.empty())
603 SaveMessage(*new_msg_ptr, rewritten_msg.get());
604 else
605 SaveMessage(msg, rewritten_msg.get());
606 } 244 }
607 cond_var_.Signal();
608 return true; 245 return true;
609 } 246 }
610 247
611 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) { 248 void HandleConverter::RegisterSyncMessageForReply(const IPC::Message& msg) {
249 DCHECK(msg.is_sync());
250
251 int msg_id = IPC::SyncMessage::GetMessageId(msg);
252 DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end());
253
254 pending_sync_msgs_[msg_id] = msg.type();
612 } 255 }
613 256
614 void NaClIPCAdapter::OnChannelError() { 257 } // namespace proxy
615 CloseChannel(); 258 } // namespace ppapi
616 }
617
618 NaClIPCAdapter::~NaClIPCAdapter() {
619 // Make sure the channel is deleted on the IO thread.
620 task_runner_->PostTask(FROM_HERE,
621 base::Bind(&DeleteChannel, io_thread_data_.channel_.release()));
622 }
623
624 int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) {
625 lock_.AssertAcquired();
626
627 if (locked_data_.to_be_received_.empty())
628 return 0;
629 scoped_refptr<RewrittenMessage> current =
630 locked_data_.to_be_received_.front();
631
632 int retval = current->Read(msg);
633
634 // When a message is entirely consumed, remove if from the waiting queue.
635 if (current->is_consumed())
636 locked_data_.to_be_received_.pop();
637
638 return retval;
639 }
640
641 bool NaClIPCAdapter::SendCompleteMessage(const char* buffer,
642 size_t buffer_len) {
643 // The message will have already been validated, so we know it's large enough
644 // for our header.
645 const NaClMessageHeader* header =
646 reinterpret_cast<const NaClMessageHeader*>(buffer);
647
648 // Length of the message not including the body. The data passed to us by the
649 // plugin should match that in the message header. This should have already
650 // been validated by GetBufferStatus.
651 int body_len = static_cast<int>(buffer_len - sizeof(NaClMessageHeader));
652 DCHECK(body_len == static_cast<int>(header->payload_size));
653
654 // We actually discard the flags and only copy the ones we care about. This
655 // is just because message doesn't have a constructor that takes raw flags.
656 scoped_ptr<IPC::Message> msg(
657 new IPC::Message(header->routing, header->type,
658 IPC::Message::PRIORITY_NORMAL));
659 if (header->flags & IPC::Message::SYNC_BIT)
660 msg->set_sync();
661 if (header->flags & IPC::Message::REPLY_BIT)
662 msg->set_reply();
663 if (header->flags & IPC::Message::REPLY_ERROR_BIT)
664 msg->set_reply_error();
665 if (header->flags & IPC::Message::UNBLOCK_BIT)
666 msg->set_unblock(true);
667
668 msg->WriteBytes(&buffer[sizeof(NaClMessageHeader)], body_len);
669
670 // Technically we didn't have to do any of the previous work in the lock. But
671 // sometimes our buffer will point to the to_be_sent_ string which is
672 // protected by the lock, and it's messier to factor Send() such that it can
673 // unlock for us. Holding the lock for the message construction, which is
674 // just some memcpys, shouldn't be a big deal.
675 lock_.AssertAcquired();
676 if (locked_data_.channel_closed_)
677 return false; // TODO(brettw) clean up handles here when we add support!
678
679 // Store the type of all sync messages so that later we can translate the
680 // reply if necessary.
681 if (msg->is_sync()) {
682 int id = IPC::SyncMessage::GetMessageId(*msg);
683 locked_data_.pending_sync_msgs_[id] = msg->type();
684 }
685 // Actual send must be done on the I/O thread.
686 task_runner_->PostTask(FROM_HERE,
687 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
688 base::Passed(&msg)));
689 return true;
690 }
691
692 void NaClIPCAdapter::ClearToBeSent() {
693 lock_.AssertAcquired();
694
695 // Don't let the string keep its buffer behind our back.
696 std::string empty;
697 locked_data_.to_be_sent_.swap(empty);
698 }
699
700 void NaClIPCAdapter::ConnectChannelOnIOThread() {
701 if (!io_thread_data_.channel_->Connect())
702 NOTREACHED();
703 }
704
705 void NaClIPCAdapter::CloseChannelOnIOThread() {
706 io_thread_data_.channel_->Close();
707 }
708
709 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
710 io_thread_data_.channel_->Send(message.release());
711 }
712
713 void NaClIPCAdapter::SaveMessage(const IPC::Message& msg,
714 RewrittenMessage* rewritten_msg) {
715 lock_.AssertAcquired();
716 // There is some padding in this structure (the "padding" member is 16
717 // bits but this then gets padded to 32 bits). We want to be sure not to
718 // leak data to the untrusted plugin, so zero everything out first.
719 NaClMessageHeader header;
720 memset(&header, 0, sizeof(NaClMessageHeader));
721
722 header.payload_size = static_cast<uint32>(msg.payload_size());
723 header.routing = msg.routing_id();
724 header.type = msg.type();
725 header.flags = msg.flags();
726 header.num_fds = static_cast<int>(rewritten_msg->desc_count());
727
728 rewritten_msg->SetData(header, msg.payload(), msg.payload_size());
729 locked_data_.to_be_received_.push(rewritten_msg);
730 }
731
OLDNEW
« no previous file with comments | « ppapi/proxy/handle_converter.h ('k') | ppapi/proxy/ppapi_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698