Bug 1477335 - Replace reference type mFrameMetrics with two getter functions, |Metrics()| and |Metrics() Const| which both return mScrollMetadata.mMetrics. Fixes const correctness loophole. r=Botond draft
authorBotond Ballo <botond@mozilla.com>
Fri, 27 Jul 2018 14:58:46 -0400
changeset 823657 9ce19c0ca399
parent 819019 f6df6a982ee9
push id117753
push userbballo@mozilla.com
push dateFri, 27 Jul 2018 18:59:57 +0000
reviewersBotond
bugs1477335
milestone63.0a1
Bug 1477335 - Replace reference type mFrameMetrics with two getter functions, |Metrics()| and |Metrics() Const| which both return mScrollMetadata.mMetrics. Fixes const correctness loophole. r=Botond MozReview-Commit-ID: I8yM74OAr8m
gfx/layers/FrameMetrics.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/apz/src/Axis.h
gfx/layers/apz/test/gtest/APZTestCommon.h
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -508,17 +508,17 @@ public:
 
   // If the frame is in vertical-RTL writing mode(E.g. "writing-mode:
   // vertical-rl" in CSS), or if it's in horizontal-RTL writing-mode(E.g.
   // "writing-mode: horizontal-tb; direction: rtl;" in CSS), then this function
   // returns true. From the representation perspective, frames whose horizontal
   // contents start at rightside also cause their horizontal scrollbars, if any,
   // initially start at rightside. So we can also learn about the initial side
   // of the horizontal scrollbar for the frame by calling this function.
-  bool IsHorizontalContentRightToLeft() {
+  bool IsHorizontalContentRightToLeft() const {
     return mScrollableRect.x < 0;
   }
 
   void SetPaintRequestTime(const TimeStamp& aTime) {
     mPaintRequestTime = aTime;
   }
   const TimeStamp& GetPaintRequestTime() const {
     return mPaintRequestTime;
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -816,26 +816,25 @@ AsyncPanZoomController::AsyncPanZoomCont
                                                const RefPtr<InputQueue>& aInputQueue,
                                                GeckoContentController* aGeckoContentController,
                                                GestureBehavior aGestures)
   :  mLayersId(aLayersId),
      mGeckoContentController(aGeckoContentController),
      mRefPtrMonitor("RefPtrMonitor"),
      // mTreeManager must be initialized before GetFrameTime() is called
      mTreeManager(aTreeManager),
-     mFrameMetrics(mScrollMetadata.GetMetrics()),
      mRecursiveMutex("AsyncPanZoomController"),
      mLastContentPaintMetrics(mLastContentPaintMetadata.GetMetrics()),
      mX(this),
      mY(this),
      mPanDirRestricted(false),
      mPinchLocked(false),
      mZoomConstraints(false, false,
-        mFrameMetrics.GetDevPixelsPerCSSPixel() * kViewportMinScale / ParentLayerToScreenScale(1),
-        mFrameMetrics.GetDevPixelsPerCSSPixel() * kViewportMaxScale / ParentLayerToScreenScale(1)),
+        Metrics().GetDevPixelsPerCSSPixel() * kViewportMinScale / ParentLayerToScreenScale(1),
+        Metrics().GetDevPixelsPerCSSPixel() * kViewportMaxScale / ParentLayerToScreenScale(1)),
      mLastSampleTime(GetFrameTime()),
      mLastCheckerboardReport(GetFrameTime()),
      mOverscrollEffect(MakeUnique<OverscrollEffect>(*this)),
      mState(NOTHING),
      mNotificationBlockers(0),
      mInputQueue(aInputQueue),
      mPinchPaintTimerSet(false),
      mAPZCId(sAsyncPanZoomControllerCount++),
@@ -894,17 +893,17 @@ AsyncPanZoomController::Destroy()
     mGeckoContentController = nullptr;
     mGestureEventListener = nullptr;
   }
   mParent = nullptr;
   mTreeManager = nullptr;
 
   // Only send the release message if the SharedFrameMetrics has been created.
   if (mMetricsSharingController && mSharedFrameMetricsBuffer) {
-    Unused << mMetricsSharingController->StopSharingMetrics(mFrameMetrics.GetScrollId(), mAPZCId);
+    Unused << mMetricsSharingController->StopSharingMetrics(Metrics().GetScrollId(), mAPZCId);
   }
 
   { // scope the lock
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     mSharedFrameMetricsBuffer = nullptr;
     delete mSharedLock;
     mSharedLock = nullptr;
   }
@@ -1058,26 +1057,26 @@ nsEventStatus AsyncPanZoomController::Ha
 
   CSSCoord maxThumbPos = scrollbarData.mScrollTrackLength;
   maxThumbPos -= scrollbarData.mThumbLength;
 
   float scrollPercent = thumbPosition / maxThumbPos;
   APZC_LOG("%p scrollbar dragged to %f percent\n", this, scrollPercent);
 
   CSSCoord minScrollPosition =
-    GetAxisStart(direction, mFrameMetrics.GetScrollableRect().TopLeft());
+    GetAxisStart(direction, Metrics().GetScrollableRect().TopLeft());
   CSSCoord maxScrollPosition =
-    GetAxisStart(direction, mFrameMetrics.GetScrollableRect().BottomRight()) -
-    GetAxisLength(direction, mFrameMetrics.CalculateCompositionBoundsInCssPixelsOfSurroundingContent());
+    GetAxisStart(direction, Metrics().GetScrollableRect().BottomRight()) -
+    GetAxisLength(direction, Metrics().CalculateCompositionBoundsInCssPixelsOfSurroundingContent());
   CSSCoord scrollPosition = minScrollPosition + (scrollPercent * (maxScrollPosition - minScrollPosition));
 
   scrollPosition = std::max(scrollPosition, minScrollPosition);
   scrollPosition = std::min(scrollPosition, maxScrollPosition);
 
-  CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
+  CSSPoint scrollOffset = Metrics().GetScrollOffset();
   if (direction == ScrollDirection::eHorizontal) {
     scrollOffset.x = scrollPosition;
   } else {
     scrollOffset.y = scrollPosition;
   }
   APZC_LOG("%p set scroll offset to %s from scrollbar drag\n", this, Stringify(scrollOffset).c_str());
   SetScrollOffset(scrollOffset);
   ScheduleCompositeAndMaybeRepaint();
@@ -1458,17 +1457,17 @@ nsEventStatus AsyncPanZoomController::On
     if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
       controller->NotifyPinchGesture(aEvent.mType, GetGuid(), 0, aEvent.modifiers);
     }
   }
 
   SetState(PINCHING);
   mX.SetVelocity(0);
   mY.SetVelocity(0);
-  mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.GetCompositionBounds().TopLeft();
+  mLastZoomFocus = aEvent.mLocalFocusPoint - Metrics().GetCompositionBounds().TopLeft();
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
   APZC_LOG("%p got a scale in state %d\n", this, mState);
 
   if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
@@ -1479,17 +1478,17 @@ nsEventStatus AsyncPanZoomController::On
     return nsEventStatus_eConsumeNoDefault;
   }
 
   ParentLayerCoord spanDistance = fabsf(aEvent.mPreviousSpan - aEvent.mCurrentSpan);
   ParentLayerPoint focusPoint, focusChange;
   {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
 
-    focusPoint = aEvent.mLocalFocusPoint - mFrameMetrics.GetCompositionBounds().TopLeft();
+    focusPoint = aEvent.mLocalFocusPoint - Metrics().GetCompositionBounds().TopLeft();
     focusChange = mLastZoomFocus - focusPoint;
     mLastZoomFocus = focusPoint;
   }
 
   HandlePinchLocking(
     ToScreenCoordinates(ParentLayerPoint(0, spanDistance), focusPoint).Length(),
     ToScreenCoordinates(focusChange, focusPoint));
   bool allowZoom = mZoomConstraints.mAllowZoom && !mPinchLocked;
@@ -1512,24 +1511,24 @@ nsEventStatus AsyncPanZoomController::On
     }
   }
 
   // Only the root APZC is zoomable, and the root APZC is not allowed to have
   // different x and y scales. If it did, the calculations in this function
   // would have to be adjusted (as e.g. it would no longer be valid to take
   // the minimum or maximum of the ratios of the widths and heights of the
   // page rect and the composition bounds).
-  MOZ_ASSERT(mFrameMetrics.IsRootContent());
-  MOZ_ASSERT(mFrameMetrics.GetZoom().AreScalesSame());
+  MOZ_ASSERT(Metrics().IsRootContent());
+  MOZ_ASSERT(Metrics().GetZoom().AreScalesSame());
 
   {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
 
-    CSSToParentLayerScale userZoom = mFrameMetrics.GetZoom().ToScaleFactor();
-    CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoom();
+    CSSToParentLayerScale userZoom = Metrics().GetZoom().ToScaleFactor();
+    CSSPoint cssFocusPoint = focusPoint / Metrics().GetZoom();
 
     // If displacing by the change in focus point will take us off page bounds,
     // then reduce the displacement such that it doesn't.
     focusChange.x -= mX.DisplacementWillOverscrollAmount(focusChange.x);
     focusChange.y -= mY.DisplacementWillOverscrollAmount(focusChange.y);
     ScrollBy(focusChange / userZoom);
 
     // If the span is zero or close to it, we don't want to process this zoom
@@ -1551,19 +1550,19 @@ nsEventStatus AsyncPanZoomController::On
     // When we zoom in with focus, we can zoom too much towards the boundaries
     // that we actually go over them. These are the needed displacements along
     // either axis such that we don't overscroll the boundaries when zooming.
     CSSPoint neededDisplacement;
 
     CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom;
     CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom;
     realMinZoom.scale = std::max(realMinZoom.scale,
-                                 mFrameMetrics.GetCompositionBounds().Width() / mFrameMetrics.GetScrollableRect().Width());
+                                 Metrics().GetCompositionBounds().Width() / Metrics().GetScrollableRect().Width());
     realMinZoom.scale = std::max(realMinZoom.scale,
-                                 mFrameMetrics.GetCompositionBounds().Height() / mFrameMetrics.GetScrollableRect().Height());
+                                 Metrics().GetCompositionBounds().Height() / Metrics().GetScrollableRect().Height());
     if (realMaxZoom < realMinZoom) {
       realMaxZoom = realMinZoom;
     }
 
     bool doScale = allowZoom && (
                    (spanRatio > 1.0 && userZoom < realMaxZoom) ||
                    (spanRatio < 1.0 && userZoom > realMinZoom));
 
