1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/time/time.h" 8 #include "content/browser/renderer_host/input/synthetic_gesture.h" 9 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h" 10 #include "content/browser/renderer_host/input/synthetic_gesture_target.h" 11 #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" 12 #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" 13 #include "content/browser/renderer_host/input/synthetic_tap_gesture.h" 14 #include "content/browser/renderer_host/render_widget_host_delegate.h" 15 #include "content/common/input/synthetic_pinch_gesture_params.h" 16 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" 17 #include "content/common/input/synthetic_tap_gesture_params.h" 18 #include "content/public/test/mock_render_process_host.h" 19 #include "content/public/test/test_browser_context.h" 20 #include "content/test/test_render_view_host.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "third_party/WebKit/public/web/WebInputEvent.h" 23 #include "ui/gfx/point.h" 24 #include "ui/gfx/point_f.h" 25 #include "ui/gfx/vector2d.h" 26 #include "ui/gfx/vector2d_f.h" 27 28 using blink::WebInputEvent; 29 using blink::WebMouseEvent; 30 using blink::WebMouseWheelEvent; 31 using blink::WebTouchEvent; 32 33 namespace content { 34 35 namespace { 36 37 const int kFlushInputRateInMs = 16; 38 const int kPointerAssumedStoppedTimeMs = 43; 39 const float kTouchSlopInDips = 7.0f; 40 const float kMinScalingSpanInDips = 27.5f; 41 42 class MockSyntheticGesture : public SyntheticGesture { 43 public: 44 MockSyntheticGesture(bool* finished, int num_steps) 45 : finished_(finished), 46 num_steps_(num_steps), 47 step_count_(0) { 48 *finished_ = false; 49 } 50 virtual ~MockSyntheticGesture() {} 51 52 virtual Result ForwardInputEvents(const base::TimeTicks& timestamp, 53 SyntheticGestureTarget* target) OVERRIDE { 54 step_count_++; 55 if (step_count_ == num_steps_) { 56 *finished_ = true; 57 return SyntheticGesture::GESTURE_FINISHED; 58 } else if (step_count_ > num_steps_) { 59 *finished_ = true; 60 // Return arbitrary failure. 61 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; 62 } 63 64 return SyntheticGesture::GESTURE_RUNNING; 65 } 66 67 protected: 68 bool* finished_; 69 int num_steps_; 70 int step_count_; 71 }; 72 73 class MockSyntheticGestureTarget : public SyntheticGestureTarget { 74 public: 75 MockSyntheticGestureTarget() 76 : flush_requested_(false), 77 pointer_assumed_stopped_time_ms_(kPointerAssumedStoppedTimeMs) {} 78 virtual ~MockSyntheticGestureTarget() {} 79 80 // SyntheticGestureTarget: 81 virtual void DispatchInputEventToPlatform( 82 const WebInputEvent& event) OVERRIDE {} 83 84 virtual void SetNeedsFlush() OVERRIDE { 85 flush_requested_ = true; 86 } 87 88 virtual SyntheticGestureParams::GestureSourceType 89 GetDefaultSyntheticGestureSourceType() const OVERRIDE { 90 return SyntheticGestureParams::TOUCH_INPUT; 91 } 92 93 virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE { 94 return base::TimeDelta::FromMilliseconds(pointer_assumed_stopped_time_ms_); 95 } 96 97 void set_pointer_assumed_stopped_time_ms(int time_ms) { 98 pointer_assumed_stopped_time_ms_ = time_ms; 99 } 100 101 virtual float GetTouchSlopInDips() const OVERRIDE { 102 return kTouchSlopInDips; 103 } 104 105 virtual float GetMinScalingSpanInDips() const OVERRIDE { 106 return kMinScalingSpanInDips; 107 } 108 109 bool flush_requested() const { return flush_requested_; } 110 void ClearFlushRequest() { flush_requested_ = false; } 111 112 private: 113 bool flush_requested_; 114 115 int pointer_assumed_stopped_time_ms_; 116 }; 117 118 class MockScrollGestureTarget : public MockSyntheticGestureTarget { 119 public: 120 MockScrollGestureTarget() : total_abs_scroll_distance_length_(0) {} 121 virtual ~MockScrollGestureTarget() {} 122 123 gfx::Vector2dF start_to_end_distance() const { 124 return start_to_end_distance_; 125 } 126 float total_abs_scroll_distance_length() const { 127 return total_abs_scroll_distance_length_; 128 } 129 130 protected: 131 gfx::Vector2dF start_to_end_distance_; 132 float total_abs_scroll_distance_length_; 133 }; 134 135 class MockScrollMouseTarget : public MockScrollGestureTarget { 136 public: 137 MockScrollMouseTarget() {} 138 virtual ~MockScrollMouseTarget() {} 139 140 virtual void DispatchInputEventToPlatform( 141 const WebInputEvent& event) OVERRIDE { 142 ASSERT_EQ(event.type, WebInputEvent::MouseWheel); 143 const WebMouseWheelEvent& mouse_wheel_event = 144 static_cast<const WebMouseWheelEvent&>(event); 145 gfx::Vector2dF delta(mouse_wheel_event.deltaX, mouse_wheel_event.deltaY); 146 start_to_end_distance_ += delta; 147 total_abs_scroll_distance_length_ += delta.Length(); 148 } 149 }; 150 151 class MockScrollTouchTarget : public MockScrollGestureTarget { 152 public: 153 MockScrollTouchTarget() : started_(false) {} 154 virtual ~MockScrollTouchTarget() {} 155 156 virtual void DispatchInputEventToPlatform( 157 const WebInputEvent& event) OVERRIDE { 158 ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); 159 const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); 160 ASSERT_EQ(touch_event.touchesLength, 1U); 161 162 if (!started_) { 163 ASSERT_EQ(touch_event.type, WebInputEvent::TouchStart); 164 start_.SetPoint(touch_event.touches[0].position.x, 165 touch_event.touches[0].position.y); 166 last_touch_point_ = start_; 167 started_ = true; 168 } else { 169 ASSERT_NE(touch_event.type, WebInputEvent::TouchStart); 170 ASSERT_NE(touch_event.type, WebInputEvent::TouchCancel); 171 172 gfx::PointF touch_point(touch_event.touches[0].position.x, 173 touch_event.touches[0].position.y); 174 gfx::Vector2dF delta = touch_point - last_touch_point_; 175 total_abs_scroll_distance_length_ += delta.Length(); 176 177 if (touch_event.type == WebInputEvent::TouchEnd) 178 start_to_end_distance_ = touch_point - start_; 179 180 last_touch_point_ = touch_point; 181 } 182 } 183 184 protected: 185 gfx::Point start_; 186 gfx::PointF last_touch_point_; 187 bool started_; 188 }; 189 190 class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget { 191 public: 192 enum ZoomDirection { 193 ZOOM_DIRECTION_UNKNOWN, 194 ZOOM_IN, 195 ZOOM_OUT 196 }; 197 198 MockSyntheticPinchTouchTarget() 199 : initial_pointer_distance_(0), 200 last_pointer_distance_(0), 201 zoom_direction_(ZOOM_DIRECTION_UNKNOWN), 202 started_(false) {} 203 virtual ~MockSyntheticPinchTouchTarget() {} 204 205 virtual void DispatchInputEventToPlatform( 206 const WebInputEvent& event) OVERRIDE { 207 ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); 208 const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); 209 ASSERT_EQ(touch_event.touchesLength, 2U); 210 211 if (!started_) { 212 ASSERT_EQ(touch_event.type, WebInputEvent::TouchStart); 213 214 start_0_ = gfx::PointF(touch_event.touches[0].position); 215 start_1_ = gfx::PointF(touch_event.touches[1].position); 216 last_pointer_distance_ = (start_0_ - start_1_).Length(); 217 initial_pointer_distance_ = last_pointer_distance_; 218 EXPECT_GE(initial_pointer_distance_, GetMinScalingSpanInDips()); 219 220 started_ = true; 221 } else { 222 ASSERT_NE(touch_event.type, WebInputEvent::TouchStart); 223 ASSERT_NE(touch_event.type, WebInputEvent::TouchCancel); 224 225 gfx::PointF current_0 = gfx::PointF(touch_event.touches[0].position); 226 gfx::PointF current_1 = gfx::PointF(touch_event.touches[1].position); 227 228 float pointer_distance = (current_0 - current_1).Length(); 229 230 if (last_pointer_distance_ != pointer_distance) { 231 if (zoom_direction_ == ZOOM_DIRECTION_UNKNOWN) 232 zoom_direction_ = 233 ComputeZoomDirection(last_pointer_distance_, pointer_distance); 234 else 235 EXPECT_EQ( 236 zoom_direction_, 237 ComputeZoomDirection(last_pointer_distance_, pointer_distance)); 238 } 239 240 last_pointer_distance_ = pointer_distance; 241 } 242 } 243 244 ZoomDirection zoom_direction() const { return zoom_direction_; } 245 246 float ComputeScaleFactor() const { 247 switch (zoom_direction_) { 248 case ZOOM_IN: 249 return last_pointer_distance_ / 250 (initial_pointer_distance_ + 2 * GetTouchSlopInDips()); 251 case ZOOM_OUT: 252 return last_pointer_distance_ / 253 (initial_pointer_distance_ - 2 * GetTouchSlopInDips()); 254 case ZOOM_DIRECTION_UNKNOWN: 255 return 1.0f; 256 default: 257 NOTREACHED(); 258 return 0.0f; 259 } 260 } 261 262 private: 263 ZoomDirection ComputeZoomDirection(float last_pointer_distance, 264 float current_pointer_distance) { 265 DCHECK_NE(last_pointer_distance, current_pointer_distance); 266 return last_pointer_distance < current_pointer_distance ? ZOOM_IN 267 : ZOOM_OUT; 268 } 269 270 float initial_pointer_distance_; 271 float last_pointer_distance_; 272 ZoomDirection zoom_direction_; 273 gfx::PointF start_0_; 274 gfx::PointF start_1_; 275 bool started_; 276 }; 277 278 class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget { 279 public: 280 MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {} 281 virtual ~MockSyntheticTapGestureTarget() {} 282 283 bool GestureFinished() const { return state_ == FINISHED; } 284 gfx::PointF position() const { return position_; } 285 base::TimeDelta GetDuration() const { return stop_time_ - start_time_; } 286 287 protected: 288 enum GestureState { 289 NOT_STARTED, 290 STARTED, 291 FINISHED 292 }; 293 294 gfx::PointF position_; 295 base::TimeDelta start_time_; 296 base::TimeDelta stop_time_; 297 GestureState state_; 298 }; 299 300 class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget { 301 public: 302 MockSyntheticTapTouchTarget() {} 303 virtual ~MockSyntheticTapTouchTarget() {} 304 305 virtual void DispatchInputEventToPlatform( 306 const WebInputEvent& event) OVERRIDE { 307 ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); 308 const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); 309 ASSERT_EQ(touch_event.touchesLength, 1U); 310 311 switch (state_) { 312 case NOT_STARTED: 313 EXPECT_EQ(touch_event.type, WebInputEvent::TouchStart); 314 position_ = gfx::PointF(touch_event.touches[0].position); 315 start_time_ = base::TimeDelta::FromMilliseconds( 316 static_cast<int64>(touch_event.timeStampSeconds * 1000)); 317 state_ = STARTED; 318 break; 319 case STARTED: 320 EXPECT_EQ(touch_event.type, WebInputEvent::TouchEnd); 321 EXPECT_EQ(position_, gfx::PointF(touch_event.touches[0].position)); 322 stop_time_ = base::TimeDelta::FromMilliseconds( 323 static_cast<int64>(touch_event.timeStampSeconds * 1000)); 324 state_ = FINISHED; 325 break; 326 case FINISHED: 327 EXPECT_FALSE(true); 328 break; 329 } 330 } 331 }; 332 333 class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget { 334 public: 335 MockSyntheticTapMouseTarget() {} 336 virtual ~MockSyntheticTapMouseTarget() {} 337 338 virtual void DispatchInputEventToPlatform( 339 const WebInputEvent& event) OVERRIDE { 340 ASSERT_TRUE(WebInputEvent::isMouseEventType(event.type)); 341 const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event); 342 343 switch (state_) { 344 case NOT_STARTED: 345 EXPECT_EQ(mouse_event.type, WebInputEvent::MouseDown); 346 EXPECT_EQ(mouse_event.button, WebMouseEvent::ButtonLeft); 347 EXPECT_EQ(mouse_event.clickCount, 1); 348 position_ = gfx::PointF(mouse_event.x, mouse_event.y); 349 start_time_ = base::TimeDelta::FromMilliseconds( 350 static_cast<int64>(mouse_event.timeStampSeconds * 1000)); 351 state_ = STARTED; 352 break; 353 case STARTED: 354 EXPECT_EQ(mouse_event.type, WebInputEvent::MouseUp); 355 EXPECT_EQ(mouse_event.button, WebMouseEvent::ButtonLeft); 356 EXPECT_EQ(mouse_event.clickCount, 1); 357 EXPECT_EQ(position_, gfx::PointF(mouse_event.x, mouse_event.y)); 358 stop_time_ = base::TimeDelta::FromMilliseconds( 359 static_cast<int64>(mouse_event.timeStampSeconds * 1000)); 360 state_ = FINISHED; 361 break; 362 case FINISHED: 363 EXPECT_FALSE(true); 364 break; 365 } 366 } 367 }; 368 369 class SyntheticGestureControllerTest : public testing::Test { 370 public: 371 SyntheticGestureControllerTest() {} 372 virtual ~SyntheticGestureControllerTest() {} 373 374 protected: 375 template<typename MockGestureTarget> 376 void CreateControllerAndTarget() { 377 target_ = new MockGestureTarget(); 378 controller_.reset(new SyntheticGestureController( 379 scoped_ptr<SyntheticGestureTarget>(target_))); 380 } 381 382 virtual void SetUp() OVERRIDE { 383 start_time_ = base::TimeTicks::Now(); 384 time_ = start_time_; 385 num_success_ = 0; 386 num_failure_ = 0; 387 } 388 389 virtual void TearDown() OVERRIDE { 390 controller_.reset(); 391 target_ = NULL; 392 time_ = base::TimeTicks(); 393 } 394 395 void QueueSyntheticGesture(scoped_ptr<SyntheticGesture> gesture) { 396 controller_->QueueSyntheticGesture(gesture.Pass(), 397 base::Bind(&SyntheticGestureControllerTest::OnSyntheticGestureCompleted, 398 base::Unretained(this))); 399 } 400 401 void FlushInputUntilComplete() { 402 while (target_->flush_requested()) { 403 while (target_->flush_requested()) { 404 target_->ClearFlushRequest(); 405 time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs); 406 controller_->Flush(time_); 407 } 408 controller_->OnDidFlushInput(); 409 } 410 } 411 412 void OnSyntheticGestureCompleted(SyntheticGesture::Result result) { 413 DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING); 414 if (result == SyntheticGesture::GESTURE_FINISHED) 415 num_success_++; 416 else 417 num_failure_++; 418 } 419 420 base::TimeDelta GetTotalTime() const { return time_ - start_time_; } 421 422 MockSyntheticGestureTarget* target_; 423 scoped_ptr<SyntheticGestureController> controller_; 424 base::TimeTicks start_time_; 425 base::TimeTicks time_; 426 int num_success_; 427 int num_failure_; 428 }; 429 430 TEST_F(SyntheticGestureControllerTest, SingleGesture) { 431 CreateControllerAndTarget<MockSyntheticGestureTarget>(); 432 433 bool finished; 434 scoped_ptr<MockSyntheticGesture> gesture( 435 new MockSyntheticGesture(&finished, 3)); 436 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 437 FlushInputUntilComplete(); 438 439 EXPECT_TRUE(finished); 440 EXPECT_EQ(1, num_success_); 441 EXPECT_EQ(0, num_failure_); 442 } 443 444 TEST_F(SyntheticGestureControllerTest, GestureFailed) { 445 CreateControllerAndTarget<MockSyntheticGestureTarget>(); 446 447 bool finished; 448 scoped_ptr<MockSyntheticGesture> gesture( 449 new MockSyntheticGesture(&finished, 0)); 450 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 451 FlushInputUntilComplete(); 452 453 EXPECT_TRUE(finished); 454 EXPECT_EQ(1, num_failure_); 455 EXPECT_EQ(0, num_success_); 456 } 457 458 TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) { 459 CreateControllerAndTarget<MockSyntheticGestureTarget>(); 460 461 bool finished_1, finished_2; 462 scoped_ptr<MockSyntheticGesture> gesture_1( 463 new MockSyntheticGesture(&finished_1, 2)); 464 scoped_ptr<MockSyntheticGesture> gesture_2( 465 new MockSyntheticGesture(&finished_2, 4)); 466 467 // Queue first gesture and wait for it to finish 468 QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>()); 469 FlushInputUntilComplete(); 470 471 EXPECT_TRUE(finished_1); 472 EXPECT_EQ(1, num_success_); 473 EXPECT_EQ(0, num_failure_); 474 475 // Queue second gesture. 476 QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>()); 477 FlushInputUntilComplete(); 478 479 EXPECT_TRUE(finished_2); 480 EXPECT_EQ(2, num_success_); 481 EXPECT_EQ(0, num_failure_); 482 } 483 484 TEST_F(SyntheticGestureControllerTest, TwoGesturesInFlight) { 485 CreateControllerAndTarget<MockSyntheticGestureTarget>(); 486 487 bool finished_1, finished_2; 488 scoped_ptr<MockSyntheticGesture> gesture_1( 489 new MockSyntheticGesture(&finished_1, 2)); 490 scoped_ptr<MockSyntheticGesture> gesture_2( 491 new MockSyntheticGesture(&finished_2, 4)); 492 493 QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>()); 494 QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>()); 495 FlushInputUntilComplete(); 496 497 EXPECT_TRUE(finished_1); 498 EXPECT_TRUE(finished_2); 499 500 EXPECT_EQ(2, num_success_); 501 EXPECT_EQ(0, num_failure_); 502 } 503 504 TEST_F(SyntheticGestureControllerTest, GestureCompletedOnDidFlushInput) { 505 CreateControllerAndTarget<MockSyntheticGestureTarget>(); 506 507 bool finished_1, finished_2; 508 scoped_ptr<MockSyntheticGesture> gesture_1( 509 new MockSyntheticGesture(&finished_1, 2)); 510 scoped_ptr<MockSyntheticGesture> gesture_2( 511 new MockSyntheticGesture(&finished_2, 4)); 512 513 QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>()); 514 QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>()); 515 516 while (target_->flush_requested()) { 517 target_->ClearFlushRequest(); 518 time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs); 519 controller_->Flush(time_); 520 } 521 EXPECT_EQ(0, num_success_); 522 controller_->OnDidFlushInput(); 523 EXPECT_EQ(1, num_success_); 524 525 while (target_->flush_requested()) { 526 target_->ClearFlushRequest(); 527 time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs); 528 controller_->Flush(time_); 529 } 530 EXPECT_EQ(1, num_success_); 531 controller_->OnDidFlushInput(); 532 EXPECT_EQ(2, num_success_); 533 } 534 535 gfx::Vector2d AddTouchSlopToVector(const gfx::Vector2d& vector, 536 SyntheticGestureTarget* target) { 537 const int kTouchSlop = target->GetTouchSlopInDips(); 538 539 int x = vector.x(); 540 if (x > 0) 541 x += kTouchSlop; 542 else if (x < 0) 543 x -= kTouchSlop; 544 545 int y = vector.y(); 546 if (y > 0) 547 y += kTouchSlop; 548 else if (y < 0) 549 y -= kTouchSlop; 550 551 return gfx::Vector2d(x, y); 552 } 553 554 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchVertical) { 555 CreateControllerAndTarget<MockScrollTouchTarget>(); 556 557 SyntheticSmoothScrollGestureParams params; 558 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 559 params.anchor.SetPoint(89, 32); 560 params.distances.push_back(gfx::Vector2d(0, 123)); 561 562 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 563 new SyntheticSmoothScrollGesture(params)); 564 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 565 FlushInputUntilComplete(); 566 567 MockScrollGestureTarget* scroll_target = 568 static_cast<MockScrollGestureTarget*>(target_); 569 EXPECT_EQ(1, num_success_); 570 EXPECT_EQ(0, num_failure_); 571 // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed. 572 EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_), 573 scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f)); 574 } 575 576 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchHorizontal) { 577 CreateControllerAndTarget<MockScrollTouchTarget>(); 578 579 SyntheticSmoothScrollGestureParams params; 580 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 581 params.anchor.SetPoint(12, -23); 582 params.distances.push_back(gfx::Vector2d(-234, 0)); 583 584 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 585 new SyntheticSmoothScrollGesture(params)); 586 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 587 FlushInputUntilComplete(); 588 589 MockScrollGestureTarget* scroll_target = 590 static_cast<MockScrollGestureTarget*>(target_); 591 EXPECT_EQ(1, num_success_); 592 EXPECT_EQ(0, num_failure_); 593 // TODO(dominikg): Use vector comparison when crbug.com/332418 is fixed. 594 //EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_), 595 // scroll_target->start_to_end_distance()); 596 EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_).x(), 597 scroll_target->start_to_end_distance().x()); 598 EXPECT_LT(AddTouchSlopToVector(params.distances[0], target_).y(), 599 scroll_target->start_to_end_distance().y()); 600 EXPECT_GE(AddTouchSlopToVector(params.distances[0], target_).y(), 601 scroll_target->start_to_end_distance().y() - 0.001f); 602 } 603 604 void CheckIsWithinRangeSingle(float scroll_distance, 605 int target_distance, 606 SyntheticGestureTarget* target) { 607 if (target_distance > 0) { 608 EXPECT_LE(target_distance, scroll_distance); 609 EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips()); 610 } else { 611 EXPECT_GE(target_distance, scroll_distance); 612 EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips()); 613 } 614 } 615 616 void CheckSingleScrollDistanceIsWithinRange( 617 const gfx::Vector2dF& scroll_distance, 618 const gfx::Vector2d& target_distance, 619 SyntheticGestureTarget* target) { 620 CheckIsWithinRangeSingle(scroll_distance.x(), target_distance.x(), target); 621 CheckIsWithinRangeSingle(scroll_distance.y(), target_distance.y(), target); 622 } 623 624 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchDiagonal) { 625 CreateControllerAndTarget<MockScrollTouchTarget>(); 626 627 SyntheticSmoothScrollGestureParams params; 628 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 629 params.anchor.SetPoint(0, 7); 630 params.distances.push_back(gfx::Vector2d(413, -83)); 631 632 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 633 new SyntheticSmoothScrollGesture(params)); 634 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 635 FlushInputUntilComplete(); 636 637 MockScrollGestureTarget* scroll_target = 638 static_cast<MockScrollGestureTarget*>(target_); 639 EXPECT_EQ(1, num_success_); 640 EXPECT_EQ(0, num_failure_); 641 CheckSingleScrollDistanceIsWithinRange( 642 scroll_target->start_to_end_distance(), params.distances[0], target_); 643 } 644 645 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchLongStop) { 646 CreateControllerAndTarget<MockScrollTouchTarget>(); 647 648 // Create a smooth scroll with a short distance and set the pointer assumed 649 // stopped time high, so that the stopping should dominate the time the 650 // gesture is active. 651 SyntheticSmoothScrollGestureParams params; 652 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 653 params.anchor.SetPoint(-98, -23); 654 params.distances.push_back(gfx::Vector2d(21, -12)); 655 params.prevent_fling = true; 656 657 target_->set_pointer_assumed_stopped_time_ms(543); 658 659 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 660 new SyntheticSmoothScrollGesture(params)); 661 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 662 FlushInputUntilComplete(); 663 664 MockScrollGestureTarget* scroll_target = 665 static_cast<MockScrollGestureTarget*>(target_); 666 EXPECT_EQ(1, num_success_); 667 EXPECT_EQ(0, num_failure_); 668 CheckSingleScrollDistanceIsWithinRange( 669 scroll_target->start_to_end_distance(), params.distances[0], target_); 670 EXPECT_GE(GetTotalTime(), target_->PointerAssumedStoppedTime()); 671 } 672 673 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchFling) { 674 CreateControllerAndTarget<MockScrollTouchTarget>(); 675 676 // Create a smooth scroll with a short distance and set the pointer assumed 677 // stopped time high. Disable 'prevent_fling' and check that the gesture 678 // finishes without waiting before it stops. 679 SyntheticSmoothScrollGestureParams params; 680 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 681 params.anchor.SetPoint(-89, 78); 682 params.distances.push_back(gfx::Vector2d(-43, 19)); 683 params.prevent_fling = false; 684 685 target_->set_pointer_assumed_stopped_time_ms(543); 686 687 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 688 new SyntheticSmoothScrollGesture(params)); 689 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 690 FlushInputUntilComplete(); 691 692 MockScrollGestureTarget* scroll_target = 693 static_cast<MockScrollGestureTarget*>(target_); 694 EXPECT_EQ(1, num_success_); 695 EXPECT_EQ(0, num_failure_); 696 CheckSingleScrollDistanceIsWithinRange( 697 scroll_target->start_to_end_distance(), params.distances[0], target_); 698 EXPECT_LE(GetTotalTime(), target_->PointerAssumedStoppedTime()); 699 } 700 701 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchZeroDistance) { 702 CreateControllerAndTarget<MockScrollTouchTarget>(); 703 704 SyntheticSmoothScrollGestureParams params; 705 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 706 params.anchor.SetPoint(-32, 43); 707 params.distances.push_back(gfx::Vector2d(0, 0)); 708 709 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 710 new SyntheticSmoothScrollGesture(params)); 711 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 712 FlushInputUntilComplete(); 713 714 MockScrollGestureTarget* scroll_target = 715 static_cast<MockScrollGestureTarget*>(target_); 716 EXPECT_EQ(1, num_success_); 717 EXPECT_EQ(0, num_failure_); 718 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_target->start_to_end_distance()); 719 } 720 721 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseVertical) { 722 CreateControllerAndTarget<MockScrollMouseTarget>(); 723 724 SyntheticSmoothScrollGestureParams params; 725 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 726 params.anchor.SetPoint(432, 89); 727 params.distances.push_back(gfx::Vector2d(0, -234)); 728 729 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 730 new SyntheticSmoothScrollGesture(params)); 731 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 732 FlushInputUntilComplete(); 733 734 MockScrollGestureTarget* scroll_target = 735 static_cast<MockScrollGestureTarget*>(target_); 736 EXPECT_EQ(1, num_success_); 737 EXPECT_EQ(0, num_failure_); 738 EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance()); 739 } 740 741 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseHorizontal) { 742 CreateControllerAndTarget<MockScrollMouseTarget>(); 743 744 SyntheticSmoothScrollGestureParams params; 745 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 746 params.anchor.SetPoint(90, 12); 747 params.distances.push_back(gfx::Vector2d(345, 0)); 748 749 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 750 new SyntheticSmoothScrollGesture(params)); 751 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 752 FlushInputUntilComplete(); 753 754 MockScrollGestureTarget* scroll_target = 755 static_cast<MockScrollGestureTarget*>(target_); 756 EXPECT_EQ(1, num_success_); 757 EXPECT_EQ(0, num_failure_); 758 EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance()); 759 } 760 761 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseDiagonal) { 762 CreateControllerAndTarget<MockScrollMouseTarget>(); 763 764 SyntheticSmoothScrollGestureParams params; 765 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 766 params.anchor.SetPoint(90, 12); 767 params.distances.push_back(gfx::Vector2d(-194, 303)); 768 769 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 770 new SyntheticSmoothScrollGesture(params)); 771 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 772 FlushInputUntilComplete(); 773 774 MockScrollGestureTarget* scroll_target = 775 static_cast<MockScrollGestureTarget*>(target_); 776 EXPECT_EQ(1, num_success_); 777 EXPECT_EQ(0, num_failure_); 778 EXPECT_EQ(params.distances[0], scroll_target->start_to_end_distance()); 779 } 780 781 TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouse) { 782 CreateControllerAndTarget<MockScrollMouseTarget>(); 783 784 SyntheticSmoothScrollGestureParams params; 785 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 786 params.anchor.SetPoint(90, 12); 787 params.distances.push_back(gfx::Vector2d(-129, 212)); 788 params.distances.push_back(gfx::Vector2d(8, -9)); 789 790 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 791 new SyntheticSmoothScrollGesture(params)); 792 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 793 FlushInputUntilComplete(); 794 795 MockScrollGestureTarget* scroll_target = 796 static_cast<MockScrollGestureTarget*>(target_); 797 EXPECT_EQ(1, num_success_); 798 EXPECT_EQ(0, num_failure_); 799 EXPECT_EQ(params.distances[0] + params.distances[1], 800 scroll_target->start_to_end_distance()); 801 } 802 803 TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouseHorizontal) { 804 CreateControllerAndTarget<MockScrollMouseTarget>(); 805 806 SyntheticSmoothScrollGestureParams params; 807 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 808 params.anchor.SetPoint(90, 12); 809 params.distances.push_back(gfx::Vector2d(-129, 0)); 810 params.distances.push_back(gfx::Vector2d(79, 0)); 811 812 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 813 new SyntheticSmoothScrollGesture(params)); 814 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 815 FlushInputUntilComplete(); 816 817 MockScrollGestureTarget* scroll_target = 818 static_cast<MockScrollGestureTarget*>(target_); 819 EXPECT_EQ(1, num_success_); 820 EXPECT_EQ(0, num_failure_); 821 // This check only works for horizontal or vertical scrolls because of 822 // floating point precision issues with diagonal scrolls. 823 EXPECT_FLOAT_EQ(params.distances[0].Length() + params.distances[1].Length(), 824 scroll_target->total_abs_scroll_distance_length()); 825 EXPECT_EQ(params.distances[0] + params.distances[1], 826 scroll_target->start_to_end_distance()); 827 } 828 829 void CheckIsWithinRangeMulti(float scroll_distance, 830 int target_distance, 831 SyntheticGestureTarget* target) { 832 if (target_distance > 0) { 833 EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips()); 834 EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips()); 835 } else { 836 EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips()); 837 EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips()); 838 } 839 } 840 841 void CheckMultiScrollDistanceIsWithinRange( 842 const gfx::Vector2dF& scroll_distance, 843 const gfx::Vector2d& target_distance, 844 SyntheticGestureTarget* target) { 845 CheckIsWithinRangeMulti(scroll_distance.x(), target_distance.x(), target); 846 CheckIsWithinRangeMulti(scroll_distance.y(), target_distance.y(), target); 847 } 848 849 TEST_F(SyntheticGestureControllerTest, MultiScrollGestureTouch) { 850 CreateControllerAndTarget<MockScrollTouchTarget>(); 851 852 SyntheticSmoothScrollGestureParams params; 853 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 854 params.anchor.SetPoint(8, -13); 855 params.distances.push_back(gfx::Vector2d(234, 133)); 856 params.distances.push_back(gfx::Vector2d(-9, 78)); 857 858 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 859 new SyntheticSmoothScrollGesture(params)); 860 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 861 FlushInputUntilComplete(); 862 863 MockScrollGestureTarget* scroll_target = 864 static_cast<MockScrollGestureTarget*>(target_); 865 EXPECT_EQ(1, num_success_); 866 EXPECT_EQ(0, num_failure_); 867 CheckMultiScrollDistanceIsWithinRange( 868 scroll_target->start_to_end_distance(), 869 params.distances[0] + params.distances[1], 870 target_); 871 } 872 873 TEST_F(SyntheticGestureControllerTest, MultiScrollGestureTouchVertical) { 874 CreateControllerAndTarget<MockScrollTouchTarget>(); 875 876 SyntheticSmoothScrollGestureParams params; 877 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 878 params.anchor.SetPoint(234, -13); 879 params.distances.push_back(gfx::Vector2d(0, 133)); 880 params.distances.push_back(gfx::Vector2d(0, 78)); 881 882 scoped_ptr<SyntheticSmoothScrollGesture> gesture( 883 new SyntheticSmoothScrollGesture(params)); 884 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 885 FlushInputUntilComplete(); 886 887 MockScrollGestureTarget* scroll_target = 888 static_cast<MockScrollGestureTarget*>(target_); 889 EXPECT_EQ(1, num_success_); 890 EXPECT_EQ(0, num_failure_); 891 // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed. 892 EXPECT_FLOAT_EQ( 893 params.distances[0].Length() + params.distances[1].Length() + 894 target_->GetTouchSlopInDips(), 895 scroll_target->total_abs_scroll_distance_length() - 0.001f); 896 EXPECT_EQ(AddTouchSlopToVector(params.distances[0] + params.distances[1], 897 target_), 898 scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f)); 899 } 900 901 TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) { 902 CreateControllerAndTarget<MockSyntheticPinchTouchTarget>(); 903 904 SyntheticPinchGestureParams params; 905 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 906 params.scale_factor = 2.3f; 907 params.anchor.SetPoint(54, 89); 908 909 scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); 910 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 911 FlushInputUntilComplete(); 912 913 MockSyntheticPinchTouchTarget* pinch_target = 914 static_cast<MockSyntheticPinchTouchTarget*>(target_); 915 EXPECT_EQ(1, num_success_); 916 EXPECT_EQ(0, num_failure_); 917 EXPECT_EQ(pinch_target->zoom_direction(), 918 MockSyntheticPinchTouchTarget::ZOOM_IN); 919 EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor()); 920 } 921 922 TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) { 923 CreateControllerAndTarget<MockSyntheticPinchTouchTarget>(); 924 925 SyntheticPinchGestureParams params; 926 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 927 params.scale_factor = 0.4f; 928 params.anchor.SetPoint(-12, 93); 929 930 scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); 931 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 932 FlushInputUntilComplete(); 933 934 MockSyntheticPinchTouchTarget* pinch_target = 935 static_cast<MockSyntheticPinchTouchTarget*>(target_); 936 EXPECT_EQ(1, num_success_); 937 EXPECT_EQ(0, num_failure_); 938 EXPECT_EQ(pinch_target->zoom_direction(), 939 MockSyntheticPinchTouchTarget::ZOOM_OUT); 940 EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor()); 941 } 942 943 TEST_F(SyntheticGestureControllerTest, PinchGestureTouchNoScaling) { 944 CreateControllerAndTarget<MockSyntheticPinchTouchTarget>(); 945 946 SyntheticPinchGestureParams params; 947 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 948 params.scale_factor = 1.0f; 949 950 scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); 951 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 952 FlushInputUntilComplete(); 953 954 MockSyntheticPinchTouchTarget* pinch_target = 955 static_cast<MockSyntheticPinchTouchTarget*>(target_); 956 EXPECT_EQ(1, num_success_); 957 EXPECT_EQ(0, num_failure_); 958 EXPECT_EQ(pinch_target->zoom_direction(), 959 MockSyntheticPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN); 960 EXPECT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor()); 961 } 962 963 TEST_F(SyntheticGestureControllerTest, TapGestureTouch) { 964 CreateControllerAndTarget<MockSyntheticTapTouchTarget>(); 965 966 SyntheticTapGestureParams params; 967 params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; 968 params.duration_ms = 123; 969 params.position.SetPoint(87, -124); 970 971 scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params)); 972 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 973 FlushInputUntilComplete(); 974 975 MockSyntheticTapTouchTarget* tap_target = 976 static_cast<MockSyntheticTapTouchTarget*>(target_); 977 EXPECT_EQ(1, num_success_); 978 EXPECT_EQ(0, num_failure_); 979 EXPECT_TRUE(tap_target->GestureFinished()); 980 EXPECT_EQ(tap_target->position(), params.position); 981 EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms); 982 EXPECT_GE(GetTotalTime(), 983 base::TimeDelta::FromMilliseconds(params.duration_ms)); 984 } 985 986 TEST_F(SyntheticGestureControllerTest, TapGestureMouse) { 987 CreateControllerAndTarget<MockSyntheticTapMouseTarget>(); 988 989 SyntheticTapGestureParams params; 990 params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; 991 params.duration_ms = 79; 992 params.position.SetPoint(98, 123); 993 994 scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params)); 995 QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); 996 FlushInputUntilComplete(); 997 998 MockSyntheticTapMouseTarget* tap_target = 999 static_cast<MockSyntheticTapMouseTarget*>(target_); 1000 EXPECT_EQ(1, num_success_); 1001 EXPECT_EQ(0, num_failure_); 1002 EXPECT_TRUE(tap_target->GestureFinished()); 1003 EXPECT_EQ(tap_target->position(), params.position); 1004 EXPECT_EQ(tap_target->GetDuration().InMilliseconds(), params.duration_ms); 1005 EXPECT_GE(GetTotalTime(), 1006 base::TimeDelta::FromMilliseconds(params.duration_ms)); 1007 } 1008 1009 } // namespace 1010 1011 } // namespace content 1012