Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / input / touch_emulator_unittest.cc
blobd91b1b5beff4f2f344751e313bf138165ef8160c
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"
15 #include "ui/events/gesture_detection/gesture_config_helper.h"
17 #if defined(USE_AURA)
18 #include "ui/aura/env.h"
19 #include "ui/aura/test/test_screen.h"
20 #endif
22 using blink::WebGestureEvent;
23 using blink::WebInputEvent;
24 using blink::WebKeyboardEvent;
25 using blink::WebMouseEvent;
26 using blink::WebMouseWheelEvent;
27 using blink::WebTouchEvent;
28 using blink::WebTouchPoint;
30 namespace content {
32 class TouchEmulatorTest : public testing::Test,
33 public TouchEmulatorClient {
34 public:
35 TouchEmulatorTest()
36 : shift_pressed_(false),
37 mouse_pressed_(false),
38 ack_touches_synchronously_(true),
39 last_mouse_x_(-1),
40 last_mouse_y_(-1) {
41 last_event_time_seconds_ =
42 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
43 event_time_delta_seconds_ = 0.1;
46 virtual ~TouchEmulatorTest() {}
48 // testing::Test
49 virtual void SetUp() OVERRIDE {
50 #if defined(USE_AURA)
51 aura::Env::CreateInstance(true);
52 screen_.reset(aura::TestScreen::Create(gfx::Size()));
53 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
54 #endif
56 emulator_.reset(new TouchEmulator(this));
57 emulator_->Enable();
60 virtual void TearDown() OVERRIDE {
61 emulator_->Disable();
62 EXPECT_EQ("", ExpectedEvents());
64 #if defined(USE_AURA)
65 aura::Env::DeleteInstance();
66 screen_.reset();
67 #endif
70 virtual void ForwardGestureEvent(
71 const blink::WebGestureEvent& event) OVERRIDE {
72 forwarded_events_.push_back(event.type);
75 virtual void ForwardEmulatedTouchEvent(
76 const blink::WebTouchEvent& event) OVERRIDE {
77 forwarded_events_.push_back(event.type);
78 EXPECT_EQ(1U, event.touchesLength);
79 EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
80 EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
81 int expectedCancelable = event.type != WebInputEvent::TouchCancel;
82 EXPECT_EQ(expectedCancelable, event.cancelable);
83 if (ack_touches_synchronously_) {
84 emulator()->HandleTouchEventAck(
85 event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
89 virtual void SetCursor(const WebCursor& cursor) OVERRIDE {}
91 virtual void ShowContextMenuAtPoint(const gfx::Point& point) OVERRIDE {}
93 protected:
94 TouchEmulator* emulator() const {
95 return emulator_.get();
98 int modifiers() const {
99 return shift_pressed_ ? WebInputEvent::ShiftKey : 0;
102 std::string ExpectedEvents() {
103 std::string result;
104 for (size_t i = 0; i < forwarded_events_.size(); ++i) {
105 if (i != 0)
106 result += " ";
107 result += WebInputEventTraits::GetName(forwarded_events_[i]);
109 forwarded_events_.clear();
110 return result;
113 double GetNextEventTimeSeconds() {
114 last_event_time_seconds_ += event_time_delta_seconds_;
115 return last_event_time_seconds_;
118 void set_event_time_delta_seconds_(double delta) {
119 event_time_delta_seconds_ = delta;
122 void SendKeyboardEvent(WebInputEvent::Type type) {
123 WebKeyboardEvent event;
124 event.timeStampSeconds = GetNextEventTimeSeconds();
125 event.type = type;
126 event.modifiers = modifiers();
127 emulator()->HandleKeyboardEvent(event);
130 void PressShift() {
131 DCHECK(!shift_pressed_);
132 shift_pressed_ = true;
133 SendKeyboardEvent(WebInputEvent::KeyDown);
136 void ReleaseShift() {
137 DCHECK(shift_pressed_);
138 shift_pressed_ = false;
139 SendKeyboardEvent(WebInputEvent::KeyUp);
142 void SendMouseEvent(WebInputEvent::Type type, int x, int y) {
143 WebMouseEvent event;
144 event.timeStampSeconds = GetNextEventTimeSeconds();
145 event.type = type;
146 event.button = mouse_pressed_ ? WebMouseEvent::ButtonLeft :
147 WebMouseEvent::ButtonNone;
148 event.modifiers = modifiers();
149 last_mouse_x_ = x;
150 last_mouse_y_ = y;
151 event.x = event.windowX = event.globalX = x;
152 event.y = event.windowY = event.globalY = y;
153 emulator()->HandleMouseEvent(event);
156 bool SendMouseWheelEvent() {
157 WebMouseWheelEvent event;
158 event.type = WebInputEvent::MouseWheel;
159 event.timeStampSeconds = GetNextEventTimeSeconds();
160 // Return whether mouse wheel is forwarded.
161 return !emulator()->HandleMouseWheelEvent(event);
164 void MouseDown(int x, int y) {
165 DCHECK(!mouse_pressed_);
166 if (x != last_mouse_x_ || y != last_mouse_y_)
167 SendMouseEvent(WebInputEvent::MouseMove, x, y);
168 mouse_pressed_ = true;
169 SendMouseEvent(WebInputEvent::MouseDown, x, y);
172 void MouseDrag(int x, int y) {
173 DCHECK(mouse_pressed_);
174 SendMouseEvent(WebInputEvent::MouseMove, x, y);
177 void MouseMove(int x, int y) {
178 DCHECK(!mouse_pressed_);
179 SendMouseEvent(WebInputEvent::MouseMove, x, y);
182 void MouseUp(int x, int y) {
183 DCHECK(mouse_pressed_);
184 if (x != last_mouse_x_ || y != last_mouse_y_)
185 SendMouseEvent(WebInputEvent::MouseMove, x, y);
186 SendMouseEvent(WebInputEvent::MouseUp, x, y);
187 mouse_pressed_ = false;
190 bool TouchStart(int x, int y, bool ack) {
191 return SendTouchEvent(
192 WebInputEvent::TouchStart, WebTouchPoint::StatePressed, x, y, ack);
195 bool TouchMove(int x, int y, bool ack) {
196 return SendTouchEvent(
197 WebInputEvent::TouchMove, WebTouchPoint::StateMoved, x, y, ack);
200 bool TouchEnd(int x, int y, bool ack) {
201 return SendTouchEvent(
202 WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, x, y, ack);
205 WebTouchEvent MakeTouchEvent(WebInputEvent::Type type,
206 WebTouchPoint::State state, int x, int y) {
207 WebTouchEvent event;
208 event.type = type;
209 event.timeStampSeconds = GetNextEventTimeSeconds();
210 event.touchesLength = 1;
211 event.touches[0].id = 0;
212 event.touches[0].state = state;
213 event.touches[0].position.x = x;
214 event.touches[0].position.y = y;
215 event.touches[0].screenPosition.x = x;
216 event.touches[0].screenPosition.y = y;
217 return event;
220 bool SendTouchEvent(WebInputEvent::Type type, WebTouchPoint::State state,
221 int x, int y, bool ack) {
222 WebTouchEvent event = MakeTouchEvent(type, state, x, y);
223 if (emulator()->HandleTouchEvent(event)) {
224 // Touch event is not forwarded.
225 return false;
228 if (ack) {
229 // Can't send ack if there are some pending acks.
230 DCHECK(!touch_events_to_ack_.size());
232 // Touch event is forwarded, ack should not be handled by emulator.
233 EXPECT_FALSE(emulator()->HandleTouchEventAck(
234 event, INPUT_EVENT_ACK_STATE_CONSUMED));
235 } else {
236 touch_events_to_ack_.push_back(event);
238 return true;
241 void AckOldestTouchEvent() {
242 DCHECK(touch_events_to_ack_.size());
243 WebTouchEvent event = touch_events_to_ack_[0];
244 touch_events_to_ack_.erase(touch_events_to_ack_.begin());
245 // Emulator should not handle ack from native stream.
246 EXPECT_FALSE(emulator()->HandleTouchEventAck(
247 event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
250 void DisableSynchronousTouchAck() { ack_touches_synchronously_ = false; }
252 private:
253 scoped_ptr<TouchEmulator> emulator_;
254 std::vector<WebInputEvent::Type> forwarded_events_;
255 #if defined(USE_AURA)
256 scoped_ptr<gfx::Screen> screen_;
257 #endif
258 double last_event_time_seconds_;
259 double event_time_delta_seconds_;
260 bool shift_pressed_;
261 bool mouse_pressed_;
262 bool ack_touches_synchronously_;
263 int last_mouse_x_;
264 int last_mouse_y_;
265 std::vector<WebTouchEvent> touch_events_to_ack_;
266 base::MessageLoopForUI message_loop_;
270 TEST_F(TouchEmulatorTest, NoTouches) {
271 MouseMove(100, 200);
272 MouseMove(300, 300);
273 EXPECT_EQ("", ExpectedEvents());
276 TEST_F(TouchEmulatorTest, Touch) {
277 MouseMove(100, 200);
278 EXPECT_EQ("", ExpectedEvents());
279 MouseDown(100, 200);
280 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
281 MouseUp(200, 200);
282 EXPECT_EQ(
283 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
284 " TouchEnd GestureScrollEnd",
285 ExpectedEvents());
288 TEST_F(TouchEmulatorTest, MultipleTouches) {
289 MouseMove(100, 200);
290 EXPECT_EQ("", ExpectedEvents());
291 MouseDown(100, 200);
292 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
293 MouseUp(200, 200);
294 EXPECT_EQ(
295 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
296 " TouchEnd GestureScrollEnd",
297 ExpectedEvents());
298 MouseMove(300, 200);
299 MouseMove(200, 200);
300 EXPECT_EQ("", ExpectedEvents());
301 MouseDown(300, 200);
302 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
303 MouseDrag(300, 300);
304 EXPECT_EQ(
305 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
306 ExpectedEvents());
307 MouseDrag(300, 400);
308 EXPECT_EQ("TouchMove GestureScrollUpdate", ExpectedEvents());
309 MouseUp(300, 500);
310 EXPECT_EQ(
311 "TouchMove GestureScrollUpdate TouchEnd GestureScrollEnd",
312 ExpectedEvents());
315 TEST_F(TouchEmulatorTest, Pinch) {
316 MouseDown(100, 200);
317 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
318 MouseDrag(200, 200);
319 EXPECT_EQ(
320 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
321 ExpectedEvents());
322 PressShift();
323 EXPECT_EQ("", ExpectedEvents());
324 MouseDrag(300, 200);
325 EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
326 ReleaseShift();
327 EXPECT_EQ("", ExpectedEvents());
328 MouseDrag(400, 200);
329 EXPECT_EQ(
330 "TouchMove GesturePinchEnd GestureScrollUpdate",
331 ExpectedEvents());
332 MouseUp(400, 200);
333 EXPECT_EQ("TouchEnd GestureScrollEnd", ExpectedEvents());
336 TEST_F(TouchEmulatorTest, CancelWithDelayedAck) {
337 DisableSynchronousTouchAck();
339 // Simulate a sequence that is interrupted by |CancelTouch()|.
340 MouseDown(100, 200);
341 EXPECT_EQ("TouchStart", ExpectedEvents());
342 MouseDrag(200, 200);
343 EXPECT_EQ("TouchMove", ExpectedEvents());
344 emulator()->CancelTouch();
345 EXPECT_EQ("TouchCancel", ExpectedEvents());
346 // The mouse up should have no effect as the sequence was already cancelled.
347 MouseUp(400, 200);
348 EXPECT_EQ("", ExpectedEvents());
350 // Simulate a sequence that fully completes before |CancelTouch()|.
351 MouseDown(100, 200);
352 EXPECT_EQ("TouchStart", ExpectedEvents());
353 MouseUp(100, 200);
354 EXPECT_EQ("TouchEnd", ExpectedEvents());
355 // |CancelTouch| should have no effect as the sequence was already terminated.
356 emulator()->CancelTouch();
357 EXPECT_EQ("", ExpectedEvents());
360 TEST_F(TouchEmulatorTest, DisableAndReenable) {
361 MouseDown(100, 200);
362 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
363 MouseDrag(200, 200);
364 EXPECT_EQ(
365 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
366 ExpectedEvents());
367 PressShift();
368 MouseDrag(300, 200);
369 EXPECT_EQ("TouchMove GesturePinchBegin", ExpectedEvents());
371 // Disable while pinch is in progress.
372 emulator()->Disable();
373 EXPECT_EQ("TouchCancel GesturePinchEnd GestureScrollEnd", ExpectedEvents());
374 MouseUp(300, 200);
375 ReleaseShift();
376 MouseMove(300, 300);
377 EXPECT_EQ("", ExpectedEvents());
379 emulator()->Enable();
380 MouseDown(300, 300);
381 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
382 MouseDrag(300, 400);
383 EXPECT_EQ(
384 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
385 ExpectedEvents());
387 // Disable while scroll is in progress.
388 emulator()->Disable();
389 EXPECT_EQ("TouchCancel GestureScrollEnd", ExpectedEvents());
392 TEST_F(TouchEmulatorTest, MouseMovesDropped) {
393 MouseMove(100, 200);
394 EXPECT_EQ("", ExpectedEvents());
395 MouseDown(100, 200);
396 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
398 // Mouse move after mouse down is never dropped.
399 set_event_time_delta_seconds_(0.001);
400 MouseDrag(200, 200);
401 EXPECT_EQ(
402 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
403 ExpectedEvents());
405 // The following mouse moves are dropped.
406 MouseDrag(300, 200);
407 EXPECT_EQ("", ExpectedEvents());
408 MouseDrag(350, 200);
409 EXPECT_EQ("", ExpectedEvents());
411 // Dispatching again.
412 set_event_time_delta_seconds_(0.1);
413 MouseDrag(400, 200);
414 EXPECT_EQ(
415 "TouchMove GestureScrollUpdate",
416 ExpectedEvents());
417 MouseUp(400, 200);
418 EXPECT_EQ(
419 "TouchEnd GestureScrollEnd",
420 ExpectedEvents());
423 TEST_F(TouchEmulatorTest, MouseWheel) {
424 MouseMove(100, 200);
425 EXPECT_EQ("", ExpectedEvents());
426 EXPECT_TRUE(SendMouseWheelEvent());
427 MouseDown(100, 200);
428 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
429 EXPECT_FALSE(SendMouseWheelEvent());
430 MouseUp(100, 200);
431 EXPECT_EQ("TouchEnd GestureShowPress GestureTap", ExpectedEvents());
432 EXPECT_TRUE(SendMouseWheelEvent());
433 MouseDown(300, 200);
434 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
435 EXPECT_FALSE(SendMouseWheelEvent());
436 emulator()->Disable();
437 EXPECT_EQ("TouchCancel GestureTapCancel", ExpectedEvents());
438 EXPECT_TRUE(SendMouseWheelEvent());
439 emulator()->Enable();
440 EXPECT_TRUE(SendMouseWheelEvent());
443 TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
444 // Native stream should be blocked while emulated is active.
445 MouseMove(100, 200);
446 EXPECT_EQ("", ExpectedEvents());
447 MouseDown(100, 200);
448 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
449 EXPECT_FALSE(TouchStart(10, 10, true));
450 EXPECT_FALSE(TouchMove(20, 20, true));
451 MouseUp(200, 200);
452 EXPECT_EQ(
453 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
454 " TouchEnd GestureScrollEnd",
455 ExpectedEvents());
456 EXPECT_FALSE(TouchEnd(20, 20, true));
458 // Emulated stream should be blocked while native is active.
459 EXPECT_TRUE(TouchStart(10, 10, true));
460 EXPECT_TRUE(TouchMove(20, 20, true));
461 MouseDown(300, 200);
462 EXPECT_EQ("", ExpectedEvents());
463 // Re-enabling in the middle of a touch sequence should not affect this.
464 emulator()->Disable();
465 emulator()->Enable();
466 MouseDrag(300, 300);
467 EXPECT_EQ("", ExpectedEvents());
468 MouseUp(300, 300);
469 EXPECT_EQ("", ExpectedEvents());
470 EXPECT_TRUE(TouchEnd(20, 20, true));
471 EXPECT_EQ("", ExpectedEvents());
473 // Late ack for TouchEnd should not mess things up.
474 EXPECT_TRUE(TouchStart(10, 10, false));
475 EXPECT_TRUE(TouchMove(20, 20, false));
476 emulator()->Disable();
477 EXPECT_TRUE(TouchEnd(20, 20, false));
478 EXPECT_TRUE(TouchStart(30, 30, false));
479 AckOldestTouchEvent(); // TouchStart.
480 emulator()->Enable();
481 AckOldestTouchEvent(); // TouchMove.
482 AckOldestTouchEvent(); // TouchEnd.
483 MouseDown(300, 200);
484 EXPECT_EQ("", ExpectedEvents());
485 MouseDrag(300, 300);
486 EXPECT_EQ("", ExpectedEvents());
487 MouseUp(300, 300);
488 EXPECT_EQ("", ExpectedEvents());
489 AckOldestTouchEvent(); // TouchStart.
490 MouseDown(300, 200);
491 EXPECT_EQ("", ExpectedEvents());
492 EXPECT_TRUE(TouchMove(30, 40, true));
493 EXPECT_TRUE(TouchEnd(30, 40, true));
494 MouseUp(300, 200);
495 EXPECT_EQ("", ExpectedEvents());
497 // Emulation should be back to normal.
498 MouseDown(100, 200);
499 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
500 MouseUp(200, 200);
501 EXPECT_EQ(
502 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
503 " TouchEnd GestureScrollEnd",
504 ExpectedEvents());
507 TEST_F(TouchEmulatorTest, MultipleTouchStreamsLateEnable) {
508 // Enabling in the middle of native touch sequence should be handled.
509 // Send artificial late TouchEnd ack, like it is the first thing emulator
510 // does see.
511 WebTouchEvent event = MakeTouchEvent(
512 WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, 10, 10);
513 EXPECT_FALSE(emulator()->HandleTouchEventAck(
514 event, INPUT_EVENT_ACK_STATE_CONSUMED));
516 MouseDown(100, 200);
517 EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
518 MouseUp(200, 200);
519 EXPECT_EQ(
520 "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
521 " TouchEnd GestureScrollEnd",
522 ExpectedEvents());
525 } // namespace content