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