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