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
3// found in the LICENSE file.
4
5#include "content/renderer/input/input_handler_proxy.h"
6
7#include "base/basictypes.h"
8#include "base/memory/scoped_ptr.h"
9#include "cc/base/swap_promise_monitor.h"
10#include "content/renderer/input/input_handler_proxy_client.h"
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "third_party/WebKit/public/platform/WebFloatPoint.h"
14#include "third_party/WebKit/public/platform/WebFloatSize.h"
15#include "third_party/WebKit/public/platform/WebGestureCurve.h"
16#include "third_party/WebKit/public/platform/WebPoint.h"
17#include "third_party/WebKit/public/web/WebInputEvent.h"
18#include "ui/events/latency_info.h"
19
20using blink::WebActiveWheelFlingParameters;
21using blink::WebFloatPoint;
22using blink::WebFloatSize;
23using blink::WebGestureEvent;
24using blink::WebInputEvent;
25using blink::WebMouseWheelEvent;
26using blink::WebPoint;
27using blink::WebSize;
28using blink::WebTouchEvent;
29using blink::WebTouchPoint;
30
31namespace content {
32namespace {
33
34class MockInputHandler : public cc::InputHandler {
35 public:
36  MockInputHandler() {}
37  virtual ~MockInputHandler() {}
38
39  MOCK_METHOD0(PinchGestureBegin, void());
40  MOCK_METHOD2(PinchGestureUpdate,
41               void(float magnify_delta, gfx::Point anchor));
42  MOCK_METHOD0(PinchGestureEnd, void());
43
44  MOCK_METHOD0(ScheduleAnimation, void());
45
46  MOCK_METHOD2(ScrollBegin,
47               ScrollStatus(gfx::Point viewport_point,
48                            cc::InputHandler::ScrollInputType type));
49  MOCK_METHOD2(ScrollBy,
50               bool(gfx::Point viewport_point, gfx::Vector2dF scroll_delta));
51  MOCK_METHOD2(ScrollVerticallyByPage,
52               bool(gfx::Point viewport_point,
53                    cc::ScrollDirection direction));
54  MOCK_METHOD0(ScrollEnd, void());
55  MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
56
57  virtual scoped_ptr<cc::SwapPromiseMonitor>
58    CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE {
59      return scoped_ptr<cc::SwapPromiseMonitor>();
60  }
61
62  virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
63
64  virtual void StartPageScaleAnimation(gfx::Vector2d target_offset,
65                                       bool anchor_point,
66                                       float page_scale,
67                                       base::TimeDelta duration) OVERRIDE {}
68
69  virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {}
70  virtual void MouseMoveAt(gfx::Point mouse_position) OVERRIDE {}
71
72  MOCK_METHOD1(HaveTouchEventHandlersAt,
73               bool(gfx::Point point));
74
75  virtual void SetRootLayerScrollOffsetDelegate(
76      cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
77      OVERRIDE {}
78
79  virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {}
80
81  DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
82};
83
84// A simple WebGestureCurve implementation that flings at a constant velocity
85// indefinitely.
86class FakeWebGestureCurve : public blink::WebGestureCurve {
87 public:
88  FakeWebGestureCurve(const blink::WebFloatPoint& velocity,
89                      const blink::WebSize& cumulative_scroll)
90      : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {}
91
92  virtual ~FakeWebGestureCurve() {}
93
94  // Returns false if curve has finished and can no longer be applied.
95  virtual bool apply(double time, blink::WebGestureCurveTarget* target) {
96    blink::WebSize displacement(velocity_.x * time, velocity_.y * time);
97    blink::WebFloatSize increment(
98        displacement.width - cumulative_scroll_.width,
99        displacement.height - cumulative_scroll_.height);
100    cumulative_scroll_ = displacement;
101    // scrollBy() could delete this curve if the animation is over, so don't
102    // touch any member variables after making that call.
103    target->scrollBy(increment);
104    return true;
105  }
106
107 private:
108  blink::WebFloatPoint velocity_;
109  blink::WebSize cumulative_scroll_;
110
111  DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
112};
113
114class MockInputHandlerProxyClient
115    : public content::InputHandlerProxyClient {
116 public:
117  MockInputHandlerProxyClient() {}
118  virtual ~MockInputHandlerProxyClient() {}
119
120  virtual void WillShutdown() OVERRIDE {}
121
122  MOCK_METHOD1(TransferActiveWheelFlingAnimation,
123               void(const WebActiveWheelFlingParameters&));
124
125  virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
126      int deviceSource,
127      const WebFloatPoint& velocity,
128      const WebSize& cumulative_scroll) OVERRIDE {
129    return new FakeWebGestureCurve(velocity, cumulative_scroll);
130  }
131
132  virtual void DidOverscroll(const cc::DidOverscrollParams& params) {}
133
134 private:
135  DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
136};
137
138class InputHandlerProxyTest : public testing::Test {
139 public:
140  InputHandlerProxyTest()
141      : expected_disposition_(InputHandlerProxy::DID_HANDLE) {
142    input_handler_.reset(
143        new content::InputHandlerProxy(&mock_input_handler_));
144    input_handler_->SetClient(&mock_client_);
145  }
146
147  ~InputHandlerProxyTest() {
148    input_handler_.reset();
149  }
150
151// This is defined as a macro because when an expectation is not satisfied the
152// only output you get
153// out of gmock is the line number that set the expectation.
154#define VERIFY_AND_RESET_MOCKS()                                              \
155  do {                                                                        \
156    testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);          \
157    testing::Mock::VerifyAndClearExpectations(&mock_client_);                 \
158  } while (false)
159
160 protected:
161  testing::StrictMock<MockInputHandler> mock_input_handler_;
162  scoped_ptr<content::InputHandlerProxy> input_handler_;
163  testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
164  WebGestureEvent gesture_;
165
166  InputHandlerProxy::EventDisposition expected_disposition_;
167};
168
169TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) {
170  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
171  WebMouseWheelEvent wheel;
172  wheel.type = WebInputEvent::MouseWheel;
173  wheel.scrollByPage = true;
174
175  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
176  testing::Mock::VerifyAndClearExpectations(&mock_client_);
177}
178
179TEST_F(InputHandlerProxyTest, GestureScrollStarted) {
180  // We shouldn't send any events to the widget for this gesture.
181  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
182  VERIFY_AND_RESET_MOCKS();
183
184  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
185      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
186
187  gesture_.type = WebInputEvent::GestureScrollBegin;
188  EXPECT_EQ(expected_disposition_,input_handler_->HandleInputEvent(gesture_));
189
190  // The event should not be marked as handled if scrolling is not possible.
191  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
192  VERIFY_AND_RESET_MOCKS();
193
194  gesture_.type = WebInputEvent::GestureScrollUpdate;
195  gesture_.data.scrollUpdate.deltaY =
196      -40;  // -Y means scroll down - i.e. in the +Y direction.
197  EXPECT_CALL(mock_input_handler_,
198              ScrollBy(testing::_,
199                       testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
200      .WillOnce(testing::Return(false));
201  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
202
203  // Mark the event as handled if scroll happens.
204  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
205  VERIFY_AND_RESET_MOCKS();
206
207  gesture_.type = WebInputEvent::GestureScrollUpdate;
208  gesture_.data.scrollUpdate.deltaY =
209      -40;  // -Y means scroll down - i.e. in the +Y direction.
210  EXPECT_CALL(mock_input_handler_,
211              ScrollBy(testing::_,
212                       testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
213      .WillOnce(testing::Return(true));
214  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
215
216  VERIFY_AND_RESET_MOCKS();
217
218  gesture_.type = WebInputEvent::GestureScrollEnd;
219  gesture_.data.scrollUpdate.deltaY = 0;
220  EXPECT_CALL(mock_input_handler_, ScrollEnd());
221  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
222}
223
224TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) {
225  // We should send all events to the widget for this gesture.
226  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
227  VERIFY_AND_RESET_MOCKS();
228
229  EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
230      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
231
232  gesture_.type = WebInputEvent::GestureScrollBegin;
233  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
234
235  VERIFY_AND_RESET_MOCKS();
236
237  gesture_.type = WebInputEvent::GestureScrollUpdate;
238  gesture_.data.scrollUpdate.deltaY = 40;
239  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
240
241  VERIFY_AND_RESET_MOCKS();
242
243  gesture_.type = WebInputEvent::GestureScrollEnd;
244  gesture_.data.scrollUpdate.deltaY = 0;
245  EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
246  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
247}
248
249TEST_F(InputHandlerProxyTest, GestureScrollIgnored) {
250  // We shouldn't handle the GestureScrollBegin.
251  // Instead, we should get a DROP_EVENT result, indicating
252  // that we could determine that there's nothing that could scroll or otherwise
253  // react to this gesture sequence and thus we should drop the whole gesture
254  // sequence on the floor, except for the ScrollEnd.
255  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
256  VERIFY_AND_RESET_MOCKS();
257
258  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
259      .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
260
261  gesture_.type = WebInputEvent::GestureScrollBegin;
262  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
263
264  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
265  gesture_.type = WebInputEvent::GestureScrollEnd;
266  EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
267  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
268}
269
270TEST_F(InputHandlerProxyTest, GesturePinch) {
271  // We shouldn't send any events to the widget for this gesture.
272  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
273  VERIFY_AND_RESET_MOCKS();
274
275  gesture_.type = WebInputEvent::GesturePinchBegin;
276  EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
277  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
278
279  VERIFY_AND_RESET_MOCKS();
280
281  gesture_.type = WebInputEvent::GesturePinchUpdate;
282  gesture_.data.pinchUpdate.scale = 1.5;
283  gesture_.x = 7;
284  gesture_.y = 13;
285  EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
286  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
287
288  VERIFY_AND_RESET_MOCKS();
289
290  gesture_.type = WebInputEvent::GesturePinchUpdate;
291  gesture_.data.pinchUpdate.scale = 0.5;
292  gesture_.x = 9;
293  gesture_.y = 6;
294  EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
295  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
296
297  VERIFY_AND_RESET_MOCKS();
298
299  gesture_.type = WebInputEvent::GesturePinchEnd;
300  EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
301  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
302}
303
304TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
305  // Scrolls will start by being sent to the main thread.
306  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
307  VERIFY_AND_RESET_MOCKS();
308
309  EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
310      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
311
312  gesture_.type = WebInputEvent::GestureScrollBegin;
313  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
314
315  VERIFY_AND_RESET_MOCKS();
316
317  gesture_.type = WebInputEvent::GestureScrollUpdate;
318  gesture_.data.scrollUpdate.deltaY = 40;
319  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
320
321  // However, after the pinch gesture starts, they should go to the impl
322  // thread.
323  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
324  VERIFY_AND_RESET_MOCKS();
325
326  gesture_.type = WebInputEvent::GesturePinchBegin;
327  EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
328  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
329
330  VERIFY_AND_RESET_MOCKS();
331
332  gesture_.type = WebInputEvent::GesturePinchUpdate;
333  gesture_.data.pinchUpdate.scale = 1.5;
334  gesture_.x = 7;
335  gesture_.y = 13;
336  EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
337  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
338
339  VERIFY_AND_RESET_MOCKS();
340
341  gesture_.type = WebInputEvent::GestureScrollUpdate;
342  gesture_.data.scrollUpdate.deltaY =
343      -40;  // -Y means scroll down - i.e. in the +Y direction.
344  EXPECT_CALL(mock_input_handler_,
345              ScrollBy(testing::_,
346                       testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
347      .WillOnce(testing::Return(true));
348  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
349
350  VERIFY_AND_RESET_MOCKS();
351
352  gesture_.type = WebInputEvent::GesturePinchUpdate;
353  gesture_.data.pinchUpdate.scale = 0.5;
354  gesture_.x = 9;
355  gesture_.y = 6;
356  EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
357  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
358
359  VERIFY_AND_RESET_MOCKS();
360
361  gesture_.type = WebInputEvent::GesturePinchEnd;
362  EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
363  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
364
365  // After the pinch gesture ends, they should go to back to the main
366  // thread.
367  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
368  VERIFY_AND_RESET_MOCKS();
369
370  gesture_.type = WebInputEvent::GestureScrollEnd;
371  gesture_.data.scrollUpdate.deltaY = 0;
372  EXPECT_CALL(mock_input_handler_, ScrollEnd())
373      .WillOnce(testing::Return());
374  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
375}
376
377TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) {
378  // We shouldn't send any events to the widget for this gesture.
379  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
380  VERIFY_AND_RESET_MOCKS();
381
382  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
383      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
384  EXPECT_CALL(mock_input_handler_, ScrollEnd());
385  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
386
387  gesture_.type = WebInputEvent::GestureFlingStart;
388  gesture_.data.flingStart.velocityX = 10;
389  gesture_.sourceDevice = WebGestureEvent::Touchpad;
390  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
391
392  VERIFY_AND_RESET_MOCKS();
393
394  // Verify that a GestureFlingCancel during an animation cancels it.
395  gesture_.type = WebInputEvent::GestureFlingCancel;
396  gesture_.sourceDevice = WebGestureEvent::Touchpad;
397  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
398}
399
400TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) {
401  // We should send all events to the widget for this gesture.
402  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
403  VERIFY_AND_RESET_MOCKS();
404
405  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
406      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
407
408  gesture_.type = WebInputEvent::GestureFlingStart;
409  gesture_.sourceDevice = WebGestureEvent::Touchpad;
410  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
411
412  // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the
413  // input handler knows it's scrolling off the impl thread
414  ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
415
416  VERIFY_AND_RESET_MOCKS();
417
418  // Even if we didn't start a fling ourselves, we still need to send the cancel
419  // event to the widget.
420  gesture_.type = WebInputEvent::GestureFlingCancel;
421  gesture_.sourceDevice = WebGestureEvent::Touchpad;
422  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
423}
424
425TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) {
426  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
427  VERIFY_AND_RESET_MOCKS();
428
429  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
430      .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
431
432  gesture_.type = WebInputEvent::GestureFlingStart;
433  gesture_.sourceDevice = WebGestureEvent::Touchpad;
434  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
435
436  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
437  VERIFY_AND_RESET_MOCKS();
438
439  // Since the previous fling was ignored, we should also be dropping the next
440  // fling_cancel.
441  gesture_.type = WebInputEvent::GestureFlingCancel;
442  gesture_.sourceDevice = WebGestureEvent::Touchpad;
443  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
444}
445
446TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
447  // We shouldn't send any events to the widget for this gesture.
448  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
449  VERIFY_AND_RESET_MOCKS();
450
451  // On the fling start, we should schedule an animation but not actually start
452  // scrolling.
453  gesture_.type = WebInputEvent::GestureFlingStart;
454  WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
455  WebPoint fling_point = WebPoint(7, 13);
456  WebPoint fling_global_point = WebPoint(17, 23);
457  int modifiers = 7;
458  gesture_.data.flingStart.velocityX = fling_delta.x;
459  gesture_.data.flingStart.velocityY = fling_delta.y;
460  gesture_.sourceDevice = WebGestureEvent::Touchpad;
461  gesture_.x = fling_point.x;
462  gesture_.y = fling_point.y;
463  gesture_.globalX = fling_global_point.x;
464  gesture_.globalY = fling_global_point.y;
465  gesture_.modifiers = modifiers;
466  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
467  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
468      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
469  EXPECT_CALL(mock_input_handler_, ScrollEnd());
470  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
471
472  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
473  // The first animate call should let us pick up an animation start time, but
474  // we shouldn't actually move anywhere just yet. The first frame after the
475  // fling start will typically include the last scroll from the gesture that
476  // lead to the scroll (either wheel or gesture scroll), so there should be no
477  // visible hitch.
478  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
479  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
480      .Times(0);
481  base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
482  input_handler_->Animate(time);
483
484  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
485
486  // The second call should start scrolling in the -X direction.
487  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
488  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
489      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
490  EXPECT_CALL(mock_input_handler_,
491              ScrollBy(testing::_,
492                       testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
493      .WillOnce(testing::Return(true));
494  EXPECT_CALL(mock_input_handler_, ScrollEnd());
495  time += base::TimeDelta::FromMilliseconds(100);
496  input_handler_->Animate(time);
497
498  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
499
500  // Let's say on the third call we hit a non-scrollable region. We should abort
501  // the fling and not scroll.
502  // We also should pass the current fling parameters out to the client so the
503  // rest of the fling can be
504  // transferred to the main thread.
505  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
506  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
507      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
508  EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
509  EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
510  // Expected wheel fling animation parameters:
511  // *) fling_delta and fling_point should match the original GestureFlingStart
512  // event
513  // *) startTime should be 10 to match the time parameter of the first
514  // Animate() call after the GestureFlingStart
515  // *) cumulativeScroll depends on the curve, but since we've animated in the
516  // -X direction the X value should be < 0
517  EXPECT_CALL(
518      mock_client_,
519      TransferActiveWheelFlingAnimation(testing::AllOf(
520          testing::Field(&WebActiveWheelFlingParameters::delta,
521                         testing::Eq(fling_delta)),
522          testing::Field(&WebActiveWheelFlingParameters::point,
523                         testing::Eq(fling_point)),
524          testing::Field(&WebActiveWheelFlingParameters::globalPoint,
525                         testing::Eq(fling_global_point)),
526          testing::Field(&WebActiveWheelFlingParameters::modifiers,
527                         testing::Eq(modifiers)),
528          testing::Field(&WebActiveWheelFlingParameters::startTime,
529                         testing::Eq(10)),
530          testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
531                         testing::Field(&WebSize::width, testing::Gt(0))))));
532  time += base::TimeDelta::FromMilliseconds(100);
533  input_handler_->Animate(time);
534
535  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
536  testing::Mock::VerifyAndClearExpectations(&mock_client_);
537
538  // Since we've aborted the fling, the next animation should be a no-op and
539  // should not result in another
540  // frame being requested.
541  EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
542  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
543      .Times(0);
544  time += base::TimeDelta::FromMilliseconds(100);
545  input_handler_->Animate(time);
546
547  // Since we've transferred the fling to the main thread, we need to pass the
548  // next GestureFlingCancel to the main
549  // thread as well.
550  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
551  gesture_.type = WebInputEvent::GestureFlingCancel;
552  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
553}
554
555TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
556  // We shouldn't send any events to the widget for this gesture.
557  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
558  VERIFY_AND_RESET_MOCKS();
559
560  // Start a gesture fling in the -X direction with zero Y movement.
561  gesture_.type = WebInputEvent::GestureFlingStart;
562  WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
563  WebPoint fling_point = WebPoint(7, 13);
564  WebPoint fling_global_point = WebPoint(17, 23);
565  int modifiers = 1;
566  gesture_.data.flingStart.velocityX = fling_delta.x;
567  gesture_.data.flingStart.velocityY = fling_delta.y;
568  gesture_.sourceDevice = WebGestureEvent::Touchpad;
569  gesture_.x = fling_point.x;
570  gesture_.y = fling_point.y;
571  gesture_.globalX = fling_global_point.x;
572  gesture_.globalY = fling_global_point.y;
573  gesture_.modifiers = modifiers;
574  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
575  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
576      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
577  EXPECT_CALL(mock_input_handler_, ScrollEnd());
578  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
579
580  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
581
582  // Start the fling animation at time 10. This shouldn't actually scroll, just
583  // establish a start time.
584  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
585  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
586      .Times(0);
587  base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
588  input_handler_->Animate(time);
589
590  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
591
592  // The second call should start scrolling in the -X direction.
593  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
594  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
595      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
596  EXPECT_CALL(mock_input_handler_,
597              ScrollBy(testing::_,
598                       testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
599      .WillOnce(testing::Return(true));
600  EXPECT_CALL(mock_input_handler_, ScrollEnd());
601  time += base::TimeDelta::FromMilliseconds(100);
602  input_handler_->Animate(time);
603
604  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
605
606  // Let's say on the third call we hit a non-scrollable region. We should abort
607  // the fling and not scroll.
608  // We also should pass the current fling parameters out to the client so the
609  // rest of the fling can be
610  // transferred to the main thread.
611  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
612  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
613      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
614  EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
615  EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
616
617  // Expected wheel fling animation parameters:
618  // *) fling_delta and fling_point should match the original GestureFlingStart
619  // event
620  // *) startTime should be 10 to match the time parameter of the first
621  // Animate() call after the GestureFlingStart
622  // *) cumulativeScroll depends on the curve, but since we've animated in the
623  // -X direction the X value should be < 0
624  EXPECT_CALL(
625      mock_client_,
626      TransferActiveWheelFlingAnimation(testing::AllOf(
627          testing::Field(&WebActiveWheelFlingParameters::delta,
628                         testing::Eq(fling_delta)),
629          testing::Field(&WebActiveWheelFlingParameters::point,
630                         testing::Eq(fling_point)),
631          testing::Field(&WebActiveWheelFlingParameters::globalPoint,
632                         testing::Eq(fling_global_point)),
633          testing::Field(&WebActiveWheelFlingParameters::modifiers,
634                         testing::Eq(modifiers)),
635          testing::Field(&WebActiveWheelFlingParameters::startTime,
636                         testing::Eq(10)),
637          testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
638                         testing::Field(&WebSize::width, testing::Gt(0))))));
639  time += base::TimeDelta::FromMilliseconds(100);
640  input_handler_->Animate(time);
641
642  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
643  testing::Mock::VerifyAndClearExpectations(&mock_client_);
644
645  // Since we've aborted the fling, the next animation should be a no-op and
646  // should not result in another
647  // frame being requested.
648  EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
649  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
650      .Times(0);
651  time += base::TimeDelta::FromMilliseconds(100);
652  input_handler_->Animate(time);
653
654  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
655
656  // Since we've transferred the fling to the main thread, we need to pass the
657  // next GestureFlingCancel to the main
658  // thread as well.
659  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
660  gesture_.type = WebInputEvent::GestureFlingCancel;
661  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
662
663  VERIFY_AND_RESET_MOCKS();
664  input_handler_->MainThreadHasStoppedFlinging();
665
666  // Start a second gesture fling, this time in the +Y direction with no X.
667  gesture_.type = WebInputEvent::GestureFlingStart;
668  fling_delta = WebFloatPoint(0, -1000);
669  fling_point = WebPoint(95, 87);
670  fling_global_point = WebPoint(32, 71);
671  modifiers = 2;
672  gesture_.data.flingStart.velocityX = fling_delta.x;
673  gesture_.data.flingStart.velocityY = fling_delta.y;
674  gesture_.sourceDevice = WebGestureEvent::Touchpad;
675  gesture_.x = fling_point.x;
676  gesture_.y = fling_point.y;
677  gesture_.globalX = fling_global_point.x;
678  gesture_.globalY = fling_global_point.y;
679  gesture_.modifiers = modifiers;
680  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
681  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
682      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
683  EXPECT_CALL(mock_input_handler_, ScrollEnd());
684  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
685  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
686
687  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
688
689  // Start the second fling animation at time 30.
690  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
691  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
692      .Times(0);
693  time = base::TimeTicks() + base::TimeDelta::FromSeconds(30);
694  input_handler_->Animate(time);
695
696  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
697
698  // Tick the second fling once normally.
699  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
700  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
701      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
702  EXPECT_CALL(mock_input_handler_,
703              ScrollBy(testing::_,
704                       testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
705      .WillOnce(testing::Return(true));
706  EXPECT_CALL(mock_input_handler_, ScrollEnd());
707  time += base::TimeDelta::FromMilliseconds(100);
708  input_handler_->Animate(time);
709
710  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
711
712  // Then abort the second fling.
713  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
714  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
715      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
716  EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
717  EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
718
719  // We should get parameters from the second fling, nothing from the first
720  // fling should "leak".
721  EXPECT_CALL(
722      mock_client_,
723      TransferActiveWheelFlingAnimation(testing::AllOf(
724          testing::Field(&WebActiveWheelFlingParameters::delta,
725                         testing::Eq(fling_delta)),
726          testing::Field(&WebActiveWheelFlingParameters::point,
727                         testing::Eq(fling_point)),
728          testing::Field(&WebActiveWheelFlingParameters::globalPoint,
729                         testing::Eq(fling_global_point)),
730          testing::Field(&WebActiveWheelFlingParameters::modifiers,
731                         testing::Eq(modifiers)),
732          testing::Field(&WebActiveWheelFlingParameters::startTime,
733                         testing::Eq(30)),
734          testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
735                         testing::Field(&WebSize::height, testing::Lt(0))))));
736  time += base::TimeDelta::FromMilliseconds(100);
737  input_handler_->Animate(time);
738}
739
740TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) {
741  // We shouldn't send any events to the widget for this gesture.
742  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
743  VERIFY_AND_RESET_MOCKS();
744
745  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
746      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
747  gesture_.type = WebInputEvent::GestureScrollBegin;
748  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
749  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
750
751  VERIFY_AND_RESET_MOCKS();
752
753  EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
754      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
755  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
756
757  gesture_.type = WebInputEvent::GestureFlingStart;
758  gesture_.data.flingStart.velocityX = 10;
759  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
760  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
761
762  VERIFY_AND_RESET_MOCKS();
763
764  EXPECT_CALL(mock_input_handler_, ScrollEnd());
765
766  // Verify that a GestureFlingCancel during an animation cancels it.
767  gesture_.type = WebInputEvent::GestureFlingCancel;
768  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
769  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
770}
771
772TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) {
773  // We should send all events to the widget for this gesture.
774  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
775  VERIFY_AND_RESET_MOCKS();
776
777  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
778      .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
779
780  gesture_.type = WebInputEvent::GestureScrollBegin;
781  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
782
783  VERIFY_AND_RESET_MOCKS();
784
785  EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0);
786
787  gesture_.type = WebInputEvent::GestureFlingStart;
788  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
789  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
790
791  VERIFY_AND_RESET_MOCKS();
792
793  // Even if we didn't start a fling ourselves, we still need to send the cancel
794  // event to the widget.
795  gesture_.type = WebInputEvent::GestureFlingCancel;
796  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
797  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
798}
799
800TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
801  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
802  VERIFY_AND_RESET_MOCKS();
803
804  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
805      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
806
807  gesture_.type = WebInputEvent::GestureScrollBegin;
808  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
809  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
810
811  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
812  VERIFY_AND_RESET_MOCKS();
813
814  EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
815      .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
816
817  gesture_.type = WebInputEvent::GestureFlingStart;
818  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
819  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
820
821  VERIFY_AND_RESET_MOCKS();
822
823  // Even if we didn't start a fling ourselves, we still need to send the cancel
824  // event to the widget.
825  gesture_.type = WebInputEvent::GestureFlingCancel;
826  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
827  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
828}
829
830TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
831  // We shouldn't send any events to the widget for this gesture.
832  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
833  VERIFY_AND_RESET_MOCKS();
834
835  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
836      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
837
838  gesture_.type = WebInputEvent::GestureScrollBegin;
839  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
840  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
841
842  VERIFY_AND_RESET_MOCKS();
843
844  // On the fling start, we should schedule an animation but not actually start
845  // scrolling.
846  gesture_.type = WebInputEvent::GestureFlingStart;
847  WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
848  WebPoint fling_point = WebPoint(7, 13);
849  WebPoint fling_global_point = WebPoint(17, 23);
850  int modifiers = 7;
851  gesture_.data.flingStart.velocityX = fling_delta.x;
852  gesture_.data.flingStart.velocityY = fling_delta.y;
853  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
854  gesture_.x = fling_point.x;
855  gesture_.y = fling_point.y;
856  gesture_.globalX = fling_global_point.x;
857  gesture_.globalY = fling_global_point.y;
858  gesture_.modifiers = modifiers;
859  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
860  EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
861      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
862  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
863
864  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
865  // The first animate call should let us pick up an animation start time, but
866  // we shouldn't actually move anywhere just yet. The first frame after the
867  // fling start will typically include the last scroll from the gesture that
868  // lead to the scroll (either wheel or gesture scroll), so there should be no
869  // visible hitch.
870  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
871  base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
872  input_handler_->Animate(time);
873
874  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
875
876  // The second call should start scrolling in the -X direction.
877  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
878  EXPECT_CALL(mock_input_handler_,
879              ScrollBy(testing::_,
880                       testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
881      .WillOnce(testing::Return(true));
882  time += base::TimeDelta::FromMilliseconds(100);
883  input_handler_->Animate(time);
884
885  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
886
887  EXPECT_CALL(mock_input_handler_, ScrollEnd());
888  gesture_.type = WebInputEvent::GestureFlingCancel;
889  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
890}
891
892TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
893  // We shouldn't send any events to the widget for this gesture.
894  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
895  VERIFY_AND_RESET_MOCKS();
896
897  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
898      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
899
900  gesture_.type = WebInputEvent::GestureScrollBegin;
901  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
902  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
903
904  VERIFY_AND_RESET_MOCKS();
905
906  // On the fling start, we should schedule an animation but not actually start
907  // scrolling.
908  base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10);
909  gesture_.type = WebInputEvent::GestureFlingStart;
910  WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
911  WebPoint fling_point = WebPoint(7, 13);
912  WebPoint fling_global_point = WebPoint(17, 23);
913  int modifiers = 7;
914  gesture_.timeStampSeconds = startTimeOffset.InSecondsF();
915  gesture_.data.flingStart.velocityX = fling_delta.x;
916  gesture_.data.flingStart.velocityY = fling_delta.y;
917  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
918  gesture_.x = fling_point.x;
919  gesture_.y = fling_point.y;
920  gesture_.globalX = fling_global_point.x;
921  gesture_.globalY = fling_global_point.y;
922  gesture_.modifiers = modifiers;
923  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
924  EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
925      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
926  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
927
928  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
929  // With a valid time stamp, the first animate call should skip start time
930  // initialization and immediately begin scroll update production. This reduces
931  // the likelihood of a hitch between the scroll preceding the fling and
932  // the first scroll generated by the fling.
933  // Scrolling should start in the -X direction.
934  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
935  EXPECT_CALL(mock_input_handler_,
936              ScrollBy(testing::_,
937                       testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
938      .WillOnce(testing::Return(true));
939  base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset;
940  input_handler_->Animate(time);
941
942  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
943
944  EXPECT_CALL(mock_input_handler_, ScrollEnd());
945  gesture_.type = WebInputEvent::GestureFlingCancel;
946  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
947}
948
949TEST_F(InputHandlerProxyTest,
950       GestureScrollOnImplThreadFlagClearedAfterFling) {
951  // We shouldn't send any events to the widget for this gesture.
952  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
953  VERIFY_AND_RESET_MOCKS();
954
955  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
956      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
957
958  gesture_.type = WebInputEvent::GestureScrollBegin;
959  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
960
961  // After sending a GestureScrollBegin, the member variable
962  // |gesture_scroll_on_impl_thread_| should be true.
963  EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
964
965  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
966  VERIFY_AND_RESET_MOCKS();
967
968  // On the fling start, we should schedule an animation but not actually start
969  // scrolling.
970  gesture_.type = WebInputEvent::GestureFlingStart;
971  WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
972  WebPoint fling_point = WebPoint(7, 13);
973  WebPoint fling_global_point = WebPoint(17, 23);
974  int modifiers = 7;
975  gesture_.data.flingStart.velocityX = fling_delta.x;
976  gesture_.data.flingStart.velocityY = fling_delta.y;
977  gesture_.sourceDevice = WebGestureEvent::Touchscreen;
978  gesture_.x = fling_point.x;
979  gesture_.y = fling_point.y;
980  gesture_.globalX = fling_global_point.x;
981  gesture_.globalY = fling_global_point.y;
982  gesture_.modifiers = modifiers;
983  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
984  EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
985      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
986  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
987
988  // |gesture_scroll_on_impl_thread_| should still be true after
989  // a GestureFlingStart is sent.
990  EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
991
992  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
993  // The first animate call should let us pick up an animation start time, but
994  // we shouldn't actually move anywhere just yet. The first frame after the
995  // fling start will typically include the last scroll from the gesture that
996  // lead to the scroll (either wheel or gesture scroll), so there should be no
997  // visible hitch.
998  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
999  base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
1000  input_handler_->Animate(time);
1001
1002  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1003
1004  // The second call should start scrolling in the -X direction.
1005  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1006  EXPECT_CALL(mock_input_handler_,
1007              ScrollBy(testing::_,
1008                       testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
1009      .WillOnce(testing::Return(true));
1010  time += base::TimeDelta::FromMilliseconds(100);
1011  input_handler_->Animate(time);
1012
1013  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1014
1015  EXPECT_CALL(mock_input_handler_, ScrollEnd());
1016  gesture_.type = WebInputEvent::GestureFlingCancel;
1017  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1018
1019  // |gesture_scroll_on_impl_thread_| should be false once
1020  // the fling has finished (note no GestureScrollEnd has been sent).
1021  EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing());
1022}
1023
1024TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
1025  // We shouldn't send any events to the widget for this gesture.
1026  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1027  VERIFY_AND_RESET_MOCKS();
1028
1029  // On the fling start, we should schedule an animation but not actually start
1030  // scrolling.
1031  gesture_.type = WebInputEvent::GestureFlingStart;
1032  WebFloatPoint fling_delta = WebFloatPoint(1000, 1000);
1033  gesture_.data.flingStart.velocityX = fling_delta.x;
1034  gesture_.data.flingStart.velocityY = fling_delta.y;
1035  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1036  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1037      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1038  EXPECT_CALL(mock_input_handler_, ScrollEnd());
1039  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1040  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1041
1042  // The first animate doesn't cause any scrolling.
1043  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1044  base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
1045  input_handler_->Animate(time);
1046  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1047
1048  // The second animate starts scrolling in the positive X and Y directions.
1049  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1050  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1051      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1052  EXPECT_CALL(mock_input_handler_,
1053              ScrollBy(testing::_,
1054                       testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
1055      .WillOnce(testing::Return(true));
1056  EXPECT_CALL(mock_input_handler_, ScrollEnd());
1057  time += base::TimeDelta::FromMilliseconds(100);
1058  input_handler_->Animate(time);
1059  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1060
1061  // Simulate hitting the bottom content edge.
1062  cc::DidOverscrollParams overscroll_params;
1063  overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100);
1064  overscroll_params.current_fling_velocity = gfx::Vector2dF(0, 10);
1065  input_handler_->DidOverscroll(overscroll_params);
1066
1067  // The next call to animate will no longer scroll vertically.
1068  EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1069  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1070      .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1071  EXPECT_CALL(mock_input_handler_,
1072              ScrollBy(testing::_,
1073                       testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
1074      .WillOnce(testing::Return(true));
1075  EXPECT_CALL(mock_input_handler_, ScrollEnd());
1076  time += base::TimeDelta::FromMilliseconds(100);
1077  input_handler_->Animate(time);
1078  testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1079}
1080
1081TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
1082  // None of the three touch points fall in the touch region. So the event
1083  // should be dropped.
1084  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1085  VERIFY_AND_RESET_MOCKS();
1086
1087  EXPECT_CALL(mock_input_handler_,
1088              HaveTouchEventHandlersAt(
1089                  testing::Property(&gfx::Point::x, testing::Gt(0))))
1090      .WillOnce(testing::Return(false));
1091  EXPECT_CALL(mock_input_handler_,
1092              HaveTouchEventHandlersAt(
1093                  testing::Property(&gfx::Point::x, testing::Lt(0))))
1094      .WillOnce(testing::Return(false));
1095
1096  WebTouchEvent touch;
1097  touch.type = WebInputEvent::TouchStart;
1098
1099  touch.touchesLength = 3;
1100  touch.touches[0].state = WebTouchPoint::StateStationary;
1101  touch.touches[0].screenPosition = WebPoint();
1102  touch.touches[0].position = WebPoint();
1103
1104  touch.touches[1].state = WebTouchPoint::StatePressed;
1105  touch.touches[1].screenPosition = WebPoint(10, 10);
1106  touch.touches[1].position = WebPoint(10, 10);
1107
1108  touch.touches[2].state = WebTouchPoint::StatePressed;
1109  touch.touches[2].screenPosition = WebPoint(-10, 10);
1110  touch.touches[2].position = WebPoint(-10, 10);
1111
1112  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
1113}
1114
1115TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
1116  // One of the touch points is on a touch-region. So the event should be sent
1117  // to the main thread.
1118  expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1119  VERIFY_AND_RESET_MOCKS();
1120
1121  EXPECT_CALL(mock_input_handler_,
1122              HaveTouchEventHandlersAt(
1123                  testing::Property(&gfx::Point::x, testing::Eq(0))))
1124      .WillOnce(testing::Return(false));
1125  EXPECT_CALL(mock_input_handler_,
1126              HaveTouchEventHandlersAt(
1127                  testing::Property(&gfx::Point::x, testing::Gt(0))))
1128      .WillOnce(testing::Return(true));
1129  // Since the second touch point hits a touch-region, there should be no
1130  // hit-testing for the third touch point.
1131
1132  WebTouchEvent touch;
1133  touch.type = WebInputEvent::TouchStart;
1134
1135  touch.touchesLength = 3;
1136  touch.touches[0].state = WebTouchPoint::StatePressed;
1137  touch.touches[0].screenPosition = WebPoint();
1138  touch.touches[0].position = WebPoint();
1139
1140  touch.touches[1].state = WebTouchPoint::StatePressed;
1141  touch.touches[1].screenPosition = WebPoint(10, 10);
1142  touch.touches[1].position = WebPoint(10, 10);
1143
1144  touch.touches[2].state = WebTouchPoint::StatePressed;
1145  touch.touches[2].screenPosition = WebPoint(-10, 10);
1146  touch.touches[2].position = WebPoint(-10, 10);
1147
1148  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
1149}
1150
1151} // namespace
1152} // namespace content
1153