Bug 1244768 part 9 - distinguish the "element is not allowd to play" and "element is blocked" cases; r?jwwang, alwu draft
authorKaku Kuo <kaku@mozilla.com>
Thu, 08 Sep 2016 16:08:40 +0800
changeset 411716 bba3f2404fda5d892222629cdc2d0b6e8041e20f
parent 411715 7b00c027ee6e7b85dcc65bb4e304f048aa85a944
child 411717 71bf7c65e26b8d1af9a61084e9af75f46d438171
push id28959
push userbmo:kaku@mozilla.com
push dateThu, 08 Sep 2016 14:11:14 +0000
reviewersjwwang, alwu
bugs1244768
milestone51.0a1
Bug 1244768 part 9 - distinguish the "element is not allowd to play" and "element is blocked" cases; r?jwwang, alwu Element is not allowd to play means that we cancel play operation and won't resume it. Element is blocked means that we suspend the play operation and will resume it later. MozReview-Commit-ID: BMAFGMcOpqu
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3116,17 +3116,17 @@ HTMLMediaElement::Play(ErrorResult& aRv)
   return PlayInternal(aRv);
 }
 
 void
 HTMLMediaElement::PlayInternal(ErrorResult& aRv)
 {
   MOZ_ASSERT(!aRv.Failed());
 
-  if (!IsAllowedToPlay()) {
+  if (!IsPlayOperationAllowed()) {
     return;
   }
 
   // Play was not blocked so assume user interacted with the element.
   mHasUserInteraction = true;
 
   StopSuspendingAfterFirstFrame();
   SetPlayedOrSeeked(true);
@@ -3152,16 +3152,21 @@ HTMLMediaElement::PlayInternal(ErrorResu
       }
     }
   }
 
   if (mCurrentPlayRangeStart == -1.0) {
     mCurrentPlayRangeStart = CurrentTime();
   }
 
+  // Check if the element is now blocked.
+  if (IsPlayOperationBlocked()) {
+    return;
+  }
+
   bool oldPaused = mPaused;
   mPaused = false;
   mAutoplaying = false;
   SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED);
 
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   // and our preload status.
   AddRemoveSelfReference();
@@ -6085,18 +6090,20 @@ HTMLMediaElement::SetAudioChannelSuspend
 bool
 HTMLMediaElement::IsSuspendedByAudioChannel() const
 {
   return (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
           mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
           mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK);
 }
 
+// This method enumerates situations that play operation should be canceled
+// directly and won't be resumed later.
 bool
-HTMLMediaElement::IsAllowedToPlay()
+HTMLMediaElement::IsPlayOperationAllowed() const
 {
   // Prevent media element from being auto-started by a script when
   // media.autoplay.enabled=false
   if (!mHasUserInteraction &&
       !IsAutoplayEnabled() &&
       !EventStateManager::IsHandlingUserInput() &&
       !nsContentUtils::IsCallerChrome()) {
 #if defined(MOZ_WIDGET_ANDROID)
@@ -6105,24 +6112,31 @@ HTMLMediaElement::IsAllowedToPlay()
                                          NS_LITERAL_STRING("MozAutoplayMediaBlocked"),
                                          false,
                                          false);
 #endif
     return false;
   }
 
   // The MediaElement can't start playback until it's resumed by audio channel.
-  if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
-      mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) {
+  if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE) {
     return false;
   }
 
   return true;
 }
 
+// This method enumerates situations that play operation is suspended and will
+// be resumed automatically later.
+bool
+HTMLMediaElement::IsPlayOperationBlocked() const
+{
+  return mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK;
+}
+
 #ifdef MOZ_EME
 MediaKeys*
 HTMLMediaElement::GetMediaKeys() const
 {
   return mMediaKeys;
 }
 
 bool
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1251,17 +1251,25 @@ protected:
 
   void ResumeFromAudioChannel();
   void ResumeFromAudioChannelPaused(SuspendTypes aSuspend);
   void ResumeFromAudioChannelBlocked();
 
   bool IsSuspendedByAudioChannel() const;
   void SetAudioChannelSuspended(SuspendTypes aSuspend);
 
-  bool IsAllowedToPlay();
+  /*
+   * If IsPlayOperationAllowed() returns false, we cancel the play operation and
+   * won't resume it later.
+   *
+   * If IsPlayOperationBlocked() returns true, we make the play operation
+   * pending for now and will resume it later.
+   */
+  bool IsPlayOperationAllowed() const;
+  bool IsPlayOperationBlocked() const;
 
   bool IsAudible() const;
   bool HaveFailedWithSourceNotSupportedError() const;
 
   void OpenUnsupportedMediaWithExtenalAppIfNeeded();
 
   class nsAsyncEventRunner;
   class nsNotifyAboutPlayingRunner;