tor-browser

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

TestTreeManager.cpp (22053B)


      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 "APZCTreeManagerTester.h"
      8 #include "APZTestCommon.h"
      9 #include "InputUtils.h"
     10 #include "Units.h"
     11 #include "mozilla/BasicEvents.h"
     12 #include "mozilla/StaticPrefs_apz.h"
     13 
     14 class APZCTreeManagerGenericTester : public APZCTreeManagerTester {
     15 protected:
     16  void CreateSimpleScrollingLayer() {
     17    const char* treeShape = "x";
     18    LayerIntRect layerVisibleRect[] = {
     19        LayerIntRect(0, 0, 200, 200),
     20    };
     21    CreateScrollData(treeShape, layerVisibleRect);
     22    SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID,
     23                              CSSRect(0, 0, 500, 500));
     24  }
     25 
     26  void CreateSimpleMultiLayerTree() {
     27    const char* treeShape = "x(xx)";
     28    // LayerID               0 12
     29    LayerIntRect layerVisibleRect[] = {
     30        LayerIntRect(0, 0, 100, 100),
     31        LayerIntRect(0, 0, 100, 50),
     32        LayerIntRect(0, 50, 100, 50),
     33    };
     34    CreateScrollData(treeShape, layerVisibleRect);
     35  }
     36 
     37  void CreatePotentiallyLeakingTree() {
     38    const char* treeShape = "x(x(x(x))x(x(x)))";
     39    // LayerID               0 1 2 3  4 5 6
     40    CreateScrollData(treeShape);
     41    SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID);
     42    SetScrollableFrameMetrics(layers[2],
     43                              ScrollableLayerGuid::START_SCROLL_ID + 1);
     44    SetScrollableFrameMetrics(layers[5],
     45                              ScrollableLayerGuid::START_SCROLL_ID + 1);
     46    SetScrollableFrameMetrics(layers[3],
     47                              ScrollableLayerGuid::START_SCROLL_ID + 2);
     48    SetScrollableFrameMetrics(layers[6],
     49                              ScrollableLayerGuid::START_SCROLL_ID + 3);
     50  }
     51 
     52  void CreateTwoLayerTree(int32_t aRootContentLayerIndex) {
     53    const char* treeShape = "x(x)";
     54    // LayerID               0 1
     55    LayerIntRect layerVisibleRect[] = {
     56        LayerIntRect(0, 0, 100, 100),
     57        LayerIntRect(0, 0, 100, 100),
     58    };
     59    CreateScrollData(treeShape, layerVisibleRect);
     60    SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID);
     61    SetScrollableFrameMetrics(layers[1],
     62                              ScrollableLayerGuid::START_SCROLL_ID + 1);
     63    SetScrollHandoff(layers[1], layers[0]);
     64 
     65    // Make layers[aRootContentLayerIndex] the root content
     66    ModifyFrameMetrics(layers[aRootContentLayerIndex],
     67                       [](ScrollMetadata& sm, FrameMetrics& fm) {
     68                         fm.SetIsRootContent(true);
     69                       });
     70  }
     71 };
     72 
     73 TEST_F(APZCTreeManagerGenericTester, ScrollablePaintedLayers) {
     74  CreateSimpleMultiLayerTree();
     75  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
     76 
     77  // both layers have the same scrollId
     78  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID);
     79  SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID);
     80  UpdateHitTestingTree();
     81 
     82  TestAsyncPanZoomController* nullAPZC = nullptr;
     83  // so they should have the same APZC
     84  EXPECT_FALSE(HasScrollableFrameMetrics(layers[0]));
     85  EXPECT_NE(nullAPZC, ApzcOf(layers[1]));
     86  EXPECT_NE(nullAPZC, ApzcOf(layers[2]));
     87  EXPECT_EQ(ApzcOf(layers[1]), ApzcOf(layers[2]));
     88 }
     89 
     90 TEST_F(APZCTreeManagerGenericTester, Bug1068268) {
     91  CreatePotentiallyLeakingTree();
     92  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
     93 
     94  UpdateHitTestingTree();
     95  RefPtr<HitTestingTreeNode> root = manager->GetRootNode();
     96  RefPtr<HitTestingTreeNode> node2 = root->GetFirstChild()->GetFirstChild();
     97  RefPtr<HitTestingTreeNode> node5 = root->GetLastChild()->GetLastChild();
     98 
     99  EXPECT_EQ(ApzcOf(layers[2]), node5->GetApzc());
    100  EXPECT_EQ(ApzcOf(layers[2]), node2->GetApzc());
    101  EXPECT_EQ(ApzcOf(layers[0]), ApzcOf(layers[2])->GetParent());
    102  EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[5]));
    103 
    104  EXPECT_EQ(node2->GetFirstChild(), node2->GetLastChild());
    105  EXPECT_EQ(ApzcOf(layers[3]), node2->GetLastChild()->GetApzc());
    106  EXPECT_EQ(node5->GetFirstChild(), node5->GetLastChild());
    107  EXPECT_EQ(ApzcOf(layers[6]), node5->GetLastChild()->GetApzc());
    108  EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[3])->GetParent());
    109  EXPECT_EQ(ApzcOf(layers[5]), ApzcOf(layers[6])->GetParent());
    110 }
    111 
    112 class APZCTreeManagerGenericTesterMock : public APZCTreeManagerGenericTester {
    113 public:
    114  APZCTreeManagerGenericTesterMock() { CreateMockHitTester(); }
    115 };
    116 
    117 TEST_F(APZCTreeManagerGenericTesterMock, Bug1194876) {
    118  // Create a layer tree with parent and child scrollable layers, with the
    119  // child being the root content.
    120  CreateTwoLayerTree(1);
    121  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    122  UpdateHitTestingTree();
    123 
    124  uint64_t blockId;
    125  nsTArray<ScrollableLayerGuid> targets;
    126 
    127  // First touch goes down, APZCTM will hit layers[1] because it is on top of
    128  // layers[0], but we tell it the real target APZC is layers[0].
    129  MultiTouchInput mti;
    130  mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    131  mti.mTouches.AppendElement(
    132      SingleTouchData(0, ScreenIntPoint(25, 50), ScreenSize(0, 0), 0, 0));
    133  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    134                     {CompositorHitTestFlags::eVisibleToHitTest,
    135                      CompositorHitTestFlags::eIrregularArea});
    136  blockId = manager->ReceiveInputEvent(mti).mInputBlockId;
    137  manager->ContentReceivedInputBlock(blockId, false);
    138  targets.AppendElement(ApzcOf(layers[0])->GetGuid());
    139  manager->SetTargetAPZC(blockId, targets);
    140 
    141  // Around here, the above touch will get processed by ApzcOf(layers[0])
    142 
    143  // Second touch goes down (first touch remains down), APZCTM will again hit
    144  // layers[1]. Again we tell it both touches landed on layers[0], but because
    145  // layers[1] is the RCD layer, it will end up being the multitouch target.
    146  mti.mTouches.AppendElement(
    147      SingleTouchData(1, ScreenIntPoint(75, 50), ScreenSize(0, 0), 0, 0));
    148  // Each touch will get hit-tested, so queue two hit-test results.
    149  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    150                     {CompositorHitTestFlags::eVisibleToHitTest,
    151                      CompositorHitTestFlags::eIrregularArea});
    152  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    153                     {CompositorHitTestFlags::eVisibleToHitTest,
    154                      CompositorHitTestFlags::eIrregularArea});
    155  blockId = manager->ReceiveInputEvent(mti).mInputBlockId;
    156  manager->ContentReceivedInputBlock(blockId, false);
    157  targets.AppendElement(ApzcOf(layers[0])->GetGuid());
    158  manager->SetTargetAPZC(blockId, targets);
    159 
    160  // Around here, the above multi-touch will get processed by ApzcOf(layers[1]).
    161  // We want to ensure that ApzcOf(layers[0]) has had its state cleared, because
    162  // otherwise it will do things like dispatch spurious long-tap events.
    163 
    164  EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _, _)).Times(0);
    165 }
    166 
    167 TEST_F(APZCTreeManagerGenericTesterMock, TargetChangesMidGesture_Bug1570559) {
    168  // Create a layer tree with parent and child scrollable layers, with the
    169  // parent being the root content.
    170  CreateTwoLayerTree(0);
    171  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    172  UpdateHitTestingTree();
    173 
    174  uint64_t blockId;
    175  nsTArray<ScrollableLayerGuid> targets;
    176 
    177  // First touch goes down. APZCTM hits the child layer because it is on top
    178  // (and we confirm this target), but do not prevent-default the event, causing
    179  // the child APZC's gesture detector to start a long-tap timeout task.
    180  MultiTouchInput mti =
    181      CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time());
    182  mti.mTouches.AppendElement(
    183      SingleTouchData(0, ScreenIntPoint(25, 50), ScreenSize(0, 0), 0, 0));
    184  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    185                     {CompositorHitTestFlags::eVisibleToHitTest,
    186                      CompositorHitTestFlags::eIrregularArea});
    187  blockId = manager->ReceiveInputEvent(mti).mInputBlockId;
    188  manager->ContentReceivedInputBlock(blockId, /* default prevented = */ false);
    189  targets.AppendElement(ApzcOf(layers[1])->GetGuid());
    190  manager->SetTargetAPZC(blockId, targets);
    191 
    192  // Second touch goes down (first touch remains down). APZCTM again hits the
    193  // child and we confirm this, but multi-touch events are routed to the root
    194  // content APZC which is the parent. This event is prevent-defaulted, so we
    195  // clear the parent's gesture state. The bug is that we fail to clear the
    196  // child's gesture state.
    197  mti.mTouches.AppendElement(
    198      SingleTouchData(1, ScreenIntPoint(75, 50), ScreenSize(0, 0), 0, 0));
    199  // Each touch will get hit-tested, so queue two hit-test results.
    200  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    201                     {CompositorHitTestFlags::eVisibleToHitTest,
    202                      CompositorHitTestFlags::eIrregularArea});
    203  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1,
    204                     {CompositorHitTestFlags::eVisibleToHitTest,
    205                      CompositorHitTestFlags::eIrregularArea});
    206  blockId = manager->ReceiveInputEvent(mti).mInputBlockId;
    207  manager->ContentReceivedInputBlock(blockId, /* default prevented = */ true);
    208  targets.AppendElement(ApzcOf(layers[1])->GetGuid());
    209  manager->SetTargetAPZC(blockId, targets);
    210 
    211  // If we've failed to clear the child's gesture state, then the long tap
    212  // timeout task will fire in TearDown() and a long-tap will be dispatched.
    213  EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _, _)).Times(0);
    214 }
    215 
    216 TEST_F(APZCTreeManagerGenericTesterMock, Bug1198900) {
    217  // This is just a test that cancels a wheel event to make sure it doesn't
    218  // crash.
    219  CreateSimpleScrollingLayer();
    220  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    221  UpdateHitTestingTree();
    222 
    223  ScreenPoint origin(100, 50);
    224  ScrollWheelInput swi(mcc->Time(), 0, ScrollWheelInput::SCROLLMODE_INSTANT,
    225                       ScrollWheelInput::SCROLLDELTA_PIXEL, origin, 0, 10,
    226                       false, WheelDeltaAdjustmentStrategy::eNone);
    227  uint64_t blockId;
    228  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID,
    229                     {CompositorHitTestFlags::eVisibleToHitTest,
    230                      CompositorHitTestFlags::eIrregularArea});
    231  blockId = manager->ReceiveInputEvent(swi).mInputBlockId;
    232  manager->ContentReceivedInputBlock(blockId, /* preventDefault= */ true);
    233 }
    234 
    235 // The next two tests check that APZ clamps the scroll offset it composites even
    236 // if the main thread fails to do so. (The main thread will always clamp its
    237 // scroll offset internally, but it may not send APZ the clamped version for
    238 // scroll offset synchronization reasons.)
    239 TEST_F(APZCTreeManagerTester, Bug1551582) {
    240  // The simple layer tree has a scrollable rect of 500x500 and a composition
    241  // bounds of 200x200, leading to a scroll range of (0,0,300,300).
    242  CreateSimpleScrollingLayer();
    243  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    244  UpdateHitTestingTree();
    245 
    246  // Simulate the main thread scrolling to the end of the scroll range.
    247  ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
    248    aMetrics.SetLayoutScrollOffset(CSSPoint(300, 300));
    249    nsTArray<ScrollPositionUpdate> scrollUpdates;
    250    scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
    251        ScrollOrigin::Other, CSSPoint::ToAppUnits(CSSPoint(300, 300))));
    252    aSm.SetScrollUpdates(scrollUpdates);
    253    aMetrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration());
    254  });
    255  UpdateHitTestingTree();
    256 
    257  // Sanity check.
    258  RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
    259  CSSPoint compositedScrollOffset = apzc->GetCompositedScrollOffset();
    260  EXPECT_EQ(CSSPoint(300, 300), compositedScrollOffset);
    261 
    262  // Simulate the main thread shrinking the scrollable rect to 400x400 (and
    263  // thereby the scroll range to (0,0,200,200) without sending a new scroll
    264  // offset update for the clamped scroll position (200,200).
    265  ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
    266    aMetrics.SetScrollableRect(CSSRect(0, 0, 400, 400));
    267  });
    268  UpdateHitTestingTree();
    269 
    270  // Check that APZ has clamped the scroll offset to (200,200) for us.
    271  compositedScrollOffset = apzc->GetCompositedScrollOffset();
    272  EXPECT_EQ(CSSPoint(200, 200), compositedScrollOffset);
    273 }
    274 TEST_F(APZCTreeManagerTester, Bug1557424) {
    275  // The simple layer tree has a scrollable rect of 500x500 and a composition
    276  // bounds of 200x200, leading to a scroll range of (0,0,300,300).
    277  CreateSimpleScrollingLayer();
    278  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    279  UpdateHitTestingTree();
    280 
    281  // Simulate the main thread scrolling to the end of the scroll range.
    282  ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
    283    aMetrics.SetLayoutScrollOffset(CSSPoint(300, 300));
    284    nsTArray<ScrollPositionUpdate> scrollUpdates;
    285    scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
    286        ScrollOrigin::Other, CSSPoint::ToAppUnits(CSSPoint(300, 300))));
    287    aSm.SetScrollUpdates(scrollUpdates);
    288    aMetrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration());
    289  });
    290  UpdateHitTestingTree();
    291 
    292  // Sanity check.
    293  RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
    294  CSSPoint compositedScrollOffset = apzc->GetCompositedScrollOffset();
    295  EXPECT_EQ(CSSPoint(300, 300), compositedScrollOffset);
    296 
    297  // Simulate the main thread expanding the composition bounds to 300x300 (and
    298  // thereby shrinking the scroll range to (0,0,200,200) without sending a new
    299  // scroll offset update for the clamped scroll position (200,200).
    300  ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
    301    aMetrics.SetCompositionBounds(ParentLayerRect(0, 0, 300, 300));
    302  });
    303  UpdateHitTestingTree();
    304 
    305  // Check that APZ has clamped the scroll offset to (200,200) for us.
    306  compositedScrollOffset = apzc->GetCompositedScrollOffset();
    307  EXPECT_EQ(CSSPoint(200, 200), compositedScrollOffset);
    308 }
    309 
    310 TEST_F(APZCTreeManagerTester, Bug1805601) {
    311  // The simple layer tree has a scrollable rect of 500x500 and a composition
    312  // bounds of 200x200, leading to a scroll range of (0,0,300,300) at unit zoom.
    313  CreateSimpleScrollingLayer();
    314  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    315  UpdateHitTestingTree();
    316  RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
    317  FrameMetrics& compositorMetrics = apzc->GetFrameMetrics();
    318  EXPECT_EQ(CSSRect(0, 0, 300, 300), compositorMetrics.CalculateScrollRange());
    319 
    320  // Zoom the page in by 2x. This needs to be reflected in each of the pres
    321  // shell resolution, cumulative resolution, and zoom. This makes the scroll
    322  // range (0,0,400,400).
    323  compositorMetrics.SetZoom(CSSToParentLayerScale(2.0));
    324  EXPECT_EQ(CSSRect(0, 0, 400, 400), compositorMetrics.CalculateScrollRange());
    325 
    326  // Scroll to an area inside the 2x scroll range but outside the original one.
    327  compositorMetrics.ClampAndSetVisualScrollOffset(CSSPoint(350, 350));
    328  EXPECT_EQ(CSSPoint(350, 350), compositorMetrics.GetVisualScrollOffset());
    329 
    330  // Simulate a main-thread update where the zoom is reset to 1x but the visual
    331  // scroll offset is unmodified.
    332  ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
    333    // Changes to |compositorMetrics| are not reflected in |aMetrics|, which
    334    // is the "layer tree" copy, so we don't need to explicitly set the zoom to
    335    // 1.0 (it still has that as the initial value), but we do need to set
    336    // the visual scroll offset to the same value the APZ copy has.
    337    aMetrics.SetVisualScrollOffset(CSSPoint(350, 350));
    338 
    339    // Needed to get APZ to accept the 1.0 zoom in |aMetrics|, otherwise
    340    // it will act as though its zoom is newer (e.g. an async zoom that hasn't
    341    // been repainted yet) and ignore ours.
    342    aSm.SetResolutionUpdated(true);
    343  });
    344  UpdateHitTestingTree();
    345 
    346  // Check that APZ clamped the scroll offset.
    347  EXPECT_EQ(CSSRect(0, 0, 300, 300), compositorMetrics.CalculateScrollRange());
    348  EXPECT_EQ(CSSPoint(300, 300), compositorMetrics.GetVisualScrollOffset());
    349 }
    350 
    351 TEST_F(APZCTreeManagerTester,
    352       InstantKeyScrollBetweenTwoSamplingsWithSameTimeStamp) {
    353  if (!StaticPrefs::apz_keyboard_enabled_AtStartup()) {
    354    // On Android apz.keyboard.enabled is false by default and it's can't be
    355    // changed here since it's `mirror: once`, so we just skip this test.
    356    return;
    357  }
    358 
    359  // For instant scrolling, i.e. no async animation should not be involved.
    360  SCOPED_GFX_PREF_BOOL("general.smoothScroll", false);
    361 
    362  // Set up a keyboard shortcuts map to scroll page down.
    363  AutoTArray<KeyboardShortcut, 1> shortcuts{KeyboardShortcut(
    364      KeyboardInput::KEY_DOWN, 0, 0, 0, 0,
    365      KeyboardScrollAction(
    366          KeyboardScrollAction::KeyboardScrollActionType::eScrollPage, true))};
    367  KeyboardMap keyboardMap(std::move(shortcuts));
    368  manager->SetKeyboardMap(keyboardMap);
    369 
    370  // Set up a scrollable layer.
    371  CreateSimpleScrollingLayer();
    372  ScopedLayerTreeRegistration registration(LayersId{0}, mcc);
    373  UpdateHitTestingTree();
    374 
    375  // Setup the scrollable layer is scrollable by key events.
    376  FocusTarget focusTarget;
    377  focusTarget.mSequenceNumber = 1;
    378  focusTarget.mData = AsVariant<FocusTarget::ScrollTargets>(
    379      {ScrollableLayerGuid::START_SCROLL_ID,
    380       ScrollableLayerGuid::START_SCROLL_ID});
    381  manager->UpdateFocusState(LayersId{0}, LayersId{0}, focusTarget);
    382 
    383  // A vsync tick happens.
    384  mcc->AdvanceByMillis(16);
    385 
    386  // The first sampling happens, there's no change have happened, thus no need
    387  // to composite.
    388  EXPECT_FALSE(manager->AdvanceAnimations(mcc->GetSampleTime()));
    389 
    390  // A key event causing scroll page down happens.
    391  WidgetKeyboardEvent widgetEvent(true, eKeyDown, nullptr);
    392  KeyboardInput input(widgetEvent);
    393  (void)manager->ReceiveInputEvent(input);
    394 
    395  // Simulate WebRender compositing frames until APZ tells it the scroll offset
    396  // has stopped changing.
    397  // Important to trigger the bug: the first composite has the same time stamp
    398  // as the earlier one above.
    399  ParentLayerPoint compositedScrollOffset;
    400  while (true) {
    401    bool needMoreFrames = manager->AdvanceAnimations(mcc->GetSampleTime());
    402    compositedScrollOffset = ApzcOf(root)->GetCurrentAsyncScrollOffset(
    403        AsyncPanZoomController::eForCompositing);
    404    if (!needMoreFrames) {
    405      break;
    406    }
    407    mcc->AdvanceBy(TimeDuration::FromMilliseconds(16));
    408  }
    409 
    410  // Check that the effect of the keyboard scroll has been composited.
    411  EXPECT_GT(compositedScrollOffset.y, 0);
    412 }
    413 
    414 TEST_F(APZCTreeManagerGenericTesterMock,
    415       PanGestureWithCtrlModifier_Bug1917488) {
    416  // The outer layer represents the browser chrome, and has layers id 0.
    417  // The inner layer represents web content, and will initally get layers id 1.
    418  const char* treeShape = "x(x)";
    419  LayerIntRect layerVisibleRect[] = {
    420      LayerIntRect(0, 0, 100, 100),
    421      LayerIntRect(0, 0, 100, 100),
    422  };
    423  CreateScrollData(treeShape, layerVisibleRect);
    424 
    425  // We need one of these for every LayersId the test will use!
    426  ScopedLayerTreeRegistration registration0(LayersId{0}, mcc);
    427  ScopedLayerTreeRegistration registration1(LayersId{1}, mcc);
    428  ScopedLayerTreeRegistration registration2(LayersId{2}, mcc);
    429 
    430  // In this test, we only bother to give the inner layer an APZC.
    431  ScrollableLayerGuid::ViewID scrollId = ScrollableLayerGuid::START_SCROLL_ID;
    432  SetScrollableFrameMetrics(layers[1], scrollId, CSSRect(0, 0, 100, 100));
    433 
    434  // Set the referent id of the root layer to 1.
    435  // Note that this causes the *descendants* of the root layer
    436  // to get a layers id of 1 during the hit-testing tree update.
    437  LayersId tab1LayersId{1};
    438  ScrollableLayerGuid tab1Guid(tab1LayersId, 0, scrollId);
    439  root->SetReferentId(tab1LayersId);
    440  UpdateHitTestingTree();
    441 
    442  // Perform a pan gesture on the content layer.
    443  // For the START event, do not use the PanGesture() helper, because we want to
    444  // check the mLayersId that APZ sets on the input event object. This
    445  // determines what content process the event will gets dispatched to.
    446  ScreenIntPoint panPoint(50, 50);
    447  QueueMockHitResult(tab1Guid);
    448  PanGestureInput panStart(PanGestureInput::PANGESTURE_START, mcc->Time(),
    449                           panPoint, ScreenPoint(0, 10), MODIFIER_NONE);
    450  manager->ReceiveInputEvent(panStart);
    451  mcc->AdvanceByMillis(5);
    452  QueueMockHitResult(tab1Guid);
    453  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
    454             ScreenPoint(0, 10), mcc->Time());
    455  mcc->AdvanceByMillis(5);
    456  QueueMockHitResult(tab1Guid);
    457  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
    458             ScreenPoint(0, 0), mcc->Time());
    459 
    460  // The layers id assigned to the events of this gesture should be 1.
    461  EXPECT_EQ(panStart.mLayersId, tab1LayersId);
    462 
    463  // Simulate a tab switch by updating the referent id of the root layer
    464  // to a new layers id, 2.
    465  LayersId tab2LayersId{2};
    466  ScrollableLayerGuid tab2Guid(tab2LayersId, 0, scrollId);
    467  root->SetReferentId(tab2LayersId);
    468  UpdateHitTestingTree();
    469 
    470  // Perform another pan gesture on the content layer, but this time with
    471  // the Control modifier held down.
    472  QueueMockHitResult(tab2Guid);
    473  PanGestureInput zoomStart(PanGestureInput::PANGESTURE_START, mcc->Time(),
    474                            panPoint, ScreenPoint(0, 10), MODIFIER_CONTROL);
    475  manager->ReceiveInputEvent(zoomStart);
    476  mcc->AdvanceByMillis(5);
    477  QueueMockHitResult(tab2Guid);
    478  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
    479             ScreenPoint(0, 10), mcc->Time(), MODIFIER_CONTROL);
    480  mcc->AdvanceByMillis(5);
    481  QueueMockHitResult(tab2Guid);
    482  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
    483             ScreenPoint(0, 0), mcc->Time(), MODIFIER_CONTROL);
    484 
    485  // The layers id assigned to the events in the zoom gesture should be 2.
    486  // (In the buggy scenario, it's 1, meaning the events get incorrectly
    487  // sent to the previous tab's content process.)
    488  EXPECT_EQ(zoomStart.mLayersId, tab2LayersId);
    489 }