d5b68a867f782cc67fd1b7bc2962052934fd709f
[WebKit-https.git] / Source / WebKit / chromium / tests / WebCompositorInputHandlerImplTest.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "WebCompositorInputHandlerImpl.h"
29
30 #include "WebCompositor.h"
31 #include "WebCompositorInputHandlerClient.h"
32 #include "WebInputEvent.h"
33 #include "cc/CCActiveGestureAnimation.h"
34 #include "cc/CCInputHandler.h"
35 #include "cc/CCSingleThreadProxy.h"
36 #include "platform/WebFloatPoint.h"
37 #include "platform/WebPoint.h"
38
39 #include <gmock/gmock.h>
40 #include <gtest/gtest.h>
41 #include <wtf/OwnPtr.h>
42
43 using namespace WebKit;
44
45 namespace {
46
47 class MockCCInputHandlerClient : public WebCore::CCInputHandlerClient {
48     WTF_MAKE_NONCOPYABLE(MockCCInputHandlerClient);
49 public:
50     MockCCInputHandlerClient()
51     {
52     }
53     virtual ~MockCCInputHandlerClient() { }
54
55
56     MOCK_METHOD0(pinchGestureBegin, void());
57     MOCK_METHOD2(pinchGestureUpdate, void(float magnifyDelta, const WebCore::IntPoint& anchor));
58     MOCK_METHOD0(pinchGestureEnd, void());
59
60     MOCK_METHOD0(scheduleAnimation, void());
61
62     MOCK_METHOD2(scrollBegin, ScrollStatus(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType));
63     MOCK_METHOD1(scrollBy, void(const WebCore::IntSize&));
64     MOCK_METHOD0(scrollEnd, void());
65
66 private:
67     virtual void startPageScaleAnimation(const WebCore::IntSize& targetPosition,
68                                          bool anchorPoint,
69                                          float pageScale,
70                                          double startTimeMs,
71                                          double durationMs) OVERRIDE { }
72
73     virtual WebCore::CCActiveGestureAnimation* activeGestureAnimation() OVERRIDE { return 0; }
74     virtual void setActiveGestureAnimation(PassOwnPtr<WebCore::CCActiveGestureAnimation>) OVERRIDE { }
75 };
76
77 class MockWebCompositorInputHandlerClient : public WebCompositorInputHandlerClient {
78     WTF_MAKE_NONCOPYABLE(MockWebCompositorInputHandlerClient);
79 public:
80     MockWebCompositorInputHandlerClient()
81         : WebCompositorInputHandlerClient()
82     {
83     }
84     virtual ~MockWebCompositorInputHandlerClient() { }
85
86     MOCK_METHOD0(willShutdown, void());
87     MOCK_METHOD0(didHandleInputEvent, void());
88     MOCK_METHOD1(didNotHandleInputEvent, void(bool sendToWidget));
89
90     MOCK_METHOD1(transferActiveWheelFlingAnimation, void(const WebActiveWheelFlingParameters&));
91
92 };
93
94 TEST(WebCompositorInputHandlerImpl, fromIdentifier)
95 {
96     WebCompositor::initialize(0);
97     WebCore::DebugScopedSetImplThread alwaysImplThread;
98
99     // Before creating any WebCompositorInputHandlers, lookups for any value should fail and not crash.
100     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(2));
101     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(0));
102     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(-1));
103
104     int compositorIdentifier = -1;
105     {
106         OwnPtr<WebCompositorInputHandlerImpl> inputHandler = WebCompositorInputHandlerImpl::create(0);
107         compositorIdentifier = inputHandler->identifier();
108         // The compositor we just created should be locatable.
109         EXPECT_EQ(inputHandler.get(), WebCompositorInputHandler::fromIdentifier(compositorIdentifier));
110
111         // But nothing else.
112         EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(inputHandler->identifier() + 10));
113     }
114
115     // After the compositor is destroyed, its entry should be removed from the map.
116     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(compositorIdentifier));
117     WebCompositor::shutdown();
118 }
119
120 class WebCompositorInputHandlerImplTest : public testing::Test {
121 public:
122     WebCompositorInputHandlerImplTest()
123         : m_expectedDisposition(DidHandle)
124     {
125         WebCompositor::initialize(0);
126         m_inputHandler = WebCompositorInputHandlerImpl::create(&m_mockCCInputHandlerClient);
127         m_inputHandler->setClient(&m_mockClient);
128     }
129
130     ~WebCompositorInputHandlerImplTest()
131     {
132         m_inputHandler->setClient(0);
133         m_inputHandler.clear();
134         WebCompositor::shutdown();
135     }
136
137     // This is defined as a macro because when an expectation is not satisfied the only output you get
138     // out of gmock is the line number that set the expectation.
139 #define VERIFY_AND_RESET_MOCKS() do                                                                                      \
140     {                                                                                                                    \
141         testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);                                          \
142         testing::Mock::VerifyAndClearExpectations(&m_mockClient);                                                        \
143         switch (m_expectedDisposition) {                                                                                 \
144         case DidHandle:                                                                                                  \
145             /* If we expect to handle events, we shouldn't get any didNotHandleInputEvent() calls with any parameter. */ \
146             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(::testing::_)).Times(0);                                    \
147             EXPECT_CALL(m_mockClient, didHandleInputEvent());                                                            \
148             break;                                                                                                       \
149         case DidNotHandle:                                                                                               \
150             /* If we aren't expecting to handle events, we shouldn't call didHandleInputEvent(). */                      \
151             EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0);                                                   \
152             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false)).Times(0);                                           \
153             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));                                                     \
154             break;                                                                                                       \
155         case DropEvent:                                                                                                  \
156             /* If we're expecting to drop, we shouldn't get any didHandle..() or didNotHandleInputEvent(true) calls. */  \
157             EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0);                                                   \
158             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true)).Times(0);                                            \
159             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false));                                                    \
160             break;                                                                                                       \
161         }                                                                                                                                                       \
162     } while (0)
163
164 protected:
165     MockCCInputHandlerClient m_mockCCInputHandlerClient;
166     OwnPtr<WebCompositorInputHandlerImpl> m_inputHandler;
167     MockWebCompositorInputHandlerClient m_mockClient;
168     WebGestureEvent gesture;
169
170     enum ExpectedDisposition { DidHandle, DidNotHandle, DropEvent };
171     ExpectedDisposition m_expectedDisposition;
172
173 private:
174     WebCore::DebugScopedSetImplThread m_alwaysImplThread;
175 };
176
177
178 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollStarted)
179 {
180     // We shouldn't send any events to the widget for this gesture.
181     m_expectedDisposition = DidHandle;
182     VERIFY_AND_RESET_MOCKS();
183
184     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
185         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
186
187     gesture.type = WebInputEvent::GestureScrollBegin;
188     m_inputHandler->handleInputEvent(gesture);
189
190     VERIFY_AND_RESET_MOCKS();
191
192     gesture.type = WebInputEvent::GestureScrollUpdate;
193     gesture.deltaY = -40; // -Y means scroll down - i.e. in the +Y direction.
194     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
195     m_inputHandler->handleInputEvent(gesture);
196
197     VERIFY_AND_RESET_MOCKS();
198
199     gesture.type = WebInputEvent::GestureScrollEnd;
200     gesture.deltaY = 0;
201     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
202     m_inputHandler->handleInputEvent(gesture);
203 }
204
205 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollOnMainThread)
206 {
207     // We should send all events to the widget for this gesture.
208     m_expectedDisposition = DidNotHandle;
209     VERIFY_AND_RESET_MOCKS();
210
211     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(::testing::_, ::testing::_))
212         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
213
214     gesture.type = WebInputEvent::GestureScrollBegin;
215     m_inputHandler->handleInputEvent(gesture);
216
217     VERIFY_AND_RESET_MOCKS();
218
219     gesture.type = WebInputEvent::GestureScrollUpdate;
220     gesture.deltaY = 40;
221     m_inputHandler->handleInputEvent(gesture);
222
223     VERIFY_AND_RESET_MOCKS();
224
225     gesture.type = WebInputEvent::GestureScrollEnd;
226     gesture.deltaY = 0;
227     m_inputHandler->handleInputEvent(gesture);
228 }
229
230 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollIgnored)
231 {
232     // We shouldn't handle the GestureScrollBegin.
233     // Instead, we should get one didNotHandleInputEvent(false) call per handleInputEvent(),
234     // indicating that we could determine that there's nothing that could scroll or otherwise
235     // react to this gesture sequence and thus we should drop the whole gesture sequence on the floor.
236     m_expectedDisposition = DropEvent;
237     VERIFY_AND_RESET_MOCKS();
238
239     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
240         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
241
242     gesture.type = WebInputEvent::GestureScrollBegin;
243     m_inputHandler->handleInputEvent(gesture);
244 }
245
246 TEST_F(WebCompositorInputHandlerImplTest, gesturePinch)
247 {
248     // We shouldn't send any events to the widget for this gesture.
249     m_expectedDisposition = DidHandle;
250     VERIFY_AND_RESET_MOCKS();
251
252     gesture.type = WebInputEvent::GesturePinchBegin;
253     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureBegin());
254     m_inputHandler->handleInputEvent(gesture);
255
256     VERIFY_AND_RESET_MOCKS();
257
258     gesture.type = WebInputEvent::GesturePinchUpdate;
259     gesture.deltaX = 1.5;
260     gesture.x = 7;
261     gesture.y = 13;
262     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(1.5, WebCore::IntPoint(7, 13)));
263     m_inputHandler->handleInputEvent(gesture);
264
265     VERIFY_AND_RESET_MOCKS();
266
267     gesture.type = WebInputEvent::GesturePinchUpdate;
268     gesture.deltaX = 0.5;
269     gesture.x = 9;
270     gesture.y = 6;
271     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(.5, WebCore::IntPoint(9, 6)));
272     m_inputHandler->handleInputEvent(gesture);
273
274     VERIFY_AND_RESET_MOCKS();
275
276     gesture.type = WebInputEvent::GesturePinchEnd;
277     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureEnd());
278     m_inputHandler->handleInputEvent(gesture);
279 }
280
281 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingStarted)
282 {
283     // We shouldn't send any events to the widget for this gesture.
284     m_expectedDisposition = DidHandle;
285     VERIFY_AND_RESET_MOCKS();
286
287     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
288         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
289
290     gesture.type = WebInputEvent::GestureFlingStart;
291     gesture.deltaX = 10;
292     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
293     m_inputHandler->handleInputEvent(gesture);
294
295     VERIFY_AND_RESET_MOCKS();
296
297     // Verify that a GestureFlingCancel during an animation cancels it.
298     gesture.type = WebInputEvent::GestureFlingCancel;
299     m_inputHandler->handleInputEvent(gesture);
300 }
301
302 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingFailed)
303 {
304     // We should send all events to the widget for this gesture.
305     m_expectedDisposition = DidNotHandle;
306     VERIFY_AND_RESET_MOCKS();
307
308     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
309         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
310
311     gesture.type = WebInputEvent::GestureFlingStart;
312     m_inputHandler->handleInputEvent(gesture);
313
314     VERIFY_AND_RESET_MOCKS();
315
316     // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
317     gesture.type = WebInputEvent::GestureFlingCancel;
318     m_inputHandler->handleInputEvent(gesture);
319 }
320
321 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingIgnored)
322 {
323     m_expectedDisposition = DidNotHandle;
324     VERIFY_AND_RESET_MOCKS();
325
326     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
327         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
328
329     gesture.type = WebInputEvent::GestureFlingStart;
330     m_inputHandler->handleInputEvent(gesture);
331
332     VERIFY_AND_RESET_MOCKS();
333
334     // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
335     gesture.type = WebInputEvent::GestureFlingCancel;
336     m_inputHandler->handleInputEvent(gesture);
337 }
338
339 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingAnimates)
340 {
341     // We shouldn't send any events to the widget for this gesture.
342     m_expectedDisposition = DidHandle;
343     VERIFY_AND_RESET_MOCKS();
344
345     // On the fling start, we should schedule an animation but not actually start
346     // scrolling.
347     gesture.type = WebInputEvent::GestureFlingStart;
348     WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
349     WebPoint flingPoint = WebPoint(7, 13);
350     WebPoint flingGlobalPoint = WebPoint(17, 23);
351     int modifiers = 7;
352     gesture.deltaX = flingDelta.x;
353     gesture.deltaY = flingDelta.y;
354     gesture.x = flingPoint.x;
355     gesture.y = flingPoint.y;
356     gesture.globalX = flingGlobalPoint.x;
357     gesture.globalY = flingGlobalPoint.y;
358     gesture.modifiers = modifiers;
359     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
360     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
361         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
362     m_inputHandler->handleInputEvent(gesture);
363
364     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
365     // The first animate call should let us pick up an animation start time, but we
366     // shouldn't actually move anywhere just yet. The first frame after the fling start
367     // will typically include the last scroll from the gesture that lead to the scroll
368     // (either wheel or gesture scroll), so there should be no visible hitch.
369     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
370     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
371     m_inputHandler->animate(10);
372
373     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
374
375     // The second call should start scrolling in the -X direction.
376     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
377     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
378         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
379     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
380     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
381     m_inputHandler->animate(10.1);
382
383     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
384
385     // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
386     // We also should pass the current fling parameters out to the client so the rest of the fling can be
387     // transferred to the main thread.
388     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
389     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
390         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
391     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
392     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
393
394     // Expected wheel fling animation parameters:
395     // *) flingDelta and flingPoint should match the original GestureFlingStart event
396     // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
397     // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
398     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
399         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
400         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
401         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
402         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
403         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
404         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
405             testing::Field(&WebSize::width, testing::Gt(0))))));
406     m_inputHandler->animate(10.2);
407
408     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
409     testing::Mock::VerifyAndClearExpectations(&m_mockClient);
410
411     // Since we've aborted the fling, the next animation should be a no-op and should not result in another
412     // frame being requested.
413     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
414     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
415     m_inputHandler->animate(10.3);
416
417     // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
418     // thread as well.
419     EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
420     gesture.type = WebInputEvent::GestureFlingCancel;
421     m_inputHandler->handleInputEvent(gesture);
422 }
423
424 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingTransferResets)
425 {
426     // We shouldn't send any events to the widget for this gesture.
427     m_expectedDisposition = DidHandle;
428     VERIFY_AND_RESET_MOCKS();
429
430     // Start a gesture fling in the -X direction with zero Y movement.
431     gesture.type = WebInputEvent::GestureFlingStart;
432     WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
433     WebPoint flingPoint = WebPoint(7, 13);
434     WebPoint flingGlobalPoint = WebPoint(17, 23);
435     int modifiers = 1;
436     gesture.deltaX = flingDelta.x;
437     gesture.deltaY = flingDelta.y;
438     gesture.x = flingPoint.x;
439     gesture.y = flingPoint.y;
440     gesture.globalX = flingGlobalPoint.x;
441     gesture.globalY = flingGlobalPoint.y;
442     gesture.modifiers = modifiers;
443     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
444     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
445         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
446     m_inputHandler->handleInputEvent(gesture);
447
448     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
449
450     // Start the fling animation at time 10. This shouldn't actually scroll, just establish a start time.
451     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
452     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
453     m_inputHandler->animate(10);
454
455     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
456
457     // The second call should start scrolling in the -X direction.
458     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
459     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
460         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
461     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
462     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
463     m_inputHandler->animate(10.1);
464
465     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
466
467     // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
468     // We also should pass the current fling parameters out to the client so the rest of the fling can be
469     // transferred to the main thread.
470     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
471     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
472         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
473     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
474     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
475
476     // Expected wheel fling animation parameters:
477     // *) flingDelta and flingPoint should match the original GestureFlingStart event
478     // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
479     // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
480     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
481         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
482         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
483         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
484         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
485         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
486         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
487             testing::Field(&WebSize::width, testing::Gt(0))))));
488     m_inputHandler->animate(10.2);
489
490     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
491     testing::Mock::VerifyAndClearExpectations(&m_mockClient);
492
493     // Since we've aborted the fling, the next animation should be a no-op and should not result in another
494     // frame being requested.
495     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
496     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
497     m_inputHandler->animate(10.3);
498
499     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
500
501     // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
502     // thread as well.
503     EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
504     gesture.type = WebInputEvent::GestureFlingCancel;
505     m_inputHandler->handleInputEvent(gesture);
506
507     VERIFY_AND_RESET_MOCKS();
508
509     // Start a second gesture fling, this time in the +Y direction with no X.
510     gesture.type = WebInputEvent::GestureFlingStart;
511     flingDelta = WebFloatPoint(0, -1000);
512     flingPoint = WebPoint(95, 87);
513     flingGlobalPoint = WebPoint(32, 71);
514     modifiers = 2;
515     gesture.deltaX = flingDelta.x;
516     gesture.deltaY = flingDelta.y;
517     gesture.x = flingPoint.x;
518     gesture.y = flingPoint.y;
519     gesture.globalX = flingGlobalPoint.x;
520     gesture.globalY = flingGlobalPoint.y;
521     gesture.modifiers = modifiers;
522     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
523     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
524         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
525     m_inputHandler->handleInputEvent(gesture);
526
527     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
528
529     // Start the second fling animation at time 30.
530     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
531     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
532     m_inputHandler->animate(30);
533
534     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
535
536     // Tick the second fling once normally.
537     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
538     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
539         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
540     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
541     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
542     m_inputHandler->animate(30.1);
543
544     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
545
546     // Then abort the second fling.
547     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
548     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
549         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
550     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
551     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
552
553     // We should get parameters from the second fling, nothing from the first fling should "leak".
554     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
555         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
556         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
557         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
558         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
559         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(30)),
560         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
561             testing::Field(&WebSize::height, testing::Lt(0))))));
562     m_inputHandler->animate(30.2);
563 }
564
565 }