Bug 1315551 - part3 : check we have initialized agent when we want to call the agent's function. draft
authorAlastor Wu <alwu@mozilla.com>
Mon, 07 Nov 2016 16:10:07 +0800
changeset 434710 f8e9da283704764832828ad7bb9bf8dde36cc43a
parent 434709 cd48c6c4e5b1b8bcbaad260940ff33a4975af05f
child 536090 8eaba9141822741094043464bcd61fa658f90fe7
push id34798
push useralwu@mozilla.com
push dateMon, 07 Nov 2016 08:10:29 +0000
bugs1315551
milestone52.0a1
Bug 1315551 - part3 : check we have initialized agent when we want to call the agent's function. MozReview-Commit-ID: 131tXUFnmXv
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2944,17 +2944,17 @@ HTMLMediaElement::HTMLMediaElement(alrea
 
   MOZ_ASSERT(NS_IsMainThread());
   mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
   // Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
   // to run until mReadyState reaches at least HAVE_METADATA by some other means.
   mWatchManager.Watch(mReadyState, &HTMLMediaElement::UpdateReadyStateInternal);
 
   mShutdownObserver->Subscribe(this);
-  CreateAudioChannelAgent();
+  MaybeCreateAudioChannelAgent();
 }
 
 HTMLMediaElement::~HTMLMediaElement()
 {
   NS_ASSERTION(!mHasSelfReference,
                "How can we be destroyed if we're still holding a self reference?");
 
   mShutdownObserver->Unsubscribe();
@@ -5757,27 +5757,36 @@ NS_IMETHODIMP HTMLMediaElement::SetMozPr
 }
 
 ImageContainer* HTMLMediaElement::GetImageContainer()
 {
   VideoFrameContainer* container = GetVideoFrameContainer();
   return container ? container->GetImageContainer() : nullptr;
 }
 
-void
-HTMLMediaElement::CreateAudioChannelAgent()
+bool
+HTMLMediaElement::MaybeCreateAudioChannelAgent()
 {
   if (mAudioChannelAgent) {
-    return;
+    return true;
   }
 
   mAudioChannelAgent = new AudioChannelAgent();
-  mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
+  nsresult rv = mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
                                            static_cast<int32_t>(mAudioChannel),
                                            this);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mAudioChannelAgent = nullptr;
+    MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
+           ("HTMLMediaElement, Fail to initialize the audio channel agent,"
+            " this = %p\n", this));
+    return false;
+  }
+
+  return true;
 }
 
 bool
 HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
 {
   // If we have an error, we are not playing.
   if (mError) {
     return false;
@@ -5823,16 +5832,20 @@ HTMLMediaElement::IsPlayingThroughTheAud
 
 void
 HTMLMediaElement::UpdateAudioChannelPlayingState(bool aForcePlaying)
 {
   bool playingThroughTheAudioChannel =
     aForcePlaying || IsPlayingThroughTheAudioChannel();
 
   if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
+    if (!MaybeCreateAudioChannelAgent()) {
+      return;
+    }
+
     mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
     NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
   }
 }
 
 void
 HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
 {
@@ -6033,29 +6046,30 @@ HTMLMediaElement::IsAllowedToPlay()
   if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
       mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) {
     return false;
   }
 
   // If the tab hasn't been activated yet, the media element in that tab can't
   // be playback now until the tab goes to foreground first time or user clicks
   // the unblocking tab icon.
-  if (!IsTabActivated()) {
+  if (MaybeCreateAudioChannelAgent() && !IsTabActivated()) {
     // Even we haven't start playing yet, we still need to notify the audio
     // channe system because we need to receive the resume notification later.
     UpdateAudioChannelPlayingState(true /* force to start */);
     return false;
   }
 
   return true;
 }
 
 bool
 HTMLMediaElement::IsTabActivated() const
 {
+  MOZ_ASSERT(mAudioChannelAgent);
   return !mAudioChannelAgent->ShouldBlockMedia();
 }
 
 static const char* VisibilityString(Visibility aVisibility) {
   switch(aVisibility) {
     case Visibility::UNTRACKED: {
       return "UNTRACKED";
     }
@@ -6457,19 +6471,18 @@ HTMLMediaElement::SetAudibleState(bool a
     NotifyAudioPlaybackChanged(
       AudioChannelService::AudibleChangedReasons::eDataAudibleChanged);
   }
 }
 
 void
 HTMLMediaElement::NotifyAudioPlaybackChanged(AudibleChangedReasons aReason)
 {
-  MOZ_ASSERT(mAudioChannelAgent);
-
-  if (!mAudioChannelAgent->IsPlayingStarted()) {
+  if (MaybeCreateAudioChannelAgent() &&
+      !mAudioChannelAgent->IsPlayingStarted()) {
     return;
   }
 
   if (mAudible == IsAudible()) {
     return;
   }
 
   mAudible = IsAudible();
@@ -6502,16 +6515,17 @@ HTMLMediaElement::MaybeNotifyMediaResume
 {
   // In fennec, we should send the notification when media is resumed from the
   // pause-disposable which was called by media control.
   if (mAudioChannelSuspended != nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE &&
       aSuspend != nsISuspendedTypes::NONE_SUSPENDED) {
     return;
   }
 
+  MOZ_ASSERT(mAudioChannelAgent);
   uint64_t windowID = mAudioChannelAgent->WindowID();
   NS_DispatchToMainThread(NS_NewRunnableFunction([windowID]() -> void {
     nsCOMPtr<nsIObserverService> observerService =
       services::GetObserverService();
     if (NS_WARN_IF(!observerService)) {
       return;
     }
 
@@ -6578,24 +6592,23 @@ HTMLMediaElement::SetMediaInfo(const Med
 {
   mMediaInfo = aInfo;
   AudioCaptureStreamChangeIfNeeded();
 }
 
 void
 HTMLMediaElement::AudioCaptureStreamChangeIfNeeded()
 {
-  MOZ_ASSERT(mAudioChannelAgent);
-
   // No need to capture a silence media element.
   if (!HasAudio()) {
     return;
   }
 
-  if (!mAudioChannelAgent->IsPlayingStarted()) {
+  if (MaybeCreateAudioChannelAgent() &&
+      !mAudioChannelAgent->IsPlayingStarted()) {
     return;
   }
 
   if (mAudioCapturedByWindow && !mCaptureStreamPort) {
     nsCOMPtr<nsPIDOMWindowInner> window = OwnerDoc()->GetInnerWindow();
     if (!OwnerDoc()->GetInnerWindow()) {
       return;
     }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1224,19 +1224,21 @@ protected:
   TextTrackManager* GetOrCreateTextTrackManager();
 
   // Recomputes ready state and fires events as necessary based on current state.
   void UpdateReadyStateInternal();
 
   // Notifies the audio channel agent when the element starts or stops playing.
   void NotifyAudioChannelAgent(bool aPlaying);
 
-  // Creates the audio channel agent in the beginning and this agent would be
-  // used to communicate with the AudioChannelService.
-  void CreateAudioChannelAgent();
+  // True if we create the audio channel agent successfully or we already have
+  // one. The agent is used to communicate with the AudioChannelService. eg.
+  // notify we are playing/audible and receive muted/unmuted/suspend/resume
+  // commands from AudioChannelService.
+  bool MaybeCreateAudioChannelAgent();
 
   // Determine if the element should be paused because of suspend conditions.
   bool ShouldElementBePaused();
 
   // Create or destroy the captured stream depend on mAudioCapturedByWindow.
   void AudioCaptureStreamChangeIfNeeded();
 
   /**