Home | History | Annotate | Download | only in input
      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