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.
5 #include "content/browser/renderer_host/render_widget_helper.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "base/posix/eintr_wrapper.h"
11 #include "base/threading/thread.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
14 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
15 #include "content/browser/gpu/gpu_surface_tracker.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/render_process_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/common/view_messages.h"
24 typedef std::map
<int, RenderWidgetHelper
*> WidgetHelperMap
;
25 base::LazyInstance
<WidgetHelperMap
> g_widget_helpers
=
26 LAZY_INSTANCE_INITIALIZER
;
28 void AddWidgetHelper(int render_process_id
,
29 const scoped_refptr
<RenderWidgetHelper
>& widget_helper
) {
30 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
31 // We don't care if RenderWidgetHelpers overwrite an existing process_id. Just
32 // want this to be up to date.
33 g_widget_helpers
.Get()[render_process_id
] = widget_helper
.get();
38 RenderWidgetHelper::RenderWidgetHelper()
39 : render_process_id_(-1),
40 resource_dispatcher_host_(NULL
) {
43 RenderWidgetHelper::~RenderWidgetHelper() {
44 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
46 // Delete this RWH from the map if it is found.
47 WidgetHelperMap
& widget_map
= g_widget_helpers
.Get();
48 WidgetHelperMap::iterator it
= widget_map
.find(render_process_id_
);
49 if (it
!= widget_map
.end() && it
->second
== this)
53 void RenderWidgetHelper::Init(
54 int render_process_id
,
55 ResourceDispatcherHostImpl
* resource_dispatcher_host
) {
56 render_process_id_
= render_process_id
;
57 resource_dispatcher_host_
= resource_dispatcher_host
;
59 BrowserThread::PostTask(
60 BrowserThread::IO
, FROM_HERE
,
61 base::Bind(&AddWidgetHelper
,
62 render_process_id_
, make_scoped_refptr(this)));
65 int RenderWidgetHelper::GetNextRoutingID() {
66 return next_routing_id_
.GetNext() + 1;
70 RenderWidgetHelper
* RenderWidgetHelper::FromProcessHostID(
71 int render_process_host_id
) {
72 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
73 WidgetHelperMap::const_iterator ci
= g_widget_helpers
.Get().find(
74 render_process_host_id
);
75 return (ci
== g_widget_helpers
.Get().end())? NULL
: ci
->second
;
78 void RenderWidgetHelper::ResumeDeferredNavigation(
79 const GlobalRequestID
& request_id
) {
80 BrowserThread::PostTask(
81 BrowserThread::IO
, FROM_HERE
,
82 base::Bind(&RenderWidgetHelper::OnResumeDeferredNavigation
,
87 void RenderWidgetHelper::ResumeResponseDeferredAtStart(
88 const GlobalRequestID
& request_id
) {
89 BrowserThread::PostTask(
92 base::Bind(&RenderWidgetHelper::OnResumeResponseDeferredAtStart
,
97 void RenderWidgetHelper::ResumeRequestsForView(int route_id
) {
98 // We only need to resume blocked requests if we used a valid route_id.
99 // See CreateNewWindow.
100 if (route_id
!= MSG_ROUTING_NONE
) {
101 BrowserThread::PostTask(
102 BrowserThread::IO
, FROM_HERE
,
103 base::Bind(&RenderWidgetHelper::OnResumeRequestsForView
,
108 void RenderWidgetHelper::OnResumeDeferredNavigation(
109 const GlobalRequestID
& request_id
) {
110 resource_dispatcher_host_
->ResumeDeferredNavigation(request_id
);
113 void RenderWidgetHelper::OnResumeResponseDeferredAtStart(
114 const GlobalRequestID
& request_id
) {
115 resource_dispatcher_host_
->ResumeResponseDeferredAtStart(request_id
);
118 void RenderWidgetHelper::CreateNewWindow(
119 const ViewHostMsg_CreateWindow_Params
& params
,
120 bool no_javascript_access
,
121 base::ProcessHandle render_process
,
123 int* main_frame_route_id
,
125 SessionStorageNamespace
* session_storage_namespace
) {
126 if (params
.opener_suppressed
|| no_javascript_access
) {
127 // If the opener is supppressed or script access is disallowed, we should
128 // open the window in a new BrowsingInstance, and thus a new process. That
129 // means the current renderer process will not be able to route messages to
130 // it. Because of this, we will immediately show and navigate the window
131 // in OnCreateWindowOnUI, using the params provided here.
132 *route_id
= MSG_ROUTING_NONE
;
133 *main_frame_route_id
= MSG_ROUTING_NONE
;
136 *route_id
= GetNextRoutingID();
137 *main_frame_route_id
= GetNextRoutingID();
138 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
139 render_process_id_
, *route_id
);
140 // Block resource requests until the view is created, since the HWND might
141 // be needed if a response ends up creating a plugin.
142 resource_dispatcher_host_
->BlockRequestsForRoute(
143 render_process_id_
, *route_id
);
144 resource_dispatcher_host_
->BlockRequestsForRoute(
145 render_process_id_
, *main_frame_route_id
);
148 BrowserThread::PostTask(
149 BrowserThread::UI
, FROM_HERE
,
150 base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI
,
151 this, params
, *route_id
, *main_frame_route_id
,
152 make_scoped_refptr(session_storage_namespace
)));
155 void RenderWidgetHelper::OnCreateWindowOnUI(
156 const ViewHostMsg_CreateWindow_Params
& params
,
158 int main_frame_route_id
,
159 SessionStorageNamespace
* session_storage_namespace
) {
160 RenderViewHostImpl
* host
=
161 RenderViewHostImpl::FromID(render_process_id_
, params
.opener_id
);
163 host
->CreateNewWindow(route_id
, main_frame_route_id
, params
,
164 session_storage_namespace
);
167 void RenderWidgetHelper::OnResumeRequestsForView(int route_id
) {
168 resource_dispatcher_host_
->ResumeBlockedRequestsForRoute(
169 render_process_id_
, route_id
);
172 void RenderWidgetHelper::CreateNewWidget(int opener_id
,
173 blink::WebPopupType popup_type
,
176 *route_id
= GetNextRoutingID();
177 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
178 render_process_id_
, *route_id
);
179 BrowserThread::PostTask(
180 BrowserThread::UI
, FROM_HERE
,
182 &RenderWidgetHelper::OnCreateWidgetOnUI
, this, opener_id
, *route_id
,
186 void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id
,
189 *route_id
= GetNextRoutingID();
190 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
191 render_process_id_
, *route_id
);
192 BrowserThread::PostTask(
193 BrowserThread::UI
, FROM_HERE
,
195 &RenderWidgetHelper::OnCreateFullscreenWidgetOnUI
, this,
196 opener_id
, *route_id
));
199 void RenderWidgetHelper::OnCreateWidgetOnUI(
200 int opener_id
, int route_id
, blink::WebPopupType popup_type
) {
201 RenderViewHostImpl
* host
= RenderViewHostImpl::FromID(
202 render_process_id_
, opener_id
);
204 host
->CreateNewWidget(route_id
, popup_type
);
207 void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(int opener_id
,
209 RenderViewHostImpl
* host
= RenderViewHostImpl::FromID(
210 render_process_id_
, opener_id
);
212 host
->CreateNewFullscreenWidget(route_id
);
215 } // namespace content