OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/renderer_host/render_widget_host.h" | 5 #include "content/browser/renderer_host/render_widget_host.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 touch_move_pending_(false), | 94 touch_move_pending_(false), |
95 touch_event_is_queued_(false), | 95 touch_event_is_queued_(false), |
96 needs_repainting_on_restore_(false), | 96 needs_repainting_on_restore_(false), |
97 is_unresponsive_(false), | 97 is_unresponsive_(false), |
98 in_get_backing_store_(false), | 98 in_get_backing_store_(false), |
99 view_being_painted_(false), | 99 view_being_painted_(false), |
100 ignore_input_events_(false), | 100 ignore_input_events_(false), |
101 text_direction_updated_(false), | 101 text_direction_updated_(false), |
102 text_direction_(WebKit::WebTextDirectionLeftToRight), | 102 text_direction_(WebKit::WebTextDirectionLeftToRight), |
103 text_direction_canceled_(false), | 103 text_direction_canceled_(false), |
104 suppress_next_char_events_(false), | 104 suppress_incoming_char_events_(false), |
| 105 suppress_outgoing_char_events_(false), |
105 pending_mouse_lock_request_(false), | 106 pending_mouse_lock_request_(false), |
106 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 107 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
107 if (routing_id_ == MSG_ROUTING_NONE) | 108 if (routing_id_ == MSG_ROUTING_NONE) |
108 routing_id_ = process_->GetNextRoutingID(); | 109 routing_id_ = process_->GetNextRoutingID(); |
109 | 110 |
110 process_->Attach(this, routing_id_); | 111 process_->Attach(this, routing_id_); |
111 // Because the widget initializes as is_hidden_ == false, | 112 // Because the widget initializes as is_hidden_ == false, |
112 // tell the process host that we're alive. | 113 // tell the process host that we're alive. |
113 process_->WidgetRestored(); | 114 process_->WidgetRestored(); |
114 | 115 |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 next_mouse_move_->movementX += x; | 568 next_mouse_move_->movementX += x; |
568 next_mouse_move_->movementY += y; | 569 next_mouse_move_->movementY += y; |
569 } | 570 } |
570 return; | 571 return; |
571 } | 572 } |
572 mouse_move_pending_ = true; | 573 mouse_move_pending_ = true; |
573 } else if (mouse_event.type == WebInputEvent::MouseDown) { | 574 } else if (mouse_event.type == WebInputEvent::MouseDown) { |
574 OnUserGesture(); | 575 OnUserGesture(); |
575 } | 576 } |
576 | 577 |
577 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent), false); | 578 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent)); |
578 } | 579 } |
579 | 580 |
580 void RenderWidgetHost::OnMouseActivate() { | 581 void RenderWidgetHost::OnMouseActivate() { |
581 } | 582 } |
582 | 583 |
583 void RenderWidgetHost::ForwardWheelEvent( | 584 void RenderWidgetHost::ForwardWheelEvent( |
584 const WebMouseWheelEvent& wheel_event) { | 585 const WebMouseWheelEvent& wheel_event) { |
585 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); | 586 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); |
586 if (ignore_input_events_ || process_->IgnoreInputEvents()) | 587 if (ignore_input_events_ || process_->IgnoreInputEvents()) |
587 return; | 588 return; |
(...skipping 17 matching lines...) Expand all Loading... |
605 last_wheel_event->timeStampSeconds = wheel_event.timeStampSeconds; | 606 last_wheel_event->timeStampSeconds = wheel_event.timeStampSeconds; |
606 } | 607 } |
607 return; | 608 return; |
608 } | 609 } |
609 mouse_wheel_pending_ = true; | 610 mouse_wheel_pending_ = true; |
610 current_wheel_event_ = wheel_event; | 611 current_wheel_event_ = wheel_event; |
611 | 612 |
612 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize", | 613 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize", |
613 coalesced_mouse_wheel_events_.size()); | 614 coalesced_mouse_wheel_events_.size()); |
614 | 615 |
615 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent), false); | 616 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent)); |
616 } | 617 } |
617 | 618 |
618 void RenderWidgetHost::ForwardGestureEvent( | 619 void RenderWidgetHost::ForwardGestureEvent( |
619 const WebKit::WebGestureEvent& gesture_event) { | 620 const WebKit::WebGestureEvent& gesture_event) { |
620 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); | 621 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); |
621 if (ignore_input_events_ || process_->IgnoreInputEvents()) | 622 if (ignore_input_events_ || process_->IgnoreInputEvents()) |
622 return; | 623 return; |
623 | 624 |
624 ForwardInputEvent(gesture_event, sizeof(WebGestureEvent), false); | 625 ForwardInputEvent(gesture_event, sizeof(WebGestureEvent)); |
625 } | 626 } |
626 | 627 |
627 void RenderWidgetHost::ForwardKeyboardEvent( | 628 void RenderWidgetHost::ForwardKeyboardEvent( |
628 const NativeWebKeyboardEvent& key_event) { | 629 const NativeWebKeyboardEvent& key_event) { |
629 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardKeyboardEvent"); | 630 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardKeyboardEvent"); |
630 if (ignore_input_events_ || process_->IgnoreInputEvents()) | 631 if (ignore_input_events_ || process_->IgnoreInputEvents()) |
631 return; | 632 return; |
632 | 633 |
| 634 // Double check the type to make sure caller hasn't sent us nonsense that |
| 635 // will mess up our key queue. |
| 636 if (!WebInputEvent::isKeyboardEventType(key_event.type)) |
| 637 return; |
| 638 |
633 if (key_event.type == WebKeyboardEvent::Char && | 639 if (key_event.type == WebKeyboardEvent::Char && |
634 (key_event.windowsKeyCode == ui::VKEY_RETURN || | 640 (key_event.windowsKeyCode == ui::VKEY_RETURN || |
635 key_event.windowsKeyCode == ui::VKEY_SPACE)) { | 641 key_event.windowsKeyCode == ui::VKEY_SPACE)) { |
636 OnUserGesture(); | 642 OnUserGesture(); |
637 } | 643 } |
638 | 644 |
639 // Double check the type to make sure caller hasn't sent us nonsense that | 645 if (suppress_incoming_char_events_) { |
640 // will mess up our key queue. | 646 // If the preceding RawKeyDown event was handled by the browser, then we |
641 if (WebInputEvent::isKeyboardEventType(key_event.type)) { | 647 // need to suppress all Char events generated by it. Please note that, one |
642 if (suppress_next_char_events_) { | 648 // RawKeyDown event may generate multiple Char events, so we can't reset |
643 // If preceding RawKeyDown event was handled by the browser, then we need | 649 // |suppress_incoming_char_events_| until we get a KeyUp or a RawKeyDown. |
644 // suppress all Char events generated by it. Please note that, one | 650 if (key_event.type == WebKeyboardEvent::Char) |
645 // RawKeyDown event may generate multiple Char events, so we can't reset | 651 return; |
646 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown. | 652 // We get a KeyUp or a RawKeyDown event. |
647 if (key_event.type == WebKeyboardEvent::Char) | 653 suppress_incoming_char_events_ = false; |
648 return; | 654 } |
649 // We get a KeyUp or a RawKeyDown event. | 655 |
650 suppress_next_char_events_ = false; | 656 bool is_keyboard_shortcut = false; |
| 657 // Only pre-handle the key event if it's not handled by the input method. |
| 658 if (!key_event.skip_in_browser) { |
| 659 // We need to set |suppress_incoming_char_events_| to true if |
| 660 // PreHandleKeyboardEvent() returns true, but |this| may already be |
| 661 // destroyed at that time. So set |suppress_incoming_char_events_| true |
| 662 // here, then revert it afterwards when necessary. |
| 663 if (key_event.type == WebKeyboardEvent::RawKeyDown) |
| 664 suppress_incoming_char_events_ = true; |
| 665 |
| 666 // Tab switching/closing accelerators aren't sent to the renderer to avoid |
| 667 // a hung/malicious renderer from interfering. |
| 668 if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut)) |
| 669 return; |
| 670 |
| 671 if (key_event.type == WebKeyboardEvent::RawKeyDown) |
| 672 suppress_incoming_char_events_ = false; |
| 673 } |
| 674 |
| 675 // Don't add this key to the queue if we have no way to send the message... |
| 676 if (!process_->HasConnection()) |
| 677 return; |
| 678 |
| 679 bool has_pending_key = !key_queue_.empty(); |
| 680 |
| 681 // We keep track of all pending keyboard events so that if any are not |
| 682 // processed by the renderer, we have the ability to process them in the |
| 683 // browser (via UnhandledKeyboardEvent). We also delay sending the next |
| 684 // keyboard event until the previous has been ACK'd by the renderer. |
| 685 key_queue_.push_back(Key(key_event, is_keyboard_shortcut)); |
| 686 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
| 687 |
| 688 if (!has_pending_key) |
| 689 ForwardNextKeyboardEvent(); |
| 690 } |
| 691 |
| 692 void RenderWidgetHost::ForwardNextKeyboardEvent() { |
| 693 while (!key_queue_.empty()) { |
| 694 const Key& front_item = key_queue_.front(); |
| 695 |
| 696 if (suppress_outgoing_char_events_) { |
| 697 if (front_item.event.type == WebInputEvent::Char) { |
| 698 key_queue_.pop_front(); |
| 699 continue; |
| 700 } |
| 701 suppress_outgoing_char_events_ = false; |
651 } | 702 } |
652 | 703 |
653 bool is_keyboard_shortcut = false; | 704 // The renderer only cares about the platform-independent event data. |
654 // Only pre-handle the key event if it's not handled by the input method. | 705 ForwardInputEvent(front_item.event, sizeof(WebKeyboardEvent)); |
655 if (!key_event.skip_in_browser) { | 706 break; |
656 // We need to set |suppress_next_char_events_| to true if | |
657 // PreHandleKeyboardEvent() returns true, but |this| may already be | |
658 // destroyed at that time. So set |suppress_next_char_events_| true here, | |
659 // then revert it afterwards when necessary. | |
660 if (key_event.type == WebKeyboardEvent::RawKeyDown) | |
661 suppress_next_char_events_ = true; | |
662 | |
663 // Tab switching/closing accelerators aren't sent to the renderer to avoid | |
664 // a hung/malicious renderer from interfering. | |
665 if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut)) | |
666 return; | |
667 | |
668 if (key_event.type == WebKeyboardEvent::RawKeyDown) | |
669 suppress_next_char_events_ = false; | |
670 } | |
671 | |
672 // Don't add this key to the queue if we have no way to send the message... | |
673 if (!process_->HasConnection()) | |
674 return; | |
675 | |
676 // Put all WebKeyboardEvent objects in a queue since we can't trust the | |
677 // renderer and we need to give something to the UnhandledInputEvent | |
678 // handler. | |
679 key_queue_.push_back(key_event); | |
680 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | |
681 | |
682 // Only forward the non-native portions of our event. | |
683 ForwardInputEvent(key_event, sizeof(WebKeyboardEvent), | |
684 is_keyboard_shortcut); | |
685 } | 707 } |
686 } | 708 } |
687 | 709 |
688 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, | 710 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, |
689 int event_size, | 711 int event_size) { |
690 bool is_keyboard_shortcut) { | |
691 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardInputEvent"); | 712 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardInputEvent"); |
692 | 713 |
693 if (!process_->HasConnection()) | 714 if (!process_->HasConnection()) |
694 return; | 715 return; |
695 | 716 |
696 DCHECK(!process_->IgnoreInputEvents()); | 717 DCHECK(!process_->IgnoreInputEvents()); |
697 | 718 |
698 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); | 719 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); |
699 message->WriteData( | 720 message->WriteData( |
700 reinterpret_cast<const char*>(&input_event), event_size); | 721 reinterpret_cast<const char*>(&input_event), event_size); |
701 // |is_keyboard_shortcut| only makes sense for RawKeyDown events. | |
702 if (input_event.type == WebInputEvent::RawKeyDown) | |
703 message->WriteBool(is_keyboard_shortcut); | |
704 input_event_start_time_ = TimeTicks::Now(); | 722 input_event_start_time_ = TimeTicks::Now(); |
705 Send(message); | 723 Send(message); |
706 | 724 |
707 // Any non-wheel input event cancels pending wheel events. | 725 // Any non-wheel input event cancels pending wheel events. |
708 if (input_event.type != WebInputEvent::MouseWheel) | 726 if (input_event.type != WebInputEvent::MouseWheel) |
709 coalesced_mouse_wheel_events_.clear(); | 727 coalesced_mouse_wheel_events_.clear(); |
710 | 728 |
711 // Any input event cancels a pending mouse move event. Note that | 729 // Any input event cancels a pending mouse move event. Note that |
712 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event| | 730 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event| |
713 // after this line. | 731 // after this line. |
(...skipping 12 matching lines...) Expand all Loading... |
726 touch_move_pending_) { | 744 touch_move_pending_) { |
727 touch_event_is_queued_ = true; | 745 touch_event_is_queued_ = true; |
728 queued_touch_event_ = touch_event; | 746 queued_touch_event_ = touch_event; |
729 return; | 747 return; |
730 } | 748 } |
731 | 749 |
732 if (touch_event.type == WebInputEvent::TouchMove) | 750 if (touch_event.type == WebInputEvent::TouchMove) |
733 touch_move_pending_ = true; | 751 touch_move_pending_ = true; |
734 else | 752 else |
735 touch_move_pending_ = false; | 753 touch_move_pending_ = false; |
736 ForwardInputEvent(touch_event, sizeof(WebKit::WebTouchEvent), false); | 754 ForwardInputEvent(touch_event, sizeof(WebKit::WebTouchEvent)); |
737 } | 755 } |
738 | 756 |
739 void RenderWidgetHost::RendererExited(base::TerminationStatus status, | 757 void RenderWidgetHost::RendererExited(base::TerminationStatus status, |
740 int exit_code) { | 758 int exit_code) { |
741 // Clearing this flag causes us to re-create the renderer when recovering | 759 // Clearing this flag causes us to re-create the renderer when recovering |
742 // from a crashed renderer. | 760 // from a crashed renderer. |
743 renderer_initialized_ = false; | 761 renderer_initialized_ = false; |
744 | 762 |
745 // Must reset these to ensure that mouse move/wheel events work with a new | 763 // Must reset these to ensure that mouse move/wheel events work with a new |
746 // renderer. | 764 // renderer. |
747 mouse_move_pending_ = false; | 765 mouse_move_pending_ = false; |
748 next_mouse_move_.reset(); | 766 next_mouse_move_.reset(); |
749 mouse_wheel_pending_ = false; | 767 mouse_wheel_pending_ = false; |
750 coalesced_mouse_wheel_events_.clear(); | 768 coalesced_mouse_wheel_events_.clear(); |
751 touch_move_pending_ = false; | 769 touch_move_pending_ = false; |
752 touch_event_is_queued_ = false; | 770 touch_event_is_queued_ = false; |
753 | 771 |
754 // Must reset these to ensure that keyboard events work with a new renderer. | 772 // Must reset these to ensure that keyboard events work with a new renderer. |
755 key_queue_.clear(); | 773 key_queue_.clear(); |
756 suppress_next_char_events_ = false; | 774 suppress_incoming_char_events_ = false; |
| 775 suppress_outgoing_char_events_ = false; |
757 | 776 |
758 // Reset some fields in preparation for recovering from a crash. | 777 // Reset some fields in preparation for recovering from a crash. |
759 resize_ack_pending_ = false; | 778 resize_ack_pending_ = false; |
760 repaint_ack_pending_ = false; | 779 repaint_ack_pending_ = false; |
761 | 780 |
762 in_flight_size_.SetSize(0, 0); | 781 in_flight_size_.SetSize(0, 0); |
763 in_flight_reserved_rect_.SetRect(0, 0, 0, 0); | 782 in_flight_reserved_rect_.SetRect(0, 0, 0, 0); |
764 current_size_.SetSize(0, 0); | 783 current_size_.SetSize(0, 0); |
765 current_reserved_rect_.SetRect(0, 0, 0, 0); | 784 current_reserved_rect_.SetRect(0, 0, 0, 0); |
766 is_hidden_ = false; | 785 is_hidden_ = false; |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1316 if (process_->HasConnection()) { | 1335 if (process_->HasConnection()) { |
1317 // Renderer accessibility wasn't enabled on process launch. Enable it now. | 1336 // Renderer accessibility wasn't enabled on process launch. Enable it now. |
1318 Send(new ViewMsg_EnableAccessibility(routing_id())); | 1337 Send(new ViewMsg_EnableAccessibility(routing_id())); |
1319 } | 1338 } |
1320 } | 1339 } |
1321 | 1340 |
1322 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) { | 1341 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) { |
1323 if (key_queue_.empty()) { | 1342 if (key_queue_.empty()) { |
1324 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " | 1343 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " |
1325 << "don't seem to have sent it to the renderer!"; | 1344 << "don't seem to have sent it to the renderer!"; |
1326 } else if (key_queue_.front().type != type) { | 1345 } else if (key_queue_.front().event.type != type) { |
1327 LOG(ERROR) << "We seem to have a different key type sent from " | 1346 LOG(ERROR) << "We seem to have a different key type sent from " |
1328 << "the renderer. (" << key_queue_.front().type << " vs. " | 1347 << "the renderer. (" << key_queue_.front().event.type << " vs. " |
1329 << type << "). Ignoring event."; | 1348 << type << "). Ignoring event."; |
1330 | 1349 |
1331 // Something must be wrong. Clear the |key_queue_| and | 1350 // Something must be wrong. Clear the |key_queue_| and |
1332 // |suppress_next_char_events_| so that we can resume from the error. | 1351 // |suppress_incoming_char_events_| so that we can resume from the error. |
1333 key_queue_.clear(); | 1352 key_queue_.clear(); |
1334 suppress_next_char_events_ = false; | 1353 suppress_incoming_char_events_ = false; |
| 1354 suppress_outgoing_char_events_ = false; |
1335 } else { | 1355 } else { |
1336 NativeWebKeyboardEvent front_item = key_queue_.front(); | 1356 Key front_item = key_queue_.front(); |
1337 key_queue_.pop_front(); | 1357 key_queue_.pop_front(); |
1338 | 1358 |
1339 #if defined(OS_MACOSX) | 1359 #if defined(OS_MACOSX) |
1340 if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item)) | 1360 if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item.event)) |
1341 return; | 1361 return; |
1342 #endif | 1362 #endif |
1343 | 1363 |
| 1364 // If this RawKeyDown event corresponds to a browser keyboard shortcut and |
| 1365 // it's not processed by the renderer, then we need to suppress the |
| 1366 // upcoming Char event. |
| 1367 if (!processed && front_item.is_shortcut) { |
| 1368 DCHECK(front_item.event.type == WebInputEvent::RawKeyDown); |
| 1369 suppress_outgoing_char_events_ = true; |
| 1370 } |
| 1371 |
| 1372 ForwardNextKeyboardEvent(); |
| 1373 |
1344 // We only send unprocessed key event upwards if we are not hidden, | 1374 // We only send unprocessed key event upwards if we are not hidden, |
1345 // because the user has moved away from us and no longer expect any effect | 1375 // because the user has moved away from us and no longer expect any effect |
1346 // of this key event. | 1376 // of this key event. |
1347 if (!processed && !is_hidden_ && !front_item.skip_in_browser) { | 1377 if (!processed && !is_hidden_ && !front_item.event.skip_in_browser) { |
1348 UnhandledKeyboardEvent(front_item); | 1378 UnhandledKeyboardEvent(front_item.event); |
1349 | 1379 |
1350 // WARNING: This RenderWidgetHost can be deallocated at this point | 1380 // WARNING: This RenderWidgetHost can be deallocated at this point |
1351 // (i.e. in the case of Ctrl+W, where the call to | 1381 // (i.e. in the case of Ctrl+W, where the call to |
1352 // UnhandledKeyboardEvent destroys this RenderWidgetHost). | 1382 // UnhandledKeyboardEvent destroys this RenderWidgetHost). |
1353 } | 1383 } |
1354 } | 1384 } |
1355 } | 1385 } |
1356 | 1386 |
1357 void RenderWidgetHost::ActivateDeferredPluginHandles() { | 1387 void RenderWidgetHost::ActivateDeferredPluginHandles() { |
1358 #if !defined(USE_AURA) | 1388 #if !defined(USE_AURA) |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1487 } | 1517 } |
1488 | 1518 |
1489 // static | 1519 // static |
1490 void RenderWidgetHost::AcknowledgePostSubBuffer(int32 route_id, | 1520 void RenderWidgetHost::AcknowledgePostSubBuffer(int32 route_id, |
1491 int gpu_host_id) { | 1521 int gpu_host_id) { |
1492 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); | 1522 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); |
1493 if (ui_shim) | 1523 if (ui_shim) |
1494 ui_shim->Send(new AcceleratedSurfaceMsg_PostSubBufferACK(route_id)); | 1524 ui_shim->Send(new AcceleratedSurfaceMsg_PostSubBufferACK(route_id)); |
1495 } | 1525 } |
1496 #endif | 1526 #endif |
OLD | NEW |