Index: content/renderer/guest_to_host_channel.cc |
diff --git a/content/renderer/guest_to_host_channel.cc b/content/renderer/guest_to_host_channel.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5691e206ce08685b5f0beabeb8d45f8d2dac4fca |
--- /dev/null |
+++ b/content/renderer/guest_to_host_channel.cc |
@@ -0,0 +1,290 @@ |
+// Copyright (c) 2012 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 "content/renderer/guest_to_host_channel.h" |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/process_util.h" |
+#include "base/string_number_conversions.h" |
+#include "content/common/child_process.h" |
+#include "content/common/view_messages.h" |
+#include "content/renderer/gpu/webgraphicscontext3d_guest.h" |
+#include "content/renderer/guest_render_view_observer.h" |
+#include "content/renderer/render_thread_impl.h" |
+#include "gpu/command_buffer/common/buffer.h" |
+#include "gpu/command_buffer/common/command_buffer.h" |
+#include "ipc/ipc_logging.h" |
+#include "ppapi/c/pp_instance.h" |
+#include "ppapi/c/pp_bool.h" |
+#include "ppapi/c/pp_graphics_3d.h" |
+#include "ppapi/cpp/graphics_3d.h" |
+#include "ppapi/proxy/ppapi_command_buffer_proxy.h" |
+#include "ppapi/proxy/ppapi_messages.h" |
+#include "ppapi/proxy/serialized_var.h" |
+#include "ppapi/shared_impl/api_id.h" |
+#include "ppapi/shared_impl/host_resource.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h" |
+#include "webkit/plugins/ppapi/event_conversion.h" |
+ |
+base::MessageLoopProxy* |
+ GuestToHostChannel::ProxyChannelDelegateImpl::GetIPCMessageLoop() { |
+ DCHECK(ChildProcess::current()) << "Must be in the renderer."; |
+ return ChildProcess::current()->io_message_loop_proxy(); |
+} |
+ |
+base::WaitableEvent* |
+ GuestToHostChannel::ProxyChannelDelegateImpl::GetShutdownEvent() { |
+ DCHECK(ChildProcess::current()) << "Must be in the renderer."; |
+ return ChildProcess::current()->GetShutDownEvent(); |
+} |
+ |
+GuestToHostChannel::GuestToHostChannel(GuestRenderViewObserver* guest, |
+ WebKit::WebView* webview): |
+ ProxyChannel(base::GetCurrentProcessHandle()), |
+ webview_(webview), |
+ guest_(guest), |
+ instance_(0), |
+ width_(0), |
+ height_(0) { |
+} |
+ |
+bool GuestToHostChannel::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ bool msg_is_ok = true; |
+ IPC_BEGIN_MESSAGE_MAP_EX(GuestToHostChannel, message, msg_is_ok) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnMsgReserveInstanceId) |
+ // Message handlers from ppp_instance_proxy |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate, |
+ OnPluginMsgDidCreate) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy, |
+ OnPluginMsgDidDestroy) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView, |
+ OnPluginMsgDidChangeView) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus, |
+ OnPluginMsgDidChangeFocus) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad, |
+ OnPluginMsgHandleDocumentLoad) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstancePrivate_GetInstanceObject, |
+ OnMsgGetInstanceObject) |
+ // Message handlers from ppp_messaging_proxy |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, |
+ OnMsgHandleMessage) |
+ // Message handlers from ppp_input_event_proxy |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleInputEvent, |
+ OnMsgHandleInputEvent) |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent, |
+ OnMsgHandleFilteredInputEvent) |
+ // Message handlers from ppb_graphics_3d_proxy |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK, |
+ OnMsgSwapBuffersACK) |
+ // Message handlers from ppp_graphics3d_proxy |
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost, |
+ OnMsgContextLost) |
+ // Have the super handle all other messages. |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ |
+ 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."; |
+ } |
+ return handled; |
+} |
+ |
+bool GuestToHostChannel::Send(IPC::Message* message) { |
+ return ProxyChannel::Send(message); |
+} |
+ |
+void GuestToHostChannel::OnChannelError() { |
+ // Our host has either crashed or is telling us (rudely) to go away, so we'll |
+ // go away. |
+ // TODO(fsamuel): Verify all of the cleanup happens. |
+ // This might not yet be the case. |
+ guest_->Send(new ViewHostMsg_Close(guest_->routing_id())); |
+} |
+ |
+WebKit::WebGraphicsContext3D* GuestToHostChannel::GetWebGraphicsContext3D() { |
+ return context_.get(); |
+} |
+ |
+void GuestToHostChannel::IssueSwapBuffers() { |
+ IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( |
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_); |
+ msg->set_unblock(true); |
+ Send(msg); |
+} |
+ |
+bool GuestToHostChannel::BindGraphics() { |
+ PP_Bool result = PP_FALSE; |
+ Send(new PpapiHostMsg_PPBInstance_BindGraphics( |
+ ppapi::API_ID_PPB_INSTANCE, instance_, resource_, |
+ &result)); |
+ return result == PP_TRUE; |
+} |
+ |
+bool GuestToHostChannel::InitChannel(const IPC::ChannelHandle& channel_handle) { |
+ return ProxyChannel::InitWithChannel(&delegate_, channel_handle, false); |
+} |
+ |
+void GuestToHostChannel::OnMsgSupportsInterface( |
+ const std::string& interface_name, |
+ bool* result) { |
+ // TODO(fsamuel): Does this make sense? |
+ // We pretend that we support every interface? |
+ *result = true; |
+} |
+ |
+void GuestToHostChannel::OnMsgSetPreferences(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 GuestToHostChannel::OnMsgReserveInstanceId(PP_Instance instance, |
+ bool* usable) { |
+ // TODO(fsamuel): Only one instance per guest, for now. |
+ // Maybe we should DCHECK to verify this is indeed what's happening? |
+ *usable = true; |
+} |
+ |
+void GuestToHostChannel::RequestInputEvents() { |
+ // 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)); |
+} |
+ |
+void GuestToHostChannel::CreateGraphicsContext() { |
+ std::vector<int32_t> attribs; |
+ attribs.push_back(PP_GRAPHICS3DATTRIB_WIDTH); |
+ attribs.push_back(webview_->size().width); |
+ attribs.push_back(PP_GRAPHICS3DATTRIB_HEIGHT); |
+ attribs.push_back(webview_->size().height); |
+ attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); |
+ |
+ // Reset the HostResource if it's already set. |
+ resource_ = ppapi::HostResource(); |
+ bool success = Send(new PpapiHostMsg_PPBGraphics3D_Create( |
+ ppapi::API_ID_PPB_GRAPHICS_3D, instance_, attribs, &resource_)); |
+ DCHECK(success && !resource_.is_null()); |
+ context_.reset(new WebGraphicsContext3DGuest( |
+ new ppapi::proxy::PpapiCommandBufferProxy( |
+ resource_, this), this, webview_)); |
+ |
+ success = context_->MaybeInitializeGL(); |
+ DCHECK(success); |
+ content::RenderThread::Get()->GetMessageLoop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&GuestRenderViewObserver::GraphicsContextCreated, |
+ base::Unretained(guest_))); |
+} |
+ |
+// Message handlers from ppp_instance_proxy |
+void GuestToHostChannel::OnPluginMsgDidCreate(PP_Instance instance, |
+ const std::vector<std::string>& argn, |
+ const std::vector<std::string>& argv, |
+ PP_Bool* result) { |
+ // Creation is always successful if we've gotten this far. |
+ *result = PP_TRUE; |
+ // Request input events from the host renderer after we reply to this message. |
+ instance_ = instance; |
+ MessageLoop::current()->PostTask(FROM_HERE, |
+ base::Bind(&GuestToHostChannel::RequestInputEvents, |
+ base::Unretained(this))); |
+ // Request a graphics context from the host renderer. |
+ MessageLoop::current()->PostTask(FROM_HERE, |
+ base::Bind(&GuestToHostChannel::CreateGraphicsContext, |
+ base::Unretained(this))); |
+ bool success = base::StringToInt(argv[2], &width_); |
+ success |= base::StringToInt(argv[3], &height_); |
+ DCHECK(success); |
+ guest_->Send(new ViewHostMsg_ResizeGuest(guest_->routing_id(), |
+ width_, height_)); |
+ |
+} |
+ |
+void GuestToHostChannel::OnPluginMsgDidDestroy(PP_Instance instance) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void GuestToHostChannel::OnPluginMsgDidChangeView( |
+ PP_Instance instance, |
+ const ppapi::ViewData& new_data, |
+ PP_Bool flash_fullscreen) { |
+ if (new_data.rect.size.width != width_ || |
+ new_data.rect.size.height != height_) { |
+ width_ = new_data.rect.size.width; |
+ height_ = new_data.rect.size.height; |
+ guest_->Send(new ViewHostMsg_ResizeGuest(guest_->routing_id(), |
+ width_, height_)); |
+ } |
+} |
+ |
+void GuestToHostChannel::OnPluginMsgDidChangeFocus(PP_Instance instance, |
+ PP_Bool has_focus) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void GuestToHostChannel::OnPluginMsgHandleDocumentLoad(PP_Instance instance, |
+ const ppapi::HostResource& url_loader, |
+ PP_Bool* result) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void GuestToHostChannel::OnMsgGetInstanceObject( |
+ PP_Instance instance, |
+ ppapi::proxy::SerializedVarReturnValue result) { |
+ NOTIMPLEMENTED(); |
+ // TODO(fsamuel): We crash here during resize of the plugin |
+ // Check failed: serialization_rules_. |
+} |
+ |
+void GuestToHostChannel::OnMsgHandleMessage( |
+ PP_Instance instance, |
+ ppapi::proxy::SerializedVarReceiveInput message_data) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void GuestToHostChannel::OnMsgHandleInputEvent( |
+ PP_Instance instance, |
+ const ppapi::InputEventData& data) { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void GuestToHostChannel::OnMsgHandleFilteredInputEvent( |
+ PP_Instance instance, |
+ const ppapi::InputEventData& data, |
+ PP_Bool* result) { |
+ scoped_ptr<WebKit::WebInputEvent> web_input_event( |
+ webkit::ppapi::CreateWebInputEvent(data)); |
+ if (webview_->handleInputEvent(*web_input_event)) |
+ *result = PP_TRUE; |
+ else |
+ *result = PP_FALSE; |
+} |
+ |
+ |
+void GuestToHostChannel::OnMsgSwapBuffersACK(const ppapi::HostResource& context, |
+ int32_t pp_error) { |
+ if (context_.get()) |
+ context_->OnSwapBuffersComplete(); |
+} |
+ |
+void GuestToHostChannel::OnMsgContextLost(PP_Instance instance) { |
+ // Create a new graphics context |
+ WebGraphicsContext3DGuest* old_context = context_.release(); |
+ DCHECK(old_context); |
+ CreateGraphicsContext(); |
+} |