Bug 1420488 - part1 : bless media if media has started playing before. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 29 Nov 2017 18:59:56 +0800
changeset 705188 b80481d7dcc75d6b147deeba683ed3ddf808accc
parent 704827 d2549af1ec448c83deb3598a09249de7bebceeb6
child 705189 76c2f9fd55e46cd67495935c3e0b1c5791ad93c8
push id91387
push useralwu@mozilla.com
push dateWed, 29 Nov 2017 16:05:23 +0000
bugs1420488
milestone59.0a1
Bug 1420488 - part1 : bless media if media has started playing before. If the media has started playing before, bless it and it would always be allowed to autoplay. MozReview-Commit-ID: 4GqMARLXULU
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/AutoplayPolicy.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1974,22 +1974,22 @@ void HTMLMediaElement::DoLoad()
     LOG(LogLevel::Debug, ("%p Media not allowed", this));
     return;
   }
 
   if (mIsRunningLoadMethod) {
     return;
   }
 
-  // Detect if user has interacted with element so that play will not be
-  // blocked when initiated by a script. This enables sites to capture user
-  // intent to play by calling load() in the click handler of a "catalog
-  // view" of a gallery of videos.
   if (EventStateManager::IsHandlingUserInput()) {
-    mHasUserInteractedLoadOrSeek = true;
+    // Detect if user has interacted with element so that play will not be
+    // blocked when initiated by a script. This enables sites to capture user
+    // intent to play by calling load() in the click handler of a "catalog
+    // view" of a gallery of videos.
+    mIsBlessed = true;
     // Mark the channel as urgent-start when autopaly so that it will play the
     // media from src after loading enough resource.
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) {
       mUseUrgentStartForChannel = true;
     }
   }
 
   SetPlayedOrSeeked(false);
@@ -2752,17 +2752,17 @@ HTMLMediaElement::Seek(double aTime,
 
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   // Detect if user has interacted with element by seeking so that
   // play will not be blocked when initiated by a script.
   if (EventStateManager::IsHandlingUserInput()) {
-    mHasUserInteractedLoadOrSeek = true;
+    mIsBlessed = true;
   }
 
   StopSuspendingAfterFirstFrame();
 
   if (mSrcStream) {
     // do nothing since media streams have an empty Seekable range.
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
@@ -4038,17 +4038,16 @@ HTMLMediaElement::HTMLMediaElement(alrea
     mShuttingDown(false),
     mSuspendedForPreloadNone(false),
     mSrcStreamIsPlaying(false),
     mMediaSecurityVerified(false),
     mCORSMode(CORS_NONE),
     mIsEncrypted(false),
     mWaitingForKey(NOT_WAITING_FOR_KEY),
     mDisableVideo(false),
-    mHasUserInteractedLoadOrSeek(false),
     mFirstFrameLoaded(false),
     mDefaultPlaybackStartPosition(0.0),
     mHasSuspendTaint(false),
     mMediaTracksConstructed(false),
     mVisibilityState(Visibility::UNTRACKED),
     mErrorSink(new ErrorSink(this)),
     mAudioChannelWrapper(new AudioChannelAgentCallback(this))
 {
@@ -4281,16 +4280,19 @@ HTMLMediaElement::PlayInternal(ErrorResu
   mAutoplaying = false;
 
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   // and our preload status.
   AddRemoveSelfReference();
   UpdatePreloadAction();
   UpdateSrcMediaStreamPlaying();
 
+  // once media start playing, we would always allow it to autoplay
+  mIsBlessed = true;
+
   // TODO: If the playback has ended, then the user agent must set
   // seek to the effective start.
 
   // 4.8.12.8 - Step 6:
   // If the media element's paused attribute is true, run the following steps:
   if (oldPaused) {
     // 6.1. Change the value of paused to false. (Already done.)
     // This step is uplifted because the "block-media-playback" feature needs
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -736,21 +736,19 @@ public:
   void NotifyCueUpdated(TextTrackCue *aCue) {
     if (mTextTrackManager) {
       mTextTrackManager->NotifyCueUpdated(aCue);
     }
   }
 
   void NotifyCueDisplayStatesChanged();
 
-  bool GetAndClearHasUserInteractedLoadOrSeek()
+  bool IsBlessed() const
   {
-    bool result = mHasUserInteractedLoadOrSeek;
-    mHasUserInteractedLoadOrSeek = false;
-    return result;
+    return mIsBlessed;
   }
 
   // A method to check whether we are currently playing.
   bool IsCurrentlyPlaying() const;
 
   // Returns true if the media element is being destroyed. Used in
   // dormancy checks to prevent dormant processing for an element
   // that will soon be gone.
@@ -1780,19 +1778,19 @@ private:
   TimeDurationAccumulator mPlayTime;
 
   // Total time a video has spent playing while hidden.
   TimeDurationAccumulator mHiddenPlayTime;
 
   // Total time a video has (or would have) spent in video-decode-suspend mode.
   TimeDurationAccumulator mVideoDecodeSuspendTime;
 
-  // True if user has called load() or seek() via user input.
+  // True if user has called load(), seek() or element has started playing before.
   // It's *only* use for checking autoplay policy
-  bool mHasUserInteractedLoadOrSeek;
+  bool mIsBlessed = false;
 
   // True if the first frame has been successfully loaded.
   bool mFirstFrameLoaded;
 
   // Media elements also have a default playback start position, which must
   // initially be set to zero seconds. This time is used to allow the element to
   // be seeked even before the media is loaded.
   double mDefaultPlaybackStartPosition;
--- a/dom/media/AutoplayPolicy.cpp
+++ b/dom/media/AutoplayPolicy.cpp
@@ -33,16 +33,15 @@ AutoplayPolicy::IsMediaElementAllowedToP
   }
 
   if (Preferences::GetBool("media.autoplay.enabled.user-gestures-needed")) {
     return AutoplayPolicy::IsDocumentAllowedToPlay(aElement->OwnerDoc());
   }
 
   // TODO : this old way would be removed when user-gestures-needed becomes
   // as a default option to block autoplay.
-  // If user triggers load() or seek() before play(), we would also allow the
-  // following play().
-  return aElement->GetAndClearHasUserInteractedLoadOrSeek() ||
+  // If elelement is blessed, it would always be allowed to play().
+  return aElement->IsBlessed() ||
          EventStateManager::IsHandlingUserInput();
 }
 
 } // namespace dom
 } // namespace mozilla
\ No newline at end of file