Bug 877097: Check that the scrollable frame is still alive after each call to SetOpacityOnElement for the two scrollbars to avoid crashing. r=roc
authorStephen Pohl <spohl.mozilla.bugs@gmail.com>
Sat, 08 Jun 2013 14:05:33 -0700
changeset 141576 122712f43da6e64aeae81bfa1016322d5158da05
parent 141575 7569629f5b3d8c29b79b12f597fc7e01bbf01cbd
child 141577 1f228b1d95664000454af81fedee37406017d585
push id3911
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 20:17:26 +0000
treeherdermozilla-aurora@7e26ca8db92b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs877097
milestone24.0a1
Bug 877097: Check that the scrollable frame is still alive after each call to SetOpacityOnElement for the two scrollbars to avoid crashing. r=roc
layout/generic/ScrollbarActivity.cpp
layout/generic/ScrollbarActivity.h
--- a/layout/generic/ScrollbarActivity.cpp
+++ b/layout/generic/ScrollbarActivity.cpp
@@ -99,17 +99,19 @@ ScrollbarActivity::HandleEvent(nsIDOMEve
 
 void
 ScrollbarActivity::WillRefresh(TimeStamp aTime)
 {
   NS_ASSERTION(mIsActive, "should only fade while scrollbars are visible");
   NS_ASSERTION(!IsActivityOngoing(), "why weren't we unregistered from the refresh driver when scrollbar activity started?");
   NS_ASSERTION(mIsFading, "should only animate fading during fade");
 
-  UpdateOpacity(aTime);
+  if (!UpdateOpacity(aTime)) {
+    return;
+  }
 
   if (!IsStillFading(aTime)) {
     EndFade();
   }
 }
 
 bool
 ScrollbarActivity::IsStillFading(TimeStamp aTime)
@@ -299,23 +301,33 @@ SetOpacityOnElement(nsIContent* aContent
     if (decl) {
       nsAutoString str;
       str.AppendFloat(aOpacity);
       decl->SetProperty(NS_LITERAL_STRING("opacity"), str, EmptyString());
     }
   }
 }
 
-void
+bool
 ScrollbarActivity::UpdateOpacity(TimeStamp aTime)
 {
   double progress = (aTime - mFadeBeginTime) / FadeDuration();
   double opacity = 1.0 - std::max(0.0, std::min(1.0, progress));
+
+  // 'this' may be getting destroyed during SetOpacityOnElement calls.
+  nsWeakFrame weakFrame((do_QueryFrame(mScrollableFrame)));
   SetOpacityOnElement(GetHorizontalScrollbar(), opacity);
+  if (!weakFrame.IsAlive()) {
+    return false;
+  }
   SetOpacityOnElement(GetVerticalScrollbar(), opacity);
+  if (!weakFrame.IsAlive()) {
+    return false;
+  }
+  return true;
 }
 
 static void
 UnsetOpacityOnElement(nsIContent* aContent)
 {
   nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent =
     do_QueryInterface(aContent);
   if (inlineStyleContent) {
--- a/layout/generic/ScrollbarActivity.h
+++ b/layout/generic/ScrollbarActivity.h
@@ -109,17 +109,17 @@ protected:
   void CancelFadeBeginTimer();
   void StartListeningForEvents();
   void StartListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar);
   void StopListeningForEvents();
   void StopListeningForEventsOnScrollbar(nsIDOMEventTarget* aScrollbar);
   void RegisterWithRefreshDriver();
   void UnregisterFromRefreshDriver();
 
-  void UpdateOpacity(TimeStamp aTime);
+  bool UpdateOpacity(TimeStamp aTime); // returns false if 'this' was destroyed
   void HoveredScrollbar(nsIContent* aScrollbar);
 
   nsRefreshDriver* GetRefreshDriver();
   nsIContent* GetScrollbarContent(bool aVertical);
   nsIContent* GetHorizontalScrollbar() { return GetScrollbarContent(false); }
   nsIContent* GetVerticalScrollbar() { return GetScrollbarContent(true); }
 
   static const TimeDuration FadeDuration() {