diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-30 13:24:23 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-30 13:24:23 +0000 |
commit | 68ca863f9323a1ab2d02545f893f34a1e58a1a3f (patch) | |
tree | d2c2a910fcdd242ca70815bba3be4f9420cd0df7 /ppapi | |
parent | 6ecc9adc9370980d134c5e3591a27712ed8f8932 (diff) | |
download | chromium_src-68ca863f9323a1ab2d02545f893f34a1e58a1a3f.zip chromium_src-68ca863f9323a1ab2d02545f893f34a1e58a1a3f.tar.gz chromium_src-68ca863f9323a1ab2d02545f893f34a1e58a1a3f.tar.bz2 |
Change NaCl IPC PPAPI proxy startup to support a NaCl-Browser process
channel.
NaClProcessHost now creates an initial NaCl-Browser channel, then uses
it to send a message to create the NaCl-Renderer channel. The main() for
the IPC-IRT creates a PpapiDispatcher object to manage this channel and
manage the PluginDispatchers for each renderer.
BUG=116317
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/10883047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154134 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/proxy/plugin_main_nacl.cc | 188 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 8 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_param_traits.cc | 9 | ||||
-rw-r--r-- | ppapi/proxy/ppb_audio_proxy.cc | 9 | ||||
-rw-r--r-- | ppapi/proxy/serialized_structs.cc | 10 | ||||
-rw-r--r-- | ppapi/proxy/serialized_structs.h | 25 |
6 files changed, 183 insertions, 66 deletions
diff --git a/ppapi/proxy/plugin_main_nacl.cc b/ppapi/proxy/plugin_main_nacl.cc index 96a6891..ac7cdcd 100644 --- a/ppapi/proxy/plugin_main_nacl.cc +++ b/ppapi/proxy/plugin_main_nacl.cc @@ -23,6 +23,7 @@ #include "ppapi/c/ppp_instance.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_globals.h" +#include "ppapi/proxy/plugin_proxy_delegate.h" #include "ppapi/shared_impl/ppb_audio_shared.h" #if defined(IPC_MESSAGE_LOG_ENABLED) @@ -36,60 +37,48 @@ using ppapi::proxy::PluginDispatcher; using ppapi::proxy::PluginGlobals; +using ppapi::proxy::PluginProxyDelegate; +using ppapi::proxy::ProxyChannel; +using ppapi::proxy::SerializedHandle; namespace { -// Copied from src/content/ppapi_plugin/ppapi_thread. This is a minimal -// implementation to get us started. -class PluginDispatcherDelegate : public PluginDispatcher::PluginDelegate { +// This class manages communication between the plugin and the browser, and +// manages the PluginDispatcher instances for communication between the plugin +// and the renderer. +class PpapiDispatcher : public ProxyChannel, + public PluginDispatcher::PluginDelegate, + public PluginProxyDelegate { public: - explicit PluginDispatcherDelegate( - scoped_refptr<base::MessageLoopProxy> io_loop) - : message_loop_(io_loop), - shutdown_event_(true, false) { - } - - virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE { - return message_loop_.get(); - } - - virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE { - return &shutdown_event_; - } + explicit PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop); + // PluginDispatcher::PluginDelegate implementation. + virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE; + virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE; virtual IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, const IPC::SyncChannel& channel, - bool should_close_source) OVERRIDE { - return IPC::InvalidPlatformFileForTransit(); - } + bool should_close_source) OVERRIDE; + virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE; + virtual uint32 Register(PluginDispatcher* plugin_dispatcher) OVERRIDE; + virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE; - virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE { - return &instances_; - } - - virtual uint32 Register(PluginDispatcher* plugin_dispatcher) OVERRIDE { - if (!plugin_dispatcher || - plugin_dispatchers_.size() >= std::numeric_limits<uint32>::max()) { - return 0; - } - - uint32 id = 0; - do { - // Although it is unlikely, make sure that we won't cause any trouble when - // the counter overflows. - id = next_plugin_dispatcher_id_++; - } while (id == 0 || - plugin_dispatchers_.find(id) != plugin_dispatchers_.end()); - plugin_dispatchers_[id] = plugin_dispatcher; - return id; - } + // PluginProxyDelegate implementation. + virtual bool SendToBrowser(IPC::Message* msg) OVERRIDE; + virtual IPC::Sender* GetBrowserSender() OVERRIDE; + virtual std::string GetUILanguage() OVERRIDE; + virtual void PreCacheFont(const void* logfontw) OVERRIDE; + virtual void SetActiveURL(const std::string& url) OVERRIDE; - virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE { - plugin_dispatchers_.erase(plugin_dispatcher_id); - } + // IPC::Listener implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: + void OnMsgCreateNaClChannel(int renderer_id, + bool incognito, + SerializedHandle handle); + void OnPluginDispatcherMessageReceived(const IPC::Message& msg); + std::set<PP_Instance> instances_; std::map<uint32, PluginDispatcher*> plugin_dispatchers_; uint32 next_plugin_dispatcher_id_; @@ -97,6 +86,113 @@ class PluginDispatcherDelegate : public PluginDispatcher::PluginDelegate { base::WaitableEvent shutdown_event_; }; +PpapiDispatcher::PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop) + : message_loop_(io_loop), + shutdown_event_(true, false) { + IPC::ChannelHandle channel_handle( + "NaCl IPC", base::FileDescriptor(NACL_IPC_FD, false)); + InitWithChannel(this, channel_handle, false); // Channel is server. +} + +base::MessageLoopProxy* PpapiDispatcher::GetIPCMessageLoop() { + return message_loop_.get(); +} + +base::WaitableEvent* PpapiDispatcher::GetShutdownEvent() { + return &shutdown_event_; +} + +IPC::PlatformFileForTransit PpapiDispatcher::ShareHandleWithRemote( + base::PlatformFile handle, + const IPC::SyncChannel& channel, + bool should_close_source) OVERRIDE { + return IPC::InvalidPlatformFileForTransit(); +} + +std::set<PP_Instance>* PpapiDispatcher::GetGloballySeenInstanceIDSet() { + return &instances_; +} + +uint32 PpapiDispatcher::Register(PluginDispatcher* plugin_dispatcher) { + if (!plugin_dispatcher || + plugin_dispatchers_.size() >= std::numeric_limits<uint32>::max()) { + return 0; + } + + uint32 id = 0; + do { + // Although it is unlikely, make sure that we won't cause any trouble + // when the counter overflows. + id = next_plugin_dispatcher_id_++; + } while (id == 0 || + plugin_dispatchers_.find(id) != plugin_dispatchers_.end()); + plugin_dispatchers_[id] = plugin_dispatcher; + return id; +} + +void PpapiDispatcher::Unregister(uint32 plugin_dispatcher_id) { + plugin_dispatchers_.erase(plugin_dispatcher_id); +} + +bool PpapiDispatcher::SendToBrowser(IPC::Message* msg) { + Send(msg); +} + +IPC::Sender* PpapiDispatcher::GetBrowserSender() { + return this; +} + +std::string PpapiDispatcher::GetUILanguage() { + NOTIMPLEMENTED(); + return std::string(); +} + +void PpapiDispatcher::PreCacheFont(const void* logfontw) { + NOTIMPLEMENTED(); +} + +void PpapiDispatcher::SetActiveURL(const std::string& url) { + NOTIMPLEMENTED(); +} + +bool PpapiDispatcher::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PpapiDispatcher, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_CreateNaClChannel, + OnMsgCreateNaClChannel) + IPC_END_MESSAGE_MAP() + return true; +} + +void PpapiDispatcher::OnMsgCreateNaClChannel(int renderer_id, + bool incognito, + SerializedHandle handle) { + PluginDispatcher* dispatcher = + new PluginDispatcher(::PPP_GetInterface, incognito); + // The channel handle's true name is not revealed here. + IPC::ChannelHandle channel_handle("nacl", handle.descriptor()); + if (!dispatcher->InitPluginWithChannel(this, channel_handle, false)) { + delete dispatcher; + return; + } + // From here, the dispatcher will manage its own lifetime according to the + // lifetime of the attached channel. +} + +void PpapiDispatcher::OnPluginDispatcherMessageReceived( + const IPC::Message& msg) { + // The first parameter should be a plugin dispatcher ID. + PickleIterator iter(msg); + uint32 id = 0; + if (!msg.ReadUInt32(&iter, &id)) { + NOTREACHED(); + return; + } + std::map<uint32, ppapi::proxy::PluginDispatcher*>::iterator dispatcher = + plugin_dispatchers_.find(id); + if (dispatcher != plugin_dispatchers_.end()) + dispatcher->second->OnMessageReceived(msg); +} + } // namespace void PpapiPluginRegisterThreadCreator( @@ -127,13 +223,7 @@ int PpapiPluginMain() { if (error) return error; - PluginDispatcherDelegate delegate(io_thread.message_loop_proxy()); - - // TODO(dmichael) Figure out how to determine if we're in incognito - PluginDispatcher dispatcher(::PPP_GetInterface, false /* incognito */); - IPC::ChannelHandle channel_handle("NaCl IPC", - base::FileDescriptor(NACL_IPC_FD, false)); - dispatcher.InitPluginWithChannel(&delegate, channel_handle, false); + PpapiDispatcher ppapi_dispatcher(io_thread.message_loop_proxy()); loop.Run(); return 0; diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 8ba5760..b1f460b 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -266,6 +266,14 @@ IPC_MESSAGE_CONTROL2(PpapiMsg_CreateChannel, int /* renderer_id */, bool /* incognito */) +// Creates a channel to talk to a renderer. This message is only used by the +// NaCl IPC proxy. It is intercepted by NaClIPCAdapter, which creates the +// actual channel and rewrites the message for the untrusted side. +IPC_MESSAGE_CONTROL3(PpapiMsg_CreateNaClChannel, + int /* renderer_id */, + bool /* incognito */, + ppapi::proxy::SerializedHandle /* channel_handle */) + // Each plugin may be referenced by multiple renderers. We need the instance // IDs to be unique within a plugin, despite coming from different renderers, // and unique within a renderer, despite going to different plugins. This means diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc index bcb2df0..a642da0 100644 --- a/ppapi/proxy/ppapi_param_traits.cc +++ b/ppapi/proxy/ppapi_param_traits.cc @@ -323,6 +323,7 @@ void ParamTraits<ppapi::proxy::SerializedHandle>::Write(Message* m, ParamTraits<base::SharedMemoryHandle>::Write(m, p.shmem()); break; case ppapi::proxy::SerializedHandle::SOCKET: + case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: ParamTraits<IPC::PlatformFileForTransit>::Write(m, p.descriptor()); break; case ppapi::proxy::SerializedHandle::INVALID: @@ -355,6 +356,14 @@ bool ParamTraits<ppapi::proxy::SerializedHandle>::Read(const Message* m, } break; } + case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: { + IPC::PlatformFileForTransit desc; + if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) { + r->set_channel_handle(desc); + return true; + } + break; + } case ppapi::proxy::SerializedHandle::INVALID: return true; // No default so the compiler will warn us if a new type is added. diff --git a/ppapi/proxy/ppb_audio_proxy.cc b/ppapi/proxy/ppb_audio_proxy.cc index bc83be3..2bd5c89 100644 --- a/ppapi/proxy/ppb_audio_proxy.cc +++ b/ppapi/proxy/ppb_audio_proxy.cc @@ -26,6 +26,7 @@ #include "ppapi/thunk/thunk.h" using ppapi::IntToPlatformFile; +using ppapi::proxy::SerializedHandle; using ppapi::thunk::EnterResourceNoLock; using ppapi::thunk::PPB_Audio_API; using ppapi::thunk::PPB_AudioConfig_API; @@ -253,14 +254,14 @@ void PPB_Audio_Proxy::AudioChannelConnected( // inconvenient to clean up. Our IPC code will automatically handle this for // us, as long as the remote side always closes the handles it receives // (in OnMsgNotifyAudioStreamCreated), even in the failure case. - ppapi::proxy::SerializedHandle fd_wrapper(socket_handle); + SerializedHandle fd_wrapper(SerializedHandle::SOCKET, socket_handle); // Note that we must call TotalSharedMemorySizeInBytes because // Audio allocates extra space in shared memory for book-keeping, so the // actual size of the shared memory buffer is larger than audio_buffer_length. // When sending to NaCl, NaClIPCAdapter expects this size to match the size // of the full shared memory buffer. - ppapi::proxy::SerializedHandle handle_wrapper( + SerializedHandle handle_wrapper( shared_memory, media::TotalSharedMemorySizeInBytes(audio_buffer_length)); dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated( @@ -309,8 +310,8 @@ int32_t PPB_Audio_Proxy::GetAudioConnectedHandles( void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated( const HostResource& audio_id, int32_t result_code, - ppapi::proxy::SerializedHandle socket_handle, - ppapi::proxy::SerializedHandle handle) { + SerializedHandle socket_handle, + SerializedHandle handle) { CHECK(socket_handle.is_socket()); CHECK(handle.is_shmem()); EnterPluginFromHostResource<PPB_Audio_API> enter(audio_id); diff --git a/ppapi/proxy/serialized_structs.cc b/ppapi/proxy/serialized_structs.cc index 5e0989f..c647ed1 100644 --- a/ppapi/proxy/serialized_structs.cc +++ b/ppapi/proxy/serialized_structs.cc @@ -102,8 +102,9 @@ SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle, } SerializedHandle::SerializedHandle( + Type type, const IPC::PlatformFileForTransit& socket_descriptor) - : type_(SOCKET), + : type_(type), shm_handle_(base::SharedMemory::NULLHandle()), size_(0), descriptor_(socket_descriptor) { @@ -112,8 +113,8 @@ SerializedHandle::SerializedHandle( bool SerializedHandle::IsHandleValid() const { if (type_ == SHARED_MEMORY) return base::SharedMemory::IsHandleValid(shm_handle_); - else if (type_ == SOCKET) - return (IPC::InvalidPlatformFileForTransit() == descriptor_); + else if (type_ == SOCKET || type_ == CHANNEL_HANDLE) + return !(IPC::InvalidPlatformFileForTransit() == descriptor_); return false; } @@ -145,8 +146,7 @@ bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) { break; } case SOCKET: - valid_type = true; - break; + case CHANNEL_HANDLE: case INVALID: valid_type = true; break; diff --git a/ppapi/proxy/serialized_structs.h b/ppapi/proxy/serialized_structs.h index 7ad8456..ac9494d 100644 --- a/ppapi/proxy/serialized_structs.h +++ b/ppapi/proxy/serialized_structs.h @@ -107,7 +107,7 @@ struct PPPVideoCapture_Buffer { // them in NaClIPCAdapter for use in NaCl. class PPAPI_PROXY_EXPORT SerializedHandle { public: - enum Type { INVALID, SHARED_MEMORY, SOCKET }; + enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE }; struct Header { Header() : type(INVALID), size(0) {} Header(Type type_arg, uint32_t size_arg) @@ -124,15 +124,14 @@ class PPAPI_PROXY_EXPORT SerializedHandle { // Create a shared memory handle. SerializedHandle(const base::SharedMemoryHandle& handle, uint32_t size); - // Create a socket handle. - // TODO(dmichael): If we have other ways to use FDs later, this would be - // ambiguous. - explicit SerializedHandle( - const IPC::PlatformFileForTransit& socket_descriptor); + // Create a socket or channel 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; } const base::SharedMemoryHandle& shmem() const { DCHECK(is_shmem()); return shm_handle_; @@ -142,7 +141,7 @@ class PPAPI_PROXY_EXPORT SerializedHandle { return size_; } const IPC::PlatformFileForTransit& descriptor() const { - DCHECK(is_socket()); + DCHECK(is_socket() || is_channel_handle()); return descriptor_; } void set_shmem(const base::SharedMemoryHandle& handle, uint32_t size) { @@ -159,12 +158,22 @@ class PPAPI_PROXY_EXPORT SerializedHandle { 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_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()); + } bool IsHandleValid() const; Header header() const { @@ -189,7 +198,7 @@ class PPAPI_PROXY_EXPORT SerializedHandle { base::SharedMemoryHandle shm_handle_; uint32_t size_; - // This is valid if type == SOCKET. + // This is valid if type == SOCKET || type == CHANNEL_HANDLE. IPC::PlatformFileForTransit descriptor_; }; |