Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / nacl / nacl_ipc_adapter.cc
blob1ee0c37dc3db9bcc9c0ca6315868cb8b39130cf5
1 // Copyright (c) 2012 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.
5 #include "chrome/nacl/nacl_ipc_adapter.h"
7 #include <limits.h>
8 #include <string.h>
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_message_macros.h"
17 #include "ipc/ipc_platform_file.h"
18 #include "native_client/src/trusted/desc/nacl_desc_custom.h"
19 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
20 #include "ppapi/proxy/ppapi_messages.h"
22 namespace {
24 enum BufferSizeStatus {
25 // The buffer contains a full message with no extra bytes.
26 MESSAGE_IS_COMPLETE,
28 // The message doesn't fit and the buffer contains only some of it.
29 MESSAGE_IS_TRUNCATED,
31 // The buffer contains a full message + extra data.
32 MESSAGE_HAS_EXTRA_DATA
35 BufferSizeStatus GetBufferStatus(const char* data, size_t len) {
36 if (len < sizeof(NaClIPCAdapter::NaClMessageHeader))
37 return MESSAGE_IS_TRUNCATED;
39 const NaClIPCAdapter::NaClMessageHeader* header =
40 reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(data);
41 uint32 message_size =
42 sizeof(NaClIPCAdapter::NaClMessageHeader) + header->payload_size;
44 if (len == message_size)
45 return MESSAGE_IS_COMPLETE;
46 if (len > message_size)
47 return MESSAGE_HAS_EXTRA_DATA;
48 return MESSAGE_IS_TRUNCATED;
51 // This object allows the NaClDesc to hold a reference to a NaClIPCAdapter and
52 // forward calls to it.
53 struct DescThunker {
54 explicit DescThunker(NaClIPCAdapter* adapter_param)
55 : adapter(adapter_param) {
57 scoped_refptr<NaClIPCAdapter> adapter;
60 NaClIPCAdapter* ToAdapter(void* handle) {
61 return static_cast<DescThunker*>(handle)->adapter.get();
64 // NaClDescCustom implementation.
65 void NaClDescCustomDestroy(void* handle) {
66 delete static_cast<DescThunker*>(handle);
69 ssize_t NaClDescCustomSendMsg(void* handle, const NaClImcTypedMsgHdr* msg,
70 int /* flags */) {
71 return static_cast<ssize_t>(ToAdapter(handle)->Send(msg));
74 ssize_t NaClDescCustomRecvMsg(void* handle, NaClImcTypedMsgHdr* msg,
75 int /* flags */) {
76 return static_cast<ssize_t>(ToAdapter(handle)->BlockingReceive(msg));
79 NaClDesc* MakeNaClDescCustom(NaClIPCAdapter* adapter) {
80 NaClDescCustomFuncs funcs = NACL_DESC_CUSTOM_FUNCS_INITIALIZER;
81 funcs.Destroy = NaClDescCustomDestroy;
82 funcs.SendMsg = NaClDescCustomSendMsg;
83 funcs.RecvMsg = NaClDescCustomRecvMsg;
84 // NaClDescMakeCustomDesc gives us a reference on the returned NaClDesc.
85 return NaClDescMakeCustomDesc(new DescThunker(adapter), &funcs);
88 void DeleteChannel(IPC::Channel* channel) {
89 delete channel;
92 void WriteHandle(int handle_index,
93 const ppapi::proxy::SerializedHandle& handle,
94 IPC::Message* message) {
95 ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message);
97 // Now write the handle itself in POSIX style.
98 message->WriteBool(true); // valid == true
99 message->WriteInt(handle_index);
102 typedef std::vector<ppapi::proxy::SerializedHandle> Handles;
104 // We define one overload for catching SerializedHandles, so that we can share
105 // them correctly to the untrusted side, and another for handling all other
106 // parameters. See ConvertHandlesImpl for how these get used.
107 void ConvertHandle(const ppapi::proxy::SerializedHandle& handle,
108 Handles* handles, IPC::Message* msg, int* handle_index) {
109 handles->push_back(handle);
110 if (msg)
111 WriteHandle((*handle_index)++, handle, msg);
114 // This overload is to catch all types other than SerializedHandle. On Windows,
115 // |msg| will be a valid pointer, and we must write |param| to it
116 template <class T>
117 void ConvertHandle(const T& param, Handles* /* handles */, IPC::Message* msg,
118 int* /* handle_index */) {
119 // It's not a handle, so just write to the output message, if necessary.
120 if (msg)
121 IPC::WriteParam(msg, param);
124 // These just break apart the given tuple and run ConvertHandle over each param.
125 // The idea is to extract any handles in the tuple, while writing all data to
126 // msg (if msg is valid). The msg will only be valid on Windows, where we need
127 // to re-write all of the message parameters, writing the handles in POSIX style
128 // for NaCl.
129 template <class A>
130 void ConvertHandlesImpl(const Tuple1<A>& t1, Handles* handles,
131 IPC::Message* msg) {
132 int handle_index = 0;
133 ConvertHandle(t1.a, handles, msg, &handle_index);
135 template <class A, class B>
136 void ConvertHandlesImpl(const Tuple2<A, B>& t1, Handles* handles,
137 IPC::Message* msg) {
138 int handle_index = 0;
139 ConvertHandle(t1.a, handles, msg, &handle_index);
140 ConvertHandle(t1.b, handles, msg, &handle_index);
142 template <class A, class B, class C>
143 void ConvertHandlesImpl(const Tuple3<A, B, C>& t1, Handles* handles,
144 IPC::Message* msg) {
145 int handle_index = 0;
146 ConvertHandle(t1.a, handles, msg, &handle_index);
147 ConvertHandle(t1.b, handles, msg, &handle_index);
148 ConvertHandle(t1.c, handles, msg, &handle_index);
150 template <class A, class B, class C, class D>
151 void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles,
152 IPC::Message* msg) {
153 int handle_index = 0;
154 ConvertHandle(t1.a, handles, msg, &handle_index);
155 ConvertHandle(t1.b, handles, msg, &handle_index);
156 ConvertHandle(t1.c, handles, msg, &handle_index);
157 ConvertHandle(t1.d, handles, msg, &handle_index);
160 template <class MessageType>
161 class HandleConverter {
162 public:
163 explicit HandleConverter(const IPC::Message* msg)
164 : msg_(static_cast<const MessageType*>(msg)) {
166 bool ConvertMessage(Handles* handles, IPC::Message* out_msg) {
167 typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params;
168 if (!MessageType::Read(msg_, &params))
169 return false;
170 ConvertHandlesImpl(params, handles, out_msg);
171 return true;
174 bool ConvertReply(Handles* handles, IPC::SyncMessage* out_msg) {
175 typename TupleTypes<typename MessageType::Schema::ReplyParam>::ValueTuple
176 params;
177 if (!MessageType::ReadReplyParam(msg_, &params))
178 return false;
179 // If we need to rewrite the message (i.e., on Windows), we need to make
180 // sure we write the message id first.
181 if (out_msg) {
182 out_msg->set_reply();
183 int id = IPC::SyncMessage::GetMessageId(*msg_);
184 out_msg->WriteInt(id);
186 ConvertHandlesImpl(params, handles, out_msg);
187 return true;
189 // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we
190 // ever pass handles in one of those.
192 private:
193 const MessageType* msg_;
196 } // namespace
198 class NaClIPCAdapter::RewrittenMessage
199 : public base::RefCounted<RewrittenMessage> {
200 public:
201 RewrittenMessage();
203 bool is_consumed() const { return data_read_cursor_ == data_len_; }
205 void SetData(const NaClIPCAdapter::NaClMessageHeader& header,
206 const void* payload, size_t payload_length);
208 int Read(NaClImcTypedMsgHdr* msg);
210 void AddDescriptor(nacl::DescWrapper* desc) { descs_.push_back(desc); }
212 size_t desc_count() const { return descs_.size(); }
214 private:
215 friend class base::RefCounted<RewrittenMessage>;
216 ~RewrittenMessage() {}
218 scoped_array<char> data_;
219 size_t data_len_;
221 // Offset into data where the next read will happen. This will be equal to
222 // data_len_ when all data has been consumed.
223 size_t data_read_cursor_;
225 // Wrapped descriptors for transfer to untrusted code.
226 ScopedVector<nacl::DescWrapper> descs_;
229 NaClIPCAdapter::RewrittenMessage::RewrittenMessage()
230 : data_len_(0),
231 data_read_cursor_(0) {
234 void NaClIPCAdapter::RewrittenMessage::SetData(
235 const NaClIPCAdapter::NaClMessageHeader& header,
236 const void* payload,
237 size_t payload_length) {
238 DCHECK(!data_.get() && data_len_ == 0);
239 size_t header_len = sizeof(NaClIPCAdapter::NaClMessageHeader);
240 data_len_ = header_len + payload_length;
241 data_.reset(new char[data_len_]);
243 memcpy(data_.get(), &header, sizeof(NaClIPCAdapter::NaClMessageHeader));
244 memcpy(&data_[header_len], payload, payload_length);
247 int NaClIPCAdapter::RewrittenMessage::Read(NaClImcTypedMsgHdr* msg) {
248 CHECK(data_len_ >= data_read_cursor_);
249 char* dest_buffer = static_cast<char*>(msg->iov[0].base);
250 size_t dest_buffer_size = msg->iov[0].length;
251 size_t bytes_to_write = std::min(dest_buffer_size,
252 data_len_ - data_read_cursor_);
253 if (bytes_to_write == 0)
254 return 0;
256 memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write);
257 data_read_cursor_ += bytes_to_write;
259 // Once all data has been consumed, transfer any file descriptors.
260 if (is_consumed()) {
261 nacl_abi_size_t desc_count = static_cast<nacl_abi_size_t>(descs_.size());
262 CHECK(desc_count <= msg->ndesc_length);
263 msg->ndesc_length = desc_count;
264 for (nacl_abi_size_t i = 0; i < desc_count; i++) {
265 // Copy the NaClDesc to the buffer and add a ref so it won't be freed
266 // when we clear our ScopedVector.
267 msg->ndescv[i] = descs_[i]->desc();
268 NaClDescRef(descs_[i]->desc());
270 descs_.clear();
271 } else {
272 msg->ndesc_length = 0;
274 return static_cast<int>(bytes_to_write);
277 NaClIPCAdapter::LockedData::LockedData()
278 : channel_closed_(false) {
281 NaClIPCAdapter::LockedData::~LockedData() {
284 NaClIPCAdapter::IOThreadData::IOThreadData() {
287 NaClIPCAdapter::IOThreadData::~IOThreadData() {
290 NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle,
291 base::TaskRunner* runner)
292 : lock_(),
293 cond_var_(&lock_),
294 task_runner_(runner),
295 locked_data_() {
296 io_thread_data_.channel_.reset(
297 new IPC::Channel(handle, IPC::Channel::MODE_SERVER, this));
298 // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did,
299 // and that task ran before this constructor completes, the reference count
300 // would go to 1 and then to 0 because of the Task, before we've been returned
301 // to the owning scoped_refptr, which is supposed to give us our first
302 // ref-count.
305 NaClIPCAdapter::NaClIPCAdapter(scoped_ptr<IPC::Channel> channel,
306 base::TaskRunner* runner)
307 : lock_(),
308 cond_var_(&lock_),
309 task_runner_(runner),
310 locked_data_() {
311 io_thread_data_.channel_ = channel.Pass();
314 void NaClIPCAdapter::ConnectChannel() {
315 task_runner_->PostTask(FROM_HERE,
316 base::Bind(&NaClIPCAdapter::ConnectChannelOnIOThread, this));
319 // Note that this message is controlled by the untrusted code. So we should be
320 // skeptical of anything it contains and quick to give up if anything is fishy.
321 int NaClIPCAdapter::Send(const NaClImcTypedMsgHdr* msg) {
322 if (msg->iov_length != 1)
323 return -1;
325 base::AutoLock lock(lock_);
327 const char* input_data = static_cast<char*>(msg->iov[0].base);
328 size_t input_data_len = msg->iov[0].length;
329 if (input_data_len > IPC::Channel::kMaximumMessageSize) {
330 ClearToBeSent();
331 return -1;
334 // current_message[_len] refers to the total input data received so far.
335 const char* current_message;
336 size_t current_message_len;
337 bool did_append_input_data;
338 if (locked_data_.to_be_sent_.empty()) {
339 // No accumulated data, we can avoid a copy by referring to the input
340 // buffer (the entire message fitting in one call is the common case).
341 current_message = input_data;
342 current_message_len = input_data_len;
343 did_append_input_data = false;
344 } else {
345 // We've already accumulated some data, accumulate this new data and
346 // point to the beginning of the buffer.
348 // Make sure our accumulated message size doesn't overflow our max. Since
349 // we know that data_len < max size (checked above) and our current
350 // accumulated value is also < max size, we just need to make sure that
351 // 2x max size can never overflow.
352 COMPILE_ASSERT(IPC::Channel::kMaximumMessageSize < (UINT_MAX / 2),
353 MaximumMessageSizeWillOverflow);
354 size_t new_size = locked_data_.to_be_sent_.size() + input_data_len;
355 if (new_size > IPC::Channel::kMaximumMessageSize) {
356 ClearToBeSent();
357 return -1;
360 locked_data_.to_be_sent_.append(input_data, input_data_len);
361 current_message = &locked_data_.to_be_sent_[0];
362 current_message_len = locked_data_.to_be_sent_.size();
363 did_append_input_data = true;
366 // Check the total data we've accumulated so far to see if it contains a full
367 // message.
368 switch (GetBufferStatus(current_message, current_message_len)) {
369 case MESSAGE_IS_COMPLETE: {
370 // Got a complete message, can send it out. This will be the common case.
371 bool success = SendCompleteMessage(current_message, current_message_len);
372 ClearToBeSent();
373 return success ? static_cast<int>(input_data_len) : -1;
375 case MESSAGE_IS_TRUNCATED:
376 // For truncated messages, just accumulate the new data (if we didn't
377 // already do so above) and go back to waiting for more.
378 if (!did_append_input_data)
379 locked_data_.to_be_sent_.append(input_data, input_data_len);
380 return static_cast<int>(input_data_len);
381 case MESSAGE_HAS_EXTRA_DATA:
382 default:
383 // When the plugin gives us too much data, it's an error.
384 ClearToBeSent();
385 return -1;
389 int NaClIPCAdapter::BlockingReceive(NaClImcTypedMsgHdr* msg) {
390 if (msg->iov_length != 1)
391 return -1;
393 int retval = 0;
395 base::AutoLock lock(lock_);
396 while (locked_data_.to_be_received_.empty() &&
397 !locked_data_.channel_closed_)
398 cond_var_.Wait();
399 if (locked_data_.channel_closed_) {
400 retval = -1;
401 } else {
402 retval = LockedReceive(msg);
403 DCHECK(retval > 0);
406 cond_var_.Signal();
407 return retval;
410 void NaClIPCAdapter::CloseChannel() {
412 base::AutoLock lock(lock_);
413 locked_data_.channel_closed_ = true;
415 cond_var_.Signal();
417 task_runner_->PostTask(FROM_HERE,
418 base::Bind(&NaClIPCAdapter::CloseChannelOnIOThread, this));
421 NaClDesc* NaClIPCAdapter::MakeNaClDesc() {
422 return MakeNaClDescCustom(this);
425 #if defined(OS_POSIX)
426 int NaClIPCAdapter::TakeClientFileDescriptor() {
427 return io_thread_data_.channel_->TakeClientFileDescriptor();
429 #endif
431 #define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
432 case MESSAGE_TYPE::ID: { \
433 HandleConverter<MESSAGE_TYPE> extractor(&msg); \
434 if (!extractor.ConvertMessage(&handles, new_msg_ptr)) \
435 return false; \
436 break; \
438 #define CASE_FOR_REPLY(MESSAGE_TYPE) \
439 case MESSAGE_TYPE::ID: { \
440 HandleConverter<MESSAGE_TYPE> extractor(&msg); \
441 if (!extractor.ConvertReply( \
442 &handles, \
443 static_cast<IPC::SyncMessage*>(new_msg_ptr))) \
444 return false; \
445 break; \
448 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) {
450 base::AutoLock lock(lock_);
452 scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage);
454 // Pointer to the "new" message we will rewrite on Windows. On posix, this
455 // isn't necessary, so it will stay NULL.
456 IPC::Message* new_msg_ptr = NULL;
457 IPC::Message new_msg(msg.routing_id(), msg.type(), msg.priority());
458 #if defined(OS_WIN)
459 new_msg_ptr = &new_msg;
460 #else
461 // Even on POSIX, we have to rewrite messages to create channels, because
462 // these contain a handle with an invalid (place holder) descriptor. The
463 // message sending code sees this and doesn't pass the descriptor over
464 // correctly.
465 if (msg.type() == PpapiMsg_CreateNaClChannel::ID)
466 new_msg_ptr = &new_msg;
467 #endif
469 Handles handles;
470 switch (msg.type()) {
471 CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel)
472 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
473 case IPC_REPLY_ID: {
474 int id = IPC::SyncMessage::GetMessageId(msg);
475 LockedData::PendingSyncMsgMap::iterator iter(
476 locked_data_.pending_sync_msgs_.find(id));
477 if (iter == locked_data_.pending_sync_msgs_.end()) {
478 NOTREACHED();
479 return false;
481 uint32_t type = iter->second;
482 locked_data_.pending_sync_msgs_.erase(iter);
483 switch (type) {
484 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
485 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl)
486 default:
487 // Do nothing for messages we don't know.
488 break;
490 break;
492 default:
493 // Do nothing for messages we don't know.
494 break;
496 // Now add any descriptors we found to rewritten_msg. |handles| is usually
497 // empty, unless we read a message containing a FD or handle.
498 nacl::DescWrapperFactory factory;
499 for (Handles::const_iterator iter = handles.begin();
500 iter != handles.end();
501 ++iter) {
502 scoped_ptr<nacl::DescWrapper> nacl_desc;
503 switch (iter->type()) {
504 case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
505 const base::SharedMemoryHandle& shm_handle = iter->shmem();
506 uint32_t size = iter->size();
507 nacl_desc.reset(factory.ImportShmHandle(
508 #if defined(OS_WIN)
509 reinterpret_cast<const NaClHandle>(shm_handle),
510 #else
511 shm_handle.fd,
512 #endif
513 static_cast<size_t>(size)));
514 break;
516 case ppapi::proxy::SerializedHandle::SOCKET: {
517 nacl_desc.reset(factory.ImportSyncSocketHandle(
518 #if defined(OS_WIN)
519 reinterpret_cast<const NaClHandle>(iter->descriptor())
520 #else
521 iter->descriptor().fd
522 #endif
524 break;
526 case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: {
527 // Check that this came from a PpapiMsg_CreateNaClChannel message.
528 // This code here is only appropriate for that message.
529 DCHECK(msg.type() == PpapiMsg_CreateNaClChannel::ID);
530 IPC::ChannelHandle channel_handle =
531 IPC::Channel::GenerateVerifiedChannelID("nacl");
532 scoped_refptr<NaClIPCAdapter> ipc_adapter(
533 new NaClIPCAdapter(channel_handle, task_runner_));
534 ipc_adapter->ConnectChannel();
535 #if defined(OS_POSIX)
536 channel_handle.socket = base::FileDescriptor(
537 ipc_adapter->TakeClientFileDescriptor(), true);
538 #endif
539 nacl_desc.reset(factory.MakeGeneric(ipc_adapter->MakeNaClDesc()));
540 // Send back a message that the channel was created.
541 scoped_ptr<IPC::Message> response(
542 new PpapiHostMsg_ChannelCreated(channel_handle));
543 task_runner_->PostTask(FROM_HERE,
544 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
545 base::Passed(&response)));
546 break;
548 case ppapi::proxy::SerializedHandle::INVALID: {
549 // Nothing to do. TODO(dmichael): Should we log this? Or is it
550 // sometimes okay to pass an INVALID handle?
551 break;
553 // No default, so the compiler will warn us if new types get added.
555 if (nacl_desc.get())
556 rewritten_msg->AddDescriptor(nacl_desc.release());
558 if (new_msg_ptr && !handles.empty())
559 SaveMessage(*new_msg_ptr, rewritten_msg.get());
560 else
561 SaveMessage(msg, rewritten_msg.get());
563 cond_var_.Signal();
564 return true;
567 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) {
570 void NaClIPCAdapter::OnChannelError() {
571 CloseChannel();
574 NaClIPCAdapter::~NaClIPCAdapter() {
575 // Make sure the channel is deleted on the IO thread.
576 task_runner_->PostTask(FROM_HERE,
577 base::Bind(&DeleteChannel, io_thread_data_.channel_.release()));
580 int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) {
581 lock_.AssertAcquired();
583 if (locked_data_.to_be_received_.empty())
584 return 0;
585 scoped_refptr<RewrittenMessage> current =
586 locked_data_.to_be_received_.front();
588 int retval = current->Read(msg);
590 // When a message is entirely consumed, remove if from the waiting queue.
591 if (current->is_consumed())
592 locked_data_.to_be_received_.pop();
594 return retval;
597 bool NaClIPCAdapter::SendCompleteMessage(const char* buffer,
598 size_t buffer_len) {
599 // The message will have already been validated, so we know it's large enough
600 // for our header.
601 const NaClMessageHeader* header =
602 reinterpret_cast<const NaClMessageHeader*>(buffer);
604 // Length of the message not including the body. The data passed to us by the
605 // plugin should match that in the message header. This should have already
606 // been validated by GetBufferStatus.
607 int body_len = static_cast<int>(buffer_len - sizeof(NaClMessageHeader));
608 DCHECK(body_len == static_cast<int>(header->payload_size));
610 // We actually discard the flags and only copy the ones we care about. This
611 // is just because message doesn't have a constructor that takes raw flags.
612 scoped_ptr<IPC::Message> msg(
613 new IPC::Message(header->routing, header->type,
614 IPC::Message::PRIORITY_NORMAL));
615 if (header->flags & IPC::Message::SYNC_BIT)
616 msg->set_sync();
617 if (header->flags & IPC::Message::REPLY_BIT)
618 msg->set_reply();
619 if (header->flags & IPC::Message::REPLY_ERROR_BIT)
620 msg->set_reply_error();
621 if (header->flags & IPC::Message::UNBLOCK_BIT)
622 msg->set_unblock(true);
624 msg->WriteBytes(&buffer[sizeof(NaClMessageHeader)], body_len);
626 // Technically we didn't have to do any of the previous work in the lock. But
627 // sometimes our buffer will point to the to_be_sent_ string which is
628 // protected by the lock, and it's messier to factor Send() such that it can
629 // unlock for us. Holding the lock for the message construction, which is
630 // just some memcpys, shouldn't be a big deal.
631 lock_.AssertAcquired();
632 if (locked_data_.channel_closed_)
633 return false; // TODO(brettw) clean up handles here when we add support!
635 // Store the type of all sync messages so that later we can translate the
636 // reply if necessary.
637 if (msg->is_sync()) {
638 int id = IPC::SyncMessage::GetMessageId(*msg);
639 locked_data_.pending_sync_msgs_[id] = msg->type();
641 // Actual send must be done on the I/O thread.
642 task_runner_->PostTask(FROM_HERE,
643 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
644 base::Passed(&msg)));
645 return true;
648 void NaClIPCAdapter::ClearToBeSent() {
649 lock_.AssertAcquired();
651 // Don't let the string keep its buffer behind our back.
652 std::string empty;
653 locked_data_.to_be_sent_.swap(empty);
656 void NaClIPCAdapter::ConnectChannelOnIOThread() {
657 if (!io_thread_data_.channel_->Connect())
658 NOTREACHED();
661 void NaClIPCAdapter::CloseChannelOnIOThread() {
662 io_thread_data_.channel_->Close();
665 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
666 io_thread_data_.channel_->Send(message.release());
669 void NaClIPCAdapter::SaveMessage(const IPC::Message& msg,
670 RewrittenMessage* rewritten_msg) {
671 lock_.AssertAcquired();
672 // There is some padding in this structure (the "padding" member is 16
673 // bits but this then gets padded to 32 bits). We want to be sure not to
674 // leak data to the untrusted plugin, so zero everything out first.
675 NaClMessageHeader header;
676 memset(&header, 0, sizeof(NaClMessageHeader));
678 header.payload_size = static_cast<uint32>(msg.payload_size());
679 header.routing = msg.routing_id();
680 header.type = msg.type();
681 header.flags = msg.flags();
682 header.num_fds = static_cast<int>(rewritten_msg->desc_count());
684 rewritten_msg->SetData(header, msg.payload(), msg.payload_size());
685 locked_data_.to_be_received_.push(rewritten_msg);