| 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/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/histogram.h" | 8 #include "base/histogram.h" |
| 9 #include "base/keyboard_codes.h" | 9 #include "base/keyboard_codes.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 Destroy(); | 117 Destroy(); |
| 118 } | 118 } |
| 119 | 119 |
| 120 void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) { | 120 void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) { |
| 121 bool msg_is_ok = true; | 121 bool msg_is_ok = true; |
| 122 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHost, msg, msg_is_ok) | 122 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHost, msg, msg_is_ok) |
| 123 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnMsgRenderViewReady) | 123 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnMsgRenderViewReady) |
| 124 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnMsgRenderViewGone) | 124 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnMsgRenderViewGone) |
| 125 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose) | 125 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose) |
| 126 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove) | 126 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove) |
| 127 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintRect, OnMsgPaintRect) | 127 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect) |
| 128 IPC_MESSAGE_HANDLER(ViewHostMsg_ScrollRect, OnMsgScrollRect) | |
| 129 IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck) | 128 IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck) |
| 130 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus) | 129 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus) |
| 131 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur) | 130 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur) |
| 132 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged) | 131 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged) |
| 133 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnMsgSetCursor) | 132 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnMsgSetCursor) |
| 134 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeUpdateStatus, OnMsgImeUpdateStatus) | 133 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeUpdateStatus, OnMsgImeUpdateStatus) |
| 135 #if defined(OS_LINUX) | 134 #if defined(OS_LINUX) |
| 136 IPC_MESSAGE_HANDLER(ViewHostMsg_CreatePluginContainer, | 135 IPC_MESSAGE_HANDLER(ViewHostMsg_CreatePluginContainer, |
| 137 OnMsgCreatePluginContainer) | 136 OnMsgCreatePluginContainer) |
| 138 IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyPluginContainer, | 137 IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyPluginContainer, |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 repaint_ack_pending_ = true; | 291 repaint_ack_pending_ = true; |
| 293 Send(new ViewMsg_Repaint(routing_id_, current_size_)); | 292 Send(new ViewMsg_Repaint(routing_id_, current_size_)); |
| 294 } | 293 } |
| 295 | 294 |
| 296 // When we have asked the RenderWidget to resize, and we are still waiting on | 295 // When we have asked the RenderWidget to resize, and we are still waiting on |
| 297 // a response, block for a little while to see if we can't get a response | 296 // a response, block for a little while to see if we can't get a response |
| 298 // before returning the old (incorrectly sized) backing store. | 297 // before returning the old (incorrectly sized) backing store. |
| 299 if (resize_ack_pending_ || !backing_store) { | 298 if (resize_ack_pending_ || !backing_store) { |
| 300 IPC::Message msg; | 299 IPC::Message msg; |
| 301 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); | 300 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); |
| 302 if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) { | 301 if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { |
| 303 ViewHostMsg_PaintRect::Dispatch( | 302 ViewHostMsg_UpdateRect::Dispatch( |
| 304 &msg, this, &RenderWidgetHost::OnMsgPaintRect); | 303 &msg, this, &RenderWidgetHost::OnMsgUpdateRect); |
| 305 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); | 304 backing_store = BackingStoreManager::GetBackingStore(this, current_size_); |
| 306 } | 305 } |
| 307 } | 306 } |
| 308 | 307 |
| 309 return backing_store; | 308 return backing_store; |
| 310 } | 309 } |
| 311 | 310 |
| 312 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { | 311 BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) { |
| 313 if (!view_) | 312 if (!view_) |
| 314 return NULL; | 313 return NULL; |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 } | 610 } |
| 612 | 611 |
| 613 void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { | 612 void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { |
| 614 // Note that we ignore the position. | 613 // Note that we ignore the position. |
| 615 if (view_) { | 614 if (view_) { |
| 616 view_->SetSize(pos.size()); | 615 view_->SetSize(pos.size()); |
| 617 Send(new ViewMsg_Move_ACK(routing_id_)); | 616 Send(new ViewMsg_Move_ACK(routing_id_)); |
| 618 } | 617 } |
| 619 } | 618 } |
| 620 | 619 |
| 621 void RenderWidgetHost::OnMsgPaintRect( | 620 void RenderWidgetHost::OnMsgUpdateRect( |
| 622 const ViewHostMsg_PaintRect_Params& params) { | 621 const ViewHostMsg_UpdateRect_Params& params) { |
| 623 TimeTicks paint_start = TimeTicks::Now(); | 622 TimeTicks paint_start = TimeTicks::Now(); |
| 624 | 623 |
| 625 // Update our knowledge of the RenderWidget's size. | 624 // Update our knowledge of the RenderWidget's size. |
| 626 current_size_ = params.view_size; | 625 current_size_ = params.view_size; |
| 627 | 626 |
| 628 bool is_resize_ack = | 627 bool is_resize_ack = |
| 629 ViewHostMsg_PaintRect_Flags::is_resize_ack(params.flags); | 628 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags); |
| 630 | 629 |
| 631 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since | 630 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since |
| 632 // that will end up reaching GetBackingStore. | 631 // that will end up reaching GetBackingStore. |
| 633 if (is_resize_ack) { | 632 if (is_resize_ack) { |
| 634 DCHECK(resize_ack_pending_); | 633 DCHECK(resize_ack_pending_); |
| 635 resize_ack_pending_ = false; | 634 resize_ack_pending_ = false; |
| 636 in_flight_size_.SetSize(0, 0); | 635 in_flight_size_.SetSize(0, 0); |
| 637 } | 636 } |
| 638 | 637 |
| 639 bool is_repaint_ack = | 638 bool is_repaint_ack = |
| 640 ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags); | 639 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags); |
| 641 if (is_repaint_ack) { | 640 if (is_repaint_ack) { |
| 642 repaint_ack_pending_ = false; | 641 repaint_ack_pending_ = false; |
| 643 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; | 642 TimeDelta delta = TimeTicks::Now() - repaint_start_time_; |
| 644 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); | 643 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta); |
| 645 } | 644 } |
| 646 | 645 |
| 647 DCHECK(!params.bitmap_rect.IsEmpty()); | 646 DCHECK(!params.bitmap_rect.IsEmpty()); |
| 648 DCHECK(!params.view_size.IsEmpty()); | 647 DCHECK(!params.view_size.IsEmpty()); |
| 649 | 648 |
| 650 const size_t size = params.bitmap_rect.height() * | 649 const size_t size = params.bitmap_rect.height() * |
| 651 params.bitmap_rect.width() * 4; | 650 params.bitmap_rect.width() * 4; |
| 652 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | 651 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); |
| 653 if (dib) { | 652 if (dib) { |
| 654 if (dib->size() < size) { | 653 if (dib->size() < size) { |
| 655 DLOG(WARNING) << "Transport DIB too small for given rectangle"; | 654 DLOG(WARNING) << "Transport DIB too small for given rectangle"; |
| 656 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); | 655 process()->ReceivedBadMessage(ViewHostMsg_UpdateRect__ID); |
| 657 } else { | 656 } else { |
| 657 // Scroll the backing store. |
| 658 if (!params.scroll_rect.IsEmpty()) { |
| 659 ScrollBackingStoreRect(params.dx, params.dy, |
| 660 params.scroll_rect, |
| 661 params.view_size); |
| 662 } |
| 663 |
| 658 // Paint the backing store. This will update it with the renderer-supplied | 664 // Paint the backing store. This will update it with the renderer-supplied |
| 659 // bits. The view will read out of the backing store later to actually | 665 // bits. The view will read out of the backing store later to actually |
| 660 // draw to the screen. | 666 // draw to the screen. |
| 661 PaintBackingStoreRect(dib, params.bitmap_rect, params.update_rects, | 667 PaintBackingStoreRect(dib, params.bitmap_rect, params.copy_rects, |
| 662 params.view_size); | 668 params.view_size); |
| 663 } | 669 } |
| 664 } | 670 } |
| 665 | 671 |
| 666 // ACK early so we can prefetch the next PaintRect if there is a next one. | 672 // ACK early so we can prefetch the next PaintRect if there is a next one. |
| 667 // This must be done AFTER we're done painting with the bitmap supplied by the | 673 // This must be done AFTER we're done painting with the bitmap supplied by the |
| 668 // renderer. This ACK is a signal to the renderer that the backing store can | 674 // renderer. This ACK is a signal to the renderer that the backing store can |
| 669 // be re-used, so the bitmap may be invalid after this call. | 675 // be re-used, so the bitmap may be invalid after this call. |
| 670 Send(new ViewMsg_PaintRect_ACK(routing_id_)); | 676 Send(new ViewMsg_UpdateRect_ACK(routing_id_)); |
| 671 | 677 |
| 672 // We don't need to update the view if the view is hidden. We must do this | 678 // We don't need to update the view if the view is hidden. We must do this |
| 673 // early return after the ACK is sent, however, or the renderer will not send | 679 // early return after the ACK is sent, however, or the renderer will not send |
| 674 // us more data. | 680 // us more data. |
| 675 if (is_hidden_) | 681 if (is_hidden_) |
| 676 return; | 682 return; |
| 677 | 683 |
| 678 // Now paint the view. Watch out: it might be destroyed already. | 684 // Now paint the view. Watch out: it might be destroyed already. |
| 679 if (view_) { | 685 if (view_) { |
| 680 view_->MovePluginWindows(params.plugin_window_moves); | 686 view_->MovePluginWindows(params.plugin_window_moves); |
| 681 view_being_painted_ = true; | 687 view_being_painted_ = true; |
| 682 view_->DidPaintRect(params.bitmap_rect); | 688 if (!params.scroll_rect.IsEmpty()) { |
| 689 view_->DidScrollBackingStoreRect(params.scroll_rect, |
| 690 params.dx, |
| 691 params.dy); |
| 692 } |
| 693 view_->DidPaintBackingStoreRects(params.copy_rects); |
| 683 view_being_painted_ = false; | 694 view_being_painted_ = false; |
| 684 } | 695 } |
| 685 | 696 |
| 686 if (paint_observer_.get()) | 697 if (paint_observer_.get()) |
| 687 paint_observer_->RenderWidgetHostDidPaint(this); | 698 paint_observer_->RenderWidgetHostDidPaint(this); |
| 688 | 699 |
| 689 // If we got a resize ack, then perhaps we have another resize to send? | 700 // If we got a resize ack, then perhaps we have another resize to send? |
| 690 if (is_resize_ack && view_) { | 701 if (is_resize_ack && view_) { |
| 691 gfx::Rect view_bounds = view_->GetViewBounds(); | 702 gfx::Rect view_bounds = view_->GetViewBounds(); |
| 692 if (current_size_.width() != view_bounds.width() || | 703 if (current_size_.width() != view_bounds.width() || |
| 693 current_size_.height() != view_bounds.height()) { | 704 current_size_.height() != view_bounds.height()) { |
| 694 WasResized(); | 705 WasResized(); |
| 695 } | 706 } |
| 696 } | 707 } |
| 697 | 708 |
| 698 if (painting_observer_) | 709 if (painting_observer_) |
| 699 painting_observer_->WidgetDidUpdateBackingStore(this); | 710 painting_observer_->WidgetDidUpdateBackingStore(this); |
| 700 | 711 |
| 701 // Log the time delta for processing a paint message. | 712 // Log the time delta for processing a paint message. |
| 702 TimeDelta delta = TimeTicks::Now() - paint_start; | 713 TimeDelta delta = TimeTicks::Now() - paint_start; |
| 703 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta); | 714 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta); |
| 704 } | |
| 705 | |
| 706 void RenderWidgetHost::OnMsgScrollRect( | |
| 707 const ViewHostMsg_ScrollRect_Params& params) { | |
| 708 TimeTicks scroll_start = TimeTicks::Now(); | |
| 709 | |
| 710 DCHECK(!params.view_size.IsEmpty()); | |
| 711 | |
| 712 const size_t size = params.bitmap_rect.height() * | |
| 713 params.bitmap_rect.width() * 4; | |
| 714 TransportDIB* dib = process_->GetTransportDIB(params.bitmap); | |
| 715 if (dib) { | |
| 716 if (dib->size() < size) { | |
| 717 LOG(WARNING) << "Transport DIB too small for given rectangle"; | |
| 718 process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); | |
| 719 } else { | |
| 720 // Scroll the backing store. | |
| 721 ScrollBackingStoreRect(dib, params.bitmap_rect, | |
| 722 params.dx, params.dy, | |
| 723 params.clip_rect, params.view_size); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 // ACK early so we can prefetch the next ScrollRect if there is a next one. | |
| 728 // This must be done AFTER we're done painting with the bitmap supplied by the | |
| 729 // renderer. This ACK is a signal to the renderer that the backing store can | |
| 730 // be re-used, so the bitmap may be invalid after this call. | |
| 731 Send(new ViewMsg_ScrollRect_ACK(routing_id_)); | |
| 732 | |
| 733 // We don't need to update the view if the view is hidden. We must do this | |
| 734 // early return after the ACK is sent, however, or the renderer will not send | |
| 735 // is more data. | |
| 736 if (is_hidden_) | |
| 737 return; | |
| 738 | |
| 739 // Paint the view. Watch out: it might be destroyed already. | |
| 740 if (view_) { | |
| 741 view_being_painted_ = true; | |
| 742 view_->MovePluginWindows(params.plugin_window_moves); | |
| 743 view_->DidScrollRect(params.clip_rect, params.dx, params.dy); | |
| 744 view_being_painted_ = false; | |
| 745 } | |
| 746 | |
| 747 if (painting_observer_) | |
| 748 painting_observer_->WidgetDidUpdateBackingStore(this); | |
| 749 | |
| 750 // Log the time delta for processing a scroll message. | |
| 751 TimeDelta delta = TimeTicks::Now() - scroll_start; | |
| 752 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta); | |
| 753 } | 715 } |
| 754 | 716 |
| 755 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { | 717 void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) { |
| 756 // Log the time delta for processing an input event. | 718 // Log the time delta for processing an input event. |
| 757 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 719 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
| 758 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); | 720 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta); |
| 759 | 721 |
| 760 // Cancel pending hung renderer checks since the renderer is responsive. | 722 // Cancel pending hung renderer checks since the renderer is responsive. |
| 761 StopHangMonitorTimeout(); | 723 StopHangMonitorTimeout(); |
| 762 | 724 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 process_->GetHandle(), | 846 process_->GetHandle(), |
| 885 bitmap, bitmap_rect, copy_rects, | 847 bitmap, bitmap_rect, copy_rects, |
| 886 &needs_full_paint); | 848 &needs_full_paint); |
| 887 if (needs_full_paint) { | 849 if (needs_full_paint) { |
| 888 repaint_start_time_ = TimeTicks::Now(); | 850 repaint_start_time_ = TimeTicks::Now(); |
| 889 repaint_ack_pending_ = true; | 851 repaint_ack_pending_ = true; |
| 890 Send(new ViewMsg_Repaint(routing_id_, view_size)); | 852 Send(new ViewMsg_Repaint(routing_id_, view_size)); |
| 891 } | 853 } |
| 892 } | 854 } |
| 893 | 855 |
| 894 void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, | 856 void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy, |
| 895 const gfx::Rect& bitmap_rect, | |
| 896 int dx, int dy, | |
| 897 const gfx::Rect& clip_rect, | 857 const gfx::Rect& clip_rect, |
| 898 const gfx::Size& view_size) { | 858 const gfx::Size& view_size) { |
| 899 if (is_hidden_) { | 859 if (is_hidden_) { |
| 900 // Don't bother updating the backing store when we're hidden. Just mark it | 860 // Don't bother updating the backing store when we're hidden. Just mark it |
| 901 // as being totally invalid. This will cause a complete repaint when the | 861 // as being totally invalid. This will cause a complete repaint when the |
| 902 // view is restored. | 862 // view is restored. |
| 903 needs_repainting_on_restore_ = true; | 863 needs_repainting_on_restore_ = true; |
| 904 return; | 864 return; |
| 905 } | 865 } |
| 906 | 866 |
| 907 // TODO(darin): do we need to do something else if our backing store is not | 867 // TODO(darin): do we need to do something else if our backing store is not |
| 908 // the same size as the advertised view? maybe we just assume there is a | 868 // the same size as the advertised view? maybe we just assume there is a |
| 909 // full paint on its way? | 869 // full paint on its way? |
| 910 BackingStore* backing_store = BackingStoreManager::Lookup(this); | 870 BackingStore* backing_store = BackingStoreManager::Lookup(this); |
| 911 if (!backing_store || (backing_store->size() != view_size)) | 871 if (!backing_store || (backing_store->size() != view_size)) |
| 912 return; | 872 return; |
| 913 backing_store->ScrollRect(process_->GetHandle(), bitmap, bitmap_rect, | 873 backing_store->ScrollRect(dx, dy, clip_rect, view_size); |
| 914 dx, dy, clip_rect, view_size); | |
| 915 } | 874 } |
| 916 | 875 |
| 917 void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) { | 876 void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) { |
| 918 Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible)); | 877 Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible)); |
| 919 } | 878 } |
| 920 | 879 |
| 921 void RenderWidgetHost::Replace(const string16& word) { | 880 void RenderWidgetHost::Replace(const string16& word) { |
| 922 Send(new ViewMsg_Replace(routing_id_, word)); | 881 Send(new ViewMsg_Replace(routing_id_, word)); |
| 923 } | 882 } |
| 924 | 883 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 945 | 904 |
| 946 if (!processed) { | 905 if (!processed) { |
| 947 UnhandledKeyboardEvent(front_item); | 906 UnhandledKeyboardEvent(front_item); |
| 948 | 907 |
| 949 // WARNING: This RenderWidgetHost can be deallocated at this point | 908 // WARNING: This RenderWidgetHost can be deallocated at this point |
| 950 // (i.e. in the case of Ctrl+W, where the call to | 909 // (i.e. in the case of Ctrl+W, where the call to |
| 951 // UnhandledKeyboardEvent destroys this RenderWidgetHost). | 910 // UnhandledKeyboardEvent destroys this RenderWidgetHost). |
| 952 } | 911 } |
| 953 } | 912 } |
| 954 } | 913 } |
| OLD | NEW |