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