Bug 1313258 - Don't create a MediaStreamGraph without doing anything with it. r?jesup draft
authorPaul Adenot <paul@paul.cx>
Wed, 07 Jun 2017 18:05:50 +0200
changeset 591824 a24508f0d4e229df824eadf04d787fa098559f95
parent 589544 4dd1d17ba22660b8f5869a707f2e4e9f9dd5be5b
child 632632 d4a51d3950e1c4d9dc1f5be8be31545d045d21f6
push id63183
push userpaul@paul.cx
push dateFri, 09 Jun 2017 16:15:07 +0000
reviewersjesup
bugs1313258
milestone55.0a1
Bug 1313258 - Don't create a MediaStreamGraph without doing anything with it. r?jesup The MediaStreamGraph relies on having at least one message sent to its message queue on creation, or it will just sit there and do nothing, and block shutdown because its not running its rendering loop, so it's not progressing in the MediaStreamGraph life cycle state machine. This patch makes sure the `captureStream` will succeed before creating an MSG. MozReview-Commit-ID: CN1arWydmxC
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3345,41 +3345,52 @@ HTMLMediaElement::AddCaptureMediaTrackTo
   }
 
   LOG(LogLevel::Debug,
       ("Created %s track %p with id %d from track %p through MediaInputPort %p",
        inputTrack->AsAudioStreamTrack() ? "audio" : "video",
        track.get(), destinationTrackID, inputTrack, port.get()));
 }
 
+bool
+HTMLMediaElement::CanBeCaptured(bool aCaptureAudio)
+{
+  // Don't bother capturing when the document has gone away
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return false;
+  }
+
+  // Prevent capturing restricted video
+  if (!aCaptureAudio && ContainsRestrictedContent()) {
+    return false;
+  }
+  return true;
+}
+
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
                                         bool aCaptureAudio,
                                         MediaStreamGraph* aGraph)
 {
   MOZ_RELEASE_ASSERT(aGraph);
+  MOZ_ASSERT(CanBeCaptured(aCaptureAudio));
 
   MarkAsContentSource(CallerAPI::CAPTURE_STREAM);
   MarkAsTainted();
 
-  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
-  if (!window) {
-    return nullptr;
-  }
-  if (!aCaptureAudio && ContainsRestrictedContent()) {
-    return nullptr;
-  }
-
+  // We don't support routing to a different graph.
   if (!mOutputStreams.IsEmpty() &&
       aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) {
     return nullptr;
   }
 
   OutputMediaStream* out = mOutputStreams.AppendElement();
   MediaStreamTrackSourceGetter* getter = new CaptureStreamTrackSourceGetter(this);
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
   out->mStream = DOMMediaStream::CreateTrackUnionStreamAsInput(window, aGraph, getter);
   out->mStream->SetInactiveOnFinish();
   out->mFinishWhenEnded = aFinishWhenEnded;
   out->mCapturingAudioOnly = aCaptureAudio;
 
   if (aCaptureAudio) {
     if (mSrcStream) {
       // We don't support applying volume and mute to the captured stream, when
@@ -3476,16 +3487,23 @@ HTMLMediaElement::CaptureAudio(ErrorResu
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::MozCaptureStream(ErrorResult& aRv)
 {
   MediaStreamGraph::GraphDriverType graphDriverType =
     HasAudio() ? MediaStreamGraph::AUDIO_THREAD_DRIVER
                : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+
+
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return nullptr;
+  }
+
   MediaStreamGraph* graph =
     MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
 
   RefPtr<DOMMediaStream> stream =
     CaptureStreamInternal(false, false, graph);
   if (!stream) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
@@ -3495,16 +3513,22 @@ HTMLMediaElement::MozCaptureStream(Error
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::MozCaptureStreamUntilEnded(ErrorResult& aRv)
 {
   MediaStreamGraph::GraphDriverType graphDriverType =
     HasAudio() ? MediaStreamGraph::AUDIO_THREAD_DRIVER
                : MediaStreamGraph::SYSTEM_THREAD_DRIVER;
+
+  nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
+  if (!window) {
+    return nullptr;
+  }
+
   MediaStreamGraph* graph =
     MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
 
   RefPtr<DOMMediaStream> stream =
     CaptureStreamInternal(true, false, graph);
   if (!stream) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1274,16 +1274,19 @@ protected:
   bool IsAllowedToPlay();
 
   // If the network state is empty and then we would trigger DoLoad().
   void MaybeDoLoad();
 
   // Anything we need to check after played success and not related with spec.
   void UpdateCustomPolicyAfterPlayed();
 
+  // True if this element can be captured, false otherwise.
+  bool CanBeCaptured(bool aCaptureAudio);
+
   class nsAsyncEventRunner;
   class nsNotifyAboutPlayingRunner;
   class nsResolveOrRejectPendingPlayPromisesRunner;
   using nsGenericHTMLElement::DispatchEvent;
   // For nsAsyncEventRunner.
   nsresult DispatchEvent(const nsAString& aName);
 
   // Open unsupported types media with the external app when the media element