@@ -1758,23 +1757,23 @@ AsyncPanZoomController::ConvertToGecko(c
 
 CSSCoord
 AsyncPanZoomController::ConvertScrollbarPoint(const ParentLayerPoint& aScrollbarPoint,
                                               const ScrollbarData& aThumbData) const
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   // First, get it into the right coordinate space.
-  CSSPoint scrollbarPoint = aScrollbarPoint / mFrameMetrics.GetZoom();
+  CSSPoint scrollbarPoint = aScrollbarPoint / Metrics().GetZoom();
   // The scrollbar can be transformed with the frame but the pres shell
   // resolution is only applied to the scroll frame.
-  scrollbarPoint = scrollbarPoint * mFrameMetrics.GetPresShellResolution();
+  scrollbarPoint = scrollbarPoint * Metrics().GetPresShellResolution();
 
   // Now, get it to be relative to the beginning of the scroll track.
-  CSSRect cssCompositionBound = mFrameMetrics.CalculateCompositionBoundsInCssPixelsOfSurroundingContent();
+  CSSRect cssCompositionBound = Metrics().CalculateCompositionBoundsInCssPixelsOfSurroundingContent();
   return GetAxisStart(*aThumbData.mDirection, scrollbarPoint)
       - GetAxisStart(*aThumbData.mDirection, cssCompositionBound)
       - aThumbData.mScrollTrackStart;
 }
 
 static bool
 AllowsScrollingMoreThanOnePage(double aMultiplier)
 {
@@ -1803,19 +1802,19 @@ AsyncPanZoomController::GetScrollWheelDe
   ParentLayerSize pageScrollSize;
 
   {
     // Grab the lock to access the frame metrics.
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     LayoutDeviceIntSize scrollAmountLD = mScrollMetadata.GetLineScrollAmount();
     LayoutDeviceIntSize pageScrollSizeLD = mScrollMetadata.GetPageScrollAmount();
     scrollAmount = scrollAmountLD /
-      mFrameMetrics.GetDevPixelsPerCSSPixel() * mFrameMetrics.GetZoom();
+      Metrics().GetDevPixelsPerCSSPixel() * Metrics().GetZoom();
     pageScrollSize = pageScrollSizeLD /
-      mFrameMetrics.GetDevPixelsPerCSSPixel() * mFrameMetrics.GetZoom();
+      Metrics().GetDevPixelsPerCSSPixel() * Metrics().GetZoom();
   }
 
   ParentLayerPoint delta;
   switch (aEvent.mDeltaType) {
     case ScrollWheelInput::SCROLLDELTA_LINE: {
       delta.x = aDeltaX * scrollAmount.width;
       delta.y = aDeltaY * scrollAmount.height;
       break;
@@ -1892,18 +1891,18 @@ AsyncPanZoomController::OnKeyboard(const
   bool scrollSnapped = MaybeAdjustDestinationForScrollSnapping(aEvent, destination);
 
   // If smooth scrolling is disabled, then scroll immediately to the destination
   if (!gfxPrefs::SmoothScrollEnabled()) {
     CancelAnimation();
 
     // CallDispatchScroll interprets the start and end points as the start and
     // end of a touch scroll so they need to be reversed.
-    ParentLayerPoint startPoint = destination * mFrameMetrics.GetZoom();
-    ParentLayerPoint endPoint = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
+    ParentLayerPoint startPoint = destination * Metrics().GetZoom();
+    ParentLayerPoint endPoint = Metrics().GetScrollOffset() * Metrics().GetZoom();
     ParentLayerPoint delta = endPoint - startPoint;
 
     ScreenPoint distance = ToScreenCoordinates(
         ParentLayerPoint(fabs(delta.x), fabs(delta.y)), startPoint);
 
     OverscrollHandoffState handoffState(
         *mInputQueue->GetCurrentKeyboardBlock()->GetOverscrollHandoffChain(),
         distance,
@@ -1930,26 +1929,26 @@ AsyncPanZoomController::OnKeyboard(const
     return nsEventStatus_eConsumeDoDefault;
   }
 
   // Use a keyboard scroll animation to scroll, reusing an existing one if it exists
   if (mState != KEYBOARD_SCROLL) {
     CancelAnimation();
     SetState(KEYBOARD_SCROLL);
 
-    nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
+    nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
     StartAnimation(new KeyboardScrollAnimation(*this, initialPosition, aEvent.mAction.mType));
   }
 
   // Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and then
   // to appunits/second.
   nsPoint velocity =
     CSSPoint::ToAppUnits(
       ParentLayerPoint(mX.GetVelocity() * 1000.0f, mY.GetVelocity() * 1000.0f) /
-      mFrameMetrics.GetZoom());
+      Metrics().GetZoom());
 
   KeyboardScrollAnimation* animation = mAnimation->AsKeyboardScrollAnimation();
   MOZ_ASSERT(animation);
 
   animation->UpdateDestination(aEvent.mTimeStamp,
                                CSSPixel::ToAppUnits(destination),
                                nsSize(velocity.x, velocity.y));
 
@@ -1964,31 +1963,31 @@ AsyncPanZoomController::GetKeyboardDesti
   CSSPoint scrollOffset;
   CSSRect scrollRect;
 
   {
     // Grab the lock to access the frame metrics.
     RecursiveMutexAutoLock lock(mRecursiveMutex);
 
     lineScrollSize = mScrollMetadata.GetLineScrollAmount() /
-      mFrameMetrics.GetDevPixelsPerCSSPixel();
+      Metrics().GetDevPixelsPerCSSPixel();
     pageScrollSize = mScrollMetadata.GetPageScrollAmount() /
-      mFrameMetrics.GetDevPixelsPerCSSPixel();
+      Metrics().GetDevPixelsPerCSSPixel();
 
     if (mState == WHEEL_SCROLL) {
       scrollOffset = mAnimation->AsWheelScrollAnimation()->GetDestination();
     } else if (mState == SMOOTH_SCROLL) {
       scrollOffset = mAnimation->AsSmoothScrollAnimation()->GetDestination();
     } else if (mState == KEYBOARD_SCROLL) {
       scrollOffset = mAnimation->AsKeyboardScrollAnimation()->GetDestination();
     } else {
-      scrollOffset = mFrameMetrics.GetScrollOffset();
+      scrollOffset = Metrics().GetScrollOffset();
     }
 
-    scrollRect = mFrameMetrics.GetScrollableRect();
+    scrollRect = Metrics().GetScrollableRect();
   }
 
   // Calculate the scroll destination based off of the scroll type and direction
   CSSPoint scrollDestination = scrollOffset;
 
   switch (aAction.mType) {
     case KeyboardScrollAction::eScrollCharacter: {
       int32_t scrollDistance = gfxPrefs::ToolkitHorizontalScrollDistance();
@@ -2135,17 +2134,17 @@ AsyncPanZoomController::CanScroll(Scroll
 bool
 AsyncPanZoomController::IsContentOfHonouredTargetRightToLeft(
                           bool aHonoursRoot) const
 {
   if (aHonoursRoot) {
     return mScrollMetadata.IsAutoDirRootContentRTL();
   }
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  return mFrameMetrics.IsHorizontalContentRightToLeft();
+  return Metrics().IsHorizontalContentRightToLeft();
 }
 
 bool
 AsyncPanZoomController::AllowScrollHandoffInCurrentBlock() const
 {
   bool result = mInputQueue->AllowScrollHandoff();
   if (!gfxPrefs::APZAllowImmediateHandoff()) {
     if (InputBlockState* currentBlock = GetCurrentInputBlock()) {
@@ -2232,17 +2231,17 @@ nsEventStatus AsyncPanZoomController::On
     APZC_LOG("%p got a scroll-wheel with adjusted auto-dir delta values\n",
              this);
   } else if ((delta.x || delta.y) && !CanScrollWithWheel(delta)) {
     // We can't scroll this apz anymore, so we simply drop the event.
     if (mInputQueue->GetActiveWheelTransaction() &&
         gfxPrefs::MouseScrollTestingEnabled()) {
       if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
         controller->NotifyMozMouseScrollEvent(
-          mFrameMetrics.GetScrollId(),
+          Metrics().GetScrollId(),
           NS_LITERAL_STRING("MozMouseScrollFailed"));
       }
     }
     return nsEventStatus_eConsumeNoDefault;
   }
 
   MOZ_ASSERT(mInputQueue->GetCurrentWheelBlock());
   AdjustDeltaForAllowedScrollDirections(delta,
@@ -2254,17 +2253,17 @@ nsEventStatus AsyncPanZoomController::On
   }
 
   switch (aEvent.mScrollMode) {
     case ScrollWheelInput::SCROLLMODE_INSTANT: {
 
       // Wheel events from "clicky" mouse wheels trigger scroll snapping to the
       // next snap point. Check for this, and adjust the delta to take into
       // account the snap point.
-      CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
+      CSSPoint startPosition = Metrics().GetScrollOffset();
       MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition);
 
       ScreenPoint distance = ToScreenCoordinates(
         ParentLayerPoint(fabs(delta.x), fabs(delta.y)), aEvent.mLocalOrigin);
 
       CancelAnimation();
 
       OverscrollHandoffState handoffState(
@@ -2287,17 +2286,17 @@ nsEventStatus AsyncPanZoomController::On
 
     case ScrollWheelInput::SCROLLMODE_SMOOTH: {
       // The lock must be held across the entire update operation, so the
       // compositor doesn't end the animation before we get a chance to
       // update it.
       RecursiveMutexAutoLock lock(mRecursiveMutex);
 
       // Perform scroll snapping if appropriate.
-      CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
+      CSSPoint startPosition = Metrics().GetScrollOffset();
       // If we're already in a wheel scroll or smooth scroll animation,
       // the delta is applied to its destination, not to the current
       // scroll position. Take this into account when finding a snap point.
       if (mState == WHEEL_SCROLL) {
         startPosition = mAnimation->AsWheelScrollAnimation()->GetDestination();
       } else if (mState == SMOOTH_SCROLL) {
         startPosition = mAnimation->AsSmoothScrollAnimation()->GetDestination();
       } else if (mState == KEYBOARD_SCROLL) {
@@ -2312,31 +2311,31 @@ nsEventStatus AsyncPanZoomController::On
         break;
       }
 
       // Otherwise, use a wheel scroll animation, also reusing one if possible.
       if (mState != WHEEL_SCROLL) {
         CancelAnimation();
         SetState(WHEEL_SCROLL);
 
-        nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
+        nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
         StartAnimation(new WheelScrollAnimation(
           *this, initialPosition, aEvent.mDeltaType));
       }
 
       nsPoint deltaInAppUnits =
-        CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
+        CSSPoint::ToAppUnits(delta / Metrics().GetZoom());
 
       // Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and
       // then to appunits/second.
       nsPoint velocity =
         CSSPoint::ToAppUnits(
           ParentLayerPoint(mX.GetVelocity() * 1000.0f,
                            mY.GetVelocity() * 1000.0f) /
-          mFrameMetrics.GetZoom());
+          Metrics().GetZoom());
 
       WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
       animation->UpdateDelta(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
       break;
     }
   }
 
   return nsEventStatus_eConsumeNoDefault;
@@ -2345,17 +2344,17 @@ nsEventStatus AsyncPanZoomController::On
 void
 AsyncPanZoomController::NotifyMozMouseScrollEvent(const nsString& aString) const
 {
   RefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (!controller) {
     return;
   }
 
-  controller->NotifyMozMouseScrollEvent(mFrameMetrics.GetScrollId(), aString);
+  controller->NotifyMozMouseScrollEvent(Metrics().GetScrollId(), aString);
 }
 
 nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
   APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);
 
   mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime);
   mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime);
   MOZ_ASSERT(GetCurrentPanGestureBlock());
@@ -2930,17 +2929,17 @@ bool AsyncPanZoomController::AttemptScro
     bool xChanged = mX.AdjustDisplacement(displacement.x, adjustedDisplacement.x,
                                           overscroll.x,
                                           forcesHorizontalOverscroll);
     if (xChanged || yChanged) {
       ScheduleComposite();
     }
 
     if (!IsZero(adjustedDisplacement)) {
-      ScrollBy(adjustedDisplacement / mFrameMetrics.GetZoom());
+      ScrollBy(adjustedDisplacement / Metrics().GetZoom());
       if (InputBlockState* block = GetCurrentInputBlock()) {
 #if defined(MOZ_WIDGET_ANDROID)
         if (block->AsTouchBlock() && (block->GetScrolledApzc() != this) && IsRootContent()) {
           if (APZCTreeManager* manager = GetApzcTreeManager()) {
             AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
             MOZ_ASSERT(animator);
             animator->SetScrollingRootContent();
           }
@@ -3150,24 +3149,24 @@ void AsyncPanZoomController::SmoothScrol
   if (mState == SMOOTH_SCROLL && mAnimation) {
     APZC_LOG("%p updating destination on existing animation\n", this);
     RefPtr<SmoothScrollAnimation> animation(
       static_cast<SmoothScrollAnimation*>(mAnimation.get()));
     animation->SetDestination(CSSPoint::ToAppUnits(aDestination));
   } else {
     CancelAnimation();
     SetState(SMOOTH_SCROLL);
-    nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
+    nsPoint initialPosition = CSSPoint::ToAppUnits(Metrics().GetScrollOffset());
     // Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s and
     // then to appunits/second.
     nsPoint initialVelocity =
       CSSPoint::ToAppUnits(
         ParentLayerPoint(mX.GetVelocity() * 1000.0f,
                           mY.GetVelocity() * 1000.0f) /
-        mFrameMetrics.GetZoom());
+        Metrics().GetZoom());
 
     nsPoint destination = CSSPoint::ToAppUnits(aDestination);
 
     StartAnimation(new SmoothScrollAnimation(*this,
                                              initialPosition, initialVelocity,
                                              destination,
                                              gfxPrefs::ScrollBehaviorSpringConstant(),
                                              gfxPrefs::ScrollBehaviorDampingRatio()));
@@ -3304,62 +3303,62 @@ void AsyncPanZoomController::SetMetricsS
   mMetricsSharingController = aMetricsSharingController;
 }
 
 void AsyncPanZoomController::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
   CSSPoint adjustment =
     ViewAs<ParentLayerPixel>(aShift, PixelCastJustification::ScreenIsParentLayerForRoot)
-    / mFrameMetrics.GetZoom();
+    / Metrics().GetZoom();
   APZC_LOG("%p adjusting scroll position by %s for surface shift\n",
     this, Stringify(adjustment).c_str());
-  CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
-  // Apply shift to mFrameMetrics.mScrollOffset.
+  CSSRect scrollRange = Metrics().CalculateScrollRange();
+  // Apply shift to Metrics().mScrollOffset.
   SetScrollOffset(scrollRange.ClampPoint(
-      mFrameMetrics.GetScrollOffset() + adjustment));
+      Metrics().GetScrollOffset() + adjustment));
   // Apply shift to mCompositedScrollOffset, since the dynamic toolbar expects
   // the shift to take effect right away, without the usual frame delay.
   mCompositedScrollOffset = scrollRange.ClampPoint(
       mCompositedScrollOffset + adjustment);
   RequestContentRepaint();
   UpdateSharedCompositorFrameMetrics();
 }
 
 void AsyncPanZoomController::SetScrollOffset(const CSSPoint& aOffset) {
-  mFrameMetrics.SetScrollOffset(aOffset);
-  mFrameMetrics.RecalculateViewportOffset();
+  Metrics().SetScrollOffset(aOffset);
+  Metrics().RecalculateViewportOffset();
 }
 
 void AsyncPanZoomController::ClampAndSetScrollOffset(const CSSPoint& aOffset) {
-  mFrameMetrics.ClampAndSetScrollOffset(aOffset);
-  mFrameMetrics.RecalculateViewportOffset();
+  Metrics().ClampAndSetScrollOffset(aOffset);
+  Metrics().RecalculateViewportOffset();
 }
 
 void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) {
-  SetScrollOffset(mFrameMetrics.GetScrollOffset() + aOffset);
+  SetScrollOffset(Metrics().GetScrollOffset() + aOffset);
 }
 
 void AsyncPanZoomController::ScrollByAndClamp(const CSSPoint& aOffset) {
-  ClampAndSetScrollOffset(mFrameMetrics.GetScrollOffset() + aOffset);
+  ClampAndSetScrollOffset(Metrics().GetScrollOffset() + aOffset);
 }
 
 void AsyncPanZoomController::CopyScrollInfoFrom(const FrameMetrics& aFrameMetrics) {
-  mFrameMetrics.CopyScrollInfoFrom(aFrameMetrics);
-  mFrameMetrics.RecalculateViewportOffset();
+  Metrics().CopyScrollInfoFrom(aFrameMetrics);
+  Metrics().RecalculateViewportOffset();
 }
 
 void AsyncPanZoomController::ScaleWithFocus(float aScale,
                                             const CSSPoint& aFocus) {
-  mFrameMetrics.ZoomBy(aScale);
+  Metrics().ZoomBy(aScale);
   // We want to adjust the scroll offset such that the CSS point represented by aFocus remains
   // at the same position on the screen before and after the change in zoom. The below code
   // accomplishes this; see https://bugzilla.mozilla.org/show_bug.cgi?id=923431#c6 for an
   // in-depth explanation of how.
-  SetScrollOffset((mFrameMetrics.GetScrollOffset() + aFocus) - (aFocus / aScale));
+  SetScrollOffset((Metrics().GetScrollOffset() + aFocus) - (aFocus / aScale));
 }
 
 /**
  * Enlarges the displayport along both axes based on the velocity.
  */
 static CSSSize
 CalculateDisplayPortSize(const CSSSize& aCompositionSize,
                          const CSSPoint& aVelocity)
@@ -3544,29 +3543,29 @@ bool AsyncPanZoomController::IsFlingingF
 
 bool AsyncPanZoomController::IsPannable() const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
   return mX.CanScroll() || mY.CanScroll();
 }
 
 bool AsyncPanZoomController::IsScrollInfoLayer() const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  return mFrameMetrics.IsScrollInfoLayer();
+  return Metrics().IsScrollInfoLayer();
 }
 
 int32_t AsyncPanZoomController::GetLastTouchIdentifier() const {
   RefPtr<GestureEventListener> listener = GetGestureEventListener();
   return listener ? listener->GetLastTouchIdentifier() : -1;
 }
 
 void AsyncPanZoomController::RequestContentRepaint(bool aUserAction) {
   // Reinvoke this method on the repaint thread if it's not there already. It's
   // important to do this before the call to CalculatePendingDisplayPort, so
   // that CalculatePendingDisplayPort uses the most recent available version of
-  // mFrameMetrics, just before the paint request is dispatched to content.
+  // Metrics(). just before the paint request is dispatched to content.
   RefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (!controller) {
     return;
   }
   if (!controller->IsRepaintThread()) {
     // use the local variable to resolve the function overload.
     auto func = static_cast<void (AsyncPanZoomController::*)(bool)>
         (&AsyncPanZoomController::RequestContentRepaint);
@@ -3577,21 +3576,21 @@ void AsyncPanZoomController::RequestCont
       aUserAction));
     return;
   }
 
   MOZ_ASSERT(controller->IsRepaintThread());
 
   RecursiveMutexAutoLock lock(mRecursiveMutex);
   ParentLayerPoint velocity = GetVelocityVector();
-  mFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(mFrameMetrics, velocity));
-  mFrameMetrics.SetUseDisplayPortMargins(true);
-  mFrameMetrics.SetPaintRequestTime(TimeStamp::Now());
-  mFrameMetrics.SetRepaintDrivenByUserAction(aUserAction);
-  RequestContentRepaint(mFrameMetrics, velocity);
+  Metrics().SetDisplayPortMargins(CalculatePendingDisplayPort(Metrics(), velocity));
+  Metrics().SetUseDisplayPortMargins(true);
+  Metrics().SetPaintRequestTime(TimeStamp::Now());
+  Metrics().SetRepaintDrivenByUserAction(aUserAction);
+  RequestContentRepaint(Metrics(), velocity);
 }
 
 /*static*/ CSSRect
 GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
 {
   // This computation is based on what happens in CalculatePendingDisplayPort. If that
   // changes then this might need to change too
   CSSRect baseRect(aFrameMetrics.GetScrollOffset(),
@@ -3678,17 +3677,17 @@ bool AsyncPanZoomController::UpdateAnima
   // call this after the |mLastSampleTime == aSampleTime| check, to ensure
   // it's only called once per APZC on each composite.
   bool needComposite = SampleCompositedAsyncTransform();
 
   TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
   mLastSampleTime = aSampleTime;
 
   if (mAnimation) {
-    bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
+    bool continueAnimation = mAnimation->Sample(Metrics(), sampleTimeDelta);
     bool wantsRepaints = mAnimation->WantsRepaints();
     *aOutDeferredTasks = mAnimation->TakeDeferredTasks();
     if (!continueAnimation) {
       mAnimation = nullptr;
       SetState(NOTHING);
     }
     // Request a repaint at the end of the animation in case something such as a
     // call to NotifyLayersUpdated was invoked during the animation and Gecko's
@@ -3744,18 +3743,18 @@ bool AsyncPanZoomController::AdvanceAnim
 
     requestAnimationFrame = UpdateAnimation(aSampleTime, &deferredTasks);
 
     { // scope lock
       MutexAutoLock lock(mCheckerboardEventLock);
       if (mCheckerboardEvent) {
         mCheckerboardEvent->UpdateRendertraceProperty(
             CheckerboardEvent::UserVisible,
-            CSSRect(mFrameMetrics.GetScrollOffset(),
-                    mFrameMetrics.CalculateCompositedSizeInCssPixels()));
+            CSSRect(Metrics().GetScrollOffset(),
+                    Metrics().CalculateCompositedSizeInCssPixels()));
       }
     }
   }
 
   // Execute any deferred tasks queued up by mAnimation's Sample() (called by
   // UpdateAnimation()). This needs to be done after the monitor is released
   // since the tasks are allowed to call APZCTreeManager methods which can grab
   // the tree lock.
@@ -3766,17 +3765,17 @@ bool AsyncPanZoomController::AdvanceAnim
   // If any of the deferred tasks starts a new animation, it will request a
   // new composite directly, so we can just return requestAnimationFrame here.
   return requestAnimationFrame;
 }
 
 CSSRect
 AsyncPanZoomController::GetCurrentAsyncLayoutViewport(AsyncTransformConsumer aMode) const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  MOZ_ASSERT(mFrameMetrics.IsRootContent(),
+  MOZ_ASSERT(Metrics().IsRootContent(),
       "Only the root content APZC has a layout viewport");
   if (aMode == eForCompositing && mScrollMetadata.IsApzForceDisabled()) {
     return mLastContentPaintMetrics.GetViewport();
   }
   return GetEffectiveLayoutViewport(aMode);
 }
 
 ParentLayerPoint
