diff options
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 10 | ||||
-rw-r--r-- | content/common/view_messages.h | 3 | ||||
-rw-r--r-- | content/renderer/pepper_plugin_delegate_impl.cc | 143 | ||||
-rw-r--r-- | content/renderer/pepper_plugin_delegate_impl.h | 36 | ||||
-rw-r--r-- | content/renderer/render_view.cc | 10 | ||||
-rw-r--r-- | content/renderer/render_view.h | 3 | ||||
-rw-r--r-- | ppapi/c/trusted/ppp_broker.h | 10 | ||||
-rw-r--r-- | ppapi/proxy/broker_dispatcher.cc | 55 | ||||
-rw-r--r-- | ppapi/proxy/broker_dispatcher.h | 16 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 6 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppb_broker_impl.cc | 8 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppb_broker_impl.h | 2 |
12 files changed, 253 insertions, 49 deletions
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 699e266..8f664d0 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -199,12 +199,12 @@ class OpenChannelToPpapiBrokerCallback : public PpapiBrokerProcessHost::Client { *renderer_id = filter_->render_process_id(); } - virtual void OnChannelOpened(base::ProcessHandle plugin_process_handle, + virtual void OnChannelOpened(base::ProcessHandle broker_process_handle, const IPC::ChannelHandle& channel_handle) { - filter_->Send( - new ViewMsg_PpapiBrokerChannelCreated(routing_id_, - request_id_, - channel_handle)); + filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_, + request_id_, + broker_process_handle, + channel_handle)); delete this; } diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 7d0f024..86e2328 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -1160,8 +1160,9 @@ IPC_MESSAGE_ROUTED0(ViewMsg_AccessibilityNotifications_ACK) // Reply to ViewHostMsg_OpenChannelToPpapiBroker // Tells the renderer that the channel to the broker has been created. -IPC_MESSAGE_ROUTED2(ViewMsg_PpapiBrokerChannelCreated, +IPC_MESSAGE_ROUTED3(ViewMsg_PpapiBrokerChannelCreated, int /* request_id */, + base::ProcessHandle /* broker_process_handle */, IPC::ChannelHandle /* handle */) // Tells the renderer to empty its plugin list cache, optional reloading diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc index 95d24db..f17a21f6 100644 --- a/content/renderer/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper_plugin_delegate_impl.cc @@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/string_split.h" +#include "base/sync_socket.h" #include "base/task.h" #include "base/time.h" #include "chrome/common/pepper_plugin_registry.h" @@ -35,11 +36,13 @@ #include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/webgraphicscontext3d_command_buffer_impl.h" #include "content/renderer/webplugin_delegate_proxy.h" +#include "ipc/ipc_channel_handle.h" #include "ppapi/c/dev/pp_video_dev.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_flash.h" #include "ppapi/c/private/ppb_flash_net_connector.h" #include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" @@ -64,6 +67,39 @@ namespace { const int32 kDefaultCommandBufferSize = 1024 * 1024; +int32_t PlatformFileToInt(base::PlatformFile handle) { +#if defined(OS_WIN) + return static_cast<int32_t>(reinterpret_cast<intptr_t>(handle)); +#elif defined(OS_POSIX) + return handle; +#else + #error Not implemented. +#endif +} + +base::SyncSocket::Handle DuplicateHandle(base::SyncSocket::Handle handle) { + base::SyncSocket::Handle out_handle = base::kInvalidPlatformFileValue; +#if defined(OS_WIN) + DWORD options = DUPLICATE_SAME_ACCESS; + if (!::DuplicateHandle(::GetCurrentProcess(), + handle, + ::GetCurrentProcess(), + &out_handle, + 0, + FALSE, + options)) { + out_handle = base::kInvalidPlatformFileValue; + } +#elif defined(OS_POSIX) + // If asked to close the source, we can simply re-use the source fd instead of + // dup()ing and close()ing. + out_handle = ::dup(handle); +#else + #error Not implemented. +#endif + return out_handle; +} + // Implements the Image2D using a TransportDIB. class PlatformImage2DImpl : public webkit::ppapi::PluginDelegate::PlatformImage2D { @@ -310,6 +346,8 @@ class DispatcherWrapper scoped_ptr<pp::proxy::HostDispatcher> dispatcher_; }; +} // namespace + bool DispatcherWrapper::Init( base::ProcessHandle plugin_process_handle, const IPC::ChannelHandle& channel_handle, @@ -327,7 +365,50 @@ bool DispatcherWrapper::Init( return true; } -} // namespace +BrokerDispatcherWrapper::BrokerDispatcherWrapper() { +} + +BrokerDispatcherWrapper::~BrokerDispatcherWrapper() { +} + +bool BrokerDispatcherWrapper::Init( + base::ProcessHandle plugin_process_handle, + const IPC::ChannelHandle& channel_handle) { + dispatcher_.reset( + new pp::proxy::BrokerHostDispatcher(plugin_process_handle)); + + if (!dispatcher_->InitBrokerWithChannel(PepperPluginRegistry::GetInstance(), + channel_handle, + true)) { + dispatcher_.reset(); + return false; + } + dispatcher_->channel()->SetRestrictDispatchToSameChannel(true); + return true; +} + +// Does not take ownership of the local pipe. +int32_t BrokerDispatcherWrapper::SendHandleToBroker( + PP_Instance instance, + base::SyncSocket::Handle handle) { + IPC::PlatformFileForTransit foreign_socket_handle = + dispatcher_->ShareHandleWithRemote(handle, false); + if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit()) + return PP_ERROR_FAILED; + + if (!dispatcher_->Send( + new PpapiMsg_ConnectToPlugin(instance, foreign_socket_handle))) { + // The plugin did not receive the handle, so it must be closed. + // The easiest way to clean it up is to just put it in an object + // and then close it. This failure case is not performance critical. + // The handle could still leak if Send succeeded but the IPC later failed. + base::SyncSocket temp_socket( + IPC::PlatformFileForTransitToPlatformFile(foreign_socket_handle)); + return PP_ERROR_FAILED; + } + + return PP_OK; +} PpapiBrokerImpl::PpapiBrokerImpl() { } @@ -337,38 +418,69 @@ PpapiBrokerImpl::~PpapiBrokerImpl() { // If the channel is not ready, queue the connection. void PpapiBrokerImpl::Connect(webkit::ppapi::PPB_Broker_Impl* client) { - if (channel_handle_.name.empty()) { + if (!dispatcher_.get()) { pending_connects_.push_back(client); return; } DCHECK(pending_connects_.empty()); - RequestPpapiBrokerPipe(client); + ConnectPluginToBroker(client); } void PpapiBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) { - // TODO(ddorwin): Send message using channel_handle_ and clean up any pending + // TODO(ddorwin): Send message using dispatcher_ and clean up any pending // connects or pipes. } void PpapiBrokerImpl::OnBrokerChannelConnected( + base::ProcessHandle broker_process_handle, const IPC::ChannelHandle& channel_handle) { - channel_handle_ = channel_handle; + scoped_ptr<BrokerDispatcherWrapper> dispatcher(new BrokerDispatcherWrapper); + if (dispatcher->Init(broker_process_handle, channel_handle)) { + dispatcher_.reset(dispatcher.release()); - // Process all pending channel requests from the renderers. - for (size_t i = 0; i < pending_connects_.size(); i++) - RequestPpapiBrokerPipe(pending_connects_[i]); + // Process all pending channel requests from the renderers. + for (size_t i = 0; i < pending_connects_.size(); i++) + ConnectPluginToBroker(pending_connects_[i]); + } else { + // Report failure to all clients. + for (size_t i = 0; i < pending_connects_.size(); i++) { + pending_connects_[i]->BrokerConnected( + PlatformFileToInt(base::kInvalidPlatformFileValue), PP_ERROR_FAILED); + } + } pending_connects_.clear(); } -void PpapiBrokerImpl::RequestPpapiBrokerPipe( +void PpapiBrokerImpl::ConnectPluginToBroker( webkit::ppapi::PPB_Broker_Impl* client) { - // TOOD(ddorwin): Send an asynchronous message to the broker using - // channel_handle_, queue the client with an ID, then return. - // The broker will create the pipe, which will be provided in a message. - // That message handler will call then client->BrokerConnected(). + base::SyncSocket::Handle plugin_handle = base::kInvalidPlatformFileValue; + int32_t result = PP_OK; + + base::SyncSocket* sockets[2] = {0}; + if (base::SyncSocket::CreatePair(sockets)) { + // The socket objects will be deleted when this function exits, closing the + // handles. Any uses of the socket must duplicate them. + scoped_ptr<base::SyncSocket> broker_socket(sockets[0]); + scoped_ptr<base::SyncSocket> plugin_socket(sockets[1]); + + result = dispatcher_->SendHandleToBroker(client->instance()->pp_instance(), + broker_socket->handle()); + + // If the broker has its pipe handle, duplicate the plugin's handle. + // Otherwise, the plugin's handle will be automatically closed. + if (result == PP_OK) + plugin_handle = DuplicateHandle(plugin_socket->handle()); + } else { + result = PP_ERROR_FAILED; + } + + // TOOD(ddorwin): Change the IPC to asynchronous: Queue an object containing + // client and plugin_socket.release(), then return. + // That message handler will then call client->BrokerConnected() with the + // saved pipe handle. // Temporarily, just call back. - client->BrokerConnected(1); + client->BrokerConnected(PlatformFileToInt(plugin_handle), result); } PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderView* render_view) @@ -463,12 +575,13 @@ PepperPluginDelegateImpl::CreatePpapiBroker( void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated( int request_id, + base::ProcessHandle broker_process_handle, const IPC::ChannelHandle& handle) { scoped_refptr<PpapiBrokerImpl> broker = *pending_connect_broker_.Lookup(request_id); pending_connect_broker_.Remove(request_id); - broker->OnBrokerChannelConnected(handle); + broker->OnBrokerChannelConnected(broker_process_handle, handle); } void PepperPluginDelegateImpl::ViewInitiatedPaint() { diff --git a/content/renderer/pepper_plugin_delegate_impl.h b/content/renderer/pepper_plugin_delegate_impl.h index f8cb567..dafafff 100644 --- a/content/renderer/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper_plugin_delegate_impl.h @@ -14,7 +14,8 @@ #include "base/id_map.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "ipc/ipc_channel_handle.h" +#include "ppapi/proxy/broker_dispatcher.h" +#include "ppapi/proxy/proxy_channel.h" #include "webkit/plugins/ppapi/plugin_delegate.h" #include "webkit/plugins/ppapi/ppb_broker_impl.h" #include "webkit/plugins/ppapi/ppb_flash_menu_impl.h" @@ -27,6 +28,10 @@ class Point; class Rect; } +namespace IPC { +struct ChannelHandle; +} + namespace webkit { namespace ppapi { class PepperFilePath; @@ -46,6 +51,21 @@ struct CustomContextMenuContext; class TransportDIB; +class BrokerDispatcherWrapper { + public: + BrokerDispatcherWrapper(); + ~BrokerDispatcherWrapper(); + + bool Init(base::ProcessHandle plugin_process_handle, + const IPC::ChannelHandle& channel_handle); + + int32_t SendHandleToBroker(PP_Instance instance, + base::SyncSocket::Handle handle); + + private: + scoped_ptr<pp::proxy::BrokerDispatcher> dispatcher_; +}; + class PpapiBrokerImpl : public webkit::ppapi::PluginDelegate::PpapiBroker { public: PpapiBrokerImpl(); @@ -55,14 +75,19 @@ class PpapiBrokerImpl : public webkit::ppapi::PluginDelegate::PpapiBroker { virtual void Disconnect(webkit::ppapi::PPB_Broker_Impl* client); // Called when the channel to the broker has been established. - void OnBrokerChannelConnected(const IPC::ChannelHandle& channel_handle); + void OnBrokerChannelConnected(base::ProcessHandle broker_process_handle, + const IPC::ChannelHandle& channel_handle); + + // Connects the plugin to the broker via a pipe. + void ConnectPluginToBroker(webkit::ppapi::PPB_Broker_Impl* client); - // Asynchronously requests a pipe for this instance from the broker. - void RequestPpapiBrokerPipe(webkit::ppapi::PPB_Broker_Impl* client); + // Asynchronously sends a pipe to the broker. + int32_t SendHandleToBroker(PP_Instance instance, + base::SyncSocket::Handle handle); protected: virtual ~PpapiBrokerImpl(); - IPC::ChannelHandle channel_handle_; + scoped_ptr<BrokerDispatcherWrapper> dispatcher_; std::vector<scoped_refptr<webkit::ppapi::PPB_Broker_Impl> > pending_connects_; std::vector<scoped_refptr<webkit::ppapi::PPB_Broker_Impl> > pending_pipes_; @@ -111,6 +136,7 @@ class PepperPluginDelegateImpl // Called by RenderView when ViewMsg_PpapiBrokerChannelCreated. void OnPpapiBrokerChannelCreated(int request_id, + base::ProcessHandle broker_process_handle, const IPC::ChannelHandle& handle); // Notification that the render view has been focused or defocused. This diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 7a339f8..58f5cfc 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -4278,9 +4278,13 @@ void RenderView::OnAsyncFileOpened(base::PlatformFileError error_code, message_id); } -void RenderView::OnPpapiBrokerChannelCreated(int request_id, - const IPC::ChannelHandle& handle) { - pepper_delegate_.OnPpapiBrokerChannelCreated(request_id, handle); +void RenderView::OnPpapiBrokerChannelCreated( + int request_id, + base::ProcessHandle broker_process_handle, + IPC::ChannelHandle handle) { + pepper_delegate_.OnPpapiBrokerChannelCreated(request_id, + broker_process_handle, + handle); } #if defined(OS_MACOSX) diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h index 548117e1..8d846468 100644 --- a/content/renderer/render_view.h +++ b/content/renderer/render_view.h @@ -726,7 +726,8 @@ class RenderView : public RenderWidget, IPC::PlatformFileForTransit file_for_transit, int message_id); void OnPpapiBrokerChannelCreated(int request_id, - const IPC::ChannelHandle& handle); + base::ProcessHandle broker_process_handle, + IPC::ChannelHandle handle); void OnCancelDownload(int32 download_id); void OnClearFocusedNode(); void OnClosePage(const ViewMsg_ClosePage_Params& params); diff --git a/ppapi/c/trusted/ppp_broker.h b/ppapi/c/trusted/ppp_broker.h index 09cd570..923c1828 100644 --- a/ppapi/c/trusted/ppp_broker.h +++ b/ppapi/c/trusted/ppp_broker.h @@ -37,14 +37,16 @@ extern "C" { /** * PP_ConnectInstance_Func defines the signature that you implement to - * receive notifications when a new instance connects to the broker. + * receive notifications when a plugin instance connects to the broker. + * The broker should listen on the socket before returning. * * @param[in] instance The plugin instance connecting to the broker. - * @param[in] socket Handle to a socket the broker can use to communicate with - * the instance. + * @param[in] handle Handle to a socket the broker can use to communicate with + * the plugin. * @return PP_OK on success. Any other value on failure. */ -typedef int32_t (*PP_ConnectInstance_Func)(PP_Instance instance, int socket); +typedef int32_t (*PP_ConnectInstance_Func)(PP_Instance instance, + int32_t handle); /** * @} */ diff --git a/ppapi/proxy/broker_dispatcher.cc b/ppapi/proxy/broker_dispatcher.cc index f72f37a..ff86212 100644 --- a/ppapi/proxy/broker_dispatcher.cc +++ b/ppapi/proxy/broker_dispatcher.cc @@ -4,15 +4,31 @@ #include "ppapi/proxy/broker_dispatcher.h" +#include "base/sync_socket.h" +#include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" namespace pp { namespace proxy { +namespace { + +int32_t PlatformFileToInt(base::PlatformFile handle) { +#if defined(OS_WIN) + return static_cast<int32_t>(reinterpret_cast<intptr_t>(handle)); +#elif defined(OS_POSIX) + return handle; +#else + #error Not implemented. +#endif +} + +} // namespace + BrokerDispatcher::BrokerDispatcher(base::ProcessHandle remote_process_handle, PP_ConnectInstance_Func connect_instance) - : ProxyChannel(remote_process_handle) { - // TODO(ddorwin): Do something with connect_instance. + : ProxyChannel(remote_process_handle), + connect_instance_(connect_instance) { } BrokerDispatcher::~BrokerDispatcher() { @@ -29,17 +45,44 @@ bool BrokerDispatcher::OnMessageReceived(const IPC::Message& msg) { // Control messages. if (msg.routing_id() == MSG_ROUTING_CONTROL) { bool handled = true; - // TODO(ddorwin): Implement. Don't build empty block - fails on Windows. -#if 0 IPC_BEGIN_MESSAGE_MAP(BrokerDispatcher, msg) - // IPC_MESSAGE_FORWARD(PpapiMsg_ConnectToInstance) + IPC_MESSAGE_HANDLER(PpapiMsg_ConnectToPlugin, OnMsgConnectToPlugin) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() -#endif return handled; } return false; } +// Transfers ownership of the handle to the broker module. +void BrokerDispatcher::OnMsgConnectToPlugin( + PP_Instance instance, + IPC::PlatformFileForTransit handle) { + int32_t result = PP_OK; + if (handle == IPC::InvalidPlatformFileForTransit()) { + result = PP_ERROR_FAILED; + } else { + base::SyncSocket::Handle socket_handle = + IPC::PlatformFileForTransitToPlatformFile(handle); + + if (connect_instance_) { + result = connect_instance_(instance, PlatformFileToInt(socket_handle)); + } else { + result = PP_ERROR_FAILED; + // Close the handle since there is no other owner. + // The easiest way to clean it up is to just put it in an object + // and then close them. This failure case is not performance critical. + base::SyncSocket temp_socket(socket_handle); + } + } + + // TODO(ddorwin): Report result via IPC. +} + +BrokerHostDispatcher::BrokerHostDispatcher( + base::ProcessHandle remote_process_handle) + : BrokerDispatcher(remote_process_handle, NULL) { +} + } // namespace proxy } // namespace pp diff --git a/ppapi/proxy/broker_dispatcher.h b/ppapi/proxy/broker_dispatcher.h index 6b0673b..e451218 100644 --- a/ppapi/proxy/broker_dispatcher.h +++ b/ppapi/proxy/broker_dispatcher.h @@ -22,11 +22,6 @@ class BrokerDispatcher : public ProxyChannel { const IPC::ChannelHandle& channel_handle, bool is_client); - // Returns true if the dispatcher is on the broker side, or false if it's the - // browser side. - // TODO(ddorwin): Implement. - // virtual bool IsBroker() const = 0; - // IPC::Channel::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& msg); @@ -35,10 +30,21 @@ class BrokerDispatcher : public ProxyChannel { BrokerDispatcher(base::ProcessHandle remote_process_handle, PP_ConnectInstance_Func connect_instance); + void OnMsgConnectToPlugin(PP_Instance instance, + IPC::PlatformFileForTransit handle); + + PP_ConnectInstance_Func connect_instance_; + private: DISALLOW_COPY_AND_ASSIGN(BrokerDispatcher); }; +// A simple class for broker hosts. +class BrokerHostDispatcher : public BrokerDispatcher { + public: + BrokerHostDispatcher(base::ProcessHandle remote_process_handle); +}; + } // namespace proxy } // namespace pp diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 3749961..2870a4a 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -67,6 +67,12 @@ IPC_MESSAGE_CONTROL2(PpapiMsg_ExecuteCallback, uint32 /* serialized_callback */, int32 /* param */) +// Broker Process. + +IPC_SYNC_MESSAGE_CONTROL2_0(PpapiMsg_ConnectToPlugin, + PP_Instance /* instance */, + IPC::PlatformFileForTransit /* handle */) + // PPB_Audio. // Notifies the result of the audio stream create call. This is called in diff --git a/webkit/plugins/ppapi/ppb_broker_impl.cc b/webkit/plugins/ppapi/ppb_broker_impl.cc index 959830a..16aa316 100644 --- a/webkit/plugins/ppapi/ppb_broker_impl.cc +++ b/webkit/plugins/ppapi/ppb_broker_impl.cc @@ -128,8 +128,10 @@ PPB_Broker_Impl* PPB_Broker_Impl::AsPPB_Broker_Impl() { } // Transfers ownership of the handle to the plugin. -void PPB_Broker_Impl::BrokerConnected(int32_t handle) { - DCHECK(handle); +void PPB_Broker_Impl::BrokerConnected(int32_t handle, int32_t result) { + DCHECK(result == PP_OK || + handle == PlatformFileToInt(base::kInvalidPlatformFileValue)); + pipe_handle_ = handle; // Synchronous calls are not supported. @@ -137,7 +139,7 @@ void PPB_Broker_Impl::BrokerConnected(int32_t handle) { scoped_refptr<TrackedCompletionCallback> callback; callback.swap(connect_callback_); - callback->Run(PP_OK); // Will complete abortively if necessary. + callback->Run(result); // Will complete abortively if necessary. } } // namespace ppapi diff --git a/webkit/plugins/ppapi/ppb_broker_impl.h b/webkit/plugins/ppapi/ppb_broker_impl.h index 2e7b0b6..5bba19a 100644 --- a/webkit/plugins/ppapi/ppb_broker_impl.h +++ b/webkit/plugins/ppapi/ppb_broker_impl.h @@ -33,7 +33,7 @@ class PPB_Broker_Impl : public Resource { // Resource override. virtual PPB_Broker_Impl* AsPPB_Broker_Impl(); - virtual void BrokerConnected(int32_t handle); + void BrokerConnected(int32_t handle, int32_t result); private: // PluginDelegate ppapi broker object. |