Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / input / touch_emulator_unittest.cc
blob4b8bd1d5d6e4b9bf6f7bff1267288d9c8364e6b4
1 // Copyright 2014 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.
5 #include <vector>
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/time.h"
11 #include "content/browser/renderer_host/input/touch_emulator.h"
12 #include "content/browser/renderer_host/input/touch_emulator_client.h"
13 #include "content/common/input/web_input_event_traits.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 #if defined(USE_AURA)
17 #include "ui/aura/env.h"
18 #include "ui/aura/test/test_screen.h"
19 #endif
21 using blink::WebGestureEvent;
22 using blink::WebInputEvent;
23 using blink::WebKeyboardEvent;
24 using blink::WebMouseEvent;
25 using blink::WebMouseWheelEvent;
26 using blink::WebTouchEvent;
27 using blink::WebTouchPoint;
29 namespace content {
31 class TouchEmulatorTest : public testing::Test,
32 public TouchEmulatorClient {
33 public:
34 TouchEmulatorTest()
35 : shift_pressed_(false),
36 mouse_pressed_(false),
37 ack_touches_synchronously_(true),
38 last_mouse_x_(-1),
39 last_mouse_y_(-1) {
40 last_event_time_seconds_ =
41 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
42 event_time_delta_seconds_ = 0.1;
45 ~TouchEmulatorTest() override {}
47 // testing::Test
48 void SetUp() override {
49 #if defined(USE_AURA)
50 aura::Env::CreateInstance(true);
51 screen_.reset(aura::TestScreen::Create(gfx::Size()));
52 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
53 #endif
55 emulator_.reset(new TouchEmulator(this));
56 emulator_->SetDoubleTapSupportForPageEnabled(false);
57 emulator_->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
60 void TearDown() override {
61 emulator_->Disable();
62 EXPECT_EQ("", ExpectedEvents());
64 #if defined(USE_AURA)
65 aura::Env::DeleteInstance();
66 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, nullptr);
67 screen_.reset();
68 #endif
71 void ForwardGestureEvent(const blink::WebGestureEvent& event) override {
72 forwarded_events_.push_back(event.type);
75 void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) override {
76 forwarded_events_.push_back(event.type);
77 EXPECT_EQ(1U, event.touchesLength);
78 EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
79 EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
80 bool expected_cancelable = event.type != WebInputEvent::TouchCancel;
81 EXPECT_EQ(expected_cancelable, !!event.cancelable);
82 if (ack_touches_synchronously_) {
83 emulator()->HandleTouchEventAck(
84 event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
88 void SetCursor(const WebCursor& cursor) override {}
90 void ShowContextMenuAtPoint(const gfx::Point& point) override {}
92 protected:
93 TouchEmulator* emulator() const {
94 return emulator_.get();
97 int modifiers() const {
98 return shift_pressed_ ? WebInputEvent::ShiftKey : 0;
101 std::string ExpectedEvents() {
102 std::string result;
103 for (size_t i = 0; i < forwarded_events_.size(); ++i) {
104 if (i != 0)
105 result += " ";
106 result += WebInputEventTraits::GetName(forwarded_events_[i]);
108 forwarded_events_.clear();
109 return result;
112 double GetNextEventTimeSeconds() {
113 last_event_time_seconds_ += event_time_delta_seconds_;
114 return last_event_time_seconds_;
117 void set_event_time_delta_seconds_(double delta) {
118 event_time_delta_seconds_ = delta;
121 void SendKeyboardEvent(WebInputEvent::Type type) {
122 WebKeyboardEvent event;
123 event.timeStampSeconds = GetNextEventTimeSeconds();
124 event.type = type;
125 event.modifiers = modifiers();
126 emulator()->HandleKeyboardEvent(event);
129 void PressShift() {
130 DCHECK(!shift_pressed_);
131 shift_pressed_ = true;
132 SendKeyboardEvent(WebInputEvent::KeyDown);
135 void ReleaseShift() {
136 DCHECK(shift_pressed_);
137 shift_pressed_ = false;
138 SendKeyboardEvent(WebInputEvent::KeyUp);
141 void SendMouseEvent(WebInputEvent::Type type, int x, int y) {
142 WebMouseEvent event;
143 event.timeStampSeconds = GetNextEventTimeSeconds();
144 event.type = type;
145 event.button = mouse_pressed_ ? WebMouseEvent::ButtonLeft :
146 WebMouseEvent::ButtonNone;
147 event.modifiers = modifiers();
148 last_mouse_x_ = x;
149 last_mouse_y_ = y;
150 event.x = event.windowX = event.globalX = x;
151 event.y = event.windowY = event.globalY = y;
152 emulator()->HandleMouseEvent(event);
155 bool SendMouseWheelEvent() {
156 WebMouseWheelEvent event;
157 event.type = WebInputEvent::MouseWheel;
158 event.timeStampSeconds = GetNextEventTimeSeconds();
159 // Return whether mouse wheel is forwarded.
160 return !emulator()->HandleMouseWheelEvent(event);
163 void MouseDown(int x, int y) {
164 DCHECK(!mouse_pressed_);
165 if (x != last_mouse_x_ || y != last_mouse_y_)
166 SendMouseEvent(WebInputEvent::MouseMove, x, y);
167 mouse_pressed_ = true;
168 SendMouseEvent(WebInputEvent::MouseDown, x, y);
171 void MouseDrag(int x, int y) {
172 DCHECK(mouse_pressed_);
173 SendMouseEvent(WebInputEvent::MouseMove, x, y);
176 void MouseMove(int x, int y) {
177 DCHECK(!mouse_pressed_);
178 SendMouseEvent(WebInputEvent::MouseMove, x, y);
181 void MouseUp(int x, int y) {
182 DCHECK(mouse_pressed_);
183 if (x != last_mouse_x_ || y != last_mouse_y_)
184 SendMouseEvent(WebInputEvent::MouseMove, x, y);
185 SendMouseEvent(WebInputEvent::MouseUp, x, y);
186 mouse_pressed_ = false;
189 bool TouchStart(int x, int y, bool ack) {
190 return SendTouchEvent(
191 WebInputEvent::TouchStart, WebTouchPoint::StatePressed, x, y, ack);
194 bool TouchMove(int x, int y, bool ack) {
195 return SendTouchEvent(
196 WebInputEvent::TouchMove, WebTouchPoint::StateMoved, x, y, ack);
199 bool TouchEnd(int x, int y, bool ack) {
200 return SendTouchEvent(
201 WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, x, y, ack);
204 WebTouchEvent MakeTouchEvent(WebInputEvent::Type type,
205 WebTouchPoint::State state, int x, int y) {
206 WebTouchEvent event;
207 event.type = type;
208 event.timeStampSeconds = GetNextEventTimeSeconds();
209 event.touchesLength = 1;
210 event.touches[0].id = 0;
211 event.touches[0].state = state;
212 event.touches[0].position.x = x;
213 event.touches[0].position.y = y;
214 event.touches[0].screenPosition.x = x;
215 event.touches[0].screenPosition.y = y;
216 return event;
219 bool SendTouchEvent(WebInputEvent::Type type, WebTouchPoint::State state,
220 int x, int y, bool ack) {
221 WebTouchEvent event = MakeTouchEvent(type, state, x, y);
222 if (emulator()->HandleTouchEvent(event)) {
223 // Touch event is not forwarded.
224 return false;
227 if (ack) {
228 // Can't send ack if there are some pending acks.
229 DCHECK(!touch_events_to_ack_.size());
231 // Touch event is forwarded, ack should not be handled by emulator.
232 EXPECT_FALSE(emulator()->HandleTouchEventAck(
233 event, INPUT_EVENT_ACK_STATE_CONSUMED));
234 } else {
235 touch_events_to_ack_.push_back(event);
237 return true;
240 void AckOldestTouchEvent() {
241 DCHECK(touch_events_to_ack_.size());
242 WebTouchEvent event = touch_events_to_ack_[0];
243 touch_events_to_ack_.erase(touch_events_to_ack_.begin());
244 // Emulator should not handle ack from native stream.
245 EXPECT_FALSE(emulator()->HandleTouchEventAck(
246 event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
249 void DisableSynchronousTouchAck() { ack_touches_synchronously_ = false; }
251 private:
252 scoped_ptr<TouchEmulator> emulator_;
253 std::vector<WebInputEvent::Type> forwarded_events_;
254 #if defined(USE_AURA)
255 scoped_ptr<gfx::Screen> screen_;
256 #endif
257 double last_event_time_seconds_;
258 double event_time_delta_seconds_;
259 bool shift_pressed_;
260 bool mouse_pressed_;
261 bool ack_touches_synchronously_;
262 int last_mouse_x_;
263 int last_mouse_y_;
264 std::vector<WebTouchEvent> touch_events_to_ack_;
265 base::MessageLoopForUI message_loop_;
269 TEST_F(TouchEmulatorTest, NoTouches) {
270 MouseMove(100, 200);
271 MouseMove(300, 300);
272 EXPECT_EQ("", ExpectedEvents());
275 TEST_F(TouchEmulatorTest, Touch) {
276 MouseMove(100, 200);
277 EXPECT_EQ("", ExpectedEvents());
278 MouseDown(100, 200);
279 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
280 MouseUp(200, 200);
281 EXPECT_EQ(
282 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
283 " TouchEnd GestureScrollEnd",
284 ExpectedEvents());
287 TEST_F(TouchEmulatorTest, DoubleTapSupport) {
288 emulator()->SetDoubleTapSupportForPageEnabled(true);
289 MouseMove(100, 200);
290 EXPECT_EQ("", ExpectedEvents());
291 MouseDown(100, 200);
292 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
293 MouseUp(100, 200);
294 EXPECT_EQ("TouchEnd GestureTapUnconfirmed", ExpectedEvents());
295 MouseDown(100, 200);
296 EXPECT_EQ("TouchStart GestureTapCancel GestureTapDown", ExpectedEvents());
297 MouseUp(100, 200);
298 EXPECT_EQ("TouchEnd GestureTapCancel GestureDoubleTap", ExpectedEvents());
301 TEST_F(TouchEmulatorTest, MultipleTouches) {
302 MouseMove(100, 200);
303 EXPECT_EQ("", ExpectedEvents());
304 MouseDown(100, 200);
305 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
306 MouseUp(200, 200);
307 EXPECT_EQ(
308 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
309 " TouchEnd GestureScrollEnd",
310 ExpectedEvents());
311 MouseMove(300, 200);
312 MouseMove(200, 200);
313 EXPECT_EQ("", ExpectedEvents());
314 MouseDown(300, 200);
315 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
316 MouseDrag(300, 300);
317 EXPECT_EQ(
318 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
319 ExpectedEvents());
320 MouseDrag(300, 400);
321 EXPECT_EQ("TouchMove GestureScrollUpdate", ExpectedEvents());
322 MouseUp(300, 500);
323 EXPECT_EQ(
324 "TouchMove GestureScrollUpdate TouchEnd GestureScrollEnd",
325 ExpectedEvents());
328 TEST_F(TouchEmulatorTest, Pinch) {
329 MouseDown(100, 200);
330 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
331 MouseDrag(200, 200);
332 EXPECT_EQ(
333 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
334 ExpectedEvents());
335 PressShift();
336 EXPECT_EQ("", ExpectedEvents());
337 MouseDrag(300, 200);
338 EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
339 ReleaseShift();
340 EXPECT_EQ("", ExpectedEvents());
341 MouseDrag(400, 200);
342 EXPECT_EQ(
343 "TouchMove GesturePinchEnd GestureScrollUpdate",
344 ExpectedEvents());
345 MouseUp(400, 200);
346 EXPECT_EQ("TouchEnd GestureScrollEnd", ExpectedEvents());
349 TEST_F(TouchEmulatorTest, CancelWithDelayedAck) {
350 DisableSynchronousTouchAck();
352 // Simulate a sequence that is interrupted by |CancelTouch()|.
353 MouseDown(100, 200);
354 EXPECT_EQ("TouchStart", ExpectedEvents());
355 MouseDrag(200, 200);
356 EXPECT_EQ("TouchMove", ExpectedEvents());
357 emulator()->CancelTouch();
358 EXPECT_EQ("TouchCancel", ExpectedEvents());
359 // The mouse up should have no effect as the sequence was already cancelled.
360 MouseUp(400, 200);
361 EXPECT_EQ("", ExpectedEvents());
363 // Simulate a sequence that fully completes before |CancelTouch()|.
364 MouseDown(100, 200);
365 EXPECT_EQ("TouchStart", ExpectedEvents());
366 MouseUp(100, 200);
367 EXPECT_EQ("TouchEnd", ExpectedEvents());
368 // |CancelTouch| should have no effect as the sequence was already terminated.
369 emulator()->CancelTouch();
370 EXPECT_EQ("", ExpectedEvents());
373 TEST_F(TouchEmulatorTest, DisableAndReenable) {
374 MouseDown(100, 200);
375 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
376 MouseDrag(200, 200);
377 EXPECT_EQ(
378 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
379 ExpectedEvents());
380 PressShift();
381 MouseDrag(300, 200);
382 EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
384 // Disable while pinch is in progress.
385 emulator()->Disable();
386 EXPECT_EQ("TouchCancel GesturePinchEnd GestureScrollEnd", ExpectedEvents());
387 MouseUp(300, 200);
388 ReleaseShift();
389 MouseMove(300, 300);
390 EXPECT_EQ("", ExpectedEvents());
392 emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
393 MouseDown(300, 300);
394 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
395 MouseDrag(300, 400);
396 EXPECT_EQ(
397 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
398 ExpectedEvents());
400 // Disable while scroll is in progress.
401 emulator()->Disable();
402 EXPECT_EQ("TouchCancel GestureScrollEnd", ExpectedEvents());
405 TEST_F(TouchEmulatorTest, DisableAndReenableDifferentConfig) {
406 MouseDown(100, 200);
407 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
408 MouseDrag(200, 200);
409 EXPECT_EQ(
410 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
411 ExpectedEvents());
412 PressShift();
413 MouseDrag(300, 200);
414 EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
416 // Disable while pinch is in progress.
417 emulator()->Disable();
418 EXPECT_EQ("TouchCancel GesturePinchEnd GestureScrollEnd", ExpectedEvents());
419 MouseUp(300, 200);
420 ReleaseShift();
421 MouseMove(300, 300);
422 EXPECT_EQ("", ExpectedEvents());
424 emulator()->Enable(ui::GestureProviderConfigType::GENERIC_DESKTOP);
425 MouseDown(300, 300);
426 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
427 MouseDrag(300, 400);
428 EXPECT_EQ(
429 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
430 ExpectedEvents());
432 // Disable while scroll is in progress.
433 emulator()->Disable();
434 EXPECT_EQ("TouchCancel GestureScrollEnd", ExpectedEvents());
437 TEST_F(TouchEmulatorTest, MouseMovesDropped) {
438 MouseMove(100, 200);
439 EXPECT_EQ("", ExpectedEvents());
440 MouseDown(100, 200);
441 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
443 // Mouse move after mouse down is never dropped.
444 set_event_time_delta_seconds_(0.001);
445 MouseDrag(200, 200);
446 EXPECT_EQ(
447 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
448 ExpectedEvents());
450 // The following mouse moves are dropped.
451 MouseDrag(300, 200);
452 EXPECT_EQ("", ExpectedEvents());
453 MouseDrag(350, 200);
454 EXPECT_EQ("", ExpectedEvents());
456 // Dispatching again.
457 set_event_time_delta_seconds_(0.1);
458 MouseDrag(400, 200);
459 EXPECT_EQ(
460 "TouchMove GestureScrollUpdate",
461 ExpectedEvents());
462 MouseUp(400, 200);
463 EXPECT_EQ(
464 "TouchEnd GestureScrollEnd",
465 ExpectedEvents());
468 TEST_F(TouchEmulatorTest, MouseWheel) {
469 MouseMove(100, 200);
470 EXPECT_EQ("", ExpectedEvents());
471 EXPECT_TRUE(SendMouseWheelEvent());
472 MouseDown(100, 200);
473 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
474 EXPECT_FALSE(SendMouseWheelEvent());
475 MouseUp(100, 200);
476 EXPECT_EQ("TouchEnd GestureShowPress GestureTap", ExpectedEvents());
477 EXPECT_TRUE(SendMouseWheelEvent());
478 MouseDown(300, 200);
479 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
480 EXPECT_FALSE(SendMouseWheelEvent());
481 emulator()->Disable();
482 EXPECT_EQ("TouchCancel GestureTapCancel", ExpectedEvents());
483 EXPECT_TRUE(SendMouseWheelEvent());
484 emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
485 EXPECT_TRUE(SendMouseWheelEvent());
488 TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
489 // Native stream should be blocked while emulated is active.
490 MouseMove(100, 200);
491 EXPECT_EQ("", ExpectedEvents());
492 MouseDown(100, 200);
493 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
494 EXPECT_FALSE(TouchStart(10, 10, true));
495 EXPECT_FALSE(TouchMove(20, 20, true));
496 MouseUp(200, 200);
497 EXPECT_EQ(
498 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
499 " TouchEnd GestureScrollEnd",
500 ExpectedEvents());
501 EXPECT_FALSE(TouchEnd(20, 20, true));
503 // Emulated stream should be blocked while native is active.
504 EXPECT_TRUE(TouchStart(10, 10, true));
505 EXPECT_TRUE(TouchMove(20, 20, true));
506 MouseDown(300, 200);
507 EXPECT_EQ("", ExpectedEvents());
508 // Re-enabling in the middle of a touch sequence should not affect this.
509 emulator()->Disable();
510 emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
511 MouseDrag(300, 300);
512 EXPECT_EQ("", ExpectedEvents());
513 MouseUp(300, 300);
514 EXPECT_EQ("", ExpectedEvents());
515 EXPECT_TRUE(TouchEnd(20, 20, true));
516 EXPECT_EQ("", ExpectedEvents());
518 // Late ack for TouchEnd should not mess things up.
519 EXPECT_TRUE(TouchStart(10, 10, false));
520 EXPECT_TRUE(TouchMove(20, 20, false));
521 emulator()->Disable();
522 EXPECT_TRUE(TouchEnd(20, 20, false));
523 EXPECT_TRUE(TouchStart(30, 30, false));
524 AckOldestTouchEvent(); // TouchStart.
525 emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
526 AckOldestTouchEvent(); // TouchMove.
527 AckOldestTouchEvent(); // TouchEnd.
528 MouseDown(300, 200);
529 EXPECT_EQ("", ExpectedEvents());
530 MouseDrag(300, 300);
531 EXPECT_EQ("", ExpectedEvents());
532 MouseUp(300, 300);
533 EXPECT_EQ("", ExpectedEvents());
534 AckOldestTouchEvent(); // TouchStart.
535 MouseDown(300, 200);
536 EXPECT_EQ("", ExpectedEvents());
537 EXPECT_TRUE(TouchMove(30, 40, true));
538 EXPECT_TRUE(TouchEnd(30, 40, true));
539 MouseUp(300, 200);
540 EXPECT_EQ("", ExpectedEvents());
542 // Emulation should be back to normal.
543 MouseDown(100, 200);
544 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
545 MouseUp(200, 200);
546 EXPECT_EQ(
547 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
548 " TouchEnd GestureScrollEnd",
549 ExpectedEvents());
552 TEST_F(TouchEmulatorTest, MultipleTouchStreamsLateEnable) {
553 // Enabling in the middle of native touch sequence should be handled.
554 // Send artificial late TouchEnd ack, like it is the first thing emulator
555 // does see.
556 WebTouchEvent event = MakeTouchEvent(
557 WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, 10, 10);
558 EXPECT_FALSE(emulator()->HandleTouchEventAck(
559 event, INPUT_EVENT_ACK_STATE_CONSUMED));
561 MouseDown(100, 200);
562 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
563 MouseUp(200, 200);
564 EXPECT_EQ(
565 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
566 " TouchEnd GestureScrollEnd",
567 ExpectedEvents());
570 TEST_F(TouchEmulatorTest, CancelAfterDisableDoesNotCrash) {
571 DisableSynchronousTouchAck();
572 MouseDown(100, 200);
573 emulator()->Disable();
574 EXPECT_EQ("TouchStart TouchCancel", ExpectedEvents());
575 emulator()->CancelTouch();
578 } // namespace content