@@ -3839,58 +3838,58 @@ AsyncPanZoomController::GetCurrentAsyncT
   }
 
   CSSToParentLayerScale2D effectiveZoom = GetEffectiveZoom(aMode);
 
   ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset)
                                * effectiveZoom * mTestAsyncZoom.scale;
 
   LayerToParentLayerScale compositedAsyncZoom =
-      (effectiveZoom / mFrameMetrics.LayersPixelsPerCSSPixel()).ToScaleFactor();
+      (effectiveZoom / Metrics().LayersPixelsPerCSSPixel()).ToScaleFactor();
   return AsyncTransform(
     LayerToParentLayerScale(compositedAsyncZoom.scale * mTestAsyncZoom.scale),
     -translation);
 }
 
 CSSRect
 AsyncPanZoomController::GetEffectiveLayoutViewport(AsyncTransformConsumer aMode) const
 {
   if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
     return mCompositedLayoutViewport;
   }
-  return mFrameMetrics.GetViewport();
+  return Metrics().GetViewport();
 }
 
 CSSPoint
 AsyncPanZoomController::GetEffectiveScrollOffset(AsyncTransformConsumer aMode) const
 {
   if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
     return mCompositedScrollOffset;
   }
-  return mFrameMetrics.GetScrollOffset();
+  return Metrics().GetScrollOffset();
 }
 
 CSSToParentLayerScale2D
 AsyncPanZoomController::GetEffectiveZoom(AsyncTransformConsumer aMode) const
 {
   if (gfxPrefs::APZFrameDelayEnabled() && aMode == eForCompositing) {
     return mCompositedZoom;
   }
-  return mFrameMetrics.GetZoom();
+  return Metrics().GetZoom();
 }
 
 bool
 AsyncPanZoomController::SampleCompositedAsyncTransform()
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  if (mCompositedScrollOffset != mFrameMetrics.GetScrollOffset() ||
-      mCompositedZoom != mFrameMetrics.GetZoom()) {
-    mCompositedLayoutViewport = mFrameMetrics.GetViewport();
-    mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
-    mCompositedZoom = mFrameMetrics.GetZoom();
+  if (mCompositedScrollOffset != Metrics().GetScrollOffset() ||
+      mCompositedZoom != Metrics().GetZoom()) {
+    mCompositedLayoutViewport = Metrics().GetViewport();
+    mCompositedScrollOffset = Metrics().GetScrollOffset();
+    mCompositedZoom = Metrics().GetZoom();
     return true;
   }
   return false;
 }
 
 AsyncTransformComponentMatrix
 AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll(AsyncTransformConsumer aMode) const
 {
@@ -3919,19 +3918,19 @@ Matrix4x4 AsyncPanZoomController::GetTra
            PostScale(zoomChange.width, zoomChange.height, 1);
 }
 
 uint32_t
 AsyncPanZoomController::GetCheckerboardMagnitude() const
 {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
-  CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
+  CSSPoint currentScrollOffset = Metrics().GetScrollOffset() + mTestAsyncScrollOffset;
   CSSRect painted = mLastContentPaintMetrics.GetDisplayPort() + mLastContentPaintMetrics.GetScrollOffset();
-  CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
+  CSSRect visible = CSSRect(currentScrollOffset, Metrics().CalculateCompositedSizeInCssPixels());
 
   CSSIntRegion checkerboard;
   // Round so as to minimize checkerboarding; if we're only showing fractional
   // pixels of checkerboarding it's not really worth counting
   checkerboard.Sub(RoundedIn(visible), RoundedOut(painted));
   return checkerboard.Area();
 }
 
