OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/renderer_host/render_widget_host.h" | 5 #include "chrome/browser/renderer_host/render_widget_host.h" |
6 | 6 |
7 #include "base/histogram.h" | 7 #include "base/histogram.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/keyboard_codes.h" | 9 #include "base/keyboard_codes.h" |
10 #include "chrome/browser/renderer_host/backing_store.h" | 10 #include "chrome/browser/renderer_host/backing_store.h" |
11 #include "chrome/browser/renderer_host/backing_store_manager.h" | 11 #include "chrome/browser/renderer_host/backing_store_manager.h" |
12 #include "chrome/browser/renderer_host/render_process_host.h" | 12 #include "chrome/browser/renderer_host/render_process_host.h" |
13 #include "chrome/browser/renderer_host/render_widget_helper.h" | 13 #include "chrome/browser/renderer_host/render_widget_helper.h" |
| 14 #include "chrome/browser/renderer_host/render_widget_host_painting_observer.h" |
14 #include "chrome/browser/renderer_host/render_widget_host_view.h" | 15 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
15 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
16 #include "chrome/common/render_messages.h" | 17 #include "chrome/common/render_messages.h" |
17 #include "views/view.h" | 18 #include "views/view.h" |
18 #include "webkit/glue/webcursor.h" | 19 #include "webkit/glue/webcursor.h" |
19 #include "webkit/glue/webtextdirection.h" | 20 #include "webkit/glue/webtextdirection.h" |
20 | 21 |
21 #if defined(OS_WIN) | 22 #if defined(OS_WIN) |
22 #include "base/gfx/gdi_util.h" | 23 #include "base/gfx/gdi_util.h" |
23 #include "chrome/app/chrome_dll_resource.h" | 24 #include "chrome/app/chrome_dll_resource.h" |
(...skipping 18 matching lines...) Expand all Loading... |
42 static const int kHungRendererDelayMs = 20000; | 43 static const int kHungRendererDelayMs = 20000; |
43 | 44 |
44 /////////////////////////////////////////////////////////////////////////////// | 45 /////////////////////////////////////////////////////////////////////////////// |
45 // RenderWidgetHost | 46 // RenderWidgetHost |
46 | 47 |
47 RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, | 48 RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, |
48 int routing_id) | 49 int routing_id) |
49 : renderer_initialized_(false), | 50 : renderer_initialized_(false), |
50 view_(NULL), | 51 view_(NULL), |
51 process_(process), | 52 process_(process), |
| 53 painting_observer_(NULL), |
52 routing_id_(routing_id), | 54 routing_id_(routing_id), |
53 is_loading_(false), | 55 is_loading_(false), |
54 is_hidden_(false), | 56 is_hidden_(false), |
55 repaint_ack_pending_(false), | 57 repaint_ack_pending_(false), |
56 resize_ack_pending_(false), | 58 resize_ack_pending_(false), |
57 mouse_move_pending_(false), | 59 mouse_move_pending_(false), |
58 needs_repainting_on_restore_(false), | 60 needs_repainting_on_restore_(false), |
59 is_unresponsive_(false), | 61 is_unresponsive_(false), |
60 in_get_backing_store_(false), | 62 in_get_backing_store_(false), |
61 view_being_painted_(false), | 63 view_being_painted_(false), |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 // reduce its resource utilization. | 137 // reduce its resource utilization. |
136 Send(new ViewMsg_WasHidden(routing_id_)); | 138 Send(new ViewMsg_WasHidden(routing_id_)); |
137 | 139 |
138 // TODO(darin): what about constrained windows? it doesn't look like they | 140 // TODO(darin): what about constrained windows? it doesn't look like they |
139 // see a message when their parent is hidden. maybe there is something more | 141 // see a message when their parent is hidden. maybe there is something more |
140 // generic we can do at the TabContents API level instead of relying on | 142 // generic we can do at the TabContents API level instead of relying on |
141 // Windows messages. | 143 // Windows messages. |
142 | 144 |
143 // Tell the RenderProcessHost we were hidden. | 145 // Tell the RenderProcessHost we were hidden. |
144 process_->WidgetHidden(); | 146 process_->WidgetHidden(); |
| 147 |
| 148 bool is_visible = false; |
| 149 NotificationService::current()->Notify( |
| 150 NotificationType::RENDER_WIDGET_VISIBILITY_CHANGED, |
| 151 Source<RenderWidgetHost>(this), |
| 152 Details<bool>(&is_visible)); |
145 } | 153 } |
146 | 154 |
147 void RenderWidgetHost::WasRestored() { | 155 void RenderWidgetHost::WasRestored() { |
148 // When we create the widget, it is created as *not* hidden. | 156 // When we create the widget, it is created as *not* hidden. |
149 if (!is_hidden_) | 157 if (!is_hidden_) |
150 return; | 158 return; |
151 is_hidden_ = false; | 159 is_hidden_ = false; |
152 | 160 |
153 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 161 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
154 // If we already have a backing store for this widget, then we don't need to | 162 // If we already have a backing store for this widget, then we don't need to |
155 // repaint on restore _unless_ we know that our backing store is invalid. | 163 // repaint on restore _unless_ we know that our backing store is invalid. |
156 bool needs_repainting; | 164 bool needs_repainting; |
157 if (needs_repainting_on_restore_ || !backing_store) { | 165 if (needs_repainting_on_restore_ || !backing_store) { |
158 needs_repainting = true; | 166 needs_repainting = true; |
159 needs_repainting_on_restore_ = false; | 167 needs_repainting_on_restore_ = false; |
160 } else { | 168 } else { |
161 needs_repainting = false; | 169 needs_repainting = false; |
162 } | 170 } |
163 Send(new ViewMsg_WasRestored(routing_id_, needs_repainting)); | 171 Send(new ViewMsg_WasRestored(routing_id_, needs_repainting)); |
164 | 172 |
165 process_->WidgetRestored(); | 173 process_->WidgetRestored(); |
| 174 |
| 175 bool is_visible = true; |
| 176 NotificationService::current()->Notify( |
| 177 NotificationType::RENDER_WIDGET_VISIBILITY_CHANGED, |
| 178 Source<RenderWidgetHost>(this), |
| 179 Details<bool>(&is_visible)); |
166 } | 180 } |
167 | 181 |
168 void RenderWidgetHost::WasResized() { | 182 void RenderWidgetHost::WasResized() { |
169 if (resize_ack_pending_ || !process_->channel() || !view_ || | 183 if (resize_ack_pending_ || !process_->channel() || !view_ || |
170 !renderer_initialized_) { | 184 !renderer_initialized_) { |
171 return; | 185 return; |
172 } | 186 } |
173 | 187 |
174 gfx::Rect view_bounds = view_->GetViewBounds(); | 188 gfx::Rect view_bounds = view_->GetViewBounds(); |
175 gfx::Size new_size(view_bounds.width(), view_bounds.height()); | 189 gfx::Size new_size(view_bounds.width(), view_bounds.height()); |
(...skipping 30 matching lines...) Expand all Loading... |
206 view_ = NULL; | 220 view_ = NULL; |
207 } | 221 } |
208 | 222 |
209 void RenderWidgetHost::SetIsLoading(bool is_loading) { | 223 void RenderWidgetHost::SetIsLoading(bool is_loading) { |
210 is_loading_ = is_loading; | 224 is_loading_ = is_loading; |
211 if (!view_) | 225 if (!view_) |
212 return; | 226 return; |
213 view_->SetIsLoading(is_loading); | 227 view_->SetIsLoading(is_loading); |
214 } | 228 } |
215 | 229 |
216 BackingStore* RenderWidgetHost::GetBackingStore() { | 230 BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) { |
217 // We should not be asked to paint while we are hidden. If we are hidden, | 231 // We should not be asked to paint while we are hidden. If we are hidden, |
218 // then it means that our consumer failed to call WasRestored. | 232 // then it means that our consumer failed to call WasRestored. If we're not |
219 DCHECK(!is_hidden_) << "GetBackingStore called while hidden!"; | 233 // force creating the backing store, it's OK since we can feel free to give |
| 234 // out our cached one if we have it. |
| 235 DCHECK(!is_hidden_ || !force_create) << |
| 236 "GetBackingStore called while hidden!"; |
220 | 237 |
221 // We should never be called recursively; this can theoretically lead to | 238 // We should never be called recursively; this can theoretically lead to |
222 // infinite recursion and almost certainly leads to lower performance. | 239 // infinite recursion and almost certainly leads to lower performance. |
223 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; | 240 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; |
224 in_get_backing_store_ = true; | 241 in_get_backing_store_ = true; |
225 | 242 |
226 // We might have a cached backing store that we can reuse! | 243 // We might have a cached backing store that we can reuse! |
227 BackingStore* backing_store = | 244 BackingStore* backing_store = |
228 BackingStoreManager::GetBackingStore(this, current_size_); | 245 BackingStoreManager::GetBackingStore(this, current_size_); |
| 246 if (!force_create) { |
| 247 in_get_backing_store_ = false; |
| 248 return backing_store; |
| 249 } |
| 250 |
229 // If we fail to find a backing store in the cache, send out a request | 251 // If we fail to find a backing store in the cache, send out a request |
230 // to the renderer to paint the view if required. | 252 // to the renderer to paint the view if required. |
231 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && | 253 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && |
232 !view_being_painted_) { | 254 !view_being_painted_) { |
233 repaint_start_time_ = TimeTicks::Now(); | 255 repaint_start_time_ = TimeTicks::Now(); |
234 repaint_ack_pending_ = true; | 256 repaint_ack_pending_ = true; |
235 Send(new ViewMsg_Repaint(routing_id_, current_size_)); | 257 Send(new ViewMsg_Repaint(routing_id_, current_size_)); |
236 } | 258 } |
237 | 259 |
238 // When we have asked the RenderWidget to resize, and we are still waiting on | 260 // When we have asked the RenderWidget to resize, and we are still waiting on |
239 // a response, block for a little while to see if we can't get a response | 261 // a response, block for a little while to see if we can't get a response |
240 // before returning the old (incorrectly sized) backing store. | 262 // before returning the old (incorrectly sized) backing store. |
241 if (resize_ack_pending_ || !backing_store) { | 263 if (resize_ack_pending_ || !backing_store) { |
242 IPC::Message msg; | 264 IPC::Message msg; |
243 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); | 265 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); |
244 if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) { | 266 if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) { |
245 ViewHostMsg_PaintRect::Dispatch( | 267 ViewHostMsg_PaintRect::Dispatch( |
246 &msg, this, &RenderWidgetHost::OnMsgPaintRect); | 268 &msg, this, &RenderWidgetHost::OnMsgPaintRect); |
247 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); | 269 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); |
248 } | 270 } |
249 } | 271 } |
250 | 272 |
251 in_get_backing_store_ = false; | 273 in_get_backing_store_ = false; |
252 return backing_store; | 274 return backing_store; |
253 } | 275 } |
254 | 276 |
255 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { | 277 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { |
256 if (!view_) | 278 if (!view_) |
257 return NULL; | 279 return NULL; |
258 | |
259 return view_->AllocBackingStore(size); | 280 return view_->AllocBackingStore(size); |
260 } | 281 } |
261 | 282 |
262 void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) { | 283 void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) { |
263 time_when_considered_hung_ = Time::Now() + delay; | 284 time_when_considered_hung_ = Time::Now() + delay; |
264 | 285 |
265 // If we already have a timer that will expire at or before the given delay, | 286 // If we already have a timer that will expire at or before the given delay, |
266 // then we have nothing more to do now. | 287 // then we have nothing more to do now. |
267 if (hung_renderer_timer_.IsRunning() && | 288 if (hung_renderer_timer_.IsRunning() && |
268 hung_renderer_timer_.GetCurrentDelay() <= delay) | 289 hung_renderer_timer_.GetCurrentDelay() <= delay) |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 | 559 |
539 // If we got a resize ack, then perhaps we have another resize to send? | 560 // If we got a resize ack, then perhaps we have another resize to send? |
540 if (is_resize_ack && view_) { | 561 if (is_resize_ack && view_) { |
541 gfx::Rect view_bounds = view_->GetViewBounds(); | 562 gfx::Rect view_bounds = view_->GetViewBounds(); |
542 if (current_size_.width() != view_bounds.width() || | 563 if (current_size_.width() != view_bounds.width() || |
543 current_size_.height() != view_bounds.height()) { | 564 current_size_.height() != view_bounds.height()) { |
544 WasResized(); | 565 WasResized(); |
545 } | 566 } |
546 } | 567 } |
547 | 568 |
| 569 if (painting_observer_) |
| 570 painting_observer_->WidgetDidUpdateBackingStore(this); |
| 571 |
548 // Log the time delta for processing a paint message. | 572 // Log the time delta for processing a paint message. |
549 TimeDelta delta = TimeTicks::Now() - paint_start; | 573 TimeDelta delta = TimeTicks::Now() - paint_start; |
550 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta); | 574 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta); |
551 } | 575 } |
552 | 576 |
553 void RenderWidgetHost::OnMsgScrollRect( | 577 void RenderWidgetHost::OnMsgScrollRect( |
554 const ViewHostMsg_ScrollRect_Params& params) { | 578 const ViewHostMsg_ScrollRect_Params& params) { |
555 TimeTicks scroll_start = TimeTicks::Now(); | 579 TimeTicks scroll_start = TimeTicks::Now(); |
556 | 580 |
557 DCHECK(!params.view_size.IsEmpty()); | 581 DCHECK(!params.view_size.IsEmpty()); |
(...skipping 26 matching lines...) Expand all Loading... |
584 return; | 608 return; |
585 | 609 |
586 // Paint the view. Watch out: it might be destroyed already. | 610 // Paint the view. Watch out: it might be destroyed already. |
587 if (view_) { | 611 if (view_) { |
588 view_being_painted_ = true; | 612 view_being_painted_ = true; |
589 view_->MovePluginWindows(params.plugin_window_moves); | 613 view_->MovePluginWindows(params.plugin_window_moves); |
590 view_->DidScrollRect(params.clip_rect, params.dx, params.dy); | 614 view_->DidScrollRect(params.clip_rect, params.dx, params.dy); |
591 view_being_painted_ = false; | 615 view_being_painted_ = false; |
592 } | 616 } |
593 | 617 |
| 618 if (painting_observer_) |
| 619 painting_observer_->WidgetDidUpdateBackingStore(this); |
| 620 |
594 // Log the time delta for processing a scroll message. | 621 // Log the time delta for processing a scroll message. |
595 TimeDelta delta = TimeTicks::Now() - scroll_start; | 622 TimeDelta delta = TimeTicks::Now() - scroll_start; |
596 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta); | 623 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta); |
597 } | 624 } |
598 | 625 |
599 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { | 626 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { |
600 // Log the time delta for processing an input event. | 627 // Log the time delta for processing an input event. |
601 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 628 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
602 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); | 629 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); |
603 | 630 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 | 759 |
733 // TODO(darin): do we need to do something else if our backing store is not | 760 // TODO(darin): do we need to do something else if our backing store is not |
734 // the same size as the advertised view? maybe we just assume there is a | 761 // the same size as the advertised view? maybe we just assume there is a |
735 // full paint on its way? | 762 // full paint on its way? |
736 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 763 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
737 if (!backing_store || (backing_store->size() != view_size)) | 764 if (!backing_store || (backing_store->size() != view_size)) |
738 return; | 765 return; |
739 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, | 766 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, |
740 dx, dy, clip_rect, view_size); | 767 dx, dy, clip_rect, view_size); |
741 } | 768 } |
OLD | NEW |