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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 view_ = NULL; | 224 view_ = NULL; |
211 } | 225 } |
212 | 226 |
213 void RenderWidgetHost::SetIsLoading(bool is_loading) { | 227 void RenderWidgetHost::SetIsLoading(bool is_loading) { |
214 is_loading_ = is_loading; | 228 is_loading_ = is_loading; |
215 if (!view_) | 229 if (!view_) |
216 return; | 230 return; |
217 view_->SetIsLoading(is_loading); | 231 view_->SetIsLoading(is_loading); |
218 } | 232 } |
219 | 233 |
220 BackingStore* RenderWidgetHost::GetBackingStore() { | 234 BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) { |
221 // We should not be asked to paint while we are hidden. If we are hidden, | 235 // We should not be asked to paint while we are hidden. If we are hidden, |
222 // then it means that our consumer failed to call WasRestored. | 236 // then it means that our consumer failed to call WasRestored. If we're not |
223 DCHECK(!is_hidden_) << "GetBackingStore called while hidden!"; | 237 // force creating the backing store, it's OK since we can feel free to give |
| 238 // out our cached one if we have it. |
| 239 DCHECK(!is_hidden_ || !force_create) << |
| 240 "GetBackingStore called while hidden!"; |
224 | 241 |
225 // We should never be called recursively; this can theoretically lead to | 242 // We should never be called recursively; this can theoretically lead to |
226 // infinite recursion and almost certainly leads to lower performance. | 243 // infinite recursion and almost certainly leads to lower performance. |
227 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; | 244 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!"; |
228 in_get_backing_store_ = true; | 245 in_get_backing_store_ = true; |
229 | 246 |
230 // We might have a cached backing store that we can reuse! | 247 // We might have a cached backing store that we can reuse! |
231 BackingStore* backing_store = | 248 BackingStore* backing_store = |
232 BackingStoreManager::GetBackingStore(this, current_size_); | 249 BackingStoreManager::GetBackingStore(this, current_size_); |
| 250 if (!force_create) { |
| 251 in_get_backing_store_ = false; |
| 252 return backing_store; |
| 253 } |
| 254 |
233 // If we fail to find a backing store in the cache, send out a request | 255 // If we fail to find a backing store in the cache, send out a request |
234 // to the renderer to paint the view if required. | 256 // to the renderer to paint the view if required. |
235 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && | 257 if (!backing_store && !repaint_ack_pending_ && !resize_ack_pending_ && |
236 !view_being_painted_) { | 258 !view_being_painted_) { |
237 repaint_start_time_ = TimeTicks::Now(); | 259 repaint_start_time_ = TimeTicks::Now(); |
238 repaint_ack_pending_ = true; | 260 repaint_ack_pending_ = true; |
239 Send(new ViewMsg_Repaint(routing_id_, current_size_)); | 261 Send(new ViewMsg_Repaint(routing_id_, current_size_)); |
240 } | 262 } |
241 | 263 |
242 // When we have asked the RenderWidget to resize, and we are still waiting on | 264 // When we have asked the RenderWidget to resize, and we are still waiting on |
243 // a response, block for a little while to see if we can't get a response | 265 // a response, block for a little while to see if we can't get a response |
244 // before returning the old (incorrectly sized) backing store. | 266 // before returning the old (incorrectly sized) backing store. |
245 if (resize_ack_pending_ || !backing_store) { | 267 if (resize_ack_pending_ || !backing_store) { |
246 IPC::Message msg; | 268 IPC::Message msg; |
247 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); | 269 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); |
248 if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) { | 270 if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) { |
249 ViewHostMsg_PaintRect::Dispatch( | 271 ViewHostMsg_PaintRect::Dispatch( |
250 &msg, this, &RenderWidgetHost::OnMsgPaintRect); | 272 &msg, this, &RenderWidgetHost::OnMsgPaintRect); |
251 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); | 273 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); |
252 } | 274 } |
253 } | 275 } |
254 | 276 |
255 in_get_backing_store_ = false; | 277 in_get_backing_store_ = false; |
256 return backing_store; | 278 return backing_store; |
257 } | 279 } |
258 | 280 |
259 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { | 281 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { |
260 if (!view_) | 282 if (!view_) |
261 return NULL; | 283 return NULL; |
262 | |
263 return view_->AllocBackingStore(size); | 284 return view_->AllocBackingStore(size); |
264 } | 285 } |
265 | 286 |
266 void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) { | 287 void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) { |
267 time_when_considered_hung_ = Time::Now() + delay; | 288 time_when_considered_hung_ = Time::Now() + delay; |
268 | 289 |
269 // If we already have a timer that will expire at or before the given delay, | 290 // If we already have a timer that will expire at or before the given delay, |
270 // then we have nothing more to do now. | 291 // then we have nothing more to do now. |
271 if (hung_renderer_timer_.IsRunning() && | 292 if (hung_renderer_timer_.IsRunning() && |
272 hung_renderer_timer_.GetCurrentDelay() <= delay) | 293 hung_renderer_timer_.GetCurrentDelay() <= delay) |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 | 563 |
543 // If we got a resize ack, then perhaps we have another resize to send? | 564 // If we got a resize ack, then perhaps we have another resize to send? |
544 if (is_resize_ack && view_) { | 565 if (is_resize_ack && view_) { |
545 gfx::Rect view_bounds = view_->GetViewBounds(); | 566 gfx::Rect view_bounds = view_->GetViewBounds(); |
546 if (current_size_.width() != view_bounds.width() || | 567 if (current_size_.width() != view_bounds.width() || |
547 current_size_.height() != view_bounds.height()) { | 568 current_size_.height() != view_bounds.height()) { |
548 WasResized(); | 569 WasResized(); |
549 } | 570 } |
550 } | 571 } |
551 | 572 |
| 573 if (painting_observer_) |
| 574 painting_observer_->WidgetDidUpdateBackingStore(this); |
| 575 |
552 // Log the time delta for processing a paint message. | 576 // Log the time delta for processing a paint message. |
553 TimeDelta delta = TimeTicks::Now() - paint_start; | 577 TimeDelta delta = TimeTicks::Now() - paint_start; |
554 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta); | 578 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta); |
555 } | 579 } |
556 | 580 |
557 void RenderWidgetHost::OnMsgScrollRect( | 581 void RenderWidgetHost::OnMsgScrollRect( |
558 const ViewHostMsg_ScrollRect_Params& params) { | 582 const ViewHostMsg_ScrollRect_Params& params) { |
559 TimeTicks scroll_start = TimeTicks::Now(); | 583 TimeTicks scroll_start = TimeTicks::Now(); |
560 | 584 |
561 DCHECK(!params.view_size.IsEmpty()); | 585 DCHECK(!params.view_size.IsEmpty()); |
(...skipping 26 matching lines...) Expand all Loading... |
588 return; | 612 return; |
589 | 613 |
590 // Paint the view. Watch out: it might be destroyed already. | 614 // Paint the view. Watch out: it might be destroyed already. |
591 if (view_) { | 615 if (view_) { |
592 view_being_painted_ = true; | 616 view_being_painted_ = true; |
593 view_->MovePluginWindows(params.plugin_window_moves); | 617 view_->MovePluginWindows(params.plugin_window_moves); |
594 view_->DidScrollRect(params.clip_rect, params.dx, params.dy); | 618 view_->DidScrollRect(params.clip_rect, params.dx, params.dy); |
595 view_being_painted_ = false; | 619 view_being_painted_ = false; |
596 } | 620 } |
597 | 621 |
| 622 if (painting_observer_) |
| 623 painting_observer_->WidgetDidUpdateBackingStore(this); |
| 624 |
598 // Log the time delta for processing a scroll message. | 625 // Log the time delta for processing a scroll message. |
599 TimeDelta delta = TimeTicks::Now() - scroll_start; | 626 TimeDelta delta = TimeTicks::Now() - scroll_start; |
600 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta); | 627 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta); |
601 } | 628 } |
602 | 629 |
603 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { | 630 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { |
604 // Log the time delta for processing an input event. | 631 // Log the time delta for processing an input event. |
605 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 632 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
606 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); | 633 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); |
607 | 634 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 | 763 |
737 // TODO(darin): do we need to do something else if our backing store is not | 764 // TODO(darin): do we need to do something else if our backing store is not |
738 // the same size as the advertised view? maybe we just assume there is a | 765 // the same size as the advertised view? maybe we just assume there is a |
739 // full paint on its way? | 766 // full paint on its way? |
740 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 767 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
741 if (!backing_store || (backing_store->size() != view_size)) | 768 if (!backing_store || (backing_store->size() != view_size)) |
742 return; | 769 return; |
743 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, | 770 backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect, |
744 dx, dy, clip_rect, view_size); | 771 dx, dy, clip_rect, view_size); |
745 } | 772 } |
OLD | NEW |