| Index: chrome/nacl/nacl_ipc_adapter.cc
|
| diff --git a/chrome/nacl/nacl_ipc_adapter.cc b/chrome/nacl/nacl_ipc_adapter.cc
|
| index 187eb8b602f85c4ffe4b4df23d48c3c84a2a8728..4d46a2d15d01192f2553fa76640160272ceeb754 100644
|
| --- a/chrome/nacl/nacl_ipc_adapter.cc
|
| +++ b/chrome/nacl/nacl_ipc_adapter.cc
|
| @@ -129,6 +129,106 @@ void WriteFileDescriptor(IPC::Message* message, int index) {
|
| message->WriteInt(index);
|
| }
|
|
|
| +typedef std::vector<ppapi::proxy::SerializedSharedMemoryHandle> ShmHandles;
|
| +typedef std::vector<ppapi::proxy::SerializedFileDescriptor> FDs;
|
| +
|
| +void ExtractHandle(const ppapi::proxy::SerializedSharedMemoryHandle& handle,
|
| + ShmHandles* handles, FDs* /* fds */, IPC::Message* msg,
|
| + int* index) {
|
| + handles->push_back(handle);
|
| + if (msg)
|
| + WriteFileDescriptor(msg, (*index)++);
|
| +}
|
| +void ExtractHandle(const ppapi::proxy::SerializedFileDescriptor& fd,
|
| + ShmHandles* /* handles */, FDs* fds, IPC::Message* msg,
|
| + int* index) {
|
| + fds->push_back(fd);
|
| + if (msg)
|
| + WriteFileDescriptor(msg, (*index)++);
|
| +}
|
| +template <class T>
|
| +ExtractHandle(cont T& param, ShmHandles* /* handles */, FDs* /* fds */,
|
| + IPC::Message* msg, int* index) {
|
| + // It's not a handle, so just write to the output message, if necessary.
|
| + if (msg)
|
| + IPC::WriteParam(m, param);
|
| +}
|
| +
|
| +// These just break apart the given tuple and run ExtractHandle over each param.
|
| +// The idea is to extract any handles in the tuple, while writing all data to
|
| +// msg (if msg is valid). The msg will only be valid on Windows, where we need
|
| +// to re-write the message to include the handles in POSIX style for NaCl.
|
| +template <class A>
|
| +void ExtractHandlesImpl(const Tuple1<A>& t1, ShmHandles* handles, FDs* fds,
|
| + IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| +}
|
| +template <class A, class B>
|
| +void ExtractHandlesImpl(const Tuple2<A, B>& t1, ShmHandles* handles, FDs* fds,
|
| + IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.b, handles, fds, msg, &fd_index);
|
| +}
|
| +template <class A, class B, class C>
|
| +void ExtractHandlesImpl(const Tuple3<A, B, C>& t1, ShmHandles* handles,
|
| + FDs* fds, IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.b, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.c, handles, fds, msg, &fd_index);
|
| +}
|
| +template <class A, class B, class C, class D>
|
| +void ExtractHandlesImpl(const Tuple4<A, B, C, D>& t1, ShmHandles* handles,
|
| + FDs* fds, IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.b, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.c, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.d, handles, fds, msg, &fd_index);
|
| +}
|
| +template <class A, class B, class C, class D, class E>
|
| +void ExtractHandlesImpl(const Tuple5<A, B, C, D, E>& t1, ShmHandles* handles,
|
| + FDs* fds, IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.b, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.c, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.d, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.e, handles, fds, msg, &fd_index);
|
| +}
|
| +template <class A, class B, class C, class D, class E, class F>
|
| +void ExtractHandlesImpl(const Tuple6<A, B, C, D, E, F>& t1, ShmHandles* handles,
|
| + FDs* fds, IPC::Message* msg) {
|
| + int fd_index = 0;
|
| + ExtractHandle(t1.a, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.b, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.c, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.d, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.e, handles, fds, msg, &fd_index);
|
| + ExtractHandle(t1.f, handles, fds, msg, &fd_index);
|
| +}
|
| +
|
| +template <class MessageType>
|
| +class HandleExtractor {
|
| + public:
|
| + explicit HandleExtractor(const IPC::Message* msg)
|
| + : msg_(static_cast<MessageType>(msg)) {
|
| + }
|
| + bool TranslateMessage(std::vector<base::SharedMemoryHandle>* shm_handles,
|
| + std::vector<IPC::PlatformFileForTransit>* fds,
|
| + IPC::Message* msg) {
|
| + typename MessageType::Schema::Param params;
|
| + if (!Read(msg, ¶ms))
|
| + return false;
|
| + ExtractHandlesImpl(params, shm_handles, fds, msg);
|
| + return true;
|
| + }
|
| + private:
|
| + const MessageType* msg_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| class NaClIPCAdapter::RewrittenMessage
|
| @@ -346,54 +446,67 @@ bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) {
|
| // Clear any descriptors left from the prior message.
|
| locked_data_.nacl_descs_.clear();
|
|
|
| - PickleIterator it(message);
|
| + // Pointer to the "new" message we will rewrite on Windows. On posix, this
|
| + // isn't necessary, so it will stay NULL.
|
| + IPC::Message new_message_ptr = NULL;
|
| +#if defined(OS_WIN)
|
| + IPC::Message new_msg(message.routing_id(),
|
| + PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
|
| + message.priority());
|
| + new_message_ptr = &new_msg;
|
| +#endif
|
| + ShmHandles handles;
|
| + FDs fds;
|
| switch (message.type()) {
|
| + // Note that the case for each message is now pretty much boilerplate...
|
| + // We can condense it to a macro if we want to save lines of code. So you
|
| + // might get:
|
| + // CASE_FOR_MESSAGE(PpapiMsg_PPB_Audio_NotifyAudioStreamCreated);
|
| + // CASE_FOR_MESSAGE(PpapiMsg_PPB_AudioInput_NotifyAudioStreamCreated);
|
| + // etc.
|
| case PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID: {
|
| - int instance_id;
|
| - int resource_id;
|
| - int result_code;
|
| - NaClHandle sock_handle;
|
| - NaClHandle shm_handle;
|
| - uint32_t shm_length;
|
| - if (ReadHostResource(&it, &instance_id, &resource_id) &&
|
| - it.ReadInt(&result_code) &&
|
| - ReadFileDescriptor(message, &it, &sock_handle) &&
|
| - ReadFileDescriptor(message, &it, &shm_handle) &&
|
| - it.ReadUInt32(&shm_length)) {
|
| - // Our caller, OnMessageReceived, holds the lock for locked_data_.
|
| - // Import the sync socket. Use DescWrappers to simplify clean up.
|
| - nacl::DescWrapperFactory factory;
|
| - scoped_ptr<nacl::DescWrapper> socket_wrapper(
|
| - factory.ImportSyncSocketHandle(sock_handle));
|
| - // Import the shared memory handle and increase its size by 4 bytes to
|
| - // accommodate the length data we write to signal the host.
|
| - scoped_ptr<nacl::DescWrapper> shm_wrapper(
|
| - factory.ImportShmHandle(shm_handle, shm_length + sizeof(uint32)));
|
| - if (shm_wrapper.get() && socket_wrapper.get()) {
|
| - locked_data_.nacl_descs_.push_back(socket_wrapper.release());
|
| - locked_data_.nacl_descs_.push_back(shm_wrapper.release());
|
| - }
|
| -#if defined(OS_POSIX)
|
| - SaveMessage(message);
|
| -#else // defined(OS_POSIX)
|
| - // On Windows we must rewrite the message to the POSIX representation.
|
| - IPC::Message new_msg(message.routing_id(),
|
| - PpapiMsg_PPBAudio_NotifyAudioStreamCreated::ID,
|
| - message.priority());
|
| - WriteHostResource(&new_msg, instance_id, resource_id);
|
| - new_msg.WriteInt(result_code);
|
| - WriteFileDescriptor(&new_msg, 0); // socket handle, index = 0
|
| - WriteFileDescriptor(&new_msg, 1); // shm handle, index = 1
|
| - new_msg.WriteUInt32(shm_length);
|
| - SaveMessage(new_msg);
|
| -#endif
|
| - }
|
| + HandleExtractor<PpapiMsg_PPBAudio_NotifyAudioStreamCreated>
|
| + extractor(message);
|
| + if (!extractor.TranslateMessage(msg, &handles, &fds, new_message_ptr))
|
| + return false;
|
| + break;
|
| + case IPC_REPLY_ID: {
|
| + /* TODO(dmichael): Look up the type of the originating message, do
|
| + another switch here to deal with any reply messages with handles.*/
|
| break;
|
| }
|
| - default: {
|
| - SaveMessage(message);
|
| + default:
|
| +#if defined(OS_WIN)
|
| + // There are no handles, and we didn't have to rewrite the new message.
|
| + // Just make sure that SaveMessage below saves the valid message, since
|
| + // new_msg doesn't have any data.
|
| + new_message_ptr = &message;
|
| +#endif
|
| + // default case has nothing to do in posix; we'll save the message
|
| + // below.
|
| + }
|
| + // Now add any descriptors we found to nacl_descs_. These are usually both
|
| + // empty, unless we read a message containing a FD or handle.
|
| + nacl::DescWrapperFactory factory;
|
| + for (ShmHandles::const_iterator iter = handles.begin();
|
| + iter != handles.end();
|
| + ++iter) {
|
| + scoped_ptr<nacl::DescWrapper> shm_wrapper(
|
| + factory.ImportShmHandle(iter->handle, iter->length));
|
| + if (shm_wrapper.get())
|
| + locked_data_.nacl_descs_.push_back(shm_wrapper.release());
|
| + }
|
| + for (FDs::const_iterator iter = fds.begin(); iter != fds.end(); ++iter) {
|
| + scoped_ptr<nacl::DescWrapper> socket_wrapper(
|
| + factory.ImportSyncSocketHandle(sock_handle));
|
| + if (socket_wrapper.get())
|
| + locked_data_.nacl_descs_.push_back(socket_wrapper.release());
|
| }
|
| }
|
| + if (new_message_ptr)
|
| + SaveMessage(*new_message_ptr); // For Windows
|
| + else
|
| + SaveMessage(message);
|
| }
|
| cond_var_.Signal();
|
| return true;
|
| @@ -467,6 +580,21 @@ bool NaClIPCAdapter::SendCompleteMessage(const char* buffer,
|
| if (locked_data_.channel_closed_)
|
| return false; // TODO(brettw) clean up handles here when we add support!
|
|
|
| + // Deal with sync messages with handles in the reply.
|
| + if (msg->is_sync()) {
|
| + if (msg->type() == PpapiHostMsg_PPBImageData_CreateNaCl::ID) {
|
| + int id = IPC::SyncMessage::GetMessageId(*msg);
|
| + PickleIterator iter(IPC::SyncMessage::GetDataIterator(msg.get()));
|
| + int dummy, height, width;
|
| + if (iter.ReadInt(&dummy) && // instance
|
| + iter.ReadInt(&dummy) && // format
|
| + iter.ReadInt(&height) &&
|
| + iter.ReadInt(&width)) {
|
| + uint32_t size = height * width * 4;
|
| + locked_data_.pending_image_data_msgs_[id] = size;
|
| + }
|
| + }
|
| + }
|
| // Actual send must be done on the I/O thread.
|
| task_runner_->PostTask(FROM_HERE,
|
| base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this,
|
| @@ -496,6 +624,7 @@ void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
|
| }
|
|
|
| void NaClIPCAdapter::SaveMessage(const IPC::Message& message) {
|
| + lock_.AssertAcquired();
|
| // There is some padding in this structure (the "padding" member is 16
|
| // bits but this then gets padded to 32 bits). We want to be sure not to
|
| // leak data to the untrusted plugin, so zero everything out first.
|
|
|