@@ -3999,24 +3998,24 @@ AsyncPanZoomController::FlushActiveCheck
 
 bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   if (!gfxPrefs::APZAllowCheckerboarding() || mScrollMetadata.IsApzForceDisabled()) {
     return false;
   }
 
-  CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
+  CSSPoint currentScrollOffset = Metrics().GetScrollOffset() + mTestAsyncScrollOffset;
   CSSRect painted = mLastContentPaintMetrics.GetDisplayPort() + mLastContentPaintMetrics.GetScrollOffset();
   painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1)));   // fuzz for rounding error
-  CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
+  CSSRect visible = CSSRect(currentScrollOffset, Metrics().CalculateCompositedSizeInCssPixels());
   if (painted.Contains(visible)) {
     return false;
   }
-  APZC_LOG_FM(mFrameMetrics, "%p is currently checkerboarding (painted %s visble %s)",
+  APZC_LOG_FM(Metrics(), "%p is currently checkerboarding (painted %s visble %s)",
     this, Stringify(painted).c_str(), Stringify(visible).c_str());
   return true;
 }
 
 void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMetadata,
                                                  bool aIsFirstPaint,
                                                  bool aThisLayerTreeUpdated)
 {
@@ -4028,28 +4027,28 @@ void AsyncPanZoomController::NotifyLayer
   const FrameMetrics& aLayerMetrics = aScrollMetadata.GetMetrics();
 
   if ((aScrollMetadata == mLastContentPaintMetadata) && !isDefault) {
     // No new information here, skip it.
     APZC_LOG("%p NotifyLayersUpdated short-circuit\n", this);
     return;
   }
 
-  // If the mFrameMetrics scroll offset is different from the last scroll offset
+  // If the Metrics scroll offset is different from the last scroll offset
   // that the main-thread sent us, then we know that the user has been doing
   // something that triggers a scroll. This check is the APZ equivalent of the
   // check on the main-thread at
   // https://hg.mozilla.org/mozilla-central/file/97a52326b06a/layout/generic/nsGfxScrollFrame.cpp#l4050
   // There is code below (the use site of userScrolled) that prevents a restored-
   // scroll-position update from overwriting a user scroll, again equivalent to
   // how the main thread code does the same thing.
   CSSPoint lastScrollOffset = mLastContentPaintMetadata.GetMetrics().GetScrollOffset();
   bool userScrolled =
-    !FuzzyEqualsAdditive(mFrameMetrics.GetScrollOffset().x, lastScrollOffset.x) ||
-    !FuzzyEqualsAdditive(mFrameMetrics.GetScrollOffset().y, lastScrollOffset.y);
+    !FuzzyEqualsAdditive(Metrics().GetScrollOffset().x, lastScrollOffset.x) ||
+    !FuzzyEqualsAdditive(Metrics().GetScrollOffset().y, lastScrollOffset.y);
 
   if (aLayerMetrics.GetScrollUpdateType() != FrameMetrics::ScrollOffsetUpdateType::ePending) {
     mLastContentPaintMetadata = aScrollMetadata;
   }
 
   mScrollMetadata.SetScrollParentId(aScrollMetadata.GetScrollParentId());
   APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d, aThisLayerTreeUpdated=%d",
     this, aIsFirstPaint, aThisLayerTreeUpdated);
