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::ResumeRequestsForView(int route_id
) {
88 // We only need to resume blocked requests if we used a valid route_id.
89 // See CreateNewWindow.
90 if (route_id
!= MSG_ROUTING_NONE
) {
91 BrowserThread::PostTask(
92 BrowserThread::IO
, FROM_HERE
,
93 base::Bind(&RenderWidgetHelper::OnResumeRequestsForView
,
98 void RenderWidgetHelper::OnResumeDeferredNavigation(
99 const GlobalRequestID
& request_id
) {
100 resource_dispatcher_host_
->ResumeDeferredNavigation(request_id
);
103 void RenderWidgetHelper::CreateNewWindow(
104 const ViewHostMsg_CreateWindow_Params
& params
,
105 bool no_javascript_access
,
106 base::ProcessHandle render_process
,
108 int* main_frame_route_id
,
110 SessionStorageNamespace
* session_storage_namespace
) {
111 if (params
.opener_suppressed
|| no_javascript_access
) {
112 // If the opener is supppressed or script access is disallowed, we should
113 // open the window in a new BrowsingInstance, and thus a new process. That
114 // means the current renderer process will not be able to route messages to
115 // it. Because of this, we will immediately show and navigate the window
116 // in OnCreateWindowOnUI, using the params provided here.
117 *route_id
= MSG_ROUTING_NONE
;
118 *main_frame_route_id
= MSG_ROUTING_NONE
;
121 *route_id
= GetNextRoutingID();
122 *main_frame_route_id
= GetNextRoutingID();
123 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
124 render_process_id_
, *route_id
);
125 // Block resource requests until the view is created, since the HWND might
126 // be needed if a response ends up creating a plugin.
127 resource_dispatcher_host_
->BlockRequestsForRoute(
128 render_process_id_
, *route_id
);
129 resource_dispatcher_host_
->BlockRequestsForRoute(
130 render_process_id_
, *main_frame_route_id
);
133 BrowserThread::PostTask(
134 BrowserThread::UI
, FROM_HERE
,
135 base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI
,
136 this, params
, *route_id
, *main_frame_route_id
,
137 make_scoped_refptr(session_storage_namespace
)));
140 void RenderWidgetHelper::OnCreateWindowOnUI(
141 const ViewHostMsg_CreateWindow_Params
& params
,
143 int main_frame_route_id
,
144 SessionStorageNamespace
* session_storage_namespace
) {
145 RenderViewHostImpl
* host
=
146 RenderViewHostImpl::FromID(render_process_id_
, params
.opener_id
);
148 host
->CreateNewWindow(route_id
, main_frame_route_id
, params
,
149 session_storage_namespace
);
152 void RenderWidgetHelper::OnResumeRequestsForView(int route_id
) {
153 resource_dispatcher_host_
->ResumeBlockedRequestsForRoute(
154 render_process_id_
, route_id
);
157 void RenderWidgetHelper::CreateNewWidget(int opener_id
,
158 blink::WebPopupType popup_type
,
161 *route_id
= GetNextRoutingID();
162 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
163 render_process_id_
, *route_id
);
164 BrowserThread::PostTask(
165 BrowserThread::UI
, FROM_HERE
,
166 base::Bind(&RenderWidgetHelper::OnCreateWidgetOnUI
, this, opener_id
,
167 *route_id
, *surface_id
, popup_type
));
170 void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id
,
173 *route_id
= GetNextRoutingID();
174 *surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
175 render_process_id_
, *route_id
);
176 BrowserThread::PostTask(
177 BrowserThread::UI
, FROM_HERE
,
178 base::Bind(&RenderWidgetHelper::OnCreateFullscreenWidgetOnUI
, this,
179 opener_id
, *route_id
, *surface_id
));
182 void RenderWidgetHelper::OnCreateWidgetOnUI(int32 opener_id
,
185 blink::WebPopupType popup_type
) {
186 RenderViewHostImpl
* host
= RenderViewHostImpl::FromID(
187 render_process_id_
, opener_id
);
189 host
->CreateNewWidget(route_id
, surface_id
, popup_type
);
192 void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(int32 opener_id
,
195 RenderViewHostImpl
* host
= RenderViewHostImpl::FromID(
196 render_process_id_
, opener_id
);
198 host
->CreateNewFullscreenWidget(route_id
, surface_id
);
201 } // namespace content