1 // Copyright 2014 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/browser/frame_host/cross_process_frame_connector.h" 6 7 #include "content/browser/frame_host/render_frame_proxy_host.h" 8 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" 9 #include "content/browser/renderer_host/render_view_host_impl.h" 10 #include "content/browser/renderer_host/render_widget_host_impl.h" 11 #include "content/common/frame_messages.h" 12 #include "content/common/gpu/gpu_messages.h" 13 #include "third_party/WebKit/public/web/WebInputEvent.h" 14 15 namespace content { 16 17 CrossProcessFrameConnector::CrossProcessFrameConnector( 18 RenderFrameProxyHost* frame_proxy_in_parent_renderer) 19 : frame_proxy_in_parent_renderer_(frame_proxy_in_parent_renderer), 20 view_(NULL), 21 device_scale_factor_(1) { 22 } 23 24 CrossProcessFrameConnector::~CrossProcessFrameConnector() { 25 if (view_) 26 view_->set_cross_process_frame_connector(NULL); 27 } 28 29 bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) { 30 bool handled = true; 31 32 IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg) 33 IPC_MESSAGE_HANDLER(FrameHostMsg_BuffersSwappedACK, OnBuffersSwappedACK) 34 IPC_MESSAGE_HANDLER(FrameHostMsg_CompositorFrameSwappedACK, 35 OnCompositorFrameSwappedACK) 36 IPC_MESSAGE_HANDLER(FrameHostMsg_ReclaimCompositorResources, 37 OnReclaimCompositorResources) 38 IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardInputEvent, OnForwardInputEvent) 39 IPC_MESSAGE_HANDLER(FrameHostMsg_InitializeChildFrame, 40 OnInitializeChildFrame) 41 IPC_MESSAGE_UNHANDLED(handled = false) 42 IPC_END_MESSAGE_MAP() 43 44 return handled; 45 } 46 47 void CrossProcessFrameConnector::set_view( 48 RenderWidgetHostViewChildFrame* view) { 49 // Detach ourselves from the previous |view_|. 50 if (view_) 51 view_->set_cross_process_frame_connector(NULL); 52 53 view_ = view; 54 55 // Attach ourselves to the new view and size it appropriately. 56 if (view_) { 57 view_->set_cross_process_frame_connector(this); 58 SetDeviceScaleFactor(device_scale_factor_); 59 SetSize(child_frame_rect_); 60 } 61 } 62 63 void CrossProcessFrameConnector::RenderProcessGone() { 64 frame_proxy_in_parent_renderer_->Send(new FrameMsg_ChildFrameProcessGone( 65 frame_proxy_in_parent_renderer_->GetRoutingID())); 66 } 67 68 void CrossProcessFrameConnector::ChildFrameBuffersSwapped( 69 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& gpu_params, 70 int gpu_host_id) { 71 72 FrameMsg_BuffersSwapped_Params params; 73 params.size = gpu_params.size; 74 params.mailbox = gpu_params.mailbox; 75 params.gpu_route_id = gpu_params.route_id; 76 params.gpu_host_id = gpu_host_id; 77 78 frame_proxy_in_parent_renderer_->Send(new FrameMsg_BuffersSwapped( 79 frame_proxy_in_parent_renderer_->GetRoutingID(), params)); 80 } 81 82 void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped( 83 uint32 output_surface_id, 84 int host_id, 85 int route_id, 86 scoped_ptr<cc::CompositorFrame> frame) { 87 FrameMsg_CompositorFrameSwapped_Params params; 88 frame->AssignTo(¶ms.frame); 89 params.output_surface_id = output_surface_id; 90 params.producing_route_id = route_id; 91 params.producing_host_id = host_id; 92 frame_proxy_in_parent_renderer_->Send(new FrameMsg_CompositorFrameSwapped( 93 frame_proxy_in_parent_renderer_->GetRoutingID(), params)); 94 } 95 96 void CrossProcessFrameConnector::OnBuffersSwappedACK( 97 const FrameHostMsg_BuffersSwappedACK_Params& params) { 98 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 99 ack_params.mailbox = params.mailbox; 100 ack_params.sync_point = params.sync_point; 101 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.gpu_route_id, 102 params.gpu_host_id, 103 ack_params); 104 105 // TODO(kenrb): Special case stuff for Win + Mac. 106 } 107 108 void CrossProcessFrameConnector::OnCompositorFrameSwappedACK( 109 const FrameHostMsg_CompositorFrameSwappedACK_Params& params) { 110 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id, 111 params.output_surface_id, 112 params.producing_host_id, 113 params.ack); 114 } 115 116 void CrossProcessFrameConnector::OnReclaimCompositorResources( 117 const FrameHostMsg_ReclaimCompositorResources_Params& params) { 118 RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id, 119 params.output_surface_id, 120 params.renderer_host_id, 121 params.ack); 122 } 123 124 void CrossProcessFrameConnector::OnInitializeChildFrame(gfx::Rect frame_rect, 125 float scale_factor) { 126 if (scale_factor != device_scale_factor_) 127 SetDeviceScaleFactor(scale_factor); 128 129 if (!frame_rect.size().IsEmpty()) 130 SetSize(frame_rect); 131 } 132 133 gfx::Rect CrossProcessFrameConnector::ChildFrameRect() { 134 return child_frame_rect_; 135 } 136 137 void CrossProcessFrameConnector::OnForwardInputEvent( 138 const blink::WebInputEvent* event) { 139 if (!view_) 140 return; 141 142 RenderWidgetHostImpl* child_widget = 143 RenderWidgetHostImpl::From(view_->GetRenderWidgetHost()); 144 RenderWidgetHostImpl* parent_widget = 145 frame_proxy_in_parent_renderer_->GetRenderViewHost(); 146 147 if (blink::WebInputEvent::isKeyboardEventType(event->type)) { 148 if (!parent_widget->GetLastKeyboardEvent()) 149 return; 150 NativeWebKeyboardEvent keyboard_event( 151 *parent_widget->GetLastKeyboardEvent()); 152 child_widget->ForwardKeyboardEvent(keyboard_event); 153 return; 154 } 155 156 if (blink::WebInputEvent::isMouseEventType(event->type)) { 157 child_widget->ForwardMouseEvent( 158 *static_cast<const blink::WebMouseEvent*>(event)); 159 return; 160 } 161 162 if (event->type == blink::WebInputEvent::MouseWheel) { 163 child_widget->ForwardWheelEvent( 164 *static_cast<const blink::WebMouseWheelEvent*>(event)); 165 return; 166 } 167 } 168 169 void CrossProcessFrameConnector::SetDeviceScaleFactor(float scale_factor) { 170 device_scale_factor_ = scale_factor; 171 if (view_) { 172 RenderWidgetHostImpl* child_widget = 173 RenderWidgetHostImpl::From(view_->GetRenderWidgetHost()); 174 child_widget->NotifyScreenInfoChanged(); 175 } 176 } 177 178 void CrossProcessFrameConnector::SetSize(gfx::Rect frame_rect) { 179 child_frame_rect_ = frame_rect; 180 if (view_) 181 view_->SetSize(frame_rect.size()); 182 } 183 184 } // namespace content 185