| Index: content/browser/renderer_host/render_widget_host_unittest.cc
|
| diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
|
| index 8f271105ad7da0a2b48b5a992cb27bf2d1fa6105..7b7a560bca7f11319c3d9fffbe9389dc0591e1f1 100644
|
| --- a/content/browser/renderer_host/render_widget_host_unittest.cc
|
| +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
|
| @@ -11,6 +11,7 @@
|
| #include "content/browser/renderer_host/render_widget_host_delegate.h"
|
| #include "content/browser/renderer_host/gesture_event_filter.h"
|
| #include "content/browser/renderer_host/test_render_view_host.h"
|
| +#include "content/browser/renderer_host/touch_event_queue.h"
|
| #include "content/common/view_messages.h"
|
| #include "content/port/browser/render_widget_host_view_port.h"
|
| #include "content/public/browser/notification_details.h"
|
| @@ -127,7 +128,8 @@ bool RenderWidgetHostProcess::WaitForBackingStoreMsg(
|
|
|
| // TestView --------------------------------------------------------------------
|
|
|
| -// This test view allows us to specify the size.
|
| +// This test view allows us to specify the size, and keep track of acked
|
| +// touch-events.
|
| class TestView : public content::TestRenderWidgetHostView {
|
| public:
|
| explicit TestView(RenderWidgetHostImpl* rwh)
|
| @@ -139,12 +141,23 @@ class TestView : public content::TestRenderWidgetHostView {
|
| bounds_ = bounds;
|
| }
|
|
|
| + const WebKit::WebTouchEvent& acked_event() const { return acked_event_; }
|
| + void ClearAckedEvent() {
|
| + acked_event_.type = WebKit::WebInputEvent::Undefined;
|
| + }
|
| +
|
| // RenderWidgetHostView override.
|
| - virtual gfx::Rect GetViewBounds() const {
|
| + virtual gfx::Rect GetViewBounds() const OVERRIDE {
|
| return bounds_;
|
| }
|
|
|
| + virtual void ProcessAckedTouchEvent(const WebKit::WebTouchEvent& touch,
|
| + bool processed) OVERRIDE {
|
| + acked_event_ = touch;
|
| + }
|
| +
|
| protected:
|
| + WebKit::WebTouchEvent acked_event_;
|
| gfx::Rect bounds_;
|
| DISALLOW_COPY_AND_ASSIGN(TestView);
|
| };
|
| @@ -227,6 +240,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
|
| using RenderWidgetHostImpl::is_hidden_;
|
| using RenderWidgetHostImpl::resize_ack_pending_;
|
| using RenderWidgetHostImpl::gesture_event_filter_;
|
| + using RenderWidgetHostImpl::touch_event_queue_;
|
|
|
| bool unresponsive_timer_fired() const {
|
| return unresponsive_timer_fired_;
|
| @@ -268,6 +282,10 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
|
| gesture_event_filter_->debounce_interval_time_ms_ = delay_ms;
|
| }
|
|
|
| + size_t TouchEventQueueSize() {
|
| + return touch_event_queue_->touch_queue_.size();
|
| + }
|
| +
|
| protected:
|
| virtual void NotifyRendererUnresponsive() OVERRIDE {
|
| unresponsive_timer_fired_ = true;
|
| @@ -398,6 +416,57 @@ class RenderWidgetHostTest : public testing::Test {
|
| host_->ForwardGestureEvent(gesture_event);
|
| }
|
|
|
| + // Sends a touch event (irrespective of whether the page has a touch-event
|
| + // handler or not).
|
| + void SendTouchEvent() {
|
| + host_->ForwardTouchEvent(touch_event_);
|
| +
|
| + // Mark all the points as stationary. And remove the points that have been
|
| + // released.
|
| + int point = 0;
|
| + for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
|
| + if (touch_event_.touches[i].state == WebKit::WebTouchPoint::StateReleased)
|
| + continue;
|
| +
|
| + touch_event_.touches[point] = touch_event_.touches[i];
|
| + touch_event_.touches[point].state =
|
| + WebKit::WebTouchPoint::StateStationary;
|
| + ++point;
|
| + }
|
| + touch_event_.touchesLength = point;
|
| + touch_event_.type = WebInputEvent::Undefined;
|
| + }
|
| +
|
| + int PressTouchPoint(int x, int y) {
|
| + if (touch_event_.touchesLength == touch_event_.touchesLengthCap)
|
| + return -1;
|
| + WebKit::WebTouchPoint& point =
|
| + touch_event_.touches[touch_event_.touchesLength];
|
| + point.id = touch_event_.touchesLength;
|
| + point.position.x = point.screenPosition.x = x;
|
| + point.position.y = point.screenPosition.y = y;
|
| + point.state = WebKit::WebTouchPoint::StatePressed;
|
| + point.radiusX = point.radiusY = 1.f;
|
| + ++touch_event_.touchesLength;
|
| + touch_event_.type = WebInputEvent::TouchStart;
|
| + return point.id;
|
| + }
|
| +
|
| + void MoveTouchPoint(int index, int x, int y) {
|
| + CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
|
| + WebKit::WebTouchPoint& point = touch_event_.touches[index];
|
| + point.position.x = point.screenPosition.x = x;
|
| + point.position.y = point.screenPosition.y = y;
|
| + touch_event_.touches[index].state = WebKit::WebTouchPoint::StateMoved;
|
| + touch_event_.type = WebInputEvent::TouchMove;
|
| + }
|
| +
|
| + void ReleaseTouchPoint(int index) {
|
| + CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
|
| + touch_event_.touches[index].state = WebKit::WebTouchPoint::StateReleased;
|
| + touch_event_.type = WebInputEvent::TouchEnd;
|
| + }
|
| +
|
| MessageLoopForUI message_loop_;
|
|
|
| scoped_ptr<content::TestBrowserContext> browser_context_;
|
| @@ -406,6 +475,9 @@ class RenderWidgetHostTest : public testing::Test {
|
| scoped_ptr<MockRenderWidgetHost> host_;
|
| scoped_ptr<TestView> view_;
|
|
|
| + private:
|
| + WebKit::WebTouchEvent touch_event_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
|
| };
|
|
|
| @@ -1238,6 +1310,113 @@ TEST_F(RenderWidgetHostTest, DebounceDropsDeferredEvents) {
|
| }
|
| }
|
|
|
| +// Tests that touch-events are queued properly.
|
| +TEST_F(RenderWidgetHostTest, TouchEventQueue) {
|
| + process_->sink().ClearMessages();
|
| +
|
| + PressTouchPoint(1, 1);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(1U, process_->sink().message_count());
|
| + process_->sink().ClearMessages();
|
| +
|
| + // The second touch should not be sent since one is already in queue.
|
| + MoveTouchPoint(0, 5, 5);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| +
|
| + EXPECT_EQ(2U, host_->TouchEventQueueSize());
|
| +
|
| + // Receive an ACK for the first touch-event.
|
| + SendInputEventACK(WebInputEvent::TouchStart, true);
|
| + EXPECT_EQ(1U, host_->TouchEventQueueSize());
|
| + EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->acked_event().type);
|
| + EXPECT_EQ(1U, process_->sink().message_count());
|
| + process_->sink().ClearMessages();
|
| +
|
| + SendInputEventACK(WebInputEvent::TouchMove, true);
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| + EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->acked_event().type);
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| +}
|
| +
|
| +// Tests that the touch-queue is emptied if a page stops listening for touch
|
| +// events.
|
| +TEST_F(RenderWidgetHostTest, TouchEventQueueFlush) {
|
| + process_->sink().ClearMessages();
|
| +
|
| + host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| +
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| + EXPECT_TRUE(host_->ShouldForwardTouchEvent());
|
| +
|
| + // Send a touch-press event.
|
| + PressTouchPoint(1, 1);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(1U, process_->sink().message_count());
|
| + process_->sink().ClearMessages();
|
| +
|
| + ReleaseTouchPoint(0);
|
| + SendTouchEvent();
|
| +
|
| + for (int i = 5; i < 15; ++i) {
|
| + PressTouchPoint(1, 1);
|
| + SendTouchEvent();
|
| + MoveTouchPoint(0, i, i);
|
| + SendTouchEvent();
|
| + ReleaseTouchPoint(0);
|
| + SendTouchEvent();
|
| + }
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| + EXPECT_EQ(32U, host_->TouchEventQueueSize());
|
| +
|
| + // Receive an ACK for the first touch-event. One of the queued touch-event
|
| + // should be forwarded.
|
| + SendInputEventACK(WebInputEvent::TouchStart, true);
|
| + EXPECT_EQ(31U, host_->TouchEventQueueSize());
|
| + EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->acked_event().type);
|
| + EXPECT_EQ(1U, process_->sink().message_count());
|
| + process_->sink().ClearMessages();
|
| +
|
| + // The page stops listening for touch-events. The touch-event queue should now
|
| + // be emptied, but none of the queued touch-events should be sent to the
|
| + // renderer.
|
| + host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| + EXPECT_FALSE(host_->ShouldForwardTouchEvent());
|
| +}
|
| +
|
| +// Tests that touch-events are coalesced properly in the queue.
|
| +TEST_F(RenderWidgetHostTest, TouchEventQueueCoalesce) {
|
| + process_->sink().ClearMessages();
|
| +
|
| + host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| +
|
| + EXPECT_EQ(0U, host_->TouchEventQueueSize());
|
| + EXPECT_TRUE(host_->ShouldForwardTouchEvent());
|
| +
|
| + // Send a touch-press event.
|
| + PressTouchPoint(1, 1);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(1U, process_->sink().message_count());
|
| + process_->sink().ClearMessages();
|
| +
|
| + // Send a few touch-move events, followed by a touch-release event. All the
|
| + // touch-move events should be coalesced into a single event.
|
| + for (int i = 5; i < 15; ++i) {
|
| + MoveTouchPoint(0, i, i);
|
| + SendTouchEvent();
|
| + }
|
| + ReleaseTouchPoint(0);
|
| + SendTouchEvent();
|
| + EXPECT_EQ(0U, process_->sink().message_count());
|
| + EXPECT_EQ(3U, host_->TouchEventQueueSize());
|
| +}
|
| +
|
| // Test that the hang monitor timer expires properly if a new timer is started
|
| // while one is in progress (see crbug.com/11007).
|
| TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
|
|
|