Bug 1308289 - Hold strong reference to VectorImage when dispatching ProgressTracker::SyncNotifyProgress. r=tnikkel, a=gchang
authorAndrew Osmond <aosmond@mozilla.com>
Thu, 13 Oct 2016 08:35:55 -0400
changeset 358725 7424d61ee7f3f7456228f95cdec45c785def7de8
parent 358724 d6580e1fcc08a9e1ce7cd1f07a2fdb99f8a087f1
child 358726 6d3f9e41d098b0f5bae91dd00d0767e785183fd4
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel, gchang
bugs1308289
milestone51.0a2
Bug 1308289 - Hold strong reference to VectorImage when dispatching ProgressTracker::SyncNotifyProgress. r=tnikkel, a=gchang
image/VectorImage.cpp
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -148,17 +148,17 @@ private:
 
 public:
   void EndLoad(nsIDocument* aDocument) override
   {
     MOZ_ASSERT(aDocument == mDocument, "Got EndLoad for wrong document?");
 
     // OnSVGDocumentParsed will release our owner's reference to us, so ensure
     // we stick around long enough to complete our work.
-    RefPtr<SVGParseCompleteListener> kungFuDeathGroup(this);
+    RefPtr<SVGParseCompleteListener> kungFuDeathGrip(this);
 
     mImage->OnSVGDocumentParsed();
   }
 
   void Cancel()
   {
     MOZ_ASSERT(mDocument, "Duplicate call to Cancel");
     if (mDocument) {
@@ -207,17 +207,17 @@ private:
 
 public:
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override
   {
     MOZ_ASSERT(mDocument, "Need an SVG document. Received multiple events?");
 
     // OnSVGDocumentLoaded/OnSVGDocumentError will release our owner's reference
     // to us, so ensure we stick around long enough to complete our work.
-    RefPtr<SVGLoadEventListener> kungFuDeathGroup(this);
+    RefPtr<SVGLoadEventListener> kungFuDeathGrip(this);
 
     nsAutoString eventType;
     aEvent->GetType(eventType);
     MOZ_ASSERT(eventType.EqualsLiteral("MozSVGAsImageDocumentLoad")  ||
                eventType.EqualsLiteral("SVGAbort")                   ||
                eventType.EqualsLiteral("SVGError"),
                "Received unexpected event");
 
@@ -531,18 +531,18 @@ VectorImage::RequestRefresh(const TimeSt
     tracker->TriggerPendingAnimationsOnNextTick(aTime);
   }
 
   EvaluateAnimation();
 
   mSVGDocumentWrapper->TickRefreshDriver();
 
   if (mHasPendingInvalidation) {
+    mHasPendingInvalidation = false;
     SendInvalidationNotifications();
-    mHasPendingInvalidation = false;
   }
 }
 
 void
 VectorImage::SendInvalidationNotifications()
 {
   // Animated images don't send out invalidation notifications as soon as
   // they're generated. Instead, InvalidateObserversOnNextRefreshDriverTick
@@ -1135,16 +1135,20 @@ VectorImage::OnStartRequest(nsIRequest* 
   mSVGDocumentWrapper = new SVGDocumentWrapper();
   nsresult rv = mSVGDocumentWrapper->OnStartRequest(aRequest, aCtxt);
   if (NS_FAILED(rv)) {
     mSVGDocumentWrapper = nullptr;
     mError = true;
     return rv;
   }
 
+  // ProgressTracker::SyncNotifyProgress may release us, so ensure we
+  // stick around long enough to complete our work.
+  RefPtr<VectorImage> kungFuDeathGrip(this);
+
   // Block page load until the document's ready.  (We unblock it in
   // OnSVGDocumentLoaded or OnSVGDocumentError.)
   if (mProgressTracker) {
     mProgressTracker->SyncNotifyProgress(FLAG_ONLOAD_BLOCKED);
   }
 
   // Create a listener to wait until the SVG document is fully loaded, which
   // will signal that this image is ready to render. Certain error conditions
@@ -1215,16 +1219,20 @@ VectorImage::OnSVGDocumentLoaded()
   mSVGDocumentWrapper->FlushLayout();
 
   mIsFullyLoaded = true;
   mHaveAnimations = mSVGDocumentWrapper->IsAnimated();
 
   // Start listening to our image for rendering updates.
   mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this);
 
+  // ProgressTracker::SyncNotifyProgress may release us, so ensure we
+  // stick around long enough to complete our work.
+  RefPtr<VectorImage> kungFuDeathGrip(this);
+
   // Tell *our* observers that we're done loading.
   if (mProgressTracker) {
     Progress progress = FLAG_SIZE_AVAILABLE |
                         FLAG_HAS_TRANSPARENCY |
                         FLAG_FRAME_COMPLETE |
                         FLAG_DECODE_COMPLETE |
                         FLAG_ONLOAD_UNBLOCKED;