| Index: content/browser/renderer_host/input/touch_event_queue_unittest.cc
|
| diff --git a/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/content/browser/renderer_host/input/touch_event_queue_unittest.cc
|
| index 3e756566eda2d0b852c2cc7d012f7181a5901a3c..04534a176e729a3883ece67ab974c58d46af86cd 100644
|
| --- a/content/browser/renderer_host/input/touch_event_queue_unittest.cc
|
| +++ b/content/browser/renderer_host/input/touch_event_queue_unittest.cc
|
| @@ -5,6 +5,8 @@
|
| #include "base/basictypes.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "content/browser/renderer_host/input/timeout_monitor.h"
|
| #include "content/browser/renderer_host/input/touch_event_queue.h"
|
| #include "content/common/input/synthetic_web_input_event_builders.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| @@ -16,6 +18,9 @@ using blink::WebTouchEvent;
|
| using blink::WebTouchPoint;
|
|
|
| namespace content {
|
| +namespace {
|
| +const size_t kDefaultTouchTimeoutDelayMs = 10;
|
| +}
|
|
|
| class TouchEventQueueTest : public testing::Test,
|
| public TouchEventQueueClient {
|
| @@ -67,6 +72,10 @@ class TouchEventQueueTest : public testing::Test,
|
|
|
| protected:
|
|
|
| + void SetUpForTimeoutTesting(size_t timeout_delay_ms) {
|
| + queue_->SetAckTimeoutEnabled(true, timeout_delay_ms);
|
| + }
|
| +
|
| void SendTouchEvent(const WebTouchEvent& event) {
|
| queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo()));
|
| }
|
| @@ -131,12 +140,24 @@ class TouchEventQueueTest : public testing::Test,
|
| queue_->FlushQueue();
|
| }
|
|
|
| + void SetEnableTouchForwarding(bool enabled) {
|
| + queue_->no_touch_to_renderer_ = !enabled;
|
| + }
|
| +
|
| + bool WillForwardTouchEvents() {
|
| + return !queue_->no_touch_to_renderer_ && !queue_->HasTimeoutEvent();
|
| + }
|
| +
|
| + bool IsTimeoutRunning() {
|
| + return queue_->IsTimeoutRunningForTesting();
|
| + }
|
| +
|
| size_t queued_event_count() const {
|
| - return queue_->GetQueueSize();
|
| + return queue_->size();
|
| }
|
|
|
| const WebTouchEvent& latest_event() const {
|
| - return queue_->GetLatestEvent().event;
|
| + return queue_->GetLatestEventForTesting().event;
|
| }
|
|
|
| const WebTouchEvent& acked_event() const {
|
| @@ -170,6 +191,7 @@ class TouchEventQueueTest : public testing::Test,
|
| scoped_ptr<WebTouchEvent> followup_touch_event_;
|
| scoped_ptr<WebGestureEvent> followup_gesture_event_;
|
| scoped_ptr<InputEventAckState> sync_ack_result_;
|
| + base::MessageLoopForUI message_loop_;
|
| };
|
|
|
|
|
| @@ -707,7 +729,7 @@ TEST_F(TouchEventQueueTest, ImmediateAckWithFollowupEvents) {
|
| // Tests basic TouchEvent forwarding suppression.
|
| TEST_F(TouchEventQueueTest, NoTouchBasic) {
|
| // Disable TouchEvent forwarding.
|
| - set_no_touch_to_renderer(true);
|
| + SetEnableTouchForwarding(false);
|
| MoveTouchPoint(0, 30, 5);
|
| SendTouchEvent();
|
| EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| @@ -732,7 +754,7 @@ TEST_F(TouchEventQueueTest, NoTouchBasic) {
|
| EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
|
|
| // Enable TouchEvent forwarding.
|
| - set_no_touch_to_renderer(false);
|
| + SetEnableTouchForwarding(true);
|
|
|
| PressTouchPoint(80, 10);
|
| SendTouchEvent();
|
| @@ -778,9 +800,9 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
|
| WebGestureEvent followup_scroll;
|
| followup_scroll.type = WebInputEvent::GestureScrollBegin;
|
| SetFollowupEvent(followup_scroll);
|
| - ASSERT_FALSE(no_touch_to_renderer());
|
| + ASSERT_TRUE(WillForwardTouchEvents());
|
| SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| - EXPECT_TRUE(no_touch_to_renderer());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| EXPECT_EQ(2U, queued_event_count());
|
| @@ -794,7 +816,7 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
|
| EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
|
|
|
| - // TouchMove should not be sent to renderer.
|
| + // TouchMove should not be sent to the renderer.
|
| MoveTouchPoint(0, 30, 5);
|
| SendTouchEvent();
|
| EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| @@ -803,9 +825,9 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
|
|
|
| // GestureScrollUpdates should not change affect touch forwarding.
|
| SendGestureEvent(WebInputEvent::GestureScrollUpdate);
|
| - EXPECT_TRUE(no_touch_to_renderer());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
|
|
| - // TouchEnd should not be sent to renderer.
|
| + // TouchEnd should not be sent to the renderer.
|
| ReleaseTouchPoint(0);
|
| SendTouchEvent();
|
| EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| @@ -814,7 +836,7 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
|
|
|
| // GestureScrollEnd will resume the sending of TouchEvents to renderer.
|
| SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
|
| - EXPECT_FALSE(no_touch_to_renderer());
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
|
|
| // Now TouchEvents should be forwarded normally.
|
| PressTouchPoint(80, 10);
|
| @@ -836,4 +858,262 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
|
| EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| }
|
|
|
| +// Tests that the touch timeout is started when sending certain touch types.
|
| +TEST_F(TouchEventQueueTest, TouchTimeoutTypes) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Sending a TouchStart will start the timeout.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +
|
| + // A TouchMove should start the timeout.
|
| + MoveTouchPoint(0, 5, 5);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +
|
| + // A TouchEnd should not start the timeout.
|
| + ReleaseTouchPoint(0);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +
|
| + // A TouchCancel should not start the timeout.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + ASSERT_FALSE(IsTimeoutRunning());
|
| + CancelTouchPoint(0);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +}
|
| +
|
| +// Tests that a delayed TouchEvent ack will trigger a TouchCancel timeout,
|
| +// disabling touch forwarding until the next TouchStart is received after
|
| +// the timeout events are ack'ed.
|
| +TEST_F(TouchEventQueueTest, TouchTimeoutBasic) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Queue a TouchStart.
|
| + GetAndResetSentEventCount();
|
| + GetAndResetAckedEventCount();
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + ASSERT_EQ(1U, GetAndResetSentEventCount());
|
| + ASSERT_EQ(0U, GetAndResetAckedEventCount());
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
| +
|
| + // Delay the ack.
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::MessageLoop::QuitClosure(),
|
| + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
|
| + base::MessageLoop::current()->Run();
|
| +
|
| + // The timeout should have fired, sending a TouchCancel and ack'ing the
|
| + // TouchStart immediately. TouchEvent forwarding is disabled until both
|
| + // acks are received.
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Ack'ing the original event should have no effect; we're still waiting
|
| + // on the cancel ack.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| + EXPECT_EQ(0U, GetAndResetAckedEventCount());
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| +
|
| + // Touch events should not be forwarded until we receive the original acks.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + ASSERT_EQ(0U, GetAndResetSentEventCount());
|
| + ASSERT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // The synthetic TouchCancel ack should not reach the client, but should
|
| + // resume touch forwarding.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(0U, GetAndResetAckedEventCount());
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
| +
|
| + // Subsequent events should be handled normally.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(0U, GetAndResetAckedEventCount());
|
| +}
|
| +
|
| +// Tests that the timeout is never started if the renderer consumes
|
| +// a TouchEvent from the current touch sequence.
|
| +TEST_F(TouchEventQueueTest, NoTouchTimeoutIfRendererIsConsumingGesture) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Queue a TouchStart.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + ASSERT_TRUE(IsTimeoutRunning());
|
| +
|
| + // Mark the event as consumed. This should prevent the timeout from
|
| + // being activated on subsequent TouchEvents in this gesture.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +
|
| + // A TouchMove should not start the timeout.
|
| + MoveTouchPoint(0, 5, 5);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| +
|
| + // A TouchCancel should not start the timeout.
|
| + CancelTouchPoint(0);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +}
|
| +
|
| +// Tests that the timeout is never started if the ack is synchronous.
|
| +TEST_F(TouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Queue a TouchStart.
|
| + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + ASSERT_FALSE(IsTimeoutRunning());
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| +}
|
| +
|
| +// Tests that a TouchCancel timeout plays nice when the timed out touch stream
|
| +// turns into a scroll gesture sequence.
|
| +TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGesture) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Queue a TouchStart.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| +
|
| + // The cancelled sequence may turn into a scroll gesture.
|
| + WebGestureEvent followup_scroll;
|
| + followup_scroll.type = WebInputEvent::GestureScrollBegin;
|
| + SetFollowupEvent(followup_scroll);
|
| +
|
| + // Delay the ack.
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::MessageLoop::QuitClosure(),
|
| + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
|
| + base::MessageLoop::current()->Run();
|
| +
|
| + // The timeout should have fired, disabling touch forwarding until both acks
|
| + // are received, acking the timed out event, and forwarding a TouchCancel.
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Ack the original event.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| +
|
| + // Ack the cancel event. Normally, this would resume touch forwarding,
|
| + // but we're still within a scroll gesture so it remains disabled.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| +
|
| + // Try to forward a touch event.
|
| + GetAndResetSentEventCount();
|
| + GetAndResetAckedEventCount();
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Now end the scroll sequence, resuming touch handling.
|
| + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(0U, GetAndResetAckedEventCount());
|
| +}
|
| +
|
| +// Tests that a TouchCancel timeout plays nice when the timed out touch stream
|
| +// turns into a scroll gesture sequence, but the original event acks are
|
| +// significantly delayed.
|
| +TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGestureAndDelayedAck) {
|
| + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
|
| +
|
| + // Queue a TouchStart.
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + EXPECT_TRUE(WillForwardTouchEvents());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| +
|
| + // The cancelled sequence may turn into a scroll gesture.
|
| + WebGestureEvent followup_scroll;
|
| + followup_scroll.type = WebInputEvent::GestureScrollBegin;
|
| + SetFollowupEvent(followup_scroll);
|
| +
|
| + // Delay the ack.
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::MessageLoop::QuitClosure(),
|
| + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
|
| + base::MessageLoop::current()->Run();
|
| +
|
| + // The timeout should have fired, disabling touch forwarding until both acks
|
| + // are received, acking the timed out event, and forwarding a TouchCancel.
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_FALSE(WillForwardTouchEvents());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Try to forward a touch event.
|
| + GetAndResetSentEventCount();
|
| + GetAndResetAckedEventCount();
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Now end the scroll sequence. Events will not be forwarded until the two
|
| + // outstanding touch acks are received.
|
| + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_FALSE(IsTimeoutRunning());
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(1U, GetAndResetAckedEventCount());
|
| +
|
| + // Ack the original and cancel events. Events will now be forwarded.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentEventCount());
|
| + EXPECT_EQ(0U, GetAndResetAckedEventCount());
|
| +
|
| + PressTouchPoint(0, 1);
|
| + SendTouchEvent();
|
| + EXPECT_TRUE(IsTimeoutRunning());
|
| + EXPECT_EQ(1U, GetAndResetSentEventCount());
|
| +}
|
| +
|
| } // namespace content
|
|
|