diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-16 23:23:53 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-16 23:23:53 +0000 |
commit | eb5960da1e59be98182120c3c489d92094f3c5c9 (patch) | |
tree | 0baeb22b52e5c9d54d15f4fdc5a36dc7a976733a /ppapi | |
parent | 97af43ea66f1a7a734cccbc0e4bf65b88c37c4a7 (diff) | |
download | chromium_src-eb5960da1e59be98182120c3c489d92094f3c5c9.zip chromium_src-eb5960da1e59be98182120c3c489d92094f3c5c9.tar.gz chromium_src-eb5960da1e59be98182120c3c489d92094f3c5c9.tar.bz2 |
PPAPI/NaCl: Move handle extraction code to ppapi/proxy
BUG=165201
TEST=
TBR=jln@chromium.org
Review URL: https://chromiumcodereview.appspot.com/11894003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177257 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/ppapi_ipc.gypi | 4 | ||||
-rw-r--r-- | ppapi/proxy/audio_input_resource.cc | 2 | ||||
-rw-r--r-- | ppapi/proxy/audio_input_resource.h | 1 | ||||
-rw-r--r-- | ppapi/proxy/handle_converter.cc | 258 | ||||
-rw-r--r-- | ppapi/proxy/handle_converter.h | 62 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 1 | ||||
-rw-r--r-- | ppapi/proxy/ppb_audio_proxy.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppb_buffer_proxy.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppb_graphics_3d_proxy.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppb_image_data_proxy.h | 2 | ||||
-rw-r--r-- | ppapi/proxy/resource_message_params.h | 2 | ||||
-rw-r--r-- | ppapi/proxy/serialized_handle.cc | 133 | ||||
-rw-r--r-- | ppapi/proxy/serialized_handle.h | 141 | ||||
-rw-r--r-- | ppapi/proxy/serialized_structs.cc | 119 | ||||
-rw-r--r-- | ppapi/proxy/serialized_structs.h | 114 |
15 files changed, 609 insertions, 239 deletions
diff --git a/ppapi/ppapi_ipc.gypi b/ppapi/ppapi_ipc.gypi index 8e374b2..616d8e5 100644 --- a/ppapi/ppapi_ipc.gypi +++ b/ppapi/ppapi_ipc.gypi @@ -12,6 +12,8 @@ # This part is shared between the targets defined below. ['ppapi_ipc_target==1', { 'sources': [ + 'proxy/handle_converter.cc', + 'proxy/handle_converter.h', 'proxy/ppapi_messages.cc', 'proxy/ppapi_messages.h', 'proxy/ppapi_param_traits.cc', @@ -20,6 +22,8 @@ 'proxy/resource_message_params.h', 'proxy/serialized_flash_menu.cc', 'proxy/serialized_flash_menu.h', + 'proxy/serialized_handle.cc', + 'proxy/serialized_handle.h', 'proxy/serialized_structs.cc', 'proxy/serialized_structs.h', 'proxy/serialized_var.cc', diff --git a/ppapi/proxy/audio_input_resource.cc b/ppapi/proxy/audio_input_resource.cc index 2f17c6c..14dd236 100644 --- a/ppapi/proxy/audio_input_resource.cc +++ b/ppapi/proxy/audio_input_resource.cc @@ -12,7 +12,7 @@ #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/resource_message_params.h" -#include "ppapi/proxy/serialized_structs.h" +#include "ppapi/proxy/serialized_handle.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/resource_tracker.h" #include "ppapi/shared_impl/tracked_callback.h" diff --git a/ppapi/proxy/audio_input_resource.h b/ppapi/proxy/audio_input_resource.h index e8a1ffd..85f27e2 100644 --- a/ppapi/proxy/audio_input_resource.h +++ b/ppapi/proxy/audio_input_resource.h @@ -21,7 +21,6 @@ namespace ppapi { namespace proxy { class ResourceMessageReplyParams; -class SerializedHandle; class AudioInputResource : public PluginResource, public thunk::PPB_AudioInput_API, diff --git a/ppapi/proxy/handle_converter.cc b/ppapi/proxy/handle_converter.cc new file mode 100644 index 0000000..a669062 --- /dev/null +++ b/ppapi/proxy/handle_converter.cc @@ -0,0 +1,258 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/handle_converter.h" + +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_macros.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ppapi/proxy/serialized_handle.h" + +namespace IPC { +class Message; +} + +namespace { + +void WriteHandle(int handle_index, + const ppapi::proxy::SerializedHandle& handle, + IPC::Message* message) { + ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message); + + // Now write the handle itself in POSIX style. + message->WriteBool(true); // valid == true + message->WriteInt(handle_index); +} + +typedef std::vector<ppapi::proxy::SerializedHandle> Handles; + +// We define overload for catching SerializedHandles, so that we can share +// them correctly to the untrusted side, and another for handling all other +// parameters. See ConvertHandlesImpl for how these get used. +void ConvertHandlesInParam(const ppapi::proxy::SerializedHandle& handle, + Handles* handles, + IPC::Message* msg, + int* handle_index) { + handles->push_back(handle); + if (msg) + WriteHandle((*handle_index)++, handle, msg); +} + +// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall, +// the handles are carried inside the ResourceMessageReplyParams. +// NOTE: We only translate handles from host->NaCl. The only kind of +// ResourceMessageParams that travels this direction is +// ResourceMessageReplyParams, so that's the only one we need to handle. +void ConvertHandlesInParam( + const ppapi::proxy::ResourceMessageReplyParams& params, + Handles* handles, + IPC::Message* msg, + int* handle_index) { + // First, if we need to rewrite the message parameters, write everything + // before the handles (there's nothing after the handles). + if (msg) { + params.WriteReplyHeader(msg); + // IPC writes the vector length as an int before the contents of the + // vector. + msg->WriteInt(static_cast<int>(params.handles().size())); + } + for (Handles::const_iterator iter = params.handles().begin(); + iter != params.handles().end(); + ++iter) { + // ConvertHandle will write each handle to |msg|, if necessary. + ConvertHandlesInParam(*iter, handles, msg, handle_index); + } + // Tell ResourceMessageReplyParams that we have taken the handles, so it + // shouldn't close them. The NaCl runtime will take ownership of them. + params.ConsumeHandles(); +} + +// This overload is to catch all types other than SerializedHandle or +// ResourceMessageReplyParams. On Windows, |msg| will be a valid pointer, and we +// must write |param| to it. +template <class T> +void ConvertHandlesInParam(const T& param, + Handles* /* handles */, + IPC::Message* msg, + int* /* handle_index */) { + // It's not a handle, so just write to the output message, if necessary. + if (msg) + IPC::WriteParam(msg, param); +} + +// These just break apart the given tuple and run ConvertHandle 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 all of the message parameters, writing the handles in POSIX style +// for NaCl. +template <class A> +void ConvertHandlesImpl(const Tuple1<A>& t1, Handles* handles, + IPC::Message* msg) { + int handle_index = 0; + ConvertHandlesInParam(t1.a, handles, msg, &handle_index); +} +template <class A, class B> +void ConvertHandlesImpl(const Tuple2<A, B>& t1, Handles* handles, + IPC::Message* msg) { + int handle_index = 0; + ConvertHandlesInParam(t1.a, handles, msg, &handle_index); + ConvertHandlesInParam(t1.b, handles, msg, &handle_index); +} +template <class A, class B, class C> +void ConvertHandlesImpl(const Tuple3<A, B, C>& t1, Handles* handles, + IPC::Message* msg) { + int handle_index = 0; + ConvertHandlesInParam(t1.a, handles, msg, &handle_index); + ConvertHandlesInParam(t1.b, handles, msg, &handle_index); + ConvertHandlesInParam(t1.c, handles, msg, &handle_index); +} +template <class A, class B, class C, class D> +void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles, + IPC::Message* msg) { + int handle_index = 0; + ConvertHandlesInParam(t1.a, handles, msg, &handle_index); + ConvertHandlesInParam(t1.b, handles, msg, &handle_index); + ConvertHandlesInParam(t1.c, handles, msg, &handle_index); + ConvertHandlesInParam(t1.d, handles, msg, &handle_index); +} + +template <class MessageType> +class HandleConverterImpl { + public: + explicit HandleConverterImpl(const IPC::Message* msg) + : msg_(static_cast<const MessageType*>(msg)) { + } + bool ConvertMessage(Handles* handles, IPC::Message* out_msg) { + typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params; + if (!MessageType::Read(msg_, ¶ms)) + return false; + ConvertHandlesImpl(params, handles, out_msg); + return true; + } + + bool ConvertReply(Handles* handles, IPC::SyncMessage* out_msg) { + typename TupleTypes<typename MessageType::Schema::ReplyParam>::ValueTuple + params; + if (!MessageType::ReadReplyParam(msg_, ¶ms)) + return false; + // If we need to rewrite the message (i.e., on Windows), we need to make + // sure we write the message id first. + if (out_msg) { + out_msg->set_reply(); + int id = IPC::SyncMessage::GetMessageId(*msg_); + out_msg->WriteInt(id); + } + ConvertHandlesImpl(params, handles, out_msg); + return true; + } + // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we + // ever pass handles in one of those. + + private: + const MessageType* msg_; +}; + +} // namespace + +#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \ + case MESSAGE_TYPE::ID: { \ + HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \ + if (!extractor.ConvertMessage(handles, new_msg_ptr->get())) \ + return false; \ + break; \ + } +#define CASE_FOR_REPLY(MESSAGE_TYPE) \ + case MESSAGE_TYPE::ID: { \ + HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \ + if (!extractor.ConvertReply( \ + handles, \ + static_cast<IPC::SyncMessage*>(new_msg_ptr->get()))) \ + return false; \ + break; \ + } + +namespace ppapi { +namespace proxy { + +class SerializedHandle; + +HandleConverter::HandleConverter() { +} + +bool HandleConverter::ConvertNativeHandlesToPosix( + const IPC::Message& msg, + std::vector<SerializedHandle>* handles, + scoped_ptr<IPC::Message>* new_msg_ptr) { + DCHECK(handles); + DCHECK(new_msg_ptr); + DCHECK(!new_msg_ptr->get()); + + // In Windows, we need to re-write the contents of the message. This is + // because in Windows IPC code, native HANDLE values are serialized in the + // body of the message. + // + // In POSIX, we only serialize an index in to a FileDescriptorSet, and the + // actual file descriptors are sent out-of-band. So on Windows, to make a + // message that's compatible with Windows, we need to write a new message that + // has simple indices in the message body instead of the HANDLEs. + // + // NOTE: This means on Windows, new_msg_ptr's serialized contents are not + // compatible with Windows IPC deserialization code; it is intended to be + // passed to NaCl. +#if defined(OS_WIN) + new_msg_ptr->reset( + new IPC::Message(msg.routing_id(), msg.type(), msg.priority())); +#else + // Even on POSIX, we have to rewrite messages to create channels, because + // these contain a handle with an invalid (place holder) descriptor. The + // message sending code sees this and doesn't pass the descriptor over + // correctly. + if (msg.type() == PpapiMsg_CreateNaClChannel::ID) { + new_msg_ptr->reset( + new IPC::Message(msg.routing_id(), msg.type(), msg.priority())); + } +#endif + + switch (msg.type()) { + CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) + CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) + CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) + case IPC_REPLY_ID: { + int id = IPC::SyncMessage::GetMessageId(msg); + PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id)); + if (iter == pending_sync_msgs_.end()) { + NOTREACHED(); + return false; + } + uint32_t type = iter->second; + pending_sync_msgs_.erase(iter); + switch (type) { + CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer) + CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl) + CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall) + default: + // Do nothing for messages we don't know. + break; + } + break; + } + default: + // Do nothing for messages we don't know. + break; + } + return true; +} + +void HandleConverter::RegisterSyncMessageForReply(const IPC::Message& msg) { + DCHECK(msg.is_sync()); + + int msg_id = IPC::SyncMessage::GetMessageId(msg); + DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end()); + + pending_sync_msgs_[msg_id] = msg.type(); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/handle_converter.h b/ppapi/proxy/handle_converter.h new file mode 100644 index 0000000..456ee8d --- /dev/null +++ b/ppapi/proxy/handle_converter.h @@ -0,0 +1,62 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PPAPI_PROXY_HANDLE_CONVERTER_H_ +#define PPAPI_PROXY_HANDLE_CONVERTER_H_ + +#include <map> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +namespace IPC { +class Message; +} + +namespace ppapi { +namespace proxy { + +class SerializedHandle; + +class PPAPI_PROXY_EXPORT HandleConverter { + public: + HandleConverter(); + + // Convert the native handles in |msg| to NaCl style. + // In some cases (e.g., Windows), we need to re-write the contents of the + // message; in those cases, |new_msg_ptr| will be set to the new message. + // If |msg| is already in a good form for NaCl, |new_msg_ptr| is left NULL. + // See the explanation in the body of the method. + // + // In either case, all the handles in |msg| are extracted into |handles| so + // that they can be converted to NaClDesc handles. + // See chrome/nacl/nacl_ipc_adapter.cc for where this gets used. + bool ConvertNativeHandlesToPosix(const IPC::Message& msg, + std::vector<SerializedHandle>* handles, + scoped_ptr<IPC::Message>* new_msg_ptr); + + // This method informs HandleConverter that a sync message is being sent so + // that it can associate reply messages with their type. + // + // Users of HandleConverter must call this when they send a synchronous + // message, otherwise HandleConverter won't be able to convert handles in + // replies. + void RegisterSyncMessageForReply(const IPC::Message& msg); + + private: + // When we send a synchronous message (from untrusted to trusted), we store + // its type here, so that later we can associate the reply with its type + // and potentially translate handles in the message. + typedef std::map<int, uint32> PendingSyncMsgMap; + PendingSyncMsgMap pending_sync_msgs_; + + DISALLOW_COPY_AND_ASSIGN(HandleConverter); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_HANDLE_CONVERTER_H_ diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 54d6bfb..b4666e4 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -45,6 +45,7 @@ #include "ppapi/proxy/ppapi_proxy_export.h" #include "ppapi/proxy/resource_message_params.h" #include "ppapi/proxy/serialized_flash_menu.h" +#include "ppapi/proxy/serialized_handle.h" #include "ppapi/proxy/serialized_structs.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/shared_impl/dir_contents.h" diff --git a/ppapi/proxy/ppb_audio_proxy.h b/ppapi/proxy/ppb_audio_proxy.h index 2f85a83..757bdeb 100644 --- a/ppapi/proxy/ppb_audio_proxy.h +++ b/ppapi/proxy/ppb_audio_proxy.h @@ -17,7 +17,6 @@ #include "ppapi/c/ppb_audio_config.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_completion_callback_factory.h" -#include "ppapi/proxy/serialized_structs.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -26,6 +25,8 @@ class HostResource; namespace proxy { +class SerializedHandle; + class PPB_Audio_Proxy : public InterfaceProxy { public: PPB_Audio_Proxy(Dispatcher* dispatcher); diff --git a/ppapi/proxy/ppb_buffer_proxy.h b/ppapi/proxy/ppb_buffer_proxy.h index 41f5e19..ff8e0ca 100644 --- a/ppapi/proxy/ppb_buffer_proxy.h +++ b/ppapi/proxy/ppb_buffer_proxy.h @@ -8,7 +8,6 @@ #include "base/shared_memory.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/serialized_structs.h" #include "ppapi/shared_impl/resource.h" #include "ppapi/thunk/ppb_buffer_api.h" @@ -18,6 +17,8 @@ class HostResource; namespace proxy { +class SerializedHandle; + class Buffer : public thunk::PPB_Buffer_API, public Resource { public: Buffer(const HostResource& resource, diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index 17529a1..493c489 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h @@ -13,7 +13,6 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_completion_callback_factory.h" -#include "ppapi/proxy/serialized_structs.h" #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" #include "ppapi/shared_impl/resource.h" #include "ppapi/utility/completion_callback_factory.h" @@ -24,6 +23,8 @@ class HostResource; namespace proxy { +class SerializedHandle; + class Graphics3D : public PPB_Graphics3D_Shared { public: explicit Graphics3D(const HostResource& resource); diff --git a/ppapi/proxy/ppb_image_data_proxy.h b/ppapi/proxy/ppb_image_data_proxy.h index c56217a5..ae24b35 100644 --- a/ppapi/proxy/ppb_image_data_proxy.h +++ b/ppapi/proxy/ppb_image_data_proxy.h @@ -27,6 +27,8 @@ class TransportDIB; namespace ppapi { namespace proxy { +class SerializedHandle; + // The proxied image data resource. Unlike most resources, this needs to be // public in the header since a number of other resources need to access it. class ImageData : public ppapi::Resource, diff --git a/ppapi/proxy/resource_message_params.h b/ppapi/proxy/resource_message_params.h index 0e42ec9..21b0f73 100644 --- a/ppapi/proxy/resource_message_params.h +++ b/ppapi/proxy/resource_message_params.h @@ -11,7 +11,7 @@ #include "ipc/ipc_message_utils.h" #include "ppapi/c/pp_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" -#include "ppapi/proxy/serialized_structs.h" +#include "ppapi/proxy/serialized_handle.h" namespace ppapi { namespace proxy { diff --git a/ppapi/proxy/serialized_handle.cc b/ppapi/proxy/serialized_handle.cc new file mode 100644 index 0000000..0159e6f --- /dev/null +++ b/ppapi/proxy/serialized_handle.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/serialized_handle.h" + +#include "base/pickle.h" +#include "base/platform_file.h" +#include "base/shared_memory.h" +#include "build/build_config.h" +#include "ipc/ipc_platform_file.h" + +#if defined(OS_NACL) +#include <unistd.h> +#endif + +namespace ppapi { +namespace proxy { + +SerializedHandle::SerializedHandle() + : type_(INVALID), + shm_handle_(base::SharedMemory::NULLHandle()), + size_(0), + descriptor_(IPC::InvalidPlatformFileForTransit()) { +} + +SerializedHandle::SerializedHandle(Type type_param) + : type_(type_param), + shm_handle_(base::SharedMemory::NULLHandle()), + size_(0), + descriptor_(IPC::InvalidPlatformFileForTransit()) { +} + +SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle, + uint32 size) + : type_(SHARED_MEMORY), + shm_handle_(handle), + size_(size), + descriptor_(IPC::InvalidPlatformFileForTransit()) { +} + +SerializedHandle::SerializedHandle( + Type type, + const IPC::PlatformFileForTransit& socket_descriptor) + : type_(type), + shm_handle_(base::SharedMemory::NULLHandle()), + size_(0), + descriptor_(socket_descriptor) { +} + +bool SerializedHandle::IsHandleValid() const { + switch (type_) { + case SHARED_MEMORY: + return base::SharedMemory::IsHandleValid(shm_handle_); + case SOCKET: + case CHANNEL_HANDLE: + case FILE: + return !(IPC::InvalidPlatformFileForTransit() == descriptor_); + case INVALID: + return false; + // No default so the compiler will warn us if a new type is added. + } + return false; +} + +void SerializedHandle::Close() { + if (IsHandleValid()) { + switch (type_) { + case INVALID: + NOTREACHED(); + break; + case SHARED_MEMORY: + base::SharedMemory::CloseHandle(shm_handle_); + break; + case SOCKET: + case CHANNEL_HANDLE: + case FILE: + base::PlatformFile file = + IPC::PlatformFileForTransitToPlatformFile(descriptor_); +#if !defined(OS_NACL) + base::ClosePlatformFile(file); +#else + close(file); +#endif + break; + // No default so the compiler will warn us if a new type is added. + } + } + *this = SerializedHandle(); +} + +// static +bool SerializedHandle::WriteHeader(const Header& hdr, Pickle* pickle) { + if (!pickle->WriteInt(hdr.type)) + return false; + if (hdr.type == SHARED_MEMORY) { + if (!pickle->WriteUInt32(hdr.size)) + return false; + } + return true; +} + +// static +bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) { + *hdr = Header(INVALID, 0); + int type = 0; + if (!iter->ReadInt(&type)) + return false; + bool valid_type = false; + switch (type) { + case SHARED_MEMORY: { + uint32 size = 0; + if (!iter->ReadUInt32(&size)) + return false; + hdr->size = size; + valid_type = true; + break; + } + case SOCKET: + case CHANNEL_HANDLE: + case FILE: + case INVALID: + valid_type = true; + break; + // No default so the compiler will warn us if a new type is added. + } + if (valid_type) + hdr->type = Type(type); + return valid_type; +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/serialized_handle.h b/ppapi/proxy/serialized_handle.h new file mode 100644 index 0000000..9e4136f --- /dev/null +++ b/ppapi/proxy/serialized_handle.h @@ -0,0 +1,141 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PPAPI_PROXY_SERIALIZED_HANDLES_H_ +#define PPAPI_PROXY_SERIALIZED_HANDLES_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/shared_memory.h" +#include "build/build_config.h" +#include "ipc/ipc_platform_file.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +class Pickle; + +namespace ppapi { +namespace proxy { + +// SerializedHandle is a unified structure for holding a handle (e.g., a shared +// memory handle, socket descriptor, etc). This is useful for passing handles in +// resource messages and also makes it easier to translate handles in +// NaClIPCAdapter for use in NaCl. +class PPAPI_PROXY_EXPORT SerializedHandle { + public: + enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE, FILE }; + struct Header { + Header() : type(INVALID), size(0) {} + Header(Type type_arg, uint32 size_arg) + : type(type_arg), size(size_arg) { + } + Type type; + uint32 size; + }; + + SerializedHandle(); + // Create an invalid handle of the given type. + explicit SerializedHandle(Type type); + + // Create a shared memory handle. + SerializedHandle(const base::SharedMemoryHandle& handle, uint32 size); + + // Create a socket, channel or file handle. + SerializedHandle(const Type type, + const IPC::PlatformFileForTransit& descriptor); + + Type type() const { return type_; } + bool is_shmem() const { return type_ == SHARED_MEMORY; } + bool is_socket() const { return type_ == SOCKET; } + bool is_channel_handle() const { return type_ == CHANNEL_HANDLE; } + bool is_file() const { return type_ == FILE; } + const base::SharedMemoryHandle& shmem() const { + DCHECK(is_shmem()); + return shm_handle_; + } + uint32 size() const { + DCHECK(is_shmem()); + return size_; + } + const IPC::PlatformFileForTransit& descriptor() const { + DCHECK(is_socket() || is_channel_handle() || is_file()); + return descriptor_; + } + void set_shmem(const base::SharedMemoryHandle& handle, uint32 size) { + type_ = SHARED_MEMORY; + shm_handle_ = handle; + size_ = size; + + descriptor_ = IPC::InvalidPlatformFileForTransit(); + } + void set_socket(const IPC::PlatformFileForTransit& socket) { + type_ = SOCKET; + descriptor_ = socket; + + shm_handle_ = base::SharedMemory::NULLHandle(); + size_ = 0; + } + void set_channel_handle(const IPC::PlatformFileForTransit& descriptor) { + type_ = CHANNEL_HANDLE; + + descriptor_ = descriptor; + shm_handle_ = base::SharedMemory::NULLHandle(); + size_ = 0; + } + void set_file_handle(const IPC::PlatformFileForTransit& descriptor) { + type_ = FILE; + + descriptor_ = descriptor; + shm_handle_ = base::SharedMemory::NULLHandle(); + size_ = 0; + } + void set_null_shmem() { + set_shmem(base::SharedMemory::NULLHandle(), 0); + } + void set_null_socket() { + set_socket(IPC::InvalidPlatformFileForTransit()); + } + void set_null_channel_handle() { + set_channel_handle(IPC::InvalidPlatformFileForTransit()); + } + void set_null_file_handle() { + set_file_handle(IPC::InvalidPlatformFileForTransit()); + } + bool IsHandleValid() const; + + Header header() const { + return Header(type_, size_); + } + + // Closes the handle and sets it to invalid. + void Close(); + + // Write/Read a Header, which contains all the data except the handle. This + // allows us to write the handle in a platform-specific way, as is necessary + // in NaClIPCAdapter to share handles with NaCl from Windows. + static bool WriteHeader(const Header& hdr, Pickle* pickle); + static bool ReadHeader(PickleIterator* iter, Header* hdr); + + private: + // The kind of handle we're holding. + Type type_; + + // We hold more members than we really need; we can't easily use a union, + // because we hold non-POD types. But these types are pretty light-weight. If + // we add more complex things later, we should come up with a more memory- + // efficient strategy. + // These are valid if type == SHARED_MEMORY. + base::SharedMemoryHandle shm_handle_; + uint32 size_; + + // This is valid if type == SOCKET || type == CHANNEL_HANDLE. + IPC::PlatformFileForTransit descriptor_; +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_SERIALIZED_HANDLES_H_ diff --git a/ppapi/proxy/serialized_structs.cc b/ppapi/proxy/serialized_structs.cc index fcd41a7..ebd7ed0 100644 --- a/ppapi/proxy/serialized_structs.cc +++ b/ppapi/proxy/serialized_structs.cc @@ -5,20 +5,13 @@ #include "ppapi/proxy/serialized_structs.h" #include "base/pickle.h" -#include "base/platform_file.h" -#include "base/shared_memory.h" #include "build/build_config.h" -#include "ipc/ipc_platform_file.h" #include "ppapi/c/dev/ppb_font_dev.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_rect.h" #include "ppapi/c/trusted/ppb_browser_font_trusted.h" #include "ppapi/shared_impl/var.h" -#if defined(OS_NACL) -#include <unistd.h> -#endif - namespace ppapi { namespace proxy { @@ -102,117 +95,5 @@ PPBFlash_DrawGlyphs_Params::PPBFlash_DrawGlyphs_Params() PPBFlash_DrawGlyphs_Params::~PPBFlash_DrawGlyphs_Params() {} -SerializedHandle::SerializedHandle() - : type_(INVALID), - shm_handle_(base::SharedMemory::NULLHandle()), - size_(0), - descriptor_(IPC::InvalidPlatformFileForTransit()) { -} - -SerializedHandle::SerializedHandle(Type type_param) - : type_(type_param), - shm_handle_(base::SharedMemory::NULLHandle()), - size_(0), - descriptor_(IPC::InvalidPlatformFileForTransit()) { -} - -SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle, - uint32_t size) - : type_(SHARED_MEMORY), - shm_handle_(handle), - size_(size), - descriptor_(IPC::InvalidPlatformFileForTransit()) { -} - -SerializedHandle::SerializedHandle( - Type type, - const IPC::PlatformFileForTransit& socket_descriptor) - : type_(type), - shm_handle_(base::SharedMemory::NULLHandle()), - size_(0), - descriptor_(socket_descriptor) { -} - -bool SerializedHandle::IsHandleValid() const { - switch (type_) { - case SHARED_MEMORY: - return base::SharedMemory::IsHandleValid(shm_handle_); - case SOCKET: - case CHANNEL_HANDLE: - case FILE: - return !(IPC::InvalidPlatformFileForTransit() == descriptor_); - case INVALID: - return false; - // No default so the compiler will warn us if a new type is added. - } - return false; -} - -void SerializedHandle::Close() { - if (IsHandleValid()) { - switch (type_) { - case INVALID: - NOTREACHED(); - break; - case SHARED_MEMORY: - base::SharedMemory::CloseHandle(shm_handle_); - break; - case SOCKET: - case CHANNEL_HANDLE: - case FILE: - base::PlatformFile file = - IPC::PlatformFileForTransitToPlatformFile(descriptor_); -#if !defined(OS_NACL) - base::ClosePlatformFile(file); -#else - close(file); -#endif - break; - // No default so the compiler will warn us if a new type is added. - } - } - *this = SerializedHandle(); -} - -// static -bool SerializedHandle::WriteHeader(const Header& hdr, Pickle* pickle) { - if (!pickle->WriteInt(hdr.type)) - return false; - if (hdr.type == SHARED_MEMORY) { - if (!pickle->WriteUInt32(hdr.size)) - return false; - } - return true; -} - -// static -bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) { - *hdr = Header(INVALID, 0); - int type = 0; - if (!iter->ReadInt(&type)) - return false; - bool valid_type = false; - switch (type) { - case SHARED_MEMORY: { - uint32_t size = 0; - if (!iter->ReadUInt32(&size)) - return false; - hdr->size = size; - valid_type = true; - break; - } - case SOCKET: - case CHANNEL_HANDLE: - case FILE: - case INVALID: - valid_type = true; - break; - // No default so the compiler will warn us if a new type is added. - } - if (valid_type) - hdr->type = Type(type); - return valid_type; -} - } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/serialized_structs.h b/ppapi/proxy/serialized_structs.h index 5c5dcab..dcb99817 100644 --- a/ppapi/proxy/serialized_structs.h +++ b/ppapi/proxy/serialized_structs.h @@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/shared_memory.h" #include "build/build_config.h" -#include "ipc/ipc_platform_file.h" #include "ppapi/c/pp_bool.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_point.h" @@ -87,119 +86,6 @@ struct PPBURLLoader_UpdateProgress_Params { int64_t total_bytes_to_be_received; }; -// We put all our handles in a unified structure to make it easy to translate -// them in NaClIPCAdapter for use in NaCl. -class PPAPI_PROXY_EXPORT SerializedHandle { - public: - enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE, FILE }; - struct Header { - Header() : type(INVALID), size(0) {} - Header(Type type_arg, uint32_t size_arg) - : type(type_arg), size(size_arg) { - } - Type type; - uint32_t size; - }; - - SerializedHandle(); - // Create an invalid handle of the given type. - explicit SerializedHandle(Type type); - - // Create a shared memory handle. - SerializedHandle(const base::SharedMemoryHandle& handle, uint32_t size); - - // Create a socket, channel or file handle. - SerializedHandle(const Type type, - const IPC::PlatformFileForTransit& descriptor); - - Type type() const { return type_; } - bool is_shmem() const { return type_ == SHARED_MEMORY; } - bool is_socket() const { return type_ == SOCKET; } - bool is_channel_handle() const { return type_ == CHANNEL_HANDLE; } - bool is_file() const { return type_ == FILE; } - const base::SharedMemoryHandle& shmem() const { - DCHECK(is_shmem()); - return shm_handle_; - } - uint32_t size() const { - DCHECK(is_shmem()); - return size_; - } - const IPC::PlatformFileForTransit& descriptor() const { - DCHECK(is_socket() || is_channel_handle() || is_file()); - return descriptor_; - } - void set_shmem(const base::SharedMemoryHandle& handle, uint32_t size) { - type_ = SHARED_MEMORY; - shm_handle_ = handle; - size_ = size; - - descriptor_ = IPC::InvalidPlatformFileForTransit(); - } - void set_socket(const IPC::PlatformFileForTransit& socket) { - type_ = SOCKET; - descriptor_ = socket; - - shm_handle_ = base::SharedMemory::NULLHandle(); - size_ = 0; - } - void set_channel_handle(const IPC::PlatformFileForTransit& descriptor) { - type_ = CHANNEL_HANDLE; - - descriptor_ = descriptor; - shm_handle_ = base::SharedMemory::NULLHandle(); - size_ = 0; - } - void set_file_handle(const IPC::PlatformFileForTransit& descriptor) { - type_ = FILE; - - descriptor_ = descriptor; - shm_handle_ = base::SharedMemory::NULLHandle(); - size_ = 0; - } - void set_null_shmem() { - set_shmem(base::SharedMemory::NULLHandle(), 0); - } - void set_null_socket() { - set_socket(IPC::InvalidPlatformFileForTransit()); - } - void set_null_channel_handle() { - set_channel_handle(IPC::InvalidPlatformFileForTransit()); - } - void set_null_file_handle() { - set_file_handle(IPC::InvalidPlatformFileForTransit()); - } - bool IsHandleValid() const; - - Header header() const { - return Header(type_, size_); - } - - // Closes the handle and sets it to invalid. - void Close(); - - // Write/Read a Header, which contains all the data except the handle. This - // allows us to write the handle in a platform-specific way, as is necessary - // in NaClIPCAdapter to share handles with NaCl from Windows. - static bool WriteHeader(const Header& hdr, Pickle* pickle); - static bool ReadHeader(PickleIterator* iter, Header* hdr); - - private: - // The kind of handle we're holding. - Type type_; - - // We hold more members than we really need; we can't easily use a union, - // because we hold non-POD types. But these types are pretty light-weight. If - // we add more complex things later, we should come up with a more memory- - // efficient strategy. - // These are valid if type == SHARED_MEMORY. - base::SharedMemoryHandle shm_handle_; - uint32_t size_; - - // This is valid if type == SOCKET || type == CHANNEL_HANDLE. - IPC::PlatformFileForTransit descriptor_; -}; - struct PPPDecryptor_Buffer { ppapi::HostResource resource; uint32_t size; |