1 // Copyright 2016 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 <stddef.h>
6 
7 #include <new>
8 #include <tuple>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/auto_reset.h"
13 #include "base/bind.h"
14 #include "base/macros.h"
15 #include "base/strings/string_util.h"
16 #include "base/test/test_simple_task_runner.h"
17 #include "build/build_config.h"
18 #include "cc/metrics/event_metrics.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
21 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
22 #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
23 #include "third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h"
24 #include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
25 
26 namespace blink {
27 namespace {
28 
29 // Simulate a 16ms frame signal.
30 const base::TimeDelta kFrameInterval = base::TimeDelta::FromMilliseconds(16);
31 
Equal(const WebTouchEvent & lhs,const WebTouchEvent & rhs)32 bool Equal(const WebTouchEvent& lhs, const WebTouchEvent& rhs) {
33   auto tie = [](const WebTouchEvent& e) {
34     return std::make_tuple(
35         e.touches_length, e.dispatch_type, e.moved_beyond_slop_region,
36         e.hovering, e.touch_start_or_first_touch_move, e.unique_touch_event_id,
37         e.GetType(), e.TimeStamp(), e.FrameScale(), e.FrameTranslate(),
38         e.GetModifiers());
39   };
40   if (tie(lhs) != tie(rhs))
41     return false;
42 
43   for (unsigned i = 0; i < lhs.touches_length; ++i) {
44     auto touch_tie = [](const blink::WebTouchPoint& e) {
45       return std::make_tuple(e.state, e.radius_x, e.radius_y, e.rotation_angle,
46                              e.id, e.tilt_x, e.tilt_y, e.tangential_pressure,
47                              e.twist, e.button, e.pointer_type, e.movement_x,
48                              e.movement_y, e.is_raw_movement_event,
49                              e.PositionInWidget(), e.PositionInScreen());
50     };
51 
52     if (touch_tie(lhs.touches[i]) != touch_tie(rhs.touches[i]) ||
53         (!std::isnan(lhs.touches[i].force) &&
54          !std::isnan(rhs.touches[i].force) &&
55          lhs.touches[i].force != rhs.touches[i].force))
56       return false;
57   }
58 
59   return true;
60 }
61 
Equal(const WebMouseWheelEvent & lhs,const WebMouseWheelEvent & rhs)62 bool Equal(const WebMouseWheelEvent& lhs, const WebMouseWheelEvent& rhs) {
63   auto tie = [](const WebMouseWheelEvent& e) {
64     return std::make_tuple(
65         e.delta_x, e.delta_y, e.wheel_ticks_x, e.wheel_ticks_y,
66         e.acceleration_ratio_x, e.acceleration_ratio_y, e.phase,
67         e.momentum_phase, e.rails_mode, e.dispatch_type, e.event_action,
68         e.has_synthetic_phase, e.delta_units, e.click_count, e.menu_source_type,
69         e.id, e.button, e.movement_x, e.movement_y, e.is_raw_movement_event,
70         e.GetType(), e.TimeStamp(), e.FrameScale(), e.FrameTranslate(),
71         e.GetModifiers(), e.PositionInWidget(), e.PositionInScreen());
72   };
73   return tie(lhs) == tie(rhs);
74 }
75 
76 }  // namespace
77 
78 class HandledTask {
79  public:
80   virtual ~HandledTask() = default;
81 
82   virtual blink::WebCoalescedInputEvent* taskAsEvent() = 0;
83   virtual unsigned taskAsClosure() const = 0;
84 };
85 
86 class HandledEvent : public HandledTask {
87  public:
HandledEvent(const blink::WebCoalescedInputEvent & event)88   explicit HandledEvent(const blink::WebCoalescedInputEvent& event)
89       : event_(event) {}
90   ~HandledEvent() override = default;
91 
taskAsEvent()92   blink::WebCoalescedInputEvent* taskAsEvent() override { return &event_; }
taskAsClosure() const93   unsigned taskAsClosure() const override {
94     NOTREACHED();
95     return 0;
96   }
97 
98  private:
99   blink::WebCoalescedInputEvent event_;
100 };
101 
102 class HandledClosure : public HandledTask {
103  public:
HandledClosure(unsigned closure_id)104   explicit HandledClosure(unsigned closure_id) : closure_id_(closure_id) {}
105   ~HandledClosure() override = default;
106 
taskAsEvent()107   blink::WebCoalescedInputEvent* taskAsEvent() override {
108     NOTREACHED();
109     return nullptr;
110   }
taskAsClosure() const111   unsigned taskAsClosure() const override { return closure_id_; }
112 
113  private:
114   unsigned closure_id_;
115 };
116 
117 enum class CallbackReceivedState {
118   kPending,
119   kCalledWhileHandlingEvent,
120   kCalledAfterHandleEvent,
121 };
122 
123 class ReceivedCallback {
124  public:
ReceivedCallback()125   ReceivedCallback()
126       : ReceivedCallback(CallbackReceivedState::kPending, false) {}
127 
ReceivedCallback(CallbackReceivedState state,bool coalesced_latency)128   ReceivedCallback(CallbackReceivedState state, bool coalesced_latency)
129       : state_(state), coalesced_latency_(coalesced_latency) {}
operator ==(const ReceivedCallback & other) const130   bool operator==(const ReceivedCallback& other) const {
131     return state_ == other.state_ &&
132            coalesced_latency_ == other.coalesced_latency_;
133   }
134 
135  private:
136   CallbackReceivedState state_;
137   bool coalesced_latency_;
138 };
139 
140 class HandledEventCallbackTracker {
141  public:
HandledEventCallbackTracker()142   HandledEventCallbackTracker() : handling_event_(false) {
143     weak_this_ = weak_ptr_factory_.GetWeakPtr();
144   }
145 
GetCallback()146   HandledEventCallback GetCallback() {
147     callbacks_received_.push_back(ReceivedCallback());
148     HandledEventCallback callback =
149         base::BindOnce(&HandledEventCallbackTracker::DidHandleEvent, weak_this_,
150                        callbacks_received_.size() - 1);
151     return callback;
152   }
153 
DidHandleEvent(size_t index,blink::mojom::InputEventResultState ack_result,const ui::LatencyInfo & latency,mojom::blink::DidOverscrollParamsPtr params,base::Optional<cc::TouchAction> touch_action)154   void DidHandleEvent(size_t index,
155                       blink::mojom::InputEventResultState ack_result,
156                       const ui::LatencyInfo& latency,
157                       mojom::blink::DidOverscrollParamsPtr params,
158                       base::Optional<cc::TouchAction> touch_action) {
159     callbacks_received_[index] = ReceivedCallback(
160         handling_event_ ? CallbackReceivedState::kCalledWhileHandlingEvent
161                         : CallbackReceivedState::kCalledAfterHandleEvent,
162         latency.coalesced());
163   }
164 
GetReceivedCallbacks() const165   const std::vector<ReceivedCallback>& GetReceivedCallbacks() const {
166     return callbacks_received_;
167   }
168 
169   bool handling_event_;
170 
171  private:
172   std::vector<ReceivedCallback> callbacks_received_;
173   base::WeakPtr<HandledEventCallbackTracker> weak_this_;
174   base::WeakPtrFactory<HandledEventCallbackTracker> weak_ptr_factory_{this};
175 };
176 
177 class MainThreadEventQueueTest : public testing::Test,
178                                  public MainThreadEventQueueClient {
179  public:
MainThreadEventQueueTest()180   MainThreadEventQueueTest()
181       : main_task_runner_(new base::TestSimpleTaskRunner()) {
182     handler_callback_ = std::make_unique<HandledEventCallbackTracker>();
183   }
184 
SetUp()185   void SetUp() override {
186     queue_ = new MainThreadEventQueue(this, main_task_runner_,
187                                       &thread_scheduler_, true);
188     queue_->ClearRafFallbackTimerForTesting();
189   }
190 
HandleEvent(WebInputEvent & event,blink::mojom::InputEventResultState ack_result)191   void HandleEvent(WebInputEvent& event,
192                    blink::mojom::InputEventResultState ack_result) {
193     base::AutoReset<bool> in_handle_event(&handler_callback_->handling_event_,
194                                           true);
195     queue_->HandleEvent(std::make_unique<blink::WebCoalescedInputEvent>(
196                             event.Clone(), ui::LatencyInfo()),
197                         MainThreadEventQueue::DispatchType::kBlocking,
198                         ack_result, blink::WebInputEventAttribution(), nullptr,
199                         handler_callback_->GetCallback());
200   }
201 
RunClosure(unsigned closure_id)202   void RunClosure(unsigned closure_id) {
203     auto closure = std::make_unique<HandledClosure>(closure_id);
204     handled_tasks_.push_back(std::move(closure));
205   }
206 
QueueClosure()207   void QueueClosure() {
208     unsigned closure_id = ++closure_count_;
209     queue_->QueueClosure(base::BindOnce(&MainThreadEventQueueTest::RunClosure,
210                                         base::Unretained(this), closure_id));
211   }
212 
event_queue()213   MainThreadEventQueueTaskList& event_queue() {
214     return queue_->shared_state_.events_;
215   }
216 
needs_low_latency_until_pointer_up()217   bool needs_low_latency_until_pointer_up() {
218     return queue_->needs_low_latency_until_pointer_up_;
219   }
220 
last_touch_start_forced_nonblocking_due_to_fling()221   bool last_touch_start_forced_nonblocking_due_to_fling() {
222     return queue_->last_touch_start_forced_nonblocking_due_to_fling_;
223   }
224 
RunPendingTasksWithSimulatedRaf()225   void RunPendingTasksWithSimulatedRaf() {
226     while (needs_main_frame_ || main_task_runner_->HasPendingTask()) {
227       main_task_runner_->RunUntilIdle();
228       needs_main_frame_ = false;
229       frame_time_ += kFrameInterval;
230       queue_->DispatchRafAlignedInput(frame_time_);
231     }
232   }
233 
RunSimulatedRafOnce()234   void RunSimulatedRafOnce() {
235     if (needs_main_frame_) {
236       needs_main_frame_ = false;
237       frame_time_ += kFrameInterval;
238       queue_->DispatchRafAlignedInput(frame_time_);
239     }
240   }
241 
242   // MainThreadEventQueueClient overrides.
HandleInputEvent(const blink::WebCoalescedInputEvent & event,std::unique_ptr<cc::EventMetrics> metrics,HandledEventCallback callback)243   bool HandleInputEvent(const blink::WebCoalescedInputEvent& event,
244                         std::unique_ptr<cc::EventMetrics> metrics,
245                         HandledEventCallback callback) override {
246     if (!handle_input_event_)
247       return false;
248     auto handled_event = std::make_unique<HandledEvent>(event);
249     handled_tasks_.push_back(std::move(handled_event));
250     std::move(callback).Run(blink::mojom::InputEventResultState::kNotConsumed,
251                             event.latency_info(), nullptr, base::nullopt);
252     return true;
253   }
SetNeedsMainFrame()254   void SetNeedsMainFrame() override { needs_main_frame_ = true; }
255 
GetAndResetCallbackResults()256   std::vector<ReceivedCallback> GetAndResetCallbackResults() {
257     std::unique_ptr<HandledEventCallbackTracker> callback =
258         std::make_unique<HandledEventCallbackTracker>();
259     handler_callback_.swap(callback);
260     return callback->GetReceivedCallbacks();
261   }
262 
set_handle_input_event(bool handle)263   void set_handle_input_event(bool handle) { handle_input_event_ = handle; }
264 
265  protected:
266   scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
267   blink::scheduler::WebMockThreadScheduler thread_scheduler_;
268   scoped_refptr<MainThreadEventQueue> queue_;
269   std::vector<std::unique_ptr<HandledTask>> handled_tasks_;
270   std::unique_ptr<HandledEventCallbackTracker> handler_callback_;
271 
272   bool needs_main_frame_ = false;
273   bool handle_input_event_ = true;
274   base::TimeTicks frame_time_;
275   unsigned closure_count_ = 0;
276 };
277 
TEST_F(MainThreadEventQueueTest,ClientDoesntHandleInputEvent)278 TEST_F(MainThreadEventQueueTest, ClientDoesntHandleInputEvent) {
279   // Prevent MainThreadEventQueueClient::HandleInputEvent() from handling the
280   // event, and have it return false. Then the MainThreadEventQueue should
281   // call the handled callback.
282   set_handle_input_event(false);
283 
284   // The blocking event used in this test is reported to the scheduler.
285   EXPECT_CALL(thread_scheduler_,
286               DidHandleInputEventOnMainThread(testing::_, testing::_))
287       .Times(1);
288 
289   // Inject and try to dispatch an input event. This event is not considered
290   // "non-blocking" which means the reply callback gets stored with the queued
291   // event, and will be run when we work through the queue.
292   SyntheticWebTouchEvent event;
293   event.PressPoint(10, 10);
294   event.MovePoint(0, 20, 20);
295   WebMouseWheelEvent event2 = SyntheticWebMouseWheelEventBuilder::Build(
296       10, 10, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel);
297   HandleEvent(event2, blink::mojom::InputEventResultState::kNotConsumed);
298   RunPendingTasksWithSimulatedRaf();
299 
300   std::vector<ReceivedCallback> received = GetAndResetCallbackResults();
301   // We didn't handle the event in the client method.
302   EXPECT_EQ(handled_tasks_.size(), 0u);
303   // There's 1 reply callback for our 1 event.
304   EXPECT_EQ(received.size(), 1u);
305   // The event was queued and disaptched, then the callback was run when
306   // the client failed to handle it. If this fails, the callback was run
307   // by HandleEvent() without dispatching it (kCalledWhileHandlingEvent)
308   // or was not called at all (kPending).
309   EXPECT_THAT(received,
310               testing::Each(ReceivedCallback(
311                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
312 }
313 
TEST_F(MainThreadEventQueueTest,NonBlockingWheel)314 TEST_F(MainThreadEventQueueTest, NonBlockingWheel) {
315   WebMouseWheelEvent kEvents[4] = {
316       SyntheticWebMouseWheelEventBuilder::Build(
317           10, 10, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
318       SyntheticWebMouseWheelEventBuilder::Build(
319           20, 20, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
320       SyntheticWebMouseWheelEventBuilder::Build(
321           30, 30, 0, 53, 1, ui::ScrollGranularity::kScrollByPixel),
322       SyntheticWebMouseWheelEventBuilder::Build(
323           30, 30, 0, 53, 1, ui::ScrollGranularity::kScrollByPixel),
324   };
325 
326   EXPECT_FALSE(main_task_runner_->HasPendingTask());
327   EXPECT_EQ(0u, event_queue().size());
328 
329   EXPECT_CALL(thread_scheduler_,
330               DidHandleInputEventOnMainThread(testing::_, testing::_))
331       .Times(0);
332 
333   for (WebMouseWheelEvent& event : kEvents)
334     HandleEvent(event, blink::mojom::InputEventResultState::kSetNonBlocking);
335 
336   EXPECT_EQ(2u, event_queue().size());
337   EXPECT_FALSE(main_task_runner_->HasPendingTask());
338   RunPendingTasksWithSimulatedRaf();
339   EXPECT_THAT(GetAndResetCallbackResults(),
340               testing::Each(ReceivedCallback(
341                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
342   EXPECT_FALSE(main_task_runner_->HasPendingTask());
343   EXPECT_EQ(0u, event_queue().size());
344   EXPECT_EQ(2u, handled_tasks_.size());
345   for (const auto& task : handled_tasks_) {
346     EXPECT_EQ(2u, task->taskAsEvent()->CoalescedEventSize());
347   }
348 
349   {
350     EXPECT_EQ(kEvents[0].GetType(),
351               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
352     const WebMouseWheelEvent* last_wheel_event =
353         static_cast<const WebMouseWheelEvent*>(
354             handled_tasks_.at(0)->taskAsEvent()->EventPointer());
355     EXPECT_EQ(WebInputEvent::DispatchType::kListenersNonBlockingPassive,
356               last_wheel_event->dispatch_type);
357     WebMouseWheelEvent coalesced_event = kEvents[0];
358     coalesced_event.Coalesce(kEvents[1]);
359     coalesced_event.dispatch_type =
360         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
361     EXPECT_TRUE(Equal(coalesced_event, *last_wheel_event));
362   }
363 
364   {
365     WebMouseWheelEvent coalesced_event = kEvents[0];
366     const auto& coalesced_events =
367         handled_tasks_[0]->taskAsEvent()->GetCoalescedEventsPointers();
368     const WebMouseWheelEvent* coalesced_wheel_event0 =
369         static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get());
370     EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0));
371 
372     coalesced_event = kEvents[1];
373     const WebMouseWheelEvent* coalesced_wheel_event1 =
374         static_cast<const WebMouseWheelEvent*>(coalesced_events[1].get());
375     coalesced_event.dispatch_type =
376         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
377     EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event1));
378   }
379 
380   {
381     const WebMouseWheelEvent* last_wheel_event =
382         static_cast<const WebMouseWheelEvent*>(
383             handled_tasks_.at(1)->taskAsEvent()->EventPointer());
384     WebMouseWheelEvent coalesced_event = kEvents[2];
385     coalesced_event.Coalesce(kEvents[3]);
386     coalesced_event.dispatch_type =
387         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
388     EXPECT_TRUE(Equal(coalesced_event, *last_wheel_event));
389   }
390 
391   {
392     WebMouseWheelEvent coalesced_event = kEvents[2];
393     const auto& coalesced_events =
394         handled_tasks_[1]->taskAsEvent()->GetCoalescedEventsPointers();
395     const WebMouseWheelEvent* coalesced_wheel_event0 =
396         static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get());
397     EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0));
398 
399     coalesced_event = kEvents[3];
400     const WebMouseWheelEvent* coalesced_wheel_event1 =
401         static_cast<const WebMouseWheelEvent*>(coalesced_events[1].get());
402     coalesced_event.dispatch_type =
403         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
404     EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event1));
405   }
406 }
407 
TEST_F(MainThreadEventQueueTest,NonBlockingTouch)408 TEST_F(MainThreadEventQueueTest, NonBlockingTouch) {
409   EXPECT_CALL(thread_scheduler_,
410               DidHandleInputEventOnMainThread(testing::_, testing::_))
411       .Times(0);
412 
413   SyntheticWebTouchEvent kEvents[4];
414   kEvents[0].PressPoint(10, 10);
415   kEvents[1].PressPoint(10, 10);
416   kEvents[1].SetModifiers(1);
417   kEvents[1].MovePoint(0, 20, 20);
418   kEvents[2].PressPoint(10, 10);
419   kEvents[2].MovePoint(0, 30, 30);
420   kEvents[3].PressPoint(10, 10);
421   kEvents[3].MovePoint(0, 35, 35);
422 
423   for (SyntheticWebTouchEvent& event : kEvents)
424     HandleEvent(event, blink::mojom::InputEventResultState::kSetNonBlocking);
425 
426   EXPECT_EQ(3u, event_queue().size());
427   EXPECT_TRUE(main_task_runner_->HasPendingTask());
428   RunPendingTasksWithSimulatedRaf();
429   EXPECT_THAT(GetAndResetCallbackResults(),
430               testing::Each(ReceivedCallback(
431                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
432   EXPECT_FALSE(main_task_runner_->HasPendingTask());
433   EXPECT_EQ(0u, event_queue().size());
434   EXPECT_EQ(3u, handled_tasks_.size());
435 
436   EXPECT_EQ(kEvents[0].GetType(),
437             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
438   const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
439       handled_tasks_.at(0)->taskAsEvent()->EventPointer());
440   SyntheticWebTouchEvent non_blocking_touch = kEvents[0];
441   non_blocking_touch.dispatch_type =
442       WebInputEvent::DispatchType::kListenersNonBlockingPassive;
443   EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event));
444 
445   {
446     EXPECT_EQ(1u, handled_tasks_[0]->taskAsEvent()->CoalescedEventSize());
447     const WebTouchEvent* coalesced_touch_event =
448         static_cast<const WebTouchEvent*>(handled_tasks_[0]
449                                               ->taskAsEvent()
450                                               ->GetCoalescedEventsPointers()[0]
451                                               .get());
452     EXPECT_TRUE(Equal(kEvents[0], *coalesced_touch_event));
453   }
454 
455   EXPECT_EQ(kEvents[1].GetType(),
456             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
457   last_touch_event = static_cast<const WebTouchEvent*>(
458       handled_tasks_.at(1)->taskAsEvent()->EventPointer());
459   non_blocking_touch = kEvents[1];
460   non_blocking_touch.dispatch_type =
461       WebInputEvent::DispatchType::kListenersNonBlockingPassive;
462   EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event));
463 
464   {
465     EXPECT_EQ(1u, handled_tasks_[1]->taskAsEvent()->CoalescedEventSize());
466     const WebTouchEvent* coalesced_touch_event =
467         static_cast<const WebTouchEvent*>(handled_tasks_[1]
468                                               ->taskAsEvent()
469                                               ->GetCoalescedEventsPointers()[0]
470                                               .get());
471     EXPECT_TRUE(Equal(kEvents[1], *coalesced_touch_event));
472   }
473 
474   EXPECT_EQ(kEvents[2].GetType(),
475             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
476   last_touch_event = static_cast<const WebTouchEvent*>(
477       handled_tasks_.at(2)->taskAsEvent()->EventPointer());
478   WebTouchEvent coalesced_event = kEvents[2];
479   coalesced_event.Coalesce(kEvents[3]);
480   coalesced_event.dispatch_type =
481       WebInputEvent::DispatchType::kListenersNonBlockingPassive;
482   EXPECT_TRUE(Equal(coalesced_event, *last_touch_event));
483 
484   {
485     EXPECT_EQ(2u, handled_tasks_[2]->taskAsEvent()->CoalescedEventSize());
486     WebTouchEvent coalesced_event = kEvents[2];
487     const auto& coalesced_events =
488         handled_tasks_[2]->taskAsEvent()->GetCoalescedEventsPointers();
489     const WebTouchEvent* coalesced_touch_event0 =
490         static_cast<const WebTouchEvent*>(coalesced_events[0].get());
491     EXPECT_TRUE(Equal(coalesced_event, *coalesced_touch_event0));
492 
493     coalesced_event = kEvents[3];
494     const WebTouchEvent* coalesced_touch_event1 =
495         static_cast<const WebTouchEvent*>(coalesced_events[1].get());
496     coalesced_event.dispatch_type =
497         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
498     EXPECT_TRUE(Equal(coalesced_event, *coalesced_touch_event1));
499   }
500 }
501 
TEST_F(MainThreadEventQueueTest,BlockingTouch)502 TEST_F(MainThreadEventQueueTest, BlockingTouch) {
503   SyntheticWebTouchEvent kEvents[4];
504   kEvents[0].PressPoint(10, 10);
505   kEvents[1].PressPoint(10, 10);
506   kEvents[1].MovePoint(0, 20, 20);
507   kEvents[2].PressPoint(10, 10);
508   kEvents[2].MovePoint(0, 30, 30);
509   kEvents[3].PressPoint(10, 10);
510   kEvents[3].MovePoint(0, 35, 35);
511 
512   EXPECT_CALL(thread_scheduler_,
513               DidHandleInputEventOnMainThread(testing::_, testing::_))
514       .Times(3);
515   {
516     // Ensure that coalescing takes place.
517     HandleEvent(kEvents[0],
518                 blink::mojom::InputEventResultState::kSetNonBlocking);
519     HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
520     HandleEvent(kEvents[2], blink::mojom::InputEventResultState::kNotConsumed);
521     HandleEvent(kEvents[3], blink::mojom::InputEventResultState::kNotConsumed);
522 
523     EXPECT_EQ(2u, event_queue().size());
524     EXPECT_TRUE(main_task_runner_->HasPendingTask());
525     RunPendingTasksWithSimulatedRaf();
526 
527     EXPECT_THAT(
528         GetAndResetCallbackResults(),
529         testing::ElementsAre(
530             ReceivedCallback(CallbackReceivedState::kCalledWhileHandlingEvent,
531                              false),
532             ReceivedCallback(CallbackReceivedState::kCalledAfterHandleEvent,
533                              false),
534             ReceivedCallback(CallbackReceivedState::kCalledAfterHandleEvent,
535                              true),
536             ReceivedCallback(CallbackReceivedState::kCalledAfterHandleEvent,
537                              true)));
538     EXPECT_EQ(0u, event_queue().size());
539 
540     const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
541         handled_tasks_.at(1)->taskAsEvent()->EventPointer());
542     EXPECT_EQ(kEvents[1].unique_touch_event_id,
543               last_touch_event->unique_touch_event_id);
544   }
545 
546   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kSetNonBlocking);
547   HandleEvent(kEvents[2], blink::mojom::InputEventResultState::kSetNonBlocking);
548   HandleEvent(kEvents[3], blink::mojom::InputEventResultState::kSetNonBlocking);
549   EXPECT_EQ(1u, event_queue().size());
550   RunPendingTasksWithSimulatedRaf();
551   EXPECT_THAT(GetAndResetCallbackResults(),
552               testing::Each(ReceivedCallback(
553                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
554 }
555 
TEST_F(MainThreadEventQueueTest,InterleavedEvents)556 TEST_F(MainThreadEventQueueTest, InterleavedEvents) {
557   WebMouseWheelEvent kWheelEvents[2] = {
558       SyntheticWebMouseWheelEventBuilder::Build(
559           10, 10, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
560       SyntheticWebMouseWheelEventBuilder::Build(
561           20, 20, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
562   };
563   SyntheticWebTouchEvent kTouchEvents[2];
564   kTouchEvents[0].PressPoint(10, 10);
565   kTouchEvents[0].MovePoint(0, 20, 20);
566   kTouchEvents[1].PressPoint(10, 10);
567   kTouchEvents[1].MovePoint(0, 30, 30);
568 
569   EXPECT_CALL(thread_scheduler_,
570               DidHandleInputEventOnMainThread(testing::_, testing::_))
571       .Times(0);
572 
573   EXPECT_FALSE(main_task_runner_->HasPendingTask());
574   EXPECT_EQ(0u, event_queue().size());
575 
576   HandleEvent(kWheelEvents[0],
577               blink::mojom::InputEventResultState::kSetNonBlocking);
578   HandleEvent(kTouchEvents[0],
579               blink::mojom::InputEventResultState::kSetNonBlocking);
580   HandleEvent(kWheelEvents[1],
581               blink::mojom::InputEventResultState::kSetNonBlocking);
582   HandleEvent(kTouchEvents[1],
583               blink::mojom::InputEventResultState::kSetNonBlocking);
584 
585   EXPECT_EQ(2u, event_queue().size());
586   EXPECT_FALSE(main_task_runner_->HasPendingTask());
587   RunPendingTasksWithSimulatedRaf();
588   EXPECT_THAT(GetAndResetCallbackResults(),
589               testing::Each(ReceivedCallback(
590                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
591   EXPECT_FALSE(main_task_runner_->HasPendingTask());
592   EXPECT_EQ(0u, event_queue().size());
593   EXPECT_EQ(2u, handled_tasks_.size());
594   {
595     EXPECT_EQ(kWheelEvents[0].GetType(),
596               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
597     const WebMouseWheelEvent* last_wheel_event =
598         static_cast<const WebMouseWheelEvent*>(
599             handled_tasks_.at(0)->taskAsEvent()->EventPointer());
600     EXPECT_EQ(WebInputEvent::DispatchType::kListenersNonBlockingPassive,
601               last_wheel_event->dispatch_type);
602     WebMouseWheelEvent coalesced_event = kWheelEvents[0];
603     coalesced_event.Coalesce(kWheelEvents[1]);
604     coalesced_event.dispatch_type =
605         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
606     EXPECT_TRUE(Equal(coalesced_event, *last_wheel_event));
607   }
608   {
609     EXPECT_EQ(kTouchEvents[0].GetType(),
610               handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
611     const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
612         handled_tasks_.at(1)->taskAsEvent()->EventPointer());
613     WebTouchEvent coalesced_event = kTouchEvents[0];
614     coalesced_event.Coalesce(kTouchEvents[1]);
615     coalesced_event.dispatch_type =
616         WebInputEvent::DispatchType::kListenersNonBlockingPassive;
617     EXPECT_TRUE(Equal(coalesced_event, *last_touch_event));
618   }
619 }
620 
TEST_F(MainThreadEventQueueTest,RafAlignedMouseInput)621 TEST_F(MainThreadEventQueueTest, RafAlignedMouseInput) {
622   WebMouseEvent mouseDown = SyntheticWebMouseEventBuilder::Build(
623       WebInputEvent::Type::kMouseDown, 10, 10, 0);
624 
625   WebMouseEvent mouseMove = SyntheticWebMouseEventBuilder::Build(
626       WebInputEvent::Type::kMouseMove, 10, 10, 0);
627 
628   WebMouseEvent mouseUp = SyntheticWebMouseEventBuilder::Build(
629       WebInputEvent::Type::kMouseUp, 10, 10, 0);
630 
631   WebMouseWheelEvent wheelEvents[3] = {
632       SyntheticWebMouseWheelEventBuilder::Build(
633           10, 10, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
634       SyntheticWebMouseWheelEventBuilder::Build(
635           20, 20, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel),
636       SyntheticWebMouseWheelEventBuilder::Build(
637           20, 20, 0, 53, 1, ui::ScrollGranularity::kScrollByPixel),
638   };
639 
640   EXPECT_FALSE(main_task_runner_->HasPendingTask());
641   EXPECT_EQ(0u, event_queue().size());
642 
643   EXPECT_CALL(thread_scheduler_,
644               DidHandleInputEventOnMainThread(testing::_, testing::_))
645       .Times(0);
646 
647   // Simulate enqueing a discrete event, followed by continuous events and
648   // then a discrete event. The last discrete event should flush the
649   // continuous events so the aren't aligned to rAF and are processed
650   // immediately.
651   HandleEvent(mouseDown, blink::mojom::InputEventResultState::kSetNonBlocking);
652   HandleEvent(mouseMove, blink::mojom::InputEventResultState::kSetNonBlocking);
653   HandleEvent(wheelEvents[0],
654               blink::mojom::InputEventResultState::kSetNonBlocking);
655   HandleEvent(wheelEvents[1],
656               blink::mojom::InputEventResultState::kSetNonBlocking);
657   HandleEvent(mouseUp, blink::mojom::InputEventResultState::kSetNonBlocking);
658 
659   EXPECT_EQ(4u, event_queue().size());
660   EXPECT_TRUE(main_task_runner_->HasPendingTask());
661   EXPECT_TRUE(needs_main_frame_);
662   main_task_runner_->RunUntilIdle();
663   EXPECT_EQ(0u, event_queue().size());
664   RunPendingTasksWithSimulatedRaf();
665   EXPECT_THAT(GetAndResetCallbackResults(),
666               testing::Each(ReceivedCallback(
667                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
668 
669   // Simulate the rAF running before the PostTask occurs. The rAF
670   // will consume everything.
671   HandleEvent(mouseDown, blink::mojom::InputEventResultState::kSetNonBlocking);
672   HandleEvent(wheelEvents[0],
673               blink::mojom::InputEventResultState::kSetNonBlocking);
674   EXPECT_EQ(2u, event_queue().size());
675   EXPECT_TRUE(needs_main_frame_);
676   RunSimulatedRafOnce();
677   EXPECT_FALSE(needs_main_frame_);
678   EXPECT_EQ(0u, event_queue().size());
679   main_task_runner_->RunUntilIdle();
680   EXPECT_THAT(GetAndResetCallbackResults(),
681               testing::Each(ReceivedCallback(
682                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
683 
684   // Simulate event consumption but no rAF signal. The mouse wheel events
685   // should still be in the queue.
686   handled_tasks_.clear();
687   HandleEvent(mouseDown, blink::mojom::InputEventResultState::kSetNonBlocking);
688   HandleEvent(wheelEvents[0],
689               blink::mojom::InputEventResultState::kSetNonBlocking);
690   HandleEvent(mouseUp, blink::mojom::InputEventResultState::kSetNonBlocking);
691   HandleEvent(wheelEvents[2],
692               blink::mojom::InputEventResultState::kSetNonBlocking);
693   HandleEvent(wheelEvents[0],
694               blink::mojom::InputEventResultState::kSetNonBlocking);
695   EXPECT_EQ(5u, event_queue().size());
696   EXPECT_TRUE(needs_main_frame_);
697   main_task_runner_->RunUntilIdle();
698   EXPECT_TRUE(needs_main_frame_);
699   EXPECT_EQ(2u, event_queue().size());
700   RunSimulatedRafOnce();
701   EXPECT_THAT(GetAndResetCallbackResults(),
702               testing::Each(ReceivedCallback(
703                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
704   EXPECT_EQ(wheelEvents[2].GetModifiers(),
705             handled_tasks_.at(3)->taskAsEvent()->Event().GetModifiers());
706   EXPECT_EQ(wheelEvents[0].GetModifiers(),
707             handled_tasks_.at(4)->taskAsEvent()->Event().GetModifiers());
708 }
709 
TEST_F(MainThreadEventQueueTest,RafAlignedTouchInput)710 TEST_F(MainThreadEventQueueTest, RafAlignedTouchInput) {
711   SyntheticWebTouchEvent kEvents[3];
712   kEvents[0].PressPoint(10, 10);
713   kEvents[1].PressPoint(10, 10);
714   kEvents[1].MovePoint(0, 50, 50);
715   kEvents[2].PressPoint(10, 10);
716   kEvents[2].ReleasePoint(0);
717 
718   EXPECT_FALSE(main_task_runner_->HasPendingTask());
719   EXPECT_EQ(0u, event_queue().size());
720 
721   EXPECT_CALL(thread_scheduler_,
722               DidHandleInputEventOnMainThread(testing::_, testing::_))
723       .Times(3);
724 
725   // Simulate enqueing a discrete event, followed by continuous events and
726   // then a discrete event. The last discrete event should flush the
727   // continuous events so the aren't aligned to rAF and are processed
728   // immediately.
729   for (SyntheticWebTouchEvent& event : kEvents)
730     HandleEvent(event, blink::mojom::InputEventResultState::kSetNonBlocking);
731 
732   EXPECT_EQ(3u, event_queue().size());
733   EXPECT_TRUE(main_task_runner_->HasPendingTask());
734   EXPECT_TRUE(needs_main_frame_);
735   main_task_runner_->RunUntilIdle();
736   EXPECT_EQ(0u, event_queue().size());
737   RunPendingTasksWithSimulatedRaf();
738   EXPECT_THAT(GetAndResetCallbackResults(),
739               testing::Each(ReceivedCallback(
740                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
741 
742   // Simulate the rAF running before the PostTask occurs. The rAF
743   // will consume everything.
744   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kSetNonBlocking);
745   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kSetNonBlocking);
746   EXPECT_EQ(2u, event_queue().size());
747   EXPECT_TRUE(needs_main_frame_);
748   RunSimulatedRafOnce();
749   EXPECT_FALSE(needs_main_frame_);
750   EXPECT_EQ(0u, event_queue().size());
751   main_task_runner_->RunUntilIdle();
752   EXPECT_THAT(GetAndResetCallbackResults(),
753               testing::Each(ReceivedCallback(
754                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
755 
756   // Simulate event consumption but no rAF signal. The touch events
757   // should still be in the queue.
758   handled_tasks_.clear();
759   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kSetNonBlocking);
760   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kSetNonBlocking);
761   EXPECT_EQ(2u, event_queue().size());
762   EXPECT_TRUE(needs_main_frame_);
763   main_task_runner_->RunUntilIdle();
764   EXPECT_TRUE(needs_main_frame_);
765   EXPECT_EQ(1u, event_queue().size());
766   RunSimulatedRafOnce();
767   EXPECT_THAT(GetAndResetCallbackResults(),
768               testing::Each(ReceivedCallback(
769                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
770 
771   // Simulate the touch move being discrete
772   kEvents[0].touch_start_or_first_touch_move = true;
773   kEvents[1].touch_start_or_first_touch_move = true;
774 
775   for (SyntheticWebTouchEvent& event : kEvents)
776     HandleEvent(event, blink::mojom::InputEventResultState::kNotConsumed);
777 
778   EXPECT_EQ(3u, event_queue().size());
779   EXPECT_TRUE(main_task_runner_->HasPendingTask());
780   EXPECT_TRUE(needs_main_frame_);
781   main_task_runner_->RunUntilIdle();
782   EXPECT_THAT(GetAndResetCallbackResults(),
783               testing::Each(ReceivedCallback(
784                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
785 }
786 
TEST_F(MainThreadEventQueueTest,RafAlignedTouchInputCoalescedMoves)787 TEST_F(MainThreadEventQueueTest, RafAlignedTouchInputCoalescedMoves) {
788   SyntheticWebTouchEvent kEvents[2];
789   kEvents[0].PressPoint(10, 10);
790   kEvents[0].MovePoint(0, 50, 50);
791   kEvents[1].PressPoint(10, 10);
792   kEvents[1].MovePoint(0, 20, 20);
793   kEvents[0].dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
794 
795   EXPECT_CALL(thread_scheduler_,
796               DidHandleInputEventOnMainThread(testing::_, testing::_))
797       .Times(4);
798 
799   EXPECT_FALSE(main_task_runner_->HasPendingTask());
800   EXPECT_EQ(0u, event_queue().size());
801 
802   {
803     // Send a non-blocking input event and then blocking  event.
804     // The events should coalesce together.
805     HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
806     EXPECT_EQ(1u, event_queue().size());
807     EXPECT_FALSE(main_task_runner_->HasPendingTask());
808     EXPECT_TRUE(needs_main_frame_);
809     HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
810     EXPECT_EQ(1u, event_queue().size());
811     EXPECT_FALSE(main_task_runner_->HasPendingTask());
812     EXPECT_TRUE(needs_main_frame_);
813     RunPendingTasksWithSimulatedRaf();
814     EXPECT_EQ(0u, event_queue().size());
815     EXPECT_THAT(
816         GetAndResetCallbackResults(),
817         testing::ElementsAre(
818             ReceivedCallback(CallbackReceivedState::kCalledWhileHandlingEvent,
819                              false),
820             ReceivedCallback(CallbackReceivedState::kCalledAfterHandleEvent,
821                              true)));
822   }
823 
824   // Send a non-cancelable ack required event, and then a non-ack
825   // required event they should be coalesced together.
826   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
827   EXPECT_EQ(1u, event_queue().size());
828   EXPECT_FALSE(main_task_runner_->HasPendingTask());
829   EXPECT_TRUE(needs_main_frame_);
830   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kSetNonBlocking);
831   EXPECT_EQ(1u, event_queue().size());
832   EXPECT_FALSE(main_task_runner_->HasPendingTask());
833   EXPECT_TRUE(needs_main_frame_);
834   RunPendingTasksWithSimulatedRaf();
835   EXPECT_EQ(0u, event_queue().size());
836   EXPECT_THAT(GetAndResetCallbackResults(),
837               testing::Each(ReceivedCallback(
838                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
839 
840   // Send a non-ack required event, and then a non-cancelable ack
841   // required event they should be coalesced together.
842   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kSetNonBlocking);
843   EXPECT_EQ(1u, event_queue().size());
844   EXPECT_FALSE(main_task_runner_->HasPendingTask());
845   EXPECT_TRUE(needs_main_frame_);
846   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
847   EXPECT_EQ(1u, event_queue().size());
848   EXPECT_FALSE(main_task_runner_->HasPendingTask());
849   EXPECT_TRUE(needs_main_frame_);
850   RunPendingTasksWithSimulatedRaf();
851   EXPECT_EQ(0u, event_queue().size());
852   EXPECT_THAT(GetAndResetCallbackResults(),
853               testing::Each(ReceivedCallback(
854                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
855 }
856 
TEST_F(MainThreadEventQueueTest,RafAlignedTouchInputThrottlingMoves)857 TEST_F(MainThreadEventQueueTest, RafAlignedTouchInputThrottlingMoves) {
858   EXPECT_CALL(thread_scheduler_,
859               DidHandleInputEventOnMainThread(testing::_, testing::_))
860       .Times(3);
861 
862   SyntheticWebTouchEvent kEvents[2];
863   kEvents[0].PressPoint(10, 10);
864   kEvents[0].MovePoint(0, 50, 50);
865   kEvents[0].dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
866   kEvents[1].PressPoint(10, 10);
867   kEvents[1].MovePoint(0, 20, 20);
868   kEvents[1].dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
869 
870   EXPECT_FALSE(main_task_runner_->HasPendingTask());
871   EXPECT_EQ(0u, event_queue().size());
872 
873   // Send a non-cancelable touch move and then send it another one. The
874   // second one shouldn't go out with the next rAF call and should be throttled.
875   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
876   EXPECT_EQ(1u, event_queue().size());
877   EXPECT_FALSE(main_task_runner_->HasPendingTask());
878   EXPECT_TRUE(needs_main_frame_);
879   RunPendingTasksWithSimulatedRaf();
880   EXPECT_THAT(GetAndResetCallbackResults(),
881               testing::Each(ReceivedCallback(
882                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
883   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
884   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
885   EXPECT_EQ(1u, event_queue().size());
886   EXPECT_FALSE(main_task_runner_->HasPendingTask());
887   EXPECT_TRUE(needs_main_frame_);
888 
889   // Event should still be in queue after handling a single rAF call.
890   RunSimulatedRafOnce();
891   EXPECT_EQ(1u, event_queue().size());
892   EXPECT_FALSE(main_task_runner_->HasPendingTask());
893   EXPECT_TRUE(needs_main_frame_);
894 
895   // And should eventually flush.
896   RunPendingTasksWithSimulatedRaf();
897   EXPECT_THAT(GetAndResetCallbackResults(),
898               testing::Each(ReceivedCallback(
899                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
900   EXPECT_EQ(0u, event_queue().size());
901 }
902 
TEST_F(MainThreadEventQueueTest,LowLatency)903 TEST_F(MainThreadEventQueueTest, LowLatency) {
904   SyntheticWebTouchEvent kEvents[2];
905   kEvents[0].PressPoint(10, 10);
906   kEvents[1].PressPoint(10, 10);
907   kEvents[1].MovePoint(0, 50, 50);
908 
909   queue_->SetNeedsLowLatency(true);
910   EXPECT_FALSE(main_task_runner_->HasPendingTask());
911   EXPECT_EQ(0u, event_queue().size());
912 
913   EXPECT_CALL(thread_scheduler_,
914               DidHandleInputEventOnMainThread(testing::_, testing::_))
915       .Times(0);
916 
917   for (SyntheticWebTouchEvent& event : kEvents)
918     HandleEvent(event, blink::mojom::InputEventResultState::kSetNonBlocking);
919 
920   EXPECT_EQ(2u, event_queue().size());
921   EXPECT_TRUE(main_task_runner_->HasPendingTask());
922   EXPECT_FALSE(needs_main_frame_);
923   main_task_runner_->RunUntilIdle();
924   EXPECT_THAT(GetAndResetCallbackResults(),
925               testing::Each(ReceivedCallback(
926                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
927   EXPECT_EQ(0u, event_queue().size());
928   EXPECT_FALSE(main_task_runner_->HasPendingTask());
929 
930   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
931       WebInputEvent::Type::kMouseMove, 10, 10, 0);
932   WebMouseWheelEvent mouse_wheel = SyntheticWebMouseWheelEventBuilder::Build(
933       10, 10, 0, 53, 0, ui::ScrollGranularity::kScrollByPixel);
934 
935   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
936   HandleEvent(mouse_wheel,
937               blink::mojom::InputEventResultState::kSetNonBlocking);
938 
939   EXPECT_EQ(2u, event_queue().size());
940   EXPECT_TRUE(main_task_runner_->HasPendingTask());
941   EXPECT_FALSE(needs_main_frame_);
942   main_task_runner_->RunUntilIdle();
943   EXPECT_THAT(GetAndResetCallbackResults(),
944               testing::Each(ReceivedCallback(
945                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
946   EXPECT_EQ(0u, event_queue().size());
947 
948   // Now turn off low latency mode.
949   queue_->SetNeedsLowLatency(false);
950   for (SyntheticWebTouchEvent& event : kEvents)
951     HandleEvent(event, blink::mojom::InputEventResultState::kSetNonBlocking);
952 
953   EXPECT_EQ(2u, event_queue().size());
954   EXPECT_TRUE(main_task_runner_->HasPendingTask());
955   EXPECT_TRUE(needs_main_frame_);
956   RunPendingTasksWithSimulatedRaf();
957   EXPECT_THAT(GetAndResetCallbackResults(),
958               testing::Each(ReceivedCallback(
959                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
960   EXPECT_EQ(0u, event_queue().size());
961   EXPECT_FALSE(main_task_runner_->HasPendingTask());
962 
963   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
964   HandleEvent(mouse_wheel,
965               blink::mojom::InputEventResultState::kSetNonBlocking);
966 
967   EXPECT_EQ(2u, event_queue().size());
968   EXPECT_FALSE(main_task_runner_->HasPendingTask());
969   EXPECT_TRUE(needs_main_frame_);
970   RunPendingTasksWithSimulatedRaf();
971   EXPECT_THAT(GetAndResetCallbackResults(),
972               testing::Each(ReceivedCallback(
973                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
974   EXPECT_EQ(0u, event_queue().size());
975 }
976 
TEST_F(MainThreadEventQueueTest,BlockingTouchesDuringFling)977 TEST_F(MainThreadEventQueueTest, BlockingTouchesDuringFling) {
978   SyntheticWebTouchEvent kEvents;
979   kEvents.PressPoint(10, 10);
980   kEvents.touch_start_or_first_touch_move = true;
981 
982   EXPECT_CALL(thread_scheduler_,
983               DidHandleInputEventOnMainThread(testing::_, testing::_))
984       .Times(4);
985 
986   EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
987   HandleEvent(kEvents,
988               blink::mojom::InputEventResultState::kSetNonBlockingDueToFling);
989   RunPendingTasksWithSimulatedRaf();
990   EXPECT_THAT(GetAndResetCallbackResults(),
991               testing::Each(ReceivedCallback(
992                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
993   EXPECT_FALSE(main_task_runner_->HasPendingTask());
994   EXPECT_EQ(0u, event_queue().size());
995   EXPECT_EQ(1u, handled_tasks_.size());
996   EXPECT_EQ(kEvents.GetType(),
997             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
998   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
999   const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
1000       handled_tasks_.at(0)->taskAsEvent()->EventPointer());
1001   kEvents.dispatch_type =
1002       WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling;
1003   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1004 
1005   kEvents.MovePoint(0, 30, 30);
1006   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1007   HandleEvent(kEvents,
1008               blink::mojom::InputEventResultState::kSetNonBlockingDueToFling);
1009   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1010   RunPendingTasksWithSimulatedRaf();
1011   EXPECT_THAT(GetAndResetCallbackResults(),
1012               testing::Each(ReceivedCallback(
1013                   CallbackReceivedState::kCalledWhileHandlingEvent, false)));
1014   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1015   EXPECT_EQ(0u, event_queue().size());
1016   EXPECT_EQ(2u, handled_tasks_.size());
1017   EXPECT_EQ(kEvents.GetType(),
1018             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
1019   EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
1020   last_touch_event = static_cast<const WebTouchEvent*>(
1021       handled_tasks_.at(1)->taskAsEvent()->EventPointer());
1022   kEvents.dispatch_type =
1023       WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling;
1024   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1025 
1026   kEvents.MovePoint(0, 50, 50);
1027   kEvents.touch_start_or_first_touch_move = false;
1028   HandleEvent(kEvents,
1029               blink::mojom::InputEventResultState::kSetNonBlockingDueToFling);
1030   RunPendingTasksWithSimulatedRaf();
1031   EXPECT_THAT(GetAndResetCallbackResults(),
1032               testing::Each(ReceivedCallback(
1033                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1034   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1035   EXPECT_EQ(0u, event_queue().size());
1036   EXPECT_EQ(3u, handled_tasks_.size());
1037   EXPECT_EQ(kEvents.GetType(),
1038             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
1039   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1040   last_touch_event = static_cast<const WebTouchEvent*>(
1041       handled_tasks_.at(2)->taskAsEvent()->EventPointer());
1042   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1043 
1044   kEvents.ReleasePoint(0);
1045   HandleEvent(kEvents,
1046               blink::mojom::InputEventResultState::kSetNonBlockingDueToFling);
1047   RunPendingTasksWithSimulatedRaf();
1048   EXPECT_THAT(GetAndResetCallbackResults(),
1049               testing::Each(ReceivedCallback(
1050                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1051   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1052   EXPECT_EQ(0u, event_queue().size());
1053   EXPECT_EQ(4u, handled_tasks_.size());
1054   EXPECT_EQ(kEvents.GetType(),
1055             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
1056   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1057   last_touch_event = static_cast<const WebTouchEvent*>(
1058       handled_tasks_.at(3)->taskAsEvent()->EventPointer());
1059   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1060 }
1061 
TEST_F(MainThreadEventQueueTest,BlockingTouchesOutsideFling)1062 TEST_F(MainThreadEventQueueTest, BlockingTouchesOutsideFling) {
1063   SyntheticWebTouchEvent kEvents;
1064   kEvents.PressPoint(10, 10);
1065   kEvents.touch_start_or_first_touch_move = true;
1066 
1067   EXPECT_CALL(thread_scheduler_,
1068               DidHandleInputEventOnMainThread(testing::_, testing::_))
1069       .Times(4);
1070 
1071   HandleEvent(kEvents, blink::mojom::InputEventResultState::kNotConsumed);
1072   RunPendingTasksWithSimulatedRaf();
1073   EXPECT_THAT(GetAndResetCallbackResults(),
1074               testing::Each(ReceivedCallback(
1075                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1076   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1077   EXPECT_EQ(0u, event_queue().size());
1078   EXPECT_EQ(1u, handled_tasks_.size());
1079   EXPECT_EQ(kEvents.GetType(),
1080             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
1081   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1082   EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
1083   const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>(
1084       handled_tasks_.at(0)->taskAsEvent()->EventPointer());
1085   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1086 
1087   HandleEvent(kEvents, blink::mojom::InputEventResultState::kNotConsumed);
1088   RunPendingTasksWithSimulatedRaf();
1089   EXPECT_THAT(GetAndResetCallbackResults(),
1090               testing::Each(ReceivedCallback(
1091                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1092   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1093   EXPECT_EQ(0u, event_queue().size());
1094   EXPECT_EQ(2u, handled_tasks_.size());
1095   EXPECT_EQ(kEvents.GetType(),
1096             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
1097   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1098   EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
1099   last_touch_event = static_cast<const WebTouchEvent*>(
1100       handled_tasks_.at(1)->taskAsEvent()->EventPointer());
1101   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1102 
1103   HandleEvent(kEvents, blink::mojom::InputEventResultState::kNotConsumed);
1104   RunPendingTasksWithSimulatedRaf();
1105   EXPECT_THAT(GetAndResetCallbackResults(),
1106               testing::Each(ReceivedCallback(
1107                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1108   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1109   EXPECT_EQ(0u, event_queue().size());
1110   EXPECT_EQ(3u, handled_tasks_.size());
1111   EXPECT_EQ(kEvents.GetType(),
1112             handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
1113   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1114   EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
1115   last_touch_event = static_cast<const WebTouchEvent*>(
1116       handled_tasks_.at(2)->taskAsEvent()->EventPointer());
1117   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1118 
1119   kEvents.MovePoint(0, 30, 30);
1120   HandleEvent(kEvents, blink::mojom::InputEventResultState::kNotConsumed);
1121   RunPendingTasksWithSimulatedRaf();
1122   EXPECT_THAT(GetAndResetCallbackResults(),
1123               testing::Each(ReceivedCallback(
1124                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1125   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1126   EXPECT_EQ(0u, event_queue().size());
1127   EXPECT_EQ(4u, handled_tasks_.size());
1128   EXPECT_EQ(kEvents.GetType(),
1129             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
1130   EXPECT_EQ(kEvents.dispatch_type, WebInputEvent::DispatchType::kBlocking);
1131   EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
1132   last_touch_event = static_cast<const WebTouchEvent*>(
1133       handled_tasks_.at(3)->taskAsEvent()->EventPointer());
1134   EXPECT_TRUE(Equal(kEvents, *last_touch_event));
1135 }
1136 
1137 class MainThreadEventQueueInitializationTest
1138     : public testing::Test,
1139       public MainThreadEventQueueClient {
1140  public:
1141   MainThreadEventQueueInitializationTest() = default;
1142 
HandleInputEvent(const blink::WebCoalescedInputEvent & event,std::unique_ptr<cc::EventMetrics> metrics,HandledEventCallback callback)1143   bool HandleInputEvent(const blink::WebCoalescedInputEvent& event,
1144                         std::unique_ptr<cc::EventMetrics> metrics,
1145                         HandledEventCallback callback) override {
1146     std::move(callback).Run(blink::mojom::InputEventResultState::kNotConsumed,
1147                             event.latency_info(), nullptr, base::nullopt);
1148     return true;
1149   }
1150 
SetNeedsMainFrame()1151   void SetNeedsMainFrame() override {}
1152 
1153  protected:
1154   scoped_refptr<MainThreadEventQueue> queue_;
1155   blink::scheduler::WebMockThreadScheduler thread_scheduler_;
1156   scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
1157 };
1158 
TEST_F(MainThreadEventQueueTest,QueuingTwoClosures)1159 TEST_F(MainThreadEventQueueTest, QueuingTwoClosures) {
1160   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1161   EXPECT_EQ(0u, event_queue().size());
1162 
1163   QueueClosure();
1164   QueueClosure();
1165   EXPECT_EQ(2u, event_queue().size());
1166   EXPECT_TRUE(main_task_runner_->HasPendingTask());
1167   EXPECT_FALSE(needs_main_frame_);
1168   main_task_runner_->RunUntilIdle();
1169   EXPECT_EQ(1u, handled_tasks_.at(0)->taskAsClosure());
1170   EXPECT_EQ(2u, handled_tasks_.at(1)->taskAsClosure());
1171 }
1172 
TEST_F(MainThreadEventQueueTest,QueuingClosureWithRafEvent)1173 TEST_F(MainThreadEventQueueTest, QueuingClosureWithRafEvent) {
1174   SyntheticWebTouchEvent kEvents[2];
1175   kEvents[0].PressPoint(10, 10);
1176   kEvents[1].PressPoint(10, 10);
1177   kEvents[1].MovePoint(0, 20, 20);
1178 
1179   // Simulate queueuing closure, event, closure, raf aligned event.
1180   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1181   EXPECT_EQ(0u, event_queue().size());
1182   QueueClosure();
1183   EXPECT_EQ(1u, event_queue().size());
1184   EXPECT_TRUE(main_task_runner_->HasPendingTask());
1185   EXPECT_FALSE(needs_main_frame_);
1186 
1187   EXPECT_CALL(thread_scheduler_,
1188               DidHandleInputEventOnMainThread(testing::_, testing::_))
1189       .Times(2);
1190 
1191   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
1192   QueueClosure();
1193   EXPECT_EQ(3u, event_queue().size());
1194   EXPECT_TRUE(main_task_runner_->HasPendingTask());
1195   EXPECT_FALSE(needs_main_frame_);
1196   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
1197   EXPECT_EQ(4u, event_queue().size());
1198 
1199   EXPECT_TRUE(needs_main_frame_);
1200   main_task_runner_->RunUntilIdle();
1201 
1202   // The queue should still have the rAF event.
1203   EXPECT_TRUE(needs_main_frame_);
1204   EXPECT_EQ(1u, event_queue().size());
1205   RunPendingTasksWithSimulatedRaf();
1206 
1207   EXPECT_EQ(0u, event_queue().size());
1208   EXPECT_THAT(GetAndResetCallbackResults(),
1209               testing::Each(ReceivedCallback(
1210                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1211   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1212   EXPECT_FALSE(needs_main_frame_);
1213 
1214   EXPECT_EQ(1u, handled_tasks_.at(0)->taskAsClosure());
1215   EXPECT_EQ(kEvents[0].GetType(),
1216             handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
1217   EXPECT_EQ(2u, handled_tasks_.at(2)->taskAsClosure());
1218   EXPECT_EQ(kEvents[1].GetType(),
1219             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
1220 }
1221 
TEST_F(MainThreadEventQueueTest,QueuingClosuresBetweenEvents)1222 TEST_F(MainThreadEventQueueTest, QueuingClosuresBetweenEvents) {
1223   SyntheticWebTouchEvent kEvents[2];
1224   kEvents[0].PressPoint(10, 10);
1225   kEvents[1].PressPoint(10, 10);
1226   kEvents[1].ReleasePoint(0);
1227 
1228   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1229   EXPECT_EQ(0u, event_queue().size());
1230 
1231   EXPECT_CALL(thread_scheduler_,
1232               DidHandleInputEventOnMainThread(testing::_, testing::_))
1233       .Times(2);
1234 
1235   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
1236   QueueClosure();
1237   QueueClosure();
1238   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
1239   EXPECT_EQ(4u, event_queue().size());
1240   EXPECT_FALSE(needs_main_frame_);
1241   main_task_runner_->RunUntilIdle();
1242   EXPECT_EQ(0u, event_queue().size());
1243   EXPECT_THAT(GetAndResetCallbackResults(),
1244               testing::Each(ReceivedCallback(
1245                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1246   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1247   EXPECT_FALSE(needs_main_frame_);
1248 
1249   EXPECT_EQ(kEvents[0].GetType(),
1250             handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
1251   EXPECT_EQ(1u, handled_tasks_.at(1)->taskAsClosure());
1252   EXPECT_EQ(2u, handled_tasks_.at(2)->taskAsClosure());
1253   EXPECT_EQ(kEvents[1].GetType(),
1254             handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
1255 }
1256 
TEST_F(MainThreadEventQueueTest,BlockingTouchMoveBecomesNonBlocking)1257 TEST_F(MainThreadEventQueueTest, BlockingTouchMoveBecomesNonBlocking) {
1258   SyntheticWebTouchEvent kEvents[2];
1259   kEvents[0].PressPoint(10, 10);
1260   kEvents[0].MovePoint(0, 20, 20);
1261   kEvents[1].SetModifiers(1);
1262   kEvents[1].PressPoint(10, 10);
1263   kEvents[1].MovePoint(0, 20, 30);
1264   kEvents[1].dispatch_type = WebInputEvent::DispatchType::kEventNonBlocking;
1265   WebTouchEvent scroll_start(WebInputEvent::Type::kTouchScrollStarted,
1266                              WebInputEvent::kNoModifiers,
1267                              WebInputEvent::GetStaticTimeStampForTests());
1268 
1269   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1270   EXPECT_EQ(0u, event_queue().size());
1271 
1272   EXPECT_CALL(thread_scheduler_,
1273               DidHandleInputEventOnMainThread(testing::_, testing::_))
1274       .Times(3);
1275   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking, kEvents[0].dispatch_type);
1276   EXPECT_EQ(WebInputEvent::DispatchType::kEventNonBlocking,
1277             kEvents[1].dispatch_type);
1278   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
1279   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
1280   HandleEvent(scroll_start, blink::mojom::InputEventResultState::kNotConsumed);
1281   EXPECT_EQ(3u, event_queue().size());
1282   RunPendingTasksWithSimulatedRaf();
1283   EXPECT_THAT(GetAndResetCallbackResults(),
1284               testing::ElementsAre(
1285                   ReceivedCallback(
1286                       CallbackReceivedState::kCalledAfterHandleEvent, false),
1287                   ReceivedCallback(
1288                       CallbackReceivedState::kCalledWhileHandlingEvent, false),
1289                   ReceivedCallback(
1290                       CallbackReceivedState::kCalledAfterHandleEvent, false)));
1291   EXPECT_EQ(0u, event_queue().size());
1292   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1293   EXPECT_FALSE(needs_main_frame_);
1294 
1295   EXPECT_EQ(WebInputEvent::DispatchType::kEventNonBlocking,
1296             static_cast<const WebTouchEvent&>(
1297                 handled_tasks_.at(0)->taskAsEvent()->Event())
1298                 .dispatch_type);
1299   EXPECT_EQ(WebInputEvent::DispatchType::kEventNonBlocking,
1300             static_cast<const WebTouchEvent&>(
1301                 handled_tasks_.at(1)->taskAsEvent()->Event())
1302                 .dispatch_type);
1303 }
1304 
TEST_F(MainThreadEventQueueTest,BlockingTouchMoveWithTouchEnd)1305 TEST_F(MainThreadEventQueueTest, BlockingTouchMoveWithTouchEnd) {
1306   SyntheticWebTouchEvent kEvents[2];
1307   kEvents[0].PressPoint(10, 10);
1308   kEvents[0].MovePoint(0, 20, 20);
1309   kEvents[1].PressPoint(10, 10);
1310   kEvents[1].ReleasePoint(0);
1311   WebTouchEvent scroll_start(WebInputEvent::Type::kTouchScrollStarted,
1312                              WebInputEvent::kNoModifiers,
1313                              WebInputEvent::GetStaticTimeStampForTests());
1314 
1315   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1316   EXPECT_EQ(0u, event_queue().size());
1317 
1318   EXPECT_CALL(thread_scheduler_,
1319               DidHandleInputEventOnMainThread(testing::_, testing::_))
1320       .Times(3);
1321   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking, kEvents[0].dispatch_type);
1322   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking, kEvents[1].dispatch_type);
1323   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
1324   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
1325   HandleEvent(scroll_start, blink::mojom::InputEventResultState::kNotConsumed);
1326   EXPECT_EQ(3u, event_queue().size());
1327   RunPendingTasksWithSimulatedRaf();
1328   EXPECT_THAT(GetAndResetCallbackResults(),
1329               testing::Each(ReceivedCallback(
1330                   CallbackReceivedState::kCalledAfterHandleEvent, false)));
1331   EXPECT_EQ(0u, event_queue().size());
1332   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1333   EXPECT_FALSE(needs_main_frame_);
1334 
1335   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking,
1336             static_cast<const WebTouchEvent&>(
1337                 handled_tasks_.at(0)->taskAsEvent()->Event())
1338                 .dispatch_type);
1339   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking,
1340             static_cast<const WebTouchEvent&>(
1341                 handled_tasks_.at(1)->taskAsEvent()->Event())
1342                 .dispatch_type);
1343 }
1344 
TEST_F(MainThreadEventQueueTest,UnbufferedDispatchTouchEvent)1345 TEST_F(MainThreadEventQueueTest, UnbufferedDispatchTouchEvent) {
1346   SyntheticWebTouchEvent kEvents[3];
1347   kEvents[0].PressPoint(10, 10);
1348   kEvents[1].PressPoint(10, 10);
1349   kEvents[1].MovePoint(0, 20, 20);
1350   kEvents[2].PressPoint(10, 10);
1351   kEvents[2].ReleasePoint(0);
1352 
1353   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1354   EXPECT_EQ(0u, event_queue().size());
1355 
1356   EXPECT_CALL(thread_scheduler_,
1357               DidHandleInputEventOnMainThread(testing::_, testing::_))
1358       .Times(3);
1359 
1360   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking, kEvents[0].dispatch_type);
1361   EXPECT_EQ(WebInputEvent::DispatchType::kBlocking, kEvents[1].dispatch_type);
1362   HandleEvent(kEvents[0], blink::mojom::InputEventResultState::kNotConsumed);
1363   queue_->RequestUnbufferedInputEvents();
1364   EXPECT_EQ(1u, event_queue().size());
1365   RunPendingTasksWithSimulatedRaf();
1366   EXPECT_TRUE(needs_low_latency_until_pointer_up());
1367   EXPECT_FALSE(needs_main_frame_);
1368 
1369   HandleEvent(kEvents[1], blink::mojom::InputEventResultState::kNotConsumed);
1370   EXPECT_EQ(1u, event_queue().size());
1371   RunPendingTasksWithSimulatedRaf();
1372   EXPECT_TRUE(needs_low_latency_until_pointer_up());
1373   EXPECT_FALSE(needs_main_frame_);
1374 
1375   HandleEvent(kEvents[2], blink::mojom::InputEventResultState::kNotConsumed);
1376   EXPECT_EQ(1u, event_queue().size());
1377   RunPendingTasksWithSimulatedRaf();
1378   EXPECT_FALSE(needs_low_latency_until_pointer_up());
1379   EXPECT_FALSE(needs_main_frame_);
1380 }
1381 
TEST_F(MainThreadEventQueueTest,PointerEventsCoalescing)1382 TEST_F(MainThreadEventQueueTest, PointerEventsCoalescing) {
1383   queue_->HasPointerRawUpdateEventHandlers(true);
1384   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
1385       WebInputEvent::Type::kMouseMove, 10, 10, 0);
1386   SyntheticWebTouchEvent touch_move;
1387   touch_move.PressPoint(10, 10);
1388   touch_move.MovePoint(0, 50, 50);
1389 
1390   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1391   EXPECT_EQ(0u, event_queue().size());
1392 
1393   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1394   HandleEvent(touch_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1395   EXPECT_EQ(4u, event_queue().size());
1396 
1397   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1398   HandleEvent(touch_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1399   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1400   HandleEvent(touch_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1401   EXPECT_EQ(4u, event_queue().size());
1402 
1403   main_task_runner_->RunUntilIdle();
1404   EXPECT_EQ(2u, event_queue().size());
1405 
1406   RunPendingTasksWithSimulatedRaf();
1407   EXPECT_EQ(0u, event_queue().size());
1408   EXPECT_FALSE(needs_main_frame_);
1409 }
1410 
TEST_F(MainThreadEventQueueTest,PointerRawUpdateEvents)1411 TEST_F(MainThreadEventQueueTest, PointerRawUpdateEvents) {
1412   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
1413       WebInputEvent::Type::kMouseMove, 10, 10, 0);
1414 
1415   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1416   EXPECT_EQ(0u, event_queue().size());
1417 
1418   EXPECT_CALL(thread_scheduler_,
1419               DidHandleInputEventOnMainThread(testing::_, testing::_))
1420       .Times(0);
1421 
1422   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1423   EXPECT_EQ(1u, event_queue().size());
1424   RunPendingTasksWithSimulatedRaf();
1425   EXPECT_EQ(0u, event_queue().size());
1426   EXPECT_FALSE(needs_main_frame_);
1427 
1428   queue_->HasPointerRawUpdateEventHandlers(true);
1429   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1430   EXPECT_EQ(2u, event_queue().size());
1431   RunPendingTasksWithSimulatedRaf();
1432   EXPECT_EQ(0u, event_queue().size());
1433   EXPECT_FALSE(needs_main_frame_);
1434 
1435   queue_->HasPointerRawUpdateEventHandlers(false);
1436   SyntheticWebTouchEvent touch_move;
1437   touch_move.PressPoint(10, 10);
1438   touch_move.MovePoint(0, 50, 50);
1439   HandleEvent(touch_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1440   EXPECT_EQ(1u, event_queue().size());
1441   RunPendingTasksWithSimulatedRaf();
1442   EXPECT_EQ(0u, event_queue().size());
1443   EXPECT_FALSE(needs_main_frame_);
1444 
1445   queue_->HasPointerRawUpdateEventHandlers(true);
1446   HandleEvent(touch_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1447   EXPECT_EQ(2u, event_queue().size());
1448   RunPendingTasksWithSimulatedRaf();
1449   EXPECT_EQ(0u, event_queue().size());
1450   EXPECT_FALSE(needs_main_frame_);
1451 }
1452 
TEST_F(MainThreadEventQueueTest,UnbufferedDispatchMouseEvent)1453 TEST_F(MainThreadEventQueueTest, UnbufferedDispatchMouseEvent) {
1454   WebMouseEvent mouse_down = SyntheticWebMouseEventBuilder::Build(
1455       WebInputEvent::Type::kMouseDown, 10, 10, 0);
1456   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
1457       WebInputEvent::Type::kMouseMove, 10, 10, 0);
1458   WebMouseEvent mouse_up = SyntheticWebMouseEventBuilder::Build(
1459       WebInputEvent::Type::kMouseUp, 10, 10, 0);
1460 
1461   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1462   EXPECT_EQ(0u, event_queue().size());
1463 
1464   EXPECT_CALL(thread_scheduler_,
1465               DidHandleInputEventOnMainThread(testing::_, testing::_))
1466       .Times(0);
1467 
1468   HandleEvent(mouse_down, blink::mojom::InputEventResultState::kSetNonBlocking);
1469   queue_->RequestUnbufferedInputEvents();
1470   EXPECT_EQ(1u, event_queue().size());
1471   RunPendingTasksWithSimulatedRaf();
1472   EXPECT_TRUE(needs_low_latency_until_pointer_up());
1473   EXPECT_FALSE(needs_main_frame_);
1474 
1475   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1476   queue_->RequestUnbufferedInputEvents();
1477   EXPECT_EQ(1u, event_queue().size());
1478   RunPendingTasksWithSimulatedRaf();
1479   EXPECT_TRUE(needs_low_latency_until_pointer_up());
1480   EXPECT_FALSE(needs_main_frame_);
1481 
1482   HandleEvent(mouse_up, blink::mojom::InputEventResultState::kSetNonBlocking);
1483   queue_->RequestUnbufferedInputEvents();
1484   EXPECT_EQ(1u, event_queue().size());
1485   RunPendingTasksWithSimulatedRaf();
1486   EXPECT_FALSE(needs_low_latency_until_pointer_up());
1487   EXPECT_FALSE(needs_main_frame_);
1488 }
1489 
1490 // This test verifies that the events marked with kRelativeMotionEvent modifier
1491 // are not coalesced with other events. During pointer lock,
1492 // kRelativeMotionEvent is sent to the Renderer only to update the new screen
1493 // position. Events of this kind shouldn't be dispatched or coalesced.
TEST_F(MainThreadEventQueueTest,PointerEventsWithRelativeMotionCoalescing)1494 TEST_F(MainThreadEventQueueTest, PointerEventsWithRelativeMotionCoalescing) {
1495   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
1496       WebInputEvent::Type::kMouseMove, 10, 10, 0);
1497 
1498   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1499   EXPECT_EQ(0u, event_queue().size());
1500 
1501   // Non blocking events are not reported to the scheduler.
1502   EXPECT_CALL(thread_scheduler_,
1503               DidHandleInputEventOnMainThread(testing::_, testing::_))
1504       .Times(0);
1505 
1506   queue_->HasPointerRawUpdateEventHandlers(true);
1507 
1508   // Inject two mouse move events. For each event injected, there will be two
1509   // events in the queue. One for kPointerRawUpdate and another kMouseMove
1510   // event.
1511   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1512   EXPECT_EQ(2u, event_queue().size());
1513   // When another event of the same kind is injected, it is coalesced with the
1514   // previous event, hence queue size doesn't change.
1515   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1516   EXPECT_EQ(2u, event_queue().size());
1517 
1518   // Inject a kRelativeMotionEvent, which cannot be coalesced. Thus, the queue
1519   // size should increase.
1520   WebMouseEvent fake_mouse_move = SyntheticWebMouseEventBuilder::Build(
1521       WebInputEvent::Type::kMouseMove, 10, 10,
1522       blink::WebInputEvent::Modifiers::kRelativeMotionEvent);
1523   HandleEvent(fake_mouse_move,
1524               blink::mojom::InputEventResultState::kSetNonBlocking);
1525   EXPECT_EQ(4u, event_queue().size());
1526 
1527   // Lastly inject another mouse move event. Since it cannot be coalesced with
1528   // previous event, which is a kRelativeMotionEvent, expect the queue size to
1529   // increase again.
1530   HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
1531   EXPECT_EQ(6u, event_queue().size());
1532 
1533   RunPendingTasksWithSimulatedRaf();
1534   EXPECT_EQ(0u, event_queue().size());
1535   EXPECT_FALSE(needs_main_frame_);
1536   EXPECT_FALSE(main_task_runner_->HasPendingTask());
1537 
1538   // For the 4 events injected, verify that the queue size should be 6, that is
1539   // 3 kPointerRawUpdate events and 3 kMouseMove events.
1540   EXPECT_EQ(6u, handled_tasks_.size());
1541   {
1542     // The first event should have a |CoalescedEventSize| of 2, since two events
1543     // of the same kind are coalesced.
1544     EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate,
1545               handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
1546     EXPECT_EQ(2u, handled_tasks_.at(0)->taskAsEvent()->CoalescedEventSize());
1547   }
1548   {
1549     // The second event is a kRelativeMotionEvent, it cannot be coalesced, so
1550     // the |CoalescedEventSize| should be 1.
1551     EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate,
1552               handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
1553     EXPECT_EQ(1u, handled_tasks_.at(1)->taskAsEvent()->CoalescedEventSize());
1554     EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent,
1555               handled_tasks_.at(1)->taskAsEvent()->Event().GetModifiers());
1556   }
1557   {
1558     // The third event cannot be coalesced with the previous kPointerRawUpdate,
1559     // so |CoalescedEventSize| should be 1.
1560     EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate,
1561               handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
1562     EXPECT_EQ(1u, handled_tasks_.at(2)->taskAsEvent()->CoalescedEventSize());
1563   }
1564   {
1565     // The fourth event should have a |CoalescedEventSize| of 2, since two
1566     // events of the same kind are coalesced.
1567     EXPECT_EQ(WebInputEvent::Type::kMouseMove,
1568               handled_tasks_.at(3)->taskAsEvent()->Event().GetType());
1569     EXPECT_EQ(2u, handled_tasks_.at(3)->taskAsEvent()->CoalescedEventSize());
1570   }
1571   {
1572     // The fifth event is a kRelativeMotionEvent, it cannot be coalesced, so
1573     // the |CoalescedEventSize| should be 1.
1574     EXPECT_EQ(WebInputEvent::Type::kMouseMove,
1575               handled_tasks_.at(4)->taskAsEvent()->Event().GetType());
1576     EXPECT_EQ(1u, handled_tasks_.at(4)->taskAsEvent()->CoalescedEventSize());
1577     EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent,
1578               handled_tasks_.at(4)->taskAsEvent()->Event().GetModifiers());
1579   }
1580   {
1581     // The sixth event cannot be coalesced with the previous kMouseMove,
1582     // so |CoalescedEventSize| should be 1.
1583     EXPECT_EQ(WebInputEvent::Type::kMouseMove,
1584               handled_tasks_.at(5)->taskAsEvent()->Event().GetType());
1585     EXPECT_EQ(1u, handled_tasks_.at(5)->taskAsEvent()->CoalescedEventSize());
1586   }
1587 }
1588 
1589 }  // namespace blink
1590