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 134451 122712f43da6e64aeae81bfa1016322d5158da05
parent 134450 7569629f5b3d8c29b79b12f597fc7e01bbf01cbd
child 134452 1f228b1d95664000454af81fedee37406017d585
push id29220
push userspohl@mozilla.com
push dateSat, 08 Jun 2013 21:05:47 +0000
treeherdermozilla-inbound@122712f43da6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs877097
milestone24.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
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() {