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