Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_helper.cc
blob1f88835cd275d8fe60cc96cbc4735ac4ed5025ee
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"
7 #include "base/bind.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/gpu/gpu_process_host_ui_shim.h"
14 #include "content/browser/gpu/gpu_surface_tracker.h"
15 #include "content/browser/loader/resource_dispatcher_host_impl.h"
16 #include "content/browser/renderer_host/render_process_host_impl.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
19 #include "content/common/view_messages.h"
21 namespace content {
22 namespace {
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();
36 } // namespace
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)
50 widget_map.erase(it);
52 #if defined(OS_POSIX) && !defined(OS_ANDROID)
53 ClearAllocatedDIBs();
54 #endif
57 void RenderWidgetHelper::Init(
58 int render_process_id,
59 ResourceDispatcherHostImpl* resource_dispatcher_host) {
60 render_process_id_ = render_process_id;
61 resource_dispatcher_host_ = resource_dispatcher_host;
63 BrowserThread::PostTask(
64 BrowserThread::IO, FROM_HERE,
65 base::Bind(&AddWidgetHelper,
66 render_process_id_, make_scoped_refptr(this)));
69 int RenderWidgetHelper::GetNextRoutingID() {
70 return next_routing_id_.GetNext() + 1;
73 // static
74 RenderWidgetHelper* RenderWidgetHelper::FromProcessHostID(
75 int render_process_host_id) {
76 DCHECK_CURRENTLY_ON(BrowserThread::IO);
77 WidgetHelperMap::const_iterator ci = g_widget_helpers.Get().find(
78 render_process_host_id);
79 return (ci == g_widget_helpers.Get().end())? NULL : ci->second;
82 void RenderWidgetHelper::ResumeDeferredNavigation(
83 const GlobalRequestID& request_id) {
84 BrowserThread::PostTask(
85 BrowserThread::IO, FROM_HERE,
86 base::Bind(&RenderWidgetHelper::OnResumeDeferredNavigation,
87 this,
88 request_id));
91 void RenderWidgetHelper::ResumeResponseDeferredAtStart(
92 const GlobalRequestID& request_id) {
93 BrowserThread::PostTask(
94 BrowserThread::IO,
95 FROM_HERE,
96 base::Bind(&RenderWidgetHelper::OnResumeResponseDeferredAtStart,
97 this,
98 request_id));
101 void RenderWidgetHelper::ResumeRequestsForView(int route_id) {
102 // We only need to resume blocked requests if we used a valid route_id.
103 // See CreateNewWindow.
104 if (route_id != MSG_ROUTING_NONE) {
105 BrowserThread::PostTask(
106 BrowserThread::IO, FROM_HERE,
107 base::Bind(&RenderWidgetHelper::OnResumeRequestsForView,
108 this, route_id));
112 void RenderWidgetHelper::OnResumeDeferredNavigation(
113 const GlobalRequestID& request_id) {
114 resource_dispatcher_host_->ResumeDeferredNavigation(request_id);
117 void RenderWidgetHelper::OnResumeResponseDeferredAtStart(
118 const GlobalRequestID& request_id) {
119 resource_dispatcher_host_->ResumeResponseDeferredAtStart(request_id);
122 void RenderWidgetHelper::CreateNewWindow(
123 const ViewHostMsg_CreateWindow_Params& params,
124 bool no_javascript_access,
125 base::ProcessHandle render_process,
126 int* route_id,
127 int* main_frame_route_id,
128 int* surface_id,
129 SessionStorageNamespace* session_storage_namespace) {
130 if (params.opener_suppressed || no_javascript_access) {
131 // If the opener is supppressed or script access is disallowed, we should
132 // open the window in a new BrowsingInstance, and thus a new process. That
133 // means the current renderer process will not be able to route messages to
134 // it. Because of this, we will immediately show and navigate the window
135 // in OnCreateWindowOnUI, using the params provided here.
136 *route_id = MSG_ROUTING_NONE;
137 *main_frame_route_id = MSG_ROUTING_NONE;
138 *surface_id = 0;
139 } else {
140 *route_id = GetNextRoutingID();
141 *main_frame_route_id = GetNextRoutingID();
142 *surface_id = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
143 render_process_id_, *route_id);
144 // Block resource requests until the view is created, since the HWND might
145 // be needed if a response ends up creating a plugin.
146 resource_dispatcher_host_->BlockRequestsForRoute(
147 render_process_id_, *route_id);
148 resource_dispatcher_host_->BlockRequestsForRoute(
149 render_process_id_, *main_frame_route_id);
152 BrowserThread::PostTask(
153 BrowserThread::UI, FROM_HERE,
154 base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI,
155 this, params, *route_id, *main_frame_route_id,
156 make_scoped_refptr(session_storage_namespace)));
159 void RenderWidgetHelper::OnCreateWindowOnUI(
160 const ViewHostMsg_CreateWindow_Params& params,
161 int route_id,
162 int main_frame_route_id,
163 SessionStorageNamespace* session_storage_namespace) {
164 RenderViewHostImpl* host =
165 RenderViewHostImpl::FromID(render_process_id_, params.opener_id);
166 if (host)
167 host->CreateNewWindow(route_id, main_frame_route_id, params,
168 session_storage_namespace);
171 void RenderWidgetHelper::OnResumeRequestsForView(int route_id) {
172 resource_dispatcher_host_->ResumeBlockedRequestsForRoute(
173 render_process_id_, route_id);
176 void RenderWidgetHelper::CreateNewWidget(int opener_id,
177 blink::WebPopupType popup_type,
178 int* route_id,
179 int* surface_id) {
180 *route_id = GetNextRoutingID();
181 *surface_id = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
182 render_process_id_, *route_id);
183 BrowserThread::PostTask(
184 BrowserThread::UI, FROM_HERE,
185 base::Bind(
186 &RenderWidgetHelper::OnCreateWidgetOnUI, this, opener_id, *route_id,
187 popup_type));
190 void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id,
191 int* route_id,
192 int* surface_id) {
193 *route_id = GetNextRoutingID();
194 *surface_id = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
195 render_process_id_, *route_id);
196 BrowserThread::PostTask(
197 BrowserThread::UI, FROM_HERE,
198 base::Bind(
199 &RenderWidgetHelper::OnCreateFullscreenWidgetOnUI, this,
200 opener_id, *route_id));
203 void RenderWidgetHelper::OnCreateWidgetOnUI(
204 int opener_id, int route_id, blink::WebPopupType popup_type) {
205 RenderViewHostImpl* host = RenderViewHostImpl::FromID(
206 render_process_id_, opener_id);
207 if (host)
208 host->CreateNewWidget(route_id, popup_type);
211 void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(int opener_id,
212 int route_id) {
213 RenderViewHostImpl* host = RenderViewHostImpl::FromID(
214 render_process_id_, opener_id);
215 if (host)
216 host->CreateNewFullscreenWidget(route_id);
219 #if defined(OS_POSIX) && !defined(OS_ANDROID)
220 void RenderWidgetHelper::AllocTransportDIB(uint32 size,
221 bool cache_in_browser,
222 TransportDIB::Handle* result) {
223 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
224 if (!shared_memory->CreateAnonymous(size)) {
225 result->fd = -1;
226 result->auto_close = false;
227 return;
230 shared_memory->GiveToProcess(0 /* pid, not needed */, result);
232 if (cache_in_browser) {
233 // Keep a copy of the file descriptor around
234 base::AutoLock locked(allocated_dibs_lock_);
235 allocated_dibs_[shared_memory->id()] = dup(result->fd);
239 void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) {
240 base::AutoLock locked(allocated_dibs_lock_);
242 const std::map<TransportDIB::Id, int>::iterator
243 i = allocated_dibs_.find(dib_id);
245 if (i != allocated_dibs_.end()) {
246 if (IGNORE_EINTR(close(i->second)) < 0)
247 PLOG(ERROR) << "close";
248 allocated_dibs_.erase(i);
249 } else {
250 DLOG(WARNING) << "Renderer asked us to free unknown transport DIB";
254 void RenderWidgetHelper::ClearAllocatedDIBs() {
255 for (std::map<TransportDIB::Id, int>::iterator
256 i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) {
257 if (IGNORE_EINTR(close(i->second)) < 0)
258 PLOG(ERROR) << "close: " << i->first;
261 allocated_dibs_.clear();
263 #endif
265 } // namespace content