OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/guest_to_host_channel.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 9 #include "base/process_util.h" |
| 10 #include "base/string_number_conversions.h" |
| 11 #include "content/common/child_process.h" |
| 12 #include "content/common/view_messages.h" |
| 13 #include "content/renderer/gpu/webgraphicscontext3d_guest.h" |
| 14 #include "content/renderer/guest_render_view_observer.h" |
| 15 #include "content/renderer/render_thread_impl.h" |
| 16 #include "gpu/command_buffer/common/buffer.h" |
| 17 #include "gpu/command_buffer/common/command_buffer.h" |
| 18 #include "ipc/ipc_logging.h" |
| 19 #include "ppapi/c/pp_instance.h" |
| 20 #include "ppapi/c/pp_bool.h" |
| 21 #include "ppapi/c/pp_graphics_3d.h" |
| 22 #include "ppapi/cpp/graphics_3d.h" |
| 23 #include "ppapi/proxy/ppapi_command_buffer_proxy.h" |
| 24 #include "ppapi/proxy/ppapi_messages.h" |
| 25 #include "ppapi/proxy/serialized_var.h" |
| 26 #include "ppapi/shared_impl/api_id.h" |
| 27 #include "ppapi/shared_impl/host_resource.h" |
| 28 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" |
| 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h" |
| 32 #include "webkit/plugins/ppapi/event_conversion.h" |
| 33 |
| 34 base::MessageLoopProxy* |
| 35 GuestToHostChannel::ProxyChannelDelegateImpl::GetIPCMessageLoop() { |
| 36 DCHECK(ChildProcess::current()) << "Must be in the renderer."; |
| 37 return ChildProcess::current()->io_message_loop_proxy(); |
| 38 } |
| 39 |
| 40 base::WaitableEvent* |
| 41 GuestToHostChannel::ProxyChannelDelegateImpl::GetShutdownEvent() { |
| 42 DCHECK(ChildProcess::current()) << "Must be in the renderer."; |
| 43 return ChildProcess::current()->GetShutDownEvent(); |
| 44 } |
| 45 |
| 46 GuestToHostChannel::GuestToHostChannel(GuestRenderViewObserver* guest, |
| 47 WebKit::WebView* webview): |
| 48 ProxyChannel(base::GetCurrentProcessHandle()), |
| 49 webview_(webview), |
| 50 guest_(guest), |
| 51 instance_(0), |
| 52 width_(0), |
| 53 height_(0) { |
| 54 } |
| 55 |
| 56 bool GuestToHostChannel::OnMessageReceived(const IPC::Message& message) { |
| 57 bool handled = true; |
| 58 bool msg_is_ok = true; |
| 59 IPC_BEGIN_MESSAGE_MAP_EX(GuestToHostChannel, message, msg_is_ok) |
| 60 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface) |
| 61 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences) |
| 62 IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnMsgReserveInstanceId) |
| 63 // Message handlers from ppp_instance_proxy |
| 64 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate, |
| 65 OnPluginMsgDidCreate) |
| 66 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy, |
| 67 OnPluginMsgDidDestroy) |
| 68 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView, |
| 69 OnPluginMsgDidChangeView) |
| 70 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus, |
| 71 OnPluginMsgDidChangeFocus) |
| 72 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad, |
| 73 OnPluginMsgHandleDocumentLoad) |
| 74 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstancePrivate_GetInstanceObject, |
| 75 OnMsgGetInstanceObject) |
| 76 // Message handlers from ppp_messaging_proxy |
| 77 IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, |
| 78 OnMsgHandleMessage) |
| 79 // Message handlers from ppp_input_event_proxy |
| 80 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleInputEvent, |
| 81 OnMsgHandleInputEvent) |
| 82 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent, |
| 83 OnMsgHandleFilteredInputEvent) |
| 84 // Message handlers from ppb_graphics_3d_proxy |
| 85 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK, |
| 86 OnMsgSwapBuffersACK) |
| 87 // Message handlers from ppp_graphics3d_proxy |
| 88 IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost, |
| 89 OnMsgContextLost) |
| 90 // Have the super handle all other messages. |
| 91 IPC_MESSAGE_UNHANDLED(handled = false) |
| 92 IPC_END_MESSAGE_MAP() |
| 93 |
| 94 if (!msg_is_ok) { |
| 95 // The message had a handler, but its deserialization failed. |
| 96 // Kill the renderer to avoid potential spoofing attacks. |
| 97 CHECK(false) << "Unable to deserialize message in ProxyChannel."; |
| 98 } |
| 99 return handled; |
| 100 } |
| 101 |
| 102 bool GuestToHostChannel::Send(IPC::Message* message) { |
| 103 return ProxyChannel::Send(message); |
| 104 } |
| 105 |
| 106 void GuestToHostChannel::OnChannelError() { |
| 107 // Our host has either crashed or is telling us (rudely) to go away, so we'll |
| 108 // go away. |
| 109 // TODO(fsamuel): Verify all of the cleanup happens. |
| 110 // This might not yet be the case. |
| 111 guest_->Send(new ViewHostMsg_Close(guest_->routing_id())); |
| 112 } |
| 113 |
| 114 WebKit::WebGraphicsContext3D* GuestToHostChannel::GetWebGraphicsContext3D() { |
| 115 return context_.get(); |
| 116 } |
| 117 |
| 118 void GuestToHostChannel::IssueSwapBuffers() { |
| 119 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( |
| 120 ppapi::API_ID_PPB_GRAPHICS_3D, resource_); |
| 121 msg->set_unblock(true); |
| 122 Send(msg); |
| 123 } |
| 124 |
| 125 bool GuestToHostChannel::BindGraphics() { |
| 126 PP_Bool result = PP_FALSE; |
| 127 Send(new PpapiHostMsg_PPBInstance_BindGraphics( |
| 128 ppapi::API_ID_PPB_INSTANCE, instance_, resource_, |
| 129 &result)); |
| 130 return result == PP_TRUE; |
| 131 } |
| 132 |
| 133 bool GuestToHostChannel::InitChannel(const IPC::ChannelHandle& channel_handle) { |
| 134 return ProxyChannel::InitWithChannel(&delegate_, channel_handle, false); |
| 135 } |
| 136 |
| 137 void GuestToHostChannel::OnMsgSupportsInterface( |
| 138 const std::string& interface_name, |
| 139 bool* result) { |
| 140 // TODO(fsamuel): Does this make sense? |
| 141 // We pretend that we support every interface? |
| 142 *result = true; |
| 143 } |
| 144 |
| 145 void GuestToHostChannel::OnMsgSetPreferences(const ppapi::Preferences& prefs) { |
| 146 // TODO(fsamuel): Do we care about these preferences? |
| 147 // These look like some font stuff from WebPreferences. |
| 148 // Perhaps this should be plumbed into our associated RenderView? |
| 149 NOTIMPLEMENTED(); |
| 150 } |
| 151 |
| 152 void GuestToHostChannel::OnMsgReserveInstanceId(PP_Instance instance, |
| 153 bool* usable) { |
| 154 // TODO(fsamuel): Only one instance per guest, for now. |
| 155 // Maybe we should DCHECK to verify this is indeed what's happening? |
| 156 *usable = true; |
| 157 } |
| 158 |
| 159 void GuestToHostChannel::RequestInputEvents() { |
| 160 // Request receipt of input events |
| 161 Send(new PpapiHostMsg_PPBInstance_RequestInputEvents( |
| 162 ppapi::API_ID_PPB_INSTANCE, instance_, true, |
| 163 PP_INPUTEVENT_CLASS_MOUSE | |
| 164 PP_INPUTEVENT_CLASS_KEYBOARD | |
| 165 PP_INPUTEVENT_CLASS_WHEEL | |
| 166 PP_INPUTEVENT_CLASS_TOUCH)); |
| 167 } |
| 168 |
| 169 void GuestToHostChannel::CreateGraphicsContext() { |
| 170 std::vector<int32_t> attribs; |
| 171 attribs.push_back(PP_GRAPHICS3DATTRIB_WIDTH); |
| 172 attribs.push_back(webview_->size().width); |
| 173 attribs.push_back(PP_GRAPHICS3DATTRIB_HEIGHT); |
| 174 attribs.push_back(webview_->size().height); |
| 175 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); |
| 176 |
| 177 // Reset the HostResource if it's already set. |
| 178 resource_ = ppapi::HostResource(); |
| 179 bool success = Send(new PpapiHostMsg_PPBGraphics3D_Create( |
| 180 ppapi::API_ID_PPB_GRAPHICS_3D, instance_, attribs, &resource_)); |
| 181 DCHECK(success && !resource_.is_null()); |
| 182 context_.reset(new WebGraphicsContext3DGuest( |
| 183 new ppapi::proxy::PpapiCommandBufferProxy( |
| 184 resource_, this), this, webview_)); |
| 185 |
| 186 success = context_->MaybeInitializeGL(); |
| 187 DCHECK(success); |
| 188 content::RenderThread::Get()->GetMessageLoop()->PostTask( |
| 189 FROM_HERE, |
| 190 base::Bind(&GuestRenderViewObserver::GraphicsContextCreated, |
| 191 base::Unretained(guest_))); |
| 192 } |
| 193 |
| 194 // Message handlers from ppp_instance_proxy |
| 195 void GuestToHostChannel::OnPluginMsgDidCreate(PP_Instance instance, |
| 196 const std::vector<std::string>& argn, |
| 197 const std::vector<std::string>& argv, |
| 198 PP_Bool* result) { |
| 199 // Creation is always successful if we've gotten this far. |
| 200 *result = PP_TRUE; |
| 201 // Request input events from the host renderer after we reply to this message. |
| 202 instance_ = instance; |
| 203 MessageLoop::current()->PostTask(FROM_HERE, |
| 204 base::Bind(&GuestToHostChannel::RequestInputEvents, |
| 205 base::Unretained(this))); |
| 206 // Request a graphics context from the host renderer. |
| 207 MessageLoop::current()->PostTask(FROM_HERE, |
| 208 base::Bind(&GuestToHostChannel::CreateGraphicsContext, |
| 209 base::Unretained(this))); |
| 210 bool success = base::StringToInt(argv[2], &width_); |
| 211 success |= base::StringToInt(argv[3], &height_); |
| 212 DCHECK(success); |
| 213 guest_->Send(new ViewHostMsg_ResizeGuest(guest_->routing_id(), |
| 214 width_, height_)); |
| 215 |
| 216 } |
| 217 |
| 218 void GuestToHostChannel::OnPluginMsgDidDestroy(PP_Instance instance) { |
| 219 NOTIMPLEMENTED(); |
| 220 } |
| 221 |
| 222 void GuestToHostChannel::OnPluginMsgDidChangeView( |
| 223 PP_Instance instance, |
| 224 const ppapi::ViewData& new_data, |
| 225 PP_Bool flash_fullscreen) { |
| 226 if (new_data.rect.size.width != width_ || |
| 227 new_data.rect.size.height != height_) { |
| 228 width_ = new_data.rect.size.width; |
| 229 height_ = new_data.rect.size.height; |
| 230 guest_->Send(new ViewHostMsg_ResizeGuest(guest_->routing_id(), |
| 231 width_, height_)); |
| 232 } |
| 233 } |
| 234 |
| 235 void GuestToHostChannel::OnPluginMsgDidChangeFocus(PP_Instance instance, |
| 236 PP_Bool has_focus) { |
| 237 NOTIMPLEMENTED(); |
| 238 } |
| 239 |
| 240 void GuestToHostChannel::OnPluginMsgHandleDocumentLoad(PP_Instance instance, |
| 241 const ppapi::HostResource& url_loader, |
| 242 PP_Bool* result) { |
| 243 NOTIMPLEMENTED(); |
| 244 } |
| 245 |
| 246 void GuestToHostChannel::OnMsgGetInstanceObject( |
| 247 PP_Instance instance, |
| 248 ppapi::proxy::SerializedVarReturnValue result) { |
| 249 NOTIMPLEMENTED(); |
| 250 // TODO(fsamuel): We crash here during resize of the plugin |
| 251 // Check failed: serialization_rules_. |
| 252 } |
| 253 |
| 254 void GuestToHostChannel::OnMsgHandleMessage( |
| 255 PP_Instance instance, |
| 256 ppapi::proxy::SerializedVarReceiveInput message_data) { |
| 257 NOTIMPLEMENTED(); |
| 258 } |
| 259 |
| 260 void GuestToHostChannel::OnMsgHandleInputEvent( |
| 261 PP_Instance instance, |
| 262 const ppapi::InputEventData& data) { |
| 263 NOTIMPLEMENTED(); |
| 264 } |
| 265 |
| 266 void GuestToHostChannel::OnMsgHandleFilteredInputEvent( |
| 267 PP_Instance instance, |
| 268 const ppapi::InputEventData& data, |
| 269 PP_Bool* result) { |
| 270 scoped_ptr<WebKit::WebInputEvent> web_input_event( |
| 271 webkit::ppapi::CreateWebInputEvent(data)); |
| 272 if (webview_->handleInputEvent(*web_input_event)) |
| 273 *result = PP_TRUE; |
| 274 else |
| 275 *result = PP_FALSE; |
| 276 } |
| 277 |
| 278 |
| 279 void GuestToHostChannel::OnMsgSwapBuffersACK(const ppapi::HostResource& context, |
| 280 int32_t pp_error) { |
| 281 if (context_.get()) |
| 282 context_->OnSwapBuffersComplete(); |
| 283 } |
| 284 |
| 285 void GuestToHostChannel::OnMsgContextLost(PP_Instance instance) { |
| 286 // Create a new graphics context |
| 287 WebGraphicsContext3DGuest* old_context = context_.release(); |
| 288 DCHECK(old_context); |
| 289 CreateGraphicsContext(); |
| 290 } |
OLD | NEW |