Bug 1301675 - Refactor canvas captureStream to be more clear on removing frame listeners. r?jib draft
authorAndreas Pehrson <pehrsons@gmail.com>
Mon, 12 Sep 2016 17:59:38 +0200
changeset 432216 bae7c2c903ce183dda9865145f0a8974b7bb2d34
parent 432215 f03b5f28751babf2c58254bce556f210c5f58994
child 432217 d2e0383c99254fb4786bd7fd6ed5357d19caae33
push id34235
push userbmo:pehrson@telenordigital.com
push dateTue, 01 Nov 2016 13:40:03 +0000
reviewersjib
bugs1301675
milestone52.0a1
Bug 1301675 - Refactor canvas captureStream to be more clear on removing frame listeners. r?jib MozReview-Commit-ID: 8gDlYA4AXOR
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLCanvasElement.h
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -115,16 +115,18 @@ public:
     if (mOwningElement->IsWriteOnly()) {
       return;
     }
 
     if (mOwningElement->IsContextCleanForFrameCapture()) {
       return;
     }
 
+    mOwningElement->ProcessDestroyedFrameListeners();
+
     if (!mOwningElement->IsFrameCaptureRequested()) {
       return;
     }
 
     RefPtr<SourceSurface> snapshot = mOwningElement->GetSurfaceSnapshot(nullptr);
     if (!snapshot) {
       return;
     }
@@ -1194,39 +1196,49 @@ HTMLCanvasElement::IsFrameCaptureRequest
     if (listener->FrameCaptureRequested()) {
       return true;
     }
   }
   return false;
 }
 
 void
-HTMLCanvasElement::SetFrameCapture(already_AddRefed<SourceSurface> aSurface)
+HTMLCanvasElement::ProcessDestroyedFrameListeners()
 {
-  RefPtr<SourceSurface> surface = aSurface;
-  RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(surface->GetSize(), surface);
-
   // Loop backwards to allow removing elements in the loop.
   for (int i = mRequestedFrameListeners.Length() - 1; i >= 0; --i) {
     WeakPtr<FrameCaptureListener> listener = mRequestedFrameListeners[i];
     if (!listener) {
       // listener was destroyed. Remove it from the list.
       mRequestedFrameListeners.RemoveElementAt(i);
       continue;
     }
-
-    RefPtr<Image> imageRefCopy = image.get();
-    listener->NewFrame(imageRefCopy.forget());
   }
 
   if (mRequestedFrameListeners.IsEmpty()) {
     mRequestedFrameRefreshObserver->Unregister();
   }
 }
 
+void
+HTMLCanvasElement::SetFrameCapture(already_AddRefed<SourceSurface> aSurface)
+{
+  RefPtr<SourceSurface> surface = aSurface;
+  RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(surface->GetSize(), surface);
+
+  for (WeakPtr<FrameCaptureListener> listener : mRequestedFrameListeners) {
+    if (!listener) {
+      continue;
+    }
+
+    RefPtr<Image> imageRefCopy = image.get();
+    listener->NewFrame(imageRefCopy.forget());
+  }
+}
+
 already_AddRefed<SourceSurface>
 HTMLCanvasElement::GetSurfaceSnapshot(bool* aPremultAlpha)
 {
   if (!mCurrentContext)
     return nullptr;
 
   return mCurrentContext->GetSurfaceSnapshot(aPremultAlpha);
 }
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -272,16 +272,22 @@ public:
 
   /*
    * Returns true when there is at least one registered FrameCaptureListener
    * that has requested a frame capture.
    */
   bool IsFrameCaptureRequested() const;
 
   /*
+   * Processes destroyed FrameCaptureListeners and removes them if necessary.
+   * Should there be none left, the FrameRefreshObserver will be unregistered.
+   */
+  void ProcessDestroyedFrameListeners();
+
+  /*
    * Called by the RefreshDriver hook when a frame has been captured.
    * Makes a copy of the provided surface and hands it to all
    * FrameCaptureListeners having requested frame capture.
    */
   void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface);
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,