@@ -4090,43 +4089,43 @@ void AsyncPanZoomController::NotifyLayer
     }
   }
 
   // If the layers update was not triggered by our own repaint request, then
   // we want to take the new scroll offset. Check the scroll generation as well
   // to filter duplicate calls to NotifyLayersUpdated with the same scroll offset
   // update message.
   bool scrollOffsetUpdated = aLayerMetrics.GetScrollOffsetUpdated()
-        && (aLayerMetrics.GetScrollGeneration() != mFrameMetrics.GetScrollGeneration());
+        && (aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
 
   if (scrollOffsetUpdated && userScrolled &&
       aLayerMetrics.GetScrollUpdateType() == FrameMetrics::ScrollOffsetUpdateType::eRestore) {
     APZC_LOG("%p dropping scroll update of type eRestore because of user scroll\n", this);
     scrollOffsetUpdated = false;
   }
 
   bool smoothScrollRequested = aLayerMetrics.GetDoSmoothScroll()
-       && (aLayerMetrics.GetScrollGeneration() != mFrameMetrics.GetScrollGeneration());
+       && (aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
 
   // TODO if we're in a drag and scrollOffsetUpdated is set then we want to
   // ignore it
 
   bool needContentRepaint = false;
   bool viewportUpdated = false;
-  if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Width(), mFrameMetrics.GetCompositionBounds().Width()) &&
-      FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Height(), mFrameMetrics.GetCompositionBounds().Height())) {
+  if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Width(), Metrics().GetCompositionBounds().Width()) &&
+      FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().Height(), Metrics().GetCompositionBounds().Height())) {
     // Remote content has sync'd up to the composition geometry
     // change, so we can accept the viewport it's calculated.
-    if (mFrameMetrics.GetViewport().Width() != aLayerMetrics.GetViewport().Width() ||
-        mFrameMetrics.GetViewport().Height() != aLayerMetrics.GetViewport().Height()) {
+    if (Metrics().GetViewport().Width() != aLayerMetrics.GetViewport().Width() ||
+        Metrics().GetViewport().Height() != aLayerMetrics.GetViewport().Height()) {
       needContentRepaint = true;
       viewportUpdated = true;
     }
     if (viewportUpdated || scrollOffsetUpdated) {
-      mFrameMetrics.SetViewport(aLayerMetrics.GetViewport());
+      Metrics().SetViewport(aLayerMetrics.GetViewport());
     }
   }
 
 #if defined(MOZ_WIDGET_ANDROID)
   if (aLayerMetrics.IsRootContent()) {
     if (APZCTreeManager* manager = GetApzcTreeManager()) {
       AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
       MOZ_ASSERT(animator);
@@ -4139,103 +4138,103 @@ void AsyncPanZoomController::NotifyLayer
     // Initialize our internal state to something sane when the content
     // that was just painted is something we knew nothing about previously
     CancelAnimation();
 
     mScrollMetadata = aScrollMetadata;
     mExpectedGeckoMetrics = aLayerMetrics;
     ShareCompositorFrameMetrics();
 
-    mCompositedLayoutViewport = mFrameMetrics.GetViewport();
-    mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
-    mCompositedZoom = mFrameMetrics.GetZoom();
-
-    if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) {
+    mCompositedLayoutViewport = Metrics().GetViewport();
+    mCompositedScrollOffset = Metrics().GetScrollOffset();
+    mCompositedZoom = Metrics().GetZoom();
+
+    if (Metrics().GetDisplayPortMargins() != ScreenMargin()) {
       // A non-zero display port margin here indicates a displayport has
       // been set by a previous APZC for the content at this guid. The
       // scrollable rect may have changed since then, making the margins
       // wrong, so we need to calculate a new display port.
       APZC_LOG("%p detected non-empty margins which probably need updating\n", this);
       needContentRepaint = true;
     }
   } else {
     // If we're not taking the aLayerMetrics wholesale we still need to pull
-    // in some things into our local mFrameMetrics because these things are
-    // determined by Gecko and our copy in mFrameMetrics may be stale.
-
-    if (FuzzyEqualsAdditive(mFrameMetrics.GetCompositionBounds().Width(), aLayerMetrics.GetCompositionBounds().Width()) &&
-        mFrameMetrics.GetDevPixelsPerCSSPixel() == aLayerMetrics.GetDevPixelsPerCSSPixel() &&
+    // in some things into our local Metrics() because these things are
+    // determined by Gecko and our copy in Metrics() may be stale.
+
+    if (FuzzyEqualsAdditive(Metrics().GetCompositionBounds().Width(), aLayerMetrics.GetCompositionBounds().Width()) &&
+        Metrics().GetDevPixelsPerCSSPixel() == aLayerMetrics.GetDevPixelsPerCSSPixel() &&
         !viewportUpdated) {
       // Any change to the pres shell resolution was requested by APZ and is
       // already included in our zoom; however, other components of the
       // cumulative resolution (a parent document's pres-shell resolution, or
       // the css-driven resolution) may have changed, and we need to update
       // our zoom to reflect that. Note that we can't just take
       // aLayerMetrics.mZoom because the APZ may have additional async zoom
       // since the repaint request.
       gfxSize totalResolutionChange = aLayerMetrics.GetCumulativeResolution()
-                                    / mFrameMetrics.GetCumulativeResolution();
+                                    / Metrics().GetCumulativeResolution();
       float presShellResolutionChange = aLayerMetrics.GetPresShellResolution()
-                                      / mFrameMetrics.GetPresShellResolution();
+                                      / Metrics().GetPresShellResolution();
       if (presShellResolutionChange != 1.0f) {
         needContentRepaint = true;
       }
-      mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange);
+      Metrics().ZoomBy(totalResolutionChange / presShellResolutionChange);
       mCompositedZoom.xScale *= (totalResolutionChange / presShellResolutionChange).width;
       mCompositedZoom.yScale *= (totalResolutionChange / presShellResolutionChange).height;
     } else {
       // Take the new zoom as either device scale or composition width or
       // viewport size got changed (e.g. due to orientation change, or content
       // changing the meta-viewport tag).
-      mFrameMetrics.SetZoom(aLayerMetrics.GetZoom());
+      Metrics().SetZoom(aLayerMetrics.GetZoom());
       mCompositedZoom = aLayerMetrics.GetZoom();
-      mFrameMetrics.SetDevPixelsPerCSSPixel(aLayerMetrics.GetDevPixelsPerCSSPixel());
+      Metrics().SetDevPixelsPerCSSPixel(aLayerMetrics.GetDevPixelsPerCSSPixel());
     }
     bool scrollableRectChanged = false;
-    if (!mFrameMetrics.GetScrollableRect().IsEqualEdges(aLayerMetrics.GetScrollableRect())) {
-      mFrameMetrics.SetScrollableRect(aLayerMetrics.GetScrollableRect());
+    if (!Metrics().GetScrollableRect().IsEqualEdges(aLayerMetrics.GetScrollableRect())) {
+      Metrics().SetScrollableRect(aLayerMetrics.GetScrollableRect());
       needContentRepaint = true;
       scrollableRectChanged = true;
     }
-    mFrameMetrics.SetCompositionBounds(aLayerMetrics.GetCompositionBounds());
-    mFrameMetrics.SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize());
-    mFrameMetrics.SetPresShellResolution(aLayerMetrics.GetPresShellResolution());
-    mFrameMetrics.SetCumulativeResolution(aLayerMetrics.GetCumulativeResolution());
+    Metrics().SetCompositionBounds(aLayerMetrics.GetCompositionBounds());
+    Metrics().SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize());
+    Metrics().SetPresShellResolution(aLayerMetrics.GetPresShellResolution());
+    Metrics().SetCumulativeResolution(aLayerMetrics.GetCumulativeResolution());
     mScrollMetadata.SetHasScrollgrab(aScrollMetadata.GetHasScrollgrab());
     mScrollMetadata.SetLineScrollAmount(aScrollMetadata.GetLineScrollAmount());
     mScrollMetadata.SetPageScrollAmount(aScrollMetadata.GetPageScrollAmount());
     mScrollMetadata.SetSnapInfo(ScrollSnapInfo(aScrollMetadata.GetSnapInfo()));
     // The scroll clip can differ between layers associated a given scroll frame,
     // so APZC (which keeps a single copy of ScrollMetadata per scroll frame)
     // has no business using it.
     mScrollMetadata.SetScrollClip(Nothing());
     mScrollMetadata.SetIsLayersIdRoot(aScrollMetadata.IsLayersIdRoot());
     mScrollMetadata.SetIsAutoDirRootContentRTL(
                       aScrollMetadata.IsAutoDirRootContentRTL());
     mScrollMetadata.SetUsesContainerScrolling(aScrollMetadata.UsesContainerScrolling());
-    mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
+    Metrics().SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
     mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled());
     mScrollMetadata.SetDisregardedDirection(aScrollMetadata.GetDisregardedDirection());
     mScrollMetadata.SetOverscrollBehavior(aScrollMetadata.GetOverscrollBehavior());
 
     if (scrollOffsetUpdated) {
       APZC_LOG("%p updating scroll offset from %s to %s\n", this,
-        ToString(mFrameMetrics.GetScrollOffset()).c_str(),
+        ToString(Metrics().GetScrollOffset()).c_str(),
         ToString(aLayerMetrics.GetScrollOffset()).c_str());
 
       // Send an acknowledgement with the new scroll generation so that any
       // repaint requests later in this function go through.
       // Because of the scroll generation update, any inflight paint requests are
       // going to be ignored by layout, and so mExpectedGeckoMetrics
       // becomes incorrect for the purposes of calculating the LD transform. To
       // correct this we need to update mExpectedGeckoMetrics to be the
       // last thing we know was painted by Gecko.
       CopyScrollInfoFrom(aLayerMetrics);
-      mCompositedLayoutViewport = mFrameMetrics.GetViewport();
-      mCompositedScrollOffset = mFrameMetrics.GetScrollOffset();
+      mCompositedLayoutViewport = Metrics().GetViewport();
+      mCompositedScrollOffset = Metrics().GetScrollOffset();
       mExpectedGeckoMetrics = aLayerMetrics;
 
       // Cancel the animation (which might also trigger a repaint request)
       // after we update the scroll offset above. Otherwise we can be left
       // in a state where things are out of sync.
       CancelAnimation();
 
       // Since the scroll offset has changed, we need to recompute the
@@ -4248,49 +4247,57 @@ void AsyncPanZoomController::NotifyLayer
       needContentRepaint = true;
       // Since the main-thread scroll offset changed we should trigger a
       // recomposite to make sure it becomes user-visible.
       ScheduleComposite();
     } else if (scrollableRectChanged) {
       // Even if we didn't accept a new scroll offset from content, the
       // scrollable rect may have changed in a way that makes our local
       // scroll offset out of bounds, so re-clamp it.
-      ClampAndSetScrollOffset(mFrameMetrics.GetScrollOffset());
+      ClampAndSetScrollOffset(Metrics().GetScrollOffset());
     }
   }
 
   if (smoothScrollRequested) {
     // A smooth scroll has been requested for animation on the compositor
     // thread.  This flag will be reset by the main thread when it receives
     // the scroll update acknowledgement.
 
     APZC_LOG("%p smooth scrolling from %s to %s in state %d\n", this,
-      Stringify(mFrameMetrics.GetScrollOffset()).c_str(),
+      Stringify(Metrics().GetScrollOffset()).c_str(),
       Stringify(aLayerMetrics.GetSmoothScrollOffset()).c_str(),
       mState);
 
     // See comment on the similar code in the |if (scrollOffsetUpdated)| block
     // above.
-    mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics);
+    Metrics().CopySmoothScrollInfoFrom(aLayerMetrics);
     needContentRepaint = true;
     mExpectedGeckoMetrics = aLayerMetrics;
 
