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
15namespace content {
16
17CrossProcessFrameConnector::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
24CrossProcessFrameConnector::~CrossProcessFrameConnector() {
25  if (view_)
26    view_->set_cross_process_frame_connector(NULL);
27}
28
29bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
30  bool handled = true;
31
32  IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg)
33    IPC_MESSAGE_HANDLER(FrameHostMsg_CompositorFrameSwappedACK,
34                        OnCompositorFrameSwappedACK)
35    IPC_MESSAGE_HANDLER(FrameHostMsg_ReclaimCompositorResources,
36                        OnReclaimCompositorResources)
37    IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardInputEvent, OnForwardInputEvent)
38    IPC_MESSAGE_HANDLER(FrameHostMsg_InitializeChildFrame,
39                        OnInitializeChildFrame)
40    IPC_MESSAGE_UNHANDLED(handled = false)
41  IPC_END_MESSAGE_MAP()
42
43  return handled;
44}
45
46void CrossProcessFrameConnector::set_view(
47    RenderWidgetHostViewChildFrame* view) {
48  // Detach ourselves from the previous |view_|.
49  if (view_)
50    view_->set_cross_process_frame_connector(NULL);
51
52  view_ = view;
53
54  // Attach ourselves to the new view and size it appropriately.
55  if (view_) {
56    view_->set_cross_process_frame_connector(this);
57    SetDeviceScaleFactor(device_scale_factor_);
58    SetSize(child_frame_rect_);
59  }
60}
61
62void CrossProcessFrameConnector::RenderProcessGone() {
63  frame_proxy_in_parent_renderer_->Send(new FrameMsg_ChildFrameProcessGone(
64      frame_proxy_in_parent_renderer_->GetRoutingID()));
65}
66
67void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped(
68    uint32 output_surface_id,
69    int host_id,
70    int route_id,
71    scoped_ptr<cc::CompositorFrame> frame) {
72  FrameMsg_CompositorFrameSwapped_Params params;
73  frame->AssignTo(&params.frame);
74  params.output_surface_id = output_surface_id;
75  params.producing_route_id = route_id;
76  params.producing_host_id = host_id;
77  frame_proxy_in_parent_renderer_->Send(new FrameMsg_CompositorFrameSwapped(
78      frame_proxy_in_parent_renderer_->GetRoutingID(), params));
79}
80
81void CrossProcessFrameConnector::OnCompositorFrameSwappedACK(
82    const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
83  RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
84                                                   params.output_surface_id,
85                                                   params.producing_host_id,
86                                                   params.ack);
87}
88
89void CrossProcessFrameConnector::OnReclaimCompositorResources(
90    const FrameHostMsg_ReclaimCompositorResources_Params& params) {
91  RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
92                                                       params.output_surface_id,
93                                                       params.renderer_host_id,
94                                                       params.ack);
95}
96
97void CrossProcessFrameConnector::OnInitializeChildFrame(gfx::Rect frame_rect,
98                                                        float scale_factor) {
99  if (scale_factor != device_scale_factor_)
100    SetDeviceScaleFactor(scale_factor);
101
102  if (!frame_rect.size().IsEmpty())
103    SetSize(frame_rect);
104}
105
106gfx::Rect CrossProcessFrameConnector::ChildFrameRect() {
107  return child_frame_rect_;
108}
109
110void CrossProcessFrameConnector::OnForwardInputEvent(
111    const blink::WebInputEvent* event) {
112  if (!view_)
113    return;
114
115  RenderWidgetHostImpl* child_widget =
116      RenderWidgetHostImpl::From(view_->GetRenderWidgetHost());
117  RenderWidgetHostImpl* parent_widget =
118      frame_proxy_in_parent_renderer_->GetRenderViewHost();
119
120  if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
121    if (!parent_widget->GetLastKeyboardEvent())
122      return;
123    NativeWebKeyboardEvent keyboard_event(
124        *parent_widget->GetLastKeyboardEvent());
125    child_widget->ForwardKeyboardEvent(keyboard_event);
126    return;
127  }
128
129  if (blink::WebInputEvent::isMouseEventType(event->type)) {
130    child_widget->ForwardMouseEvent(
131        *static_cast<const blink::WebMouseEvent*>(event));
132    return;
133  }
134
135  if (event->type == blink::WebInputEvent::MouseWheel) {
136    child_widget->ForwardWheelEvent(
137        *static_cast<const blink::WebMouseWheelEvent*>(event));
138    return;
139  }
140}
141
142void CrossProcessFrameConnector::SetDeviceScaleFactor(float scale_factor) {
143  device_scale_factor_ = scale_factor;
144  if (view_) {
145    RenderWidgetHostImpl* child_widget =
146        RenderWidgetHostImpl::From(view_->GetRenderWidgetHost());
147    child_widget->NotifyScreenInfoChanged();
148  }
149}
150
151void CrossProcessFrameConnector::SetSize(gfx::Rect frame_rect) {
152  child_frame_rect_ = frame_rect;
153  if (view_)
154    view_->SetSize(frame_rect.size());
155}
156
157}  // namespace content
158