Chromium Code Reviews| Index: content/renderer/browser_plugin/guest_to_embedder_channel.cc |
| diff --git a/content/renderer/browser_plugin/guest_to_embedder_channel.cc b/content/renderer/browser_plugin/guest_to_embedder_channel.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..353c679e7813f23b00c66920d452ddfe076b18f2 |
| --- /dev/null |
| +++ b/content/renderer/browser_plugin/guest_to_embedder_channel.cc |
| @@ -0,0 +1,284 @@ |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/renderer/browser_plugin/guest_to_embedder_channel.h" |
| + |
| +#include "base/process_util.h" |
| +#include "content/common/browser_plugin_messages.h" |
| +#include "content/common/child_process.h" |
| +#include "content/renderer/browser_plugin/browser_plugin_var_serialization_rules.h" |
| +#include "content/renderer/render_thread_impl.h" |
| +#include "content/renderer/render_view_impl.h" |
| +#include "ipc/ipc_message_macros.h" |
|
jam
2012/05/16 02:22:40
nit: not needed
Fady Samuel
2012/05/16 04:43:54
Done.
|
| +#include "ppapi/c/pp_bool.h" |
| +#include "ppapi/c/pp_graphics_3d.h" |
| +#include "ppapi/proxy/ppapi_command_buffer_proxy.h" |
| +#include "ppapi/proxy/ppapi_messages.h" |
| +#include "ppapi/shared_impl/api_id.h" |
| +#include "ppapi/shared_impl/ppapi_globals.h" |
| +#include "ppapi/shared_impl/var.h" |
| +#include "webkit/plugins/ppapi/event_conversion.h" |
| + |
| +namespace content { |
| + |
| +GuestToEmbedderChannel::GuestToEmbedderChannel( |
| + const std::string& embedder_channel_name) |
| + : Dispatcher(NULL), |
| + embedder_channel_name_(embedder_channel_name) { |
| + SetSerializationRules(new BrowserPluginVarSerializationRules()); |
| +} |
| + |
| +bool GuestToEmbedderChannel::OnMessageReceived(const IPC::Message& message) { |
| + bool handled = true; |
| + bool msg_is_ok = true; |
| + IPC_BEGIN_MESSAGE_MAP_EX(GuestToEmbedderChannel, message, msg_is_ok) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnSupportsInterface) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnSetPreferences) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnReserveInstanceId) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate, |
| + OnDidCreate) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy, |
| + OnDidDestroy) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView, |
| + OnDidChangeView) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus, |
| + OnDidChangeFocus) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, |
| + OnHandleMessage) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent, |
| + OnHandleFilteredInputEvent) |
| + IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost, |
| + OnContextLost) |
| + // Have the super handle all other messages. |
| + IPC_MESSAGE_UNHANDLED(handled = false) |
| + IPC_END_MESSAGE_MAP_EX() |
| + |
| + if (!msg_is_ok) { |
| + // The message had a handler, but its deserialization failed. |
| + // Kill the renderer to avoid potential spoofing attacks. |
| + CHECK(false) << "Unable to deserialize message in ProxyChannel."; |
|
jam
2012/05/16 02:22:40
you're in an untrusted process getting IPCs from a
Fady Samuel
2012/05/16 04:43:54
This is a copy-and-paste remnant. Removing.
This
|
| + } |
| + return handled; |
| +} |
| + |
| +bool GuestToEmbedderChannel::Send(IPC::Message* message) { |
| + // We always want guest->host messages to arrive in-order. If some sync |
| + // and some async messages are sent in response to a synchronous |
| + // host->guest call, the sync reply will be processed before the async |
| + // reply, and everything will be confused. |
| + // |
| + // Allowing all async messages to unblock the renderer means more reentrancy |
| + // there but gives correct ordering. |
| + message->set_unblock(true); |
| + return ProxyChannel::Send(message); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnChannelError() { |
| + // We cannot destroy the GuestToEmbedderChannel here because a |
| + // PpapiCommandBufferProxy may still refer to this object. |
| + // However, we should not be using this channel again once we get a |
| + // channel error so when remove it from the channel manager. |
| + RenderThreadImpl::current()->browser_plugin_channel_manager()-> |
| + RemoveChannelByName(embedder_channel_name_); |
| +} |
| + |
| +bool GuestToEmbedderChannel::IsPlugin() const { |
| + return true; |
| +} |
| + |
| +WebGraphicsContext3DCommandBufferImpl* |
| + GuestToEmbedderChannel::CreateWebGraphicsContext3D( |
| + RenderViewImpl* render_view, |
| + const WebKit::WebGraphicsContext3D::Attributes& attributes, |
| + bool offscreen) { |
| + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( |
| + new WebGraphicsContext3DCommandBufferImpl( |
| + 0, GURL(), NULL, |
| + render_view->AsWeakPtr())); |
| + |
| + // Special case: RenderView initialization has not yet completed. |
| + if (!render_view->pp_instance()) |
| + return context.release(); |
| + |
| + if (CreateGraphicsContext(context.get(), |
| + attributes, |
| + offscreen, |
| + render_view)) |
| + return context.release(); |
| + |
| + return NULL; |
| +} |
| + |
| +void GuestToEmbedderChannel::IssueSwapBuffers( |
| + const ppapi::HostResource& resource) { |
| + Send(new PpapiHostMsg_PPBGraphics3D_SwapBuffers( |
| + ppapi::API_ID_PPB_GRAPHICS_3D, resource)); |
| +} |
| + |
| +bool GuestToEmbedderChannel::InitChannel( |
| + const IPC::ChannelHandle& channel_handle) { |
| + return ProxyChannel::InitWithChannel(&delegate_, channel_handle, false); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnSupportsInterface( |
| + const std::string& interface_name, |
| + bool* result) { |
| + // TODO: This is a hack to avoid getting GetInstanceObject messages |
| + // and failing a CHECK. A more correct solution is to implement |
| + // VarSerializationRules for GuestToEmbedderChannel. |
| + *result = interface_name.find("PPP_Instance_Private") == std::string::npos; |
| +} |
| + |
| +void GuestToEmbedderChannel::OnSetPreferences(const ppapi::Preferences& prefs) { |
| + // TODO(fsamuel): Do we care about these preferences? |
| + // These look like some font stuff from WebPreferences. |
| + // Perhaps this should be plumbed into our associated RenderView? |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnReserveInstanceId(PP_Instance instance, |
| + bool* usable) { |
| + *usable = |
| + render_view_instances_.find(instance) == render_view_instances_.end(); |
| +} |
| + |
| +void GuestToEmbedderChannel::RequestInputEvents(PP_Instance instance) { |
| + // Request receipt of input events |
| + Send(new PpapiHostMsg_PPBInstance_RequestInputEvents( |
| + ppapi::API_ID_PPB_INSTANCE, instance, true, |
| + PP_INPUTEVENT_CLASS_MOUSE | |
| + PP_INPUTEVENT_CLASS_KEYBOARD | |
| + PP_INPUTEVENT_CLASS_WHEEL | |
| + PP_INPUTEVENT_CLASS_TOUCH)); |
| +} |
| + |
| +bool GuestToEmbedderChannel::CreateGraphicsContext( |
| + WebGraphicsContext3DCommandBufferImpl* context, |
| + const WebKit::WebGraphicsContext3D::Attributes& attributes, |
| + bool offscreen, |
| + RenderViewImpl* render_view) { |
| + std::vector<int32_t> attribs; |
| + attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); |
| + |
| + ppapi::HostResource resource; |
| + DCHECK(render_view->pp_instance()); |
| + // TODO(fsamuel): Support child contexts. |
| + bool success = Send(new PpapiHostMsg_PPBGraphics3D_Create( |
| + ppapi::API_ID_PPB_GRAPHICS_3D, |
| + render_view->pp_instance(), |
| + attribs, |
| + &resource)); |
| + if (!success || resource.is_null()) |
| + return false; |
| + if (!offscreen) { |
| + PP_Bool result = PP_FALSE; |
| + Send(new PpapiHostMsg_PPBInstance_BindGraphics( |
| + ppapi::API_ID_PPB_INSTANCE, |
| + render_view->pp_instance(), |
| + resource, |
| + &result)); |
| + if (result != PP_TRUE) |
| + return false; |
| + } |
| + |
| + CommandBufferProxy* command_buffer = |
| + new ppapi::proxy::PpapiCommandBufferProxy(resource, this); |
| + command_buffer->Initialize(); |
| + context->InitializeWithCommandBuffer( |
| + command_buffer, |
| + attributes, |
| + false /* bind generates resources */); |
| + render_view->set_host_resource(resource); |
| + return true; |
| +} |
| + |
| +void GuestToEmbedderChannel::AddGuest( |
| + PP_Instance instance, |
| + RenderViewImpl* render_view) { |
| + DCHECK(instance); |
| + DCHECK(render_view_instances_.find(instance) == render_view_instances_.end()); |
| + render_view_instances_[instance] = render_view->AsWeakPtr(); |
| +} |
| + |
| + |
| +void GuestToEmbedderChannel::RemoveGuest(PP_Instance instance) { |
| + DCHECK(render_view_instances_.find(instance) != render_view_instances_.end()); |
| + render_view_instances_.erase(instance); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnDidCreate(PP_Instance instance, |
| + const std::vector<std::string>& argn, |
| + const std::vector<std::string>& argv, |
| + PP_Bool* result) { |
| + *result = PP_TRUE; |
| +} |
| + |
| +void GuestToEmbedderChannel::OnDidDestroy(PP_Instance instance) { |
| + RemoveGuest(instance); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnDidChangeView( |
| + PP_Instance instance, |
| + const ppapi::ViewData& new_data, |
| + PP_Bool flash_fullscreen) { |
| + // We can't do anything with this message if we don't have a render view |
| + // yet. If we do have a RenderView then we need to tell the associated |
| + // WebContentsObserver to resize. |
| + if (render_view_instances_.find(instance) != render_view_instances_.end()) { |
| + RenderViewImpl* render_view = render_view_instances_[instance]; |
| + render_view->Send( |
| + new BrowserPluginHostMsg_ResizeGuest( |
| + render_view->GetRoutingID(), |
| + new_data.rect.size.width, |
| + new_data.rect.size.height)); |
| + } |
| +} |
| + |
| +void GuestToEmbedderChannel::OnDidChangeFocus(PP_Instance instance, |
| + PP_Bool has_focus) { |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnHandleMessage( |
| + PP_Instance instance, |
| + ppapi::proxy::SerializedVarReceiveInput message_data) { |
| + InstanceMap::iterator it = render_view_instances_.find(instance); |
| + if (it == render_view_instances_.end()) |
| + return; |
| + |
| + PP_Var received_var(message_data.Get(this)); |
| + DCHECK(received_var.type == PP_VARTYPE_STRING); |
| + ppapi::VarTracker* tracker = ppapi::PpapiGlobals::Get()->GetVarTracker(); |
| + ppapi::StringVar* var = tracker->GetVar(received_var)->AsStringVar(); |
| + DCHECK(var); |
| + |
| + RenderViewImpl* render_view = it->second; |
| + render_view->Send( |
| + new BrowserPluginHostMsg_NavigateFromGuest( |
| + render_view->GetRoutingID(), |
| + instance, |
| + var->value())); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnHandleFilteredInputEvent( |
| + PP_Instance instance, |
| + const ppapi::InputEventData& data, |
| + PP_Bool* result) { |
| + DCHECK(render_view_instances_.find(instance) != render_view_instances_.end()); |
| + |
| + RenderViewImpl* render_view = render_view_instances_[instance]; |
| + scoped_ptr<WebKit::WebInputEvent> web_input_event( |
| + webkit::ppapi::CreateWebInputEvent(data)); |
| + *result = PP_FromBool( |
| + render_view->GetWebView()->handleInputEvent(*web_input_event)); |
| +} |
| + |
| +void GuestToEmbedderChannel::OnContextLost(PP_Instance instance) { |
| + InstanceMap::iterator it = render_view_instances_.begin(); |
| + for (InstanceMap::iterator it = render_view_instances_.begin(); |
| + it != render_view_instances_.end(); ++it) { |
| + it->second->GetWebView()->loseCompositorContext(1); |
| + } |
| +} |
| + |
| +} // namespace content |