-    SmoothScrollTo(mFrameMetrics.GetSmoothScrollOffset());
+    SmoothScrollTo(Metrics().GetSmoothScrollOffset());
   }
 
   if (needContentRepaint) {
     // This repaint request is not driven by a user action on the APZ side
     RequestContentRepaint(false);
   }
   UpdateSharedCompositorFrameMetrics();
 }
 
+FrameMetrics& AsyncPanZoomController::Metrics() {
+  return mScrollMetadata.GetMetrics();
+}
+
+const FrameMetrics& AsyncPanZoomController::Metrics() const {
+  return mScrollMetadata.GetMetrics();;
+}
+
 const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() const {
   mRecursiveMutex.AssertCurrentThreadIn();
-  return mFrameMetrics;
+  return mScrollMetadata.GetMetrics();;
 }
 
 const ScrollMetadata& AsyncPanZoomController::GetScrollMetadata() const {
   mRecursiveMutex.AssertCurrentThreadIn();
   return mScrollMetadata;
 }
 
 void
@@ -4326,28 +4333,28 @@ void AsyncPanZoomController::ZoomToRect(
     return;
   }
 
   // Only the root APZC is zoomable, and the root APZC is not allowed to have
   // different x and y scales. If it did, the calculations in this function
   // would have to be adjusted (as e.g. it would no longer be valid to take
   // the minimum or maximum of the ratios of the widths and heights of the
   // page rect and the composition bounds).
-  MOZ_ASSERT(mFrameMetrics.IsRootContent());
-  MOZ_ASSERT(mFrameMetrics.GetZoom().AreScalesSame());
+  MOZ_ASSERT(Metrics().IsRootContent());
+  MOZ_ASSERT(Metrics().GetZoom().AreScalesSame());
 
   SetState(ANIMATING_ZOOM);
 
   {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
 
-    ParentLayerRect compositionBounds = mFrameMetrics.GetCompositionBounds();
-    CSSRect cssPageRect = mFrameMetrics.GetScrollableRect();
-    CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
-    CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoom().ToScaleFactor();
+    ParentLayerRect compositionBounds = Metrics().GetCompositionBounds();
+    CSSRect cssPageRect = Metrics().GetScrollableRect();
+    CSSPoint scrollOffset = Metrics().GetScrollOffset();
+    CSSToParentLayerScale currentZoom = Metrics().GetZoom().ToScaleFactor();
     CSSToParentLayerScale targetZoom;
 
     // The minimum zoom to prevent over-zoom-out.
     // If the zoom factor is lower than this (i.e. we are zoomed more into the page),
     // then the CSS content rect, in layers pixels, will be smaller than the
     // composition bounds. If this happens, we can't fill the target composited
     // area with this frame.
     CSSToParentLayerScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale,
@@ -4372,38 +4379,38 @@ void AsyncPanZoomController::ZoomToRect(
       zoomOut = false;
     } else {
       zoomOut = aRect.IsEmpty() ||
         (currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
         (currentZoom == localMinZoom && targetZoom <= localMinZoom);
     }
 
     if (zoomOut) {
-      CSSSize compositedSize = mFrameMetrics.CalculateCompositedSizeInCssPixels();
+      CSSSize compositedSize = Metrics().CalculateCompositedSizeInCssPixels();
       float y = scrollOffset.y;
       float newHeight =
         cssPageRect.Width() * (compositedSize.height / compositedSize.width);
       float dh = compositedSize.height - newHeight;
 
       aRect = CSSRect(0.0f,
                       y + dh/2,
                       cssPageRect.Width(),
                       newHeight);
       aRect = aRect.Intersect(cssPageRect);
       targetZoom = CSSToParentLayerScale(std::min(compositionBounds.Width() / aRect.Width(),
                                                   compositionBounds.Height() / aRect.Height()));
     }
 
     targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale);
-    FrameMetrics endZoomToMetrics = mFrameMetrics;
+    FrameMetrics endZoomToMetrics = Metrics();
     if (aFlags & PAN_INTO_VIEW_ONLY) {
       targetZoom = currentZoom;
     } else if(aFlags & ONLY_ZOOM_TO_DEFAULT_SCALE) {
       CSSToParentLayerScale zoomAtDefaultScale =
-        mFrameMetrics.GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0);
+        Metrics().GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0);
       if (targetZoom.scale > zoomAtDefaultScale.scale) {
         // Only change the zoom if we are less than the default zoom
         if (currentZoom.scale < zoomAtDefaultScale.scale) {
           targetZoom = zoomAtDefaultScale;
         } else {
           targetZoom = currentZoom;
         }
       }
