Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: content/browser/renderer_host/render_widget_helper.cc

Issue 396483003: Separate ResizeHelper from RenderWidgetHelper (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make dtor order more robust Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/render_widget_helper.h" 5 #include "content/browser/renderer_host/render_widget_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/posix/eintr_wrapper.h" 10 #include "base/posix/eintr_wrapper.h"
11 #include "base/threading/thread.h" 11 #include "base/threading/thread.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
13 #include "content/browser/gpu/gpu_surface_tracker.h" 14 #include "content/browser/gpu/gpu_surface_tracker.h"
14 #include "content/browser/loader/resource_dispatcher_host_impl.h" 15 #include "content/browser/loader/resource_dispatcher_host_impl.h"
15 #include "content/browser/renderer_host/render_process_host_impl.h" 16 #include "content/browser/renderer_host/render_process_host_impl.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h" 17 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 18 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
18 #include "content/common/view_messages.h" 19 #include "content/common/view_messages.h"
19 20
20 namespace content { 21 namespace content {
21 namespace { 22 namespace {
22 23
23 typedef std::map<int, RenderWidgetHelper*> WidgetHelperMap; 24 typedef std::map<int, RenderWidgetHelper*> WidgetHelperMap;
24 base::LazyInstance<WidgetHelperMap> g_widget_helpers = 25 base::LazyInstance<WidgetHelperMap> g_widget_helpers =
25 LAZY_INSTANCE_INITIALIZER; 26 LAZY_INSTANCE_INITIALIZER;
26 27
27 void AddWidgetHelper(int render_process_id, 28 void AddWidgetHelper(int render_process_id,
28 const scoped_refptr<RenderWidgetHelper>& widget_helper) { 29 const scoped_refptr<RenderWidgetHelper>& widget_helper) {
29 DCHECK_CURRENTLY_ON(BrowserThread::IO); 30 DCHECK_CURRENTLY_ON(BrowserThread::IO);
30 // We don't care if RenderWidgetHelpers overwrite an existing process_id. Just 31 // We don't care if RenderWidgetHelpers overwrite an existing process_id. Just
31 // want this to be up to date. 32 // want this to be up to date.
32 g_widget_helpers.Get()[render_process_id] = widget_helper.get(); 33 g_widget_helpers.Get()[render_process_id] = widget_helper.get();
33 } 34 }
34 35
35 } // namespace 36 } // namespace
36 37
37 // A helper used with DidReceiveBackingStoreMsg that we hold a pointer to in
38 // pending_paints_.
39 class RenderWidgetHelper::BackingStoreMsgProxy {
40 public:
41 BackingStoreMsgProxy(RenderWidgetHelper* h, const IPC::Message& m);
42 ~BackingStoreMsgProxy();
43 void Run();
44 void Cancel() { cancelled_ = true; }
45
46 const IPC::Message& message() const { return message_; }
47
48 private:
49 scoped_refptr<RenderWidgetHelper> helper_;
50 IPC::Message message_;
51 bool cancelled_; // If true, then the message will not be dispatched.
52
53 DISALLOW_COPY_AND_ASSIGN(BackingStoreMsgProxy);
54 };
55
56 RenderWidgetHelper::BackingStoreMsgProxy::BackingStoreMsgProxy(
57 RenderWidgetHelper* h, const IPC::Message& m)
58 : helper_(h),
59 message_(m),
60 cancelled_(false) {
61 }
62
63 RenderWidgetHelper::BackingStoreMsgProxy::~BackingStoreMsgProxy() {
64 // If the paint message was never dispatched, then we need to let the
65 // helper know that we are going away.
66 if (!cancelled_ && helper_.get())
67 helper_->OnDiscardBackingStoreMsg(this);
68 }
69
70 void RenderWidgetHelper::BackingStoreMsgProxy::Run() {
71 if (!cancelled_) {
72 helper_->OnDispatchBackingStoreMsg(this);
73 helper_ = NULL;
74 }
75 }
76
77 RenderWidgetHelper::RenderWidgetHelper() 38 RenderWidgetHelper::RenderWidgetHelper()
78 : render_process_id_(-1), 39 : render_process_id_(-1),
79 #if defined(OS_WIN)
80 event_(CreateEvent(NULL, FALSE /* auto-reset */, FALSE, NULL)),
81 #elif defined(OS_POSIX)
82 event_(false /* auto-reset */, false),
83 #endif
84 resource_dispatcher_host_(NULL) { 40 resource_dispatcher_host_(NULL) {
85 } 41 }
86 42
87 RenderWidgetHelper::~RenderWidgetHelper() { 43 RenderWidgetHelper::~RenderWidgetHelper() {
88 DCHECK_CURRENTLY_ON(BrowserThread::IO); 44 DCHECK_CURRENTLY_ON(BrowserThread::IO);
89 45
90 // Delete this RWH from the map if it is found. 46 // Delete this RWH from the map if it is found.
91 WidgetHelperMap& widget_map = g_widget_helpers.Get(); 47 WidgetHelperMap& widget_map = g_widget_helpers.Get();
92 WidgetHelperMap::iterator it = widget_map.find(render_process_id_); 48 WidgetHelperMap::iterator it = widget_map.find(render_process_id_);
93 if (it != widget_map.end() && it->second == this) 49 if (it != widget_map.end() && it->second == this)
94 widget_map.erase(it); 50 widget_map.erase(it);
95 51
96 // The elements of pending_paints_ each hold an owning reference back to this
97 // object, so we should not be destroyed unless pending_paints_ is empty!
98 DCHECK(pending_paints_.empty());
99
100 #if defined(OS_POSIX) && !defined(OS_ANDROID) 52 #if defined(OS_POSIX) && !defined(OS_ANDROID)
101 ClearAllocatedDIBs(); 53 ClearAllocatedDIBs();
102 #endif 54 #endif
103 } 55 }
104 56
105 void RenderWidgetHelper::Init( 57 void RenderWidgetHelper::Init(
106 int render_process_id, 58 int render_process_id,
107 ResourceDispatcherHostImpl* resource_dispatcher_host) { 59 ResourceDispatcherHostImpl* resource_dispatcher_host) {
108 render_process_id_ = render_process_id; 60 render_process_id_ = render_process_id;
109 resource_dispatcher_host_ = resource_dispatcher_host; 61 resource_dispatcher_host_ = resource_dispatcher_host;
(...skipping 29 matching lines...) Expand all
139 void RenderWidgetHelper::ResumeResponseDeferredAtStart( 91 void RenderWidgetHelper::ResumeResponseDeferredAtStart(
140 const GlobalRequestID& request_id) { 92 const GlobalRequestID& request_id) {
141 BrowserThread::PostTask( 93 BrowserThread::PostTask(
142 BrowserThread::IO, 94 BrowserThread::IO,
143 FROM_HERE, 95 FROM_HERE,
144 base::Bind(&RenderWidgetHelper::OnResumeResponseDeferredAtStart, 96 base::Bind(&RenderWidgetHelper::OnResumeResponseDeferredAtStart,
145 this, 97 this,
146 request_id)); 98 request_id));
147 } 99 }
148 100
149 bool RenderWidgetHelper::WaitForBackingStoreMsg(
150 int render_widget_id, const base::TimeDelta& max_delay, IPC::Message* msg) {
151 base::TimeTicks time_start = base::TimeTicks::Now();
152
153 for (;;) {
154 BackingStoreMsgProxy* proxy = NULL;
155 {
156 base::AutoLock lock(pending_paints_lock_);
157
158 BackingStoreMsgProxyMap::iterator it =
159 pending_paints_.find(render_widget_id);
160 if (it != pending_paints_.end()) {
161 BackingStoreMsgProxyQueue &queue = it->second;
162 DCHECK(!queue.empty());
163 proxy = queue.front();
164
165 // Flag the proxy as cancelled so that when it is run as a task it will
166 // do nothing.
167 proxy->Cancel();
168
169 queue.pop_front();
170 if (queue.empty())
171 pending_paints_.erase(it);
172 }
173 }
174
175 if (proxy) {
176 *msg = proxy->message();
177 DCHECK(msg->routing_id() == render_widget_id);
178 return true;
179 }
180
181 // Calculate the maximum amount of time that we are willing to sleep.
182 base::TimeDelta max_sleep_time =
183 max_delay - (base::TimeTicks::Now() - time_start);
184 if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0))
185 break;
186
187 base::ThreadRestrictions::ScopedAllowWait allow_wait;
188 event_.TimedWait(max_sleep_time);
189 }
190
191 return false;
192 }
193
194 void RenderWidgetHelper::ResumeRequestsForView(int route_id) { 101 void RenderWidgetHelper::ResumeRequestsForView(int route_id) {
195 // We only need to resume blocked requests if we used a valid route_id. 102 // We only need to resume blocked requests if we used a valid route_id.
196 // See CreateNewWindow. 103 // See CreateNewWindow.
197 if (route_id != MSG_ROUTING_NONE) { 104 if (route_id != MSG_ROUTING_NONE) {
198 BrowserThread::PostTask( 105 BrowserThread::PostTask(
199 BrowserThread::IO, FROM_HERE, 106 BrowserThread::IO, FROM_HERE,
200 base::Bind(&RenderWidgetHelper::OnResumeRequestsForView, 107 base::Bind(&RenderWidgetHelper::OnResumeRequestsForView,
201 this, route_id)); 108 this, route_id));
202 } 109 }
203 } 110 }
204 111
205 void RenderWidgetHelper::DidReceiveBackingStoreMsg(const IPC::Message& msg) {
206 int render_widget_id = msg.routing_id();
207
208 BackingStoreMsgProxy* proxy = new BackingStoreMsgProxy(this, msg);
209 {
210 base::AutoLock lock(pending_paints_lock_);
211
212 pending_paints_[render_widget_id].push_back(proxy);
213 }
214
215 // Notify anyone waiting on the UI thread that there is a new entry in the
216 // proxy map. If they don't find the entry they are looking for, then they
217 // will just continue waiting.
218 event_.Signal();
219
220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
221 base::Bind(&BackingStoreMsgProxy::Run, base::Owned(proxy)));
222 }
223
224 void RenderWidgetHelper::OnDiscardBackingStoreMsg(BackingStoreMsgProxy* proxy) {
225 const IPC::Message& msg = proxy->message();
226
227 // Remove the proxy from the map now that we are going to handle it normally.
228 {
229 base::AutoLock lock(pending_paints_lock_);
230
231 BackingStoreMsgProxyMap::iterator it =
232 pending_paints_.find(msg.routing_id());
233 DCHECK(it != pending_paints_.end());
234 BackingStoreMsgProxyQueue &queue = it->second;
235 DCHECK(queue.front() == proxy);
236
237 queue.pop_front();
238 if (queue.empty())
239 pending_paints_.erase(it);
240 }
241 }
242
243 void RenderWidgetHelper::OnDispatchBackingStoreMsg(
244 BackingStoreMsgProxy* proxy) {
245 OnDiscardBackingStoreMsg(proxy);
246
247 // It is reasonable for the host to no longer exist.
248 RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
249 if (host)
250 host->OnMessageReceived(proxy->message());
251 }
252
253 void RenderWidgetHelper::OnResumeDeferredNavigation( 112 void RenderWidgetHelper::OnResumeDeferredNavigation(
254 const GlobalRequestID& request_id) { 113 const GlobalRequestID& request_id) {
255 resource_dispatcher_host_->ResumeDeferredNavigation(request_id); 114 resource_dispatcher_host_->ResumeDeferredNavigation(request_id);
256 } 115 }
257 116
258 void RenderWidgetHelper::OnResumeResponseDeferredAtStart( 117 void RenderWidgetHelper::OnResumeResponseDeferredAtStart(
259 const GlobalRequestID& request_id) { 118 const GlobalRequestID& request_id) {
260 resource_dispatcher_host_->ResumeResponseDeferredAtStart(request_id); 119 resource_dispatcher_host_->ResumeResponseDeferredAtStart(request_id);
261 } 120 }
262 121
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) { 256 i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) {
398 if (IGNORE_EINTR(close(i->second)) < 0) 257 if (IGNORE_EINTR(close(i->second)) < 0)
399 PLOG(ERROR) << "close: " << i->first; 258 PLOG(ERROR) << "close: " << i->first;
400 } 259 }
401 260
402 allocated_dibs_.clear(); 261 allocated_dibs_.clear();
403 } 262 }
404 #endif 263 #endif
405 264
406 } // namespace content 265 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_widget_helper.h ('k') | content/browser/renderer_host/render_widget_helper_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698