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.
5 #include "content/browser/frame_host/cross_process_frame_connector.h"
7 #include "cc/surfaces/surface.h"
8 #include "cc/surfaces/surface_manager.h"
9 #include "content/browser/compositor/surface_utils.h"
10 #include "content/browser/frame_host/frame_tree_node.h"
11 #include "content/browser/frame_host/render_frame_host_manager.h"
12 #include "content/browser/frame_host/render_frame_proxy_host.h"
13 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
14 #include "content/browser/renderer_host/render_view_host_impl.h"
15 #include "content/browser/renderer_host/render_widget_host_impl.h"
16 #include "content/browser/renderer_host/render_widget_host_view_base.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/gpu/gpu_messages.h"
19 #include "third_party/WebKit/public/web/WebInputEvent.h"
23 CrossProcessFrameConnector::CrossProcessFrameConnector(
24 RenderFrameProxyHost
* frame_proxy_in_parent_renderer
)
25 : frame_proxy_in_parent_renderer_(frame_proxy_in_parent_renderer
),
27 device_scale_factor_(1) {
30 CrossProcessFrameConnector::~CrossProcessFrameConnector() {
32 view_
->set_cross_process_frame_connector(NULL
);
35 bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message
& msg
) {
38 IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector
, msg
)
39 IPC_MESSAGE_HANDLER(FrameHostMsg_CompositorFrameSwappedACK
,
40 OnCompositorFrameSwappedACK
)
41 IPC_MESSAGE_HANDLER(FrameHostMsg_ReclaimCompositorResources
,
42 OnReclaimCompositorResources
)
43 IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardInputEvent
, OnForwardInputEvent
)
44 IPC_MESSAGE_HANDLER(FrameHostMsg_InitializeChildFrame
,
45 OnInitializeChildFrame
)
46 IPC_MESSAGE_HANDLER(FrameHostMsg_SatisfySequence
, OnSatisfySequence
)
47 IPC_MESSAGE_HANDLER(FrameHostMsg_RequireSequence
, OnRequireSequence
)
48 IPC_MESSAGE_UNHANDLED(handled
= false)
54 void CrossProcessFrameConnector::set_view(
55 RenderWidgetHostViewChildFrame
* view
) {
56 // Detach ourselves from the previous |view_|.
58 view_
->set_cross_process_frame_connector(NULL
);
62 // Attach ourselves to the new view and size it appropriately.
64 view_
->set_cross_process_frame_connector(this);
65 SetDeviceScaleFactor(device_scale_factor_
);
66 SetSize(child_frame_rect_
);
70 void CrossProcessFrameConnector::RenderProcessGone() {
71 frame_proxy_in_parent_renderer_
->Send(new FrameMsg_ChildFrameProcessGone(
72 frame_proxy_in_parent_renderer_
->GetRoutingID()));
75 void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped(
76 uint32 output_surface_id
,
79 scoped_ptr
<cc::CompositorFrame
> frame
) {
80 FrameMsg_CompositorFrameSwapped_Params params
;
81 frame
->AssignTo(¶ms
.frame
);
82 params
.output_surface_id
= output_surface_id
;
83 params
.producing_route_id
= route_id
;
84 params
.producing_host_id
= host_id
;
85 frame_proxy_in_parent_renderer_
->Send(new FrameMsg_CompositorFrameSwapped(
86 frame_proxy_in_parent_renderer_
->GetRoutingID(), params
));
89 void CrossProcessFrameConnector::SetChildFrameSurface(
90 const cc::SurfaceId
& surface_id
,
91 const gfx::Size
& frame_size
,
93 const cc::SurfaceSequence
& sequence
) {
94 frame_proxy_in_parent_renderer_
->Send(new FrameMsg_SetChildFrameSurface(
95 frame_proxy_in_parent_renderer_
->GetRoutingID(), surface_id
, frame_size
,
96 scale_factor
, sequence
));
99 void CrossProcessFrameConnector::OnSatisfySequence(
100 const cc::SurfaceSequence
& sequence
) {
101 std::vector
<uint32_t> sequences
;
102 sequences
.push_back(sequence
.sequence
);
103 cc::SurfaceManager
* manager
= GetSurfaceManager();
104 manager
->DidSatisfySequences(sequence
.id_namespace
, &sequences
);
107 void CrossProcessFrameConnector::OnRequireSequence(
108 const cc::SurfaceId
& id
,
109 const cc::SurfaceSequence
& sequence
) {
110 cc::SurfaceManager
* manager
= GetSurfaceManager();
111 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
113 LOG(ERROR
) << "Attempting to require callback on nonexistent surface";
116 surface
->AddDestructionDependency(sequence
);
119 void CrossProcessFrameConnector::OnCompositorFrameSwappedACK(
120 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
) {
121 RenderWidgetHostImpl::SendSwapCompositorFrameAck(params
.producing_route_id
,
122 params
.output_surface_id
,
123 params
.producing_host_id
,
127 void CrossProcessFrameConnector::OnReclaimCompositorResources(
128 const FrameHostMsg_ReclaimCompositorResources_Params
& params
) {
129 RenderWidgetHostImpl::SendReclaimCompositorResources(params
.route_id
,
130 params
.output_surface_id
,
131 params
.renderer_host_id
,
135 void CrossProcessFrameConnector::OnInitializeChildFrame(gfx::Rect frame_rect
,
136 float scale_factor
) {
137 if (scale_factor
!= device_scale_factor_
)
138 SetDeviceScaleFactor(scale_factor
);
140 if (!frame_rect
.size().IsEmpty())
144 gfx::Rect
CrossProcessFrameConnector::ChildFrameRect() {
145 return child_frame_rect_
;
148 void CrossProcessFrameConnector::GetScreenInfo(blink::WebScreenInfo
* results
) {
149 // Inner WebContents's root FrameTreeNode does not have a parent(), so
150 // GetRenderWidgetHostView() call below will fail.
151 // TODO(lazyboy): Fix this.
152 if (frame_proxy_in_parent_renderer_
->frame_tree_node()
154 ->ForInnerDelegate()) {
155 DCHECK(frame_proxy_in_parent_renderer_
->frame_tree_node()->IsMainFrame());
159 RenderWidgetHostView
* rwhv
=
160 frame_proxy_in_parent_renderer_
->GetRenderWidgetHostView();
162 static_cast<RenderWidgetHostViewBase
*>(rwhv
)->GetScreenInfo(results
);
165 void CrossProcessFrameConnector::OnForwardInputEvent(
166 const blink::WebInputEvent
* event
) {
170 RenderWidgetHostImpl
* child_widget
=
171 RenderWidgetHostImpl::From(view_
->GetRenderWidgetHost());
172 RenderFrameHostManager
* manager
=
173 frame_proxy_in_parent_renderer_
->frame_tree_node()->render_manager();
174 RenderWidgetHostImpl
* parent_widget
=
175 manager
->ForInnerDelegate()
176 ? manager
->GetOuterRenderWidgetHostForKeyboardInput()
177 : frame_proxy_in_parent_renderer_
->GetRenderViewHost();
179 if (blink::WebInputEvent::isKeyboardEventType(event
->type
)) {
180 if (!parent_widget
->GetLastKeyboardEvent())
182 NativeWebKeyboardEvent
keyboard_event(
183 *parent_widget
->GetLastKeyboardEvent());
184 child_widget
->ForwardKeyboardEvent(keyboard_event
);
188 if (blink::WebInputEvent::isMouseEventType(event
->type
)) {
189 child_widget
->ForwardMouseEvent(
190 *static_cast<const blink::WebMouseEvent
*>(event
));
194 if (event
->type
== blink::WebInputEvent::MouseWheel
) {
195 child_widget
->ForwardWheelEvent(
196 *static_cast<const blink::WebMouseWheelEvent
*>(event
));
201 void CrossProcessFrameConnector::SetDeviceScaleFactor(float scale_factor
) {
202 device_scale_factor_
= scale_factor
;
203 // The RenderWidgetHost is null in unit tests.
204 if (view_
&& view_
->GetRenderWidgetHost()) {
205 RenderWidgetHostImpl
* child_widget
=
206 RenderWidgetHostImpl::From(view_
->GetRenderWidgetHost());
207 child_widget
->NotifyScreenInfoChanged();
211 void CrossProcessFrameConnector::SetSize(gfx::Rect frame_rect
) {
212 child_frame_rect_
= frame_rect
;
214 view_
->SetSize(frame_rect
.size());
217 } // namespace content