From fdbac095968bc952fec6a03765a7156940ae4733 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 31 Oct 2018 18:47:29 +0100 Subject: Ensure that the scroll frame deregisters its refresh driver observers (mAsyncScroll & mAsyncSmoothMSDScroll) before it's destroyed. Tag #345 --- layout/generic/nsGfxScrollFrame.cpp | 52 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 22 deletions(-) (limited to 'layout/generic') diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index ccdc3a0ce..cfa366aa3 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1774,6 +1774,18 @@ public: return true; } + /** + * The mCallee holds a strong ref to us since the refresh driver doesn't. + * Our dtor and mCallee's Destroy() method both call RemoveObserver() - + * whichever comes first removes us from the refresh driver. + */ + void RemoveObserver() { + if (mCallee) { + RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); + mCallee = nullptr; + } + } + private: // Private destructor, to discourage deletion outside of Release(): ~AsyncSmoothMSDScroll() { @@ -1786,17 +1798,6 @@ private: return aCallee->mOuter->PresContext()->RefreshDriver(); } - /* - * The refresh driver doesn't hold a reference to its observers, - * so releasing this object can (and is) used to remove the observer on DTOR. - * Currently, this object is released once the scrolling ends. - */ - void RemoveObserver() { - if (mCallee) { - RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); - } - } - mozilla::layers::AxisPhysicsMSDModel mXAxisModel, mYAxisModel; nsRect mRange; mozilla::TimeStamp mLastRefreshTime; @@ -1875,24 +1876,25 @@ public: ScrollFrameHelper::AsyncScrollCallback(mCallee, aTime); } -private: - ScrollFrameHelper *mCallee; - - nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) { - return aCallee->mOuter->PresContext()->RefreshDriver(); - } - - /* - * The refresh driver doesn't hold a reference to its observers, - * so releasing this object can (and is) used to remove the observer on DTOR. - * Currently, this object is released once the scrolling ends. + /** + * The mCallee holds a strong ref to us since the refresh driver doesn't. + * Our dtor and mCallee's Destroy() method both call RemoveObserver() - + * whichever comes first removes us from the refresh driver. */ void RemoveObserver() { if (mCallee) { RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); APZCCallbackHelper::SuppressDisplayport(false, mCallee->mOuter->PresContext()->PresShell()); + mCallee = nullptr; } } + +private: + ScrollFrameHelper *mCallee; + + nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) { + return aCallee->mOuter->PresContext()->RefreshDriver(); + } }; /* @@ -4586,6 +4588,12 @@ ScrollFrameHelper::Destroy() mScrollActivityTimer->Cancel(); mScrollActivityTimer = nullptr; } + if (mAsyncScroll) { + mAsyncScroll->RemoveObserver(); + } + if (mAsyncSmoothMSDScroll) { + mAsyncSmoothMSDScroll->RemoveObserver(); + } } /** -- cgit v1.2.3