Fix crashes when a wheel transaction has a null confirmed apzc. (bug 1147249, r=kats)
authorDavid Anderson <danderson@mozilla.com>
Thu, 26 Mar 2015 14:15:41 -0700
changeset 264874 fb063ad596fdc2ea9f631d353bbf4069ab288293
parent 264873 02fabf032cbe19ad846d3b674b11cab6a15f1b64
child 264875 5bbd37d1d21a49e5b90687b21004d93c94581e75
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1147249
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Fix crashes when a wheel transaction has a null confirmed apzc. (bug 1147249, r=kats)
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -260,27 +260,30 @@ WheelBlockState::Type()
 
 bool
 WheelBlockState::ShouldAcceptNewEvent() const
 {
   if (!InTransaction()) {
     // If we're not in a transaction, start a new one.
     return false;
   }
+
   nsRefPtr<AsyncPanZoomController> apzc = GetTargetApzc();
-  if (!apzc || apzc->IsDestroyed()) {
+  if (apzc->IsDestroyed()) {
     return false;
   }
 
   return true;
 }
 
 bool
 WheelBlockState::MaybeTimeout(const ScrollWheelInput& aEvent)
 {
+  MOZ_ASSERT(InTransaction());
+
   if (MaybeTimeout(aEvent.mTimeStamp)) {
     return true;
   }
 
   if (!mLastMouseMove.IsNull()) {
     // If there's a recent mouse movement, we can time out the transaction early.
     TimeDuration duration = TimeStamp::Now() - mLastMouseMove;
     if (duration.ToMilliseconds() >= gfxPrefs::MouseWheelIgnoreMoveDelayMs()) {
@@ -291,16 +294,18 @@ WheelBlockState::MaybeTimeout(const Scro
   }
 
   return false;
 }
 
 bool
 WheelBlockState::MaybeTimeout(const TimeStamp& aTimeStamp)
 {
+  MOZ_ASSERT(InTransaction());
+
   // End the transaction if the event occurred > 1.5s after the most recently
   // seen wheel event.
   TimeDuration duration = aTimeStamp - mLastEventTime;
   if (duration.ToMilliseconds() < gfxPrefs::MouseWheelTransactionTimeoutMs()) {
     return false;
   }
 
   TBS_LOG("%p wheel transaction timed out\n", this);
@@ -312,16 +317,18 @@ WheelBlockState::MaybeTimeout(const Time
 
   EndTransaction();
   return true;
 }
 
 void
 WheelBlockState::OnMouseMove(const ScreenIntPoint& aPoint)
 {
+  MOZ_ASSERT(InTransaction());
+
   if (!GetTargetApzc()->Contains(aPoint)) {
     EndTransaction();
     return;
   }
 
   if (mLastMouseMove.IsNull()) {
     // If the cursor is moving inside the frame, and it is more than the
     // ignoremovedelay time since the last scroll operation, we record
@@ -329,25 +336,42 @@ WheelBlockState::OnMouseMove(const Scree
     TimeStamp now = TimeStamp::Now();
     TimeDuration duration = now - mLastEventTime;
     if (duration.ToMilliseconds() >= gfxPrefs::MouseWheelIgnoreMoveDelayMs()) {
       mLastMouseMove = now;
     }
   }
 }
 
+void
+WheelBlockState::UpdateTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc)
+{
+  InputBlockState::UpdateTargetApzc(aTargetApzc);
+
+  // If we found there was no target apzc, then we end the transaction.
+  if (!GetTargetApzc()) {
+    EndTransaction();
+  }
+}
+
 bool
 WheelBlockState::InTransaction() const
 {
   // We consider a wheel block to be in a transaction if it has a confirmed
   // target and is the most recent wheel input block to be created.
   if (GetBlockId() != sLastWheelBlockId) {
     return false;
   }
-  return !mTransactionEnded;
+
+  if (mTransactionEnded) {
+    return false;
+  }
+
+  MOZ_ASSERT(GetTargetApzc());
+  return true;
 }
 
 bool
 WheelBlockState::AllowScrollHandoff() const
 {
   // If we're in a wheel transaction, we do not allow overscroll handoff until
   // a new event ends the wheel transaction.
   return !IsTargetConfirmed() || !InTransaction();
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -41,17 +41,17 @@ public:
   bool SetConfirmedTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc);
   const nsRefPtr<AsyncPanZoomController>& GetTargetApzc() const;
   const nsRefPtr<const OverscrollHandoffChain>& GetOverscrollHandoffChain() const;
   uint64_t GetBlockId() const;
 
   bool IsTargetConfirmed() const;
 
 protected:
-  void UpdateTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc);
+  virtual void UpdateTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc);
 
 private:
   nsRefPtr<AsyncPanZoomController> mTargetApzc;
   bool mTargetConfirmed;
   const uint64_t mBlockId;
 protected:
   nsRefPtr<const OverscrollHandoffChain> mOverscrollHandoffChain;
 
@@ -219,16 +219,19 @@ public:
    */
   bool MaybeTimeout(const TimeStamp& aTimeStamp);
 
   /**
    * Update the wheel transaction state for a new event.
    */
   void Update(const ScrollWheelInput& aEvent);
 
+protected:
+  void UpdateTargetApzc(const nsRefPtr<AsyncPanZoomController>& aTargetApzc) override;
+
 private:
   nsTArray<ScrollWheelInput> mEvents;
   TimeStamp mLastEventTime;
   TimeStamp mLastMouseMove;
   bool mTransactionEnded;
 };
 
 /**