OLD | NEW |
---|---|
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/eintr_wrapper.h" | 9 #include "base/eintr_wrapper.h" |
10 #include "base/id_map.h" | |
11 #include "base/lazy_instance.h" | |
10 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
11 #include "content/browser/gpu/gpu_surface_tracker.h" | 13 #include "content/browser/gpu/gpu_surface_tracker.h" |
12 #include "content/browser/renderer_host/render_process_host_impl.h" | 14 #include "content/browser/renderer_host/render_process_host_impl.h" |
13 #include "content/browser/renderer_host/render_view_host_impl.h" | 15 #include "content/browser/renderer_host/render_view_host_impl.h" |
14 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" | 16 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
15 #include "content/common/view_messages.h" | 17 #include "content/common/view_messages.h" |
16 #include "content/public/browser/browser_thread.h" | |
17 | 18 |
18 using content::BrowserThread; | 19 using content::BrowserThread; |
19 using content::RenderViewHostImpl; | 20 using content::RenderViewHostImpl; |
20 using content::ResourceDispatcherHostImpl; | 21 using content::ResourceDispatcherHostImpl; |
21 | 22 |
22 // A helper used with DidReceiveUpdateMsg that we hold a pointer to in | 23 namespace { |
24 | |
25 base::LazyInstance<IDMap<RenderWidgetHelper> > g_widget_helpers = | |
darin (slow to review)
2012/04/23 16:47:14
it looks like you aren't using IDMap to create ide
jbates
2012/04/23 20:48:18
You're right, I had copied another instance of a L
| |
26 LAZY_INSTANCE_INITIALIZER; | |
27 | |
28 } // namespace | |
29 | |
30 // A helper used with DidReceiveBackingStoreMsg that we hold a pointer to in | |
23 // pending_paints_. | 31 // pending_paints_. |
24 class RenderWidgetHelper::UpdateMsgProxy { | 32 class RenderWidgetHelper::BackingStoreMsgProxy { |
25 public: | 33 public: |
26 UpdateMsgProxy(RenderWidgetHelper* h, const IPC::Message& m); | 34 BackingStoreMsgProxy(RenderWidgetHelper* h, const IPC::Message& m); |
27 ~UpdateMsgProxy(); | 35 ~BackingStoreMsgProxy(); |
28 void Run(); | 36 void Run(); |
29 void Cancel() { cancelled_ = true; } | 37 void Cancel() { cancelled_ = true; } |
30 | 38 |
31 const IPC::Message& message() const { return message_; } | 39 const IPC::Message& message() const { return message_; } |
32 | 40 |
33 private: | 41 private: |
34 scoped_refptr<RenderWidgetHelper> helper_; | 42 scoped_refptr<RenderWidgetHelper> helper_; |
35 IPC::Message message_; | 43 IPC::Message message_; |
36 bool cancelled_; // If true, then the message will not be dispatched. | 44 bool cancelled_; // If true, then the message will not be dispatched. |
37 | 45 |
38 DISALLOW_COPY_AND_ASSIGN(UpdateMsgProxy); | 46 DISALLOW_COPY_AND_ASSIGN(BackingStoreMsgProxy); |
39 }; | 47 }; |
40 | 48 |
41 RenderWidgetHelper::UpdateMsgProxy::UpdateMsgProxy( | 49 RenderWidgetHelper::BackingStoreMsgProxy::BackingStoreMsgProxy( |
42 RenderWidgetHelper* h, const IPC::Message& m) | 50 RenderWidgetHelper* h, const IPC::Message& m) |
43 : helper_(h), | 51 : helper_(h), |
44 message_(m), | 52 message_(m), |
45 cancelled_(false) { | 53 cancelled_(false) { |
46 } | 54 } |
47 | 55 |
48 RenderWidgetHelper::UpdateMsgProxy::~UpdateMsgProxy() { | 56 RenderWidgetHelper::BackingStoreMsgProxy::~BackingStoreMsgProxy() { |
49 // If the paint message was never dispatched, then we need to let the | 57 // If the paint message was never dispatched, then we need to let the |
50 // helper know that we are going away. | 58 // helper know that we are going away. |
51 if (!cancelled_ && helper_) | 59 if (!cancelled_ && helper_) |
52 helper_->OnDiscardUpdateMsg(this); | 60 helper_->OnDiscardBackingStoreMsg(this); |
53 } | 61 } |
54 | 62 |
55 void RenderWidgetHelper::UpdateMsgProxy::Run() { | 63 void RenderWidgetHelper::BackingStoreMsgProxy::Run() { |
56 if (!cancelled_) { | 64 if (!cancelled_) { |
57 helper_->OnDispatchUpdateMsg(this); | 65 helper_->OnDispatchBackingStoreMsg(this); |
58 helper_ = NULL; | 66 helper_ = NULL; |
59 } | 67 } |
60 } | 68 } |
61 | 69 |
62 RenderWidgetHelper::RenderWidgetHelper() | 70 RenderWidgetHelper::RenderWidgetHelper() |
63 : render_process_id_(-1), | 71 : render_process_id_(-1), |
64 #if defined(OS_WIN) | 72 #if defined(OS_WIN) |
65 event_(CreateEvent(NULL, FALSE /* auto-reset */, FALSE, NULL)), | 73 event_(CreateEvent(NULL, FALSE /* auto-reset */, FALSE, NULL)), |
66 #elif defined(OS_POSIX) | 74 #elif defined(OS_POSIX) |
67 event_(false /* auto-reset */, false), | 75 event_(false /* auto-reset */, false), |
68 #endif | 76 #endif |
69 resource_dispatcher_host_(NULL) { | 77 resource_dispatcher_host_(NULL) { |
70 } | 78 } |
71 | 79 |
72 RenderWidgetHelper::~RenderWidgetHelper() { | 80 RenderWidgetHelper::~RenderWidgetHelper() { |
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
82 g_widget_helpers.Get().Remove(render_process_id_); | |
83 | |
73 // The elements of pending_paints_ each hold an owning reference back to this | 84 // The elements of pending_paints_ each hold an owning reference back to this |
74 // object, so we should not be destroyed unless pending_paints_ is empty! | 85 // object, so we should not be destroyed unless pending_paints_ is empty! |
75 DCHECK(pending_paints_.empty()); | 86 DCHECK(pending_paints_.empty()); |
76 | 87 |
77 #if defined(OS_MACOSX) | 88 #if defined(OS_MACOSX) |
78 ClearAllocatedDIBs(); | 89 ClearAllocatedDIBs(); |
79 #endif | 90 #endif |
80 } | 91 } |
81 | 92 |
82 void RenderWidgetHelper::Init( | 93 void RenderWidgetHelper::Init( |
83 int render_process_id, | 94 int render_process_id, |
84 ResourceDispatcherHostImpl* resource_dispatcher_host) { | 95 ResourceDispatcherHostImpl* resource_dispatcher_host) { |
85 render_process_id_ = render_process_id; | 96 render_process_id_ = render_process_id; |
86 resource_dispatcher_host_ = resource_dispatcher_host; | 97 resource_dispatcher_host_ = resource_dispatcher_host; |
98 | |
99 BrowserThread::PostTask( | |
100 BrowserThread::IO, FROM_HERE, | |
101 base::Bind(&IDMap<RenderWidgetHelper>::AddWithID, | |
102 base::Unretained(g_widget_helpers.Pointer()), | |
103 make_scoped_refptr(this), render_process_id_)); | |
87 } | 104 } |
88 | 105 |
89 int RenderWidgetHelper::GetNextRoutingID() { | 106 int RenderWidgetHelper::GetNextRoutingID() { |
90 return next_routing_id_.GetNext() + 1; | 107 return next_routing_id_.GetNext() + 1; |
91 } | 108 } |
92 | 109 |
110 // static | |
111 RenderWidgetHelper* RenderWidgetHelper::FromProcessHostID( | |
112 int render_process_host_id) { | |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
114 return g_widget_helpers.Get().Lookup(render_process_host_id); | |
115 } | |
116 | |
93 void RenderWidgetHelper::CancelResourceRequests(int render_widget_id) { | 117 void RenderWidgetHelper::CancelResourceRequests(int render_widget_id) { |
94 if (render_process_id_ == -1) | 118 if (render_process_id_ == -1) |
95 return; | 119 return; |
96 | 120 |
97 BrowserThread::PostTask( | 121 BrowserThread::PostTask( |
98 BrowserThread::IO, FROM_HERE, | 122 BrowserThread::IO, FROM_HERE, |
99 base::Bind(&RenderWidgetHelper::OnCancelResourceRequests, | 123 base::Bind(&RenderWidgetHelper::OnCancelResourceRequests, |
100 this, | 124 this, |
101 render_widget_id)); | 125 render_widget_id)); |
102 } | 126 } |
103 | 127 |
104 void RenderWidgetHelper::SimulateSwapOutACK( | 128 void RenderWidgetHelper::SimulateSwapOutACK( |
105 const ViewMsg_SwapOut_Params& params) { | 129 const ViewMsg_SwapOut_Params& params) { |
106 BrowserThread::PostTask( | 130 BrowserThread::PostTask( |
107 BrowserThread::IO, FROM_HERE, | 131 BrowserThread::IO, FROM_HERE, |
108 base::Bind(&RenderWidgetHelper::OnSimulateSwapOutACK, | 132 base::Bind(&RenderWidgetHelper::OnSimulateSwapOutACK, |
109 this, | 133 this, |
110 params)); | 134 params)); |
111 } | 135 } |
112 | 136 |
113 bool RenderWidgetHelper::WaitForUpdateMsg(int render_widget_id, | 137 bool RenderWidgetHelper::WaitForBackingStoreMsg( |
114 const base::TimeDelta& max_delay, | 138 int render_widget_id, |
115 IPC::Message* msg) { | 139 const base::TimeDelta& max_delay, |
140 IPC::Message* msg) { | |
116 base::TimeTicks time_start = base::TimeTicks::Now(); | 141 base::TimeTicks time_start = base::TimeTicks::Now(); |
117 | 142 |
118 for (;;) { | 143 for (;;) { |
119 UpdateMsgProxy* proxy = NULL; | 144 BackingStoreMsgProxy* proxy = NULL; |
120 { | 145 { |
121 base::AutoLock lock(pending_paints_lock_); | 146 base::AutoLock lock(pending_paints_lock_); |
122 | 147 |
123 UpdateMsgProxyMap::iterator it = pending_paints_.find(render_widget_id); | 148 BackingStoreMsgProxyMap::iterator it = |
149 pending_paints_.find(render_widget_id); | |
124 if (it != pending_paints_.end()) { | 150 if (it != pending_paints_.end()) { |
125 UpdateMsgProxyQueue &queue = it->second; | 151 BackingStoreMsgProxyQueue &queue = it->second; |
126 DCHECK(!queue.empty()); | 152 DCHECK(!queue.empty()); |
127 proxy = queue.front(); | 153 proxy = queue.front(); |
128 | 154 |
129 // Flag the proxy as cancelled so that when it is run as a task it will | 155 // Flag the proxy as cancelled so that when it is run as a task it will |
130 // do nothing. | 156 // do nothing. |
131 proxy->Cancel(); | 157 proxy->Cancel(); |
132 | 158 |
133 queue.pop_front(); | 159 queue.pop_front(); |
134 if (queue.empty()) | 160 if (queue.empty()) |
135 pending_paints_.erase(it); | 161 pending_paints_.erase(it); |
(...skipping 11 matching lines...) Expand all Loading... | |
147 max_delay - (base::TimeTicks::Now() - time_start); | 173 max_delay - (base::TimeTicks::Now() - time_start); |
148 if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0)) | 174 if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0)) |
149 break; | 175 break; |
150 | 176 |
151 event_.TimedWait(max_sleep_time); | 177 event_.TimedWait(max_sleep_time); |
152 } | 178 } |
153 | 179 |
154 return false; | 180 return false; |
155 } | 181 } |
156 | 182 |
157 void RenderWidgetHelper::DidReceiveUpdateMsg(const IPC::Message& msg) { | 183 void RenderWidgetHelper::DidReceiveBackingStoreMsg(const IPC::Message& msg) { |
158 int render_widget_id = msg.routing_id(); | 184 int render_widget_id = msg.routing_id(); |
159 | 185 |
160 UpdateMsgProxy* proxy = new UpdateMsgProxy(this, msg); | 186 BackingStoreMsgProxy* proxy = new BackingStoreMsgProxy(this, msg); |
161 { | 187 { |
162 base::AutoLock lock(pending_paints_lock_); | 188 base::AutoLock lock(pending_paints_lock_); |
163 | 189 |
164 pending_paints_[render_widget_id].push_back(proxy); | 190 pending_paints_[render_widget_id].push_back(proxy); |
165 } | 191 } |
166 | 192 |
167 // Notify anyone waiting on the UI thread that there is a new entry in the | 193 // Notify anyone waiting on the UI thread that there is a new entry in the |
168 // proxy map. If they don't find the entry they are looking for, then they | 194 // proxy map. If they don't find the entry they are looking for, then they |
169 // will just continue waiting. | 195 // will just continue waiting. |
170 event_.Signal(); | 196 event_.Signal(); |
171 | 197 |
172 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 198 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
173 base::Bind(&UpdateMsgProxy::Run, base::Owned(proxy))); | 199 base::Bind(&BackingStoreMsgProxy::Run, base::Owned(proxy))); |
174 } | 200 } |
175 | 201 |
176 void RenderWidgetHelper::OnDiscardUpdateMsg(UpdateMsgProxy* proxy) { | 202 void RenderWidgetHelper::OnDiscardBackingStoreMsg(BackingStoreMsgProxy* proxy) { |
177 const IPC::Message& msg = proxy->message(); | 203 const IPC::Message& msg = proxy->message(); |
178 | 204 |
179 // Remove the proxy from the map now that we are going to handle it normally. | 205 // Remove the proxy from the map now that we are going to handle it normally. |
180 { | 206 { |
181 base::AutoLock lock(pending_paints_lock_); | 207 base::AutoLock lock(pending_paints_lock_); |
182 | 208 |
183 UpdateMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id()); | 209 BackingStoreMsgProxyMap::iterator it = |
210 pending_paints_.find(msg.routing_id()); | |
184 DCHECK(it != pending_paints_.end()); | 211 DCHECK(it != pending_paints_.end()); |
185 UpdateMsgProxyQueue &queue = it->second; | 212 BackingStoreMsgProxyQueue &queue = it->second; |
186 DCHECK(queue.front() == proxy); | 213 DCHECK(queue.front() == proxy); |
187 | 214 |
188 queue.pop_front(); | 215 queue.pop_front(); |
189 if (queue.empty()) | 216 if (queue.empty()) |
190 pending_paints_.erase(it); | 217 pending_paints_.erase(it); |
191 } | 218 } |
192 } | 219 } |
193 | 220 |
194 void RenderWidgetHelper::OnDispatchUpdateMsg(UpdateMsgProxy* proxy) { | 221 void RenderWidgetHelper::OnDispatchBackingStoreMsg( |
195 OnDiscardUpdateMsg(proxy); | 222 BackingStoreMsgProxy* proxy) { |
223 OnDiscardBackingStoreMsg(proxy); | |
196 | 224 |
197 // It is reasonable for the host to no longer exist. | 225 // It is reasonable for the host to no longer exist. |
198 content::RenderProcessHost* host = | 226 content::RenderProcessHost* host = |
199 content::RenderProcessHost::FromID(render_process_id_); | 227 content::RenderProcessHost::FromID(render_process_id_); |
200 if (host) | 228 if (host) |
201 host->OnMessageReceived(proxy->message()); | 229 host->OnMessageReceived(proxy->message()); |
202 } | 230 } |
203 | 231 |
204 void RenderWidgetHelper::OnCancelResourceRequests( | 232 void RenderWidgetHelper::OnCancelResourceRequests( |
205 int render_widget_id) { | 233 int render_widget_id) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 void RenderWidgetHelper::ClearAllocatedDIBs() { | 384 void RenderWidgetHelper::ClearAllocatedDIBs() { |
357 for (std::map<TransportDIB::Id, int>::iterator | 385 for (std::map<TransportDIB::Id, int>::iterator |
358 i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) { | 386 i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) { |
359 if (HANDLE_EINTR(close(i->second)) < 0) | 387 if (HANDLE_EINTR(close(i->second)) < 0) |
360 PLOG(ERROR) << "close: " << i->first; | 388 PLOG(ERROR) << "close: " << i->first; |
361 } | 389 } |
362 | 390 |
363 allocated_dibs_.clear(); | 391 allocated_dibs_.clear(); |
364 } | 392 } |
365 #endif | 393 #endif |
OLD | NEW |