Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(676)

Side by Side Diff: content/browser/renderer_host/input/input_router_impl.cc

Issue 660663002: Clear pending events upon main frame navigation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updates Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/input/input_router_impl.h" 5 #include "content/browser/renderer_host/input/input_router_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 client_(client), 68 client_(client),
69 ack_handler_(ack_handler), 69 ack_handler_(ack_handler),
70 routing_id_(routing_id), 70 routing_id_(routing_id),
71 select_message_pending_(false), 71 select_message_pending_(false),
72 move_caret_pending_(false), 72 move_caret_pending_(false),
73 mouse_move_pending_(false), 73 mouse_move_pending_(false),
74 mouse_wheel_pending_(false), 74 mouse_wheel_pending_(false),
75 current_view_flags_(0), 75 current_view_flags_(0),
76 current_ack_source_(ACK_SOURCE_NONE), 76 current_ack_source_(ACK_SOURCE_NONE),
77 flush_requested_(false), 77 flush_requested_(false),
78 in_shutdown_(false),
78 touch_event_queue_(this, config.touch_config), 79 touch_event_queue_(this, config.touch_config),
79 gesture_event_queue_(this, this, config.gesture_config) { 80 gesture_event_queue_(this, this, config.gesture_config) {
80 DCHECK(sender); 81 DCHECK(sender);
81 DCHECK(client); 82 DCHECK(client);
82 DCHECK(ack_handler); 83 DCHECK(ack_handler);
83 UpdateTouchAckTimeoutEnabled(); 84 UpdateTouchAckTimeoutEnabled();
84 } 85 }
85 86
86 InputRouterImpl::~InputRouterImpl() { 87 InputRouterImpl::~InputRouterImpl() {
87 STLDeleteElements(&pending_select_messages_); 88 STLDeleteElements(&pending_select_messages_);
88 } 89 in_shutdown_ = true;
89 90 // As upstream code may depend on acks for currently queued touch events,
90 void InputRouterImpl::Flush() { 91 // explicitly flush the touch queue, dropping any generated gesture events.
91 flush_requested_ = true; 92 touch_event_queue_.Flush(INPUT_EVENT_ACK_STATE_CONSUMED);
92 SignalFlushedIfNecessary(); 93 if (flush_requested_) {
94 flush_requested_ = false;
95 client_->DidFlush();
96 }
93 } 97 }
94 98
95 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { 99 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) {
96 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); 100 DCHECK(!in_shutdown_);
101 DCHECK_EQ(IPC_MESSAGE_ID_CLASS(message->type()),
102 static_cast<uint32>(InputMsgStart));
97 switch (message->type()) { 103 switch (message->type()) {
98 // Check for types that require an ACK. 104 // Check for types that require an ACK.
99 case InputMsg_SelectRange::ID: 105 case InputMsg_SelectRange::ID:
100 case InputMsg_MoveRangeSelectionExtent::ID: 106 case InputMsg_MoveRangeSelectionExtent::ID:
101 return SendSelectMessage(message.Pass()); 107 return SendSelectMessage(message.Pass());
102 case InputMsg_MoveCaret::ID: 108 case InputMsg_MoveCaret::ID:
103 return SendMoveCaret(message.Pass()); 109 return SendMoveCaret(message.Pass());
104 case InputMsg_HandleInputEvent::ID: 110 case InputMsg_HandleInputEvent::ID:
105 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; 111 NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
106 return false; 112 return false;
107 default: 113 default:
108 return Send(message.release()); 114 return Send(message.release());
109 } 115 }
110 } 116 }
111 117
112 void InputRouterImpl::SendMouseEvent( 118 void InputRouterImpl::SendMouseEvent(
113 const MouseEventWithLatencyInfo& mouse_event) { 119 const MouseEventWithLatencyInfo& mouse_event) {
120 DCHECK(!in_shutdown_);
114 if (mouse_event.event.type == WebInputEvent::MouseDown && 121 if (mouse_event.event.type == WebInputEvent::MouseDown &&
115 gesture_event_queue_.GetTouchpadTapSuppressionController()-> 122 gesture_event_queue_.GetTouchpadTapSuppressionController()->
116 ShouldDeferMouseDown(mouse_event)) 123 ShouldDeferMouseDown(mouse_event))
117 return; 124 return;
118 if (mouse_event.event.type == WebInputEvent::MouseUp && 125 if (mouse_event.event.type == WebInputEvent::MouseUp &&
119 gesture_event_queue_.GetTouchpadTapSuppressionController()-> 126 gesture_event_queue_.GetTouchpadTapSuppressionController()->
120 ShouldSuppressMouseUp()) 127 ShouldSuppressMouseUp())
121 return; 128 return;
122 129
123 SendMouseEventImmediately(mouse_event); 130 SendMouseEventImmediately(mouse_event);
124 } 131 }
125 132
126 void InputRouterImpl::SendWheelEvent( 133 void InputRouterImpl::SendWheelEvent(
127 const MouseWheelEventWithLatencyInfo& wheel_event) { 134 const MouseWheelEventWithLatencyInfo& wheel_event) {
135 DCHECK(!in_shutdown_);
128 SendWheelEvent(QueuedWheelEvent(wheel_event, false)); 136 SendWheelEvent(QueuedWheelEvent(wheel_event, false));
129 } 137 }
130 138
131 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { 139 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) {
140 DCHECK(!in_shutdown_);
132 if (mouse_wheel_pending_) { 141 if (mouse_wheel_pending_) {
133 // If there's already a mouse wheel event waiting to be sent to the 142 // If there's already a mouse wheel event waiting to be sent to the
134 // renderer, add the new deltas to that event. Not doing so (e.g., by 143 // renderer, add the new deltas to that event. Not doing so (e.g., by
135 // dropping the old event, as for mouse moves) results in very slow 144 // dropping the old event, as for mouse moves) results in very slow
136 // scrolling on the Mac (on which many, very small wheel events are sent). 145 // scrolling on the Mac (on which many, very small wheel events are sent).
137 // Note that we can't coalesce wheel events for pinches because the GEQ 146 // Note that we can't coalesce wheel events for pinches because the GEQ
138 // expects one ACK for each (but it's fine to coalesce non-pinch wheels 147 // expects one ACK for each (but it's fine to coalesce non-pinch wheels
139 // into a pinch one). Note that the GestureEventQueue ensures we only 148 // into a pinch one). Note that the GestureEventQueue ensures we only
140 // ever have a single pinch event queued here. 149 // ever have a single pinch event queued here.
141 if (coalesced_mouse_wheel_events_.empty() || 150 if (coalesced_mouse_wheel_events_.empty() ||
(...skipping 14 matching lines...) Expand all
156 LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", 165 LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
157 coalesced_mouse_wheel_events_.size()); 166 coalesced_mouse_wheel_events_.size());
158 167
159 FilterAndSendWebInputEvent( 168 FilterAndSendWebInputEvent(
160 wheel_event.event.event, wheel_event.event.latency, false); 169 wheel_event.event.event, wheel_event.event.latency, false);
161 } 170 }
162 171
163 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, 172 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
164 const ui::LatencyInfo& latency_info, 173 const ui::LatencyInfo& latency_info,
165 bool is_keyboard_shortcut) { 174 bool is_keyboard_shortcut) {
175 DCHECK(!in_shutdown_);
166 // Put all WebKeyboardEvent objects in a queue since we can't trust the 176 // Put all WebKeyboardEvent objects in a queue since we can't trust the
167 // renderer and we need to give something to the HandleKeyboardEvent 177 // renderer and we need to give something to the HandleKeyboardEvent
168 // handler. 178 // handler.
169 key_queue_.push_back(key_event); 179 key_queue_.push_back(key_event);
170 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); 180 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
171 181
172 gesture_event_queue_.FlingHasBeenHalted(); 182 gesture_event_queue_.FlingHasBeenHalted();
173 183
174 // Only forward the non-native portions of our event. 184 // Only forward the non-native portions of our event.
175 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); 185 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut);
176 } 186 }
177 187
178 void InputRouterImpl::SendGestureEvent( 188 void InputRouterImpl::SendGestureEvent(
179 const GestureEventWithLatencyInfo& original_gesture_event) { 189 const GestureEventWithLatencyInfo& original_gesture_event) {
190 if (in_shutdown_)
191 return;
192
180 input_stream_validator_.Validate(original_gesture_event.event); 193 input_stream_validator_.Validate(original_gesture_event.event);
181 194
182 GestureEventWithLatencyInfo gesture_event(original_gesture_event); 195 GestureEventWithLatencyInfo gesture_event(original_gesture_event);
183 196
184 if (touch_action_filter_.FilterGestureEvent(&gesture_event.event)) 197 if (touch_action_filter_.FilterGestureEvent(&gesture_event.event))
185 return; 198 return;
186 199
187 if (gesture_event.event.sourceDevice == blink::WebGestureDeviceTouchscreen) 200 if (gesture_event.event.sourceDevice == blink::WebGestureDeviceTouchscreen)
188 touch_event_queue_.OnGestureScrollEvent(gesture_event); 201 touch_event_queue_.OnGestureScrollEvent(gesture_event);
189 202
190 if (!gesture_event_queue_.ShouldForward(gesture_event)) 203 if (!gesture_event_queue_.ShouldForward(gesture_event))
191 return; 204 return;
192 205
193 SendGestureEventImmediately(gesture_event); 206 SendGestureEventImmediately(gesture_event);
194 } 207 }
195 208
196 void InputRouterImpl::SendTouchEvent( 209 void InputRouterImpl::SendTouchEvent(
197 const TouchEventWithLatencyInfo& touch_event) { 210 const TouchEventWithLatencyInfo& touch_event) {
211 DCHECK(!in_shutdown_);
198 input_stream_validator_.Validate(touch_event.event); 212 input_stream_validator_.Validate(touch_event.event);
199 touch_event_queue_.QueueEvent(touch_event); 213 touch_event_queue_.QueueEvent(touch_event);
200 } 214 }
201 215
216 void InputRouterImpl::RequestFlushedNotification() {
217 flush_requested_ = true;
218 SignalFlushedIfNecessary();
219 }
220
202 // Forwards MouseEvent without passing it through 221 // Forwards MouseEvent without passing it through
203 // TouchpadTapSuppressionController. 222 // TouchpadTapSuppressionController.
204 void InputRouterImpl::SendMouseEventImmediately( 223 void InputRouterImpl::SendMouseEventImmediately(
205 const MouseEventWithLatencyInfo& mouse_event) { 224 const MouseEventWithLatencyInfo& mouse_event) {
206 // Avoid spamming the renderer with mouse move events. It is important 225 // Avoid spamming the renderer with mouse move events. It is important
207 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our 226 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
208 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way 227 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
209 // more WM_MOUSEMOVE events than we wish to send to the renderer. 228 // more WM_MOUSEMOVE events than we wish to send to the renderer.
210 if (mouse_event.event.type == WebInputEvent::MouseMove) { 229 if (mouse_event.event.type == WebInputEvent::MouseMove) {
211 if (mouse_move_pending_) { 230 if (mouse_move_pending_) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 338
320 pending_select_messages_.push_back(message.release()); 339 pending_select_messages_.push_back(message.release());
321 return true; 340 return true;
322 } 341 }
323 342
324 select_message_pending_ = true; 343 select_message_pending_ = true;
325 return Send(message.release()); 344 return Send(message.release());
326 } 345 }
327 346
328 bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) { 347 bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) {
329 DCHECK(message->type() == InputMsg_MoveCaret::ID); 348 DCHECK_EQ(message->type(), static_cast<uint32>(InputMsg_MoveCaret::ID));
330 if (move_caret_pending_) { 349 if (move_caret_pending_) {
331 next_move_caret_ = message.Pass(); 350 next_move_caret_ = message.Pass();
332 return true; 351 return true;
333 } 352 }
334 353
335 move_caret_pending_ = true; 354 move_caret_pending_ = true;
336 return Send(message.release()); 355 return Send(message.release());
337 } 356 }
338 357
339 bool InputRouterImpl::Send(IPC::Message* message) { 358 bool InputRouterImpl::Send(IPC::Message* message) {
(...skipping 11 matching lines...) Expand all
351 370
352 // Any input event cancels a pending mouse move event. 371 // Any input event cancels a pending mouse move event.
353 next_mouse_move_.reset(); 372 next_mouse_move_.reset();
354 373
355 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); 374 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut);
356 } 375 }
357 376
358 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, 377 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
359 const ui::LatencyInfo& latency_info, 378 const ui::LatencyInfo& latency_info,
360 bool is_keyboard_shortcut) { 379 bool is_keyboard_shortcut) {
380 DCHECK(!in_shutdown_);
361 output_stream_validator_.Validate(input_event); 381 output_stream_validator_.Validate(input_event);
362 382
363 if (OfferToClient(input_event, latency_info)) 383 if (OfferToClient(input_event, latency_info))
364 return; 384 return;
365 385
366 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); 386 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut);
367 387
368 // Touch events should always indicate in the event whether they are 388 // Touch events should always indicate in the event whether they are
369 // cancelable (respect ACK disposition) or not. 389 // cancelable (respect ACK disposition) or not.
370 bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event); 390 bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 // Lack of a touch handler indicates that the page either has no touch-action 541 // Lack of a touch handler indicates that the page either has no touch-action
522 // modifiers or that all its touch-action modifiers are auto. Resetting the 542 // modifiers or that all its touch-action modifiers are auto. Resetting the
523 // touch-action here allows forwarding of subsequent gestures even if the 543 // touch-action here allows forwarding of subsequent gestures even if the
524 // underlying touches never reach the router. 544 // underlying touches never reach the router.
525 // TODO(jdduke): Reset touch-action only at the end of a touch sequence to 545 // TODO(jdduke): Reset touch-action only at the end of a touch sequence to
526 // prevent potentially strange mid-sequence behavior, crbug.com/375940. 546 // prevent potentially strange mid-sequence behavior, crbug.com/375940.
527 if (!has_handlers) 547 if (!has_handlers)
528 touch_action_filter_.ResetTouchAction(); 548 touch_action_filter_.ResetTouchAction();
529 549
530 touch_event_queue_.OnHasTouchEventHandlers(has_handlers); 550 touch_event_queue_.OnHasTouchEventHandlers(has_handlers);
531 client_->OnHasTouchEventHandlers(has_handlers);
532 } 551 }
533 552
534 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { 553 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) {
535 // Synthetic touchstart events should get filtered out in RenderWidget. 554 // Synthetic touchstart events should get filtered out in RenderWidget.
536 DCHECK(touch_event_queue_.IsPendingAckTouchStart()); 555 DCHECK(touch_event_queue_.IsPendingAckTouchStart());
537 TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", 556 TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction",
538 "action", touch_action); 557 "action", touch_action);
539 558
540 touch_action_filter_.OnSetTouchAction(touch_action); 559 touch_action_filter_.OnSetTouchAction(touch_action);
541 560
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 ProcessGestureAck(event_type, ack_result, latency_info); 593 ProcessGestureAck(event_type, ack_result, latency_info);
575 } else if (event_type != WebInputEvent::Undefined) { 594 } else if (event_type != WebInputEvent::Undefined) {
576 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); 595 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
577 } 596 }
578 597
579 SignalFlushedIfNecessary(); 598 SignalFlushedIfNecessary();
580 } 599 }
581 600
582 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, 601 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
583 InputEventAckState ack_result) { 602 InputEventAckState ack_result) {
584 if (key_queue_.empty()) { 603 if (key_queue_.empty())
585 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK); 604 return;
586 } else if (key_queue_.front().type != type) { 605
606 if (key_queue_.front().type != type) {
587 // Something must be wrong. Clear the |key_queue_| and char event 607 // Something must be wrong. Clear the |key_queue_| and char event
588 // suppression so that we can resume from the error. 608 // suppression so that we can resume from the error.
589 key_queue_.clear(); 609 key_queue_.clear();
590 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE); 610 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
591 } else { 611 } else {
592 NativeWebKeyboardEvent front_item = key_queue_.front(); 612 NativeWebKeyboardEvent front_item = key_queue_.front();
593 key_queue_.pop_front(); 613 key_queue_.pop_front();
594 614
595 ack_handler_->OnKeyboardEventAck(front_item, ack_result); 615 ack_handler_->OnKeyboardEventAck(front_item, ack_result);
596 // WARNING: This InputRouterImpl can be deallocated at this point 616 // WARNING: This InputRouterImpl can be deallocated at this point
597 // (i.e. in the case of Ctrl+W, where the call to 617 // (i.e. in the case of Ctrl+W, where the call to
598 // HandleKeyboardEvent destroys this InputRouterImpl). 618 // HandleKeyboardEvent destroys this InputRouterImpl).
599 // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async. 619 // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async.
600 } 620 }
601 } 621 }
602 622
603 void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type, 623 void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
604 InputEventAckState ack_result) { 624 InputEventAckState ack_result) {
605 if (type != WebInputEvent::MouseMove) 625 if (type != WebInputEvent::MouseMove)
606 return; 626 return;
607 627
608 DCHECK(mouse_move_pending_);
609 mouse_move_pending_ = false; 628 mouse_move_pending_ = false;
610 629
611 if (next_mouse_move_) { 630 if (next_mouse_move_) {
612 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); 631 DCHECK_EQ(next_mouse_move_->event.type, WebInputEvent::MouseMove);
613 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move 632 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move
614 = next_mouse_move_.Pass(); 633 = next_mouse_move_.Pass();
615 SendMouseEvent(*next_mouse_move); 634 SendMouseEvent(*next_mouse_move);
616 } 635 }
617 } 636 }
618 637
619 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, 638 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result,
620 const ui::LatencyInfo& latency) { 639 const ui::LatencyInfo& latency) {
621 // TODO(miletus): Add renderer side latency to each uncoalesced mouse 640 // TODO(miletus): Add renderer side latency to each uncoalesced mouse
622 // wheel event and add terminal component to each of them. 641 // wheel event and add terminal component to each of them.
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent( 730 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent(
712 const MouseWheelEventWithLatencyInfo& event, 731 const MouseWheelEventWithLatencyInfo& event,
713 bool synthesized_from_pinch) 732 bool synthesized_from_pinch)
714 : event(event), synthesized_from_pinch(synthesized_from_pinch) { 733 : event(event), synthesized_from_pinch(synthesized_from_pinch) {
715 } 734 }
716 735
717 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() { 736 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() {
718 } 737 }
719 738
720 } // namespace content 739 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698