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

Side by Side Diff: chrome/nacl/nacl_ipc_adapter.cc

Issue 10828023: PPAPI/NaCl: Make NaClIPCAdapter transfer handles more generally (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: re-add gyp files Created 8 years, 3 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 | « chrome/nacl/nacl_ipc_adapter.h ('k') | content/content_browser.gypi » ('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) 2012 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 "chrome/nacl/nacl_ipc_adapter.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 funcs.SendMsg = NaClDescCustomSendMsg; 82 funcs.SendMsg = NaClDescCustomSendMsg;
83 funcs.RecvMsg = NaClDescCustomRecvMsg; 83 funcs.RecvMsg = NaClDescCustomRecvMsg;
84 // NaClDescMakeCustomDesc gives us a reference on the returned NaClDesc. 84 // NaClDescMakeCustomDesc gives us a reference on the returned NaClDesc.
85 return NaClDescMakeCustomDesc(new DescThunker(adapter), &funcs); 85 return NaClDescMakeCustomDesc(new DescThunker(adapter), &funcs);
86 } 86 }
87 87
88 void DeleteChannel(IPC::Channel* channel) { 88 void DeleteChannel(IPC::Channel* channel) {
89 delete channel; 89 delete channel;
90 } 90 }
91 91
92 bool ReadHostResource(PickleIterator* it, int* instance_id, int* resource_id) { 92 void WriteFileDescriptor(int handle_index,
93 return it->ReadInt(instance_id) && 93 const ppapi::proxy::SerializedHandle& handle,
94 it->ReadInt(resource_id); 94 IPC::Message* message) {
95 ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message);
96
97 // Now write the handle itself in POSIX style.
98 message->WriteBool(true); // valid == true
99 message->WriteInt(handle_index);
95 } 100 }
96 101
97 bool ReadFileDescriptor(const IPC::Message& message, 102 typedef std::vector<ppapi::proxy::SerializedHandle> Handles;
98 PickleIterator* it,
99 NaClHandle* handle) {
100 #if defined(OS_POSIX)
101 bool valid;
102 base::FileDescriptor desc;
103 if (!it->ReadBool(&valid) ||
104 !valid ||
105 !message.ReadFileDescriptor(it, &desc))
106 return false;
107 103
108 *handle = desc.fd; 104 // We define one overload for catching SerializedHandles, so that we can share
109 return true; 105 // them correctly to the untrusted side, and another for handling all other
110 #else 106 // parameters. See ConvertHandlesImpl for how these get used.
111 uint32 value; 107 void ConvertHandle(const ppapi::proxy::SerializedHandle& handle,
112 if (!it->ReadUInt32(&value)) 108 Handles* handles, IPC::Message* msg, int* handle_index) {
113 return false; 109 handles->push_back(handle);
114 110 if (msg)
115 *handle = reinterpret_cast<NaClHandle>(value); 111 WriteFileDescriptor((*handle_index)++, handle, msg);
116 return true;
117 #endif // defined(OS_POSIX)
118 } 112 }
119 113
120 void WriteHostResource(IPC::Message* message, 114 // This overload is to catch all types other than SerializedHandle. On Windows,
121 int instance_id, 115 // |msg| will be a valid pointer, and we must write |param| to it
122 int resource_id) { 116 template <class T>
123 message->WriteInt(instance_id); 117 void ConvertHandle(const T& param, Handles* /* handles */, IPC::Message* msg,
124 message->WriteInt(resource_id); 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);
125 } 122 }
126 123
127 void WriteFileDescriptor(IPC::Message* message, int index) { 124 // These just break apart the given tuple and run ConvertHandle over each param.
128 message->WriteBool(true); // valid == true 125 // The idea is to extract any handles in the tuple, while writing all data to
129 message->WriteInt(index); 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);
130 } 134 }
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);
141 }
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);
149 }
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);
158 }
159
160 template <class MessageType>
161 class HandleConverter {
162 public:
163 explicit HandleConverter(const IPC::Message* msg)
164 : msg_(static_cast<const MessageType*>(msg)) {
165 }
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;
172 }
173
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 out_msg->set_reply();
180 // If we need to rewrite the message (i.e., on Windows), we need to make
181 // sure we write the message id first.
182 if (out_msg) {
183 int id = IPC::SyncMessage::GetMessageId(*msg_);
184 out_msg->WriteInt(id);
185 }
186 ConvertHandlesImpl(params, handles, out_msg);
187 return true;
188 }
189 // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we
190 // ever pass handles in one of those.
191
192 private:
193 const MessageType* msg_;
194 };
131 195
132 } // namespace 196 } // namespace
133 197
134 class NaClIPCAdapter::RewrittenMessage 198 class NaClIPCAdapter::RewrittenMessage
135 : public base::RefCounted<RewrittenMessage> { 199 : public base::RefCounted<RewrittenMessage> {
136 public: 200 public:
137 RewrittenMessage(); 201 RewrittenMessage();
138 202
139 bool is_consumed() const { return data_read_cursor_ == data_len_; } 203 bool is_consumed() const { return data_read_cursor_ == data_len_; }
140 204
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 NaClDesc* NaClIPCAdapter::MakeNaClDesc() { 411 NaClDesc* NaClIPCAdapter::MakeNaClDesc() {
348 return MakeNaClDescCustom(this); 412 return MakeNaClDescCustom(this);
349 } 413 }
350 414
351 #if defined(OS_POSIX) 415 #if defined(OS_POSIX)
352 int NaClIPCAdapter::TakeClientFileDescriptor() { 416 int NaClIPCAdapter::TakeClientFileDescriptor() {
353 return io_thread_data_.channel_->TakeClientFileDescriptor(); 417 return io_thread_data_.channel_->TakeClientFileDescriptor();
354 } 418 }
355 #endif 419 #endif
356 420
421 #define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
422 case MESSAGE_TYPE::ID: { \
423 HandleConverter<MESSAGE_TYPE> extractor(&msg); \
424 if (!extractor.ConvertMessage(&handles, new_msg_ptr)) \
425 return false; \
426 break; \
427 }
428 #define CASE_FOR_REPLY(MESSAGE_TYPE) \
429 case MESSAGE_TYPE::ID: { \
430 HandleConverter<MESSAGE_TYPE> extractor(&msg); \
431 if (!extractor.ConvertReply( \
432 &handles, \
433 static_cast<IPC::SyncMessage*>(new_msg_ptr))) \
434 return false; \
435 break; \
436 }
357 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { 437 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) {
358 { 438 {
359 base::AutoLock lock(lock_); 439 base::AutoLock lock(lock_);
360 440
361 scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage); 441 scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage);
362 442
363 PickleIterator it(msg); 443 // Pointer to the "new" message we will rewrite on Windows. On posix, this
444 // isn't necessary, so it will stay NULL.
445 IPC::Message* new_msg_ptr = NULL;
446 #if defined(OS_WIN)
447 IPC::Message new_msg(msg.routing_id(), msg.type(), msg.priority());
448 new_msg_ptr = &new_msg;
449 #endif
450 Handles handles;
364 switch (msg.type()) { 451 switch (msg.type()) {
365 case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: { 452 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
366 int instance_id; 453 CASE_FOR_MESSAGE(PpapiMsg_PPBAudioInput_OpenACK)
367 int resource_id; 454 case IPC_REPLY_ID: {
368 int result_code; 455 int id = IPC::SyncMessage::GetMessageId(msg);
369 NaClHandle sock_handle; 456 LockedData::PendingSyncMsgMap::iterator iter(
370 NaClHandle shm_handle; 457 locked_data_.pending_sync_msgs_.find(id));
371 uint32_t shm_length; 458 if (iter == locked_data_.pending_sync_msgs_.end()) {
372 if (ReadHostResource(&it, &instance_id, &resource_id) && 459 NOTREACHED();
373 it.ReadInt(&result_code) && 460 return false;
374 ReadFileDescriptor(msg, &it, &sock_handle) && 461 }
375 ReadFileDescriptor(msg, &it, &shm_handle) && 462 uint32_t type = iter->second;
376 it.ReadUInt32(&shm_length)) { 463 locked_data_.pending_sync_msgs_.erase(iter);
377 // Import the sync socket. 464 switch (type) {
378 nacl::DescWrapperFactory factory; 465 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
379 scoped_ptr<nacl::DescWrapper> socket_wrapper( 466 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl)
380 factory.ImportSyncSocketHandle(sock_handle)); 467 default:
381 // Import the shared memory handle and increase its size by 4 bytes to 468 // Do nothing for messages we don't know.
382 // accommodate the length data we write at the end to signal the host. 469 break;
383 scoped_ptr<nacl::DescWrapper> shm_wrapper(
384 factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32)));
385 if (shm_wrapper.get() && socket_wrapper.get()) {
386 rewritten_msg->AddDescriptor(socket_wrapper.release());
387 rewritten_msg->AddDescriptor(shm_wrapper.release());
388 }
389 #if defined(OS_POSIX)
390 SaveMessage(msg, rewritten_msg.get());
391 #else
392 // On Windows we must rewrite the message to match the POSIX form.
393 IPC::Message new_msg(msg.routing_id(),
394 PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
395 msg.priority());
396 WriteHostResource(&new_msg, instance_id, resource_id);
397 new_msg.WriteInt(result_code);
398 WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0
399 WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1
400 new_msg.WriteUInt32(shm_length);
401 SaveMessage(new_msg, rewritten_msg.get());
402 #endif
403 } 470 }
404 break; 471 break;
405 } 472 }
406 default: { 473 default:
407 SaveMessage(msg, rewritten_msg.get()); 474 // Do nothing for messages we don't know.
475 break;
476 }
477 // Now add any descriptors we found to rewritten_msg. |handles| is usually
478 // empty, unless we read a message containing a FD or handle.
479 nacl::DescWrapperFactory factory;
480 for (Handles::const_iterator iter = handles.begin();
481 iter != handles.end();
482 ++iter) {
483 scoped_ptr<nacl::DescWrapper> nacl_desc;
484 switch (iter->type()) {
485 case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
486 const base::SharedMemoryHandle& shm_handle = iter->shmem();
487 uint32_t size = iter->size();
488 nacl_desc.reset(factory.ImportShmHandle(
489 #if defined(OS_WIN)
490 reinterpret_cast<const NaClHandle>(shm_handle),
491 #else
492 shm_handle.fd,
493 #endif
494 static_cast<size_t>(size)));
495 break;
496 }
497 case ppapi::proxy::SerializedHandle::SOCKET: {
498 nacl_desc.reset(factory.ImportSyncSocketHandle(
499 #if defined(OS_WIN)
500 reinterpret_cast<const NaClHandle>(iter->descriptor())
501 #else
502 iter->descriptor().fd
503 #endif
504 ));
505 }
506 case ppapi::proxy::SerializedHandle::INVALID: {
507 // Nothing to do. TODO(dmichael): Should we log this? Or is it
508 // sometimes okay to pass an INVALID handle?
509 }
510 // No default, so the compiler will warn us if new types get added.
408 } 511 }
512 if (nacl_desc.get())
513 rewritten_msg->AddDescriptor(nacl_desc.release());
409 } 514 }
515 if (new_msg_ptr && !handles.empty())
516 SaveMessage(*new_msg_ptr, rewritten_msg.get());
517 else
518 SaveMessage(msg, rewritten_msg.get());
410 } 519 }
411 cond_var_.Signal(); 520 cond_var_.Signal();
412 return true; 521 return true;
413 } 522 }
414 523
415 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) { 524 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) {
416 } 525 }
417 526
418 void NaClIPCAdapter::OnChannelError() { 527 void NaClIPCAdapter::OnChannelError() {
419 CloseChannel(); 528 CloseChannel();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 582
474 // Technically we didn't have to do any of the previous work in the lock. But 583 // Technically we didn't have to do any of the previous work in the lock. But
475 // sometimes our buffer will point to the to_be_sent_ string which is 584 // sometimes our buffer will point to the to_be_sent_ string which is
476 // protected by the lock, and it's messier to factor Send() such that it can 585 // protected by the lock, and it's messier to factor Send() such that it can
477 // unlock for us. Holding the lock for the message construction, which is 586 // unlock for us. Holding the lock for the message construction, which is
478 // just some memcpys, shouldn't be a big deal. 587 // just some memcpys, shouldn't be a big deal.
479 lock_.AssertAcquired(); 588 lock_.AssertAcquired();
480 if (locked_data_.channel_closed_) 589 if (locked_data_.channel_closed_)
481 return false; // TODO(brettw) clean up handles here when we add support! 590 return false; // TODO(brettw) clean up handles here when we add support!
482 591
592 // Store the type of all sync messages so that later we can translate the
593 // reply if necessary.
594 if (msg->is_sync()) {
595 int id = IPC::SyncMessage::GetMessageId(*msg);
596 locked_data_.pending_sync_msgs_[id] = msg->type();
597 }
483 // Actual send must be done on the I/O thread. 598 // Actual send must be done on the I/O thread.
484 task_runner_->PostTask(FROM_HERE, 599 task_runner_->PostTask(FROM_HERE,
485 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this, 600 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
486 base::Passed(&msg))); 601 base::Passed(&msg)));
487 return true; 602 return true;
488 } 603 }
489 604
490 void NaClIPCAdapter::ClearToBeSent() { 605 void NaClIPCAdapter::ClearToBeSent() {
491 lock_.AssertAcquired(); 606 lock_.AssertAcquired();
492 607
(...skipping 27 matching lines...) Expand all
520 header.payload_size = static_cast<uint32>(msg.payload_size()); 635 header.payload_size = static_cast<uint32>(msg.payload_size());
521 header.routing = msg.routing_id(); 636 header.routing = msg.routing_id();
522 header.type = msg.type(); 637 header.type = msg.type();
523 header.flags = msg.flags(); 638 header.flags = msg.flags();
524 header.num_fds = static_cast<int>(rewritten_msg->desc_count()); 639 header.num_fds = static_cast<int>(rewritten_msg->desc_count());
525 640
526 rewritten_msg->SetData(header, msg.payload(), msg.payload_size()); 641 rewritten_msg->SetData(header, msg.payload(), msg.payload_size());
527 locked_data_.to_be_received_.push(rewritten_msg); 642 locked_data_.to_be_received_.push(rewritten_msg);
528 } 643 }
529 644
OLDNEW
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698