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

Unified Diff: content/browser/renderer_host/input/touch_event_queue.cc

Issue 130993003: Prevent partial touch sequences from reaching the renderer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test Created 6 years, 11 months 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/touch_event_queue.cc
diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc
index 5921521e8ce0b2115106fad05b9561420f0aba6f..909f105bae4ab96b525a42476af2ee0368acd9bb 100644
--- a/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/content/browser/renderer_host/input/touch_event_queue.cc
@@ -80,8 +80,6 @@ class TouchEventQueue::TouchTimeoutHandler {
SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
TouchEventWithLatencyInfo cancel_event =
ObtainCancelEventForTouchEvent(timeout_event_);
- touch_queue_->UpdateTouchAckStates(
- cancel_event.event, kDefaultNotForwardedAck);
touch_queue_->client_->SendTouchEventImmediately(cancel_event);
} else {
SetPendingAckState(PENDING_ACK_NONE);
@@ -241,9 +239,7 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
: client_(client),
dispatching_touch_ack_(NULL),
dispatching_touch_(false),
- has_handlers_(false),
- scroll_in_progress_(false),
- renderer_is_consuming_touch_gesture_(false),
+ touch_handling_state_(TOUCH_HANDLING_STATE_DEFAULT),
ack_timeout_enabled_(false) {
DCHECK(client);
}
@@ -256,7 +252,7 @@ TouchEventQueue::~TouchEventQueue() {
void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
// Optimization of the case without touch handlers. Removing this path
// yields identical results, but this avoids unnecessary allocations.
- if (!has_handlers_) {
+ if (touch_handling_state_ == NO_TOUCH_HANDLER) {
DCHECK(touch_queue_.empty());
client_->OnTouchEventAck(event, kDefaultNotForwardedAck);
return;
@@ -294,7 +290,7 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
return;
if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
- renderer_is_consuming_touch_gesture_ = true;
+ touch_handling_state_ = RENDERER_CONSUMING_GESTURE;
const WebTouchEvent& acked_event =
touch_queue_.front()->coalesced_event().event;
@@ -310,10 +306,6 @@ void TouchEventQueue::TryForwardNextEventToRenderer() {
while (!touch_queue_.empty()) {
const TouchEventWithLatencyInfo& touch =
touch_queue_.front()->coalesced_event();
- if (IsNewTouchGesture(touch.event)) {
- touch_ack_states_.clear();
- renderer_is_consuming_touch_gesture_ = false;
- }
if (ShouldForwardToRenderer(touch.event)) {
ForwardToRenderer(touch);
break;
@@ -325,13 +317,20 @@ void TouchEventQueue::TryForwardNextEventToRenderer() {
void TouchEventQueue::ForwardToRenderer(
const TouchEventWithLatencyInfo& touch) {
DCHECK(!dispatching_touch_);
+ DCHECK_NE(touch_handling_state_, NO_TOUCH_HANDLER);
+
+ if (IsNewTouchGesture(touch.event)) {
+ touch_handling_state_ = HAS_TOUCH_HANDLER;
+ touch_ack_states_.clear();
+ }
+
// A synchronous ack will reset |dispatching_touch_|, in which case
// the touch timeout should not be started.
base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
client_->SendTouchEventImmediately(touch);
if (ack_timeout_enabled_ &&
dispatching_touch_ &&
- !renderer_is_consuming_touch_gesture_ &&
+ touch_handling_state_ != RENDERER_CONSUMING_GESTURE &&
ShouldTouchTypeTriggerTimeout(touch.event.type)) {
DCHECK(timeout_handler_);
timeout_handler_->Start(touch);
@@ -340,59 +339,56 @@ void TouchEventQueue::ForwardToRenderer(
void TouchEventQueue::OnGestureScrollEvent(
const GestureEventWithLatencyInfo& gesture_event) {
- blink::WebInputEvent::Type type = gesture_event.event.type;
- if (type == blink::WebInputEvent::GestureScrollBegin) {
- // We assume the scroll event are generated synchronously from
- // dispatching a touch event ack, so that we can fake a cancel
- // event that has the correct touch ids as the touch event that
- // is being acked. If not, we don't do the touch-cancel optimization.
- if (scroll_in_progress_ || !dispatching_touch_ack_)
- return;
- scroll_in_progress_ = true;
+ if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin)
+ return;
- // If we have a timeout event, a cancel has already been dispatched
- // for the current touch stream.
- if (HasTimeoutEvent())
- return;
+ // We assume the scroll event are generated synchronously from
tdresser 2014/01/17 14:33:40 While you're here, wouldn't hurt to fix "scroll ev
jdduke (slow) 2014/01/17 18:29:07 Done.
+ // dispatching a touch event ack, so that we can fake a cancel
+ // event that has the correct touch ids as the touch event that
+ // is being acked. If not, we don't do the touch-cancel optimization.
+ if (!dispatching_touch_ack_)
+ return;
- // Fake a TouchCancel to cancel the touch points of the touch event
- // that is currently being acked.
- // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
- // are in the scope of PopTouchEventToClient() and that no touch event
- // in the queue is waiting for ack from renderer. So we can just insert
- // the touch cancel at the beginning of the queue.
- touch_queue_.push_front(new CoalescedWebTouchEvent(
- ObtainCancelEventForTouchEvent(
- dispatching_touch_ack_->coalesced_event()), true));
- } else if (type == blink::WebInputEvent::GestureScrollEnd ||
- type == blink::WebInputEvent::GestureFlingStart) {
- scroll_in_progress_ = false;
- }
+ if (touch_handling_state_ == NO_TOUCH_HANDLER_FOR_GESTURE)
+ return;
+
+ touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE;
+
+ // If we have a timeout event, a cancel has already been dispatched
+ // for the current touch stream.
+ if (HasTimeoutEvent())
+ return;
+
+ // Fake a TouchCancel to cancel the touch points of the touch event
+ // that is currently being acked.
+ // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
+ // are in the scope of PopTouchEventToClient() and that no touch event
+ // in the queue is waiting for ack from renderer. So we can just insert
+ // the touch cancel at the beginning of the queue.
+ touch_queue_.push_front(new CoalescedWebTouchEvent(
+ ObtainCancelEventForTouchEvent(
+ dispatching_touch_ack_->coalesced_event()), true));
}
void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
DCHECK(!dispatching_touch_ack_);
DCHECK(!dispatching_touch_);
- if (has_handlers_ == has_handlers)
- return;
-
- has_handlers_ = has_handlers;
- if (!has_handlers_) {
- // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
- // state tracking.
+ if (has_handlers) {
+ if (touch_handling_state_ == NO_TOUCH_HANDLER) {
+ // If no touch handler was previously registered, ensure that we don't
+ // send a partial gesture to the renderer.
+ DCHECK(touch_queue_.empty());
+ touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE;
+ }
+ } else {
+ touch_handling_state_ = NO_TOUCH_HANDLER;
if (timeout_handler_)
timeout_handler_->Reset();
if (!touch_queue_.empty())
ProcessTouchAck(kDefaultNotForwardedAck, ui::LatencyInfo());
// As there is no touch handler, ack'ing the event should flush the queue.
DCHECK(touch_queue_.empty());
- } else {
- DCHECK(touch_queue_.empty());
- // Prevent a partial sequence from being sent to the renderer.
- TouchPointAckStates::iterator ack_it = touch_ack_states_.begin();
- for (; ack_it != touch_ack_states_.end(); ++ack_it)
- ack_it->second = kDefaultNotForwardedAck;
}
}
@@ -436,6 +432,9 @@ TouchEventQueue::GetLatestEventForTesting() const {
void TouchEventQueue::FlushQueue() {
DCHECK(!dispatching_touch_ack_);
DCHECK(!dispatching_touch_);
+ DCHECK_NE(RENDERER_CONSUMING_GESTURE, touch_handling_state_);
+ if (touch_handling_state_ != NO_TOUCH_HANDLER)
+ touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE;
while (!touch_queue_.empty())
PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
}
@@ -470,12 +469,16 @@ bool TouchEventQueue::ShouldForwardToRenderer(
if (HasTimeoutEvent())
return false;
- if (!has_handlers_)
+ if (touch_handling_state_ == NO_TOUCH_HANDLER)
return false;
- if (scroll_in_progress_ &&
- event.type != blink::WebInputEvent::TouchCancel)
+ if (touch_handling_state_ == NO_TOUCH_HANDLER_FOR_GESTURE) {
+ if (IsNewTouchGesture(event))
+ return true;
+ if (event.type == WebInputEvent::TouchCancel)
+ return true;
return false;
+ }
// Touch press events should always be forwarded to the renderer.
if (event.type == WebInputEvent::TouchStart)

Powered by Google App Engine
This is Rietveld 408576698