| 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 |