tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestGestureDetector.cpp (45203B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include "gmock/gmock.h"
      9 
     10 #include "APZCBasicTester.h"
     11 #include "APZTestCommon.h"
     12 #include "InputUtils.h"
     13 #include "apz/src/InputBlockState.h"
     14 #include "mozilla/StaticPrefs_apz.h"
     15 
     16 // Note: There are additional tests that test gesture detection behaviour
     17 //       with multiple APZCs in TestTreeManager.cpp.
     18 
     19 class APZCGestureDetectorTester : public APZCBasicTester {
     20 public:
     21  APZCGestureDetectorTester()
     22      : APZCBasicTester(AsyncPanZoomController::USE_GESTURE_DETECTOR) {}
     23 
     24 protected:
     25  FrameMetrics GetPinchableFrameMetrics(float aZoom = 2.0f) {
     26    FrameMetrics fm;
     27    fm.SetCompositionBounds(ParentLayerRect(200, 200, 100, 200));
     28    fm.SetScrollableRect(CSSRect(0, 0, 980, 1000));
     29    fm.SetVisualScrollOffset(CSSPoint(300, 300));
     30    fm.SetZoom(CSSToParentLayerScale(aZoom));
     31    // APZC only allows zooming on the root scrollable frame.
     32    fm.SetIsRootContent(true);
     33    // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
     34    return fm;
     35  }
     36 };
     37 
     38 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
     39 TEST_F(APZCGestureDetectorTester, Pan_After_Pinch) {
     40  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
     41  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 6.0f);
     42  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 8.0f);
     43 
     44  FrameMetrics originalMetrics = GetPinchableFrameMetrics();
     45  apzc->SetFrameMetrics(originalMetrics);
     46 
     47  MakeApzcZoomable();
     48 
     49  // Test parameters
     50  float zoomAmount = 1.25;
     51  float pinchLength = 100.0;
     52  float pinchLengthScaled = pinchLength * zoomAmount;
     53  int focusX = 250;
     54  int focusY = 300;
     55  int panDistance = 20;
     56  const TimeDuration TIME_BETWEEN_TOUCH_EVENT =
     57      TimeDuration::FromMilliseconds(50);
     58 
     59  int firstFingerId = 0;
     60  int secondFingerId = firstFingerId + 1;
     61 
     62  // Put fingers down
     63  MultiTouchInput mti =
     64      MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, mcc->Time(), 0);
     65  mti.mTouches.AppendElement(
     66      CreateSingleTouchData(firstFingerId, focusX, focusY));
     67  mti.mTouches.AppendElement(
     68      CreateSingleTouchData(secondFingerId, focusX, focusY));
     69  apzc->ReceiveInputEvent(mti, Some(nsTArray<uint32_t>{kDefaultTouchBehavior}));
     70  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
     71 
     72  // Spread fingers out to enter the pinch state
     73  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0);
     74  mti.mTouches.AppendElement(CreateSingleTouchData(
     75      firstFingerId, static_cast<int32_t>(focusX - pinchLength), focusY));
     76  mti.mTouches.AppendElement(CreateSingleTouchData(
     77      secondFingerId, static_cast<int32_t>(focusX + pinchLength), focusY));
     78  apzc->ReceiveInputEvent(mti);
     79  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
     80 
     81  // Do the actual pinch of 1.25x
     82  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0);
     83  mti.mTouches.AppendElement(CreateSingleTouchData(
     84      firstFingerId, static_cast<int32_t>(focusX - pinchLengthScaled), focusY));
     85  mti.mTouches.AppendElement(CreateSingleTouchData(
     86      secondFingerId, static_cast<int32_t>(focusX + pinchLengthScaled),
     87      focusY));
     88  apzc->ReceiveInputEvent(mti);
     89  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
     90 
     91  // Verify that the zoom changed, just to make sure our code above did what it
     92  // was supposed to.
     93  FrameMetrics zoomedMetrics = apzc->GetFrameMetrics();
     94  float newZoom = zoomedMetrics.GetZoom().scale;
     95  EXPECT_EQ(originalMetrics.GetZoom().scale * zoomAmount, newZoom);
     96 
     97  // Now we lift one finger...
     98  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, mcc->Time(), 0);
     99  mti.mTouches.AppendElement(CreateSingleTouchData(
    100      secondFingerId, static_cast<int32_t>(focusX + pinchLengthScaled),
    101      focusY));
    102  apzc->ReceiveInputEvent(mti);
    103  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
    104 
    105  // ... and pan with the remaining finger. This pan just breaks through the
    106  // distance threshold.
    107  focusY += StaticPrefs::apz_touch_start_tolerance() * tm->GetDPI();
    108  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0);
    109  mti.mTouches.AppendElement(CreateSingleTouchData(
    110      firstFingerId, static_cast<int32_t>(focusX - pinchLengthScaled), focusY));
    111  apzc->ReceiveInputEvent(mti);
    112  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
    113 
    114  // This one does an actual pan of 20 pixels
    115  focusY += panDistance;
    116  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0);
    117  mti.mTouches.AppendElement(CreateSingleTouchData(
    118      firstFingerId, static_cast<int32_t>(focusX - pinchLengthScaled), focusY));
    119  apzc->ReceiveInputEvent(mti);
    120  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
    121 
    122  // Lift the remaining finger
    123  mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, mcc->Time(), 0);
    124  mti.mTouches.AppendElement(CreateSingleTouchData(
    125      firstFingerId, static_cast<int32_t>(focusX - pinchLengthScaled), focusY));
    126  apzc->ReceiveInputEvent(mti);
    127  mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
    128 
    129  // Verify that we scrolled
    130  FrameMetrics finalMetrics = apzc->GetFrameMetrics();
    131  EXPECT_EQ(zoomedMetrics.GetVisualScrollOffset().y - (panDistance / newZoom),
    132            finalMetrics.GetVisualScrollOffset().y);
    133 
    134  // Clear out any remaining fling animation and pending tasks
    135  apzc->AdvanceAnimationsUntilEnd();
    136  while (mcc->RunThroughDelayedTasks());
    137  apzc->AssertStateIsReset();
    138 }
    139 #endif
    140 
    141 TEST_F(APZCGestureDetectorTester, Pan_With_Tap) {
    142  SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 0.1);
    143 
    144  FrameMetrics originalMetrics = GetPinchableFrameMetrics();
    145  apzc->SetFrameMetrics(originalMetrics);
    146 
    147  // Making the APZC zoomable isn't really needed for the correct operation of
    148  // this test, but it could help catch regressions where we accidentally enter
    149  // a pinch state.
    150  MakeApzcZoomable();
    151 
    152  // Test parameters
    153  int touchX = 250;
    154  int touchY = 300;
    155  int panDistance = 20;
    156 
    157  int firstFingerId = 0;
    158  int secondFingerId = firstFingerId + 1;
    159 
    160  const float panThreshold =
    161      StaticPrefs::apz_touch_start_tolerance() * tm->GetDPI();
    162 
    163  // Put finger down
    164  MultiTouchInput mti =
    165      CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    166  mti.mTouches.AppendElement(
    167      CreateSingleTouchData(firstFingerId, touchX, touchY));
    168  apzc->ReceiveInputEvent(mti, Some(nsTArray<uint32_t>{kDefaultTouchBehavior}));
    169 
    170  // Start a pan, break through the threshold
    171  touchY += panThreshold;
    172  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time());
    173  mti.mTouches.AppendElement(
    174      CreateSingleTouchData(firstFingerId, touchX, touchY));
    175  apzc->ReceiveInputEvent(mti);
    176 
    177  // Do an actual pan for a bit
    178  touchY += panDistance;
    179  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time());
    180  mti.mTouches.AppendElement(
    181      CreateSingleTouchData(firstFingerId, touchX, touchY));
    182  apzc->ReceiveInputEvent(mti);
    183 
    184  // Put a second finger down
    185  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    186  mti.mTouches.AppendElement(
    187      CreateSingleTouchData(firstFingerId, touchX, touchY));
    188  mti.mTouches.AppendElement(
    189      CreateSingleTouchData(secondFingerId, touchX + 10, touchY));
    190  apzc->ReceiveInputEvent(mti, Some(nsTArray<uint32_t>{kDefaultTouchBehavior}));
    191 
    192  // Lift the second finger
    193  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_END, mcc->Time());
    194  mti.mTouches.AppendElement(
    195      CreateSingleTouchData(secondFingerId, touchX + 10, touchY));
    196  apzc->ReceiveInputEvent(mti);
    197 
    198  // Bust through the threshold again
    199  touchY += panThreshold;
    200  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time());
    201  mti.mTouches.AppendElement(
    202      CreateSingleTouchData(firstFingerId, touchX, touchY));
    203  apzc->ReceiveInputEvent(mti);
    204 
    205  // Do some more actual panning
    206  touchY += panDistance;
    207  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time());
    208  mti.mTouches.AppendElement(
    209      CreateSingleTouchData(firstFingerId, touchX, touchY));
    210  apzc->ReceiveInputEvent(mti);
    211 
    212  // Lift the first finger
    213  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_END, mcc->Time());
    214  mti.mTouches.AppendElement(
    215      CreateSingleTouchData(firstFingerId, touchX, touchY));
    216  apzc->ReceiveInputEvent(mti);
    217 
    218  // Verify that we scrolled
    219  FrameMetrics finalMetrics = apzc->GetFrameMetrics();
    220  float zoom = finalMetrics.GetZoom().scale;
    221  EXPECT_EQ(
    222      originalMetrics.GetVisualScrollOffset().y - (panDistance * 2 / zoom),
    223      finalMetrics.GetVisualScrollOffset().y);
    224 
    225  // Clear out any remaining fling animation and pending tasks
    226  apzc->AdvanceAnimationsUntilEnd();
    227  while (mcc->RunThroughDelayedTasks());
    228  apzc->AssertStateIsReset();
    229 }
    230 
    231 TEST_F(APZCGestureDetectorTester, SecondTapIsFar_Bug1586496) {
    232  // Test that we receive two single-tap events when two tap gestures are
    233  // close in time but far in distance.
    234  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
    235      .Times(2);
    236 
    237  TimeDuration brief =
    238      TimeDuration::FromMilliseconds(StaticPrefs::apz_max_tap_time() / 10.0);
    239 
    240  ScreenIntPoint point(10, 10);
    241  Tap(apzc, point, brief);
    242 
    243  mcc->AdvanceBy(brief);
    244 
    245  point.x += static_cast<int32_t>(apzc->GetSecondTapTolerance() * 2);
    246  point.y += static_cast<int32_t>(apzc->GetSecondTapTolerance() * 2);
    247 
    248  Tap(apzc, point, brief);
    249 }
    250 
    251 class APZCFlingStopTester : public APZCGestureDetectorTester {
    252 protected:
    253  // Start a fling, and then tap while the fling is ongoing. When
    254  // aSlow is false, the tap will happen while the fling is at a
    255  // high velocity, and we check that the tap doesn't trigger sending a tap
    256  // to content. If aSlow is true, the tap will happen while the fling
    257  // is at a slow velocity, and we check that the tap does trigger sending
    258  // a tap to content. See bug 1022956.
    259  void DoFlingStopTest(bool aSlow) {
    260    int touchStart = 50;
    261    int touchEnd = 10;
    262 
    263    // Start the fling down.
    264    Pan(apzc, touchStart, touchEnd);
    265    // The touchstart from the pan will leave some cancelled tasks in the queue,
    266    // clear them out
    267 
    268    // If we want to tap while the fling is fast, let the fling advance for 10ms
    269    // only. If we want the fling to slow down more, advance to 2000ms. These
    270    // numbers may need adjusting if our friction and threshold values change,
    271    // but they should be deterministic at least.
    272    int timeDelta = aSlow ? 2000 : 10;
    273    int tapCallsExpected = aSlow ? 2 : 1;
    274 
    275    // Advance the fling animation by timeDelta milliseconds.
    276    ParentLayerPoint pointOut;
    277    AsyncTransform viewTransformOut;
    278    apzc->SampleContentTransformForFrame(
    279        &viewTransformOut, pointOut, TimeDuration::FromMilliseconds(timeDelta));
    280 
    281    // Deliver a tap to abort the fling. Ensure that we get a SingleTap
    282    // call out of it if and only if the fling is slow.
    283    EXPECT_CALL(*mcc,
    284                HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
    285        .Times(tapCallsExpected);
    286    Tap(apzc, ScreenIntPoint(10, 10), 0);
    287    while (mcc->RunThroughDelayedTasks());
    288 
    289    // Deliver another tap, to make sure that taps are flowing properly once
    290    // the fling is aborted.
    291    Tap(apzc, ScreenIntPoint(100, 100), 0);
    292    while (mcc->RunThroughDelayedTasks());
    293 
    294    // Verify that we didn't advance any further after the fling was aborted, in
    295    // either case.
    296    ParentLayerPoint finalPointOut;
    297    apzc->SampleContentTransformForFrame(&viewTransformOut, finalPointOut);
    298    EXPECT_EQ(pointOut.x, finalPointOut.x);
    299    EXPECT_EQ(pointOut.y, finalPointOut.y);
    300 
    301    apzc->AssertStateIsReset();
    302  }
    303 
    304  void DoFlingStopWithSlowListener(bool aPreventDefault) {
    305    MakeApzcWaitForMainThread();
    306 
    307    int touchStart = 50;
    308    int touchEnd = 10;
    309    uint64_t blockId = 0;
    310 
    311    // Start the fling down.
    312    Pan(apzc, touchStart, touchEnd, PanOptions::None, nullptr, nullptr,
    313        &blockId);
    314    apzc->ConfirmTarget(blockId);
    315    apzc->ContentReceivedInputBlock(blockId, false);
    316 
    317    // Sample the fling a couple of times to ensure it's going.
    318    ParentLayerPoint point, finalPoint;
    319    AsyncTransform viewTransform;
    320    apzc->SampleContentTransformForFrame(&viewTransform, point,
    321                                         TimeDuration::FromMilliseconds(10));
    322    apzc->SampleContentTransformForFrame(&viewTransform, finalPoint,
    323                                         TimeDuration::FromMilliseconds(10));
    324    EXPECT_GT(finalPoint.y, point.y);
    325 
    326    // Now we put our finger down to stop the fling
    327    blockId =
    328        TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId;
    329 
    330    // Re-sample to make sure it hasn't moved
    331    apzc->SampleContentTransformForFrame(&viewTransform, point,
    332                                         TimeDuration::FromMilliseconds(10));
    333    EXPECT_EQ(finalPoint.x, point.x);
    334    EXPECT_EQ(finalPoint.y, point.y);
    335 
    336    // respond to the touchdown that stopped the fling.
    337    // even if we do a prevent-default on it, the animation should remain
    338    // stopped.
    339    apzc->ContentReceivedInputBlock(blockId, aPreventDefault);
    340 
    341    // Verify the page hasn't moved
    342    apzc->SampleContentTransformForFrame(&viewTransform, point,
    343                                         TimeDuration::FromMilliseconds(70));
    344    EXPECT_EQ(finalPoint.x, point.x);
    345    EXPECT_EQ(finalPoint.y, point.y);
    346 
    347    // clean up
    348    TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
    349 
    350    apzc->AssertStateIsReset();
    351  }
    352 };
    353 
    354 TEST_F(APZCFlingStopTester, FlingStop) {
    355  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
    356  DoFlingStopTest(false);
    357 }
    358 
    359 TEST_F(APZCFlingStopTester, FlingStopTap) {
    360  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
    361  DoFlingStopTest(true);
    362 }
    363 
    364 TEST_F(APZCFlingStopTester, FlingStopSlowListener) {
    365  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
    366  DoFlingStopWithSlowListener(false);
    367 }
    368 
    369 TEST_F(APZCFlingStopTester, FlingStopPreventDefault) {
    370  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
    371  DoFlingStopWithSlowListener(true);
    372 }
    373 
    374 TEST_F(APZCGestureDetectorTester, ShortPress) {
    375  MakeApzcUnzoomable();
    376 
    377  MockFunction<void(std::string checkPointName)> check;
    378  {
    379    InSequence s;
    380    // This verifies that the single tap notification is sent after the
    381    // touchup is fully processed. The ordering here is important.
    382    EXPECT_CALL(check, Call("pre-tap"));
    383    EXPECT_CALL(check, Call("post-tap"));
    384    EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10),
    385                                0, apzc->GetGuid(), _, _))
    386        .Times(1);
    387  }
    388 
    389  check.Call("pre-tap");
    390  TapAndCheckStatus(apzc, ScreenIntPoint(10, 10),
    391                    TimeDuration::FromMilliseconds(100));
    392  check.Call("post-tap");
    393 
    394  apzc->AssertStateIsReset();
    395 }
    396 
    397 TEST_F(APZCGestureDetectorTester, MediumPress) {
    398  MakeApzcUnzoomable();
    399 
    400  MockFunction<void(std::string checkPointName)> check;
    401  {
    402    InSequence s;
    403    // This verifies that the single tap notification is sent after the
    404    // touchup is fully processed. The ordering here is important.
    405    EXPECT_CALL(check, Call("pre-tap"));
    406    EXPECT_CALL(check, Call("post-tap"));
    407    EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10),
    408                                0, apzc->GetGuid(), _, _))
    409        .Times(1);
    410  }
    411 
    412  check.Call("pre-tap");
    413  TapAndCheckStatus(apzc, ScreenIntPoint(10, 10),
    414                    TimeDuration::FromMilliseconds(400));
    415  check.Call("post-tap");
    416 
    417  apzc->AssertStateIsReset();
    418 }
    419 
    420 class APZCLongPressTester : public APZCGestureDetectorTester {
    421 protected:
    422  void DoLongPressTest(uint32_t aBehavior) {
    423    MakeApzcUnzoomable();
    424 
    425    APZEventResult result =
    426        TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    427    EXPECT_EQ(nsEventStatus_eConsumeDoDefault, result.GetStatus());
    428    uint64_t blockId = result.mInputBlockId;
    429 
    430    if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
    431      // SetAllowedTouchBehavior() must be called after sending touch-start.
    432      nsTArray<uint32_t> allowedTouchBehaviors;
    433      allowedTouchBehaviors.AppendElement(aBehavior);
    434      apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors);
    435    }
    436    // Have content "respond" to the touchstart
    437    apzc->ContentReceivedInputBlock(blockId, false);
    438 
    439    MockFunction<void(std::string checkPointName)> check;
    440 
    441    {
    442      InSequence s;
    443 
    444      EXPECT_CALL(check, Call("preHandleLongTap"));
    445      blockId++;
    446      EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10),
    447                                  0, apzc->GetGuid(), blockId, _))
    448          .Times(1);
    449      EXPECT_CALL(check, Call("postHandleLongTap"));
    450 
    451      EXPECT_CALL(check, Call("preHandleLongTapUp"));
    452      EXPECT_CALL(*mcc,
    453                  HandleTap(TapType::eLongTapUp, LayoutDevicePoint(10, 10), 0,
    454                            apzc->GetGuid(), _, _))
    455          .Times(1);
    456      EXPECT_CALL(check, Call("postHandleLongTapUp"));
    457    }
    458 
    459    // Manually invoke the longpress while the touch is currently down.
    460    check.Call("preHandleLongTap");
    461    mcc->RunThroughDelayedTasks();
    462    check.Call("postHandleLongTap");
    463 
    464    // Dispatching the longpress event starts a new touch block, which
    465    // needs a new content response and also has a pending timeout task
    466    // in the queue. Deal with those here. We do the content response first
    467    // with preventDefault=false, and then we run the timeout task which
    468    // "loses the race" and does nothing.
    469    apzc->ContentReceivedInputBlock(blockId, false);
    470    mcc->AdvanceByMillis(1000);
    471 
    472    // Finally, simulate lifting the finger. Since the long-press wasn't
    473    // prevent-defaulted, we should get a long-tap-up event.
    474    check.Call("preHandleLongTapUp");
    475    result = TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
    476    mcc->RunThroughDelayedTasks();
    477    EXPECT_EQ(nsEventStatus_eConsumeDoDefault, result.GetStatus());
    478    check.Call("postHandleLongTapUp");
    479 
    480    apzc->AssertStateIsReset();
    481  }
    482 
    483  void DoLongPressPreventDefaultTest(uint32_t aBehavior) {
    484    MakeApzcUnzoomable();
    485 
    486    EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
    487 
    488    int touchX = 10, touchStartY = 50, touchEndY = 10;
    489 
    490    APZEventResult result =
    491        TouchDown(apzc, ScreenIntPoint(touchX, touchStartY), mcc->Time());
    492    EXPECT_EQ(nsEventStatus_eConsumeDoDefault, result.GetStatus());
    493    uint64_t blockId = result.mInputBlockId;
    494 
    495    if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
    496      // SetAllowedTouchBehavior() must be called after sending touch-start.
    497      nsTArray<uint32_t> allowedTouchBehaviors;
    498      allowedTouchBehaviors.AppendElement(aBehavior);
    499      apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors);
    500    }
    501    // Have content "respond" to the touchstart
    502    apzc->ContentReceivedInputBlock(blockId, false);
    503 
    504    MockFunction<void(std::string checkPointName)> check;
    505 
    506    {
    507      InSequence s;
    508 
    509      EXPECT_CALL(check, Call("preHandleLongTap"));
    510      blockId++;
    511      EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap,
    512                                  LayoutDevicePoint(touchX, touchStartY), 0,
    513                                  apzc->GetGuid(), blockId, _))
    514          .Times(1);
    515      EXPECT_CALL(check, Call("postHandleLongTap"));
    516    }
    517 
    518    // Manually invoke the longpress while the touch is currently down.
    519    check.Call("preHandleLongTap");
    520    mcc->RunThroughDelayedTasks();
    521    check.Call("postHandleLongTap");
    522 
    523    // There should be a TimeoutContentResponse task in the queue still,
    524    // waiting for the response from the longtap event dispatched above.
    525    // Send the signal that content has handled the long-tap, and then run
    526    // the timeout task (it will be a no-op because the content "wins" the
    527    // race. This takes the place of the "contextmenu" event.
    528    apzc->ContentReceivedInputBlock(blockId, true);
    529    mcc->AdvanceByMillis(1000);
    530 
    531    MultiTouchInput mti =
    532        CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, mcc->Time());
    533    mti.mTouches.AppendElement(CreateSingleTouchData(0, touchX, touchEndY));
    534    result = apzc->ReceiveInputEvent(mti);
    535    EXPECT_EQ(nsEventStatus_eConsumeDoDefault, result.GetStatus());
    536 
    537    EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap,
    538                                LayoutDevicePoint(touchX, touchEndY), 0,
    539                                apzc->GetGuid(), _, _))
    540        .Times(0);
    541    result = TouchUp(apzc, ScreenIntPoint(touchX, touchEndY), mcc->Time());
    542    EXPECT_EQ(nsEventStatus_eConsumeDoDefault, result.GetStatus());
    543 
    544    ParentLayerPoint pointOut;
    545    AsyncTransform viewTransformOut;
    546    apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
    547 
    548    EXPECT_EQ(ParentLayerPoint(), pointOut);
    549    EXPECT_EQ(AsyncTransform(), viewTransformOut);
    550 
    551    apzc->AssertStateIsReset();
    552  }
    553 
    554  // Tests a scenario that after a long-press event happened the original touch
    555  // block initiated by a touch-start event and the touch block initiated by a
    556  // long-tap event have been discarded when a new touch-start event happens.
    557  void DoLongPressDiscardTouchBlockTest(bool aWithTouchMove) {
    558    // Set apz.content_response_timeout > ui.click_hold_context_menus.delay and
    559    // apz.touch_start_tolerance explicitly to match Android preferences.
    560    SCOPED_GFX_PREF_INT("apz.content_response_timeout", 60);
    561    SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 30);
    562    SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 0.06);
    563 
    564    MockFunction<void(std::string checkPointName)> check;
    565    {
    566      InSequence s;
    567      EXPECT_CALL(check, Call("pre long-tap dispatch"));
    568      EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10),
    569                                  0, apzc->GetGuid(), _, _))
    570          .Times(1);
    571      EXPECT_CALL(check, Call("post long-tap dispatch"));
    572 
    573      // If a touch-move happens while long-tap is happening, there's no
    574      // eLongTapUp event.
    575      if (!aWithTouchMove) {
    576        EXPECT_CALL(*mcc,
    577                    HandleTap(TapType::eLongTapUp, LayoutDevicePoint(10, 20), 0,
    578                              apzc->GetGuid(), _, _))
    579            .Times(1);
    580      }
    581      EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10),
    582                                  0, apzc->GetGuid(), _, _))
    583          .Times(1);
    584    }
    585 
    586    // Keep touching for a while to trigger a long tap event.
    587    uint64_t firstTouchBlockId =
    588        TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId;
    589    TouchBlockState* firstTouchBlock =
    590        tm->GetInputQueue()->GetCurrentTouchBlock();
    591    EXPECT_NE(firstTouchBlock, nullptr);
    592    EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId),
    593              firstTouchBlock);
    594 
    595    // Wait for a long tap.
    596    check.Call("pre long-tap dispatch");
    597    mcc->AdvanceByMillis(30);
    598    check.Call("post long-tap dispatch");
    599 
    600    // Now the current touch block is not the first touch block, it should be
    601    // a new touch block for the long tap event.
    602    TouchBlockState* secondTouchBlock =
    603        tm->GetInputQueue()->GetCurrentTouchBlock();
    604    EXPECT_NE(secondTouchBlock, firstTouchBlock);
    605    EXPECT_TRUE(secondTouchBlock->ForLongTap());
    606    uint64_t secondTouchBlockId = secondTouchBlock->GetBlockId();
    607 
    608    if (aWithTouchMove) {
    609      mcc->AdvanceByMillis(10);
    610      TouchMove(apzc, ScreenIntPoint(10, 20), mcc->Time());
    611    }
    612 
    613    // Finish the first touch block.
    614    mcc->AdvanceByMillis(10);
    615    TouchUp(apzc, ScreenIntPoint(10, 20), mcc->Time());
    616 
    617    // And start a new touch block.
    618    mcc->AdvanceByMillis(10);
    619    uint64_t newTouchBlockId =
    620        TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId;
    621 
    622    mcc->AdvanceByMillis(10);
    623    // Now the original touch block and the touch block for long-tap should have
    624    // been discarded from the input queue.
    625    EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId), nullptr);
    626    EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(secondTouchBlockId), nullptr);
    627    EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(newTouchBlockId),
    628              tm->GetInputQueue()->GetCurrentBlock());
    629  }
    630 };
    631 
    632 TEST_F(APZCLongPressTester, LongPress) {
    633  DoLongPressTest(kDefaultTouchBehavior);
    634 }
    635 
    636 TEST_F(APZCLongPressTester, LongPressPreventDefault) {
    637  DoLongPressPreventDefaultTest(kDefaultTouchBehavior);
    638 }
    639 
    640 TEST_F(APZCLongPressTester, LongPressDiscardBlock) {
    641  DoLongPressDiscardTouchBlockTest(true /* with touch-move */);
    642 }
    643 
    644 // Similar to above LongPressDiscardBlock but APZ is waiting for responses from
    645 // the content.
    646 TEST_F(APZCLongPressTester, LongPressDiscardBlock2) {
    647  MakeApzcWaitForMainThread();
    648  DoLongPressDiscardTouchBlockTest(true /* with touch-move */);
    649 }
    650 
    651 // Similar to above LongPressDiscardBlock/LongPressDiscardBlock2 without
    652 // touch-move events.
    653 TEST_F(APZCLongPressTester, LongPressDiscardBlock3) {
    654  DoLongPressDiscardTouchBlockTest(false /* without touch-move */);
    655 }
    656 
    657 TEST_F(APZCLongPressTester, LongPressDiscardBlock4) {
    658  MakeApzcWaitForMainThread();
    659  DoLongPressDiscardTouchBlockTest(false /* without touch-move */);
    660 }
    661 
    662 TEST_F(APZCGestureDetectorTester, DoubleTap) {
    663  MakeApzcWaitForMainThread();
    664  MakeApzcZoomable();
    665 
    666  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    667                              apzc->GetGuid(), _, _))
    668      .Times(0);
    669  EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, LayoutDevicePoint(10, 10), 0,
    670                              apzc->GetGuid(), _, _))
    671      .Times(1);
    672 
    673  uint64_t blockIds[2];
    674  DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
    675 
    676  // responses to the two touchstarts
    677  apzc->ContentReceivedInputBlock(blockIds[0], false);
    678  apzc->ContentReceivedInputBlock(blockIds[1], false);
    679 
    680  apzc->AssertStateIsReset();
    681 }
    682 
    683 TEST_F(APZCGestureDetectorTester, DoubleTapNotZoomable) {
    684  MakeApzcWaitForMainThread();
    685  MakeApzcUnzoomable();
    686 
    687  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    688                              apzc->GetGuid(), _, _))
    689      .Times(1);
    690  EXPECT_CALL(*mcc, HandleTap(TapType::eSecondTap, LayoutDevicePoint(10, 10), 0,
    691                              apzc->GetGuid(), _, _))
    692      .Times(1);
    693  EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, LayoutDevicePoint(10, 10), 0,
    694                              apzc->GetGuid(), _, _))
    695      .Times(0);
    696 
    697  uint64_t blockIds[2];
    698  DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
    699 
    700  // responses to the two touchstarts
    701  apzc->ContentReceivedInputBlock(blockIds[0], false);
    702  apzc->ContentReceivedInputBlock(blockIds[1], false);
    703 
    704  apzc->AssertStateIsReset();
    705 }
    706 
    707 TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultFirstOnly) {
    708  MakeApzcWaitForMainThread();
    709  MakeApzcZoomable();
    710 
    711  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    712                              apzc->GetGuid(), _, _))
    713      .Times(1);
    714  EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, LayoutDevicePoint(10, 10), 0,
    715                              apzc->GetGuid(), _, _))
    716      .Times(0);
    717 
    718  uint64_t blockIds[2];
    719  DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
    720 
    721  // responses to the two touchstarts
    722  apzc->ContentReceivedInputBlock(blockIds[0], true);
    723  apzc->ContentReceivedInputBlock(blockIds[1], false);
    724 
    725  apzc->AssertStateIsReset();
    726 }
    727 
    728 TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) {
    729  MakeApzcWaitForMainThread();
    730  MakeApzcZoomable();
    731 
    732  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    733                              apzc->GetGuid(), _, _))
    734      .Times(0);
    735  EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, LayoutDevicePoint(10, 10), 0,
    736                              apzc->GetGuid(), _, _))
    737      .Times(0);
    738 
    739  uint64_t blockIds[2];
    740  DoubleTapAndCheckStatus(apzc, ScreenIntPoint(10, 10), &blockIds);
    741 
    742  // responses to the two touchstarts
    743  apzc->ContentReceivedInputBlock(blockIds[0], true);
    744  apzc->ContentReceivedInputBlock(blockIds[1], true);
    745 
    746  apzc->AssertStateIsReset();
    747 }
    748 
    749 // Test for bug 947892
    750 // We test whether we dispatch tap event when the tap is followed by pinch.
    751 // Additionally test that the pinch gesture successfully results in zooming.
    752 TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) {
    753  MakeApzcZoomable();
    754 
    755  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    756                              apzc->GetGuid(), _, _))
    757      .Times(1);
    758 
    759  Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(100));
    760 
    761  PinchWithTouchInput(
    762      apzc, ScreenIntPoint(15, 15), 1.5,
    763      PinchOptions().TimeBetweenTouchEvents(
    764          // Time it so that the max tap timer expires while the fingers are
    765          // down for the pinch but haven't started to move yet.
    766          TimeDuration::FromMilliseconds(StaticPrefs::apz_max_tap_time() -
    767                                         90)));
    768 
    769  EXPECT_GT(apzc->GetFrameMetrics().GetZoom().scale, 1.0f);
    770  apzc->AssertStateIsReset();
    771 }
    772 
    773 TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) {
    774  MakeApzcZoomable();
    775 
    776  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    777                              apzc->GetGuid(), _, _))
    778      .Times(1);
    779 
    780  Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(100));
    781 
    782  int inputId = 0;
    783  MultiTouchInput mti;
    784  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    785  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20),
    786                                             ScreenSize(0, 0), 0, 0));
    787  apzc->ReceiveInputEvent(mti, Some(nsTArray<uint32_t>{kDefaultTouchBehavior}));
    788 
    789  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    790  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20),
    791                                             ScreenSize(0, 0), 0, 0));
    792  mti.mTouches.AppendElement(SingleTouchData(
    793      inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
    794  apzc->ReceiveInputEvent(mti, Some(nsTArray<uint32_t>{kDefaultTouchBehavior}));
    795 
    796  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_END, mcc->Time());
    797  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20),
    798                                             ScreenSize(0, 0), 0, 0));
    799  mti.mTouches.AppendElement(SingleTouchData(
    800      inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
    801  apzc->ReceiveInputEvent(mti);
    802 
    803  apzc->AssertStateIsReset();
    804 }
    805 
    806 TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) {
    807  // Since we try to allow concurrent input blocks of different types to
    808  // co-exist, the wheel block shouldn't interrupt the long-press detection.
    809  // But more importantly, this shouldn't crash, which is what it did at one
    810  // point in time.
    811  EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _, _)).Times(1);
    812 
    813  APZEventResult result = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    814  uint64_t touchBlockId = result.mInputBlockId;
    815  if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
    816    SetDefaultAllowedTouchBehavior(apzc, touchBlockId);
    817  }
    818  mcc->AdvanceByMillis(10);
    819  uint64_t wheelBlockId =
    820      Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time())
    821          .mInputBlockId;
    822  EXPECT_NE(touchBlockId, wheelBlockId);
    823  mcc->AdvanceByMillis(1000);
    824 }
    825 
    826 TEST_F(APZCGestureDetectorTester, TapTimeoutInterruptedByWheel) {
    827  // In this test, even though the wheel block comes right after the tap, the
    828  // tap should still be dispatched because it completes fully before the wheel
    829  // block arrived.
    830  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, LayoutDevicePoint(10, 10), 0,
    831                              apzc->GetGuid(), _, _))
    832      .Times(1);
    833 
    834  // We make the APZC zoomable so the gesture detector needs to wait to
    835  // distinguish between tap and double-tap. During that timeout is when we
    836  // insert the wheel event.
    837  MakeApzcZoomable();
    838 
    839  APZEventResult result = Tap(apzc, ScreenIntPoint(10, 10),
    840                              TimeDuration::FromMilliseconds(100), nullptr);
    841  mcc->AdvanceByMillis(10);
    842  uint64_t wheelBlockId =
    843      Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time())
    844          .mInputBlockId;
    845  EXPECT_NE(result.mInputBlockId, wheelBlockId);
    846  while (mcc->RunThroughDelayedTasks());
    847 }
    848 
    849 TEST_F(APZCGestureDetectorTester, LongPressWithInputQueueDelay) {
    850  // In this test, we ensure that any time spent waiting in the input queue for
    851  // the content response is subtracted from the long-press timeout in the
    852  // GestureEventListener. In this test the content response timeout is longer
    853  // than the long-press timeout.
    854  SCOPED_GFX_PREF_INT("apz.content_response_timeout", 60);
    855  SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 30);
    856 
    857  MakeApzcWaitForMainThread();
    858 
    859  MockFunction<void(std::string checkPointName)> check;
    860 
    861  {
    862    InSequence s;
    863    EXPECT_CALL(check, Call("pre long-tap dispatch"));
    864    EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), 0,
    865                                apzc->GetGuid(), _, _))
    866        .Times(1);
    867    EXPECT_CALL(check, Call("post long-tap dispatch"));
    868  }
    869 
    870  // Touch down
    871  APZEventResult result = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    872  uint64_t touchBlockId = result.mInputBlockId;
    873  // Simulate content response after 10ms
    874  mcc->AdvanceByMillis(10);
    875  apzc->ContentReceivedInputBlock(touchBlockId, false);
    876  apzc->SetAllowedTouchBehavior(touchBlockId, {kDefaultTouchBehavior});
    877  apzc->ConfirmTarget(touchBlockId);
    878  // Ensure long-tap event happens within 20ms after that
    879  check.Call("pre long-tap dispatch");
    880  mcc->AdvanceByMillis(20);
    881  check.Call("post long-tap dispatch");
    882 }
    883 
    884 TEST_F(APZCGestureDetectorTester, LongPressWithInputQueueDelay2) {
    885  // Similar to the previous test, except this time we don't simulate the
    886  // content response at all, and still expect the long-press to happen on
    887  // schedule.
    888  SCOPED_GFX_PREF_INT("apz.content_response_timeout", 60);
    889  SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 30);
    890 
    891  MakeApzcWaitForMainThread();
    892 
    893  MockFunction<void(std::string checkPointName)> check;
    894 
    895  {
    896    InSequence s;
    897    EXPECT_CALL(check, Call("pre long-tap dispatch"));
    898    EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), 0,
    899                                apzc->GetGuid(), _, _))
    900        .Times(1);
    901    EXPECT_CALL(check, Call("post long-tap dispatch"));
    902  }
    903 
    904  // Touch down
    905  TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    906  // Ensure the long-tap happens within 30ms even though there's no content
    907  // response.
    908  check.Call("pre long-tap dispatch");
    909  mcc->AdvanceByMillis(30);
    910  check.Call("post long-tap dispatch");
    911 }
    912 
    913 TEST_F(APZCGestureDetectorTester, LongPressWithInputQueueDelay3) {
    914  // Similar to the previous test, except now we have the long-press delay
    915  // being longer than the content response timeout.
    916  SCOPED_GFX_PREF_INT("apz.content_response_timeout", 30);
    917  SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 60);
    918 
    919  MakeApzcWaitForMainThread();
    920 
    921  MockFunction<void(std::string checkPointName)> check;
    922 
    923  {
    924    InSequence s;
    925    EXPECT_CALL(check, Call("pre long-tap dispatch"));
    926    EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), 0,
    927                                apzc->GetGuid(), _, _))
    928        .Times(1);
    929    EXPECT_CALL(check, Call("post long-tap dispatch"));
    930  }
    931 
    932  // Touch down
    933  TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    934  // Ensure the long-tap happens at the 60ms mark even though the input event
    935  // waits in the input queue for the full content response timeout of 30ms
    936  mcc->AdvanceByMillis(59);
    937  check.Call("pre long-tap dispatch");
    938  mcc->AdvanceByMillis(1);
    939  check.Call("post long-tap dispatch");
    940 }
    941 
    942 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureShort) {
    943  // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
    944  // hold second touch down for a very short time, then move
    945  // and expect a successful one touch pinch gesture
    946  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
    947 
    948  MakeApzcZoomable();
    949  apzc->SetFrameMetrics(GetPinchableFrameMetrics());
    950  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
    951 
    952  const auto tapResult =
    953      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
    954  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
    955                                {kDefaultTouchBehavior});
    956 
    957  mcc->AdvanceByMillis(10);
    958  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    959  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
    960                                {kDefaultTouchBehavior});
    961 
    962  // We should be able to hold down the second touch as long as we like
    963  // before beginning to move
    964  mcc->AdvanceByMillis(10);
    965  TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
    966 
    967  mcc->AdvanceByMillis(10);
    968  TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
    969 
    970  mcc->AdvanceByMillis(10);
    971  TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
    972 
    973  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
    974  EXPECT_NE(newZoom, oldZoom);
    975 }
    976 
    977 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureLong) {
    978  // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
    979  // hold second touch down for a long time, then move
    980  // and expect a successful one touch pinch gesture
    981  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
    982 
    983  MakeApzcZoomable();
    984  apzc->SetFrameMetrics(GetPinchableFrameMetrics());
    985  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
    986 
    987  const auto tapResult =
    988      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
    989  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
    990                                {kDefaultTouchBehavior});
    991 
    992  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
    993  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    994  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
    995                                {kDefaultTouchBehavior});
    996 
    997  // We should be able to hold down the second touch as long as we like
    998  // before beginning to move
    999  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
   1000  TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
   1001 
   1002  mcc->AdvanceByMillis(10);
   1003  TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1004 
   1005  mcc->AdvanceByMillis(10);
   1006  TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1007 
   1008  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1009  EXPECT_NE(newZoom, oldZoom);
   1010 }
   1011 
   1012 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNoMoveTriggersDoubleTap) {
   1013  // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
   1014  // then wait longer than StaticPrefs::apz_max_tap_time(), lift finger up
   1015  // and expect a successful double tap. No zooming should be performed
   1016  // by the one-touch pinch codepath.
   1017  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
   1018 
   1019  apzc->SetFrameMetrics(GetPinchableFrameMetrics());
   1020  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1021 
   1022  MakeApzcZoomable();
   1023 
   1024  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
   1025      .Times(0);
   1026  EXPECT_CALL(*mcc,
   1027              HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _));
   1028 
   1029  const auto tapResult =
   1030      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
   1031  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
   1032                                {kDefaultTouchBehavior});
   1033 
   1034  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
   1035  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
   1036  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
   1037                                {kDefaultTouchBehavior});
   1038 
   1039  // We should be able to hold down the second touch as long as we like
   1040  // before lifting the finger
   1041  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
   1042  TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
   1043 
   1044  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1045  EXPECT_EQ(newZoom, oldZoom);
   1046 }
   1047 
   1048 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNonZoomablePage) {
   1049  // Use a non-zoomable page. Perform a tap and a touch-drag
   1050  // which on a zoomable page trigger a one touch pinch gesture,
   1051  // and expect a single tap followed by a touch-scroll
   1052  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
   1053 
   1054  apzc->SetFrameMetrics(GetPinchableFrameMetrics(1.0f));
   1055  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1056  const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
   1057  MakeApzcUnzoomable();
   1058 
   1059  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
   1060      .Times(1);
   1061  EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _))
   1062      .Times(0);
   1063 
   1064  const auto tapResult =
   1065      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
   1066  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
   1067                                {kDefaultTouchBehavior});
   1068 
   1069  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
   1070  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
   1071  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
   1072                                {kDefaultTouchBehavior});
   1073 
   1074  // We should be able to hold down the second touch as long as we like
   1075  // before beginning to move
   1076  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
   1077  TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
   1078 
   1079  mcc->AdvanceByMillis(10);
   1080  TouchMove(apzc, ScreenIntPoint(10, 100), mcc->Time());
   1081 
   1082  mcc->AdvanceByMillis(10);
   1083  TouchUp(apzc, ScreenIntPoint(10, 100), mcc->Time());
   1084 
   1085  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1086  EXPECT_EQ(newZoom, oldZoom);
   1087 
   1088  const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
   1089  EXPECT_NE(newScrollOffset, oldScrollOffset);
   1090 }
   1091 
   1092 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureTimeout) {
   1093  // Take longer than StaticPrefs::apz_max_tap_time() until second touch down
   1094  // and expect no one touch pinch gesture being performed
   1095  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
   1096 
   1097  MakeApzcZoomable();
   1098  apzc->SetFrameMetrics(GetPinchableFrameMetrics());
   1099  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1100 
   1101  EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
   1102      .Times(1);
   1103 
   1104  const auto tapResult =
   1105      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
   1106  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
   1107                                {kDefaultTouchBehavior});
   1108 
   1109  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time());
   1110  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
   1111  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
   1112                                {kDefaultTouchBehavior});
   1113 
   1114  mcc->AdvanceByMillis(10);
   1115  TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
   1116 
   1117  mcc->AdvanceByMillis(10);
   1118  TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1119 
   1120  mcc->AdvanceByMillis(10);
   1121  TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1122 
   1123  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1124  EXPECT_EQ(newZoom, oldZoom);
   1125 }
   1126 
   1127 TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureDisabled) {
   1128  // With apz.one_touch_pinch disabled,
   1129  // perform one touch pinch gesture within the time threshold,
   1130  // and expect no zooming.
   1131  SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", false);
   1132 
   1133  MakeApzcZoomable();
   1134  apzc->SetFrameMetrics(GetPinchableFrameMetrics());
   1135  const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1136  const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
   1137 
   1138  // todo: enable following EXPECT_CALLs when fixing bug 1881794
   1139  // EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _,
   1140  // _))
   1141  //     .Times(1);
   1142  // EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _,
   1143  // _))
   1144  //     .Times(0);
   1145 
   1146  const auto tapResult =
   1147      Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
   1148  apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
   1149                                {kDefaultTouchBehavior});
   1150 
   1151  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
   1152  const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
   1153  apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
   1154                                {kDefaultTouchBehavior});
   1155 
   1156  // We should be able to hold down the second touch as long as we like
   1157  // before beginning to move
   1158  mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
   1159  TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
   1160 
   1161  mcc->AdvanceByMillis(10);
   1162  TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1163 
   1164  mcc->AdvanceByMillis(10);
   1165  TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
   1166 
   1167  const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
   1168  EXPECT_EQ(newZoom, oldZoom);
   1169 
   1170  const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
   1171  EXPECT_NE(newScrollOffset, oldScrollOffset);
   1172 }