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 "ui/events/blink/input_handler_proxy.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/containers/circular_deque.h"
12 #include "base/macros.h"
13 #include "base/test/bind_test_util.h"
14 #include "base/test/metrics/histogram_tester.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "base/test/simple_test_tick_clock.h"
17 #include "base/test/task_environment.h"
18 #include "base/test/trace_event_analyzer.h"
19 #include "build/build_config.h"
20 #include "cc/input/main_thread_scrolling_reason.h"
21 #include "cc/input/scroll_input_type.h"
22 #include "cc/trees/swap_promise_monitor.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/blink/public/common/input/web_input_event.h"
26 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
27 #include "third_party/blink/public/common/input/web_keyboard_event.h"
28 #include "third_party/blink/public/common/input/web_mouse_event.h"
29 #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
30 #include "third_party/blink/public/common/input/web_pointer_event.h"
31 #include "third_party/blink/public/common/input/web_touch_event.h"
32 #include "ui/events/blink/blink_event_util.h"
33 #include "ui/events/blink/compositor_thread_event_queue.h"
34 #include "ui/events/blink/did_overscroll_params.h"
35 #include "ui/events/blink/event_with_callback.h"
36 #include "ui/events/blink/input_handler_proxy.h"
37 #include "ui/events/blink/input_handler_proxy_client.h"
38 #include "ui/events/blink/scroll_predictor.h"
39 #include "ui/events/blink/web_input_event_traits.h"
40 #include "ui/gfx/geometry/scroll_offset.h"
41 #include "ui/gfx/geometry/size_f.h"
42 #include "ui/latency/latency_info.h"
43 
44 using blink::WebGestureDevice;
45 using blink::WebGestureEvent;
46 using blink::WebInputEvent;
47 using blink::WebKeyboardEvent;
48 using blink::WebMouseEvent;
49 using blink::WebMouseWheelEvent;
50 using blink::WebTouchEvent;
51 using blink::WebTouchPoint;
52 using testing::_;
53 using testing::DoAll;
54 using testing::Field;
55 
56 namespace ui {
57 namespace test {
58 
59 namespace {
60 
61 enum InputHandlerProxyTestType {
62   ROOT_SCROLL_NORMAL_HANDLER,
63   ROOT_SCROLL_SYNCHRONOUS_HANDLER,
64   CHILD_SCROLL_NORMAL_HANDLER,
65   CHILD_SCROLL_SYNCHRONOUS_HANDLER,
66   COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_NORMAL,
67   COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_SYNCHRONOUS,
68   COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_NORMAL,
69   COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_SYNCHRONOUS,
70 };
71 static const InputHandlerProxyTestType test_types[] = {
72     ROOT_SCROLL_NORMAL_HANDLER,
73     ROOT_SCROLL_SYNCHRONOUS_HANDLER,
74     CHILD_SCROLL_NORMAL_HANDLER,
75     CHILD_SCROLL_SYNCHRONOUS_HANDLER,
76     COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_NORMAL,
77     COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_SYNCHRONOUS,
78     COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_NORMAL,
79     COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_SYNCHRONOUS,
80 };
81 
82 MATCHER_P(WheelEventsMatch, expected, "") {
83   return WheelEventsMatch(arg, expected);
84 }
85 
CreateGestureScrollPinch(WebInputEvent::Type type,WebGestureDevice source_device,base::TimeTicks event_time,float delta_y_or_scale=0,int x=0,int y=0)86 WebScopedInputEvent CreateGestureScrollPinch(WebInputEvent::Type type,
87                                              WebGestureDevice source_device,
88                                              base::TimeTicks event_time,
89                                              float delta_y_or_scale = 0,
90                                              int x = 0,
91                                              int y = 0) {
92   WebGestureEvent gesture(type, WebInputEvent::kNoModifiers, event_time,
93                           source_device);
94   if (type == WebInputEvent::kGestureScrollUpdate) {
95     gesture.data.scroll_update.delta_y = delta_y_or_scale;
96   } else if (type == WebInputEvent::kGesturePinchUpdate) {
97     gesture.data.pinch_update.scale = delta_y_or_scale;
98     gesture.SetPositionInWidget(gfx::PointF(x, y));
99   }
100   return gesture.Clone();
101 }
102 
103 class MockInputHandler : public cc::InputHandler {
104  public:
MockInputHandler()105   MockInputHandler() {}
~MockInputHandler()106   ~MockInputHandler() override {}
107 
108   MOCK_METHOD0(PinchGestureBegin, void());
109   MOCK_METHOD2(PinchGestureUpdate,
110                void(float magnify_delta, const gfx::Point& anchor));
111   MOCK_METHOD2(PinchGestureEnd, void(const gfx::Point& anchor, bool snap));
112 
113   MOCK_METHOD0(SetNeedsAnimateInput, void());
114 
115   MOCK_METHOD2(ScrollBegin,
116                ScrollStatus(cc::ScrollState*, cc::ScrollInputType type));
117   MOCK_METHOD2(RootScrollBegin,
118                ScrollStatus(cc::ScrollState*, cc::ScrollInputType type));
119   MOCK_METHOD2(ScrollUpdate,
120                cc::InputHandlerScrollResult(cc::ScrollState*, base::TimeDelta));
121   MOCK_METHOD1(ScrollEnd, void(bool));
122   MOCK_METHOD2(RecordScrollBegin,
123                void(cc::ScrollInputType type,
124                     cc::ScrollBeginThreadState state));
125   MOCK_METHOD1(RecordScrollEnd, void(cc::ScrollInputType type));
126   MOCK_METHOD0(ScrollingShouldSwitchtoMainThread, bool());
127 
CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo * latency)128   std::unique_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
129       ui::LatencyInfo* latency) override {
130     return nullptr;
131   }
132 
133   std::unique_ptr<cc::EventsMetricsManager::ScopedMonitor>
GetScopedEventMetricsMonitor(const cc::EventMetrics & event_metrics)134   GetScopedEventMetricsMonitor(const cc::EventMetrics& event_metrics) override {
135     return nullptr;
136   }
137 
CreateScrollElasticityHelper()138   cc::ScrollElasticityHelper* CreateScrollElasticityHelper() override {
139     return nullptr;
140   }
GetScrollOffsetForLayer(cc::ElementId element_id,gfx::ScrollOffset * offset)141   bool GetScrollOffsetForLayer(cc::ElementId element_id,
142                                gfx::ScrollOffset* offset) override {
143     return false;
144   }
ScrollLayerTo(cc::ElementId element_id,const gfx::ScrollOffset & offset)145   bool ScrollLayerTo(cc::ElementId element_id,
146                      const gfx::ScrollOffset& offset) override {
147     return false;
148   }
149 
BindToClient(cc::InputHandlerClient * client)150   void BindToClient(cc::InputHandlerClient* client) override {}
151 
MouseDown(const gfx::PointF & mouse_position,const bool shift_modifier)152   cc::InputHandlerPointerResult MouseDown(const gfx::PointF& mouse_position,
153                                           const bool shift_modifier) override {
154     cc::InputHandlerPointerResult pointer_result;
155     pointer_result.type = cc::kScrollbarScroll;
156     pointer_result.scroll_offset = gfx::ScrollOffset(0, 1);
157     return pointer_result;
158   }
159 
MouseUp(const gfx::PointF & mouse_position)160   cc::InputHandlerPointerResult MouseUp(
161       const gfx::PointF& mouse_position) override {
162     cc::InputHandlerPointerResult pointer_result;
163     pointer_result.type = cc::kScrollbarScroll;
164     return pointer_result;
165   }
166 
MouseLeave()167   void MouseLeave() override {}
168 
FindFrameElementIdAtPoint(const gfx::PointF & mouse_position)169   cc::ElementId FindFrameElementIdAtPoint(
170       const gfx::PointF& mouse_position) override {
171     return cc::ElementId();
172   }
173 
MouseMoveAt(const gfx::Point & mouse_position)174   cc::InputHandlerPointerResult MouseMoveAt(
175       const gfx::Point& mouse_position) override {
176     return cc::InputHandlerPointerResult();
177   }
178 
179   MOCK_CONST_METHOD1(IsCurrentlyScrollingLayerAt,
180                      bool(const gfx::Point& point));
181 
182   MOCK_CONST_METHOD1(
183       GetEventListenerProperties,
184       cc::EventListenerProperties(cc::EventListenerClass event_class));
185   MOCK_METHOD2(EventListenerTypeForTouchStartOrMoveAt,
186                cc::InputHandler::TouchStartOrMoveEventListenerType(
187                    const gfx::Point& point,
188                    cc::TouchAction* touch_action));
189   MOCK_CONST_METHOD1(HasBlockingWheelEventHandlerAt, bool(const gfx::Point&));
190 
191   MOCK_METHOD0(RequestUpdateForSynchronousInputHandler, void());
192   MOCK_METHOD1(SetSynchronousInputHandlerRootScrollOffset,
193                void(const gfx::ScrollOffset& root_offset));
194 
IsCurrentlyScrollingViewport() const195   bool IsCurrentlyScrollingViewport() const override {
196     return is_scrolling_root_;
197   }
set_is_scrolling_root(bool is)198   void set_is_scrolling_root(bool is) { is_scrolling_root_ = is; }
199 
200   MOCK_METHOD3(GetSnapFlingInfoAndSetAnimatingSnapTarget,
201                bool(const gfx::Vector2dF& natural_displacement,
202                     gfx::Vector2dF* initial_offset,
203                     gfx::Vector2dF* target_offset));
204   MOCK_METHOD1(ScrollEndForSnapFling, void(bool));
205 
206  private:
207   bool is_scrolling_root_ = true;
208   DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
209 };
210 
211 class MockSynchronousInputHandler : public SynchronousInputHandler {
212  public:
213   MOCK_METHOD6(UpdateRootLayerState,
214                void(const gfx::ScrollOffset& total_scroll_offset,
215                     const gfx::ScrollOffset& max_scroll_offset,
216                     const gfx::SizeF& scrollable_size,
217                     float page_scale_factor,
218                     float min_page_scale_factor,
219                     float max_page_scale_factor));
220 };
221 
222 class MockInputHandlerProxyClient : public InputHandlerProxyClient {
223  public:
MockInputHandlerProxyClient()224   MockInputHandlerProxyClient() {}
~MockInputHandlerProxyClient()225   ~MockInputHandlerProxyClient() override {}
226 
WillShutdown()227   void WillShutdown() override {}
228 
229   MOCK_METHOD1(DispatchNonBlockingEventToMainThread_,
230                void(const WebInputEvent&));
231 
232   MOCK_METHOD2(GenerateScrollBeginAndSendToMainThread,
233                void(const blink::WebGestureEvent& update_event,
234                     const blink::WebInputEventAttribution&));
235 
DispatchNonBlockingEventToMainThread(WebScopedInputEvent event,const ui::LatencyInfo & latency_info,const blink::WebInputEventAttribution &)236   void DispatchNonBlockingEventToMainThread(
237       WebScopedInputEvent event,
238       const ui::LatencyInfo& latency_info,
239       const blink::WebInputEventAttribution&) override {
240     CHECK(event.get());
241     DispatchNonBlockingEventToMainThread_(*event.get());
242   }
243 
244   MOCK_METHOD5(DidOverscroll,
245                void(const gfx::Vector2dF& accumulated_overscroll,
246                     const gfx::Vector2dF& latest_overscroll_delta,
247                     const gfx::Vector2dF& current_fling_velocity,
248                     const gfx::PointF& causal_event_viewport_point,
249                     const cc::OverscrollBehavior& overscroll_behavior));
DidAnimateForInput()250   void DidAnimateForInput() override {}
DidStartScrollingViewport()251   void DidStartScrollingViewport() override {}
252   MOCK_METHOD3(SetWhiteListedTouchAction,
253                void(cc::TouchAction touch_action,
254                     uint32_t unique_touch_event_id,
255                     InputHandlerProxy::EventDisposition event_disposition));
256 
257  private:
258   DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
259 };
260 
261 class MockInputHandlerProxyClientWithDidAnimateForInput
262     : public MockInputHandlerProxyClient {
263  public:
MockInputHandlerProxyClientWithDidAnimateForInput()264   MockInputHandlerProxyClientWithDidAnimateForInput() {}
~MockInputHandlerProxyClientWithDidAnimateForInput()265   ~MockInputHandlerProxyClientWithDidAnimateForInput() override {}
266 
267   MOCK_METHOD0(DidAnimateForInput, void());
268 
269  private:
270   DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidAnimateForInput);
271 };
272 
CreateWebTouchPoint(WebTouchPoint::State state,float x,float y)273 WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state,
274                                   float x,
275                                   float y) {
276   WebTouchPoint point;
277   point.state = state;
278   point.SetPositionInScreen(x, y);
279   point.SetPositionInWidget(x, y);
280   return point;
281 }
282 
283 const cc::InputHandler::ScrollStatus kImplThreadScrollState(
284     cc::InputHandler::SCROLL_ON_IMPL_THREAD,
285     cc::MainThreadScrollingReason::kNotScrollingOnMain);
286 
287 const cc::InputHandler::ScrollStatus kMainThreadScrollState(
288     cc::InputHandler::SCROLL_ON_MAIN_THREAD,
289     cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
290 
291 const cc::InputHandler::ScrollStatus kScrollIgnoredScrollState(
292     cc::InputHandler::SCROLL_IGNORED,
293     cc::MainThreadScrollingReason::kNotScrollable);
294 
295 }  // namespace
296 
297 class TestInputHandlerProxy : public InputHandlerProxy {
298  public:
TestInputHandlerProxy(cc::InputHandler * input_handler,InputHandlerProxyClient * client,bool force_input_to_main_thread)299   TestInputHandlerProxy(cc::InputHandler* input_handler,
300                         InputHandlerProxyClient* client,
301                         bool force_input_to_main_thread)
302       : InputHandlerProxy(input_handler, client, force_input_to_main_thread) {}
RecordMainThreadScrollingReasonsForTest(blink::WebGestureDevice device,uint32_t reasons)303   void RecordMainThreadScrollingReasonsForTest(blink::WebGestureDevice device,
304                                                uint32_t reasons) {
305     RecordMainThreadScrollingReasons(device, reasons);
306   }
307 
308   MOCK_METHOD0(SetNeedsAnimateInput, void());
309 
HitTestTouchEventForTest(const blink::WebTouchEvent & touch_event,bool * is_touching_scrolling_layer,cc::TouchAction * white_listed_touch_action)310   EventDisposition HitTestTouchEventForTest(
311       const blink::WebTouchEvent& touch_event,
312       bool* is_touching_scrolling_layer,
313       cc::TouchAction* white_listed_touch_action) {
314     return HitTestTouchEvent(touch_event, is_touching_scrolling_layer,
315                              white_listed_touch_action);
316   }
317 
HandleMouseWheelForTest(const blink::WebMouseWheelEvent & wheel_event)318   EventDisposition HandleMouseWheelForTest(
319       const blink::WebMouseWheelEvent& wheel_event) {
320     return HandleMouseWheel(wheel_event);
321   }
322 
323   // This is needed because the tests can't directly call
324   // DispatchQueuedInputEvents since it is private.
DispatchQueuedInputEventsHelper()325   void DispatchQueuedInputEventsHelper() { DispatchQueuedInputEvents(); }
326 };
327 
328 class InputHandlerProxyTest
329     : public testing::Test,
330       public testing::WithParamInterface<InputHandlerProxyTestType> {
331  public:
InputHandlerProxyTest()332   InputHandlerProxyTest()
333       : synchronous_root_scroll_(
334             GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER ||
335             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_SYNCHRONOUS),
336         install_synchronous_handler_(
337             GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER ||
338             GetParam() == CHILD_SCROLL_SYNCHRONOUS_HANDLER ||
339             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_SYNCHRONOUS ||
340             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_SYNCHRONOUS),
341         compositor_touch_action_enabled_(
342             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_NORMAL ||
343             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_ROOT_SYNCHRONOUS ||
344             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_NORMAL ||
345             GetParam() == COMPOSITOR_TOUCH_ACTION_ENABLED_CHILD_SYNCHRONOUS),
346         expected_disposition_(InputHandlerProxy::DID_HANDLE) {
347     if (compositor_touch_action_enabled_)
348       feature_list_.InitAndEnableFeature(features::kCompositorTouchAction);
349     else
350       feature_list_.InitAndDisableFeature(features::kCompositorTouchAction);
351     input_handler_ = std::make_unique<TestInputHandlerProxy>(
352         &mock_input_handler_, &mock_client_,
353         /*force_input_to_main_thread=*/false);
354     scroll_result_did_scroll_.did_scroll = true;
355     scroll_result_did_not_scroll_.did_scroll = false;
356 
357     if (install_synchronous_handler_) {
358       EXPECT_CALL(mock_input_handler_,
359                   RequestUpdateForSynchronousInputHandler())
360           .Times(1);
361       input_handler_->SetSynchronousInputHandler(
362           &mock_synchronous_input_handler_);
363     }
364 
365     mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_);
366 
367     // Set a default device so tests don't always have to set this.
368     gesture_.SetSourceDevice(blink::WebGestureDevice::kTouchpad);
369   }
370 
371   virtual ~InputHandlerProxyTest() = default;
372 
373 // This is defined as a macro so the line numbers can be traced back to the
374 // correct spot when it fails.
375 #define EXPECT_SET_NEEDS_ANIMATE_INPUT(times)                              \
376   do {                                                                     \
377     EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(times); \
378   } while (false)
379 
380 // This is defined as a macro because when an expectation is not satisfied the
381 // only output you get out of gmock is the line number that set the expectation.
382 #define VERIFY_AND_RESET_MOCKS()                                     \
383   do {                                                               \
384     testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \
385     testing::Mock::VerifyAndClearExpectations(                       \
386         &mock_synchronous_input_handler_);                           \
387     testing::Mock::VerifyAndClearExpectations(&mock_client_);        \
388   } while (false)
389 
Animate(base::TimeTicks time)390   void Animate(base::TimeTicks time) { input_handler_->Animate(time); }
391 
SetSmoothScrollEnabled(bool value)392   void SetSmoothScrollEnabled(bool value) {
393   }
394 
histogram_tester()395   base::HistogramTester& histogram_tester() { return histogram_tester_; }
396 
397  protected:
398   void GestureScrollStarted();
399   void ScrollHandlingSwitchedToMainThread();
400   void GestureScrollIgnored();
401   void FlingAndSnap();
402 
403   const bool synchronous_root_scroll_;
404   const bool install_synchronous_handler_;
405   const bool compositor_touch_action_enabled_;
406   testing::StrictMock<MockInputHandler> mock_input_handler_;
407   testing::StrictMock<MockSynchronousInputHandler>
408       mock_synchronous_input_handler_;
409   std::unique_ptr<TestInputHandlerProxy> input_handler_;
410   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
411   WebGestureEvent gesture_;
412   InputHandlerProxy::EventDisposition expected_disposition_;
413   base::HistogramTester histogram_tester_;
414   cc::InputHandlerScrollResult scroll_result_did_scroll_;
415   cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
416 
417  private:
418   base::test::ScopedFeatureList feature_list_;
419 };
420 
421 // The helper basically returns the EventDisposition that is returned by
422 // RouteToTypeSpecificHandler. This is done by passing in a callback when
423 // calling HandleInputEventWithLatencyInfo. By design, DispatchSingleInputEvent
424 // will then call this callback with the disposition returned by
425 // RouteToTypeSpecificHandler and that is what gets returned by this helper.
HandleInputEventWithLatencyInfo(TestInputHandlerProxy * input_handler,const blink::WebInputEvent & event)426 InputHandlerProxy::EventDisposition HandleInputEventWithLatencyInfo(
427     TestInputHandlerProxy* input_handler,
428     const blink::WebInputEvent& event) {
429   WebScopedInputEvent scoped_input_event(event.Clone());
430   InputHandlerProxy::EventDisposition event_disposition =
431       InputHandlerProxy::DID_NOT_HANDLE;
432   input_handler->HandleInputEventWithLatencyInfo(
433       std::move(scoped_input_event), ui::LatencyInfo(),
434       base::BindLambdaForTesting(
435           [&event_disposition](
436               InputHandlerProxy::EventDisposition disposition,
437               WebScopedInputEvent event, const LatencyInfo& latency_info,
438               std::unique_ptr<ui::DidOverscrollParams> callback,
439               const blink::WebInputEventAttribution& attribution) {
440             event_disposition = disposition;
441           }));
442   return event_disposition;
443 }
444 
445 // This helper forces the CompositorThreadEventQueue to be flushed.
HandleInputEventAndFlushEventQueue(testing::StrictMock<MockInputHandler> & mock_input_handler,TestInputHandlerProxy * input_handler,const blink::WebInputEvent & event)446 InputHandlerProxy::EventDisposition HandleInputEventAndFlushEventQueue(
447     testing::StrictMock<MockInputHandler>& mock_input_handler,
448     TestInputHandlerProxy* input_handler,
449     const blink::WebInputEvent& event) {
450   EXPECT_CALL(mock_input_handler, SetNeedsAnimateInput())
451       .Times(testing::AnyNumber());
452   WebScopedInputEvent scoped_input_event(event.Clone());
453   InputHandlerProxy::EventDisposition event_disposition =
454       InputHandlerProxy::DID_NOT_HANDLE;
455   input_handler->HandleInputEventWithLatencyInfo(
456       std::move(scoped_input_event), ui::LatencyInfo(),
457       base::BindLambdaForTesting(
458           [&event_disposition](
459               InputHandlerProxy::EventDisposition disposition,
460               WebScopedInputEvent event, const LatencyInfo& latency_info,
461               std::unique_ptr<ui::DidOverscrollParams> callback,
462               const blink::WebInputEventAttribution& attribution) {
463             event_disposition = disposition;
464           }));
465 
466   input_handler->DispatchQueuedInputEventsHelper();
467   return event_disposition;
468 }
469 
470 class InputHandlerProxyEventQueueTest : public testing::Test {
471  public:
InputHandlerProxyEventQueueTest()472   InputHandlerProxyEventQueueTest()
473       : input_handler_proxy_(&mock_input_handler_,
474                              &mock_client_,
475                              /*force_input_to_main_thread=*/false) {
476     if (input_handler_proxy_.compositor_event_queue_)
477       input_handler_proxy_.compositor_event_queue_ =
478           std::make_unique<CompositorThreadEventQueue>();
479     SetScrollPredictionEnabled(true);
480   }
481 
482   ~InputHandlerProxyEventQueueTest() = default;
483 
HandleGestureEvent(WebInputEvent::Type type,float delta_y_or_scale=0,int x=0,int y=0)484   void HandleGestureEvent(WebInputEvent::Type type,
485                           float delta_y_or_scale = 0,
486                           int x = 0,
487                           int y = 0) {
488     HandleGestureEventWithSourceDevice(
489         type, blink::WebGestureDevice::kTouchscreen, delta_y_or_scale, x, y);
490   }
491 
HandleGestureEventWithSourceDevice(WebInputEvent::Type type,WebGestureDevice source_device,float delta_y_or_scale=0,int x=0,int y=0)492   void HandleGestureEventWithSourceDevice(WebInputEvent::Type type,
493                                           WebGestureDevice source_device,
494                                           float delta_y_or_scale = 0,
495                                           int x = 0,
496                                           int y = 0) {
497     LatencyInfo latency;
498     input_handler_proxy_.HandleInputEventWithLatencyInfo(
499         CreateGestureScrollPinch(type, source_device,
500                                  input_handler_proxy_.tick_clock_->NowTicks(),
501                                  delta_y_or_scale, x, y),
502         latency,
503         base::BindOnce(
504             &InputHandlerProxyEventQueueTest::DidHandleInputEventAndOverscroll,
505             weak_ptr_factory_.GetWeakPtr()));
506   }
507 
HandleMouseEvent(WebInputEvent::Type type,int x=0,int y=0)508   void HandleMouseEvent(WebInputEvent::Type type, int x = 0, int y = 0) {
509     WebMouseEvent mouse_event(type, WebInputEvent::kNoModifiers,
510                               WebInputEvent::GetStaticTimeStampForTests());
511 
512     mouse_event.SetPositionInWidget(gfx::PointF(x, y));
513     mouse_event.button = blink::WebMouseEvent::Button::kLeft;
514     HandleInputEventWithLatencyInfo(&input_handler_proxy_, mouse_event);
515   }
516 
DidHandleInputEventAndOverscroll(InputHandlerProxy::EventDisposition event_disposition,WebScopedInputEvent input_event,const ui::LatencyInfo & latency_info,std::unique_ptr<ui::DidOverscrollParams> overscroll_params,const blink::WebInputEventAttribution & attribution)517   void DidHandleInputEventAndOverscroll(
518       InputHandlerProxy::EventDisposition event_disposition,
519       WebScopedInputEvent input_event,
520       const ui::LatencyInfo& latency_info,
521       std::unique_ptr<ui::DidOverscrollParams> overscroll_params,
522       const blink::WebInputEventAttribution& attribution) {
523     event_disposition_recorder_.push_back(event_disposition);
524     latency_info_recorder_.push_back(latency_info);
525   }
526 
event_queue()527   base::circular_deque<std::unique_ptr<EventWithCallback>>& event_queue() {
528     return input_handler_proxy_.compositor_event_queue_->queue_;
529   }
530 
SetInputHandlerProxyTickClockForTesting(const base::TickClock * tick_clock)531   void SetInputHandlerProxyTickClockForTesting(
532       const base::TickClock* tick_clock) {
533     input_handler_proxy_.SetTickClockForTesting(tick_clock);
534   }
535 
DeliverInputForBeginFrame()536   void DeliverInputForBeginFrame() {
537     constexpr base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
538     base::TimeTicks frame_time =
539         WebInputEvent::GetStaticTimeStampForTests() +
540         (next_begin_frame_number_ - viz::BeginFrameArgs::kStartingFrameNumber) *
541             interval;
542     input_handler_proxy_.DeliverInputForBeginFrame(viz::BeginFrameArgs::Create(
543         BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, frame_time,
544         frame_time + interval, interval, viz::BeginFrameArgs::NORMAL));
545   }
546 
DeliverInputForHighLatencyMode()547   void DeliverInputForHighLatencyMode() {
548     input_handler_proxy_.DeliverInputForHighLatencyMode();
549   }
550 
SetScrollPredictionEnabled(bool enabled)551   void SetScrollPredictionEnabled(bool enabled) {
552     input_handler_proxy_.scroll_predictor_ =
553         enabled ? std::make_unique<ScrollPredictor>() : nullptr;
554   }
555 
556   std::unique_ptr<ui::InputPredictor::InputData>
GestureScrollEventPredictionAvailable()557   GestureScrollEventPredictionAvailable() {
558     return input_handler_proxy_.scroll_predictor_->predictor_
559         ->GeneratePrediction(WebInputEvent::GetStaticTimeStampForTests());
560   }
561 
562  protected:
563   testing::StrictMock<MockInputHandler> mock_input_handler_;
564   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
565   TestInputHandlerProxy input_handler_proxy_;
566   std::vector<InputHandlerProxy::EventDisposition> event_disposition_recorder_;
567   std::vector<ui::LatencyInfo> latency_info_recorder_;
568 
569   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
570 
571   base::test::SingleThreadTaskEnvironment task_environment_;
572   base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_{this};
573 };
574 
575 // Tests that changing source devices mid gesture scroll is handled gracefully.
576 // For example, when a touch scroll is in progress and the user initiates a
577 // scrollbar scroll before the touch scroll has had a chance to dispatch a GSE.
TEST_P(InputHandlerProxyTest,NestedGestureBasedScrolls)578 TEST_P(InputHandlerProxyTest, NestedGestureBasedScrolls) {
579   // Touchpad initiates a scroll.
580   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
581       .WillOnce(testing::Return(kImplThreadScrollState));
582   EXPECT_CALL(
583       mock_input_handler_,
584       RecordScrollBegin(cc::ScrollInputType::kWheel,
585                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
586       .Times(1);
587 
588   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
589   gesture_.SetSourceDevice(blink::WebGestureDevice::kTouchpad);
590   EXPECT_EQ(InputHandlerProxy::DID_HANDLE,
591             HandleInputEventAndFlushEventQueue(mock_input_handler_,
592                                                input_handler_.get(), gesture_));
593   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
594 
595   VERIFY_AND_RESET_MOCKS();
596 
597   // Before ScrollEnd for touchpad is fired, user starts a thumb drag. This is
598   // expected to immediately end the touchpad scroll.
599   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(cc::ScrollInputType::kWheel))
600       .Times(1);
601   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
602   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
603       .WillOnce(testing::Return(kImplThreadScrollState));
604   // TODO(crbug.com/1060708): This should be called once.
605   EXPECT_CALL(
606       mock_input_handler_,
607       RecordScrollBegin(cc::ScrollInputType::kScrollbar,
608                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
609       .Times(0);
610   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
611   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
612       .WillOnce(testing::Return(false));
613   WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
614                             WebInputEvent::kNoModifiers,
615                             WebInputEvent::GetStaticTimeStampForTests());
616   mouse_event.SetPositionInWidget(gfx::PointF(0, 20));
617   mouse_event.button = blink::WebMouseEvent::Button::kLeft;
618   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
619             HandleInputEventAndFlushEventQueue(
620                 mock_input_handler_, input_handler_.get(), mouse_event));
621 
622   VERIFY_AND_RESET_MOCKS();
623 
624   // Touchpad GSE comes in while a scrollbar drag is in progress. This is
625   // expected to be dropped because a scrollbar scroll is currently active.
626   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
627   gesture_.SetSourceDevice(blink::WebGestureDevice::kTouchpad);
628   gesture_.data.scroll_update.delta_y = 0;
629   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(cc::ScrollInputType::kWheel))
630       .Times(1);
631   EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
632             HandleInputEventAndFlushEventQueue(mock_input_handler_,
633                                                input_handler_.get(), gesture_));
634   VERIFY_AND_RESET_MOCKS();
635 
636   // The GSE from the scrollbar needs to be handled.
637   EXPECT_CALL(mock_input_handler_,
638               RecordScrollEnd(cc::ScrollInputType::kScrollbar))
639       .Times(1);
640   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
641   mouse_event.SetType(WebInputEvent::kMouseUp);
642   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
643             HandleInputEventAndFlushEventQueue(
644                 mock_input_handler_, input_handler_.get(), mouse_event));
645 
646   VERIFY_AND_RESET_MOCKS();
647 }
648 
TEST_P(InputHandlerProxyTest,MouseWheelNoListener)649 TEST_P(InputHandlerProxyTest, MouseWheelNoListener) {
650   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
651   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
652       .WillRepeatedly(testing::Return(false));
653   EXPECT_CALL(mock_input_handler_,
654               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
655       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
656 
657   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
658                            WebInputEvent::kControlKey,
659                            WebInputEvent::GetStaticTimeStampForTests());
660   EXPECT_EQ(expected_disposition_,
661             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
662   VERIFY_AND_RESET_MOCKS();
663 }
664 
TEST_P(InputHandlerProxyTest,MouseWheelPassiveListener)665 TEST_P(InputHandlerProxyTest, MouseWheelPassiveListener) {
666   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
667   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
668       .WillRepeatedly(testing::Return(false));
669   EXPECT_CALL(mock_input_handler_,
670               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
671       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
672 
673   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
674                            WebInputEvent::kControlKey,
675                            WebInputEvent::GetStaticTimeStampForTests());
676   EXPECT_EQ(expected_disposition_,
677             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
678   VERIFY_AND_RESET_MOCKS();
679 }
680 
TEST_P(InputHandlerProxyTest,MouseWheelBlockingListener)681 TEST_P(InputHandlerProxyTest, MouseWheelBlockingListener) {
682   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
683   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
684       .WillRepeatedly(testing::Return(true));
685 
686   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
687                            WebInputEvent::kControlKey,
688                            WebInputEvent::GetStaticTimeStampForTests());
689   EXPECT_EQ(expected_disposition_,
690             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
691   VERIFY_AND_RESET_MOCKS();
692 }
693 
TEST_P(InputHandlerProxyTest,MouseWheelBlockingAndPassiveListener)694 TEST_P(InputHandlerProxyTest, MouseWheelBlockingAndPassiveListener) {
695   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
696   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
697       .WillRepeatedly(testing::Return(true));
698   // We will not call GetEventListenerProperties because we early out when we
699   // hit blocking region.
700   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
701                            WebInputEvent::kControlKey,
702                            WebInputEvent::GetStaticTimeStampForTests());
703   EXPECT_EQ(expected_disposition_,
704             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
705   VERIFY_AND_RESET_MOCKS();
706 }
707 
TEST_P(InputHandlerProxyTest,MouseWheelEventOutsideBlockingListener)708 TEST_P(InputHandlerProxyTest, MouseWheelEventOutsideBlockingListener) {
709   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
710   EXPECT_CALL(mock_input_handler_,
711               HasBlockingWheelEventHandlerAt(
712                   testing::Property(&gfx::Point::y, testing::Gt(10))))
713       .WillRepeatedly(testing::Return(true));
714   EXPECT_CALL(mock_input_handler_,
715               HasBlockingWheelEventHandlerAt(
716                   testing::Property(&gfx::Point::y, testing::Le(10))))
717       .WillRepeatedly(testing::Return(false));
718   EXPECT_CALL(mock_input_handler_,
719               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
720       .WillRepeatedly(testing::Return(cc::EventListenerProperties::kBlocking));
721 
722   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
723                            WebInputEvent::kControlKey,
724                            WebInputEvent::GetStaticTimeStampForTests());
725   wheel.SetPositionInScreen(0, 5);
726   wheel.SetPositionInWidget(0, 5);
727   EXPECT_EQ(expected_disposition_,
728             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
729   VERIFY_AND_RESET_MOCKS();
730 }
731 
TEST_P(InputHandlerProxyTest,MouseWheelEventOutsideBlockingListenerWithPassiveListener)732 TEST_P(InputHandlerProxyTest,
733        MouseWheelEventOutsideBlockingListenerWithPassiveListener) {
734   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
735   EXPECT_CALL(mock_input_handler_,
736               HasBlockingWheelEventHandlerAt(
737                   testing::Property(&gfx::Point::y, testing::Gt(10))))
738       .WillRepeatedly(testing::Return(true));
739   EXPECT_CALL(mock_input_handler_,
740               HasBlockingWheelEventHandlerAt(
741                   testing::Property(&gfx::Point::y, testing::Le(10))))
742       .WillRepeatedly(testing::Return(false));
743   EXPECT_CALL(mock_input_handler_,
744               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
745       .WillRepeatedly(
746           testing::Return(cc::EventListenerProperties::kBlockingAndPassive));
747 
748   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
749                            WebInputEvent::kControlKey,
750                            WebInputEvent::GetStaticTimeStampForTests());
751   wheel.SetPositionInScreen(0, 5);
752   wheel.SetPositionInWidget(0, 5);
753   EXPECT_EQ(expected_disposition_,
754             HandleInputEventWithLatencyInfo(input_handler_.get(), wheel));
755   VERIFY_AND_RESET_MOCKS();
756 }
757 
GestureScrollStarted()758 void InputHandlerProxyTest::GestureScrollStarted() {
759   // We shouldn't send any events to the widget for this gesture.
760   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
761   VERIFY_AND_RESET_MOCKS();
762 
763   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
764       .WillOnce(testing::Return(kImplThreadScrollState));
765   EXPECT_CALL(
766       mock_input_handler_,
767       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
768       .Times(1);
769 
770   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
771   EXPECT_EQ(expected_disposition_,
772             HandleInputEventAndFlushEventQueue(mock_input_handler_,
773                                                input_handler_.get(), gesture_));
774 
775   // The event should not be marked as handled if scrolling is not possible.
776   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
777   VERIFY_AND_RESET_MOCKS();
778 
779   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
780   gesture_.data.scroll_update.delta_y =
781       -40;  // -Y means scroll down - i.e. in the +Y direction.
782   EXPECT_CALL(
783       mock_input_handler_,
784       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
785                    _))
786       .WillOnce(testing::Return(scroll_result_did_not_scroll_));
787   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
788       .WillOnce(testing::Return(false));
789   EXPECT_EQ(expected_disposition_,
790             HandleInputEventAndFlushEventQueue(mock_input_handler_,
791                                                input_handler_.get(), gesture_));
792 
793   // Mark the event as handled if scroll happens.
794   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
795   VERIFY_AND_RESET_MOCKS();
796 
797   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
798       .WillOnce(testing::Return(false));
799   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
800   gesture_.data.scroll_update.delta_y =
801       -40;  // -Y means scroll down - i.e. in the +Y direction.
802   EXPECT_CALL(
803       mock_input_handler_,
804       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
805                    _))
806       .WillOnce(testing::Return(scroll_result_did_scroll_));
807   EXPECT_EQ(expected_disposition_,
808             HandleInputEventAndFlushEventQueue(mock_input_handler_,
809                                                input_handler_.get(), gesture_));
810 
811   VERIFY_AND_RESET_MOCKS();
812 
813   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
814   gesture_.data.scroll_update.delta_y = 0;
815   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
816   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
817   EXPECT_EQ(expected_disposition_,
818             HandleInputEventAndFlushEventQueue(mock_input_handler_,
819                                                input_handler_.get(), gesture_));
820 
821   VERIFY_AND_RESET_MOCKS();
822 }
TEST_P(InputHandlerProxyTest,GestureScrollStarted)823 TEST_P(InputHandlerProxyTest, GestureScrollStarted) {
824   GestureScrollStarted();
825 }
826 
TEST_P(InputHandlerProxyTest,GestureScrollOnMainThread)827 TEST_P(InputHandlerProxyTest, GestureScrollOnMainThread) {
828   // We should send all events to the widget for this gesture.
829   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
830   VERIFY_AND_RESET_MOCKS();
831 
832   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
833       .WillOnce(testing::Return(kMainThreadScrollState));
834   EXPECT_CALL(
835       mock_input_handler_,
836       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
837       .Times(1);
838 
839   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
840   EXPECT_EQ(expected_disposition_,
841             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
842 
843   VERIFY_AND_RESET_MOCKS();
844 
845   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
846   gesture_.data.scroll_update.delta_y = 40;
847   EXPECT_EQ(expected_disposition_,
848             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
849 
850   VERIFY_AND_RESET_MOCKS();
851 
852   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
853   gesture_.data.scroll_update.delta_y = 0;
854   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
855   EXPECT_EQ(expected_disposition_,
856             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
857 
858   VERIFY_AND_RESET_MOCKS();
859 }
860 
TEST_P(InputHandlerProxyTest,GestureScrollIgnored)861 TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
862   // We shouldn't handle the GestureScrollBegin.
863   // Instead, we should get a DROP_EVENT result, indicating
864   // that we could determine that there's nothing that could scroll or otherwise
865   // react to this gesture sequence and thus we should drop the whole gesture
866   // sequence on the floor, except for the ScrollEnd.
867   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
868   VERIFY_AND_RESET_MOCKS();
869 
870   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
871       .WillOnce(testing::Return(kScrollIgnoredScrollState));
872   EXPECT_CALL(
873       mock_input_handler_,
874       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
875       .Times(1);
876 
877   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
878   EXPECT_EQ(expected_disposition_,
879             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
880 
881   VERIFY_AND_RESET_MOCKS();
882 
883   // GSB is dropped and not sent to the main thread, GSE shouldn't get sent to
884   // the main thread, either.
885   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
886   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
887   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
888   EXPECT_EQ(expected_disposition_,
889             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
890 
891   VERIFY_AND_RESET_MOCKS();
892 }
893 
TEST_P(InputHandlerProxyTest,GestureScrollByPage)894 TEST_P(InputHandlerProxyTest, GestureScrollByPage) {
895   // We should send all events to the widget for this gesture.
896   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
897   VERIFY_AND_RESET_MOCKS();
898 
899   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
900   gesture_.data.scroll_begin.delta_hint_units =
901       ui::ScrollGranularity::kScrollByPage;
902   EXPECT_CALL(
903       mock_input_handler_,
904       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
905       .Times(1);
906   EXPECT_EQ(expected_disposition_,
907             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
908 
909   VERIFY_AND_RESET_MOCKS();
910 
911   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
912   gesture_.data.scroll_update.delta_y = 1;
913   gesture_.data.scroll_update.delta_units =
914       ui::ScrollGranularity::kScrollByPage;
915   EXPECT_EQ(expected_disposition_,
916             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
917 
918   VERIFY_AND_RESET_MOCKS();
919 
920   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
921   gesture_.data.scroll_update.delta_y = 0;
922   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
923   EXPECT_EQ(expected_disposition_,
924             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
925 
926   VERIFY_AND_RESET_MOCKS();
927 }
928 
TEST_P(InputHandlerProxyTest,GestureScrollBeginThatTargetViewport)929 TEST_P(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) {
930   // We shouldn't send any events to the widget for this gesture.
931   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
932   VERIFY_AND_RESET_MOCKS();
933 
934   EXPECT_CALL(mock_input_handler_, RootScrollBegin(_, _))
935       .WillOnce(testing::Return(kImplThreadScrollState));
936   EXPECT_CALL(
937       mock_input_handler_,
938       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
939       .Times(1);
940 
941   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
942   gesture_.data.scroll_begin.target_viewport = true;
943   EXPECT_EQ(expected_disposition_,
944             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
945 
946   VERIFY_AND_RESET_MOCKS();
947 }
948 
FlingAndSnap()949 void InputHandlerProxyTest::FlingAndSnap() {
950   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
951   VERIFY_AND_RESET_MOCKS();
952 
953   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
954       .WillOnce(testing::Return(kImplThreadScrollState));
955   EXPECT_CALL(
956       mock_input_handler_,
957       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
958       .Times(1);
959 
960   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
961   EXPECT_EQ(expected_disposition_,
962             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
963 
964   // The event should be dropped if InputHandler decides to snap.
965   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
966   VERIFY_AND_RESET_MOCKS();
967 
968   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
969   gesture_.data.scroll_update.delta_y =
970       -40;  // -Y means scroll down - i.e. in the +Y direction.
971   gesture_.data.scroll_update.inertial_phase =
972       blink::WebGestureEvent::InertialPhaseState::kMomentum;
973   EXPECT_CALL(mock_input_handler_,
974               GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _))
975       .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)),
976                       testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)),
977                       testing::Return(true)));
978   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
979   EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
980   EXPECT_EQ(expected_disposition_,
981             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
982   VERIFY_AND_RESET_MOCKS();
983 }
984 
TEST_P(InputHandlerProxyTest,SnapFlingIgnoresFollowingGSUAndGSE)985 TEST_P(InputHandlerProxyTest, SnapFlingIgnoresFollowingGSUAndGSE) {
986   FlingAndSnap();
987   // The next GestureScrollUpdate should also be ignored, and will not ask for
988   // snap position.
989   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
990 
991   EXPECT_CALL(mock_input_handler_,
992               GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _))
993       .Times(0);
994   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
995   EXPECT_EQ(expected_disposition_,
996             HandleInputEventAndFlushEventQueue(mock_input_handler_,
997                                                input_handler_.get(), gesture_));
998   VERIFY_AND_RESET_MOCKS();
999 
1000   // The GestureScrollEnd should also be ignored.
1001   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1002   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
1003   gesture_.data.scroll_end.inertial_phase =
1004       blink::WebGestureEvent::InertialPhaseState::kMomentum;
1005   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0);
1006   EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0);
1007   EXPECT_EQ(expected_disposition_,
1008             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1009                                                input_handler_.get(), gesture_));
1010   VERIFY_AND_RESET_MOCKS();
1011 }
1012 
TEST_P(InputHandlerProxyTest,GesturePinch)1013 TEST_P(InputHandlerProxyTest, GesturePinch) {
1014   // We shouldn't send any events to the widget for this gesture.
1015   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1016   VERIFY_AND_RESET_MOCKS();
1017 
1018   gesture_.SetType(WebInputEvent::kGesturePinchBegin);
1019   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1020   EXPECT_EQ(expected_disposition_,
1021             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1022                                                input_handler_.get(), gesture_));
1023 
1024   VERIFY_AND_RESET_MOCKS();
1025 
1026   gesture_.SetType(WebInputEvent::kGesturePinchUpdate);
1027   gesture_.data.pinch_update.scale = 1.5;
1028   gesture_.SetPositionInWidget(gfx::PointF(7, 13));
1029   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
1030   EXPECT_EQ(expected_disposition_,
1031             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1032                                                input_handler_.get(), gesture_));
1033 
1034   VERIFY_AND_RESET_MOCKS();
1035 
1036   gesture_.SetType(WebInputEvent::kGesturePinchUpdate);
1037   gesture_.data.pinch_update.scale = 0.5;
1038   gesture_.SetPositionInWidget(gfx::PointF(9, 6));
1039   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
1040   EXPECT_EQ(expected_disposition_,
1041             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1042                                                input_handler_.get(), gesture_));
1043 
1044   VERIFY_AND_RESET_MOCKS();
1045 
1046   gesture_.SetType(WebInputEvent::kGesturePinchEnd);
1047   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(9, 6), true));
1048   EXPECT_EQ(expected_disposition_,
1049             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1050                                                input_handler_.get(), gesture_));
1051 
1052   VERIFY_AND_RESET_MOCKS();
1053 }
1054 
TEST_P(InputHandlerProxyTest,GesturePinchAfterScrollOnMainThread)1055 TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
1056   // Scrolls will start by being sent to the main thread.
1057   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1058   VERIFY_AND_RESET_MOCKS();
1059 
1060   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1061       .WillOnce(testing::Return(kMainThreadScrollState));
1062   EXPECT_CALL(
1063       mock_input_handler_,
1064       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
1065       .Times(1);
1066 
1067   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
1068   EXPECT_EQ(expected_disposition_,
1069             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1070                                                input_handler_.get(), gesture_));
1071 
1072   VERIFY_AND_RESET_MOCKS();
1073 
1074   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
1075   gesture_.data.scroll_update.delta_y = 40;
1076   EXPECT_EQ(expected_disposition_,
1077             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1078                                                input_handler_.get(), gesture_));
1079 
1080   // However, after the pinch gesture starts, they should go to the impl
1081   // thread.
1082   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1083   VERIFY_AND_RESET_MOCKS();
1084 
1085   gesture_.SetType(WebInputEvent::kGesturePinchBegin);
1086   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1087   EXPECT_EQ(expected_disposition_,
1088             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1089                                                input_handler_.get(), gesture_));
1090 
1091   VERIFY_AND_RESET_MOCKS();
1092 
1093   gesture_.SetType(WebInputEvent::kGesturePinchUpdate);
1094   gesture_.data.pinch_update.scale = 1.5;
1095   gesture_.SetPositionInWidget(gfx::PointF(7, 13));
1096   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
1097   EXPECT_EQ(expected_disposition_,
1098             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1099                                                input_handler_.get(), gesture_));
1100 
1101   VERIFY_AND_RESET_MOCKS();
1102 
1103   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1104       .WillOnce(testing::Return(false));
1105   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
1106   gesture_.data.scroll_update.delta_y =
1107       -40;  // -Y means scroll down - i.e. in the +Y direction.
1108   EXPECT_CALL(
1109       mock_input_handler_,
1110       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1111                    _))
1112       .WillOnce(testing::Return(scroll_result_did_scroll_));
1113   EXPECT_EQ(expected_disposition_,
1114             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1115                                                input_handler_.get(), gesture_));
1116 
1117   VERIFY_AND_RESET_MOCKS();
1118 
1119   gesture_.SetType(WebInputEvent::kGesturePinchUpdate);
1120   gesture_.data.pinch_update.scale = 0.5;
1121   gesture_.SetPositionInWidget(gfx::PointF(9, 6));
1122   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
1123   EXPECT_EQ(expected_disposition_,
1124             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1125                                                input_handler_.get(), gesture_));
1126 
1127   VERIFY_AND_RESET_MOCKS();
1128 
1129   gesture_.SetType(WebInputEvent::kGesturePinchEnd);
1130   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(9, 6), true));
1131   EXPECT_EQ(expected_disposition_,
1132             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1133                                                input_handler_.get(), gesture_));
1134 
1135   // After the pinch gesture ends, they should go to back to the main
1136   // thread.
1137   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1138   VERIFY_AND_RESET_MOCKS();
1139 
1140   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
1141   gesture_.data.scroll_update.delta_y = 0;
1142   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1143   EXPECT_EQ(expected_disposition_,
1144             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1145 
1146   VERIFY_AND_RESET_MOCKS();
1147 }
1148 
ScrollHandlingSwitchedToMainThread()1149 void InputHandlerProxyTest::ScrollHandlingSwitchedToMainThread() {
1150   // We shouldn't send any events to the widget for this gesture.
1151   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1152   VERIFY_AND_RESET_MOCKS();
1153 
1154   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1155       .WillOnce(testing::Return(kImplThreadScrollState));
1156   EXPECT_CALL(
1157       mock_input_handler_,
1158       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1159       .Times(1);
1160 
1161   // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_.
1162   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
1163   EXPECT_EQ(expected_disposition_,
1164             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1165                                                input_handler_.get(), gesture_));
1166   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1167 
1168   VERIFY_AND_RESET_MOCKS();
1169 
1170   gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
1171   gesture_.data.scroll_update.delta_y = -40;
1172   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1173       .WillOnce(testing::Return(false));
1174   EXPECT_CALL(
1175       mock_input_handler_,
1176       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1177                    _))
1178       .WillOnce(testing::Return(scroll_result_did_scroll_));
1179   EXPECT_EQ(expected_disposition_,
1180             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1181                                                input_handler_.get(), gesture_));
1182   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1183   VERIFY_AND_RESET_MOCKS();
1184 
1185   // The scroll handling switches to the main thread, a GSB is sent to the main
1186   // thread to initiate the hit testing and compute the scroll chain.
1187   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1188   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
1189   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1190       .WillOnce(testing::Return(true));
1191   EXPECT_CALL(mock_client_, GenerateScrollBeginAndSendToMainThread(_, _));
1192   EXPECT_EQ(expected_disposition_,
1193             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1194                                                input_handler_.get(), gesture_));
1195   EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1196 
1197   VERIFY_AND_RESET_MOCKS();
1198 
1199   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
1200   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1201   EXPECT_EQ(expected_disposition_,
1202             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1203                                                input_handler_.get(), gesture_));
1204 
1205   VERIFY_AND_RESET_MOCKS();
1206 }
TEST_P(InputHandlerProxyTest,WheelScrollHandlingSwitchedToMainThread)1207 TEST_P(InputHandlerProxyTest, WheelScrollHandlingSwitchedToMainThread) {
1208   gesture_.SetSourceDevice(blink::WebGestureDevice::kTouchpad);
1209   ScrollHandlingSwitchedToMainThread();
1210 }
TEST_P(InputHandlerProxyTest,TouchScrollHandlingSwitchedToMainThread)1211 TEST_P(InputHandlerProxyTest, TouchScrollHandlingSwitchedToMainThread) {
1212   gesture_.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
1213   ScrollHandlingSwitchedToMainThread();
1214 }
1215 
TEST_P(InputHandlerProxyTest,GestureScrollOnImplThreadFlagClearedAfterScrollEnd)1216 TEST_P(InputHandlerProxyTest,
1217        GestureScrollOnImplThreadFlagClearedAfterScrollEnd) {
1218   // We shouldn't send any events to the widget for this gesture.
1219   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1220   VERIFY_AND_RESET_MOCKS();
1221 
1222   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1223       .WillOnce(testing::Return(kImplThreadScrollState));
1224   EXPECT_CALL(
1225       mock_input_handler_,
1226       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1227       .Times(1);
1228 
1229   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
1230   EXPECT_EQ(expected_disposition_,
1231             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1232 
1233   // After sending a GestureScrollBegin, the member variable
1234   // |gesture_scroll_on_impl_thread_| should be true.
1235   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1236 
1237   VERIFY_AND_RESET_MOCKS();
1238 
1239   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
1240   gesture_.SetType(WebInputEvent::kGestureScrollEnd);
1241   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1242   EXPECT_EQ(expected_disposition_,
1243             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1244 
1245   // |gesture_scroll_on_impl_thread_| should be false once a GestureScrollEnd
1246   // gets handled.
1247   EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1248 
1249   VERIFY_AND_RESET_MOCKS();
1250 }
1251 
TEST_P(InputHandlerProxyTest,BeginScrollWhenGestureScrollOnImplThreadFlagIsSet)1252 TEST_P(InputHandlerProxyTest,
1253        BeginScrollWhenGestureScrollOnImplThreadFlagIsSet) {
1254   // We shouldn't send any events to the widget for this gesture.
1255   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1256   VERIFY_AND_RESET_MOCKS();
1257 
1258   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1259       .WillOnce(testing::Return(kImplThreadScrollState));
1260   EXPECT_CALL(
1261       mock_input_handler_,
1262       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1263       .Times(1);
1264 
1265   gesture_.SetType(WebInputEvent::kGestureScrollBegin);
1266   EXPECT_EQ(expected_disposition_,
1267             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1268 
1269   // After sending a GestureScrollBegin, the member variable
1270   // |gesture_scroll_on_impl_thread_| should be true.
1271   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1272 
1273   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1274   VERIFY_AND_RESET_MOCKS();
1275 }
1276 
TEST_P(InputHandlerProxyTest,HitTestTouchEventNonNullTouchAction)1277 TEST_P(InputHandlerProxyTest, HitTestTouchEventNonNullTouchAction) {
1278   // One of the touch points is on a touch-region. So the event should be sent
1279   // to the main thread.
1280   expected_disposition_ = compositor_touch_action_enabled_
1281                               ? InputHandlerProxy::DID_HANDLE_NON_BLOCKING
1282                               : InputHandlerProxy::DID_NOT_HANDLE;
1283   VERIFY_AND_RESET_MOCKS();
1284 
1285   EXPECT_CALL(mock_input_handler_,
1286               EventListenerTypeForTouchStartOrMoveAt(
1287                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1288       .WillOnce(testing::Invoke([](const gfx::Point&,
1289                                    cc::TouchAction* touch_action) {
1290         *touch_action = cc::TouchAction::kMax;
1291         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1292       }));
1293 
1294   EXPECT_CALL(mock_input_handler_,
1295               EventListenerTypeForTouchStartOrMoveAt(
1296                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1297       .WillOnce(
1298           testing::Invoke([](const gfx::Point&, cc::TouchAction* touch_action) {
1299             *touch_action = cc::TouchAction::kPanUp;
1300             return cc::InputHandler::TouchStartOrMoveEventListenerType::
1301                 HANDLER_ON_SCROLLING_LAYER;
1302           }));
1303   // Since the second touch point hits a touch-region, there should be no
1304   // hit-testing for the third touch point.
1305 
1306   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1307                       WebInputEvent::GetStaticTimeStampForTests());
1308 
1309   touch.touches_length = 3;
1310   touch.touch_start_or_first_touch_move = true;
1311   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1312   touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1313   touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, -10, 10);
1314 
1315   bool is_touching_scrolling_layer;
1316   cc::TouchAction white_listed_touch_action = cc::TouchAction::kAuto;
1317   EXPECT_EQ(expected_disposition_, input_handler_->HitTestTouchEventForTest(
1318                                        touch, &is_touching_scrolling_layer,
1319                                        &white_listed_touch_action));
1320   EXPECT_TRUE(is_touching_scrolling_layer);
1321   EXPECT_EQ(white_listed_touch_action, cc::TouchAction::kPanUp);
1322   VERIFY_AND_RESET_MOCKS();
1323 }
1324 
TEST_P(InputHandlerProxyTest,HitTestTouchEventNullTouchAction)1325 TEST_P(InputHandlerProxyTest, HitTestTouchEventNullTouchAction) {
1326   // One of the touch points is on a touch-region. So the event should be sent
1327   // to the main thread.
1328   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1329   VERIFY_AND_RESET_MOCKS();
1330 
1331   EXPECT_CALL(mock_input_handler_,
1332               EventListenerTypeForTouchStartOrMoveAt(
1333                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1334       .WillOnce(testing::Return(
1335           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
1336 
1337   EXPECT_CALL(mock_input_handler_,
1338               EventListenerTypeForTouchStartOrMoveAt(
1339                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1340       .WillOnce(
1341           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
1342                               HANDLER_ON_SCROLLING_LAYER));
1343   // Since the second touch point hits a touch-region, there should be no
1344   // hit-testing for the third touch point.
1345 
1346   WebTouchEvent touch(WebInputEvent::kTouchMove, WebInputEvent::kNoModifiers,
1347                       WebInputEvent::GetStaticTimeStampForTests());
1348 
1349   touch.touches_length = 3;
1350   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1351   touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1352   touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, -10, 10);
1353 
1354   bool is_touching_scrolling_layer;
1355   cc::TouchAction* white_listed_touch_action = nullptr;
1356   EXPECT_EQ(expected_disposition_, input_handler_->HitTestTouchEventForTest(
1357                                        touch, &is_touching_scrolling_layer,
1358                                        white_listed_touch_action));
1359   EXPECT_TRUE(is_touching_scrolling_layer);
1360   EXPECT_TRUE(!white_listed_touch_action);
1361   VERIFY_AND_RESET_MOCKS();
1362 }
1363 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestNegative)1364 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
1365   // None of the three touch points fall in the touch region. So the event
1366   // should be dropped.
1367   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1368   VERIFY_AND_RESET_MOCKS();
1369 
1370   EXPECT_CALL(
1371       mock_input_handler_,
1372       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1373       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1374   EXPECT_CALL(
1375       mock_input_handler_,
1376       GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
1377       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1378   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1379       .Times(2)
1380       .WillRepeatedly(testing::Invoke([](const gfx::Point&,
1381                                          cc::TouchAction* touch_action) {
1382         *touch_action = cc::TouchAction::kPanUp;
1383         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1384       }));
1385   EXPECT_CALL(mock_client_,
1386               SetWhiteListedTouchAction(cc::TouchAction::kPanUp, 1,
1387                                         InputHandlerProxy::DROP_EVENT))
1388       .WillOnce(testing::Return());
1389 
1390   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1391                       WebInputEvent::GetStaticTimeStampForTests());
1392 
1393   touch.unique_touch_event_id = 1;
1394   touch.touches_length = 3;
1395   touch.touch_start_or_first_touch_move = true;
1396   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStateStationary, 0, 0);
1397   touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1398   touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, -10, 10);
1399   EXPECT_EQ(expected_disposition_,
1400             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1401 
1402   VERIFY_AND_RESET_MOCKS();
1403 }
1404 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestPositive)1405 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
1406   // One of the touch points is on a touch-region. So the event should be sent
1407   // to the main thread.
1408   expected_disposition_ = compositor_touch_action_enabled_
1409                               ? InputHandlerProxy::DID_HANDLE_NON_BLOCKING
1410                               : InputHandlerProxy::DID_NOT_HANDLE;
1411   VERIFY_AND_RESET_MOCKS();
1412 
1413   EXPECT_CALL(mock_input_handler_,
1414               EventListenerTypeForTouchStartOrMoveAt(
1415                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1416       .WillOnce(testing::Invoke([](const gfx::Point&,
1417                                    cc::TouchAction* touch_action) {
1418         *touch_action = cc::TouchAction::kAuto;
1419         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1420       }));
1421   EXPECT_CALL(mock_input_handler_,
1422               EventListenerTypeForTouchStartOrMoveAt(
1423                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1424       .WillOnce(
1425           testing::Invoke([](const gfx::Point&, cc::TouchAction* touch_action) {
1426             *touch_action = cc::TouchAction::kPanY;
1427             return cc::InputHandler::TouchStartOrMoveEventListenerType::
1428                 HANDLER_ON_SCROLLING_LAYER;
1429           }));
1430   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(cc::TouchAction::kPanY, 1,
1431                                                       expected_disposition_))
1432       .WillOnce(testing::Return());
1433   // Since the second touch point hits a touch-region, there should be no
1434   // hit-testing for the third touch point.
1435 
1436   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1437                       WebInputEvent::GetStaticTimeStampForTests());
1438 
1439   touch.unique_touch_event_id = 1;
1440   touch.touches_length = 3;
1441   touch.touch_start_or_first_touch_move = true;
1442   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1443   touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1444   touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, -10, 10);
1445   EXPECT_EQ(expected_disposition_,
1446             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1447 
1448   VERIFY_AND_RESET_MOCKS();
1449 }
1450 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestPassivePositive)1451 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPassivePositive) {
1452   // One of the touch points is not on a touch-region. So the event should be
1453   // sent to the impl thread.
1454   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1455   VERIFY_AND_RESET_MOCKS();
1456 
1457   EXPECT_CALL(
1458       mock_input_handler_,
1459       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1460       .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
1461   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1462       .Times(3)
1463       .WillOnce(testing::Invoke([](const gfx::Point&,
1464                                    cc::TouchAction* touch_action) {
1465         *touch_action = cc::TouchAction::kPanRight;
1466         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1467       }))
1468       .WillRepeatedly(testing::Invoke([](const gfx::Point&,
1469                                          cc::TouchAction* touch_action) {
1470         *touch_action = cc::TouchAction::kPanX;
1471         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1472       }));
1473   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(
1474                                 cc::TouchAction::kPanRight, 1,
1475                                 InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
1476       .WillOnce(testing::Return());
1477 
1478   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1479                       WebInputEvent::GetStaticTimeStampForTests());
1480 
1481   touch.unique_touch_event_id = 1;
1482   touch.touches_length = 3;
1483   touch.touch_start_or_first_touch_move = true;
1484   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1485   touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1486   touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, -10, 10);
1487   EXPECT_EQ(expected_disposition_,
1488             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1489 
1490   VERIFY_AND_RESET_MOCKS();
1491 }
1492 
TEST_P(InputHandlerProxyTest,TouchStartPassiveAndTouchEndBlocking)1493 TEST_P(InputHandlerProxyTest, TouchStartPassiveAndTouchEndBlocking) {
1494   // The touch start is not in a touch-region but there is a touch end handler
1495   // so to maintain targeting we need to dispatch the touch start as
1496   // non-blocking but drop all touch moves.
1497   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1498   VERIFY_AND_RESET_MOCKS();
1499 
1500   EXPECT_CALL(
1501       mock_input_handler_,
1502       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1503       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1504   EXPECT_CALL(
1505       mock_input_handler_,
1506       GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
1507       .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
1508   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1509       .WillOnce(testing::Invoke([](const gfx::Point&,
1510                                    cc::TouchAction* touch_action) {
1511         *touch_action = cc::TouchAction::kNone;
1512         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1513       }));
1514   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(
1515                                 cc::TouchAction::kNone, 1,
1516                                 InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
1517       .WillOnce(testing::Return());
1518 
1519   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1520                       WebInputEvent::GetStaticTimeStampForTests());
1521   touch.unique_touch_event_id = 1;
1522   touch.touches_length = 1;
1523   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1524   touch.touch_start_or_first_touch_move = true;
1525   EXPECT_EQ(expected_disposition_,
1526             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1527 
1528   touch.SetType(WebInputEvent::kTouchMove);
1529   touch.touches_length = 1;
1530   touch.touch_start_or_first_touch_move = false;
1531   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
1532   EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
1533             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1534   VERIFY_AND_RESET_MOCKS();
1535 }
1536 
TEST_P(InputHandlerProxyTest,TouchMoveBlockingAddedAfterPassiveTouchStart)1537 TEST_P(InputHandlerProxyTest, TouchMoveBlockingAddedAfterPassiveTouchStart) {
1538   // The touch start is not in a touch-region but there is a touch end handler
1539   // so to maintain targeting we need to dispatch the touch start as
1540   // non-blocking but drop all touch moves.
1541   VERIFY_AND_RESET_MOCKS();
1542 
1543   EXPECT_CALL(
1544       mock_input_handler_,
1545       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1546       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
1547   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1548       .WillOnce(testing::Return(
1549           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
1550   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
1551       .WillOnce(testing::Return());
1552 
1553   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
1554                       WebInputEvent::GetStaticTimeStampForTests());
1555   touch.touches_length = 1;
1556   touch.touch_start_or_first_touch_move = true;
1557   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
1558   EXPECT_EQ(InputHandlerProxy::DID_HANDLE_NON_BLOCKING,
1559             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1560 
1561   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1562       .WillOnce(testing::Return(
1563           cc::InputHandler::TouchStartOrMoveEventListenerType::HANDLER));
1564   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
1565       .WillOnce(testing::Return());
1566 
1567   touch.SetType(WebInputEvent::kTouchMove);
1568   touch.touches_length = 1;
1569   touch.touch_start_or_first_touch_move = true;
1570   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStateMoved, 10, 10);
1571   EXPECT_EQ(compositor_touch_action_enabled_
1572                 ? InputHandlerProxy::DID_HANDLE_NON_BLOCKING
1573                 : InputHandlerProxy::DID_NOT_HANDLE,
1574             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1575   VERIFY_AND_RESET_MOCKS();
1576 }
1577 
TEST(SynchronousInputHandlerProxyTest,StartupShutdown)1578 TEST(SynchronousInputHandlerProxyTest, StartupShutdown) {
1579   testing::StrictMock<MockInputHandler> mock_input_handler;
1580   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
1581   testing::StrictMock<MockSynchronousInputHandler>
1582       mock_synchronous_input_handler;
1583   ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client, false);
1584 
1585   // When adding a SynchronousInputHandler, immediately request an
1586   // UpdateRootLayerStateForSynchronousInputHandler() call.
1587   EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
1588       .Times(1);
1589   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
1590 
1591   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
1592   testing::Mock::VerifyAndClearExpectations(&mock_client);
1593   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
1594 
1595   EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
1596       .Times(0);
1597   proxy.SetSynchronousInputHandler(nullptr);
1598 
1599   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
1600   testing::Mock::VerifyAndClearExpectations(&mock_client);
1601   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
1602 }
1603 
TEST(SynchronousInputHandlerProxyTest,UpdateRootLayerState)1604 TEST(SynchronousInputHandlerProxyTest, UpdateRootLayerState) {
1605   testing::NiceMock<MockInputHandler> mock_input_handler;
1606   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
1607   testing::StrictMock<MockSynchronousInputHandler>
1608       mock_synchronous_input_handler;
1609   ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client, false);
1610 
1611   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
1612 
1613   // When adding a SynchronousInputHandler, immediately request an
1614   // UpdateRootLayerStateForSynchronousInputHandler() call.
1615   EXPECT_CALL(
1616       mock_synchronous_input_handler,
1617       UpdateRootLayerState(gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4),
1618                            gfx::SizeF(5, 6), 7, 8, 9))
1619       .Times(1);
1620   proxy.UpdateRootLayerStateForSynchronousInputHandler(
1621       gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4), gfx::SizeF(5, 6), 7, 8,
1622       9);
1623 
1624   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
1625   testing::Mock::VerifyAndClearExpectations(&mock_client);
1626   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
1627 }
1628 
TEST(SynchronousInputHandlerProxyTest,SetOffset)1629 TEST(SynchronousInputHandlerProxyTest, SetOffset) {
1630   testing::NiceMock<MockInputHandler> mock_input_handler;
1631   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
1632   testing::StrictMock<MockSynchronousInputHandler>
1633       mock_synchronous_input_handler;
1634   ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client, false);
1635 
1636   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
1637 
1638   EXPECT_CALL(mock_input_handler, SetSynchronousInputHandlerRootScrollOffset(
1639                                       gfx::ScrollOffset(5, 6)));
1640   proxy.SynchronouslySetRootScrollOffset(gfx::ScrollOffset(5, 6));
1641 
1642   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
1643   testing::Mock::VerifyAndClearExpectations(&mock_client);
1644   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
1645 }
1646 
TEST_F(InputHandlerProxyEventQueueTest,MouseEventOnScrollbarInitiatesGestureScroll)1647 TEST_F(InputHandlerProxyEventQueueTest,
1648        MouseEventOnScrollbarInitiatesGestureScroll) {
1649   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1650 
1651   // Test mousedown on the scrollbar. Expect to get GSB and GSU.
1652   HandleMouseEvent(WebInputEvent::kMouseDown);
1653   EXPECT_EQ(2ul, event_queue().size());
1654   EXPECT_EQ(event_queue()[0]->event().GetType(),
1655             blink::WebInputEvent::Type::kGestureScrollBegin);
1656   EXPECT_EQ(event_queue()[1]->event().GetType(),
1657             blink::WebInputEvent::Type::kGestureScrollUpdate);
1658 
1659   // Test mouseup on the scrollbar. Expect to get GSE.
1660   HandleMouseEvent(WebInputEvent::kMouseUp);
1661   EXPECT_EQ(3ul, event_queue().size());
1662   EXPECT_EQ(event_queue()[2]->event().GetType(),
1663             blink::WebInputEvent::Type::kGestureScrollEnd);
1664 }
1665 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedGestureScroll)1666 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScroll) {
1667   // Handle scroll on compositor.
1668   cc::InputHandlerScrollResult scroll_result_did_scroll_;
1669   scroll_result_did_scroll_.did_scroll = true;
1670 
1671   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1672       .WillOnce(testing::Return(kImplThreadScrollState));
1673   EXPECT_CALL(
1674       mock_input_handler_,
1675       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1676       .Times(1);
1677   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1678 
1679   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1680 
1681   // GestureScrollBegin will be processed immediately.
1682   EXPECT_EQ(0ul, event_queue().size());
1683   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1684   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[0]);
1685 
1686   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
1687 
1688   // GestureScrollUpdate will be queued.
1689   EXPECT_EQ(1ul, event_queue().size());
1690   EXPECT_EQ(-20, static_cast<const blink::WebGestureEvent&>(
1691                      event_queue().front()->event())
1692                      .data.scroll_update.delta_y);
1693   EXPECT_EQ(1ul, event_queue().front()->coalesced_count());
1694   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1695 
1696   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
1697 
1698   // GestureScrollUpdate will be coalesced.
1699   EXPECT_EQ(1ul, event_queue().size());
1700   EXPECT_EQ(-60, static_cast<const blink::WebGestureEvent&>(
1701                      event_queue().front()->event())
1702                      .data.scroll_update.delta_y);
1703   EXPECT_EQ(2ul, event_queue().front()->coalesced_count());
1704   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1705 
1706   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0);
1707   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1708 
1709   // GestureScrollEnd will be queued.
1710   EXPECT_EQ(2ul, event_queue().size());
1711   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1712   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1713 
1714   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1715       .WillOnce(testing::Return(false));
1716   EXPECT_CALL(
1717       mock_input_handler_,
1718       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1719                    _))
1720       .WillOnce(testing::Return(scroll_result_did_scroll_));
1721   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
1722 
1723   // Dispatch all queued events.
1724   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1725   DeliverInputForBeginFrame();
1726   EXPECT_EQ(0ul, event_queue().size());
1727   // Should run callbacks for every original events.
1728   EXPECT_EQ(4ul, event_disposition_recorder_.size());
1729   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[1]);
1730   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[2]);
1731   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[3]);
1732   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1733 }
1734 
1735 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
1736 // Flaky under sanitizers and in other "slow" bot configs:
1737 // https://crbug.com/1029250
1738 #define MAYBE_VSyncAlignedGestureScrollPinchScroll \
1739   DISABLED_VSyncAlignedGestureScrollPinchScroll
1740 #else
1741 #define MAYBE_VSyncAlignedGestureScrollPinchScroll \
1742   VSyncAlignedGestureScrollPinchScroll
1743 #endif
1744 
TEST_F(InputHandlerProxyEventQueueTest,MAYBE_VSyncAlignedGestureScrollPinchScroll)1745 TEST_F(InputHandlerProxyEventQueueTest,
1746        MAYBE_VSyncAlignedGestureScrollPinchScroll) {
1747   // Handle scroll on compositor.
1748   cc::InputHandlerScrollResult scroll_result_did_scroll_;
1749   scroll_result_did_scroll_.did_scroll = true;
1750 
1751   // Start scroll in the first frame.
1752   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1753       .WillOnce(testing::Return(kImplThreadScrollState));
1754   EXPECT_CALL(
1755       mock_input_handler_,
1756       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1757       .Times(1);
1758   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1759       .WillOnce(testing::Return(false));
1760   EXPECT_CALL(
1761       mock_input_handler_,
1762       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1763                    _))
1764       .WillOnce(testing::Return(scroll_result_did_scroll_));
1765   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1766 
1767   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1768   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
1769 
1770   EXPECT_EQ(1ul, event_queue().size());
1771   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1772 
1773   DeliverInputForBeginFrame();
1774 
1775   EXPECT_EQ(0ul, event_queue().size());
1776   EXPECT_EQ(2ul, event_disposition_recorder_.size());
1777   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1778 
1779   // Continue scroll in the second frame, pinch, then start another scroll.
1780   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1781       .WillOnce(testing::Return(kImplThreadScrollState));
1782   EXPECT_CALL(
1783       mock_input_handler_,
1784       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1785       .Times(1);
1786   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1787       .WillRepeatedly(testing::Return(false));
1788   EXPECT_CALL(
1789       mock_input_handler_,
1790       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1791                    _))
1792       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
1793   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(2);
1794   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1795   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1796   // Two |GesturePinchUpdate| will be coalesced.
1797   EXPECT_CALL(mock_input_handler_,
1798               PinchGestureUpdate(0.7f, gfx::Point(13, 17)));
1799   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(), false));
1800   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(2);
1801 
1802   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
1803   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1804   HandleGestureEvent(WebInputEvent::kGesturePinchBegin);
1805   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 1.4f, 13, 17);
1806   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 0.5f, 13, 17);
1807   HandleGestureEvent(WebInputEvent::kGesturePinchEnd);
1808   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1809   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -70);
1810   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -5);
1811   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1812 
1813   EXPECT_EQ(8ul, event_queue().size());
1814   EXPECT_EQ(2ul, event_disposition_recorder_.size());
1815 
1816   DeliverInputForBeginFrame();
1817 
1818   EXPECT_EQ(0ul, event_queue().size());
1819   EXPECT_EQ(12ul, event_disposition_recorder_.size());
1820   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1821 }
1822 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedQueueingTime)1823 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) {
1824   base::SimpleTestTickClock tick_clock;
1825   tick_clock.SetNowTicks(base::TimeTicks::Now());
1826   SetInputHandlerProxyTickClockForTesting(&tick_clock);
1827 
1828   // Handle scroll on compositor.
1829   cc::InputHandlerScrollResult scroll_result_did_scroll_;
1830   scroll_result_did_scroll_.did_scroll = true;
1831 
1832   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1833       .WillOnce(testing::Return(kImplThreadScrollState));
1834   EXPECT_CALL(
1835       mock_input_handler_,
1836       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1837       .Times(1);
1838   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1839   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1840       .WillOnce(testing::Return(false));
1841   EXPECT_CALL(
1842       mock_input_handler_,
1843       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1844                    _))
1845       .WillOnce(testing::Return(scroll_result_did_scroll_));
1846   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
1847   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1848 
1849   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1850   tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
1851   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
1852   tick_clock.Advance(base::TimeDelta::FromMicroseconds(40));
1853   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
1854   tick_clock.Advance(base::TimeDelta::FromMicroseconds(20));
1855   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
1856   tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
1857   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1858 
1859   // Dispatch all queued events.
1860   tick_clock.Advance(base::TimeDelta::FromMicroseconds(70));
1861   DeliverInputForBeginFrame();
1862   EXPECT_EQ(0ul, event_queue().size());
1863   EXPECT_EQ(5ul, event_disposition_recorder_.size());
1864   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1865 }
1866 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedCoalesceScrollAndPinch)1867 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceScrollAndPinch) {
1868   // Start scroll in the first frame.
1869   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1870       .WillOnce(testing::Return(kImplThreadScrollState));
1871   EXPECT_CALL(
1872       mock_input_handler_,
1873       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1874       .Times(1);
1875   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1876 
1877   // GSUs and GPUs in one sequence should be coalesced into 1 GSU and 1 GPU.
1878   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1879   HandleGestureEvent(WebInputEvent::kGesturePinchBegin);
1880   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
1881   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -7);
1882   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 2.0f, 13, 10);
1883   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
1884   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -6);
1885   HandleGestureEvent(WebInputEvent::kGesturePinchEnd);
1886   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1887   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
1888   HandleGestureEvent(WebInputEvent::kGesturePinchBegin);
1889   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 0.2f, 2, 20);
1890   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 10.0f, 1, 10);
1891   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
1892   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 0.25f, 3, 30);
1893   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
1894   HandleGestureEvent(WebInputEvent::kGesturePinchEnd);
1895   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
1896 
1897   // Only the first GSB was dispatched.
1898   EXPECT_EQ(11ul, event_queue().size());
1899   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1900 
1901   EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
1902             event_queue()[0]->event().GetType());
1903   EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
1904             event_queue()[1]->event().GetType());
1905   EXPECT_EQ(
1906       -35,
1907       ToWebGestureEvent(event_queue()[1]->event()).data.scroll_update.delta_y);
1908   EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
1909             event_queue()[2]->event().GetType());
1910   EXPECT_EQ(
1911       2.0f,
1912       ToWebGestureEvent(event_queue()[2]->event()).data.pinch_update.scale);
1913   EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
1914             event_queue()[3]->event().GetType());
1915   EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
1916             event_queue()[4]->event().GetType());
1917   EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
1918             event_queue()[5]->event().GetType());
1919   EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
1920             event_queue()[6]->event().GetType());
1921   EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
1922             event_queue()[7]->event().GetType());
1923   EXPECT_EQ(
1924       -85,
1925       ToWebGestureEvent(event_queue()[7]->event()).data.scroll_update.delta_y);
1926   EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
1927             event_queue()[8]->event().GetType());
1928   EXPECT_EQ(
1929       0.5f,
1930       ToWebGestureEvent(event_queue()[8]->event()).data.pinch_update.scale);
1931   EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
1932             event_queue()[9]->event().GetType());
1933   EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
1934             event_queue()[10]->event().GetType());
1935   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1936 }
1937 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedCoalesceTouchpadPinch)1938 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceTouchpadPinch) {
1939   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1940   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput());
1941 
1942   HandleGestureEventWithSourceDevice(WebInputEvent::kGesturePinchBegin,
1943                                      blink::WebGestureDevice::kTouchpad);
1944   HandleGestureEventWithSourceDevice(WebInputEvent::kGesturePinchUpdate,
1945                                      blink::WebGestureDevice::kTouchpad, 1.1f,
1946                                      10, 20);
1947   // The second update should coalesce with the first.
1948   HandleGestureEventWithSourceDevice(WebInputEvent::kGesturePinchUpdate,
1949                                      blink::WebGestureDevice::kTouchpad, 1.1f,
1950                                      10, 20);
1951   // The third update has a different anchor so it should not be coalesced.
1952   HandleGestureEventWithSourceDevice(WebInputEvent::kGesturePinchUpdate,
1953                                      blink::WebGestureDevice::kTouchpad, 1.1f,
1954                                      11, 21);
1955   HandleGestureEventWithSourceDevice(WebInputEvent::kGesturePinchEnd,
1956                                      blink::WebGestureDevice::kTouchpad);
1957 
1958   // Only the PinchBegin was dispatched.
1959   EXPECT_EQ(3ul, event_queue().size());
1960   EXPECT_EQ(1ul, event_disposition_recorder_.size());
1961 
1962   ASSERT_EQ(WebInputEvent::kGesturePinchUpdate,
1963             event_queue()[0]->event().GetType());
1964   EXPECT_FLOAT_EQ(
1965       1.21f,
1966       ToWebGestureEvent(event_queue()[0]->event()).data.pinch_update.scale);
1967   EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
1968             event_queue()[1]->event().GetType());
1969   EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
1970             event_queue()[2]->event().GetType());
1971 }
1972 
TEST_F(InputHandlerProxyEventQueueTest,OriginalEventsTracing)1973 TEST_F(InputHandlerProxyEventQueueTest, OriginalEventsTracing) {
1974   // Handle scroll on compositor.
1975   cc::InputHandlerScrollResult scroll_result_did_scroll_;
1976   scroll_result_did_scroll_.did_scroll = true;
1977 
1978   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1979       .WillRepeatedly(testing::Return(kImplThreadScrollState));
1980   EXPECT_CALL(
1981       mock_input_handler_,
1982       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1983       .Times(2);
1984   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput())
1985       .Times(::testing::AtLeast(1));
1986   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1987       .WillRepeatedly(testing::Return(false));
1988   EXPECT_CALL(
1989       mock_input_handler_,
1990       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1991                    _))
1992       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
1993   EXPECT_CALL(mock_input_handler_, ScrollEnd(true))
1994       .Times(::testing::AtLeast(1));
1995   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(2);
1996 
1997   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1998   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(_, _));
1999   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(_, _));
2000 
2001   trace_analyzer::Start("*");
2002   // Simulate scroll.
2003   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2004   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2005   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
2006   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2007   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
2008 
2009   // Simulate scroll and pinch.
2010   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2011   HandleGestureEvent(WebInputEvent::kGesturePinchBegin);
2012   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 10.0f, 1, 10);
2013   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2014   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 2.0f, 1, 10);
2015   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
2016   HandleGestureEvent(WebInputEvent::kGesturePinchEnd);
2017   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
2018 
2019   // Dispatch all events.
2020   DeliverInputForBeginFrame();
2021 
2022   // Retrieve tracing data.
2023   auto analyzer = trace_analyzer::Stop();
2024   trace_analyzer::TraceEventVector begin_events;
2025   trace_analyzer::Query begin_query = trace_analyzer::Query::EventPhaseIs(
2026       TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN);
2027   analyzer->FindEvents(begin_query, &begin_events);
2028 
2029   trace_analyzer::TraceEventVector end_events;
2030   trace_analyzer::Query end_query =
2031       trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END);
2032   analyzer->FindEvents(end_query, &end_events);
2033 
2034   EXPECT_EQ(7ul, begin_events.size());
2035   EXPECT_EQ(7ul, end_events.size());
2036   EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
2037             end_events[0]->GetKnownArgAsInt("type"));
2038   EXPECT_EQ(3, end_events[0]->GetKnownArgAsInt("coalesced_count"));
2039   EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
2040             end_events[1]->GetKnownArgAsInt("type"));
2041 
2042   EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
2043             end_events[2]->GetKnownArgAsInt("type"));
2044   EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
2045             end_events[3]->GetKnownArgAsInt("type"));
2046   // Original scroll and pinch updates will be stored in the coalesced
2047   // PinchUpdate of the <ScrollUpdate, PinchUpdate> pair.
2048   // The ScrollUpdate of the pair doesn't carry original events and won't be
2049   // traced.
2050   EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
2051             end_events[4]->GetKnownArgAsInt("type"));
2052   EXPECT_EQ(4, end_events[4]->GetKnownArgAsInt("coalesced_count"));
2053   EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
2054             end_events[5]->GetKnownArgAsInt("type"));
2055   EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
2056             end_events[6]->GetKnownArgAsInt("type"));
2057   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2058 }
2059 
TEST_F(InputHandlerProxyEventQueueTest,TouchpadGestureScrollEndFlushQueue)2060 TEST_F(InputHandlerProxyEventQueueTest, TouchpadGestureScrollEndFlushQueue) {
2061   // Handle scroll on compositor.
2062   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2063   scroll_result_did_scroll_.did_scroll = true;
2064 
2065   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2066       .WillRepeatedly(testing::Return(kImplThreadScrollState));
2067   EXPECT_CALL(
2068       mock_input_handler_,
2069       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2070       .Times(2);
2071   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2072       .WillRepeatedly(testing::Return(false));
2073   EXPECT_CALL(
2074       mock_input_handler_,
2075       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2076                    _))
2077       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
2078   EXPECT_CALL(mock_input_handler_, ScrollEnd(true))
2079       .Times(::testing::AtLeast(1));
2080 
2081   // Simulate scroll.
2082   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollBegin,
2083                                      blink::WebGestureDevice::kTouchpad);
2084   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollUpdate,
2085                                      blink::WebGestureDevice::kTouchpad, -20);
2086 
2087   // Both GSB and the first GSU will be dispatched immediately since the first
2088   // GSU has blocking wheel event source.
2089   EXPECT_EQ(0ul, event_queue().size());
2090   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2091 
2092   // The rest of the GSU events will get queued since they have non-blocking
2093   // wheel event source.
2094   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput())
2095       .Times(::testing::AtLeast(1));
2096   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollUpdate,
2097                                      blink::WebGestureDevice::kTouchpad, -20);
2098   EXPECT_EQ(1ul, event_queue().size());
2099   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2100 
2101   // Touchpad GSE will flush the queue.
2102   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2103   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollEnd,
2104                                      blink::WebGestureDevice::kTouchpad);
2105 
2106   EXPECT_EQ(0ul, event_queue().size());
2107   // GSB, GSU(with blocking wheel source), GSU(with non-blocking wheel
2108   // source), and GSE are the sent events.
2109   EXPECT_EQ(4ul, event_disposition_recorder_.size());
2110 
2111   EXPECT_FALSE(
2112       input_handler_proxy_.gesture_scroll_on_impl_thread_for_testing());
2113 
2114   // Starting a new scroll sequence should have the same behavior (namely that
2115   // the first scroll update is not queued but immediately dispatched).
2116   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollBegin,
2117                                      blink::WebGestureDevice::kTouchpad);
2118   HandleGestureEventWithSourceDevice(WebInputEvent::kGestureScrollUpdate,
2119                                      blink::WebGestureDevice::kTouchpad, -20);
2120 
2121   // Both GSB and the first GSU must be dispatched immediately since the first
2122   // GSU has blocking wheel event source.
2123   EXPECT_EQ(0ul, event_queue().size());
2124   EXPECT_EQ(6ul, event_disposition_recorder_.size());
2125 }
2126 
TEST_F(InputHandlerProxyEventQueueTest,CoalescedLatencyInfo)2127 TEST_F(InputHandlerProxyEventQueueTest, CoalescedLatencyInfo) {
2128   // Handle scroll on compositor.
2129   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2130   scroll_result_did_scroll_.did_scroll = true;
2131 
2132   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2133       .WillOnce(testing::Return(kImplThreadScrollState));
2134   EXPECT_CALL(
2135       mock_input_handler_,
2136       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2137       .Times(1);
2138   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2139   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2140       .WillOnce(testing::Return(false));
2141   EXPECT_CALL(
2142       mock_input_handler_,
2143       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2144                    _))
2145       .WillOnce(testing::Return(scroll_result_did_scroll_));
2146   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2147   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2148 
2149   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2150   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2151   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
2152   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
2153   HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
2154   DeliverInputForBeginFrame();
2155 
2156   EXPECT_EQ(0ul, event_queue().size());
2157   // Should run callbacks for every original events.
2158   EXPECT_EQ(5ul, event_disposition_recorder_.size());
2159   EXPECT_EQ(5ul, latency_info_recorder_.size());
2160   EXPECT_EQ(false, latency_info_recorder_[1].coalesced());
2161   // Coalesced events should have latency set to coalesced.
2162   EXPECT_EQ(true, latency_info_recorder_[2].coalesced());
2163   EXPECT_EQ(true, latency_info_recorder_[3].coalesced());
2164   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2165 }
2166 
TEST_F(InputHandlerProxyEventQueueTest,CoalescedEventSwitchToMainThread)2167 TEST_F(InputHandlerProxyEventQueueTest, CoalescedEventSwitchToMainThread) {
2168   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2169   cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
2170   scroll_result_did_scroll_.did_scroll = true;
2171   scroll_result_did_not_scroll_.did_scroll = false;
2172 
2173   // scroll begin on main thread
2174   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2175       .WillOnce(testing::Return(kMainThreadScrollState));
2176   EXPECT_CALL(
2177       mock_input_handler_,
2178       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2179       .Times(1);
2180   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2);
2181   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2182       .WillOnce(testing::Return(false));
2183   EXPECT_CALL(
2184       mock_input_handler_,
2185       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2186                    _))
2187       .WillOnce(testing::Return(scroll_result_did_not_scroll_));
2188 
2189   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2190   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2191   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2192   DeliverInputForBeginFrame();
2193   EXPECT_EQ(3ul, event_disposition_recorder_.size());
2194   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2195             event_disposition_recorder_.back());
2196   // GSU should not be coalesced
2197   EXPECT_EQ(false, latency_info_recorder_[1].coalesced());
2198   EXPECT_EQ(false, latency_info_recorder_[2].coalesced());
2199 
2200   // pinch start, handle scroll and pinch on compositor.
2201   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
2202   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(_, _));
2203   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(_, _));
2204 
2205   HandleGestureEvent(WebInputEvent::kGesturePinchBegin);
2206   HandleGestureEvent(WebInputEvent::kGesturePinchUpdate, 10.0f, 1, 10);
2207   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2208   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
2209   EXPECT_EQ(2ul, event_queue().size());
2210   DeliverInputForBeginFrame();
2211 
2212   EXPECT_EQ(7ul, event_disposition_recorder_.size());
2213   EXPECT_EQ(false, latency_info_recorder_[4].coalesced());
2214   // Coalesced events should have latency set to coalesced.
2215   EXPECT_EQ(true, latency_info_recorder_[5].coalesced());
2216   EXPECT_EQ(true, latency_info_recorder_[6].coalesced());
2217   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
2218 
2219   // Pinch end, handle scroll on main thread.
2220   HandleGestureEvent(WebInputEvent::kGesturePinchEnd);
2221   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
2222   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
2223   DeliverInputForBeginFrame();
2224 
2225   EXPECT_EQ(0ul, event_queue().size());
2226   // Should run callbacks for every original events.
2227   EXPECT_EQ(10ul, event_disposition_recorder_.size());
2228   EXPECT_EQ(10ul, latency_info_recorder_.size());
2229   // Latency should not be set to coalesced when send to main thread
2230   EXPECT_EQ(false, latency_info_recorder_[8].coalesced());
2231   EXPECT_EQ(false, latency_info_recorder_[9].coalesced());
2232   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2233             event_disposition_recorder_.back());
2234   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2235 }
2236 
TEST_F(InputHandlerProxyEventQueueTest,ScrollPredictorTest)2237 TEST_F(InputHandlerProxyEventQueueTest, ScrollPredictorTest) {
2238   base::SimpleTestTickClock tick_clock;
2239   tick_clock.SetNowTicks(base::TimeTicks());
2240   SetInputHandlerProxyTickClockForTesting(&tick_clock);
2241 
2242   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2243   scroll_result_did_scroll_.did_scroll = true;
2244   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2245       .WillOnce(testing::Return(kImplThreadScrollState));
2246   EXPECT_CALL(
2247       mock_input_handler_,
2248       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2249       .Times(1);
2250   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2251   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2252       .WillOnce(testing::Return(false));
2253   EXPECT_CALL(
2254       mock_input_handler_,
2255       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2256                    _))
2257       .WillOnce(testing::Return(scroll_result_did_scroll_));
2258 
2259   // No prediction when start with a GSB
2260   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
2261   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2262   DeliverInputForBeginFrame();
2263   EXPECT_FALSE(GestureScrollEventPredictionAvailable());
2264 
2265   // Test predictor returns last GSU delta.
2266   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
2267   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2268   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
2269   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -15);
2270   DeliverInputForBeginFrame();
2271   auto result = GestureScrollEventPredictionAvailable();
2272   EXPECT_TRUE(result);
2273   EXPECT_NE(0, result->pos.y());
2274 
2275   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2276 
2277   // Predictor has been reset after a new GSB.
2278   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2279   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2280       .WillOnce(testing::Return(kImplThreadScrollState));
2281   EXPECT_CALL(
2282       mock_input_handler_,
2283       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2284       .Times(1);
2285   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
2286   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2287   DeliverInputForBeginFrame();
2288   EXPECT_FALSE(GestureScrollEventPredictionAvailable());
2289 
2290   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2291 }
2292 
2293 // Test deliver input w/o prediction enabled.
TEST_F(InputHandlerProxyEventQueueTest,DeliverInputWithHighLatencyMode)2294 TEST_F(InputHandlerProxyEventQueueTest, DeliverInputWithHighLatencyMode) {
2295   SetScrollPredictionEnabled(false);
2296 
2297   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2298   scroll_result_did_scroll_.did_scroll = true;
2299   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2300       .WillOnce(testing::Return(kImplThreadScrollState));
2301   EXPECT_CALL(
2302       mock_input_handler_,
2303       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2304       .Times(1);
2305   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2);
2306   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2307       .WillRepeatedly(testing::Return(false));
2308   EXPECT_CALL(
2309       mock_input_handler_,
2310       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2311                    _))
2312       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
2313 
2314   HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
2315   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2316   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2317   DeliverInputForBeginFrame();
2318   // 3 queued event be delivered.
2319   EXPECT_EQ(3ul, event_disposition_recorder_.size());
2320   EXPECT_EQ(0ul, event_queue().size());
2321   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
2322 
2323   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
2324   HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -10);
2325   DeliverInputForHighLatencyMode();
2326   // 2 queued event be delivered.
2327   EXPECT_EQ(5ul, event_disposition_recorder_.size());
2328   EXPECT_EQ(0ul, event_queue().size());
2329   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
2330 
2331   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2332 }
2333 
2334 class InputHandlerProxyMainThreadScrollingReasonTest
2335     : public InputHandlerProxyTest {
2336  public:
2337   enum TestEventType {
2338     Touch,
2339     MouseWheel,
2340   };
2341 
InputHandlerProxyMainThreadScrollingReasonTest()2342   InputHandlerProxyMainThreadScrollingReasonTest() : InputHandlerProxyTest() {}
2343   ~InputHandlerProxyMainThreadScrollingReasonTest() = default;
2344 
SetupEvents(TestEventType type)2345   void SetupEvents(TestEventType type) {
2346     touch_start_ =
2347         WebTouchEvent(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
2348                       WebInputEvent::GetStaticTimeStampForTests());
2349     touch_end_ =
2350         WebTouchEvent(WebInputEvent::kTouchEnd, WebInputEvent::kNoModifiers,
2351                       WebInputEvent::GetStaticTimeStampForTests());
2352     wheel_event_ = WebMouseWheelEvent(
2353         WebInputEvent::kMouseWheel, WebInputEvent::kControlKey,
2354         WebInputEvent::GetStaticTimeStampForTests());
2355     gesture_scroll_begin_ = WebGestureEvent(
2356         WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
2357         WebInputEvent::GetStaticTimeStampForTests(),
2358         type == TestEventType::MouseWheel
2359             ? blink::WebGestureDevice::kTouchpad
2360             : blink::WebGestureDevice::kTouchscreen);
2361     gesture_scroll_end_ = WebGestureEvent(
2362         WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
2363         WebInputEvent::GetStaticTimeStampForTests(),
2364         type == TestEventType::MouseWheel
2365             ? blink::WebGestureDevice::kTouchpad
2366             : blink::WebGestureDevice::kTouchscreen);
2367     touch_start_.touches_length = 1;
2368     touch_start_.touch_start_or_first_touch_move = true;
2369     touch_start_.touches[0] =
2370         CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
2371 
2372     touch_end_.touches_length = 1;
2373   }
2374 
GetBucketSample(uint32_t reason)2375   base::HistogramBase::Sample GetBucketSample(uint32_t reason) {
2376     if (reason == cc::MainThreadScrollingReason::kNotScrollingOnMain)
2377       return 0;
2378 
2379     uint32_t bucket = 1;
2380     while ((reason = reason >> 1))
2381       bucket++;
2382     return bucket;
2383   }
2384 
2385  protected:
2386   WebTouchEvent touch_start_;
2387   WebTouchEvent touch_end_;
2388   WebMouseWheelEvent wheel_event_;
2389   WebGestureEvent gesture_scroll_begin_;
2390   WebGestureEvent gesture_scroll_end_;
2391 };
2392 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollNotScrollOnMain)2393 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2394        GestureScrollNotScrollOnMain) {
2395   // Touch start with passive event listener.
2396   SetupEvents(TestEventType::Touch);
2397 
2398   EXPECT_CALL(mock_input_handler_,
2399               EventListenerTypeForTouchStartOrMoveAt(
2400                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
2401       .WillOnce(testing::Return(
2402           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
2403   EXPECT_CALL(
2404       mock_input_handler_,
2405       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
2406       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
2407   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
2408       .WillOnce(testing::Return());
2409 
2410   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
2411   EXPECT_EQ(expected_disposition_,
2412             HandleInputEventAndFlushEventQueue(
2413                 mock_input_handler_, input_handler_.get(), touch_start_));
2414 
2415   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2416       .WillOnce(testing::Return(kImplThreadScrollState));
2417   EXPECT_CALL(
2418       mock_input_handler_,
2419       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2420       .Times(1);
2421   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2422   EXPECT_EQ(
2423       expected_disposition_,
2424       HandleInputEventAndFlushEventQueue(
2425           mock_input_handler_, input_handler_.get(), gesture_scroll_begin_));
2426   EXPECT_THAT(
2427       histogram_tester().GetAllSamples(
2428           "Renderer4.MainThreadGestureScrollReason"),
2429       testing::ElementsAre(base::Bucket(
2430           GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
2431           1)));
2432 
2433   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2434   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2435   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2436   EXPECT_EQ(
2437       expected_disposition_,
2438       HandleInputEventAndFlushEventQueue(
2439           mock_input_handler_, input_handler_.get(), gesture_scroll_end_));
2440 }
2441 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollTouchEventHandlerRegion)2442 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2443        GestureScrollTouchEventHandlerRegion) {
2444   // The touch event hits a touch event handler that is acked from the
2445   // compositor thread when kCompositorTouchAction is enabld.
2446   SetupEvents(TestEventType::Touch);
2447 
2448   EXPECT_CALL(mock_input_handler_,
2449               EventListenerTypeForTouchStartOrMoveAt(
2450                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
2451       .WillOnce(
2452           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
2453                               HANDLER_ON_SCROLLING_LAYER));
2454   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
2455       .WillOnce(testing::Return());
2456 
2457   expected_disposition_ = compositor_touch_action_enabled_
2458                               ? InputHandlerProxy::DID_HANDLE_NON_BLOCKING
2459                               : InputHandlerProxy::DID_NOT_HANDLE;
2460   EXPECT_EQ(expected_disposition_,
2461             HandleInputEventAndFlushEventQueue(
2462                 mock_input_handler_, input_handler_.get(), touch_start_));
2463 
2464   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2465       .WillOnce(testing::Return(kImplThreadScrollState));
2466   EXPECT_CALL(mock_input_handler_,
2467               RecordScrollBegin(
2468                   _, compositor_touch_action_enabled_
2469                          ? cc::ScrollBeginThreadState::kScrollingOnCompositor
2470                          : cc::ScrollBeginThreadState::
2471                                kScrollingOnCompositorBlockedOnMain))
2472       .Times(1);
2473   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2474   EXPECT_EQ(
2475       expected_disposition_,
2476       HandleInputEventAndFlushEventQueue(
2477           mock_input_handler_, input_handler_.get(), gesture_scroll_begin_));
2478 
2479   EXPECT_THAT(
2480       histogram_tester().GetAllSamples(
2481           "Renderer4.MainThreadGestureScrollReason"),
2482       testing::ElementsAre(base::Bucket(
2483           GetBucketSample(
2484               compositor_touch_action_enabled_
2485                   ? cc::MainThreadScrollingReason::kNotScrollingOnMain
2486                   : cc::MainThreadScrollingReason::kTouchEventHandlerRegion),
2487           1)));
2488 
2489   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2490   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2491   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2492   EXPECT_EQ(
2493       expected_disposition_,
2494       HandleInputEventAndFlushEventQueue(
2495           mock_input_handler_, input_handler_.get(), gesture_scroll_end_));
2496 }
2497 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollTouchEventHandlerRegionAndHandlingScrollFromMainThread)2498 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2499        GestureScrollTouchEventHandlerRegionAndHandlingScrollFromMainThread) {
2500   // The touch event hits a touch event handler and should block on main thread.
2501   // Since ScrollBegin doesn't allow the gesture to scroll on impl. We report
2502   // TouchEventHandler reason as well as HandlingScrollFromMainThread. Since we
2503   // do not collect HandlingScrollFromMainThread when there are other reasons
2504   // present, TouchEventHandler is the only reason being collected in the
2505   // histogram.
2506   SetupEvents(TestEventType::Touch);
2507 
2508   EXPECT_CALL(mock_input_handler_,
2509               EventListenerTypeForTouchStartOrMoveAt(
2510                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
2511       .WillOnce(
2512           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
2513                               HANDLER_ON_SCROLLING_LAYER));
2514   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
2515       .WillOnce(testing::Return());
2516 
2517   expected_disposition_ = compositor_touch_action_enabled_
2518                               ? InputHandlerProxy::DID_HANDLE_NON_BLOCKING
2519                               : InputHandlerProxy::DID_NOT_HANDLE;
2520   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2521                                        input_handler_.get(), touch_start_));
2522 
2523   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2524       .WillOnce(testing::Return(kMainThreadScrollState));
2525   EXPECT_CALL(
2526       mock_input_handler_,
2527       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2528       .Times(1);
2529   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2530   EXPECT_EQ(expected_disposition_,
2531             HandleInputEventWithLatencyInfo(input_handler_.get(),
2532                                             gesture_scroll_begin_));
2533 
2534   EXPECT_THAT(
2535       histogram_tester().GetAllSamples(
2536           "Renderer4.MainThreadGestureScrollReason"),
2537       testing::ElementsAre(base::Bucket(
2538           GetBucketSample(
2539               compositor_touch_action_enabled_
2540                   ? cc::MainThreadScrollingReason::kHandlingScrollFromMainThread
2541                   : cc::MainThreadScrollingReason::kTouchEventHandlerRegion),
2542           1)));
2543 
2544   // Handle touch end event so that input handler proxy is out of the state of
2545   // DID_NOT_HANDLE.
2546   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2547   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2548   EXPECT_EQ(expected_disposition_,
2549             HandleInputEventWithLatencyInfo(input_handler_.get(),
2550                                             gesture_scroll_end_));
2551 
2552   EXPECT_EQ(expected_disposition_,
2553             HandleInputEventWithLatencyInfo(input_handler_.get(), touch_end_));
2554 }
2555 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollHandlingScrollFromMainThread)2556 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2557        GestureScrollHandlingScrollFromMainThread) {
2558   // Gesture scrolling on main thread. We only record
2559   // HandlingScrollFromMainThread when it's the only available reason.
2560   SetupEvents(TestEventType::Touch);
2561   EXPECT_CALL(mock_input_handler_,
2562               EventListenerTypeForTouchStartOrMoveAt(
2563                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
2564       .WillOnce(testing::Return(
2565           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
2566   EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(_, _, _))
2567       .WillOnce(testing::Return());
2568   EXPECT_CALL(mock_input_handler_, GetEventListenerProperties(_))
2569       .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
2570 
2571   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
2572   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2573                                        input_handler_.get(), touch_start_));
2574 
2575   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2576       .WillOnce(testing::Return(kMainThreadScrollState));
2577   EXPECT_CALL(
2578       mock_input_handler_,
2579       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2580       .Times(1);
2581   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2582   EXPECT_EQ(expected_disposition_,
2583             HandleInputEventWithLatencyInfo(input_handler_.get(),
2584                                             gesture_scroll_begin_));
2585 
2586   EXPECT_THAT(
2587       histogram_tester().GetAllSamples(
2588           "Renderer4.MainThreadGestureScrollReason"),
2589       testing::ElementsAre(base::Bucket(
2590           GetBucketSample(
2591               cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
2592           1)));
2593 
2594   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2595   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2596   EXPECT_EQ(expected_disposition_,
2597             HandleInputEventWithLatencyInfo(input_handler_.get(),
2598                                             gesture_scroll_end_));
2599 }
2600 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollHistogram)2601 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest, WheelScrollHistogram) {
2602   // Firstly check if input handler can correctly record main thread scrolling
2603   // reasons.
2604   EXPECT_CALL(
2605       mock_input_handler_,
2606       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2607       .Times(1);
2608   input_handler_->RecordMainThreadScrollingReasonsForTest(
2609       blink::WebGestureDevice::kTouchpad,
2610       cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects |
2611           cc::MainThreadScrollingReason::kThreadedScrollingDisabled |
2612           cc::MainThreadScrollingReason::kFrameOverlay |
2613           cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
2614 
2615   EXPECT_THAT(
2616       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2617       testing::ElementsAre(
2618           base::Bucket(
2619               GetBucketSample(cc::MainThreadScrollingReason::
2620                                   kHasBackgroundAttachmentFixedObjects),
2621               1),
2622           base::Bucket(
2623               GetBucketSample(
2624                   cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
2625               1),
2626           base::Bucket(
2627               GetBucketSample(cc::MainThreadScrollingReason::kFrameOverlay),
2628               1)));
2629 
2630   // We only want to record "Handling scroll from main thread" reason if it's
2631   // the only reason. If it's not the only reason, the "real" reason for
2632   // scrolling on main is something else, and we only want to pay attention to
2633   // that reason. So we should only include this reason in the histogram when
2634   // its on its own.
2635   EXPECT_CALL(
2636       mock_input_handler_,
2637       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2638       .Times(1);
2639   input_handler_->RecordMainThreadScrollingReasonsForTest(
2640       blink::WebGestureDevice::kTouchpad,
2641       cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
2642 
2643   EXPECT_THAT(
2644       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2645       testing::ElementsAre(
2646           base::Bucket(
2647               GetBucketSample(cc::MainThreadScrollingReason::
2648                                   kHasBackgroundAttachmentFixedObjects),
2649               1),
2650           base::Bucket(
2651               GetBucketSample(
2652                   cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
2653               1),
2654           base::Bucket(
2655               GetBucketSample(cc::MainThreadScrollingReason::kFrameOverlay), 1),
2656           base::Bucket(
2657               GetBucketSample(
2658                   cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
2659               1)));
2660 }
2661 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollNotScrollingOnMain)2662 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2663        WheelScrollNotScrollingOnMain) {
2664   // Even if a scroller is composited, we still need to record its main thread
2665   // scrolling reason if it is blocked on a main thread event handler.
2666   SetupEvents(TestEventType::MouseWheel);
2667 
2668   // We can scroll on impl for an wheel event with passive event listener.
2669   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
2670       .WillRepeatedly(testing::Return(false));
2671   EXPECT_CALL(mock_input_handler_,
2672               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
2673       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
2674   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
2675   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2676                                        input_handler_.get(), wheel_event_));
2677 
2678   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2679       .WillOnce(testing::Return(kImplThreadScrollState));
2680   EXPECT_CALL(
2681       mock_input_handler_,
2682       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2683       .Times(1);
2684   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2685   EXPECT_EQ(expected_disposition_,
2686             HandleInputEventWithLatencyInfo(input_handler_.get(),
2687                                             gesture_scroll_begin_));
2688 
2689   EXPECT_THAT(
2690       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2691       testing::ElementsAre(base::Bucket(
2692           GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
2693           1)));
2694 
2695   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2696   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2697   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2698   EXPECT_EQ(expected_disposition_,
2699             HandleInputEventWithLatencyInfo(input_handler_.get(),
2700                                             gesture_scroll_end_));
2701 }
2702 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollWheelEventHandlerRegion)2703 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2704        WheelScrollWheelEventHandlerRegion) {
2705   // Wheel event with blocking event listener. If there is a wheel event handler
2706   // at the point, we do not need to call GetEventListenerProperties since it
2707   // indicates kBlocking.
2708   SetupEvents(TestEventType::MouseWheel);
2709   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
2710       .WillRepeatedly(testing::Return(true));
2711   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2712   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2713                                        input_handler_.get(), wheel_event_));
2714 
2715   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2716       .WillOnce(testing::Return(kImplThreadScrollState));
2717   EXPECT_CALL(
2718       mock_input_handler_,
2719       RecordScrollBegin(
2720           _, cc::ScrollBeginThreadState::kScrollingOnCompositorBlockedOnMain))
2721       .Times(1);
2722   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2723   EXPECT_EQ(expected_disposition_,
2724             HandleInputEventWithLatencyInfo(input_handler_.get(),
2725                                             gesture_scroll_begin_));
2726 
2727   EXPECT_THAT(
2728       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2729       testing::ElementsAre(base::Bucket(
2730           GetBucketSample(
2731               cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
2732           1)));
2733 
2734   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2735   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2736   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
2737   EXPECT_EQ(expected_disposition_,
2738             HandleInputEventWithLatencyInfo(input_handler_.get(),
2739                                             gesture_scroll_end_));
2740 }
2741 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollWheelEventHandlerRegionAndHandlingScrollFromMainThread)2742 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2743        WheelScrollWheelEventHandlerRegionAndHandlingScrollFromMainThread) {
2744   // Wheel scrolling on main thread. Because we also block scrolling with wheel
2745   // event handler, we should record that reason as well.
2746   SetupEvents(TestEventType::MouseWheel);
2747   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
2748       .WillRepeatedly(testing::Return(true));
2749   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2750   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2751                                        input_handler_.get(), wheel_event_));
2752 
2753   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2754       .WillOnce(testing::Return(kMainThreadScrollState));
2755   EXPECT_CALL(
2756       mock_input_handler_,
2757       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2758       .Times(1);
2759   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2760   EXPECT_EQ(expected_disposition_,
2761             HandleInputEventWithLatencyInfo(input_handler_.get(),
2762                                             gesture_scroll_begin_));
2763 
2764   EXPECT_THAT(
2765       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2766       testing::ElementsAre(base::Bucket(
2767           GetBucketSample(
2768               cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
2769           1)));
2770 
2771   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2772   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2773   EXPECT_EQ(expected_disposition_,
2774             HandleInputEventWithLatencyInfo(input_handler_.get(),
2775                                             gesture_scroll_end_));
2776 }
2777 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollHandlingScrollFromMainThread)2778 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
2779        WheelScrollHandlingScrollFromMainThread) {
2780   // Gesture scrolling on main thread. We only record
2781   // HandlingScrollFromMainThread when it's the only available reason.
2782   SetupEvents(TestEventType::MouseWheel);
2783   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
2784       .WillRepeatedly(testing::Return(false));
2785   EXPECT_CALL(mock_input_handler_,
2786               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
2787       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
2788   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
2789   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
2790                                        input_handler_.get(), wheel_event_));
2791 
2792   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2793       .WillOnce(testing::Return(kMainThreadScrollState));
2794   EXPECT_CALL(
2795       mock_input_handler_,
2796       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
2797       .Times(1);
2798   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2799   EXPECT_EQ(expected_disposition_,
2800             HandleInputEventWithLatencyInfo(input_handler_.get(),
2801                                             gesture_scroll_begin_));
2802 
2803   EXPECT_THAT(
2804       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
2805       testing::ElementsAre(base::Bucket(
2806           GetBucketSample(
2807               cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
2808           1)));
2809 
2810   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
2811   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2812   EXPECT_EQ(expected_disposition_,
2813             HandleInputEventWithLatencyInfo(input_handler_.get(),
2814                                             gesture_scroll_end_));
2815 }
2816 
2817 // Tests that turning on the force_input_to_main_thread flag causes all events
2818 // to be return DID_NOT_HANDLE for forwarding to the main thread.
2819 class InputHandlerProxyForceHandlingOnMainThread : public testing::Test {
2820  public:
InputHandlerProxyForceHandlingOnMainThread()2821   InputHandlerProxyForceHandlingOnMainThread()
2822       : input_handler_proxy_(&mock_input_handler_,
2823                              &mock_client_,
2824                              /*force_input_to_main_thread=*/true) {}
2825 
2826   ~InputHandlerProxyForceHandlingOnMainThread() = default;
2827 
2828  protected:
2829   testing::StrictMock<MockInputHandler> mock_input_handler_;
2830   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
2831   TestInputHandlerProxy input_handler_proxy_;
2832 };
2833 
TEST_F(InputHandlerProxyForceHandlingOnMainThread,MouseWheel)2834 TEST_F(InputHandlerProxyForceHandlingOnMainThread, MouseWheel) {
2835   // We shouldn't be checking the status of event handlers at all.
2836   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_)).Times(0);
2837   EXPECT_CALL(mock_input_handler_, GetEventListenerProperties(_)).Times(0);
2838 
2839   WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
2840                            WebInputEvent::kControlKey,
2841                            WebInputEvent::GetStaticTimeStampForTests());
2842   // The input event must return DID_NOT_HANDLE, indicating it should be
2843   // handled on the main thread.
2844   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2845             HandleInputEventWithLatencyInfo(&input_handler_proxy_, wheel));
2846 }
2847 
TEST_F(InputHandlerProxyForceHandlingOnMainThread,TouchEvents)2848 TEST_F(InputHandlerProxyForceHandlingOnMainThread, TouchEvents) {
2849   // Shouldn't query event listener state at all since we're forcing events to
2850   // the main thread.
2851   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
2852       .Times(0);
2853 
2854   WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
2855                       WebInputEvent::GetStaticTimeStampForTests());
2856 
2857   touch.touches_length = 1;
2858   touch.touch_start_or_first_touch_move = true;
2859   touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
2860 
2861   // The input event must return DID_NOT_HANDLE, indicating it should be
2862   // handled on the main thread.
2863   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2864             HandleInputEventWithLatencyInfo(&input_handler_proxy_, touch));
2865 
2866   WebTouchEvent touch_move(WebInputEvent::kTouchMove,
2867                            WebInputEvent::kNoModifiers,
2868                            WebInputEvent::GetStaticTimeStampForTests());
2869 
2870   touch_move.touches_length = 1;
2871   touch_move.touch_start_or_first_touch_move = true;
2872   touch_move.touches[0] =
2873       CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
2874 
2875   // The input event must return DID_NOT_HANDLE, indicating it should be
2876   // handled on the main thread.
2877   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2878             HandleInputEventWithLatencyInfo(&input_handler_proxy_, touch_move));
2879 
2880   touch_move.touch_start_or_first_touch_move = false;
2881 
2882   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2883             HandleInputEventWithLatencyInfo(&input_handler_proxy_, touch_move));
2884 }
2885 
TEST_F(InputHandlerProxyForceHandlingOnMainThread,GestureEvents)2886 TEST_F(InputHandlerProxyForceHandlingOnMainThread, GestureEvents) {
2887   WebGestureEvent gesture(WebInputEvent::kGestureScrollBegin,
2888                           WebInputEvent::kNoModifiers,
2889                           WebInputEvent::GetStaticTimeStampForTests(),
2890                           blink::WebGestureDevice::kTouchscreen);
2891 
2892   // The input event must return DID_NOT_HANDLE, indicating it should be
2893   // handled on the main thread.
2894   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2895             HandleInputEventWithLatencyInfo(&input_handler_proxy_, gesture));
2896   gesture.SetType(WebInputEvent::kGestureScrollUpdate);
2897   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2898             HandleInputEventWithLatencyInfo(&input_handler_proxy_, gesture));
2899   gesture.SetType(WebInputEvent::kGestureScrollEnd);
2900   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
2901             HandleInputEventWithLatencyInfo(&input_handler_proxy_, gesture));
2902 }
2903 
2904 class InputHandlerProxyMomentumScrollJankTest : public testing::Test {
2905  public:
InputHandlerProxyMomentumScrollJankTest()2906   InputHandlerProxyMomentumScrollJankTest()
2907       : input_handler_proxy_(&mock_input_handler_,
2908                              &mock_client_,
2909                              /*force_input_to_main_thread=*/false) {
2910     tick_clock_.SetNowTicks(base::TimeTicks::Now());
2911     // Disable scroll predictor for this test.
2912     input_handler_proxy_.scroll_predictor_ = nullptr;
2913     input_handler_proxy_.SetTickClockForTesting(&tick_clock_);
2914   }
2915 
2916   ~InputHandlerProxyMomentumScrollJankTest() = default;
2917 
HandleScrollBegin()2918   void HandleScrollBegin() {
2919     WebGestureEvent gesture(WebInputEvent::kGestureScrollBegin,
2920                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
2921                             blink::WebGestureDevice::kTouchscreen);
2922     HandleGesture(gesture.Clone());
2923   }
2924 
HandleScrollEnd()2925   void HandleScrollEnd() {
2926     WebGestureEvent gesture(WebInputEvent::kGestureScrollEnd,
2927                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
2928                             blink::WebGestureDevice::kTouchscreen);
2929     HandleGesture(gesture.Clone());
2930   }
2931 
HandleScrollUpdate(bool is_momentum)2932   void HandleScrollUpdate(bool is_momentum) {
2933     WebGestureEvent gesture(WebInputEvent::kGestureScrollUpdate,
2934                             WebInputEvent::kNoModifiers, tick_clock_.NowTicks(),
2935                             blink::WebGestureDevice::kTouchscreen);
2936     gesture.data.scroll_update.delta_y = -20;
2937     if (is_momentum) {
2938       gesture.data.scroll_update.inertial_phase =
2939           blink::WebGestureEvent::InertialPhaseState::kMomentum;
2940     }
2941     HandleGesture(gesture.Clone());
2942   }
2943 
AdvanceClock(uint32_t milliseconds)2944   void AdvanceClock(uint32_t milliseconds) {
2945     tick_clock_.Advance(base::TimeDelta::FromMilliseconds(milliseconds));
2946   }
2947 
AddNonJankyEvents(uint32_t count)2948   void AddNonJankyEvents(uint32_t count) {
2949     for (uint32_t i = 0; i < count; ++i) {
2950       AdvanceClock(16);
2951       HandleScrollUpdate(true /* is_momentum */);
2952       DeliverInputForBeginFrame();
2953     }
2954   }
2955 
DeliverInputForBeginFrame()2956   void DeliverInputForBeginFrame() {
2957     constexpr base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
2958     base::TimeTicks frame_time =
2959         base::TimeTicks() +
2960         (next_begin_frame_number_ - viz::BeginFrameArgs::kStartingFrameNumber) *
2961             interval;
2962     input_handler_proxy_.DeliverInputForBeginFrame(viz::BeginFrameArgs::Create(
2963         BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, frame_time,
2964         frame_time + interval, interval, viz::BeginFrameArgs::NORMAL));
2965   }
2966 
2967  protected:
HandleGesture(WebScopedInputEvent event)2968   void HandleGesture(WebScopedInputEvent event) {
2969     LatencyInfo latency;
2970     input_handler_proxy_.HandleInputEventWithLatencyInfo(
2971         std::move(event), latency, base::DoNothing());
2972   }
2973 
2974   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
2975 
2976   testing::NiceMock<MockInputHandler> mock_input_handler_;
2977   testing::NiceMock<MockInputHandlerProxyClient> mock_client_;
2978   TestInputHandlerProxy input_handler_proxy_;
2979   base::SimpleTestTickClock tick_clock_;
2980 };
2981 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJank)2982 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJank) {
2983   cc::InputHandlerScrollResult scroll_result_did_scroll;
2984   scroll_result_did_scroll.did_scroll = true;
2985   EXPECT_CALL(
2986       mock_input_handler_,
2987       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2988                    _))
2989       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
2990 
2991   base::HistogramTester histogram_tester;
2992   HandleScrollBegin();
2993 
2994   // Flush one update, the first update is always ignored.
2995   AdvanceClock(16);
2996   HandleScrollUpdate(true /* is_momentum */);
2997   DeliverInputForBeginFrame();
2998 
2999   // Enqueue three updates, they will be coalesced and count as two janks.
3000   AdvanceClock(16);
3001   HandleScrollUpdate(true /* is_momentum */);
3002   AdvanceClock(16);
3003   HandleScrollUpdate(true /* is_momentum */);
3004   AdvanceClock(16);
3005   HandleScrollUpdate(true /* is_momentum */);
3006   AdvanceClock(1);
3007   DeliverInputForBeginFrame();
3008 
3009   // Enqueue two updates, they will be coalesced and count as one jank
3010   // (https://crbug.com/952930).
3011   AdvanceClock(16);
3012   HandleScrollUpdate(true /* is_momentum */);
3013   AdvanceClock(16);
3014   HandleScrollUpdate(true /* is_momentum */);
3015   AdvanceClock(1);
3016   DeliverInputForBeginFrame();
3017 
3018   // Enqueue two updates, they will be coalesced and count as one
3019   // jank(https://crbug.com/952930).
3020   AdvanceClock(16);
3021   HandleScrollUpdate(true /* is_momentum */);
3022   AdvanceClock(16);
3023   HandleScrollUpdate(true /* is_momentum */);
3024   AdvanceClock(1);
3025   DeliverInputForBeginFrame();
3026 
3027   // Add 93 non-janky events, bringing us to a total of 100 events.
3028   AddNonJankyEvents(93);
3029 
3030   HandleScrollEnd();
3031   DeliverInputForBeginFrame();
3032 
3033   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
3034                                       4, 1);
3035 }
3036 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJankMultipleGestures)3037 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJankMultipleGestures) {
3038   cc::InputHandlerScrollResult scroll_result_did_scroll;
3039   scroll_result_did_scroll.did_scroll = true;
3040   EXPECT_CALL(
3041       mock_input_handler_,
3042       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3043                    _))
3044       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3045 
3046   base::HistogramTester histogram_tester;
3047 
3048   for (int i = 0; i < 3; ++i) {
3049     HandleScrollBegin();
3050 
3051     // Flush one update, the first update is always ignored.
3052     AdvanceClock(16);
3053     HandleScrollUpdate(true /* is_momentum */);
3054     DeliverInputForBeginFrame();
3055 
3056     // Enqueue two updates, they will be coalesced and count as one jank
3057     // (https://crbug.com/952930).
3058     AdvanceClock(16);
3059     HandleScrollUpdate(true /* is_momentum */);
3060     AdvanceClock(16);
3061     HandleScrollUpdate(true /* is_momentum */);
3062     AdvanceClock(1);
3063     DeliverInputForBeginFrame();
3064 
3065     // Add 98 non-janky events, bringing us to a total of 100 events.
3066     AddNonJankyEvents(98);
3067 
3068     HandleScrollEnd();
3069     DeliverInputForBeginFrame();
3070 
3071     histogram_tester.ExpectUniqueSample(
3072         "Renderer4.MomentumScrollJankPercentage", 1, i + 1);
3073   }
3074 }
3075 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJankRounding)3076 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJankRounding) {
3077   cc::InputHandlerScrollResult scroll_result_did_scroll;
3078   scroll_result_did_scroll.did_scroll = true;
3079   EXPECT_CALL(
3080       mock_input_handler_,
3081       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3082                    _))
3083       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3084 
3085   base::HistogramTester histogram_tester;
3086 
3087   HandleScrollBegin();
3088 
3089   // Flush one update, the first update is always ignored.
3090   AdvanceClock(16);
3091   HandleScrollUpdate(true /* is_momentum */);
3092   DeliverInputForBeginFrame();
3093 
3094   // Enqueue two updates, they will be coalesced and count as one jank
3095   // (https://crbug.com/952930).
3096   AdvanceClock(16);
3097   HandleScrollUpdate(true /* is_momentum */);
3098   AdvanceClock(16);
3099   HandleScrollUpdate(true /* is_momentum */);
3100   AdvanceClock(1);
3101   DeliverInputForBeginFrame();
3102 
3103   // Add 500 non-janky events. Even with this many events, our round-up logic
3104   // should cause us to report 1% jank.
3105   AddNonJankyEvents(500);
3106 
3107   HandleScrollEnd();
3108   DeliverInputForBeginFrame();
3109 
3110   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
3111                                       1, 1);
3112 }
3113 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestSimpleNoJank)3114 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestSimpleNoJank) {
3115   cc::InputHandlerScrollResult scroll_result_did_scroll;
3116   scroll_result_did_scroll.did_scroll = true;
3117   EXPECT_CALL(
3118       mock_input_handler_,
3119       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3120                    _))
3121       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3122 
3123   base::HistogramTester histogram_tester;
3124   HandleScrollBegin();
3125 
3126   // Flush one update, the first update is always ignored.
3127   AdvanceClock(16);
3128   HandleScrollUpdate(true /* is_momentum */);
3129   AdvanceClock(1);
3130   DeliverInputForBeginFrame();
3131 
3132   // Enqueue one updates, no jank.
3133   AdvanceClock(16);
3134   HandleScrollUpdate(true /* is_momentum */);
3135   AdvanceClock(1);
3136   DeliverInputForBeginFrame();
3137 
3138   // Enqueue one updates, no jank.
3139   AdvanceClock(16);
3140   HandleScrollUpdate(true /* is_momentum */);
3141   AdvanceClock(1);
3142   DeliverInputForBeginFrame();
3143 
3144   HandleScrollEnd();
3145   DeliverInputForBeginFrame();
3146 
3147   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
3148                                       0, 1);
3149 }
3150 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestFirstGestureNoJank)3151 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestFirstGestureNoJank) {
3152   cc::InputHandlerScrollResult scroll_result_did_scroll;
3153   scroll_result_did_scroll.did_scroll = true;
3154   EXPECT_CALL(
3155       mock_input_handler_,
3156       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3157                    _))
3158       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3159 
3160   base::HistogramTester histogram_tester;
3161   HandleScrollBegin();
3162 
3163   // Even with 3 coalesced frames, the first gesture should not trigger a jank.
3164   AdvanceClock(16);
3165   HandleScrollUpdate(true /* is_momentum */);
3166   AdvanceClock(16);
3167   HandleScrollUpdate(true /* is_momentum */);
3168   AdvanceClock(16);
3169   HandleScrollUpdate(true /* is_momentum */);
3170   AdvanceClock(1);
3171   DeliverInputForBeginFrame();
3172 
3173   HandleScrollEnd();
3174   DeliverInputForBeginFrame();
3175 
3176   histogram_tester.ExpectTotalCount("Renderer4.MomentumScrollJankPercentage",
3177                                     0);
3178 }
3179 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestNonMomentumNoJank)3180 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestNonMomentumNoJank) {
3181   cc::InputHandlerScrollResult scroll_result_did_scroll;
3182   scroll_result_did_scroll.did_scroll = true;
3183   EXPECT_CALL(
3184       mock_input_handler_,
3185       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3186                    _))
3187       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3188 
3189   base::HistogramTester histogram_tester;
3190   HandleScrollBegin();
3191 
3192   // Flush one update, the first update is always ignored.
3193   AdvanceClock(16);
3194   HandleScrollUpdate(false /* is_momentum */);
3195   AdvanceClock(1);
3196   DeliverInputForBeginFrame();
3197 
3198   // Enqueue three updates, these will not cause jank, as none are momentum.
3199   AdvanceClock(16);
3200   HandleScrollUpdate(false /* is_momentum */);
3201   AdvanceClock(16);
3202   HandleScrollUpdate(false /* is_momentum */);
3203   AdvanceClock(16);
3204   HandleScrollUpdate(false /* is_momentum */);
3205   AdvanceClock(1);
3206   DeliverInputForBeginFrame();
3207 
3208   HandleScrollEnd();
3209   DeliverInputForBeginFrame();
3210 
3211   histogram_tester.ExpectTotalCount("Renderer4.MomentumScrollJankPercentage",
3212                                     0);
3213 }
3214 
3215 INSTANTIATE_TEST_SUITE_P(AnimateInput,
3216                          InputHandlerProxyTest,
3217                          testing::ValuesIn(test_types));
3218 
3219 INSTANTIATE_TEST_SUITE_P(AnimateInput,
3220                          InputHandlerProxyMainThreadScrollingReasonTest,
3221                          testing::ValuesIn(test_types));
3222 }  // namespace test
3223 }  // namespace ui
3224