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

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

Issue 10796064: PPAPI/NaCl: Make nacl_ipc_adapter handle ImageData creation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sketch of idea for extracting handles generally Created 8 years, 4 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') | chrome/renderer/pepper/ppb_pdf_impl.cc » ('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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 int resource_id) { 122 int resource_id) {
123 message->WriteInt(instance_id); 123 message->WriteInt(instance_id);
124 message->WriteInt(resource_id); 124 message->WriteInt(resource_id);
125 } 125 }
126 126
127 void WriteFileDescriptor(IPC::Message* message, int index) { 127 void WriteFileDescriptor(IPC::Message* message, int index) {
128 message->WriteBool(true); // valid == true 128 message->WriteBool(true); // valid == true
129 message->WriteInt(index); 129 message->WriteInt(index);
130 } 130 }
131 131
132 typedef std::vector<ppapi::proxy::SerializedSharedMemoryHandle> ShmHandles;
133 typedef std::vector<ppapi::proxy::SerializedFileDescriptor> FDs;
134
135 void ExtractHandle(const ppapi::proxy::SerializedSharedMemoryHandle& handle,
136 ShmHandles* handles, FDs* /* fds */, IPC::Message* msg,
137 int* index) {
138 handles->push_back(handle);
139 if (msg)
140 WriteFileDescriptor(msg, (*index)++);
141 }
142 void ExtractHandle(const ppapi::proxy::SerializedFileDescriptor& fd,
143 ShmHandles* /* handles */, FDs* fds, IPC::Message* msg,
144 int* index) {
145 fds->push_back(fd);
146 if (msg)
147 WriteFileDescriptor(msg, (*index)++);
148 }
149 template <class T>
150 ExtractHandle(cont T& param, ShmHandles* /* handles */, FDs* /* fds */,
151 IPC::Message* msg, int* index) {
152 // It's not a handle, so just write to the output message, if necessary.
153 if (msg)
154 IPC::WriteParam(m, param);
155 }
156
157 // These just break apart the given tuple and run ExtractHandle over each param.
158 // The idea is to extract any handles in the tuple, while writing all data to
159 // msg (if msg is valid). The msg will only be valid on Windows, where we need
160 // to re-write the message to include the handles in POSIX style for NaCl.
161 template <class A>
162 void ExtractHandlesImpl(const Tuple1<A>& t1, ShmHandles* handles, FDs* fds,
163 IPC::Message* msg) {
164 int fd_index = 0;
165 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
166 }
167 template <class A, class B>
168 void ExtractHandlesImpl(const Tuple2<A, B>& t1, ShmHandles* handles, FDs* fds,
169 IPC::Message* msg) {
170 int fd_index = 0;
171 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
172 ExtractHandle(t1.b, handles, fds, msg, &fd_index);
173 }
174 template <class A, class B, class C>
175 void ExtractHandlesImpl(const Tuple3<A, B, C>& t1, ShmHandles* handles,
176 FDs* fds, IPC::Message* msg) {
177 int fd_index = 0;
178 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
179 ExtractHandle(t1.b, handles, fds, msg, &fd_index);
180 ExtractHandle(t1.c, handles, fds, msg, &fd_index);
181 }
182 template <class A, class B, class C, class D>
183 void ExtractHandlesImpl(const Tuple4<A, B, C, D>& t1, ShmHandles* handles,
184 FDs* fds, IPC::Message* msg) {
185 int fd_index = 0;
186 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
187 ExtractHandle(t1.b, handles, fds, msg, &fd_index);
188 ExtractHandle(t1.c, handles, fds, msg, &fd_index);
189 ExtractHandle(t1.d, handles, fds, msg, &fd_index);
190 }
191 template <class A, class B, class C, class D, class E>
192 void ExtractHandlesImpl(const Tuple5<A, B, C, D, E>& t1, ShmHandles* handles,
193 FDs* fds, IPC::Message* msg) {
194 int fd_index = 0;
195 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
196 ExtractHandle(t1.b, handles, fds, msg, &fd_index);
197 ExtractHandle(t1.c, handles, fds, msg, &fd_index);
198 ExtractHandle(t1.d, handles, fds, msg, &fd_index);
199 ExtractHandle(t1.e, handles, fds, msg, &fd_index);
200 }
201 template <class A, class B, class C, class D, class E, class F>
202 void ExtractHandlesImpl(const Tuple6<A, B, C, D, E, F>& t1, ShmHandles* handles,
203 FDs* fds, IPC::Message* msg) {
204 int fd_index = 0;
205 ExtractHandle(t1.a, handles, fds, msg, &fd_index);
206 ExtractHandle(t1.b, handles, fds, msg, &fd_index);
207 ExtractHandle(t1.c, handles, fds, msg, &fd_index);
208 ExtractHandle(t1.d, handles, fds, msg, &fd_index);
209 ExtractHandle(t1.e, handles, fds, msg, &fd_index);
210 ExtractHandle(t1.f, handles, fds, msg, &fd_index);
211 }
212
213 template <class MessageType>
214 class HandleExtractor {
215 public:
216 explicit HandleExtractor(const IPC::Message* msg)
217 : msg_(static_cast<MessageType>(msg)) {
218 }
219 bool TranslateMessage(std::vector<base::SharedMemoryHandle>* shm_handles,
220 std::vector<IPC::PlatformFileForTransit>* fds,
221 IPC::Message* msg) {
222 typename MessageType::Schema::Param params;
223 if (!Read(msg, &params))
224 return false;
225 ExtractHandlesImpl(params, shm_handles, fds, msg);
226 return true;
227 }
228 private:
229 const MessageType* msg_;
230 };
231
132 } // namespace 232 } // namespace
133 233
134 class NaClIPCAdapter::RewrittenMessage 234 class NaClIPCAdapter::RewrittenMessage
135 : public base::RefCounted<RewrittenMessage> { 235 : public base::RefCounted<RewrittenMessage> {
136 public: 236 public:
137 RewrittenMessage(); 237 RewrittenMessage();
138 238
139 bool is_consumed() const { return data_read_cursor_ == data_len_; } 239 bool is_consumed() const { return data_read_cursor_ == data_len_; }
140 240
141 void SetData(const NaClIPCAdapter::NaClMessageHeader& header, 241 void SetData(const NaClIPCAdapter::NaClMessageHeader& header,
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 439 }
340 #endif 440 #endif
341 441
342 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) { 442 bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) {
343 { 443 {
344 base::AutoLock lock(lock_); 444 base::AutoLock lock(lock_);
345 445
346 // Clear any descriptors left from the prior message. 446 // Clear any descriptors left from the prior message.
347 locked_data_.nacl_descs_.clear(); 447 locked_data_.nacl_descs_.clear();
348 448
349 PickleIterator it(message); 449 // Pointer to the "new" message we will rewrite on Windows. On posix, this
450 // isn't necessary, so it will stay NULL.
451 IPC::Message new_message_ptr = NULL;
452 #if defined(OS_WIN)
453 IPC::Message new_msg(message.routing_id(),
454 PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
455 message.priority());
456 new_message_ptr = &new_msg;
457 #endif
458 ShmHandles handles;
459 FDs fds;
350 switch (message.type()) { 460 switch (message.type()) {
461 // Note that the case for each message is now pretty much boilerplate...
462 // We can condense it to a macro if we want to save lines of code. So you
463 // might get:
464 // CASE_FOR_MESSAGE(PpapiMsg_PPB_Audio_NotifyAudioStreamCreated);
465 // CASE_FOR_MESSAGE(PpapiMsg_PPB_AudioInput_NotifyAudioStreamCreated);
466 // etc.
351 case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: { 467 case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: {
352 int instance_id; 468 HandleExtractor<PpapiMsg_PPBAudio_NotifyAudioStreamCreated>
353 int resource_id; 469 extractor(message);
354 int result_code; 470 if (!extractor.TranslateMessage(msg, &handles, &fds, new_message_ptr))
355 NaClHandle sock_handle; 471 return false;
356 NaClHandle shm_handle; 472 break;
357 uint32_t shm_length; 473 case IPC_REPLY_ID: {
358 if (ReadHostResource(&it, &instance_id, &resource_id) && 474 /* TODO(dmichael): Look up the type of the originating message, do
359 it.ReadInt(&result_code) && 475 another switch here to deal with any reply messages with handles.*/
360 ReadFileDescriptor(message, &it, &sock_handle) &&
361 ReadFileDescriptor(message, &it, &shm_handle) &&
362 it.ReadUInt32(&shm_length)) {
363 // Our caller, OnMessageReceived, holds the lock for locked_data_.
364 // Import the sync socket. Use DescWrappers to simplify clean up.
365 nacl::DescWrapperFactory factory;
366 scoped_ptr<nacl::DescWrapper> socket_wrapper(
367 factory.ImportSyncSocketHandle(sock_handle));
368 // Import the shared memory handle and increase its size by 4 bytes to
369 // accommodate the length data we write to signal the host.
370 scoped_ptr<nacl::DescWrapper> shm_wrapper(
371 factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32)));
372 if (shm_wrapper.get() && socket_wrapper.get()) {
373 locked_data_.nacl_descs_.push_back(socket_wrapper.release());
374 locked_data_.nacl_descs_.push_back(shm_wrapper.release());
375 }
376 #if defined(OS_POSIX)
377 SaveMessage(message);
378 #else // defined(OS_POSIX)
379 // On Windows we must rewrite the message to the POSIX representation.
380 IPC::Message new_msg(message.routing_id(),
381 PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
382 message.priority());
383 WriteHostResource(&new_msg, instance_id, resource_id);
384 new_msg.WriteInt(result_code);
385 WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0
386 WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1
387 new_msg.WriteUInt32(shm_length);
388 SaveMessage(new_msg);
389 #endif
390 }
391 break; 476 break;
392 } 477 }
393 default: { 478 default:
394 SaveMessage(message); 479 #if defined(OS_WIN)
480 // There are no handles, and we didn't have to rewrite the new message.
481 // Just make sure that SaveMessage below saves the valid message, since
482 // new_msg doesn't have any data.
483 new_message_ptr = &message;
484 #endif
485 // default case has nothing to do in posix; we'll save the message
486 // below.
487 }
488 // Now add any descriptors we found to nacl_descs_. These are usually both
489 // empty, unless we read a message containing a FD or handle.
490 nacl::DescWrapperFactory factory;
491 for (ShmHandles::const_iterator iter = handles.begin();
492 iter != handles.end();
493 ++iter) {
494 scoped_ptr<nacl::DescWrapper> shm_wrapper(
495 factory.ImportShmHandle(iter->handle, iter->length));
496 if (shm_wrapper.get())
497 locked_data_.nacl_descs_.push_back(shm_wrapper.release());
498 }
499 for (FDs::const_iterator iter = fds.begin(); iter != fds.end(); ++iter) {
500 scoped_ptr<nacl::DescWrapper> socket_wrapper(
501 factory.ImportSyncSocketHandle(sock_handle));
502 if (socket_wrapper.get())
503 locked_data_.nacl_descs_.push_back(socket_wrapper.release());
395 } 504 }
396 } 505 }
506 if (new_message_ptr)
507 SaveMessage(*new_message_ptr); // For Windows
508 else
509 SaveMessage(message);
397 } 510 }
398 cond_var_.Signal(); 511 cond_var_.Signal();
399 return true; 512 return true;
400 } 513 }
401 514
402 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) { 515 void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) {
403 } 516 }
404 517
405 void NaClIPCAdapter::OnChannelError() { 518 void NaClIPCAdapter::OnChannelError() {
406 CloseChannel(); 519 CloseChannel();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 573
461 // Technically we didn't have to do any of the previous work in the lock. But 574 // Technically we didn't have to do any of the previous work in the lock. But
462 // sometimes our buffer will point to the to_be_sent_ string which is 575 // sometimes our buffer will point to the to_be_sent_ string which is
463 // protected by the lock, and it's messier to factor Send() such that it can 576 // protected by the lock, and it's messier to factor Send() such that it can
464 // unlock for us. Holding the lock for the message construction, which is 577 // unlock for us. Holding the lock for the message construction, which is
465 // just some memcpys, shouldn't be a big deal. 578 // just some memcpys, shouldn't be a big deal.
466 lock_.AssertAcquired(); 579 lock_.AssertAcquired();
467 if (locked_data_.channel_closed_) 580 if (locked_data_.channel_closed_)
468 return false; // TODO(brettw) clean up handles here when we add support! 581 return false; // TODO(brettw) clean up handles here when we add support!
469 582
583 // Deal with sync messages with handles in the reply.
584 if (msg->is_sync()) {
585 if (msg->type() == PpapiHostMsg_PPBImageData_CreateNaCl::ID) {
586 int id = IPC::SyncMessage::GetMessageId(*msg);
587 PickleIterator iter(IPC::SyncMessage::GetDataIterator(msg.get()));
588 int dummy, height, width;
589 if (iter.ReadInt(&dummy) && // instance
590 iter.ReadInt(&dummy) && // format
591 iter.ReadInt(&height) &&
592 iter.ReadInt(&width)) {
593 uint32_t size = height * width * 4;
594 locked_data_.pending_image_data_msgs_[id] = size;
595 }
596 }
597 }
470 // Actual send must be done on the I/O thread. 598 // Actual send must be done on the I/O thread.
471 task_runner_->PostTask(FROM_HERE, 599 task_runner_->PostTask(FROM_HERE,
472 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this, 600 base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
473 base::Passed(&msg))); 601 base::Passed(&msg)));
474 return true; 602 return true;
475 } 603 }
476 604
477 void NaClIPCAdapter::ClearToBeSent() { 605 void NaClIPCAdapter::ClearToBeSent() {
478 lock_.AssertAcquired(); 606 lock_.AssertAcquired();
479 607
480 // Don't let the string keep its buffer behind our back. 608 // Don't let the string keep its buffer behind our back.
481 std::string empty; 609 std::string empty;
482 locked_data_.to_be_sent_.swap(empty); 610 locked_data_.to_be_sent_.swap(empty);
483 } 611 }
484 612
485 void NaClIPCAdapter::ConnectChannelOnIOThread() { 613 void NaClIPCAdapter::ConnectChannelOnIOThread() {
486 if (!io_thread_data_.channel_->Connect()) 614 if (!io_thread_data_.channel_->Connect())
487 NOTREACHED(); 615 NOTREACHED();
488 } 616 }
489 617
490 void NaClIPCAdapter::CloseChannelOnIOThread() { 618 void NaClIPCAdapter::CloseChannelOnIOThread() {
491 io_thread_data_.channel_->Close(); 619 io_thread_data_.channel_->Close();
492 } 620 }
493 621
494 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { 622 void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
495 io_thread_data_.channel_->Send(message.release()); 623 io_thread_data_.channel_->Send(message.release());
496 } 624 }
497 625
498 void NaClIPCAdapter::SaveMessage(const IPC::Message& message) { 626 void NaClIPCAdapter::SaveMessage(const IPC::Message& message) {
627 lock_.AssertAcquired();
499 // There is some padding in this structure (the "padding" member is 16 628 // There is some padding in this structure (the "padding" member is 16
500 // bits but this then gets padded to 32 bits). We want to be sure not to 629 // bits but this then gets padded to 32 bits). We want to be sure not to
501 // leak data to the untrusted plugin, so zero everything out first. 630 // leak data to the untrusted plugin, so zero everything out first.
502 NaClMessageHeader header; 631 NaClMessageHeader header;
503 memset(&header, 0, sizeof(NaClMessageHeader)); 632 memset(&header, 0, sizeof(NaClMessageHeader));
504 633
505 header.payload_size = static_cast<uint32>(message.payload_size()); 634 header.payload_size = static_cast<uint32>(message.payload_size());
506 header.routing = message.routing_id(); 635 header.routing = message.routing_id();
507 header.type = message.type(); 636 header.type = message.type();
508 header.flags = message.flags(); 637 header.flags = message.flags();
509 header.num_fds = static_cast<int>(locked_data_.nacl_descs_.size()); 638 header.num_fds = static_cast<int>(locked_data_.nacl_descs_.size());
510 639
511 scoped_refptr<RewrittenMessage> dest(new RewrittenMessage); 640 scoped_refptr<RewrittenMessage> dest(new RewrittenMessage);
512 dest->SetData(header, message.payload(), message.payload_size()); 641 dest->SetData(header, message.payload(), message.payload_size());
513 locked_data_.to_be_received_.push(dest); 642 locked_data_.to_be_received_.push(dest);
514 } 643 }
515 644
OLDNEW
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.h ('k') | chrome/renderer/pepper/ppb_pdf_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698