@@ -4430,18 +4437,18 @@ void AsyncPanZoomController::ZoomToRect(
       aRect.MoveToX(std::max(0.f, cssPageRect.Width() - sizeAfterZoom.width));
     }
 
     endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
     endZoomToMetrics.RecalculateViewportOffset();
 
     StartAnimation(new ZoomAnimation(
         *this,
-        mFrameMetrics.GetScrollOffset(),
-        mFrameMetrics.GetZoom(),
+        Metrics().GetScrollOffset(),
+        Metrics().GetZoom(),
         endZoomToMetrics.GetScrollOffset(),
         endZoomToMetrics.GetZoom()));
 
     // Schedule a repaint now, so the new displayport will be painted before the
     // animation finishes.
     ParentLayerPoint velocity(0, 0);
     endZoomToMetrics.SetDisplayPortMargins(
       CalculatePendingDisplayPort(endZoomToMetrics, velocity));
@@ -4557,17 +4564,17 @@ void AsyncPanZoomController::DispatchSta
     } else if (IsTransformingState(aOldState) && !IsTransformingState(aNewState)) {
 #if defined(MOZ_WIDGET_ANDROID)
       // The Android UI thread only shows overlay UI elements when the content is not being
       // panned or zoomed and it is in a steady state. So the FrameMetrics only need to be
       // updated when the transform ends.
       if (APZCTreeManager* manager = GetApzcTreeManager()) {
         AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
         MOZ_ASSERT(animator);
-        animator->UpdateRootFrameMetrics(mFrameMetrics);
+        animator->UpdateRootFrameMetrics(Metrics());
       }
 #endif
 
       controller->NotifyAPZStateChange(
           GetGuid(), APZStateChange::eTransformEnd);
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
       if (gfxPrefs::HidePluginsForScroll() && mCompositorController) {
         mCompositorController->ScheduleShowAllPluginWindows();
@@ -4588,19 +4595,19 @@ bool AsyncPanZoomController::IsInPanning
 void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConstraints) {
   APZC_LOG("%p updating zoom constraints to %d %d %f %f\n", this, aConstraints.mAllowZoom,
     aConstraints.mAllowDoubleTapZoom, aConstraints.mMinZoom.scale, aConstraints.mMaxZoom.scale);
   if (IsNaN(aConstraints.mMinZoom.scale) || IsNaN(aConstraints.mMaxZoom.scale)) {
     NS_WARNING("APZC received zoom constraints with NaN values; dropping...");
     return;
   }
 
-  CSSToParentLayerScale min = mFrameMetrics.GetDevPixelsPerCSSPixel()
+  CSSToParentLayerScale min = Metrics().GetDevPixelsPerCSSPixel()
     * kViewportMinScale / ParentLayerToScreenScale(1);
-  CSSToParentLayerScale max = mFrameMetrics.GetDevPixelsPerCSSPixel()
+  CSSToParentLayerScale max = Metrics().GetDevPixelsPerCSSPixel()
     * kViewportMaxScale / ParentLayerToScreenScale(1);
 
   // inf float values and other bad cases should be sanitized by the code below.
   mZoomConstraints.mAllowZoom = aConstraints.mAllowZoom;
   mZoomConstraints.mAllowDoubleTapZoom = aConstraints.mAllowDoubleTapZoom;
   mZoomConstraints.mMinZoom = (min > aConstraints.mMinZoom ? min : aConstraints.mMinZoom);
   mZoomConstraints.mMaxZoom = (max > aConstraints.mMaxZoom ? aConstraints.mMaxZoom : max);
   if (mZoomConstraints.mMaxZoom < mZoomConstraints.mMinZoom) {
@@ -4641,29 +4648,29 @@ void AsyncPanZoomController::GetGuid(Scr
 {
   if (aGuidOut) {
     *aGuidOut = GetGuid();
   }
 }
 
 ScrollableLayerGuid AsyncPanZoomController::GetGuid() const
 {
-  return ScrollableLayerGuid(mLayersId, mFrameMetrics);
+  return ScrollableLayerGuid(mLayersId, Metrics());
 }
 
 void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
 {
   mRecursiveMutex.AssertCurrentThreadIn();
 
   FrameMetrics* frame = mSharedFrameMetricsBuffer ?
       static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory()) : nullptr;
 
   if (frame && mSharedLock && gfxPrefs::ProgressivePaint()) {
     mSharedLock->Lock();
-    *frame = mFrameMetrics;
+    *frame = Metrics();
     mSharedLock->Unlock();
   }
 }
 
 void AsyncPanZoomController::ShareCompositorFrameMetrics()
 {
   AssertOnUpdaterThread();
 
@@ -4678,17 +4685,17 @@ void AsyncPanZoomController::ShareCompos
     mSharedFrameMetricsBuffer->Create(sizeof(FrameMetrics));
     mSharedFrameMetricsBuffer->Map(sizeof(FrameMetrics));
     frame = static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory());
 
     if (frame) {
 
       { // scope the monitor, only needed to copy the FrameMetrics.
         RecursiveMutexAutoLock lock(mRecursiveMutex);
-        *frame = mFrameMetrics;
+        *frame = Metrics();
       }
 
       // Get the process id of the content process
       base::ProcessId otherPid = mMetricsSharingController->RemotePid();
       ipc::SharedMemoryBasic::Handle mem = ipc::SharedMemoryBasic::NULLHandle();
 
       // Get the shared memory handle to share with the content process
       mSharedFrameMetricsBuffer->ShareToProcess(otherPid, &mem);
@@ -4720,76 +4727,76 @@ AsyncPanZoomController::SetTestAsyncZoom
   mTestAsyncZoom = aZoom;
   ScheduleComposite();
 }
 
 Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
     const CSSPoint& aDestination, nsIScrollableFrame::ScrollUnit aUnit) {
   mRecursiveMutex.AssertCurrentThreadIn();
   APZC_LOG("%p scroll snapping near %s\n", this, Stringify(aDestination).c_str());
-  CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
+  CSSRect scrollRange = Metrics().CalculateScrollRange();
   if (Maybe<nsPoint> snapPoint = ScrollSnapUtils::GetSnapPointForDestination(
           mScrollMetadata.GetSnapInfo(),
           aUnit,
-          CSSSize::ToAppUnits(mFrameMetrics.CalculateCompositedSizeInCssPixels()),
+          CSSSize::ToAppUnits(Metrics().CalculateCompositedSizeInCssPixels()),
           CSSRect::ToAppUnits(scrollRange),
-          CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()),
+          CSSPoint::ToAppUnits(Metrics().GetScrollOffset()),
           CSSPoint::ToAppUnits(aDestination))) {
     CSSPoint cssSnapPoint = CSSPoint::FromAppUnits(snapPoint.ref());
     // GetSnapPointForDestination() can produce a destination that's outside
     // of the scroll frame's scroll range. Clamp it here (this matches the
     // behaviour of the main-thread code path, which clamps it in
     // nsGfxScrollFrame::ScrollTo()).
     return Some(scrollRange.ClampPoint(cssSnapPoint));
   }
   return Nothing();
 }
 
 void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
   if (Maybe<CSSPoint> snapPoint =
         FindSnapPointNear(aDestination, nsIScrollableFrame::DEVICE_PIXELS)) {
-    if (*snapPoint != mFrameMetrics.GetScrollOffset()) {
+    if (*snapPoint != Metrics().GetScrollOffset()) {
       APZC_LOG("%p smooth scrolling to snap point %s\n", this, Stringify(*snapPoint).c_str());
       SmoothScrollTo(*snapPoint);
     }
   }
 }
 
 void AsyncPanZoomController::ScrollSnap() {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  ScrollSnapNear(mFrameMetrics.GetScrollOffset());
+  ScrollSnapNear(Metrics().GetScrollOffset());
 }
 
 void AsyncPanZoomController::ScrollSnapToDestination() {
   RecursiveMutexAutoLock lock(mRecursiveMutex);
 
   float friction = gfxPrefs::APZFlingFriction();
   ParentLayerPoint velocity(mX.GetVelocity(), mY.GetVelocity());
   ParentLayerPoint predictedDelta;
   // "-velocity / log(1.0 - friction)" is the integral of the deceleration
   // curve modeled for flings in the "Axis" class.
   if (velocity.x != 0.0f) {
     predictedDelta.x = -velocity.x / log(1.0 - friction);
   }
   if (velocity.y != 0.0f) {
     predictedDelta.y = -velocity.y / log(1.0 - friction);
   }
-  CSSPoint predictedDestination = mFrameMetrics.GetScrollOffset() + predictedDelta / mFrameMetrics.GetZoom();
+  CSSPoint predictedDestination = Metrics().GetScrollOffset() + predictedDelta / Metrics().GetZoom();
 
   // If the fling will overscroll, don't scroll snap, because then the user
   // user would not see any overscroll animation.
   bool flingWillOverscroll = IsOverscrolled() && ((velocity.x * mX.GetOverscroll() >= 0) ||
                                                   (velocity.y * mY.GetOverscroll() >= 0));
   if (!flingWillOverscroll) {
     APZC_LOG("%p fling snapping.  friction: %f velocity: %f, %f "
              "predictedDelta: %f, %f position: %f, %f "
              "predictedDestination: %f, %f\n",
              this, friction, velocity.x, velocity.y, (float)predictedDelta.x,
-             (float)predictedDelta.y, (float)mFrameMetrics.GetScrollOffset().x,
-             (float)mFrameMetrics.GetScrollOffset().y,
+             (float)predictedDelta.y, (float)Metrics().GetScrollOffset().x,
+             (float)Metrics().GetScrollOffset().y,
              (float)predictedDestination.x, (float)predictedDestination.y);
 
     ScrollSnapNear(predictedDestination);
   }
 }
 
 bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
     const ScrollWheelInput& aEvent,
@@ -4798,18 +4805,18 @@ bool AsyncPanZoomController::MaybeAdjust
 {
   // Don't scroll snap for pixel scrolls. This matches the main thread
   // behaviour in EventStateManager::DoScrollText().
   if (aEvent.mDeltaType == ScrollWheelInput::SCROLLDELTA_PIXEL) {
     return false;
   }
 
   RecursiveMutexAutoLock lock(mRecursiveMutex);
-  CSSToParentLayerScale2D zoom = mFrameMetrics.GetZoom();
-  CSSPoint destination = mFrameMetrics.CalculateScrollRange().ClampPoint(
+  CSSToParentLayerScale2D zoom = Metrics().GetZoom();
+  CSSPoint destination = Metrics().CalculateScrollRange().ClampPoint(
       aStartPosition + (aDelta / zoom));
   nsIScrollableFrame::ScrollUnit unit =
       ScrollWheelInput::ScrollUnitForDeltaType(aEvent.mDeltaType);
 
   if (Maybe<CSSPoint> snapPoint = FindSnapPointNear(destination, unit)) {
     aDelta = (*snapPoint - aStartPosition) * zoom;
     aStartPosition = *snapPoint;
     return true;
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -512,16 +512,23 @@ public:
    */
   CSSCoord ConvertScrollbarPoint(const ParentLayerPoint& aScrollbarPoint,
                                  const ScrollbarData& aThumbData) const;
 
   void NotifyMozMouseScrollEvent(const nsString& aString) const;
 
   bool OverscrollBehaviorAllowsSwipe() const;
 
+  //|Metrics()| and |Metrics() const| are getter functions that both return
+  //mScrollMetadata.mMetrics
+
+  const FrameMetrics& Metrics() const;
+  FrameMetrics& Metrics();
+
+
 private:
   // Get whether the horizontal content of the honoured target of auto-dir
   // scrolling starts from right to left. If you don't know of auto-dir
   // scrolling or what a honoured target means,
   // @see mozilla::WheelDeltaAdjustmentStrategy
   bool IsContentOfHonouredTargetRightToLeft(bool aHonoursRoot) const;
 
 protected:
@@ -882,23 +889,22 @@ protected:
 
   /* Utility functions that return a addrefed pointer to the corresponding fields. */
   already_AddRefed<GeckoContentController> GetGeckoContentController() const;
   already_AddRefed<GestureEventListener> GetGestureEventListener() const;
 
   PlatformSpecificStateBase* GetPlatformSpecificState();
 
 protected:
-  // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
-  // monitor. Do not read from or modify either of them without locking.
+  // Both |mScrollMetadata| and |mLastContentPaintMetrics| are protected by the
+  // monitor. Do not read from or modify them without locking.
   ScrollMetadata mScrollMetadata;
-  FrameMetrics& mFrameMetrics;  // for convenience, refers to mScrollMetadata.mMetrics
 
-  // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
-  // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
+  // Protects |mScrollMetadata|, |mLastContentPaintMetrics| and |mState|.
+  // Before manipulating |mScrollMetadata| or |mLastContentPaintMetrics| the
   // monitor should be held. When setting |mState|, either the SetState()
   // function can be used, or the monitor can be held and then |mState| updated.
   // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
   // This is mutable to allow entering it from 'const' methods; doing otherwise
   // would significantly limit what methods could be 'const'.
   // FIXME: Please keep in mind that due to some existing coupled relationships
   // among the class members, we should be aware of indirect usage of the
   // monitor-protected members. That is, although this monitor isn't required to
@@ -926,17 +932,17 @@ private:
   // The last metrics used for a content repaint request.
   FrameMetrics mLastPaintRequestMetrics;
   // The metrics that we expect content to have. This is updated when we
   // request a content repaint, and when we receive a shadow layers update.
   // This allows us to transform events into Gecko's coordinate space.
   FrameMetrics mExpectedGeckoMetrics;
 
   // These variables cache the layout viewport, scroll offset, and zoom stored
-  // in |mFrameMetrics| the last time SampleCompositedAsyncTransform() was
+  // in |Metrics()| the last time SampleCompositedAsyncTransform() was
   // called.
   CSSRect mCompositedLayoutViewport;
   CSSPoint mCompositedScrollOffset;
   CSSToParentLayerScale2D mCompositedZoom;
 
   AxisX mX;
   AxisY mY;
 
@@ -1054,30 +1060,30 @@ public:
    * any transform due to axis over-scroll.
    */
   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(AsyncTransformConsumer aMode) const;
 
 private:
   /**
    * Samples the composited async transform, making the result of
    * |GetCurrentAsyncTransform(eForCompositing)| and similar functions reflect
-   * the async scroll offset and zoom stored in |mFrameMetrics|.
+   * the async scroll offset and zoom stored in |Metrics()|.
    *
    * Returns true if the newly sampled value is different from the previously
    * sampled value.
    *
    * (This is only relevant when |gfxPrefs::APZFrameDelayEnabled() == true|.
    * Otherwise, GetCurrentAsyncTransform() always reflects what's stored in
-   * |mFrameMetrics| immediately, without any delay.)
+   * |Metrics()| immediately, without any delay.)
    */
   bool SampleCompositedAsyncTransform();
 
   /*
    * Helper functions to query the async layout viewport, scroll offset, and
-   * zoom either directly from |mFrameMetrics|, or from cached variables that
+   * zoom either directly from |Metrics()|, or from cached variables that
    * store the required value from the last time it was sampled by calling
    * SampleCompositedAsyncTransform(), depending on who is asking.
    */
   CSSRect GetEffectiveLayoutViewport(AsyncTransformConsumer aMode) const;
   CSSPoint GetEffectiveScrollOffset(AsyncTransformConsumer aMode) const;
   CSSToParentLayerScale2D GetEffectiveZoom(AsyncTransformConsumer aMode) const;
 
   /* ===================================================================
@@ -1268,17 +1274,17 @@ public:
 
   bool IsRootForLayersId() const {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     return mScrollMetadata.IsLayersIdRoot();
   }
 
   bool IsRootContent() const {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
-    return mFrameMetrics.IsRootContent();
+    return Metrics().IsRootContent();
   }
 
 private:
   // |mTreeManager| belongs in this section but it's declaration is a bit
   // further above due to initialization-order constraints.
 
   RefPtr<AsyncPanZoomController> mParent;
 
@@ -1422,17 +1428,17 @@ private:
 private:
   /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
    * shared FrameMeterics used in progressive tile painting. */
   const uint32_t mAPZCId;
 
   RefPtr<ipc::SharedMemoryBasic> mSharedFrameMetricsBuffer;
   CrossProcessMutex* mSharedLock;
   /**
-   * Called when ever mFrameMetrics is updated so that if it is being
+   * Called when ever Metrics() is updated so that if it is being
    * shared with the content process the shared FrameMetrics may be updated.
    */
   void UpdateSharedCompositorFrameMetrics();
   /**
    * Create a shared memory buffer for containing the FrameMetrics and
    * a CrossProcessMutex that may be shared with the content process
    * for use in progressive tiled update calculations.
    */
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -99,17 +99,17 @@ public:
    * The axis must be at the end of its scroll range in this direction.
    */
   void OverscrollBy(ParentLayerCoord aOverscroll);
 
   /**
    * Return the amount of overscroll on this axis, in ParentLayer pixels.
    *
    * If this amount is nonzero, the relevant component of
-   * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its
+   * mAsyncPanZoomController->Metrics().mScrollOffset must be at its
    * extreme allowed value in the relevant direction (that is, it must be at
    * its maximum value if we are overscrolled at our composition length, and
    * at its minimum value if we are overscrolled at the origin).
    */
   ParentLayerCoord GetOverscroll() const;
 
   /**
    * Start an overscroll animation with the given initial velocity.
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h
+++ b/gfx/layers/apz/test/gtest/APZTestCommon.h
@@ -222,16 +222,17 @@ public:
 protected:
   AsyncPanZoomController* NewAPZCInstance(LayersId aLayersId,
                                           GeckoContentController* aController) override;
 
   TimeStamp GetFrameTime() override {
     return mcc->Time();
   }
 
+
 private:
   RefPtr<MockContentControllerDelayed> mcc;
 };
 
 class TestAsyncPanZoomController : public AsyncPanZoomController {
 public:
   TestAsyncPanZoomController(LayersId aLayersId, MockContentControllerDelayed* aMcc,
                              TestAPZCTreeManager* aTreeManager,
@@ -264,32 +265,32 @@ public:
   }
 
   void SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) {
     GetInputQueue()->SetAllowedTouchBehavior(aInputBlockId, aBehaviors);
   }
 
   void SetFrameMetrics(const FrameMetrics& metrics) {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
-    mFrameMetrics = metrics;
+    Metrics() = metrics;
   }
 
   FrameMetrics& GetFrameMetrics() {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
-    return mFrameMetrics;
+    return mScrollMetadata.GetMetrics();
   }
 
   ScrollMetadata& GetScrollMetadata() {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     return mScrollMetadata;
   }
 
   const FrameMetrics& GetFrameMetrics() const {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
-    return mFrameMetrics;
+    return mScrollMetadata.GetMetrics();
   }
 
   using AsyncPanZoomController::GetVelocityVector;
 
   void AssertStateIsReset() const {
     RecursiveMutexAutoLock lock(mRecursiveMutex);
     EXPECT_EQ(NOTHING, mState);
   }