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