Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / renderer / render_frame_proxy.cc
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/renderer/render_frame_proxy.h"
6
7 #include <map>
8
9 #include "base/lazy_instance.h"
10 #include "content/common/frame_messages.h"
11 #include "content/common/swapped_out_messages.h"
12 #include "content/renderer/child_frame_compositing_helper.h"
13 #include "content/renderer/render_frame_impl.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "content/renderer/render_view_impl.h"
16 #include "third_party/WebKit/public/web/WebView.h"
17
18 namespace content {
19
20 namespace {
21
22 // Facilitates lookup of RenderFrameProxy by routing_id.
23 typedef std::map<int, RenderFrameProxy*> RoutingIDProxyMap;
24 static base::LazyInstance<RoutingIDProxyMap> g_routing_id_proxy_map =
25     LAZY_INSTANCE_INITIALIZER;
26
27 // Facilitates lookup of RenderFrameProxy by WebFrame.
28 typedef std::map<blink::WebFrame*, RenderFrameProxy*> FrameMap;
29 base::LazyInstance<FrameMap> g_frame_map = LAZY_INSTANCE_INITIALIZER;
30
31 }  // namespace
32
33 // static
34 RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame(
35     RenderFrameImpl* frame_to_replace,
36     int routing_id) {
37   CHECK_NE(routing_id, MSG_ROUTING_NONE);
38
39   scoped_ptr<RenderFrameProxy> proxy(
40       new RenderFrameProxy(routing_id, frame_to_replace->GetRoutingID()));
41
42   blink::WebRemoteFrame* web_frame = NULL;
43   if (frame_to_replace->GetWebFrame()->parent() &&
44       frame_to_replace->GetWebFrame()->parent()->isWebRemoteFrame()) {
45     blink::WebRemoteFrame* parent_web_frame =
46         frame_to_replace->GetWebFrame()->parent()->toWebRemoteFrame();
47     web_frame = parent_web_frame->createRemoteChild("", proxy.get());
48   } else {
49     web_frame = blink::WebRemoteFrame::create(proxy.get());
50   }
51
52   proxy->Init(web_frame, frame_to_replace->render_view());
53   return proxy.release();
54 }
55
56 RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
57     int routing_id,
58     int parent_routing_id,
59     int render_view_routing_id) {
60   scoped_ptr<RenderFrameProxy> proxy(
61       new RenderFrameProxy(routing_id, MSG_ROUTING_NONE));
62   RenderViewImpl* render_view = NULL;
63   blink::WebRemoteFrame* web_frame = NULL;
64   if (parent_routing_id == MSG_ROUTING_NONE) {
65     // Create a top level frame.
66     render_view = RenderViewImpl::FromRoutingID(render_view_routing_id);
67     web_frame = blink::WebRemoteFrame::create(proxy.get());
68     render_view->webview()->setMainFrame(web_frame);
69   } else {
70     // Create a frame under an existing parent. The parent is always expected
71     // to be a RenderFrameProxy, because navigations initiated by local frames
72     // should not wind up here.
73     RenderFrameProxy* parent =
74         RenderFrameProxy::FromRoutingID(parent_routing_id);
75     web_frame = parent->web_frame()->createRemoteChild("", proxy.get());
76     render_view = parent->render_view();
77   }
78
79   proxy->Init(web_frame, render_view);
80
81   return proxy.release();
82 }
83
84 // static
85 RenderFrameProxy* RenderFrameProxy::FromRoutingID(int32 routing_id) {
86   RoutingIDProxyMap* proxies = g_routing_id_proxy_map.Pointer();
87   RoutingIDProxyMap::iterator it = proxies->find(routing_id);
88   return it == proxies->end() ? NULL : it->second;
89 }
90
91 // static
92 RenderFrameProxy* RenderFrameProxy::FromWebFrame(blink::WebFrame* web_frame) {
93   FrameMap::iterator iter = g_frame_map.Get().find(web_frame);
94   if (iter != g_frame_map.Get().end()) {
95     RenderFrameProxy* proxy = iter->second;
96     DCHECK_EQ(web_frame, proxy->web_frame());
97     return proxy;
98   }
99   return NULL;
100 }
101
102 RenderFrameProxy::RenderFrameProxy(int routing_id, int frame_routing_id)
103     : routing_id_(routing_id),
104       frame_routing_id_(frame_routing_id),
105       web_frame_(NULL),
106       render_view_(NULL) {
107   std::pair<RoutingIDProxyMap::iterator, bool> result =
108       g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this));
109   CHECK(result.second) << "Inserting a duplicate item.";
110   RenderThread::Get()->AddRoute(routing_id_, this);
111 }
112
113 RenderFrameProxy::~RenderFrameProxy() {
114   render_view()->UnregisterRenderFrameProxy(this);
115
116   FrameMap::iterator it = g_frame_map.Get().find(web_frame_);
117   CHECK(it != g_frame_map.Get().end());
118   CHECK_EQ(it->second, this);
119   g_frame_map.Get().erase(it);
120
121   RenderThread::Get()->RemoveRoute(routing_id_);
122   g_routing_id_proxy_map.Get().erase(routing_id_);
123
124   // TODO(nick): Call close unconditionally when web_frame() is always remote.
125   if (web_frame()->isWebRemoteFrame())
126     web_frame()->close();
127 }
128
129 void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
130                             RenderViewImpl* render_view) {
131   CHECK(web_frame);
132   CHECK(render_view);
133
134   web_frame_ = web_frame;
135   render_view_ = render_view;
136
137   // TODO(nick): Should all RenderFrameProxies remain observers of their views?
138   render_view_->RegisterRenderFrameProxy(this);
139
140   std::pair<FrameMap::iterator, bool> result =
141       g_frame_map.Get().insert(std::make_pair(web_frame_, this));
142   CHECK(result.second) << "Inserted a duplicate item.";
143 }
144
145 void RenderFrameProxy::DidCommitCompositorFrame() {
146   if (compositing_helper_)
147     compositing_helper_->DidCommitCompositorFrame();
148 }
149
150 bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
151   bool handled = true;
152   IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg)
153     IPC_MESSAGE_HANDLER(FrameMsg_DeleteProxy, OnDeleteProxy)
154     IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone)
155     IPC_MESSAGE_HANDLER(FrameMsg_BuffersSwapped, OnBuffersSwapped)
156     IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped,
157                                 OnCompositorFrameSwapped(msg))
158     IPC_MESSAGE_UNHANDLED(handled = false)
159   IPC_END_MESSAGE_MAP()
160
161   // If |handled| is true, |this| may have been deleted.
162   if (handled)
163     return true;
164
165   RenderFrameImpl* render_frame =
166       RenderFrameImpl::FromRoutingID(frame_routing_id_);
167   return render_frame && render_frame->OnMessageReceived(msg);
168 }
169
170 bool RenderFrameProxy::Send(IPC::Message* message) {
171   if (!SwappedOutMessages::CanSendWhileSwappedOut(message)) {
172     delete message;
173     return false;
174   }
175   message->set_routing_id(routing_id_);
176   return RenderThread::Get()->Send(message);
177 }
178
179 void RenderFrameProxy::OnDeleteProxy() {
180   RenderFrameImpl* render_frame =
181       RenderFrameImpl::FromRoutingID(frame_routing_id_);
182
183   if (render_frame)
184     render_frame->set_render_frame_proxy(NULL);
185
186   delete this;
187 }
188
189 void RenderFrameProxy::OnChildFrameProcessGone() {
190   if (compositing_helper_)
191     compositing_helper_->ChildFrameGone();
192 }
193
194 void RenderFrameProxy::OnBuffersSwapped(
195     const FrameMsg_BuffersSwapped_Params& params) {
196   if (!compositing_helper_) {
197     compositing_helper_ =
198         ChildFrameCompositingHelper::CreateForRenderFrameProxy(this);
199     compositing_helper_->EnableCompositing(true);
200   }
201   compositing_helper_->OnBuffersSwapped(
202       params.size,
203       params.mailbox,
204       params.gpu_route_id,
205       params.gpu_host_id,
206       web_frame()->view()->deviceScaleFactor());
207 }
208
209 void RenderFrameProxy::OnCompositorFrameSwapped(const IPC::Message& message) {
210   FrameMsg_CompositorFrameSwapped::Param param;
211   if (!FrameMsg_CompositorFrameSwapped::Read(&message, &param))
212     return;
213
214   scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
215   param.a.frame.AssignTo(frame.get());
216
217   if (!compositing_helper_) {
218     compositing_helper_ =
219         ChildFrameCompositingHelper::CreateForRenderFrameProxy(this);
220     compositing_helper_->EnableCompositing(true);
221   }
222   compositing_helper_->OnCompositorFrameSwapped(frame.Pass(),
223                                                 param.a.producing_route_id,
224                                                 param.a.output_surface_id,
225                                                 param.a.producing_host_id,
226                                                 param.a.shared_memory_handle);
227 }
228
229 }  // namespace