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 "third_party/blink/public/platform/input/input_handler_proxy.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/containers/circular_deque.h"
12 #include "base/macros.h"
13 #include "base/test/bind.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/base/features.h"
21 #include "cc/input/main_thread_scrolling_reason.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 "third_party/blink/public/platform/input/input_handler_proxy.h"
33 #include "third_party/blink/public/platform/input/input_handler_proxy_client.h"
34 #include "third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h"
35 #include "third_party/blink/renderer/platform/widget/input/event_with_callback.h"
36 #include "third_party/blink/renderer/platform/widget/input/scroll_predictor.h"
37 #include "ui/events/types/scroll_input_type.h"
38 #include "ui/gfx/geometry/scroll_offset.h"
39 #include "ui/gfx/geometry/size_f.h"
40 #include "ui/latency/latency_info.h"
41 
42 using cc::InputHandler;
43 using cc::ScrollBeginThreadState;
44 using cc::TouchAction;
45 using testing::_;
46 using testing::AllOf;
47 using testing::DoAll;
48 using testing::Eq;
49 using testing::Field;
50 using testing::Mock;
51 using testing::NiceMock;
52 using testing::Property;
53 using testing::Return;
54 using testing::SetArgPointee;
55 using testing::StrictMock;
56 
57 namespace blink {
58 namespace test {
59 
60 namespace {
61 
62 MATCHER_P(WheelEventsMatch, expected, "") {
63   return WheelEventsMatch(arg, expected);
64 }
65 
CreateGestureScrollPinch(WebInputEvent::Type type,WebGestureDevice source_device,base::TimeTicks event_time,float delta_y_or_scale=0,int x=0,int y=0)66 std::unique_ptr<WebInputEvent> CreateGestureScrollPinch(
67     WebInputEvent::Type type,
68     WebGestureDevice source_device,
69     base::TimeTicks event_time,
70     float delta_y_or_scale = 0,
71     int x = 0,
72     int y = 0) {
73   auto gesture = std::make_unique<WebGestureEvent>(
74       type, WebInputEvent::kNoModifiers, event_time, source_device);
75   if (type == WebInputEvent::Type::kGestureScrollUpdate) {
76     gesture->data.scroll_update.delta_y = delta_y_or_scale;
77   } else if (type == WebInputEvent::Type::kGesturePinchUpdate) {
78     gesture->data.pinch_update.scale = delta_y_or_scale;
79     gesture->SetPositionInWidget(gfx::PointF(x, y));
80   }
81   return gesture;
82 }
83 
84 class MockInputHandler : public cc::InputHandler {
85  public:
86   MockInputHandler() = default;
87   ~MockInputHandler() override = default;
88 
89   MockInputHandler(const MockInputHandler&) = delete;
90   MockInputHandler& operator=(const MockInputHandler&) = delete;
91 
AsWeakPtr() const92   base::WeakPtr<InputHandler> AsWeakPtr() const override {
93     return weak_ptr_factory_.GetWeakPtr();
94   }
95 
96   MOCK_METHOD0(PinchGestureBegin, void());
97   MOCK_METHOD2(PinchGestureUpdate,
98                void(float magnify_delta, const gfx::Point& anchor));
99   MOCK_METHOD2(PinchGestureEnd, void(const gfx::Point& anchor, bool snap));
100 
101   MOCK_METHOD0(SetNeedsAnimateInput, void());
102 
103   MOCK_METHOD2(ScrollBegin,
104                ScrollStatus(cc::ScrollState*, ui::ScrollInputType type));
105   MOCK_METHOD2(RootScrollBegin,
106                ScrollStatus(cc::ScrollState*, ui::ScrollInputType type));
107   MOCK_METHOD2(ScrollUpdate,
108                cc::InputHandlerScrollResult(cc::ScrollState*, base::TimeDelta));
109   MOCK_METHOD1(ScrollEnd, void(bool));
110   MOCK_METHOD2(RecordScrollBegin,
111                void(ui::ScrollInputType type,
112                     cc::ScrollBeginThreadState state));
113   MOCK_METHOD1(RecordScrollEnd, void(ui::ScrollInputType type));
114   MOCK_METHOD0(ScrollingShouldSwitchtoMainThread, bool());
115   MOCK_METHOD2(MouseDown,
116                cc::InputHandlerPointerResult(const gfx::PointF& mouse_position,
117                                              const bool shift_modifier));
118   MOCK_METHOD1(
119       MouseUp,
120       cc::InputHandlerPointerResult(const gfx::PointF& mouse_position));
NotifyInputEvent()121   void NotifyInputEvent() override {}
122 
CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo * latency)123   std::unique_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
124       ui::LatencyInfo* latency) override {
125     return nullptr;
126   }
127 
128   std::unique_ptr<cc::EventsMetricsManager::ScopedMonitor>
GetScopedEventMetricsMonitor(cc::EventsMetricsManager::ScopedMonitor::DoneCallback)129   GetScopedEventMetricsMonitor(
130       cc::EventsMetricsManager::ScopedMonitor::DoneCallback) override {
131     return nullptr;
132   }
133 
CreateScrollElasticityHelper()134   cc::ScrollElasticityHelper* CreateScrollElasticityHelper() override {
135     return nullptr;
136   }
GetScrollOffsetForLayer(cc::ElementId element_id,gfx::ScrollOffset * offset)137   bool GetScrollOffsetForLayer(cc::ElementId element_id,
138                                gfx::ScrollOffset* offset) override {
139     return false;
140   }
ScrollLayerTo(cc::ElementId element_id,const gfx::ScrollOffset & offset)141   bool ScrollLayerTo(cc::ElementId element_id,
142                      const gfx::ScrollOffset& offset) override {
143     return false;
144   }
145 
BindToClient(cc::InputHandlerClient * client)146   void BindToClient(cc::InputHandlerClient* client) override {}
147 
MouseLeave()148   void MouseLeave() override {}
149 
150   MOCK_METHOD1(FindFrameElementIdAtPoint, cc::ElementId(const gfx::PointF&));
151 
MouseMoveAt(const gfx::Point & mouse_position)152   cc::InputHandlerPointerResult MouseMoveAt(
153       const gfx::Point& mouse_position) override {
154     return cc::InputHandlerPointerResult();
155   }
156 
157   MOCK_CONST_METHOD1(
158       GetEventListenerProperties,
159       cc::EventListenerProperties(cc::EventListenerClass event_class));
160   MOCK_METHOD2(EventListenerTypeForTouchStartOrMoveAt,
161                cc::InputHandler::TouchStartOrMoveEventListenerType(
162                    const gfx::Point& point,
163                    cc::TouchAction* touch_action));
164   MOCK_CONST_METHOD1(HasBlockingWheelEventHandlerAt, bool(const gfx::Point&));
165 
166   MOCK_METHOD0(RequestUpdateForSynchronousInputHandler, void());
167   MOCK_METHOD1(SetSynchronousInputHandlerRootScrollOffset,
168                void(const gfx::ScrollOffset& root_offset));
169 
IsCurrentlyScrollingViewport() const170   bool IsCurrentlyScrollingViewport() const override {
171     return is_scrolling_root_;
172   }
set_is_scrolling_root(bool is)173   void set_is_scrolling_root(bool is) { is_scrolling_root_ = is; }
174 
175   MOCK_METHOD3(GetSnapFlingInfoAndSetAnimatingSnapTarget,
176                bool(const gfx::Vector2dF& natural_displacement,
177                     gfx::Vector2dF* initial_offset,
178                     gfx::Vector2dF* target_offset));
179   MOCK_METHOD1(ScrollEndForSnapFling, void(bool));
180 
181  private:
182   bool is_scrolling_root_ = true;
183 
184   base::WeakPtrFactory<MockInputHandler> weak_ptr_factory_{this};
185 };
186 
187 class MockSynchronousInputHandler : public SynchronousInputHandler {
188  public:
189   MOCK_METHOD6(UpdateRootLayerState,
190                void(const gfx::ScrollOffset& total_scroll_offset,
191                     const gfx::ScrollOffset& max_scroll_offset,
192                     const gfx::SizeF& scrollable_size,
193                     float page_scale_factor,
194                     float min_page_scale_factor,
195                     float max_page_scale_factor));
196 };
197 
198 class MockInputHandlerProxyClient : public InputHandlerProxyClient {
199  public:
MockInputHandlerProxyClient()200   MockInputHandlerProxyClient() {}
~MockInputHandlerProxyClient()201   ~MockInputHandlerProxyClient() override {}
202 
WillShutdown()203   void WillShutdown() override {}
204 
205   MOCK_METHOD3(GenerateScrollBeginAndSendToMainThread,
206                void(const WebGestureEvent& update_event,
207                     const WebInputEventAttribution&,
208                     const cc::EventMetrics*));
209 
DispatchNonBlockingEventToMainThread(std::unique_ptr<WebCoalescedInputEvent> event,const WebInputEventAttribution &,std::unique_ptr<cc::EventMetrics> metrics)210   void DispatchNonBlockingEventToMainThread(
211       std::unique_ptr<WebCoalescedInputEvent> event,
212       const WebInputEventAttribution&,
213       std::unique_ptr<cc::EventMetrics> metrics) override {}
214 
215   MOCK_METHOD5(DidOverscroll,
216                void(const gfx::Vector2dF& accumulated_overscroll,
217                     const gfx::Vector2dF& latest_overscroll_delta,
218                     const gfx::Vector2dF& current_fling_velocity,
219                     const gfx::PointF& causal_event_viewport_point,
220                     const cc::OverscrollBehavior& overscroll_behavior));
DidAnimateForInput()221   void DidAnimateForInput() override {}
DidStartScrollingViewport()222   void DidStartScrollingViewport() override {}
223   MOCK_METHOD3(SetAllowedTouchAction,
224                void(cc::TouchAction touch_action,
225                     uint32_t unique_touch_event_id,
226                     InputHandlerProxy::EventDisposition event_disposition));
227 
228  private:
229   DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
230 };
231 
232 class MockInputHandlerProxyClientWithDidAnimateForInput
233     : public MockInputHandlerProxyClient {
234  public:
MockInputHandlerProxyClientWithDidAnimateForInput()235   MockInputHandlerProxyClientWithDidAnimateForInput() {}
~MockInputHandlerProxyClientWithDidAnimateForInput()236   ~MockInputHandlerProxyClientWithDidAnimateForInput() override {}
237 
238   MOCK_METHOD0(DidAnimateForInput, void());
239 
240  private:
241   DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidAnimateForInput);
242 };
243 
CreateWebTouchPoint(WebTouchPoint::State state,float x,float y)244 WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state,
245                                   float x,
246                                   float y) {
247   WebTouchPoint point;
248   point.state = state;
249   point.SetPositionInScreen(x, y);
250   point.SetPositionInWidget(x, y);
251   return point;
252 }
253 
254 const cc::InputHandler::ScrollStatus kImplThreadScrollState(
255     cc::InputHandler::ScrollThread::SCROLL_ON_IMPL_THREAD,
256     cc::MainThreadScrollingReason::kNotScrollingOnMain);
257 
258 const cc::InputHandler::ScrollStatus kRequiresMainThreadHitTestState(
259     cc::InputHandler::ScrollThread::SCROLL_ON_IMPL_THREAD,
260     cc::MainThreadScrollingReason::kNotScrollingOnMain,
261     /*needs_main_thread_hit_test=*/true);
262 
263 const cc::InputHandler::ScrollStatus kMainThreadScrollState(
264     cc::InputHandler::ScrollThread::SCROLL_ON_MAIN_THREAD,
265     cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
266 
267 const cc::InputHandler::ScrollStatus kScrollIgnoredScrollState(
268     cc::InputHandler::ScrollThread::SCROLL_IGNORED,
269     cc::MainThreadScrollingReason::kNotScrollable);
270 
271 }  // namespace
272 
273 class TestInputHandlerProxy : public InputHandlerProxy {
274  public:
TestInputHandlerProxy(cc::InputHandler & input_handler,InputHandlerProxyClient * client)275   TestInputHandlerProxy(cc::InputHandler& input_handler,
276                         InputHandlerProxyClient* client)
277       : InputHandlerProxy(input_handler, client) {}
RecordMainThreadScrollingReasonsForTest(WebGestureDevice device,uint32_t reasons)278   void RecordMainThreadScrollingReasonsForTest(WebGestureDevice device,
279                                                uint32_t reasons) {
280     RecordMainThreadScrollingReasons(device, reasons);
281   }
282 
283   MOCK_METHOD0(SetNeedsAnimateInput, void());
284 
HitTestTouchEventForTest(const WebTouchEvent & touch_event,bool * is_touching_scrolling_layer,cc::TouchAction * allowed_touch_action)285   EventDisposition HitTestTouchEventForTest(
286       const WebTouchEvent& touch_event,
287       bool* is_touching_scrolling_layer,
288       cc::TouchAction* allowed_touch_action) {
289     return HitTestTouchEvent(touch_event, is_touching_scrolling_layer,
290                              allowed_touch_action);
291   }
292 
HandleMouseWheelForTest(const WebMouseWheelEvent & wheel_event)293   EventDisposition HandleMouseWheelForTest(
294       const WebMouseWheelEvent& wheel_event) {
295     return HandleMouseWheel(wheel_event);
296   }
297 
298   // This is needed because the tests can't directly call
299   // DispatchQueuedInputEvents since it is private.
DispatchQueuedInputEventsHelper()300   void DispatchQueuedInputEventsHelper() { DispatchQueuedInputEvents(); }
301 };
302 
303 // Whether or not the input handler says that the viewport is scrolling the
304 // root scroller or a child.
305 enum class ScrollerType { kRoot, kChild };
306 
307 // Whether or not to setup a synchronous input handler. This simulates the mode
308 // that WebView runs in.
309 enum class HandlerType { kNormal, kSynchronous };
310 
311 // Run tests with unification both on and off.
312 enum class ScrollUnification { kEnabled, kDisabled };
313 
314 class InputHandlerProxyTest
315     : public testing::Test,
316       public testing::WithParamInterface<
317           std::tuple<ScrollerType, HandlerType, ScrollUnification>> {
GetScrollerType()318   ScrollerType GetScrollerType() { return std::get<0>(GetParam()); }
GetHandlerType()319   HandlerType GetHandlerType() { return std::get<1>(GetParam()); }
GetScrollUnificationState()320   ScrollUnification GetScrollUnificationState() {
321     return std::get<2>(GetParam());
322   }
323 
324  public:
InputHandlerProxyTest()325   InputHandlerProxyTest() {
326     if (GetScrollUnificationState() == ScrollUnification::kEnabled)
327       scoped_feature_list_.InitAndEnableFeature(features::kScrollUnification);
328     else
329       scoped_feature_list_.InitAndDisableFeature(features::kScrollUnification);
330 
331     input_handler_ = std::make_unique<TestInputHandlerProxy>(
332         mock_input_handler_, &mock_client_);
333     scroll_result_did_scroll_.did_scroll = true;
334     scroll_result_did_not_scroll_.did_scroll = false;
335 
336     if (GetHandlerType() == HandlerType::kSynchronous) {
337       EXPECT_CALL(mock_input_handler_,
338                   RequestUpdateForSynchronousInputHandler())
339           .Times(1);
340       input_handler_->SetSynchronousInputHandler(
341           &mock_synchronous_input_handler_);
342     }
343 
344     mock_input_handler_.set_is_scrolling_root(
345         GetHandlerType() == HandlerType::kSynchronous &&
346         GetScrollerType() == ScrollerType::kRoot);
347 
348     // Set a default device so tests don't always have to set this.
349     gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
350 
351     input_handler_->set_event_attribution_enabled(false);
352   }
353 
354   virtual ~InputHandlerProxyTest() = default;
355 
356 // This is defined as a macro so the line numbers can be traced back to the
357 // correct spot when it fails.
358 #define EXPECT_SET_NEEDS_ANIMATE_INPUT(times)                              \
359   do {                                                                     \
360     EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(times); \
361   } while (false)
362 
363 // This is defined as a macro because when an expectation is not satisfied the
364 // only output you get out of gmock is the line number that set the expectation.
365 #define VERIFY_AND_RESET_MOCKS()                                     \
366   do {                                                               \
367     testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \
368     testing::Mock::VerifyAndClearExpectations(                       \
369         &mock_synchronous_input_handler_);                           \
370     testing::Mock::VerifyAndClearExpectations(&mock_client_);        \
371   } while (false)
372 
Animate(base::TimeTicks time)373   void Animate(base::TimeTicks time) { input_handler_->Animate(time); }
374 
SetSmoothScrollEnabled(bool value)375   void SetSmoothScrollEnabled(bool value) {}
376 
histogram_tester()377   base::HistogramTester& histogram_tester() { return histogram_tester_; }
378 
379  protected:
380   void GestureScrollStarted();
381   void ScrollHandlingSwitchedToMainThread();
382   void GestureScrollIgnored();
383   void FlingAndSnap();
384 
385   testing::StrictMock<MockInputHandler> mock_input_handler_;
386   testing::StrictMock<MockSynchronousInputHandler>
387       mock_synchronous_input_handler_;
388   std::unique_ptr<TestInputHandlerProxy> input_handler_;
389   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
390   WebGestureEvent gesture_;
391   InputHandlerProxy::EventDisposition expected_disposition_ =
392       InputHandlerProxy::DID_HANDLE;
393   base::HistogramTester histogram_tester_;
394   cc::InputHandlerScrollResult scroll_result_did_scroll_;
395   cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
396   base::test::ScopedFeatureList scoped_feature_list_;
397 };
398 
399 // The helper basically returns the EventDisposition that is returned by
400 // RouteToTypeSpecificHandler. This is done by passing in a callback when
401 // calling HandleInputEventWithLatencyInfo. By design, DispatchSingleInputEvent
402 // will then call this callback with the disposition returned by
403 // RouteToTypeSpecificHandler and that is what gets returned by this helper.
HandleInputEventWithLatencyInfo(TestInputHandlerProxy * input_handler,const WebInputEvent & event)404 InputHandlerProxy::EventDisposition HandleInputEventWithLatencyInfo(
405     TestInputHandlerProxy* input_handler,
406     const WebInputEvent& event) {
407   std::unique_ptr<WebCoalescedInputEvent> scoped_input_event =
408       std::make_unique<WebCoalescedInputEvent>(event.Clone(),
409                                                ui::LatencyInfo());
410   InputHandlerProxy::EventDisposition event_disposition =
411       InputHandlerProxy::DID_NOT_HANDLE;
412   input_handler->HandleInputEventWithLatencyInfo(
413       std::move(scoped_input_event), nullptr,
414       base::BindLambdaForTesting(
415           [&event_disposition](
416               InputHandlerProxy::EventDisposition disposition,
417               std::unique_ptr<blink::WebCoalescedInputEvent> event,
418               std::unique_ptr<InputHandlerProxy::DidOverscrollParams> callback,
419               const WebInputEventAttribution& attribution,
420               std::unique_ptr<cc::EventMetrics> metrics) {
421             event_disposition = disposition;
422           }));
423   return event_disposition;
424 }
425 
426 // This helper forces the CompositorThreadEventQueue to be flushed.
HandleInputEventAndFlushEventQueue(testing::StrictMock<MockInputHandler> & mock_input_handler,TestInputHandlerProxy * input_handler,const WebInputEvent & event)427 InputHandlerProxy::EventDisposition HandleInputEventAndFlushEventQueue(
428     testing::StrictMock<MockInputHandler>& mock_input_handler,
429     TestInputHandlerProxy* input_handler,
430     const WebInputEvent& event) {
431   EXPECT_CALL(mock_input_handler, SetNeedsAnimateInput())
432       .Times(testing::AnyNumber());
433 
434   std::unique_ptr<WebCoalescedInputEvent> scoped_input_event =
435       std::make_unique<WebCoalescedInputEvent>(event.Clone(),
436                                                ui::LatencyInfo());
437   InputHandlerProxy::EventDisposition event_disposition =
438       InputHandlerProxy::DID_NOT_HANDLE;
439   input_handler->HandleInputEventWithLatencyInfo(
440       std::move(scoped_input_event), nullptr,
441       base::BindLambdaForTesting(
442           [&event_disposition](
443               InputHandlerProxy::EventDisposition disposition,
444               std::unique_ptr<blink::WebCoalescedInputEvent> event,
445               std::unique_ptr<InputHandlerProxy::DidOverscrollParams> callback,
446               const WebInputEventAttribution& attribution,
447               std::unique_ptr<cc::EventMetrics> metrics) {
448             event_disposition = disposition;
449           }));
450 
451   input_handler->DispatchQueuedInputEventsHelper();
452   return event_disposition;
453 }
454 
455 class InputHandlerProxyEventQueueTest : public testing::Test {
456  public:
InputHandlerProxyEventQueueTest()457   InputHandlerProxyEventQueueTest()
458       : input_handler_proxy_(mock_input_handler_, &mock_client_) {
459     SetScrollPredictionEnabled(true);
460   }
461 
462   ~InputHandlerProxyEventQueueTest() = default;
463 
HandleGestureEvent(WebInputEvent::Type type,float delta_y_or_scale=0,int x=0,int y=0)464   void HandleGestureEvent(WebInputEvent::Type type,
465                           float delta_y_or_scale = 0,
466                           int x = 0,
467                           int y = 0) {
468     HandleGestureEventWithSourceDevice(type, WebGestureDevice::kTouchscreen,
469                                        delta_y_or_scale, x, y);
470   }
471 
HandleGestureEventWithSourceDevice(WebInputEvent::Type type,WebGestureDevice source_device,float delta_y_or_scale=0,int x=0,int y=0)472   void HandleGestureEventWithSourceDevice(WebInputEvent::Type type,
473                                           WebGestureDevice source_device,
474                                           float delta_y_or_scale = 0,
475                                           int x = 0,
476                                           int y = 0) {
477     InjectInputEvent(CreateGestureScrollPinch(
478         type, source_device, input_handler_proxy_.tick_clock_->NowTicks(),
479         delta_y_or_scale, x, y));
480   }
481 
InjectInputEvent(std::unique_ptr<WebInputEvent> event)482   void InjectInputEvent(std::unique_ptr<WebInputEvent> event) {
483     input_handler_proxy_.HandleInputEventWithLatencyInfo(
484         std::make_unique<WebCoalescedInputEvent>(std::move(event),
485                                                  ui::LatencyInfo()),
486         nullptr,
487         base::BindOnce(
488             &InputHandlerProxyEventQueueTest::DidHandleInputEventAndOverscroll,
489             weak_ptr_factory_.GetWeakPtr()));
490   }
491 
HandleMouseEvent(WebInputEvent::Type type,int x=0,int y=0)492   void HandleMouseEvent(WebInputEvent::Type type, int x = 0, int y = 0) {
493     WebMouseEvent mouse_event(type, WebInputEvent::kNoModifiers,
494                               WebInputEvent::GetStaticTimeStampForTests());
495 
496     mouse_event.SetPositionInWidget(gfx::PointF(x, y));
497     mouse_event.button = WebMouseEvent::Button::kLeft;
498     HandleInputEventWithLatencyInfo(&input_handler_proxy_, mouse_event);
499   }
500 
DidHandleInputEventAndOverscroll(InputHandlerProxy::EventDisposition event_disposition,std::unique_ptr<WebCoalescedInputEvent> input_event,std::unique_ptr<InputHandlerProxy::DidOverscrollParams> overscroll_params,const WebInputEventAttribution & attribution,std::unique_ptr<cc::EventMetrics> metrics)501   void DidHandleInputEventAndOverscroll(
502       InputHandlerProxy::EventDisposition event_disposition,
503       std::unique_ptr<WebCoalescedInputEvent> input_event,
504       std::unique_ptr<InputHandlerProxy::DidOverscrollParams> overscroll_params,
505       const WebInputEventAttribution& attribution,
506       std::unique_ptr<cc::EventMetrics> metrics) {
507     event_disposition_recorder_.push_back(event_disposition);
508     latency_info_recorder_.push_back(input_event->latency_info());
509   }
510 
event_queue()511   base::circular_deque<std::unique_ptr<EventWithCallback>>& event_queue() {
512     return input_handler_proxy_.compositor_event_queue_->queue_;
513   }
514 
SetInputHandlerProxyTickClockForTesting(const base::TickClock * tick_clock)515   void SetInputHandlerProxyTickClockForTesting(
516       const base::TickClock* tick_clock) {
517     input_handler_proxy_.SetTickClockForTesting(tick_clock);
518   }
519 
DeliverInputForBeginFrame()520   void DeliverInputForBeginFrame() {
521     constexpr base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
522     base::TimeTicks frame_time =
523         WebInputEvent::GetStaticTimeStampForTests() +
524         (next_begin_frame_number_ - viz::BeginFrameArgs::kStartingFrameNumber) *
525             interval;
526     input_handler_proxy_.DeliverInputForBeginFrame(viz::BeginFrameArgs::Create(
527         BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, frame_time,
528         frame_time + interval, interval, viz::BeginFrameArgs::NORMAL));
529   }
530 
DeliverInputForHighLatencyMode()531   void DeliverInputForHighLatencyMode() {
532     input_handler_proxy_.DeliverInputForHighLatencyMode();
533   }
534 
SetScrollPredictionEnabled(bool enabled)535   void SetScrollPredictionEnabled(bool enabled) {
536     input_handler_proxy_.scroll_predictor_ =
537         enabled ? std::make_unique<ScrollPredictor>() : nullptr;
538   }
539 
540   std::unique_ptr<ui::InputPredictor::InputData>
GestureScrollEventPredictionAvailable()541   GestureScrollEventPredictionAvailable() {
542     return input_handler_proxy_.scroll_predictor_->predictor_
543         ->GeneratePrediction(WebInputEvent::GetStaticTimeStampForTests());
544   }
545 
NowTimestampForEvents()546   base::TimeTicks NowTimestampForEvents() {
547     return input_handler_proxy_.tick_clock_->NowTicks();
548   }
549 
550  protected:
551   testing::StrictMock<MockInputHandler> mock_input_handler_;
552   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
553   TestInputHandlerProxy input_handler_proxy_;
554   std::vector<InputHandlerProxy::EventDisposition> event_disposition_recorder_;
555   std::vector<ui::LatencyInfo> latency_info_recorder_;
556 
557   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
558 
559   base::test::SingleThreadTaskEnvironment task_environment_;
560   base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_{this};
561 };
562 
563 // Tests that changing source devices mid gesture scroll is handled gracefully.
564 // For example, when a touch scroll is in progress and the user initiates a
565 // scrollbar scroll before the touch scroll has had a chance to dispatch a GSE.
TEST_P(InputHandlerProxyTest,NestedGestureBasedScrollsDifferentSourceDevice)566 TEST_P(InputHandlerProxyTest, NestedGestureBasedScrollsDifferentSourceDevice) {
567   // Touchpad initiates a scroll.
568   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
569       .WillOnce(testing::Return(kImplThreadScrollState));
570   EXPECT_CALL(
571       mock_input_handler_,
572       RecordScrollBegin(ui::ScrollInputType::kWheel,
573                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
574       .Times(1);
575 
576   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
577   gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
578   EXPECT_EQ(InputHandlerProxy::DID_HANDLE,
579             HandleInputEventAndFlushEventQueue(mock_input_handler_,
580                                                input_handler_.get(), gesture_));
581   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
582 
583   VERIFY_AND_RESET_MOCKS();
584 
585   // Before ScrollEnd for touchpad is fired, user starts a thumb drag. This is
586   // expected to immediately end the touchpad scroll.
587   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(ui::ScrollInputType::kWheel))
588       .Times(1);
589   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
590   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
591       .WillOnce(testing::Return(kImplThreadScrollState));
592   EXPECT_CALL(
593       mock_input_handler_,
594       RecordScrollBegin(ui::ScrollInputType::kScrollbar,
595                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
596       .Times(1);
597   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
598   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
599     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
600         .WillOnce(testing::Return(false));
601   }
602 
603   WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
604                             WebInputEvent::kNoModifiers,
605                             WebInputEvent::GetStaticTimeStampForTests());
606   mouse_event.SetPositionInWidget(gfx::PointF(0, 20));
607   mouse_event.button = WebMouseEvent::Button::kLeft;
608 
609   cc::InputHandlerPointerResult pointer_down_result;
610   pointer_down_result.type = cc::PointerResultType::kScrollbarScroll;
611   pointer_down_result.scroll_offset = gfx::ScrollOffset(0, 1);
612   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
613       .WillOnce(testing::Return(pointer_down_result));
614 
615   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
616             HandleInputEventAndFlushEventQueue(
617                 mock_input_handler_, input_handler_.get(), mouse_event));
618 
619   VERIFY_AND_RESET_MOCKS();
620 
621   // Touchpad GSE comes in while a scrollbar drag is in progress. This is
622   // expected to be dropped because a scrollbar scroll is currently active.
623   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
624   gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
625   gesture_.data.scroll_update.delta_y = 0;
626   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(ui::ScrollInputType::kWheel))
627       .Times(1);
628   EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
629             HandleInputEventAndFlushEventQueue(mock_input_handler_,
630                                                input_handler_.get(), gesture_));
631   VERIFY_AND_RESET_MOCKS();
632 
633   // The GSE from the scrollbar needs to be handled.
634   EXPECT_CALL(mock_input_handler_,
635               RecordScrollEnd(ui::ScrollInputType::kScrollbar))
636       .Times(1);
637   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
638   cc::InputHandlerPointerResult pointer_up_result;
639   pointer_up_result.type = cc::PointerResultType::kScrollbarScroll;
640   EXPECT_CALL(mock_input_handler_, MouseUp(_))
641       .WillOnce(testing::Return(pointer_up_result));
642   mouse_event.SetType(WebInputEvent::Type::kMouseUp);
643   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
644             HandleInputEventAndFlushEventQueue(
645                 mock_input_handler_, input_handler_.get(), mouse_event));
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::Type::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::Type::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::Type::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::Type::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::Type::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::Type::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 
758 // Tests that changing source devices when an animated scroll is in progress
759 // ends the current scroll offset animation and ensures that a new one gets
760 // created.
TEST_P(InputHandlerProxyTest,ScrollbarScrollEndOnDeviceChange)761 TEST_P(InputHandlerProxyTest, ScrollbarScrollEndOnDeviceChange) {
762   // A scrollbar scroll begins.
763   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
764       .WillOnce(testing::Return(kImplThreadScrollState));
765   EXPECT_CALL(
766       mock_input_handler_,
767       RecordScrollBegin(ui::ScrollInputType::kScrollbar,
768                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
769       .Times(1);
770   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
771   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
772     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
773         .WillOnce(testing::Return(false));
774   }
775   WebMouseEvent mouse_event(WebInputEvent::Type::kMouseDown,
776                             WebInputEvent::kNoModifiers,
777                             WebInputEvent::GetStaticTimeStampForTests());
778   mouse_event.SetPositionInWidget(gfx::PointF(0, 20));
779   mouse_event.button = WebMouseEvent::Button::kLeft;
780   cc::InputHandlerPointerResult pointer_down_result;
781   pointer_down_result.type = cc::PointerResultType::kScrollbarScroll;
782   pointer_down_result.scroll_offset = gfx::ScrollOffset(0, 1);
783   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
784       .WillOnce(testing::Return(pointer_down_result));
785   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
786             HandleInputEventAndFlushEventQueue(
787                 mock_input_handler_, input_handler_.get(), mouse_event));
788 
789   EXPECT_EQ(input_handler_->currently_active_gesture_device(),
790             WebGestureDevice::kScrollbar);
791   VERIFY_AND_RESET_MOCKS();
792 
793   // A mousewheel tick takes place before the scrollbar scroll ends.
794   EXPECT_CALL(mock_input_handler_,
795               RecordScrollEnd(ui::ScrollInputType::kScrollbar))
796       .Times(1);
797   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
798   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
799       .WillOnce(testing::Return(kImplThreadScrollState));
800   EXPECT_CALL(
801       mock_input_handler_,
802       RecordScrollBegin(ui::ScrollInputType::kWheel,
803                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
804       .Times(1);
805 
806   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
807   gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
808   EXPECT_EQ(InputHandlerProxy::DID_HANDLE,
809             HandleInputEventAndFlushEventQueue(mock_input_handler_,
810                                                input_handler_.get(), gesture_));
811   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
812   EXPECT_EQ(input_handler_->currently_active_gesture_device(),
813             WebGestureDevice::kTouchpad);
814 
815   VERIFY_AND_RESET_MOCKS();
816 
817   // Mousewheel GSE is then fired and the mousewheel scroll ends.
818   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(ui::ScrollInputType::kWheel))
819       .Times(1);
820   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
821 
822   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
823   gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
824   EXPECT_EQ(InputHandlerProxy::DID_HANDLE,
825             HandleInputEventAndFlushEventQueue(mock_input_handler_,
826                                                input_handler_.get(), gesture_));
827 
828   VERIFY_AND_RESET_MOCKS();
829 
830   // Mouse up gets ignored as the scrollbar scroll already ended before the
831   // mousewheel tick took place.
832   EXPECT_CALL(mock_input_handler_,
833               RecordScrollEnd(ui::ScrollInputType::kScrollbar))
834       .Times(1);
835   mouse_event.SetType(WebInputEvent::Type::kMouseUp);
836   cc::InputHandlerPointerResult pointer_up_result;
837   pointer_up_result.type = cc::PointerResultType::kScrollbarScroll;
838   EXPECT_CALL(mock_input_handler_, MouseUp(_))
839       .WillOnce(testing::Return(pointer_up_result));
840   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
841             HandleInputEventAndFlushEventQueue(
842                 mock_input_handler_, input_handler_.get(), mouse_event));
843   VERIFY_AND_RESET_MOCKS();
844 }
845 
GestureScrollStarted()846 void InputHandlerProxyTest::GestureScrollStarted() {
847   // We shouldn't send any events to the widget for this gesture.
848   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
849   VERIFY_AND_RESET_MOCKS();
850 
851   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
852       .WillOnce(testing::Return(kImplThreadScrollState));
853   EXPECT_CALL(
854       mock_input_handler_,
855       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
856       .Times(1);
857 
858   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
859   EXPECT_EQ(expected_disposition_,
860             HandleInputEventAndFlushEventQueue(mock_input_handler_,
861                                                input_handler_.get(), gesture_));
862 
863   // The event should not be marked as handled if scrolling is not possible.
864   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
865   VERIFY_AND_RESET_MOCKS();
866 
867   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
868   gesture_.data.scroll_update.delta_y =
869       -40;  // -Y means scroll down - i.e. in the +Y direction.
870   EXPECT_CALL(
871       mock_input_handler_,
872       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
873                    _))
874       .WillOnce(testing::Return(scroll_result_did_not_scroll_));
875   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
876     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
877         .WillOnce(testing::Return(false));
878   }
879   EXPECT_EQ(expected_disposition_,
880             HandleInputEventAndFlushEventQueue(mock_input_handler_,
881                                                input_handler_.get(), gesture_));
882 
883   // Mark the event as handled if scroll happens.
884   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
885   VERIFY_AND_RESET_MOCKS();
886 
887   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
888     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
889         .WillOnce(testing::Return(false));
890   }
891   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
892   gesture_.data.scroll_update.delta_y =
893       -40;  // -Y means scroll down - i.e. in the +Y direction.
894   EXPECT_CALL(
895       mock_input_handler_,
896       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
897                    _))
898       .WillOnce(testing::Return(scroll_result_did_scroll_));
899   EXPECT_EQ(expected_disposition_,
900             HandleInputEventAndFlushEventQueue(mock_input_handler_,
901                                                input_handler_.get(), gesture_));
902 
903   VERIFY_AND_RESET_MOCKS();
904 
905   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
906   gesture_.data.scroll_update.delta_y = 0;
907   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
908   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
909   EXPECT_EQ(expected_disposition_,
910             HandleInputEventAndFlushEventQueue(mock_input_handler_,
911                                                input_handler_.get(), gesture_));
912 
913   VERIFY_AND_RESET_MOCKS();
914 }
TEST_P(InputHandlerProxyTest,GestureScrollStarted)915 TEST_P(InputHandlerProxyTest, GestureScrollStarted) {
916   GestureScrollStarted();
917 }
918 
TEST_P(InputHandlerProxyTest,GestureScrollOnMainThread)919 TEST_P(InputHandlerProxyTest, GestureScrollOnMainThread) {
920   // We should send all events to the widget for this gesture.
921   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
922   VERIFY_AND_RESET_MOCKS();
923 
924   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
925       .WillOnce(testing::Return(kMainThreadScrollState));
926   EXPECT_CALL(
927       mock_input_handler_,
928       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
929       .Times(1);
930 
931   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
932   EXPECT_EQ(expected_disposition_,
933             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
934 
935   VERIFY_AND_RESET_MOCKS();
936 
937   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
938   gesture_.data.scroll_update.delta_y = 40;
939   EXPECT_EQ(expected_disposition_,
940             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
941 
942   VERIFY_AND_RESET_MOCKS();
943 
944   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
945   gesture_.data.scroll_update.delta_y = 0;
946   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
947   EXPECT_EQ(expected_disposition_,
948             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
949 
950   VERIFY_AND_RESET_MOCKS();
951 }
952 
TEST_P(InputHandlerProxyTest,GestureScrollIgnored)953 TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
954   // We shouldn't handle the GestureScrollBegin.
955   // Instead, we should get a DROP_EVENT result, indicating
956   // that we could determine that there's nothing that could scroll or otherwise
957   // react to this gesture sequence and thus we should drop the whole gesture
958   // sequence on the floor, except for the ScrollEnd.
959   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
960   VERIFY_AND_RESET_MOCKS();
961 
962   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
963       .WillOnce(testing::Return(kScrollIgnoredScrollState));
964   EXPECT_CALL(
965       mock_input_handler_,
966       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
967       .Times(1);
968 
969   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
970   EXPECT_EQ(expected_disposition_,
971             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
972 
973   VERIFY_AND_RESET_MOCKS();
974 
975   // GSB is dropped and not sent to the main thread, GSE shouldn't get sent to
976   // the main thread, either.
977   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
978   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
979   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
980   EXPECT_EQ(expected_disposition_,
981             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
982 
983   VERIFY_AND_RESET_MOCKS();
984 }
985 
TEST_P(InputHandlerProxyTest,GestureScrollByPage)986 TEST_P(InputHandlerProxyTest, GestureScrollByPage) {
987   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
988   VERIFY_AND_RESET_MOCKS();
989 
990   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
991       .WillOnce(testing::Return(kImplThreadScrollState));
992 
993   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
994   gesture_.data.scroll_begin.delta_hint_units =
995       ui::ScrollGranularity::kScrollByPage;
996   EXPECT_CALL(
997       mock_input_handler_,
998       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
999       .Times(1);
1000   EXPECT_EQ(expected_disposition_,
1001             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1002 
1003   VERIFY_AND_RESET_MOCKS();
1004 
1005   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1006     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1007         .WillOnce(testing::Return(false));
1008   }
1009   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
1010       .WillOnce(testing::Return(scroll_result_did_scroll_));
1011 
1012   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
1013   gesture_.data.scroll_update.delta_y = 1;
1014   gesture_.data.scroll_update.delta_units =
1015       ui::ScrollGranularity::kScrollByPage;
1016   EXPECT_EQ(expected_disposition_,
1017             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1018 
1019   VERIFY_AND_RESET_MOCKS();
1020 
1021   EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(1);
1022   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
1023   gesture_.data.scroll_update.delta_y = 0;
1024   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1025   EXPECT_EQ(expected_disposition_,
1026             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1027 
1028   VERIFY_AND_RESET_MOCKS();
1029 }
1030 
TEST_P(InputHandlerProxyTest,GestureScrollBeginThatTargetViewport)1031 TEST_P(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) {
1032   // We shouldn't send any events to the widget for this gesture.
1033   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1034   VERIFY_AND_RESET_MOCKS();
1035 
1036   EXPECT_CALL(mock_input_handler_, RootScrollBegin(_, _))
1037       .WillOnce(testing::Return(kImplThreadScrollState));
1038   EXPECT_CALL(
1039       mock_input_handler_,
1040       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1041       .Times(1);
1042 
1043   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1044   gesture_.data.scroll_begin.target_viewport = true;
1045   EXPECT_EQ(expected_disposition_,
1046             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1047 
1048   VERIFY_AND_RESET_MOCKS();
1049 }
1050 
FlingAndSnap()1051 void InputHandlerProxyTest::FlingAndSnap() {
1052   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1053   VERIFY_AND_RESET_MOCKS();
1054 
1055   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1056       .WillOnce(testing::Return(kImplThreadScrollState));
1057   EXPECT_CALL(
1058       mock_input_handler_,
1059       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1060       .Times(1);
1061 
1062   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1063   EXPECT_EQ(expected_disposition_,
1064             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1065 
1066   // The event should be dropped if InputHandler decides to snap.
1067   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1068   VERIFY_AND_RESET_MOCKS();
1069 
1070   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
1071   gesture_.data.scroll_update.delta_y =
1072       -40;  // -Y means scroll down - i.e. in the +Y direction.
1073   gesture_.data.scroll_update.inertial_phase =
1074       WebGestureEvent::InertialPhaseState::kMomentum;
1075   EXPECT_CALL(mock_input_handler_,
1076               GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _))
1077       .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)),
1078                       testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)),
1079                       testing::Return(true)));
1080   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
1081   EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
1082   EXPECT_EQ(expected_disposition_,
1083             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1084   VERIFY_AND_RESET_MOCKS();
1085 }
1086 
TEST_P(InputHandlerProxyTest,SnapFlingIgnoresFollowingGSUAndGSE)1087 TEST_P(InputHandlerProxyTest, SnapFlingIgnoresFollowingGSUAndGSE) {
1088   FlingAndSnap();
1089   // The next GestureScrollUpdate should also be ignored, and will not ask for
1090   // snap position.
1091   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1092 
1093   EXPECT_CALL(mock_input_handler_,
1094               GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _))
1095       .Times(0);
1096   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
1097   EXPECT_EQ(expected_disposition_,
1098             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1099                                                input_handler_.get(), gesture_));
1100   VERIFY_AND_RESET_MOCKS();
1101 
1102   // The GestureScrollEnd should also be ignored.
1103   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1104   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
1105   gesture_.data.scroll_end.inertial_phase =
1106       WebGestureEvent::InertialPhaseState::kMomentum;
1107   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0);
1108   EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0);
1109   EXPECT_EQ(expected_disposition_,
1110             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1111                                                input_handler_.get(), gesture_));
1112   VERIFY_AND_RESET_MOCKS();
1113 }
1114 
TEST_P(InputHandlerProxyTest,GesturePinch)1115 TEST_P(InputHandlerProxyTest, GesturePinch) {
1116   // We shouldn't send any events to the widget for this gesture.
1117   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1118   VERIFY_AND_RESET_MOCKS();
1119 
1120   gesture_.SetType(WebInputEvent::Type::kGesturePinchBegin);
1121   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1122   EXPECT_EQ(expected_disposition_,
1123             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1124                                                input_handler_.get(), gesture_));
1125 
1126   VERIFY_AND_RESET_MOCKS();
1127 
1128   gesture_.SetType(WebInputEvent::Type::kGesturePinchUpdate);
1129   gesture_.data.pinch_update.scale = 1.5;
1130   gesture_.SetPositionInWidget(gfx::PointF(7, 13));
1131   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
1132   EXPECT_EQ(expected_disposition_,
1133             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1134                                                input_handler_.get(), gesture_));
1135 
1136   VERIFY_AND_RESET_MOCKS();
1137 
1138   gesture_.SetType(WebInputEvent::Type::kGesturePinchUpdate);
1139   gesture_.data.pinch_update.scale = 0.5;
1140   gesture_.SetPositionInWidget(gfx::PointF(9, 6));
1141   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
1142   EXPECT_EQ(expected_disposition_,
1143             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1144                                                input_handler_.get(), gesture_));
1145 
1146   VERIFY_AND_RESET_MOCKS();
1147 
1148   gesture_.SetType(WebInputEvent::Type::kGesturePinchEnd);
1149   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(9, 6), true));
1150   EXPECT_EQ(expected_disposition_,
1151             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1152                                                input_handler_.get(), gesture_));
1153 
1154   VERIFY_AND_RESET_MOCKS();
1155 }
1156 
TEST_P(InputHandlerProxyTest,GesturePinchAfterScrollOnMainThread)1157 TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
1158   // This situation is no longer possible under scroll unification as all
1159   // scrolling now happens on the compositor thread. This test can be removed
1160   // when the feature ships.
1161   if (base::FeatureList::IsEnabled(features::kScrollUnification))
1162     return;
1163 
1164   // Scrolls will start by being sent to the main thread.
1165   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1166   VERIFY_AND_RESET_MOCKS();
1167 
1168   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1169       .WillOnce(testing::Return(kMainThreadScrollState));
1170   EXPECT_CALL(
1171       mock_input_handler_,
1172       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
1173       .Times(1);
1174 
1175   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1176   EXPECT_EQ(expected_disposition_,
1177             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1178                                                input_handler_.get(), gesture_));
1179 
1180   VERIFY_AND_RESET_MOCKS();
1181 
1182   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
1183   gesture_.data.scroll_update.delta_y = 40;
1184   EXPECT_EQ(expected_disposition_,
1185             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1186                                                input_handler_.get(), gesture_));
1187 
1188   // However, after the pinch gesture starts, they should go to the impl
1189   // thread.
1190   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1191   VERIFY_AND_RESET_MOCKS();
1192 
1193   gesture_.SetType(WebInputEvent::Type::kGesturePinchBegin);
1194   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
1195   EXPECT_EQ(expected_disposition_,
1196             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1197                                                input_handler_.get(), gesture_));
1198 
1199   VERIFY_AND_RESET_MOCKS();
1200 
1201   gesture_.SetType(WebInputEvent::Type::kGesturePinchUpdate);
1202   gesture_.data.pinch_update.scale = 1.5;
1203   gesture_.SetPositionInWidget(gfx::PointF(7, 13));
1204   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
1205   EXPECT_EQ(expected_disposition_,
1206             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1207                                                input_handler_.get(), gesture_));
1208 
1209   VERIFY_AND_RESET_MOCKS();
1210 
1211   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1212     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1213         .WillOnce(testing::Return(false));
1214   }
1215   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
1216   gesture_.data.scroll_update.delta_y =
1217       -40;  // -Y means scroll down - i.e. in the +Y direction.
1218   EXPECT_CALL(
1219       mock_input_handler_,
1220       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1221                    _))
1222       .WillOnce(testing::Return(scroll_result_did_scroll_));
1223   EXPECT_EQ(expected_disposition_,
1224             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1225                                                input_handler_.get(), gesture_));
1226 
1227   VERIFY_AND_RESET_MOCKS();
1228 
1229   gesture_.SetType(WebInputEvent::Type::kGesturePinchUpdate);
1230   gesture_.data.pinch_update.scale = 0.5;
1231   gesture_.SetPositionInWidget(gfx::PointF(9, 6));
1232   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
1233   EXPECT_EQ(expected_disposition_,
1234             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1235                                                input_handler_.get(), gesture_));
1236 
1237   VERIFY_AND_RESET_MOCKS();
1238 
1239   gesture_.SetType(WebInputEvent::Type::kGesturePinchEnd);
1240   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(9, 6), true));
1241   EXPECT_EQ(expected_disposition_,
1242             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1243                                                input_handler_.get(), gesture_));
1244 
1245   // After the pinch gesture ends, they should go to back to the main
1246   // thread.
1247   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1248   VERIFY_AND_RESET_MOCKS();
1249 
1250   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
1251   gesture_.data.scroll_update.delta_y = 0;
1252   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1253   EXPECT_EQ(expected_disposition_,
1254             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1255 
1256   VERIFY_AND_RESET_MOCKS();
1257 }
1258 
ScrollHandlingSwitchedToMainThread()1259 void InputHandlerProxyTest::ScrollHandlingSwitchedToMainThread() {
1260   // We shouldn't send any events to the widget for this gesture.
1261   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1262   VERIFY_AND_RESET_MOCKS();
1263 
1264   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1265       .WillOnce(testing::Return(kImplThreadScrollState));
1266   EXPECT_CALL(
1267       mock_input_handler_,
1268       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1269       .Times(1);
1270 
1271   // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_.
1272   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1273   EXPECT_EQ(expected_disposition_,
1274             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1275                                                input_handler_.get(), gesture_));
1276   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1277 
1278   VERIFY_AND_RESET_MOCKS();
1279 
1280   gesture_.SetType(WebInputEvent::Type::kGestureScrollUpdate);
1281   gesture_.data.scroll_update.delta_y = -40;
1282   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1283       .WillOnce(testing::Return(false));
1284   EXPECT_CALL(
1285       mock_input_handler_,
1286       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
1287                    _))
1288       .WillOnce(testing::Return(scroll_result_did_scroll_));
1289   EXPECT_EQ(expected_disposition_,
1290             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1291                                                input_handler_.get(), gesture_));
1292   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1293   VERIFY_AND_RESET_MOCKS();
1294 
1295   // The scroll handling switches to the main thread, a GSB is sent to the main
1296   // thread to initiate the hit testing and compute the scroll chain.
1297   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1298   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
1299   EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1300       .WillOnce(testing::Return(true));
1301   EXPECT_CALL(mock_client_, GenerateScrollBeginAndSendToMainThread(_, _, _));
1302   EXPECT_EQ(expected_disposition_,
1303             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1304                                                input_handler_.get(), gesture_));
1305   EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1306 
1307   VERIFY_AND_RESET_MOCKS();
1308 
1309   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
1310   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1311   EXPECT_EQ(expected_disposition_,
1312             HandleInputEventAndFlushEventQueue(mock_input_handler_,
1313                                                input_handler_.get(), gesture_));
1314 
1315   VERIFY_AND_RESET_MOCKS();
1316 }
TEST_P(InputHandlerProxyTest,WheelScrollHandlingSwitchedToMainThread)1317 TEST_P(InputHandlerProxyTest, WheelScrollHandlingSwitchedToMainThread) {
1318   // This situation is no longer possible under scroll unification as all
1319   // scrolling now happens on the compositor thread. This test can be removed
1320   // when the feature ships.
1321   if (base::FeatureList::IsEnabled(features::kScrollUnification))
1322     return;
1323 
1324   gesture_.SetSourceDevice(WebGestureDevice::kTouchpad);
1325   ScrollHandlingSwitchedToMainThread();
1326 }
TEST_P(InputHandlerProxyTest,TouchScrollHandlingSwitchedToMainThread)1327 TEST_P(InputHandlerProxyTest, TouchScrollHandlingSwitchedToMainThread) {
1328   // This situation is no longer possible under scroll unification as all
1329   // scrolling now happens on the compositor thread. This test can be removed
1330   // when the feature ships.
1331   if (base::FeatureList::IsEnabled(features::kScrollUnification))
1332     return;
1333 
1334   gesture_.SetSourceDevice(WebGestureDevice::kTouchscreen);
1335   ScrollHandlingSwitchedToMainThread();
1336 }
1337 
TEST_P(InputHandlerProxyTest,GestureScrollOnImplThreadFlagClearedAfterScrollEnd)1338 TEST_P(InputHandlerProxyTest,
1339        GestureScrollOnImplThreadFlagClearedAfterScrollEnd) {
1340   // We shouldn't send any events to the widget for this gesture.
1341   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1342   VERIFY_AND_RESET_MOCKS();
1343 
1344   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1345       .WillOnce(testing::Return(kImplThreadScrollState));
1346   EXPECT_CALL(
1347       mock_input_handler_,
1348       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1349       .Times(1);
1350 
1351   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1352   EXPECT_EQ(expected_disposition_,
1353             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1354 
1355   // After sending a GestureScrollBegin, the member variable
1356   // |gesture_scroll_on_impl_thread_| should be true.
1357   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1358 
1359   VERIFY_AND_RESET_MOCKS();
1360 
1361   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
1362   gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd);
1363   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1364   EXPECT_EQ(expected_disposition_,
1365             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1366 
1367   // |gesture_scroll_on_impl_thread_| should be false once a GestureScrollEnd
1368   // gets handled.
1369   EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1370 
1371   VERIFY_AND_RESET_MOCKS();
1372 }
1373 
TEST_P(InputHandlerProxyTest,BeginScrollWhenGestureScrollOnImplThreadFlagIsSet)1374 TEST_P(InputHandlerProxyTest,
1375        BeginScrollWhenGestureScrollOnImplThreadFlagIsSet) {
1376   // We shouldn't send any events to the widget for this gesture.
1377   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1378   VERIFY_AND_RESET_MOCKS();
1379 
1380   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1381       .WillOnce(testing::Return(kImplThreadScrollState));
1382   EXPECT_CALL(
1383       mock_input_handler_,
1384       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
1385       .Times(1);
1386 
1387   gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin);
1388   EXPECT_EQ(expected_disposition_,
1389             HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_));
1390 
1391   // After sending a GestureScrollBegin, the member variable
1392   // |gesture_scroll_on_impl_thread_| should be true.
1393   EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1394 
1395   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1396   VERIFY_AND_RESET_MOCKS();
1397 }
1398 
TEST_P(InputHandlerProxyTest,HitTestTouchEventNonNullTouchAction)1399 TEST_P(InputHandlerProxyTest, HitTestTouchEventNonNullTouchAction) {
1400   // One of the touch points is on a touch-region. So the event should be sent
1401   // to the main thread.
1402   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1403   VERIFY_AND_RESET_MOCKS();
1404 
1405   EXPECT_CALL(mock_input_handler_,
1406               EventListenerTypeForTouchStartOrMoveAt(
1407                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1408       .WillOnce(testing::Invoke([](const gfx::Point&,
1409                                    cc::TouchAction* touch_action) {
1410         *touch_action = cc::TouchAction::kMax;
1411         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1412       }));
1413 
1414   EXPECT_CALL(mock_input_handler_,
1415               EventListenerTypeForTouchStartOrMoveAt(
1416                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1417       .WillOnce(
1418           testing::Invoke([](const gfx::Point&, cc::TouchAction* touch_action) {
1419             *touch_action = cc::TouchAction::kPanUp;
1420             return cc::InputHandler::TouchStartOrMoveEventListenerType::
1421                 HANDLER_ON_SCROLLING_LAYER;
1422           }));
1423   // Since the second touch point hits a touch-region, there should be no
1424   // hit-testing for the third touch point.
1425 
1426   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1427                       WebInputEvent::kNoModifiers,
1428                       WebInputEvent::GetStaticTimeStampForTests());
1429 
1430   touch.touches_length = 3;
1431   touch.touch_start_or_first_touch_move = true;
1432   touch.touches[0] =
1433       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1434   touch.touches[1] =
1435       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1436   touch.touches[2] =
1437       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
1438 
1439   bool is_touching_scrolling_layer;
1440   cc::TouchAction allowed_touch_action = cc::TouchAction::kAuto;
1441   EXPECT_EQ(expected_disposition_,
1442             input_handler_->HitTestTouchEventForTest(
1443                 touch, &is_touching_scrolling_layer, &allowed_touch_action));
1444   EXPECT_TRUE(is_touching_scrolling_layer);
1445   EXPECT_EQ(allowed_touch_action, cc::TouchAction::kPanUp);
1446   VERIFY_AND_RESET_MOCKS();
1447 }
1448 
1449 // Tests that multiple mousedown(s) on scrollbar are handled gracefully and
1450 // don't fail any DCHECK(s).
TEST_F(InputHandlerProxyEventQueueTest,NestedGestureBasedScrollsSameSourceDevice)1451 TEST_F(InputHandlerProxyEventQueueTest,
1452        NestedGestureBasedScrollsSameSourceDevice) {
1453   // Start with mousedown. Expect CompositorThreadEventQueue to contain [GSB,
1454   // GSU].
1455   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput());
1456   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1457       .Times(3)
1458       .WillRepeatedly(testing::Return(cc::ElementId()));
1459 
1460   cc::InputHandlerPointerResult pointer_down_result;
1461   pointer_down_result.type = cc::PointerResultType::kScrollbarScroll;
1462   pointer_down_result.scroll_offset = gfx::ScrollOffset(0, 1);
1463   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
1464       .WillOnce(testing::Return(pointer_down_result));
1465 
1466   HandleMouseEvent(WebInputEvent::Type::kMouseDown);
1467   EXPECT_EQ(2ul, event_queue().size());
1468   EXPECT_EQ(event_queue()[0]->event().GetType(),
1469             WebInputEvent::Type::kGestureScrollBegin);
1470   EXPECT_EQ(event_queue()[1]->event().GetType(),
1471             WebInputEvent::Type::kGestureScrollUpdate);
1472 
1473   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1474       .WillOnce(Return(kImplThreadScrollState));
1475   EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(1);
1476   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1477     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1478         .WillOnce(Return(false));
1479   }
1480   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
1481 
1482   DeliverInputForBeginFrame();
1483   Mock::VerifyAndClearExpectations(&mock_input_handler_);
1484 
1485   // A mouseup adds a GSE to the CompositorThreadEventQueue.
1486   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput());
1487   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1488       .Times(1)
1489       .WillOnce(testing::Return(cc::ElementId()));
1490   cc::InputHandlerPointerResult pointer_up_result;
1491   pointer_up_result.type = cc::PointerResultType::kScrollbarScroll;
1492   EXPECT_CALL(mock_input_handler_, MouseUp(_))
1493       .WillOnce(testing::Return(pointer_up_result));
1494   HandleMouseEvent(WebInputEvent::Type::kMouseUp);
1495   Mock::VerifyAndClearExpectations(&mock_input_handler_);
1496 
1497   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1498       .Times(1)
1499       .WillOnce(testing::Return(cc::ElementId()));
1500   EXPECT_EQ(1ul, event_queue().size());
1501   EXPECT_EQ(event_queue()[0]->event().GetType(),
1502             WebInputEvent::Type::kGestureScrollEnd);
1503 
1504   // Called when a mousedown is being handled as it tries to end the ongoing
1505   // scroll.
1506   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1507   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
1508 
1509   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
1510       .WillOnce(testing::Return(pointer_down_result));
1511   // A mousedown occurs on the scrollbar *before* the GSE is dispatched.
1512   HandleMouseEvent(WebInputEvent::Type::kMouseDown);
1513   Mock::VerifyAndClearExpectations(&mock_input_handler_);
1514 
1515   EXPECT_EQ(3ul, event_queue().size());
1516   EXPECT_EQ(event_queue()[1]->event().GetType(),
1517             WebInputEvent::Type::kGestureScrollBegin);
1518   EXPECT_EQ(event_queue()[2]->event().GetType(),
1519             WebInputEvent::Type::kGestureScrollUpdate);
1520 
1521   // Called when the GSE is being handled. (Note that ScrollEnd isn't called
1522   // when the GSE is being handled as the GSE gets dropped in
1523   // HandleGestureScrollEnd because handling_gesture_on_impl_thread_ is false)
1524   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1525   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1526       .WillOnce(Return(kImplThreadScrollState));
1527   EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(1);
1528   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1529     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1530         .WillOnce(Return(false));
1531   }
1532   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
1533   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1534       .Times(3)
1535       .WillRepeatedly(testing::Return(cc::ElementId()));
1536 
1537   DeliverInputForBeginFrame();
1538   Mock::VerifyAndClearExpectations(&mock_input_handler_);
1539 
1540   // Finally, a mouseup ends the scroll.
1541   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput());
1542   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1543       .Times(2)
1544       .WillRepeatedly(testing::Return(cc::ElementId()));
1545   EXPECT_CALL(mock_input_handler_, MouseUp(_))
1546       .WillOnce(testing::Return(pointer_up_result));
1547   HandleMouseEvent(WebInputEvent::Type::kMouseUp);
1548 
1549   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
1550   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(1);
1551 
1552   DeliverInputForBeginFrame();
1553   Mock::VerifyAndClearExpectations(&mock_input_handler_);
1554 }
1555 
1556 // Tests that the allowed touch action is correctly set when a touch is made
1557 // non-blocking due to an ongoing fling. https://crbug.com/1048098.
TEST_F(InputHandlerProxyEventQueueTest,AckTouchActionNonBlockingForFling)1558 TEST_F(InputHandlerProxyEventQueueTest, AckTouchActionNonBlockingForFling) {
1559   // Simulate starting a compositor scroll and then flinging. This is setup for
1560   // the real checks below.
1561   {
1562     float delta = 10;
1563 
1564     // ScrollBegin
1565     {
1566       EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
1567           .WillOnce(Return(kImplThreadScrollState));
1568       EXPECT_CALL(
1569           mock_input_handler_,
1570           RecordScrollBegin(_, ScrollBeginThreadState::kScrollingOnCompositor))
1571           .Times(1);
1572       EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1573           .Times(1)
1574           .WillOnce(testing::Return(cc::ElementId()));
1575 
1576       HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin, delta);
1577       Mock::VerifyAndClearExpectations(&mock_input_handler_);
1578     }
1579 
1580     // ScrollUpdate
1581     {
1582       EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1583       EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1584           .Times(1)
1585           .WillOnce(testing::Return(cc::ElementId()));
1586       if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1587         EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1588             .WillOnce(Return(false));
1589       }
1590       EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
1591 
1592       HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, delta);
1593       DeliverInputForBeginFrame();
1594       Mock::VerifyAndClearExpectations(&mock_input_handler_);
1595     }
1596 
1597     // Start a fling - ScrollUpdate with momentum
1598     {
1599       cc::InputHandlerScrollResult scroll_result_did_scroll;
1600       scroll_result_did_scroll.did_scroll = true;
1601       EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
1602           .WillOnce(Return(scroll_result_did_scroll));
1603       EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
1604       EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
1605           .Times(2)
1606           .WillRepeatedly(testing::Return(cc::ElementId()));
1607       if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
1608         EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
1609             .WillOnce(Return(false));
1610       }
1611       EXPECT_CALL(mock_input_handler_,
1612                   GetSnapFlingInfoAndSetAnimatingSnapTarget(_, _, _))
1613           .WillOnce(Return(false));
1614 
1615       auto gsu_fling = CreateGestureScrollPinch(
1616           WebInputEvent::Type::kGestureScrollUpdate,
1617           WebGestureDevice::kTouchscreen, NowTimestampForEvents(), delta,
1618           /*x=*/0, /*y=*/0);
1619       static_cast<WebGestureEvent*>(gsu_fling.get())
1620           ->data.scroll_update.inertial_phase =
1621           WebGestureEvent::InertialPhaseState::kMomentum;
1622       InjectInputEvent(std::move(gsu_fling));
1623       DeliverInputForBeginFrame();
1624     }
1625   }
1626 
1627   // We're now in an active gesture fling. Simulate the user touching down on
1628   // the screen. If this touch hits a blocking region (e.g. touch-action or a
1629   // non-passive touchstart listener), we won't actually treat it as blocking;
1630   // because of the ongoing fling it will be treated as non blocking. However,
1631   // we also have to ensure that the allowed_touch_action reported is also kAuto
1632   // so that the browser knows that it shouldn't wait for an ACK with an allowed
1633   // touch-action before dispatching more scrolls.
1634   {
1635     // Simulate hitting a blocking region on the scrolling layer, as if there
1636     // was a non-passive touchstart handler.
1637     EXPECT_CALL(mock_input_handler_,
1638                 EventListenerTypeForTouchStartOrMoveAt(_, _))
1639         .WillOnce(DoAll(SetArgPointee<1>(TouchAction::kNone),
1640                         Return(InputHandler::TouchStartOrMoveEventListenerType::
1641                                    HANDLER_ON_SCROLLING_LAYER)));
1642 
1643     std::unique_ptr<WebTouchEvent> touch_start =
1644         std::make_unique<WebTouchEvent>(
1645             WebInputEvent::Type::kTouchStart, WebInputEvent::kNoModifiers,
1646             WebInputEvent::GetStaticTimeStampForTests());
1647     touch_start->touches_length = 1;
1648     touch_start->touch_start_or_first_touch_move = true;
1649     touch_start->touches[0] =
1650         CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1651 
1652     // This is the call this test is checking: we expect that the client will
1653     // report the touch as non-blocking and also that the allowed touch action
1654     // matches the non blocking expectation (i.e. all touches are allowed).
1655     EXPECT_CALL(
1656         mock_client_,
1657         SetAllowedTouchAction(
1658             TouchAction::kAuto, touch_start->unique_touch_event_id,
1659             InputHandlerProxy::DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING))
1660         .WillOnce(Return());
1661 
1662     InjectInputEvent(std::move(touch_start));
1663   }
1664 }
1665 
TEST_P(InputHandlerProxyTest,HitTestTouchEventNullTouchAction)1666 TEST_P(InputHandlerProxyTest, HitTestTouchEventNullTouchAction) {
1667   // One of the touch points is on a touch-region. So the event should be sent
1668   // to the main thread.
1669   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1670   VERIFY_AND_RESET_MOCKS();
1671 
1672   EXPECT_CALL(mock_input_handler_,
1673               EventListenerTypeForTouchStartOrMoveAt(
1674                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1675       .WillOnce(testing::Return(
1676           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
1677 
1678   EXPECT_CALL(mock_input_handler_,
1679               EventListenerTypeForTouchStartOrMoveAt(
1680                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1681       .WillOnce(
1682           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
1683                               HANDLER_ON_SCROLLING_LAYER));
1684   // Since the second touch point hits a touch-region, there should be no
1685   // hit-testing for the third touch point.
1686 
1687   WebTouchEvent touch(WebInputEvent::Type::kTouchMove,
1688                       WebInputEvent::kNoModifiers,
1689                       WebInputEvent::GetStaticTimeStampForTests());
1690 
1691   touch.touches_length = 3;
1692   touch.touches[0] =
1693       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1694   touch.touches[1] =
1695       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1696   touch.touches[2] =
1697       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
1698 
1699   bool is_touching_scrolling_layer;
1700   cc::TouchAction* allowed_touch_action = nullptr;
1701   EXPECT_EQ(expected_disposition_,
1702             input_handler_->HitTestTouchEventForTest(
1703                 touch, &is_touching_scrolling_layer, allowed_touch_action));
1704   EXPECT_TRUE(is_touching_scrolling_layer);
1705   EXPECT_TRUE(!allowed_touch_action);
1706   VERIFY_AND_RESET_MOCKS();
1707 }
1708 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestNegative)1709 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
1710   // None of the three touch points fall in the touch region. So the event
1711   // should be dropped.
1712   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1713   VERIFY_AND_RESET_MOCKS();
1714 
1715   EXPECT_CALL(
1716       mock_input_handler_,
1717       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1718       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1719   EXPECT_CALL(
1720       mock_input_handler_,
1721       GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
1722       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1723   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1724       .Times(2)
1725       .WillRepeatedly(testing::Invoke([](const gfx::Point&,
1726                                          cc::TouchAction* touch_action) {
1727         *touch_action = cc::TouchAction::kPanUp;
1728         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1729       }));
1730   EXPECT_CALL(mock_client_,
1731               SetAllowedTouchAction(cc::TouchAction::kPanUp, 1,
1732                                     InputHandlerProxy::DROP_EVENT))
1733       .WillOnce(testing::Return());
1734 
1735   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1736                       WebInputEvent::kNoModifiers,
1737                       WebInputEvent::GetStaticTimeStampForTests());
1738 
1739   touch.unique_touch_event_id = 1;
1740   touch.touches_length = 3;
1741   touch.touch_start_or_first_touch_move = true;
1742   touch.touches[0] =
1743       CreateWebTouchPoint(WebTouchPoint::State::kStateStationary, 0, 0);
1744   touch.touches[1] =
1745       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1746   touch.touches[2] =
1747       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
1748   EXPECT_EQ(expected_disposition_,
1749             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1750 
1751   VERIFY_AND_RESET_MOCKS();
1752 }
1753 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestPositive)1754 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
1755   // One of the touch points is on a touch-region. So the event should be sent
1756   // to the main thread.
1757   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1758   VERIFY_AND_RESET_MOCKS();
1759 
1760   EXPECT_CALL(mock_input_handler_,
1761               EventListenerTypeForTouchStartOrMoveAt(
1762                   testing::Property(&gfx::Point::x, testing::Eq(0)), _))
1763       .WillOnce(testing::Invoke([](const gfx::Point&,
1764                                    cc::TouchAction* touch_action) {
1765         *touch_action = cc::TouchAction::kAuto;
1766         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1767       }));
1768   EXPECT_CALL(mock_input_handler_,
1769               EventListenerTypeForTouchStartOrMoveAt(
1770                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
1771       .WillOnce(
1772           testing::Invoke([](const gfx::Point&, cc::TouchAction* touch_action) {
1773             *touch_action = cc::TouchAction::kPanY;
1774             return cc::InputHandler::TouchStartOrMoveEventListenerType::
1775                 HANDLER_ON_SCROLLING_LAYER;
1776           }));
1777   EXPECT_CALL(mock_client_, SetAllowedTouchAction(cc::TouchAction::kPanY, 1,
1778                                                   expected_disposition_))
1779       .WillOnce(testing::Return());
1780   // Since the second touch point hits a touch-region, there should be no
1781   // hit-testing for the third touch point.
1782 
1783   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1784                       WebInputEvent::kNoModifiers,
1785                       WebInputEvent::GetStaticTimeStampForTests());
1786 
1787   touch.unique_touch_event_id = 1;
1788   touch.touches_length = 3;
1789   touch.touch_start_or_first_touch_move = true;
1790   touch.touches[0] =
1791       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1792   touch.touches[1] =
1793       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1794   touch.touches[2] =
1795       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
1796   EXPECT_EQ(expected_disposition_,
1797             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1798 
1799   VERIFY_AND_RESET_MOCKS();
1800 }
1801 
TEST_P(InputHandlerProxyTest,MultiTouchPointHitTestPassivePositive)1802 TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPassivePositive) {
1803   // One of the touch points is not on a touch-region. So the event should be
1804   // sent to the impl thread.
1805   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1806   VERIFY_AND_RESET_MOCKS();
1807 
1808   EXPECT_CALL(
1809       mock_input_handler_,
1810       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1811       .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
1812   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1813       .Times(3)
1814       .WillOnce(testing::Invoke([](const gfx::Point&,
1815                                    cc::TouchAction* touch_action) {
1816         *touch_action = cc::TouchAction::kPanRight;
1817         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1818       }))
1819       .WillRepeatedly(testing::Invoke([](const gfx::Point&,
1820                                          cc::TouchAction* touch_action) {
1821         *touch_action = cc::TouchAction::kPanX;
1822         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1823       }));
1824   EXPECT_CALL(mock_client_,
1825               SetAllowedTouchAction(cc::TouchAction::kPanRight, 1,
1826                                     InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
1827       .WillOnce(testing::Return());
1828 
1829   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1830                       WebInputEvent::kNoModifiers,
1831                       WebInputEvent::GetStaticTimeStampForTests());
1832 
1833   touch.unique_touch_event_id = 1;
1834   touch.touches_length = 3;
1835   touch.touch_start_or_first_touch_move = true;
1836   touch.touches[0] =
1837       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1838   touch.touches[1] =
1839       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1840   touch.touches[2] =
1841       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
1842   EXPECT_EQ(expected_disposition_,
1843             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1844 
1845   VERIFY_AND_RESET_MOCKS();
1846 }
1847 
TEST_P(InputHandlerProxyTest,TouchStartPassiveAndTouchEndBlocking)1848 TEST_P(InputHandlerProxyTest, TouchStartPassiveAndTouchEndBlocking) {
1849   // The touch start is not in a touch-region but there is a touch end handler
1850   // so to maintain targeting we need to dispatch the touch start as
1851   // non-blocking but drop all touch moves.
1852   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
1853   VERIFY_AND_RESET_MOCKS();
1854 
1855   EXPECT_CALL(
1856       mock_input_handler_,
1857       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1858       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
1859   EXPECT_CALL(
1860       mock_input_handler_,
1861       GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
1862       .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
1863   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1864       .WillOnce(testing::Invoke([](const gfx::Point&,
1865                                    cc::TouchAction* touch_action) {
1866         *touch_action = cc::TouchAction::kNone;
1867         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
1868       }));
1869   EXPECT_CALL(mock_client_,
1870               SetAllowedTouchAction(cc::TouchAction::kNone, 1,
1871                                     InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
1872       .WillOnce(testing::Return());
1873 
1874   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1875                       WebInputEvent::kNoModifiers,
1876                       WebInputEvent::GetStaticTimeStampForTests());
1877   touch.unique_touch_event_id = 1;
1878   touch.touches_length = 1;
1879   touch.touches[0] =
1880       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1881   touch.touch_start_or_first_touch_move = true;
1882   EXPECT_EQ(expected_disposition_,
1883             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1884 
1885   touch.SetType(WebInputEvent::Type::kTouchMove);
1886   touch.touches_length = 1;
1887   touch.touch_start_or_first_touch_move = false;
1888   touch.touches[0] =
1889       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
1890   EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
1891             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1892   VERIFY_AND_RESET_MOCKS();
1893 }
1894 
TEST_P(InputHandlerProxyTest,TouchMoveBlockingAddedAfterPassiveTouchStart)1895 TEST_P(InputHandlerProxyTest, TouchMoveBlockingAddedAfterPassiveTouchStart) {
1896   // The touch start is not in a touch-region but there is a touch end handler
1897   // so to maintain targeting we need to dispatch the touch start as
1898   // non-blocking but drop all touch moves.
1899   VERIFY_AND_RESET_MOCKS();
1900 
1901   EXPECT_CALL(
1902       mock_input_handler_,
1903       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
1904       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
1905   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1906       .WillOnce(testing::Return(
1907           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
1908   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
1909       .WillOnce(testing::Return());
1910 
1911   cc::InputHandlerPointerResult pointer_down_result;
1912   pointer_down_result.type = cc::PointerResultType::kUnhandled;
1913   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
1914       .WillOnce(testing::Return(pointer_down_result));
1915 
1916   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
1917                       WebInputEvent::kNoModifiers,
1918                       WebInputEvent::GetStaticTimeStampForTests());
1919   touch.touches_length = 1;
1920   touch.touch_start_or_first_touch_move = true;
1921   touch.touches[0] =
1922       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
1923   EXPECT_EQ(InputHandlerProxy::DID_HANDLE_NON_BLOCKING,
1924             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1925 
1926   EXPECT_CALL(mock_input_handler_, EventListenerTypeForTouchStartOrMoveAt(_, _))
1927       .WillOnce(testing::Return(
1928           cc::InputHandler::TouchStartOrMoveEventListenerType::HANDLER));
1929   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
1930       .WillOnce(testing::Return());
1931 
1932   touch.SetType(WebInputEvent::Type::kTouchMove);
1933   touch.touches_length = 1;
1934   touch.touch_start_or_first_touch_move = true;
1935   touch.touches[0] =
1936       CreateWebTouchPoint(WebTouchPoint::State::kStateMoved, 10, 10);
1937   EXPECT_EQ(InputHandlerProxy::DID_HANDLE_NON_BLOCKING,
1938             HandleInputEventWithLatencyInfo(input_handler_.get(), touch));
1939   VERIFY_AND_RESET_MOCKS();
1940 }
1941 
1942 class UnifiedScrollingInputHandlerProxyTest : public testing::Test {
1943  public:
1944   using ElementId = cc::ElementId;
1945   using ElementIdType = cc::ElementIdType;
1946   using EventDisposition = InputHandlerProxy::EventDisposition;
1947   using EventDispositionCallback = InputHandlerProxy::EventDispositionCallback;
1948   using LatencyInfo = ui::LatencyInfo;
1949   using ScrollGranularity = ui::ScrollGranularity;
1950   using ScrollState = cc::ScrollState;
1951   using ReturnedDisposition = base::Optional<EventDisposition>;
1952 
UnifiedScrollingInputHandlerProxyTest()1953   UnifiedScrollingInputHandlerProxyTest()
1954       : input_handler_proxy_(mock_input_handler_, &mock_client_) {}
1955 
SetUp()1956   void SetUp() override {
1957     scoped_feature_list_.InitAndEnableFeature(features::kScrollUnification);
1958   }
1959 
ScrollBegin()1960   std::unique_ptr<WebCoalescedInputEvent> ScrollBegin() {
1961     auto gsb = std::make_unique<WebGestureEvent>(
1962         WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
1963         TimeForInputEvents(), WebGestureDevice::kTouchpad);
1964     gsb->data.scroll_begin.scrollable_area_element_id = 0;
1965     gsb->data.scroll_begin.main_thread_hit_tested = false;
1966     gsb->data.scroll_begin.delta_x_hint = 0;
1967     gsb->data.scroll_begin.delta_y_hint = 10;
1968     gsb->data.scroll_begin.pointer_count = 0;
1969 
1970     LatencyInfo unused;
1971     return std::make_unique<WebCoalescedInputEvent>(std::move(gsb), unused);
1972   }
1973 
ScrollUpdate()1974   std::unique_ptr<WebCoalescedInputEvent> ScrollUpdate() {
1975     auto gsu = std::make_unique<WebGestureEvent>(
1976         WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
1977         TimeForInputEvents(), WebGestureDevice::kTouchpad);
1978     gsu->data.scroll_update.delta_x = 0;
1979     gsu->data.scroll_update.delta_y = 10;
1980 
1981     LatencyInfo unused;
1982     return std::make_unique<WebCoalescedInputEvent>(std::move(gsu), unused);
1983   }
1984 
ScrollEnd()1985   std::unique_ptr<WebCoalescedInputEvent> ScrollEnd() {
1986     auto gse = std::make_unique<WebGestureEvent>(
1987         WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
1988         TimeForInputEvents(), WebGestureDevice::kTouchpad);
1989 
1990     LatencyInfo unused;
1991     return std::make_unique<WebCoalescedInputEvent>(std::move(gse), unused);
1992   }
1993 
DispatchEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event,ReturnedDisposition * out_disposition=nullptr)1994   void DispatchEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event,
1995                      ReturnedDisposition* out_disposition = nullptr) {
1996     input_handler_proxy_.HandleInputEventWithLatencyInfo(
1997         std::move(event), nullptr, BindEventHandledCallback(out_disposition));
1998   }
1999 
ContinueScrollBeginAfterMainThreadHitTest(std::unique_ptr<WebCoalescedInputEvent> event,cc::ElementIdType hit_test_result,ReturnedDisposition * out_disposition=nullptr)2000   void ContinueScrollBeginAfterMainThreadHitTest(
2001       std::unique_ptr<WebCoalescedInputEvent> event,
2002       cc::ElementIdType hit_test_result,
2003       ReturnedDisposition* out_disposition = nullptr) {
2004     input_handler_proxy_.ContinueScrollBeginAfterMainThreadHitTest(
2005         std::move(event), nullptr, BindEventHandledCallback(out_disposition),
2006         hit_test_result);
2007   }
2008 
MainThreadHitTestInProgress() const2009   bool MainThreadHitTestInProgress() const {
2010     return input_handler_proxy_.hit_testing_scroll_begin_on_main_thread_;
2011   }
2012 
BeginFrame()2013   void BeginFrame() {
2014     constexpr base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
2015     base::TimeTicks frame_time =
2016         TimeForInputEvents() +
2017         (next_begin_frame_number_ - viz::BeginFrameArgs::kStartingFrameNumber) *
2018             interval;
2019     input_handler_proxy_.DeliverInputForBeginFrame(viz::BeginFrameArgs::Create(
2020         BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, frame_time,
2021         frame_time + interval, interval, viz::BeginFrameArgs::NORMAL));
2022   }
2023 
DidScrollResult() const2024   cc::InputHandlerScrollResult DidScrollResult() const {
2025     cc::InputHandlerScrollResult result;
2026     result.did_scroll = true;
2027     return result;
2028   }
2029 
2030  protected:
2031   NiceMock<MockInputHandler> mock_input_handler_;
2032   NiceMock<MockInputHandlerProxyClient> mock_client_;
2033 
2034  private:
EventHandledCallback(ReturnedDisposition * out_disposition,EventDisposition event_disposition,std::unique_ptr<WebCoalescedInputEvent> input_event,std::unique_ptr<InputHandlerProxy::DidOverscrollParams> overscroll_params,const WebInputEventAttribution & attribution,std::unique_ptr<cc::EventMetrics> metrics)2035   void EventHandledCallback(
2036       ReturnedDisposition* out_disposition,
2037       EventDisposition event_disposition,
2038       std::unique_ptr<WebCoalescedInputEvent> input_event,
2039       std::unique_ptr<InputHandlerProxy::DidOverscrollParams> overscroll_params,
2040       const WebInputEventAttribution& attribution,
2041       std::unique_ptr<cc::EventMetrics> metrics) {
2042     if (out_disposition)
2043       *out_disposition = event_disposition;
2044   }
2045 
BindEventHandledCallback(ReturnedDisposition * out_disposition=nullptr)2046   EventDispositionCallback BindEventHandledCallback(
2047       ReturnedDisposition* out_disposition = nullptr) {
2048     return base::BindOnce(
2049         &UnifiedScrollingInputHandlerProxyTest::EventHandledCallback,
2050         weak_ptr_factory_.GetWeakPtr(), out_disposition);
2051   }
2052 
TimeForInputEvents() const2053   base::TimeTicks TimeForInputEvents() const {
2054     return WebInputEvent::GetStaticTimeStampForTests();
2055   }
2056 
2057   InputHandlerProxy input_handler_proxy_;
2058   base::test::ScopedFeatureList scoped_feature_list_;
2059   base::SimpleTestTickClock tick_clock_;
2060   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
2061   base::WeakPtrFactory<UnifiedScrollingInputHandlerProxyTest> weak_ptr_factory_{
2062       this};
2063 };
2064 
2065 // Test that when a main thread hit test is requested, the InputHandlerProxy
2066 // starts queueing incoming gesture event and the compositor queue is blocked
2067 // until the hit test is satisfied.
TEST_F(UnifiedScrollingInputHandlerProxyTest,MainThreadHitTestRequired)2068 TEST_F(UnifiedScrollingInputHandlerProxyTest, MainThreadHitTestRequired) {
2069   // The hit testing state shouldn't be entered until one is actually requested.
2070   EXPECT_FALSE(MainThreadHitTestInProgress());
2071 
2072   // Inject a GSB that returns RequiresMainThreadHitTest.
2073   {
2074     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2075         .WillOnce(Return(kRequiresMainThreadHitTestState));
2076 
2077     ReturnedDisposition disposition;
2078     DispatchEvent(ScrollBegin(), &disposition);
2079 
2080     EXPECT_TRUE(MainThreadHitTestInProgress());
2081     EXPECT_EQ(InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST, *disposition);
2082 
2083     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2084   }
2085 
2086   ReturnedDisposition gsu1_disposition;
2087   ReturnedDisposition gsu2_disposition;
2088 
2089   // Now inject a GSU. This should be queued.
2090   {
2091     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
2092 
2093     DispatchEvent(ScrollUpdate(), &gsu1_disposition);
2094     EXPECT_FALSE(gsu1_disposition);
2095 
2096     // Ensure the queue is blocked; a BeginFrame doesn't cause event dispatch.
2097     BeginFrame();
2098     EXPECT_FALSE(gsu1_disposition);
2099 
2100     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2101   }
2102 
2103   // Inject a second GSU; it should be coalesced and also queued.
2104   {
2105     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
2106 
2107     DispatchEvent(ScrollUpdate(), &gsu2_disposition);
2108     EXPECT_FALSE(gsu2_disposition);
2109 
2110     // Ensure the queue is blocked.
2111     BeginFrame();
2112     EXPECT_FALSE(gsu2_disposition);
2113 
2114     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2115   }
2116 
2117   EXPECT_TRUE(MainThreadHitTestInProgress());
2118 
2119   // The hit test reply arrives. Ensure we call ScrollBegin and unblock the
2120   // queue.
2121   {
2122     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2123         .WillOnce(Return(kImplThreadScrollState));
2124 
2125     // Additionally, the queue should be flushed by
2126     // ContinueScrollBeginAfterMainThreadHitTest so that the GSUs dispatched
2127     // earlier will now handled.
2128     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
2129         .WillOnce(Return(DidScrollResult()));
2130 
2131     // Ensure we don't spurriously call ScrollEnd (because we think we're
2132     // already in a scroll from the first GSB).
2133     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0);
2134 
2135     ReturnedDisposition disposition;
2136     const ElementIdType kHitTestResult = 12345;
2137     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(), kHitTestResult,
2138                                               &disposition);
2139 
2140     // The ScrollBegin should have been immediately re-injected and queue
2141     // flushed.
2142     EXPECT_FALSE(MainThreadHitTestInProgress());
2143     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2144     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gsu1_disposition);
2145     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gsu2_disposition);
2146 
2147     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2148   }
2149 
2150   // Injecting a new GSU should cause queueing and dispatching as usual.
2151   {
2152     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
2153         .WillOnce(Return(DidScrollResult()));
2154 
2155     ReturnedDisposition disposition;
2156     DispatchEvent(ScrollUpdate(), &disposition);
2157     EXPECT_FALSE(disposition);
2158 
2159     BeginFrame();
2160     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2161 
2162     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2163   }
2164 
2165   // Finish the scroll.
2166   {
2167     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(1);
2168     ReturnedDisposition disposition;
2169     DispatchEvent(ScrollEnd(), &disposition);
2170     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2171     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2172   }
2173 
2174   EXPECT_FALSE(MainThreadHitTestInProgress());
2175 }
2176 
2177 // Test to ensure that a main thread hit test sets the correct flags on the
2178 // re-injected GestureScrollBegin.
TEST_F(UnifiedScrollingInputHandlerProxyTest,MainThreadHitTestEvent)2179 TEST_F(UnifiedScrollingInputHandlerProxyTest, MainThreadHitTestEvent) {
2180   // Inject a GSB that returns RequiresMainThreadHitTest.
2181   {
2182     // Ensure that by default we don't set a target. The
2183     // |is_main_thread_hit_tested| property should default to false.
2184     EXPECT_CALL(
2185         mock_input_handler_,
2186         ScrollBegin(
2187             AllOf(Property(&ScrollState::target_element_id, Eq(ElementId())),
2188                   Property(&ScrollState::is_main_thread_hit_tested, Eq(false))),
2189             _))
2190         .WillOnce(Return(kRequiresMainThreadHitTestState));
2191     DispatchEvent(ScrollBegin());
2192     ASSERT_TRUE(MainThreadHitTestInProgress());
2193     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2194   }
2195 
2196   // The hit test reply arrives. Ensure we call ScrollBegin with the ElementId
2197   // from the hit test and the main_thread
2198   {
2199     const ElementId kHitTestResult(12345);
2200 
2201     EXPECT_CALL(
2202         mock_input_handler_,
2203         ScrollBegin(
2204             AllOf(Property(&ScrollState::target_element_id, Eq(kHitTestResult)),
2205                   Property(&ScrollState::is_main_thread_hit_tested, Eq(true))),
2206             _))
2207         .Times(1);
2208 
2209     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(),
2210                                               kHitTestResult.GetStableId());
2211     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2212   }
2213 }
2214 
2215 // Test to ensure that a main thread hit test counts the correct number of
2216 // scrolls for metrics.
TEST_F(UnifiedScrollingInputHandlerProxyTest,MainThreadHitTestMetrics)2217 TEST_F(UnifiedScrollingInputHandlerProxyTest, MainThreadHitTestMetrics) {
2218   // Inject a GSB that returns RequiresMainThreadHitTest followed by a GSU and
2219   // a GSE.
2220   {
2221     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2222         .WillOnce(Return(kRequiresMainThreadHitTestState))
2223         .WillOnce(Return(kImplThreadScrollState));
2224     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(1);
2225     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(1);
2226 
2227     // The record begin/end should be called exactly once.
2228     EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(1);
2229     EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2230 
2231     DispatchEvent(ScrollBegin());
2232     EXPECT_TRUE(MainThreadHitTestInProgress());
2233     DispatchEvent(ScrollUpdate());
2234     DispatchEvent(ScrollEnd());
2235 
2236     // Hit test reply.
2237     const ElementIdType kHitTestResult = 12345;
2238     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(), kHitTestResult);
2239     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2240   }
2241 
2242   // Ensure we don't record either a begin or an end if the hit test fails.
2243   // TODO(bokan): Though it looks odd, it appears that today we do record the
2244   // scrolling thread if the scroll is dropped. We should fix that but in the
2245   // mean-time we add a test for the unified path in this case.
2246   // https://crbug.com/1082601.
2247   {
2248     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2249         .WillOnce(Return(kRequiresMainThreadHitTestState));
2250     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
2251     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0);
2252 
2253     EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(1);
2254     EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2255 
2256     DispatchEvent(ScrollBegin());
2257     EXPECT_TRUE(MainThreadHitTestInProgress());
2258     DispatchEvent(ScrollUpdate());
2259     DispatchEvent(ScrollEnd());
2260 
2261     // Hit test reply failed.
2262     const ElementIdType kHitTestResult = 0;
2263     ASSERT_FALSE(ElementId::IsValid(kHitTestResult));
2264 
2265     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(), kHitTestResult);
2266     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2267   }
2268 }
2269 
2270 // Test the case where a main thread hit test is in progress on the main thread
2271 // and a GSE and new GSB arrive.
TEST_F(UnifiedScrollingInputHandlerProxyTest,ScrollEndAndBeginsDuringMainThreadHitTest)2272 TEST_F(UnifiedScrollingInputHandlerProxyTest,
2273        ScrollEndAndBeginsDuringMainThreadHitTest) {
2274   ReturnedDisposition gsb1_disposition;
2275   ReturnedDisposition gsu1_disposition;
2276   ReturnedDisposition gse1_disposition;
2277   ReturnedDisposition gsb2_disposition;
2278   ReturnedDisposition gsu2_disposition;
2279   ReturnedDisposition gse2_disposition;
2280 
2281   // Inject a GSB that returns RequiresMainThreadHitTest followed by a GSU and
2282   // GSE that get queued.
2283   {
2284     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2285         .WillOnce(Return(kRequiresMainThreadHitTestState));
2286     DispatchEvent(ScrollBegin(), &gsb1_disposition);
2287     ASSERT_TRUE(MainThreadHitTestInProgress());
2288     ASSERT_EQ(InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST,
2289               *gsb1_disposition);
2290 
2291     DispatchEvent(ScrollUpdate(), &gsu1_disposition);
2292     DispatchEvent(ScrollEnd(), &gse1_disposition);
2293 
2294     // The queue is blocked so none of the events should be processed.
2295     BeginFrame();
2296 
2297     ASSERT_FALSE(gsu1_disposition);
2298     ASSERT_FALSE(gse1_disposition);
2299   }
2300 
2301   // Inject another group of GSB, GSU, GSE. They should all be queued.
2302   {
2303     DispatchEvent(ScrollBegin(), &gsb2_disposition);
2304     DispatchEvent(ScrollUpdate(), &gsu2_disposition);
2305     DispatchEvent(ScrollEnd(), &gse2_disposition);
2306 
2307     // The queue is blocked so none of the events should be processed.
2308     BeginFrame();
2309 
2310     EXPECT_FALSE(gsb2_disposition);
2311     EXPECT_FALSE(gsu2_disposition);
2312     EXPECT_FALSE(gse2_disposition);
2313   }
2314 
2315   ASSERT_TRUE(MainThreadHitTestInProgress());
2316 
2317   // The hit test reply arrives. Ensure we call ScrollBegin and unblock the
2318   // queue.
2319   {
2320     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2321         .Times(2)
2322         .WillRepeatedly(Return(kImplThreadScrollState));
2323     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
2324         .Times(2)
2325         .WillRepeatedly(Return(DidScrollResult()));
2326     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(2);
2327 
2328     ReturnedDisposition disposition;
2329     const ElementIdType kHitTestResult = 12345;
2330     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(), kHitTestResult,
2331                                               &disposition);
2332 
2333     // The ScrollBegin should have been immediately re-injected and queue
2334     // flushed.
2335     EXPECT_FALSE(MainThreadHitTestInProgress());
2336     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2337     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gsu1_disposition);
2338     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gse1_disposition);
2339 
2340     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gsb2_disposition);
2341     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gsu2_disposition);
2342     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *gse2_disposition);
2343 
2344     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2345   }
2346 }
2347 
2348 // Test the case where a main thread hit test returns a null element_id. In
2349 // this case we should reset the state and unblock the queue.
TEST_F(UnifiedScrollingInputHandlerProxyTest,MainThreadHitTestFailed)2350 TEST_F(UnifiedScrollingInputHandlerProxyTest, MainThreadHitTestFailed) {
2351   ReturnedDisposition gsu1_disposition;
2352 
2353   // Inject a GSB that returns RequiresMainThreadHitTest.
2354   {
2355     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2356         .WillOnce(Return(kRequiresMainThreadHitTestState));
2357     DispatchEvent(ScrollBegin());
2358     DispatchEvent(ScrollUpdate(), &gsu1_disposition);
2359     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2360   }
2361 
2362   // The hit test reply arrives with an invalid ElementId. We shouldn't call
2363   // ScrollBegin nor ScrollUpdate. Both should be dropped without reaching the
2364   // input handler.
2365   {
2366     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)).Times(0);
2367     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
2368     EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0);
2369 
2370     const ElementIdType kHitTestResult = 0;
2371     ASSERT_FALSE(ElementId::IsValid(kHitTestResult));
2372 
2373     ReturnedDisposition gsb_disposition;
2374     ContinueScrollBeginAfterMainThreadHitTest(ScrollBegin(), kHitTestResult,
2375                                               &gsb_disposition);
2376 
2377     EXPECT_EQ(InputHandlerProxy::DROP_EVENT, *gsb_disposition);
2378     EXPECT_EQ(InputHandlerProxy::DROP_EVENT, *gsu1_disposition);
2379     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2380   }
2381 
2382   // Send a new GSU, ensure it's dropped without queueing since there's no
2383   // scroll in progress.
2384   {
2385     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0);
2386 
2387     ReturnedDisposition disposition;
2388     DispatchEvent(ScrollUpdate(), &disposition);
2389     EXPECT_EQ(InputHandlerProxy::DROP_EVENT, *disposition);
2390     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2391   }
2392 
2393   // Ensure there's no left-over bad state by sending a new GSB+GSU which
2394   // should be handled by the input handler immediately. A following GSU should
2395   // be queued and dispatched at BeginFrame.
2396   {
2397     EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2398         .WillOnce(Return(kImplThreadScrollState));
2399     EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
2400         .WillOnce(Return(DidScrollResult()))
2401         .WillOnce(Return(DidScrollResult()));
2402 
2403     // Note: The first GSU after a GSB is dispatched immediately without
2404     // queueing.
2405     ReturnedDisposition disposition;
2406     DispatchEvent(ScrollBegin(), &disposition);
2407     DispatchEvent(ScrollUpdate());
2408 
2409     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2410     disposition = base::nullopt;
2411 
2412     DispatchEvent(ScrollUpdate(), &disposition);
2413     EXPECT_FALSE(disposition);
2414 
2415     BeginFrame();
2416     EXPECT_EQ(InputHandlerProxy::DID_HANDLE, *disposition);
2417     Mock::VerifyAndClearExpectations(&mock_input_handler_);
2418   }
2419 }
2420 
TEST(SynchronousInputHandlerProxyTest,StartupShutdown)2421 TEST(SynchronousInputHandlerProxyTest, StartupShutdown) {
2422   testing::StrictMock<MockInputHandler> mock_input_handler;
2423   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
2424   testing::StrictMock<MockSynchronousInputHandler>
2425       mock_synchronous_input_handler;
2426   InputHandlerProxy proxy(mock_input_handler, &mock_client);
2427 
2428   // When adding a SynchronousInputHandler, immediately request an
2429   // UpdateRootLayerStateForSynchronousInputHandler() call.
2430   EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
2431       .Times(1);
2432   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
2433 
2434   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
2435   testing::Mock::VerifyAndClearExpectations(&mock_client);
2436   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
2437 
2438   EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
2439       .Times(0);
2440   proxy.SetSynchronousInputHandler(nullptr);
2441 
2442   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
2443   testing::Mock::VerifyAndClearExpectations(&mock_client);
2444   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
2445 }
2446 
TEST(SynchronousInputHandlerProxyTest,UpdateRootLayerState)2447 TEST(SynchronousInputHandlerProxyTest, UpdateRootLayerState) {
2448   testing::NiceMock<MockInputHandler> mock_input_handler;
2449   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
2450   testing::StrictMock<MockSynchronousInputHandler>
2451       mock_synchronous_input_handler;
2452   InputHandlerProxy proxy(mock_input_handler, &mock_client);
2453 
2454   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
2455 
2456   // When adding a SynchronousInputHandler, immediately request an
2457   // UpdateRootLayerStateForSynchronousInputHandler() call.
2458   EXPECT_CALL(
2459       mock_synchronous_input_handler,
2460       UpdateRootLayerState(gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4),
2461                            gfx::SizeF(5, 6), 7, 8, 9))
2462       .Times(1);
2463   proxy.UpdateRootLayerStateForSynchronousInputHandler(
2464       gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4), gfx::SizeF(5, 6), 7, 8,
2465       9);
2466 
2467   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
2468   testing::Mock::VerifyAndClearExpectations(&mock_client);
2469   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
2470 }
2471 
TEST(SynchronousInputHandlerProxyTest,SetOffset)2472 TEST(SynchronousInputHandlerProxyTest, SetOffset) {
2473   testing::NiceMock<MockInputHandler> mock_input_handler;
2474   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
2475   testing::StrictMock<MockSynchronousInputHandler>
2476       mock_synchronous_input_handler;
2477   InputHandlerProxy proxy(mock_input_handler, &mock_client);
2478 
2479   proxy.SetSynchronousInputHandler(&mock_synchronous_input_handler);
2480 
2481   EXPECT_CALL(mock_input_handler, SetSynchronousInputHandlerRootScrollOffset(
2482                                       gfx::ScrollOffset(5, 6)));
2483   proxy.SynchronouslySetRootScrollOffset(gfx::ScrollOffset(5, 6));
2484 
2485   testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
2486   testing::Mock::VerifyAndClearExpectations(&mock_client);
2487   testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
2488 }
2489 
TEST_F(InputHandlerProxyEventQueueTest,MouseEventOnScrollbarInitiatesGestureScroll)2490 TEST_F(InputHandlerProxyEventQueueTest,
2491        MouseEventOnScrollbarInitiatesGestureScroll) {
2492   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2493   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2494       .Times(2)
2495       .WillRepeatedly(testing::Return(cc::ElementId()));
2496 
2497   // Test mousedown on the scrollbar. Expect to get GSB and GSU.
2498   cc::InputHandlerPointerResult pointer_down_result;
2499   pointer_down_result.type = cc::PointerResultType::kScrollbarScroll;
2500   pointer_down_result.scroll_offset = gfx::ScrollOffset(0, 1);
2501 
2502   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
2503       .WillOnce(testing::Return(pointer_down_result));
2504   HandleMouseEvent(WebInputEvent::Type::kMouseDown);
2505   EXPECT_EQ(2ul, event_queue().size());
2506   EXPECT_EQ(event_queue()[0]->event().GetType(),
2507             WebInputEvent::Type::kGestureScrollBegin);
2508   EXPECT_EQ(event_queue()[1]->event().GetType(),
2509             WebInputEvent::Type::kGestureScrollUpdate);
2510   cc::InputHandlerPointerResult pointer_up_result;
2511   pointer_up_result.type = cc::PointerResultType::kScrollbarScroll;
2512   EXPECT_CALL(mock_input_handler_, MouseUp(_))
2513       .WillOnce(testing::Return(pointer_up_result));
2514   // Test mouseup on the scrollbar. Expect to get GSE.
2515   HandleMouseEvent(WebInputEvent::Type::kMouseUp);
2516   EXPECT_EQ(3ul, event_queue().size());
2517   EXPECT_EQ(event_queue()[2]->event().GetType(),
2518             WebInputEvent::Type::kGestureScrollEnd);
2519 }
2520 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedGestureScroll)2521 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScroll) {
2522   // Handle scroll on compositor.
2523   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2524   scroll_result_did_scroll_.did_scroll = true;
2525 
2526   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2527       .WillOnce(testing::Return(kImplThreadScrollState));
2528   EXPECT_CALL(
2529       mock_input_handler_,
2530       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2531       .Times(1);
2532   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2533   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2534       .Times(1)
2535       .WillOnce(testing::Return(cc::ElementId()));
2536 
2537   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2538 
2539   // GestureScrollBegin will be processed immediately.
2540   EXPECT_EQ(0ul, event_queue().size());
2541   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2542   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[0]);
2543 
2544   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
2545 
2546   // GestureScrollUpdate will be queued.
2547   EXPECT_EQ(1ul, event_queue().size());
2548   EXPECT_EQ(-20,
2549             static_cast<const WebGestureEvent&>(event_queue().front()->event())
2550                 .data.scroll_update.delta_y);
2551   EXPECT_EQ(1ul, event_queue().front()->coalesced_count());
2552   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2553 
2554   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -40);
2555 
2556   // GestureScrollUpdate will be coalesced.
2557   EXPECT_EQ(1ul, event_queue().size());
2558   EXPECT_EQ(-60,
2559             static_cast<const WebGestureEvent&>(event_queue().front()->event())
2560                 .data.scroll_update.delta_y);
2561   EXPECT_EQ(2ul, event_queue().front()->coalesced_count());
2562   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2563 
2564   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0);
2565   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2566 
2567   // GestureScrollEnd will be queued.
2568   EXPECT_EQ(2ul, event_queue().size());
2569   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2570   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2571 
2572   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2573     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2574         .WillOnce(testing::Return(false));
2575   }
2576   EXPECT_CALL(
2577       mock_input_handler_,
2578       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2579                    _))
2580       .WillOnce(testing::Return(scroll_result_did_scroll_));
2581   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2582   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2583       .Times(2)
2584       .WillRepeatedly(testing::Return(cc::ElementId()));
2585 
2586   // Dispatch all queued events.
2587   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2588   DeliverInputForBeginFrame();
2589   EXPECT_EQ(0ul, event_queue().size());
2590   // Should run callbacks for every original events.
2591   EXPECT_EQ(4ul, event_disposition_recorder_.size());
2592   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[1]);
2593   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[2]);
2594   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_[3]);
2595   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2596 }
2597 
2598 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
2599     defined(MEMORY_SANITIZER)
2600 // Flaky under sanitizers and in other "slow" bot configs:
2601 // https://crbug.com/1029250
2602 #define MAYBE_VSyncAlignedGestureScrollPinchScroll \
2603   DISABLED_VSyncAlignedGestureScrollPinchScroll
2604 #else
2605 #define MAYBE_VSyncAlignedGestureScrollPinchScroll \
2606   VSyncAlignedGestureScrollPinchScroll
2607 #endif
2608 
TEST_F(InputHandlerProxyEventQueueTest,MAYBE_VSyncAlignedGestureScrollPinchScroll)2609 TEST_F(InputHandlerProxyEventQueueTest,
2610        MAYBE_VSyncAlignedGestureScrollPinchScroll) {
2611   // Handle scroll on compositor.
2612   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2613   scroll_result_did_scroll_.did_scroll = true;
2614 
2615   // Start scroll in the first frame.
2616   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2617       .WillOnce(testing::Return(kImplThreadScrollState));
2618   EXPECT_CALL(
2619       mock_input_handler_,
2620       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2621       .Times(1);
2622   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2623     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2624         .WillOnce(testing::Return(false));
2625   }
2626   EXPECT_CALL(
2627       mock_input_handler_,
2628       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2629                    _))
2630       .WillOnce(testing::Return(scroll_result_did_scroll_));
2631   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2632   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2633       .Times(2)
2634       .WillRepeatedly(testing::Return(cc::ElementId()));
2635 
2636   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2637   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
2638 
2639   EXPECT_EQ(1ul, event_queue().size());
2640   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2641 
2642   DeliverInputForBeginFrame();
2643 
2644   EXPECT_EQ(0ul, event_queue().size());
2645   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2646   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2647 
2648   // Continue scroll in the second frame, pinch, then start another scroll.
2649   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2650       .WillOnce(testing::Return(kImplThreadScrollState));
2651   EXPECT_CALL(
2652       mock_input_handler_,
2653       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2654       .Times(1);
2655   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2656     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2657         .WillRepeatedly(testing::Return(false));
2658   }
2659   EXPECT_CALL(
2660       mock_input_handler_,
2661       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2662                    _))
2663       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
2664   EXPECT_CALL(mock_input_handler_, ScrollEnd(true)).Times(2);
2665   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2666   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2667       .Times(8)
2668       .WillRepeatedly(testing::Return(cc::ElementId()));
2669   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
2670   // Two |GesturePinchUpdate| will be coalesced.
2671   EXPECT_CALL(mock_input_handler_,
2672               PinchGestureUpdate(0.7f, gfx::Point(13, 17)));
2673   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(gfx::Point(), false));
2674   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(2);
2675 
2676   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
2677   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2678   HandleGestureEvent(WebInputEvent::Type::kGesturePinchBegin);
2679   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 1.4f, 13, 17);
2680   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 0.5f, 13, 17);
2681   HandleGestureEvent(WebInputEvent::Type::kGesturePinchEnd);
2682   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2683   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -70);
2684   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -5);
2685   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2686 
2687   EXPECT_EQ(8ul, event_queue().size());
2688   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2689 
2690   DeliverInputForBeginFrame();
2691 
2692   EXPECT_EQ(0ul, event_queue().size());
2693   EXPECT_EQ(12ul, event_disposition_recorder_.size());
2694   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2695 }
2696 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedQueueingTime)2697 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedQueueingTime) {
2698   base::SimpleTestTickClock tick_clock;
2699   tick_clock.SetNowTicks(base::TimeTicks::Now());
2700   SetInputHandlerProxyTickClockForTesting(&tick_clock);
2701 
2702   // Handle scroll on compositor.
2703   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2704   scroll_result_did_scroll_.did_scroll = true;
2705 
2706   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2707       .WillOnce(testing::Return(kImplThreadScrollState));
2708   EXPECT_CALL(
2709       mock_input_handler_,
2710       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2711       .Times(1);
2712   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2713   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2714       .Times(3)
2715       .WillRepeatedly(testing::Return(cc::ElementId()));
2716   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2717     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2718         .WillOnce(testing::Return(false));
2719   }
2720   EXPECT_CALL(
2721       mock_input_handler_,
2722       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2723                    _))
2724       .WillOnce(testing::Return(scroll_result_did_scroll_));
2725   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
2726   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2727 
2728   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2729   tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
2730   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
2731   tick_clock.Advance(base::TimeDelta::FromMicroseconds(40));
2732   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -40);
2733   tick_clock.Advance(base::TimeDelta::FromMicroseconds(20));
2734   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
2735   tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
2736   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2737 
2738   // Dispatch all queued events.
2739   tick_clock.Advance(base::TimeDelta::FromMicroseconds(70));
2740   DeliverInputForBeginFrame();
2741   EXPECT_EQ(0ul, event_queue().size());
2742   EXPECT_EQ(5ul, event_disposition_recorder_.size());
2743   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2744 }
2745 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedCoalesceScrollAndPinch)2746 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceScrollAndPinch) {
2747   // Start scroll in the first frame.
2748   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2749       .WillOnce(testing::Return(kImplThreadScrollState));
2750   EXPECT_CALL(
2751       mock_input_handler_,
2752       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2753       .Times(1);
2754   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
2755   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2756       .Times(1)
2757       .WillOnce(testing::Return(cc::ElementId()));
2758 
2759   // GSUs and GPUs in one sequence should be coalesced into 1 GSU and 1 GPU.
2760   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2761   HandleGestureEvent(WebInputEvent::Type::kGesturePinchBegin);
2762   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
2763   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -7);
2764   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 2.0f, 13, 10);
2765   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
2766   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -6);
2767   HandleGestureEvent(WebInputEvent::Type::kGesturePinchEnd);
2768   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2769   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2770   HandleGestureEvent(WebInputEvent::Type::kGesturePinchBegin);
2771   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 0.2f, 2, 20);
2772   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 10.0f, 1, 10);
2773   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
2774   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 0.25f, 3, 30);
2775   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
2776   HandleGestureEvent(WebInputEvent::Type::kGesturePinchEnd);
2777   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2778 
2779   // Only the first GSB was dispatched.
2780   EXPECT_EQ(11ul, event_queue().size());
2781   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2782 
2783   EXPECT_EQ(WebInputEvent::Type::kGesturePinchBegin,
2784             event_queue()[0]->event().GetType());
2785   EXPECT_EQ(WebInputEvent::Type::kGestureScrollUpdate,
2786             event_queue()[1]->event().GetType());
2787   EXPECT_EQ(-35, static_cast<const WebGestureEvent&>(event_queue()[1]->event())
2788                      .data.scroll_update.delta_y);
2789   EXPECT_EQ(WebInputEvent::Type::kGesturePinchUpdate,
2790             event_queue()[2]->event().GetType());
2791   EXPECT_EQ(2.0f, static_cast<const WebGestureEvent&>(event_queue()[2]->event())
2792                       .data.pinch_update.scale);
2793   EXPECT_EQ(WebInputEvent::Type::kGesturePinchEnd,
2794             event_queue()[3]->event().GetType());
2795   EXPECT_EQ(WebInputEvent::Type::kGestureScrollEnd,
2796             event_queue()[4]->event().GetType());
2797   EXPECT_EQ(WebInputEvent::Type::kGestureScrollBegin,
2798             event_queue()[5]->event().GetType());
2799   EXPECT_EQ(WebInputEvent::Type::kGesturePinchBegin,
2800             event_queue()[6]->event().GetType());
2801   EXPECT_EQ(WebInputEvent::Type::kGestureScrollUpdate,
2802             event_queue()[7]->event().GetType());
2803   EXPECT_EQ(-85, static_cast<const WebGestureEvent&>(event_queue()[7]->event())
2804                      .data.scroll_update.delta_y);
2805   EXPECT_EQ(WebInputEvent::Type::kGesturePinchUpdate,
2806             event_queue()[8]->event().GetType());
2807   EXPECT_EQ(0.5f, static_cast<const WebGestureEvent&>(event_queue()[8]->event())
2808                       .data.pinch_update.scale);
2809   EXPECT_EQ(WebInputEvent::Type::kGesturePinchEnd,
2810             event_queue()[9]->event().GetType());
2811   EXPECT_EQ(WebInputEvent::Type::kGestureScrollEnd,
2812             event_queue()[10]->event().GetType());
2813   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2814 }
2815 
TEST_F(InputHandlerProxyEventQueueTest,VSyncAlignedCoalesceTouchpadPinch)2816 TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedCoalesceTouchpadPinch) {
2817   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
2818   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput());
2819   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2820       .Times(1)
2821       .WillOnce(testing::Return(cc::ElementId()));
2822 
2823   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGesturePinchBegin,
2824                                      WebGestureDevice::kTouchpad);
2825   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGesturePinchUpdate,
2826                                      WebGestureDevice::kTouchpad, 1.1f, 10, 20);
2827   // The second update should coalesce with the first.
2828   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGesturePinchUpdate,
2829                                      WebGestureDevice::kTouchpad, 1.1f, 10, 20);
2830   // The third update has a different anchor so it should not be coalesced.
2831   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGesturePinchUpdate,
2832                                      WebGestureDevice::kTouchpad, 1.1f, 11, 21);
2833   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGesturePinchEnd,
2834                                      WebGestureDevice::kTouchpad);
2835 
2836   // Only the PinchBegin was dispatched.
2837   EXPECT_EQ(3ul, event_queue().size());
2838   EXPECT_EQ(1ul, event_disposition_recorder_.size());
2839 
2840   ASSERT_EQ(WebInputEvent::Type::kGesturePinchUpdate,
2841             event_queue()[0]->event().GetType());
2842   EXPECT_FLOAT_EQ(1.21f,
2843                   static_cast<const WebGestureEvent&>(event_queue()[0]->event())
2844                       .data.pinch_update.scale);
2845   EXPECT_EQ(WebInputEvent::Type::kGesturePinchUpdate,
2846             event_queue()[1]->event().GetType());
2847   EXPECT_EQ(WebInputEvent::Type::kGesturePinchEnd,
2848             event_queue()[2]->event().GetType());
2849 }
2850 
TEST_F(InputHandlerProxyEventQueueTest,OriginalEventsTracing)2851 TEST_F(InputHandlerProxyEventQueueTest, OriginalEventsTracing) {
2852   // Handle scroll on compositor.
2853   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2854   scroll_result_did_scroll_.did_scroll = true;
2855 
2856   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2857       .WillRepeatedly(testing::Return(kImplThreadScrollState));
2858   EXPECT_CALL(
2859       mock_input_handler_,
2860       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2861       .Times(2);
2862   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput())
2863       .Times(::testing::AtLeast(1));
2864   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2865       .Times(9)
2866       .WillRepeatedly(testing::Return(cc::ElementId()));
2867   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2868     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2869         .WillRepeatedly(testing::Return(false));
2870   }
2871   EXPECT_CALL(
2872       mock_input_handler_,
2873       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2874                    _))
2875       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
2876   EXPECT_CALL(mock_input_handler_, ScrollEnd(true))
2877       .Times(::testing::AtLeast(1));
2878   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(2);
2879 
2880   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
2881   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(_, _));
2882   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(_, _));
2883 
2884   trace_analyzer::Start("*");
2885   // Simulate scroll.
2886   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2887   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
2888   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -40);
2889   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
2890   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2891 
2892   // Simulate scroll and pinch.
2893   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
2894   HandleGestureEvent(WebInputEvent::Type::kGesturePinchBegin);
2895   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 10.0f, 1, 10);
2896   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
2897   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 2.0f, 1, 10);
2898   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
2899   HandleGestureEvent(WebInputEvent::Type::kGesturePinchEnd);
2900   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
2901 
2902   // Dispatch all events.
2903   DeliverInputForBeginFrame();
2904 
2905   // Retrieve tracing data.
2906   auto analyzer = trace_analyzer::Stop();
2907   trace_analyzer::TraceEventVector begin_events;
2908   trace_analyzer::Query begin_query = trace_analyzer::Query::EventPhaseIs(
2909       TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN);
2910   analyzer->FindEvents(begin_query, &begin_events);
2911 
2912   trace_analyzer::TraceEventVector end_events;
2913   trace_analyzer::Query end_query =
2914       trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END);
2915   analyzer->FindEvents(end_query, &end_events);
2916 
2917   EXPECT_EQ(7ul, begin_events.size());
2918   EXPECT_EQ(7ul, end_events.size());
2919   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGestureScrollUpdate),
2920             end_events[0]->GetKnownArgAsInt("type"));
2921   EXPECT_EQ(3, end_events[0]->GetKnownArgAsInt("coalesced_count"));
2922   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGestureScrollEnd),
2923             end_events[1]->GetKnownArgAsInt("type"));
2924 
2925   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGestureScrollBegin),
2926             end_events[2]->GetKnownArgAsInt("type"));
2927   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGesturePinchBegin),
2928             end_events[3]->GetKnownArgAsInt("type"));
2929   // Original scroll and pinch updates will be stored in the coalesced
2930   // PinchUpdate of the <ScrollUpdate, PinchUpdate> pair.
2931   // The ScrollUpdate of the pair doesn't carry original events and won't be
2932   // traced.
2933   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGesturePinchUpdate),
2934             end_events[4]->GetKnownArgAsInt("type"));
2935   EXPECT_EQ(4, end_events[4]->GetKnownArgAsInt("coalesced_count"));
2936   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGesturePinchEnd),
2937             end_events[5]->GetKnownArgAsInt("type"));
2938   EXPECT_EQ(static_cast<int>(WebInputEvent::Type::kGestureScrollEnd),
2939             end_events[6]->GetKnownArgAsInt("type"));
2940   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
2941 }
2942 
TEST_F(InputHandlerProxyEventQueueTest,TouchpadGestureScrollEndFlushQueue)2943 TEST_F(InputHandlerProxyEventQueueTest, TouchpadGestureScrollEndFlushQueue) {
2944   // Handle scroll on compositor.
2945   cc::InputHandlerScrollResult scroll_result_did_scroll_;
2946   scroll_result_did_scroll_.did_scroll = true;
2947 
2948   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
2949       .WillRepeatedly(testing::Return(kImplThreadScrollState));
2950   EXPECT_CALL(
2951       mock_input_handler_,
2952       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
2953       .Times(2);
2954   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
2955     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
2956         .WillRepeatedly(testing::Return(false));
2957   }
2958   EXPECT_CALL(
2959       mock_input_handler_,
2960       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
2961                    _))
2962       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
2963   EXPECT_CALL(mock_input_handler_, ScrollEnd(true))
2964       .Times(::testing::AtLeast(1));
2965   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2966       .Times(2)
2967       .WillRepeatedly(testing::Return(cc::ElementId()));
2968 
2969   // Simulate scroll.
2970   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollBegin,
2971                                      WebGestureDevice::kTouchpad);
2972   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollUpdate,
2973                                      WebGestureDevice::kTouchpad, -20);
2974 
2975   // Both GSB and the first GSU will be dispatched immediately since the first
2976   // GSU has blocking wheel event source.
2977   EXPECT_EQ(0ul, event_queue().size());
2978   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2979 
2980   // The rest of the GSU events will get queued since they have non-blocking
2981   // wheel event source.
2982   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput())
2983       .Times(::testing::AtLeast(1));
2984   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
2985       .Times(4)
2986       .WillRepeatedly(testing::Return(cc::ElementId()));
2987   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollUpdate,
2988                                      WebGestureDevice::kTouchpad, -20);
2989   EXPECT_EQ(1ul, event_queue().size());
2990   EXPECT_EQ(2ul, event_disposition_recorder_.size());
2991 
2992   // Touchpad GSE will flush the queue.
2993   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
2994   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollEnd,
2995                                      WebGestureDevice::kTouchpad);
2996 
2997   EXPECT_EQ(0ul, event_queue().size());
2998   // GSB, GSU(with blocking wheel source), GSU(with non-blocking wheel
2999   // source), and GSE are the sent events.
3000   EXPECT_EQ(4ul, event_disposition_recorder_.size());
3001 
3002   EXPECT_FALSE(
3003       input_handler_proxy_.gesture_scroll_on_impl_thread_for_testing());
3004 
3005   // Starting a new scroll sequence should have the same behavior (namely that
3006   // the first scroll update is not queued but immediately dispatched).
3007   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollBegin,
3008                                      WebGestureDevice::kTouchpad);
3009   HandleGestureEventWithSourceDevice(WebInputEvent::Type::kGestureScrollUpdate,
3010                                      WebGestureDevice::kTouchpad, -20);
3011 
3012   // Both GSB and the first GSU must be dispatched immediately since the first
3013   // GSU has blocking wheel event source.
3014   EXPECT_EQ(0ul, event_queue().size());
3015   EXPECT_EQ(6ul, event_disposition_recorder_.size());
3016 }
3017 
TEST_F(InputHandlerProxyEventQueueTest,CoalescedLatencyInfo)3018 TEST_F(InputHandlerProxyEventQueueTest, CoalescedLatencyInfo) {
3019   // Handle scroll on compositor.
3020   cc::InputHandlerScrollResult scroll_result_did_scroll_;
3021   scroll_result_did_scroll_.did_scroll = true;
3022 
3023   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3024       .WillOnce(testing::Return(kImplThreadScrollState));
3025   EXPECT_CALL(
3026       mock_input_handler_,
3027       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3028       .Times(1);
3029   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
3030   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
3031       .Times(3)
3032       .WillRepeatedly(testing::Return(cc::ElementId()));
3033   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
3034     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
3035         .WillOnce(testing::Return(false));
3036   }
3037   EXPECT_CALL(
3038       mock_input_handler_,
3039       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3040                    _))
3041       .WillOnce(testing::Return(scroll_result_did_scroll_));
3042   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3043   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3044 
3045   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
3046   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
3047   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -40);
3048   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
3049   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
3050   DeliverInputForBeginFrame();
3051 
3052   EXPECT_EQ(0ul, event_queue().size());
3053   // Should run callbacks for every original events.
3054   EXPECT_EQ(5ul, event_disposition_recorder_.size());
3055   EXPECT_EQ(5ul, latency_info_recorder_.size());
3056   EXPECT_EQ(false, latency_info_recorder_[1].coalesced());
3057   // Coalesced events should have latency set to coalesced.
3058   EXPECT_EQ(true, latency_info_recorder_[2].coalesced());
3059   EXPECT_EQ(true, latency_info_recorder_[3].coalesced());
3060   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3061 }
3062 
TEST_F(InputHandlerProxyEventQueueTest,CoalescedEventSwitchToMainThread)3063 TEST_F(InputHandlerProxyEventQueueTest, CoalescedEventSwitchToMainThread) {
3064   cc::InputHandlerScrollResult scroll_result_did_scroll_;
3065   cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
3066   scroll_result_did_scroll_.did_scroll = true;
3067   scroll_result_did_not_scroll_.did_scroll = false;
3068 
3069   // scroll begin on main thread
3070   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3071       .WillOnce(testing::Return(kMainThreadScrollState));
3072   EXPECT_CALL(
3073       mock_input_handler_,
3074       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3075       .Times(1);
3076   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2);
3077   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
3078       .Times(8)
3079       .WillRepeatedly(testing::Return(cc::ElementId()));
3080   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
3081     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
3082         .WillOnce(testing::Return(false));
3083   }
3084   EXPECT_CALL(
3085       mock_input_handler_,
3086       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3087                    _))
3088       .WillOnce(testing::Return(scroll_result_did_not_scroll_));
3089 
3090   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
3091   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
3092   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
3093   DeliverInputForBeginFrame();
3094   EXPECT_EQ(3ul, event_disposition_recorder_.size());
3095   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
3096             event_disposition_recorder_.back());
3097   // GSU should not be coalesced
3098   EXPECT_EQ(false, latency_info_recorder_[1].coalesced());
3099   EXPECT_EQ(false, latency_info_recorder_[2].coalesced());
3100 
3101   // pinch start, handle scroll and pinch on compositor.
3102   EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
3103   EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(_, _));
3104   EXPECT_CALL(mock_input_handler_, PinchGestureEnd(_, _));
3105 
3106   HandleGestureEvent(WebInputEvent::Type::kGesturePinchBegin);
3107   HandleGestureEvent(WebInputEvent::Type::kGesturePinchUpdate, 10.0f, 1, 10);
3108   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
3109   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
3110   EXPECT_EQ(2ul, event_queue().size());
3111   DeliverInputForBeginFrame();
3112 
3113   EXPECT_EQ(7ul, event_disposition_recorder_.size());
3114   EXPECT_EQ(false, latency_info_recorder_[4].coalesced());
3115   // Coalesced events should have latency set to coalesced.
3116   EXPECT_EQ(true, latency_info_recorder_[5].coalesced());
3117   EXPECT_EQ(true, latency_info_recorder_[6].coalesced());
3118   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
3119 
3120   // Pinch end, handle scroll on main thread.
3121   HandleGestureEvent(WebInputEvent::Type::kGesturePinchEnd);
3122   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -40);
3123   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -30);
3124   DeliverInputForBeginFrame();
3125 
3126   EXPECT_EQ(0ul, event_queue().size());
3127   // Should run callbacks for every original events.
3128   EXPECT_EQ(10ul, event_disposition_recorder_.size());
3129   EXPECT_EQ(10ul, latency_info_recorder_.size());
3130   // Latency should not be set to coalesced when send to main thread
3131   EXPECT_EQ(false, latency_info_recorder_[8].coalesced());
3132   EXPECT_EQ(false, latency_info_recorder_[9].coalesced());
3133   EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
3134             event_disposition_recorder_.back());
3135   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3136 }
3137 
TEST_F(InputHandlerProxyEventQueueTest,ScrollPredictorTest)3138 TEST_F(InputHandlerProxyEventQueueTest, ScrollPredictorTest) {
3139   base::SimpleTestTickClock tick_clock;
3140   tick_clock.SetNowTicks(base::TimeTicks());
3141   SetInputHandlerProxyTickClockForTesting(&tick_clock);
3142 
3143   cc::InputHandlerScrollResult scroll_result_did_scroll_;
3144   scroll_result_did_scroll_.did_scroll = true;
3145   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3146       .WillOnce(testing::Return(kImplThreadScrollState));
3147   EXPECT_CALL(
3148       mock_input_handler_,
3149       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3150       .Times(1);
3151   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2);
3152   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
3153       .Times(2)
3154       .WillRepeatedly(testing::Return(cc::ElementId()));
3155   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
3156     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
3157         .WillOnce(testing::Return(false));
3158   }
3159   EXPECT_CALL(
3160       mock_input_handler_,
3161       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3162                    _))
3163       .WillOnce(testing::Return(scroll_result_did_scroll_));
3164 
3165   // No prediction when start with a GSB
3166   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
3167   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
3168   DeliverInputForBeginFrame();
3169   EXPECT_FALSE(GestureScrollEventPredictionAvailable());
3170 
3171   // Test predictor returns last GSU delta.
3172   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
3173   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
3174   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
3175   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -15);
3176   DeliverInputForBeginFrame();
3177   auto result = GestureScrollEventPredictionAvailable();
3178   EXPECT_TRUE(result);
3179   EXPECT_NE(0, result->pos.y());
3180   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
3181 
3182   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3183 
3184   // Predictor has been reset after a new GSB.
3185   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
3186   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
3187       .Times(2)
3188       .WillRepeatedly(testing::Return(cc::ElementId()));
3189   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3190       .WillOnce(testing::Return(kImplThreadScrollState));
3191   EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(1);
3192   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3193   EXPECT_CALL(
3194       mock_input_handler_,
3195       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3196       .Times(1);
3197   tick_clock.Advance(base::TimeDelta::FromMilliseconds(8));
3198   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
3199   DeliverInputForBeginFrame();
3200   EXPECT_FALSE(GestureScrollEventPredictionAvailable());
3201   HandleGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
3202 
3203   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3204 }
3205 
3206 // Test deliver input w/o prediction enabled.
TEST_F(InputHandlerProxyEventQueueTest,DeliverInputWithHighLatencyMode)3207 TEST_F(InputHandlerProxyEventQueueTest, DeliverInputWithHighLatencyMode) {
3208   SetScrollPredictionEnabled(false);
3209 
3210   cc::InputHandlerScrollResult scroll_result_did_scroll_;
3211   scroll_result_did_scroll_.did_scroll = true;
3212   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3213       .WillOnce(testing::Return(kImplThreadScrollState));
3214   EXPECT_CALL(
3215       mock_input_handler_,
3216       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3217       .Times(1);
3218   EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(2);
3219   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_))
3220       .Times(3)
3221       .WillRepeatedly(testing::Return(cc::ElementId()));
3222   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
3223     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
3224         .WillRepeatedly(testing::Return(false));
3225   }
3226   EXPECT_CALL(
3227       mock_input_handler_,
3228       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
3229                    _))
3230       .WillRepeatedly(testing::Return(scroll_result_did_scroll_));
3231 
3232   HandleGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
3233   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
3234   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
3235   DeliverInputForBeginFrame();
3236   // 3 queued event be delivered.
3237   EXPECT_EQ(3ul, event_disposition_recorder_.size());
3238   EXPECT_EQ(0ul, event_queue().size());
3239   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
3240 
3241   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -20);
3242   HandleGestureEvent(WebInputEvent::Type::kGestureScrollUpdate, -10);
3243   DeliverInputForHighLatencyMode();
3244   // 2 queued event be delivered.
3245   EXPECT_EQ(5ul, event_disposition_recorder_.size());
3246   EXPECT_EQ(0ul, event_queue().size());
3247   EXPECT_EQ(InputHandlerProxy::DID_HANDLE, event_disposition_recorder_.back());
3248 
3249   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3250 }
3251 
TEST_F(InputHandlerProxyEventQueueTest,KeyEventAttribution)3252 TEST_F(InputHandlerProxyEventQueueTest, KeyEventAttribution) {
3253   WebKeyboardEvent key(WebInputEvent::Type::kKeyDown,
3254                        WebInputEvent::kNoModifiers,
3255                        WebInputEvent::GetStaticTimeStampForTests());
3256 
3257   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(_)).Times(0);
3258 
3259   WebInputEventAttribution attribution =
3260       input_handler_proxy_.PerformEventAttribution(key);
3261   EXPECT_EQ(attribution.type(), WebInputEventAttribution::kFocusedFrame);
3262   EXPECT_EQ(attribution.target_frame_id(), cc::ElementId());
3263   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3264 }
3265 
TEST_F(InputHandlerProxyEventQueueTest,MouseEventAttribution)3266 TEST_F(InputHandlerProxyEventQueueTest, MouseEventAttribution) {
3267   WebMouseEvent mouse_down(WebInputEvent::Type::kMouseDown,
3268                            WebInputEvent::kNoModifiers,
3269                            WebInputEvent::GetStaticTimeStampForTests());
3270 
3271   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(gfx::PointF(0, 0)))
3272       .Times(1)
3273       .WillOnce(testing::Return(cc::ElementId(0xDEADBEEF)));
3274 
3275   WebInputEventAttribution attribution =
3276       input_handler_proxy_.PerformEventAttribution(mouse_down);
3277   EXPECT_EQ(attribution.type(), WebInputEventAttribution::kTargetedFrame);
3278   EXPECT_EQ(attribution.target_frame_id(), cc::ElementId(0xDEADBEEF));
3279   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3280 }
3281 
TEST_F(InputHandlerProxyEventQueueTest,MouseWheelEventAttribution)3282 TEST_F(InputHandlerProxyEventQueueTest, MouseWheelEventAttribution) {
3283   WebMouseWheelEvent wheel(WebInputEvent::Type::kMouseWheel,
3284                            WebInputEvent::kNoModifiers,
3285                            WebInputEvent::GetStaticTimeStampForTests());
3286 
3287   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(gfx::PointF(0, 0)))
3288       .Times(1)
3289       .WillOnce(testing::Return(cc::ElementId(0xDEADBEEF)));
3290 
3291   WebInputEventAttribution attribution =
3292       input_handler_proxy_.PerformEventAttribution(wheel);
3293   EXPECT_EQ(attribution.type(), WebInputEventAttribution::kTargetedFrame);
3294   EXPECT_EQ(attribution.target_frame_id(), cc::ElementId(0xDEADBEEF));
3295   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3296 }
3297 
3298 // Verify that the first point in a touch event is used for performing event
3299 // attribution.
TEST_F(InputHandlerProxyEventQueueTest,TouchEventAttribution)3300 TEST_F(InputHandlerProxyEventQueueTest, TouchEventAttribution) {
3301   WebTouchEvent touch(WebInputEvent::Type::kTouchStart,
3302                       WebInputEvent::kNoModifiers,
3303                       WebInputEvent::GetStaticTimeStampForTests());
3304 
3305   touch.touches_length = 3;
3306   touch.touch_start_or_first_touch_move = true;
3307   touch.touches[0] =
3308       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 0, 0);
3309   touch.touches[1] =
3310       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
3311   touch.touches[2] =
3312       CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, -10, 10);
3313 
3314   EXPECT_CALL(mock_input_handler_, FindFrameElementIdAtPoint(gfx::PointF(0, 0)))
3315       .Times(1)
3316       .WillOnce(testing::Return(cc::ElementId(0xDEADBEEF)));
3317 
3318   WebInputEventAttribution attribution =
3319       input_handler_proxy_.PerformEventAttribution(touch);
3320   EXPECT_EQ(attribution.type(), WebInputEventAttribution::kTargetedFrame);
3321   EXPECT_EQ(attribution.target_frame_id(), cc::ElementId(0xDEADBEEF));
3322   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3323 }
3324 
TEST_F(InputHandlerProxyEventQueueTest,GestureEventAttribution)3325 TEST_F(InputHandlerProxyEventQueueTest, GestureEventAttribution) {
3326   WebGestureEvent gesture(WebInputEvent::Type::kGestureTap,
3327                           WebInputEvent::kNoModifiers,
3328                           WebInputEvent::GetStaticTimeStampForTests());
3329   gesture.SetPositionInWidget(gfx::PointF(10, 10));
3330 
3331   EXPECT_CALL(mock_input_handler_,
3332               FindFrameElementIdAtPoint(gfx::PointF(10, 10)))
3333       .Times(1)
3334       .WillOnce(testing::Return(cc::ElementId(0xDEADBEEF)));
3335   WebInputEventAttribution attribution =
3336       input_handler_proxy_.PerformEventAttribution(gesture);
3337   EXPECT_EQ(attribution.type(), WebInputEventAttribution::kTargetedFrame);
3338   EXPECT_EQ(attribution.target_frame_id(), cc::ElementId(0xDEADBEEF));
3339   testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
3340 }
3341 
3342 class InputHandlerProxyMainThreadScrollingReasonTest
3343     : public InputHandlerProxyTest {
3344  public:
3345   enum TestEventType {
3346     Touch,
3347     MouseWheel,
3348   };
3349 
InputHandlerProxyMainThreadScrollingReasonTest()3350   InputHandlerProxyMainThreadScrollingReasonTest() : InputHandlerProxyTest() {}
3351   ~InputHandlerProxyMainThreadScrollingReasonTest() = default;
3352 
SetupEvents(TestEventType type)3353   void SetupEvents(TestEventType type) {
3354     touch_start_ = WebTouchEvent(WebInputEvent::Type::kTouchStart,
3355                                  WebInputEvent::kNoModifiers,
3356                                  WebInputEvent::GetStaticTimeStampForTests());
3357     touch_end_ = WebTouchEvent(WebInputEvent::Type::kTouchEnd,
3358                                WebInputEvent::kNoModifiers,
3359                                WebInputEvent::GetStaticTimeStampForTests());
3360     wheel_event_ = WebMouseWheelEvent(
3361         WebInputEvent::Type::kMouseWheel, WebInputEvent::kControlKey,
3362         WebInputEvent::GetStaticTimeStampForTests());
3363     gesture_scroll_begin_ = WebGestureEvent(
3364         WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
3365         WebInputEvent::GetStaticTimeStampForTests(),
3366         type == TestEventType::MouseWheel ? WebGestureDevice::kTouchpad
3367                                           : WebGestureDevice::kTouchscreen);
3368     gesture_scroll_end_ = WebGestureEvent(
3369         WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
3370         WebInputEvent::GetStaticTimeStampForTests(),
3371         type == TestEventType::MouseWheel ? WebGestureDevice::kTouchpad
3372                                           : WebGestureDevice::kTouchscreen);
3373     touch_start_.touches_length = 1;
3374     touch_start_.touch_start_or_first_touch_move = true;
3375     touch_start_.touches[0] =
3376         CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
3377 
3378     touch_end_.touches_length = 1;
3379   }
3380 
GetBucketSample(uint32_t reason)3381   base::HistogramBase::Sample GetBucketSample(uint32_t reason) {
3382     if (reason == cc::MainThreadScrollingReason::kNotScrollingOnMain)
3383       return 0;
3384 
3385     uint32_t bucket = 1;
3386     while ((reason = reason >> 1))
3387       bucket++;
3388     return bucket;
3389   }
3390 
3391  protected:
3392   WebTouchEvent touch_start_;
3393   WebTouchEvent touch_end_;
3394   WebMouseWheelEvent wheel_event_;
3395   WebGestureEvent gesture_scroll_begin_;
3396   WebGestureEvent gesture_scroll_end_;
3397 };
3398 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollNotScrollOnMain)3399 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3400        GestureScrollNotScrollOnMain) {
3401   // Touch start with passive event listener.
3402   SetupEvents(TestEventType::Touch);
3403 
3404   EXPECT_CALL(mock_input_handler_,
3405               EventListenerTypeForTouchStartOrMoveAt(
3406                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
3407       .WillOnce(testing::Return(
3408           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
3409   EXPECT_CALL(
3410       mock_input_handler_,
3411       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
3412       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
3413   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
3414       .WillOnce(testing::Return());
3415 
3416   cc::InputHandlerPointerResult pointer_down_result;
3417   pointer_down_result.type = cc::PointerResultType::kUnhandled;
3418   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
3419       .WillOnce(testing::Return(pointer_down_result));
3420 
3421   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
3422   EXPECT_EQ(expected_disposition_,
3423             HandleInputEventAndFlushEventQueue(
3424                 mock_input_handler_, input_handler_.get(), touch_start_));
3425 
3426   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3427       .WillOnce(testing::Return(kImplThreadScrollState));
3428   EXPECT_CALL(
3429       mock_input_handler_,
3430       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3431       .Times(1);
3432   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3433   EXPECT_EQ(
3434       expected_disposition_,
3435       HandleInputEventAndFlushEventQueue(
3436           mock_input_handler_, input_handler_.get(), gesture_scroll_begin_));
3437   EXPECT_THAT(
3438       histogram_tester().GetAllSamples(
3439           "Renderer4.MainThreadGestureScrollReason"),
3440       testing::ElementsAre(base::Bucket(
3441           GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
3442           1)));
3443 
3444   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3445   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3446   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3447   EXPECT_EQ(
3448       expected_disposition_,
3449       HandleInputEventAndFlushEventQueue(
3450           mock_input_handler_, input_handler_.get(), gesture_scroll_end_));
3451 }
3452 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollTouchEventHandlerRegion)3453 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3454        GestureScrollTouchEventHandlerRegion) {
3455   // The touch event hits a touch event handler that is acked from the
3456   // compositor thread.
3457   SetupEvents(TestEventType::Touch);
3458 
3459   EXPECT_CALL(mock_input_handler_,
3460               EventListenerTypeForTouchStartOrMoveAt(
3461                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
3462       .WillOnce(
3463           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
3464                               HANDLER_ON_SCROLLING_LAYER));
3465   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
3466       .WillOnce(testing::Return());
3467 
3468   cc::InputHandlerPointerResult pointer_down_result;
3469   pointer_down_result.type = cc::PointerResultType::kUnhandled;
3470   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
3471       .WillOnce(testing::Return(pointer_down_result));
3472 
3473   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
3474   EXPECT_EQ(expected_disposition_,
3475             HandleInputEventAndFlushEventQueue(
3476                 mock_input_handler_, input_handler_.get(), touch_start_));
3477 
3478   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3479       .WillOnce(testing::Return(kImplThreadScrollState));
3480   EXPECT_CALL(
3481       mock_input_handler_,
3482       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3483       .Times(1);
3484   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3485   EXPECT_EQ(
3486       expected_disposition_,
3487       HandleInputEventAndFlushEventQueue(
3488           mock_input_handler_, input_handler_.get(), gesture_scroll_begin_));
3489 
3490   EXPECT_THAT(
3491       histogram_tester().GetAllSamples(
3492           "Renderer4.MainThreadGestureScrollReason"),
3493       testing::ElementsAre(base::Bucket(
3494           GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
3495           1)));
3496 
3497   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3498   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3499   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3500   EXPECT_EQ(
3501       expected_disposition_,
3502       HandleInputEventAndFlushEventQueue(
3503           mock_input_handler_, input_handler_.get(), gesture_scroll_end_));
3504 }
3505 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollTouchEventHandlerRegionAndHandlingScrollFromMainThread)3506 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3507        GestureScrollTouchEventHandlerRegionAndHandlingScrollFromMainThread) {
3508   // The touch event hits a touch event handler and should block on main thread.
3509   // Since ScrollBegin doesn't allow the gesture to scroll on impl. We report
3510   // TouchEventHandler reason as well as HandlingScrollFromMainThread. Since we
3511   // do not collect HandlingScrollFromMainThread when there are other reasons
3512   // present, TouchEventHandler is the only reason being collected in the
3513   // histogram.
3514   SetupEvents(TestEventType::Touch);
3515 
3516   EXPECT_CALL(mock_input_handler_,
3517               EventListenerTypeForTouchStartOrMoveAt(
3518                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
3519       .WillOnce(
3520           testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
3521                               HANDLER_ON_SCROLLING_LAYER));
3522   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
3523       .WillOnce(testing::Return());
3524 
3525   cc::InputHandlerPointerResult pointer_down_result;
3526   pointer_down_result.type = cc::PointerResultType::kUnhandled;
3527   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
3528       .WillOnce(testing::Return(pointer_down_result));
3529 
3530   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
3531   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3532                                        input_handler_.get(), touch_start_));
3533 
3534   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3535       .WillOnce(testing::Return(kMainThreadScrollState));
3536   EXPECT_CALL(
3537       mock_input_handler_,
3538       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3539       .Times(1);
3540   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3541   EXPECT_EQ(expected_disposition_,
3542             HandleInputEventWithLatencyInfo(input_handler_.get(),
3543                                             gesture_scroll_begin_));
3544 
3545   EXPECT_THAT(
3546       histogram_tester().GetAllSamples(
3547           "Renderer4.MainThreadGestureScrollReason"),
3548       testing::ElementsAre(base::Bucket(
3549           GetBucketSample(
3550               cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
3551           1)));
3552 
3553   // Handle touch end event so that input handler proxy is out of the state of
3554   // DID_NOT_HANDLE.
3555   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3556   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3557   cc::InputHandlerPointerResult pointer_up_result;
3558   pointer_up_result.type = cc::PointerResultType::kUnhandled;
3559   EXPECT_CALL(mock_input_handler_, MouseUp(_))
3560       .WillOnce(testing::Return(pointer_up_result));
3561   EXPECT_EQ(expected_disposition_,
3562             HandleInputEventWithLatencyInfo(input_handler_.get(),
3563                                             gesture_scroll_end_));
3564 
3565   EXPECT_EQ(expected_disposition_,
3566             HandleInputEventWithLatencyInfo(input_handler_.get(), touch_end_));
3567 }
3568 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,GestureScrollHandlingScrollFromMainThread)3569 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3570        GestureScrollHandlingScrollFromMainThread) {
3571   // Gesture scrolling on main thread. We only record
3572   // HandlingScrollFromMainThread when it's the only available reason.
3573   SetupEvents(TestEventType::Touch);
3574   EXPECT_CALL(mock_input_handler_,
3575               EventListenerTypeForTouchStartOrMoveAt(
3576                   testing::Property(&gfx::Point::x, testing::Gt(0)), _))
3577       .WillOnce(testing::Return(
3578           cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
3579   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
3580       .WillOnce(testing::Return());
3581   EXPECT_CALL(mock_input_handler_, GetEventListenerProperties(_))
3582       .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
3583 
3584   cc::InputHandlerPointerResult pointer_down_result;
3585   pointer_down_result.type = cc::PointerResultType::kUnhandled;
3586   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
3587       .WillOnce(testing::Return(pointer_down_result));
3588 
3589   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
3590   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3591                                        input_handler_.get(), touch_start_));
3592 
3593   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3594       .WillOnce(testing::Return(kMainThreadScrollState));
3595   EXPECT_CALL(
3596       mock_input_handler_,
3597       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3598       .Times(1);
3599   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3600   EXPECT_EQ(expected_disposition_,
3601             HandleInputEventWithLatencyInfo(input_handler_.get(),
3602                                             gesture_scroll_begin_));
3603 
3604   EXPECT_THAT(
3605       histogram_tester().GetAllSamples(
3606           "Renderer4.MainThreadGestureScrollReason"),
3607       testing::ElementsAre(base::Bucket(
3608           GetBucketSample(
3609               cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
3610           1)));
3611 
3612   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3613   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3614   EXPECT_EQ(expected_disposition_,
3615             HandleInputEventWithLatencyInfo(input_handler_.get(),
3616                                             gesture_scroll_end_));
3617 }
3618 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollHistogram)3619 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest, WheelScrollHistogram) {
3620   // Firstly check if input handler can correctly record main thread scrolling
3621   // reasons.
3622   EXPECT_CALL(
3623       mock_input_handler_,
3624       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3625       .Times(1);
3626   input_handler_->RecordMainThreadScrollingReasonsForTest(
3627       WebGestureDevice::kTouchpad,
3628       cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects |
3629           cc::MainThreadScrollingReason::kThreadedScrollingDisabled |
3630           cc::MainThreadScrollingReason::kFrameOverlay |
3631           cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
3632 
3633   EXPECT_THAT(
3634       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3635       testing::ElementsAre(
3636           base::Bucket(
3637               GetBucketSample(cc::MainThreadScrollingReason::
3638                                   kHasBackgroundAttachmentFixedObjects),
3639               1),
3640           base::Bucket(
3641               GetBucketSample(
3642                   cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
3643               1),
3644           base::Bucket(
3645               GetBucketSample(cc::MainThreadScrollingReason::kFrameOverlay),
3646               1)));
3647 
3648   // We only want to record "Handling scroll from main thread" reason if it's
3649   // the only reason. If it's not the only reason, the "real" reason for
3650   // scrolling on main is something else, and we only want to pay attention to
3651   // that reason. So we should only include this reason in the histogram when
3652   // its on its own.
3653   EXPECT_CALL(
3654       mock_input_handler_,
3655       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3656       .Times(1);
3657   input_handler_->RecordMainThreadScrollingReasonsForTest(
3658       WebGestureDevice::kTouchpad,
3659       cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
3660 
3661   EXPECT_THAT(
3662       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3663       testing::ElementsAre(
3664           base::Bucket(
3665               GetBucketSample(cc::MainThreadScrollingReason::
3666                                   kHasBackgroundAttachmentFixedObjects),
3667               1),
3668           base::Bucket(
3669               GetBucketSample(
3670                   cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
3671               1),
3672           base::Bucket(
3673               GetBucketSample(cc::MainThreadScrollingReason::kFrameOverlay), 1),
3674           base::Bucket(
3675               GetBucketSample(
3676                   cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
3677               1)));
3678 }
3679 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollNotScrollingOnMain)3680 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3681        WheelScrollNotScrollingOnMain) {
3682   // Even if a scroller is composited, we still need to record its main thread
3683   // scrolling reason if it is blocked on a main thread event handler.
3684   SetupEvents(TestEventType::MouseWheel);
3685 
3686   // We can scroll on impl for an wheel event with passive event listener.
3687   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
3688       .WillRepeatedly(testing::Return(false));
3689   EXPECT_CALL(mock_input_handler_,
3690               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
3691       .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
3692   expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
3693   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3694                                        input_handler_.get(), wheel_event_));
3695 
3696   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3697       .WillOnce(testing::Return(kImplThreadScrollState));
3698   EXPECT_CALL(
3699       mock_input_handler_,
3700       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnCompositor))
3701       .Times(1);
3702   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3703   EXPECT_EQ(expected_disposition_,
3704             HandleInputEventWithLatencyInfo(input_handler_.get(),
3705                                             gesture_scroll_begin_));
3706 
3707   EXPECT_THAT(
3708       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3709       testing::ElementsAre(base::Bucket(
3710           GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
3711           1)));
3712 
3713   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3714   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3715   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3716   EXPECT_EQ(expected_disposition_,
3717             HandleInputEventWithLatencyInfo(input_handler_.get(),
3718                                             gesture_scroll_end_));
3719 }
3720 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollWheelEventHandlerRegion)3721 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3722        WheelScrollWheelEventHandlerRegion) {
3723   // Wheel event with blocking event listener. If there is a wheel event handler
3724   // at the point, we do not need to call GetEventListenerProperties since it
3725   // indicates kBlocking.
3726   SetupEvents(TestEventType::MouseWheel);
3727   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
3728       .WillRepeatedly(testing::Return(true));
3729   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3730   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3731                                        input_handler_.get(), wheel_event_));
3732 
3733   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3734       .WillOnce(testing::Return(kImplThreadScrollState));
3735   EXPECT_CALL(
3736       mock_input_handler_,
3737       RecordScrollBegin(
3738           _, cc::ScrollBeginThreadState::kScrollingOnCompositorBlockedOnMain))
3739       .Times(1);
3740   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3741   EXPECT_EQ(expected_disposition_,
3742             HandleInputEventWithLatencyInfo(input_handler_.get(),
3743                                             gesture_scroll_begin_));
3744 
3745   EXPECT_THAT(
3746       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3747       testing::ElementsAre(base::Bucket(
3748           GetBucketSample(
3749               cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
3750           1)));
3751 
3752   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3753   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3754   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3755   EXPECT_EQ(expected_disposition_,
3756             HandleInputEventWithLatencyInfo(input_handler_.get(),
3757                                             gesture_scroll_end_));
3758 }
3759 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollWheelEventHandlerRegionAndHandlingScrollFromMainThread)3760 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3761        WheelScrollWheelEventHandlerRegionAndHandlingScrollFromMainThread) {
3762   // Wheel scrolling on main thread. Because we also block scrolling with wheel
3763   // event handler, we should record that reason as well.
3764   SetupEvents(TestEventType::MouseWheel);
3765   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
3766       .WillRepeatedly(testing::Return(true));
3767   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3768   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3769                                        input_handler_.get(), wheel_event_));
3770 
3771   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3772       .WillOnce(testing::Return(kMainThreadScrollState));
3773   EXPECT_CALL(
3774       mock_input_handler_,
3775       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3776       .Times(1);
3777   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3778   EXPECT_EQ(expected_disposition_,
3779             HandleInputEventWithLatencyInfo(input_handler_.get(),
3780                                             gesture_scroll_begin_));
3781 
3782   EXPECT_THAT(
3783       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3784       testing::ElementsAre(base::Bucket(
3785           GetBucketSample(
3786               cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
3787           1)));
3788 
3789   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3790   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3791   EXPECT_EQ(expected_disposition_,
3792             HandleInputEventWithLatencyInfo(input_handler_.get(),
3793                                             gesture_scroll_end_));
3794 }
3795 
TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,WheelScrollHandlingScrollFromMainThread)3796 TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
3797        WheelScrollHandlingScrollFromMainThread) {
3798   // Gesture scrolling on main thread. We only record
3799   // HandlingScrollFromMainThread when it's the only available reason.
3800   SetupEvents(TestEventType::MouseWheel);
3801   EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(_))
3802       .WillRepeatedly(testing::Return(false));
3803   EXPECT_CALL(mock_input_handler_,
3804               GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
3805       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
3806   expected_disposition_ = InputHandlerProxy::DROP_EVENT;
3807   EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(
3808                                        input_handler_.get(), wheel_event_));
3809 
3810   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3811       .WillOnce(testing::Return(kMainThreadScrollState));
3812   EXPECT_CALL(
3813       mock_input_handler_,
3814       RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain))
3815       .Times(1);
3816   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3817   EXPECT_EQ(expected_disposition_,
3818             HandleInputEventWithLatencyInfo(input_handler_.get(),
3819                                             gesture_scroll_begin_));
3820 
3821   EXPECT_THAT(
3822       histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
3823       testing::ElementsAre(base::Bucket(
3824           GetBucketSample(
3825               cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
3826           1)));
3827 
3828   expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
3829   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3830   EXPECT_EQ(expected_disposition_,
3831             HandleInputEventWithLatencyInfo(input_handler_.get(),
3832                                             gesture_scroll_end_));
3833 }
3834 
3835 class InputHandlerProxyTouchScrollbarTest : public InputHandlerProxyTest {
3836  public:
SetupEvents()3837   void SetupEvents() {
3838     touch_start_ = WebTouchEvent(WebInputEvent::Type::kTouchStart,
3839                                  WebInputEvent::kNoModifiers,
3840                                  WebInputEvent::GetStaticTimeStampForTests());
3841     touch_end_ = WebTouchEvent(WebInputEvent::Type::kTouchEnd,
3842                                WebInputEvent::kNoModifiers,
3843                                WebInputEvent::GetStaticTimeStampForTests());
3844     touch_start_.touches_length = 1;
3845     touch_start_.touch_start_or_first_touch_move = true;
3846     touch_start_.touches[0] =
3847         CreateWebTouchPoint(WebTouchPoint::State::kStatePressed, 10, 10);
3848 
3849     touch_end_.touches_length = 1;
3850   }
3851 
3852  protected:
3853   WebTouchEvent touch_start_;
3854   WebTouchEvent touch_end_;
3855 };
3856 
TEST_P(InputHandlerProxyTouchScrollbarTest,TouchOnScrollbarIsHandledByCompositorThread)3857 TEST_P(InputHandlerProxyTouchScrollbarTest,
3858        TouchOnScrollbarIsHandledByCompositorThread) {
3859   // The touch event hits a touch event handler that is acked from the
3860   // compositor thread.
3861   SetupEvents();
3862   cc::InputHandlerPointerResult pointer_down_result;
3863   pointer_down_result.type = cc::PointerResultType::kScrollbarScroll;
3864   pointer_down_result.scroll_offset = gfx::ScrollOffset(0, 1);
3865   cc::InputHandlerPointerResult pointer_up_result;
3866   pointer_up_result.type = cc::PointerResultType::kScrollbarScroll;
3867 
3868   EXPECT_CALL(mock_input_handler_,
3869               EventListenerTypeForTouchStartOrMoveAt(
3870                   testing::Property(&gfx::Point::x, testing::Eq(10)), _))
3871       .WillOnce(testing::Invoke([](const gfx::Point&,
3872                                    cc::TouchAction* touch_action) {
3873         *touch_action = cc::TouchAction::kAuto;
3874         return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
3875       }));
3876   EXPECT_CALL(
3877       mock_input_handler_,
3878       GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
3879       .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
3880 
3881   EXPECT_CALL(mock_client_, SetAllowedTouchAction(_, _, _))
3882       .WillOnce(testing::Return());
3883 
3884   EXPECT_CALL(mock_input_handler_, MouseDown(_, _))
3885       .WillOnce(testing::Return(pointer_down_result));
3886   cc::InputHandlerScrollResult scroll_result_did_scroll;
3887   scroll_result_did_scroll.did_scroll = true;
3888   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3889 
3890   if (!base::FeatureList::IsEnabled(features::kScrollUnification)) {
3891     EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread())
3892         .WillOnce(testing::Return(false));
3893   }
3894   EXPECT_CALL(
3895       mock_input_handler_,
3896       RecordScrollBegin(ui::ScrollInputType::kScrollbar,
3897                         cc::ScrollBeginThreadState::kScrollingOnCompositor))
3898       .Times(1);
3899   EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _))
3900       .WillOnce(testing::Return(kImplThreadScrollState));
3901   EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _))
3902       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
3903   EXPECT_CALL(mock_input_handler_, MouseUp(_))
3904       .WillOnce(testing::Return(pointer_up_result));
3905 
3906   EXPECT_EQ(expected_disposition_,
3907             HandleInputEventAndFlushEventQueue(
3908                 mock_input_handler_, input_handler_.get(), touch_start_));
3909 
3910   EXPECT_CALL(mock_input_handler_, ScrollEnd(true));
3911   EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1);
3912   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
3913   EXPECT_EQ(expected_disposition_,
3914             HandleInputEventAndFlushEventQueue(
3915                 mock_input_handler_, input_handler_.get(), touch_end_));
3916 }
3917 
3918 class InputHandlerProxyMomentumScrollJankTest : public testing::Test {
3919  public:
InputHandlerProxyMomentumScrollJankTest()3920   InputHandlerProxyMomentumScrollJankTest()
3921       : input_handler_proxy_(mock_input_handler_, &mock_client_) {
3922     tick_clock_.SetNowTicks(base::TimeTicks::Now());
3923     // Disable scroll predictor for this test.
3924     input_handler_proxy_.scroll_predictor_ = nullptr;
3925     input_handler_proxy_.SetTickClockForTesting(&tick_clock_);
3926   }
3927 
3928   ~InputHandlerProxyMomentumScrollJankTest() = default;
3929 
HandleScrollBegin()3930   void HandleScrollBegin() {
3931     auto gesture = std::make_unique<WebGestureEvent>(
3932         WebInputEvent::Type::kGestureScrollBegin, WebInputEvent::kNoModifiers,
3933         tick_clock_.NowTicks(), WebGestureDevice::kTouchscreen);
3934     HandleGesture(std::move(gesture));
3935   }
3936 
HandleScrollEnd()3937   void HandleScrollEnd() {
3938     auto gesture = std::make_unique<WebGestureEvent>(
3939         WebInputEvent::Type::kGestureScrollEnd, WebInputEvent::kNoModifiers,
3940         tick_clock_.NowTicks(), WebGestureDevice::kTouchscreen);
3941     HandleGesture(std::move(gesture));
3942   }
3943 
HandleScrollUpdate(bool is_momentum)3944   void HandleScrollUpdate(bool is_momentum) {
3945     auto gesture = std::make_unique<WebGestureEvent>(
3946         WebInputEvent::Type::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
3947         tick_clock_.NowTicks(), WebGestureDevice::kTouchscreen);
3948     gesture->data.scroll_update.delta_y = -20;
3949     if (is_momentum) {
3950       gesture->data.scroll_update.inertial_phase =
3951           WebGestureEvent::InertialPhaseState::kMomentum;
3952     }
3953     HandleGesture(std::move(gesture));
3954   }
3955 
AdvanceClock(uint32_t milliseconds)3956   void AdvanceClock(uint32_t milliseconds) {
3957     tick_clock_.Advance(base::TimeDelta::FromMilliseconds(milliseconds));
3958   }
3959 
AddNonJankyEvents(uint32_t count)3960   void AddNonJankyEvents(uint32_t count) {
3961     for (uint32_t i = 0; i < count; ++i) {
3962       AdvanceClock(16);
3963       HandleScrollUpdate(true /* is_momentum */);
3964       DeliverInputForBeginFrame();
3965     }
3966   }
3967 
DeliverInputForBeginFrame()3968   void DeliverInputForBeginFrame() {
3969     constexpr base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
3970     base::TimeTicks frame_time =
3971         base::TimeTicks() +
3972         (next_begin_frame_number_ - viz::BeginFrameArgs::kStartingFrameNumber) *
3973             interval;
3974     input_handler_proxy_.DeliverInputForBeginFrame(viz::BeginFrameArgs::Create(
3975         BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, frame_time,
3976         frame_time + interval, interval, viz::BeginFrameArgs::NORMAL));
3977   }
3978 
3979  protected:
HandleGesture(std::unique_ptr<WebInputEvent> event)3980   void HandleGesture(std::unique_ptr<WebInputEvent> event) {
3981     input_handler_proxy_.HandleInputEventWithLatencyInfo(
3982         std::make_unique<WebCoalescedInputEvent>(std::move(event),
3983                                                  ui::LatencyInfo()),
3984         nullptr, base::DoNothing());
3985   }
3986 
3987   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
3988 
3989   testing::NiceMock<MockInputHandler> mock_input_handler_;
3990   testing::NiceMock<MockInputHandlerProxyClient> mock_client_;
3991   TestInputHandlerProxy input_handler_proxy_;
3992   base::SimpleTestTickClock tick_clock_;
3993 };
3994 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJank)3995 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJank) {
3996   cc::InputHandlerScrollResult scroll_result_did_scroll;
3997   scroll_result_did_scroll.did_scroll = true;
3998   EXPECT_CALL(
3999       mock_input_handler_,
4000       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4001                    _))
4002       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4003 
4004   base::HistogramTester histogram_tester;
4005   HandleScrollBegin();
4006 
4007   // Flush one update, the first update is always ignored.
4008   AdvanceClock(16);
4009   HandleScrollUpdate(true /* is_momentum */);
4010   DeliverInputForBeginFrame();
4011 
4012   // Enqueue three updates, they will be coalesced and count as two janks.
4013   AdvanceClock(16);
4014   HandleScrollUpdate(true /* is_momentum */);
4015   AdvanceClock(16);
4016   HandleScrollUpdate(true /* is_momentum */);
4017   AdvanceClock(16);
4018   HandleScrollUpdate(true /* is_momentum */);
4019   AdvanceClock(1);
4020   DeliverInputForBeginFrame();
4021 
4022   // Enqueue two updates, they will be coalesced and count as one jank
4023   // (https://crbug.com/952930).
4024   AdvanceClock(16);
4025   HandleScrollUpdate(true /* is_momentum */);
4026   AdvanceClock(16);
4027   HandleScrollUpdate(true /* is_momentum */);
4028   AdvanceClock(1);
4029   DeliverInputForBeginFrame();
4030 
4031   // Enqueue two updates, they will be coalesced and count as one
4032   // jank(https://crbug.com/952930).
4033   AdvanceClock(16);
4034   HandleScrollUpdate(true /* is_momentum */);
4035   AdvanceClock(16);
4036   HandleScrollUpdate(true /* is_momentum */);
4037   AdvanceClock(1);
4038   DeliverInputForBeginFrame();
4039 
4040   // Add 93 non-janky events, bringing us to a total of 100 events.
4041   AddNonJankyEvents(93);
4042 
4043   HandleScrollEnd();
4044   DeliverInputForBeginFrame();
4045 
4046   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
4047                                       4, 1);
4048 }
4049 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJankMultipleGestures)4050 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJankMultipleGestures) {
4051   cc::InputHandlerScrollResult scroll_result_did_scroll;
4052   scroll_result_did_scroll.did_scroll = true;
4053   EXPECT_CALL(
4054       mock_input_handler_,
4055       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4056                    _))
4057       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4058 
4059   base::HistogramTester histogram_tester;
4060 
4061   for (int i = 0; i < 3; ++i) {
4062     HandleScrollBegin();
4063 
4064     // Flush one update, the first update is always ignored.
4065     AdvanceClock(16);
4066     HandleScrollUpdate(true /* is_momentum */);
4067     DeliverInputForBeginFrame();
4068 
4069     // Enqueue two updates, they will be coalesced and count as one jank
4070     // (https://crbug.com/952930).
4071     AdvanceClock(16);
4072     HandleScrollUpdate(true /* is_momentum */);
4073     AdvanceClock(16);
4074     HandleScrollUpdate(true /* is_momentum */);
4075     AdvanceClock(1);
4076     DeliverInputForBeginFrame();
4077 
4078     // Add 98 non-janky events, bringing us to a total of 100 events.
4079     AddNonJankyEvents(98);
4080 
4081     HandleScrollEnd();
4082     DeliverInputForBeginFrame();
4083 
4084     histogram_tester.ExpectUniqueSample(
4085         "Renderer4.MomentumScrollJankPercentage", 1, i + 1);
4086   }
4087 }
4088 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestJankRounding)4089 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestJankRounding) {
4090   cc::InputHandlerScrollResult scroll_result_did_scroll;
4091   scroll_result_did_scroll.did_scroll = true;
4092   EXPECT_CALL(
4093       mock_input_handler_,
4094       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4095                    _))
4096       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4097 
4098   base::HistogramTester histogram_tester;
4099 
4100   HandleScrollBegin();
4101 
4102   // Flush one update, the first update is always ignored.
4103   AdvanceClock(16);
4104   HandleScrollUpdate(true /* is_momentum */);
4105   DeliverInputForBeginFrame();
4106 
4107   // Enqueue two updates, they will be coalesced and count as one jank
4108   // (https://crbug.com/952930).
4109   AdvanceClock(16);
4110   HandleScrollUpdate(true /* is_momentum */);
4111   AdvanceClock(16);
4112   HandleScrollUpdate(true /* is_momentum */);
4113   AdvanceClock(1);
4114   DeliverInputForBeginFrame();
4115 
4116   // Add 500 non-janky events. Even with this many events, our round-up logic
4117   // should cause us to report 1% jank.
4118   AddNonJankyEvents(500);
4119 
4120   HandleScrollEnd();
4121   DeliverInputForBeginFrame();
4122 
4123   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
4124                                       1, 1);
4125 }
4126 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestSimpleNoJank)4127 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestSimpleNoJank) {
4128   cc::InputHandlerScrollResult scroll_result_did_scroll;
4129   scroll_result_did_scroll.did_scroll = true;
4130   EXPECT_CALL(
4131       mock_input_handler_,
4132       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4133                    _))
4134       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4135 
4136   base::HistogramTester histogram_tester;
4137   HandleScrollBegin();
4138 
4139   // Flush one update, the first update is always ignored.
4140   AdvanceClock(16);
4141   HandleScrollUpdate(true /* is_momentum */);
4142   AdvanceClock(1);
4143   DeliverInputForBeginFrame();
4144 
4145   // Enqueue one updates, no jank.
4146   AdvanceClock(16);
4147   HandleScrollUpdate(true /* is_momentum */);
4148   AdvanceClock(1);
4149   DeliverInputForBeginFrame();
4150 
4151   // Enqueue one updates, no jank.
4152   AdvanceClock(16);
4153   HandleScrollUpdate(true /* is_momentum */);
4154   AdvanceClock(1);
4155   DeliverInputForBeginFrame();
4156 
4157   HandleScrollEnd();
4158   DeliverInputForBeginFrame();
4159 
4160   histogram_tester.ExpectUniqueSample("Renderer4.MomentumScrollJankPercentage",
4161                                       0, 1);
4162 }
4163 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestFirstGestureNoJank)4164 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestFirstGestureNoJank) {
4165   cc::InputHandlerScrollResult scroll_result_did_scroll;
4166   scroll_result_did_scroll.did_scroll = true;
4167   EXPECT_CALL(
4168       mock_input_handler_,
4169       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4170                    _))
4171       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4172 
4173   base::HistogramTester histogram_tester;
4174   HandleScrollBegin();
4175 
4176   // Even with 3 coalesced frames, the first gesture should not trigger a jank.
4177   AdvanceClock(16);
4178   HandleScrollUpdate(true /* is_momentum */);
4179   AdvanceClock(16);
4180   HandleScrollUpdate(true /* is_momentum */);
4181   AdvanceClock(16);
4182   HandleScrollUpdate(true /* is_momentum */);
4183   AdvanceClock(1);
4184   DeliverInputForBeginFrame();
4185 
4186   HandleScrollEnd();
4187   DeliverInputForBeginFrame();
4188 
4189   histogram_tester.ExpectTotalCount("Renderer4.MomentumScrollJankPercentage",
4190                                     0);
4191 }
4192 
TEST_F(InputHandlerProxyMomentumScrollJankTest,TestNonMomentumNoJank)4193 TEST_F(InputHandlerProxyMomentumScrollJankTest, TestNonMomentumNoJank) {
4194   cc::InputHandlerScrollResult scroll_result_did_scroll;
4195   scroll_result_did_scroll.did_scroll = true;
4196   EXPECT_CALL(
4197       mock_input_handler_,
4198       ScrollUpdate(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)),
4199                    _))
4200       .WillRepeatedly(testing::Return(scroll_result_did_scroll));
4201 
4202   base::HistogramTester histogram_tester;
4203   HandleScrollBegin();
4204 
4205   // Flush one update, the first update is always ignored.
4206   AdvanceClock(16);
4207   HandleScrollUpdate(false /* is_momentum */);
4208   AdvanceClock(1);
4209   DeliverInputForBeginFrame();
4210 
4211   // Enqueue three updates, these will not cause jank, as none are momentum.
4212   AdvanceClock(16);
4213   HandleScrollUpdate(false /* is_momentum */);
4214   AdvanceClock(16);
4215   HandleScrollUpdate(false /* is_momentum */);
4216   AdvanceClock(16);
4217   HandleScrollUpdate(false /* is_momentum */);
4218   AdvanceClock(1);
4219   DeliverInputForBeginFrame();
4220 
4221   HandleScrollEnd();
4222   DeliverInputForBeginFrame();
4223 
4224   histogram_tester.ExpectTotalCount("Renderer4.MomentumScrollJankPercentage",
4225                                     0);
4226 }
4227 
4228 const auto kTestCombinations = testing::Combine(
4229     testing::Values(ScrollerType::kRoot, ScrollerType::kChild),
4230     testing::Values(HandlerType::kNormal, HandlerType::kSynchronous),
4231     testing::Values(ScrollUnification::kEnabled, ScrollUnification::kDisabled));
4232 
4233 const auto kSuffixGenerator =
4234     [](const testing::TestParamInfo<
__anon8a50c1ea0d02(const testing::TestParamInfo< std::tuple<ScrollerType, HandlerType, ScrollUnification>>& info) 4235         std::tuple<ScrollerType, HandlerType, ScrollUnification>>& info) {
4236       std::string name = std::get<1>(info.param) == HandlerType::kSynchronous
4237                              ? "Synchronous"
4238                              : "";
4239       name += std::get<0>(info.param) == ScrollerType::kRoot ? "Root" : "Child";
4240       name += std::get<2>(info.param) == ScrollUnification::kEnabled
4241                   ? "UnifiedScroll"
4242                   : "LegacyScroll";
4243       return name;
4244     };
4245 
4246 INSTANTIATE_TEST_SUITE_P(All,
4247                          InputHandlerProxyTest,
4248                          kTestCombinations,
4249                          kSuffixGenerator);
4250 
4251 INSTANTIATE_TEST_SUITE_P(All,
4252                          InputHandlerProxyMainThreadScrollingReasonTest,
4253                          kTestCombinations,
4254                          kSuffixGenerator);
4255 
4256 INSTANTIATE_TEST_SUITE_P(All,
4257                          InputHandlerProxyTouchScrollbarTest,
4258                          kTestCombinations,
4259                          kSuffixGenerator);
4260 
4261 }  // namespace test
4262 }  // namespace blink
4263