author | Alastor Wu <alwu@mozilla.com> |
Wed, 02 Nov 2016 14:22:24 +0800 | |
changeset 363642 | 4cdb9e2c9595ff669db771964feae1e0242698d6 |
parent 363641 | ddf60739dfd73938346d0146738f38d8802dd226 |
child 363643 | d94c3a6c1ad6785940c861225b6394c9e51ca3d4 |
push id | 6795 |
push user | jlund@mozilla.com |
push date | Mon, 23 Jan 2017 14:19:46 +0000 |
treeherder | mozilla-beta@76101b503191 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jwwang |
bugs | 1302350 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/html/HTMLMediaElement.cpp | file | annotate | diff | comparison | revisions | |
dom/html/HTMLMediaElement.h | file | annotate | diff | comparison | revisions |
--- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -3025,29 +3025,29 @@ void HTMLMediaElement::NotifyXPCOMShutdown() { ShutdownDecoder(); } void HTMLMediaElement::Play(ErrorResult& aRv) { + if (!IsAllowedToPlay()) { + return; + } + nsresult rv = PlayInternal(); if (NS_FAILED(rv)) { aRv.Throw(rv); } } nsresult HTMLMediaElement::PlayInternal() { - if (!IsAllowedToPlay()) { - return NS_OK; - } - // Play was not blocked so assume user interacted with the element. mHasUserInteraction = true; StopSuspendingAfterFirstFrame(); SetPlayedOrSeeked(true); if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) { DoLoad(); @@ -3114,16 +3114,20 @@ HTMLMediaElement::PlayInternal() } } return NS_OK; } NS_IMETHODIMP HTMLMediaElement::Play() { + if (!IsAllowedToPlay()) { + return NS_OK; + } + return PlayInternal(); } HTMLMediaElement::WakeLockBoolWrapper& HTMLMediaElement::WakeLockBoolWrapper::operator=(bool val) { if (mValue == val) { return *this; @@ -4974,16 +4978,20 @@ bool HTMLMediaElement::CanActivateAutopl if (!mPaused) { return false; } if (mPausedForInactiveDocumentOrChannel) { return false; } + if (!IsAllowedToPlay()) { + return false; + } + bool hasData = (mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) || (mSrcStream && mSrcStream->Active()) || mMediaSource; return hasData; } @@ -4999,19 +5007,17 @@ void HTMLMediaElement::CheckAutoplayData UpdateSrcMediaStreamPlaying(); UpdateAudioChannelPlayingState(); if (mDecoder) { SetPlayedOrSeeked(true); if (mCurrentPlayRangeStart == -1.0) { mCurrentPlayRangeStart = CurrentTime(); } - if (!ShouldElementBePaused()) { - mDecoder->Play(); - } + mDecoder->Play(); } else if (mSrcStream) { SetPlayedOrSeeked(true); } // For blocked media, the event would be pending until it is resumed. DispatchAsyncEvent(NS_LITERAL_STRING("play")); DispatchAsyncEvent(NS_LITERAL_STRING("playing")); @@ -5803,19 +5809,20 @@ HTMLMediaElement::IsPlayingThroughTheAud if (mSrcAttrStream) { return true; } return false; } void -HTMLMediaElement::UpdateAudioChannelPlayingState() -{ - bool playingThroughTheAudioChannel = IsPlayingThroughTheAudioChannel(); +HTMLMediaElement::UpdateAudioChannelPlayingState(bool aForcePlaying) +{ + bool playingThroughTheAudioChannel = + aForcePlaying || IsPlayingThroughTheAudioChannel(); if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) { mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel; NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel); } } void @@ -5923,31 +5930,33 @@ HTMLMediaElement::ResumeFromAudioChannel void HTMLMediaElement::ResumeFromAudioChannelPaused(SuspendTypes aSuspend) { MOZ_ASSERT(mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE || mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE); SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED); - nsresult rv = PlayInternal(); + nsresult rv = Play(); if (NS_WARN_IF(NS_FAILED(rv))) { return; } DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend")); } void HTMLMediaElement::ResumeFromAudioChannelBlocked() { MOZ_ASSERT(mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK); SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED); - mPaused = false; - SuspendOrResumeElement(false /* resume */, false); + nsresult rv = Play(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } } void HTMLMediaElement::PauseByAudioChannel(SuspendTypes aSuspend) { if (IsSuspendedByAudioChannel()) { return; } @@ -5960,18 +5969,16 @@ HTMLMediaElement::PauseByAudioChannel(Su void HTMLMediaElement::BlockByAudioChannel() { if (IsSuspendedByAudioChannel()) { return; } SetAudioChannelSuspended(nsISuspendedTypes::SUSPENDED_BLOCK); - mPaused = true; - SuspendOrResumeElement(true /* suspend */, true /* pending event */); } void HTMLMediaElement::SetAudioChannelSuspended(SuspendTypes aSuspend) { if (mAudioChannelSuspended == aSuspend) { return; } @@ -6008,25 +6015,42 @@ HTMLMediaElement::IsAllowedToPlay() static_cast<nsIContent*>(this), NS_LITERAL_STRING("MozAutoplayMediaBlocked"), false, false); #endif return false; } - // The MediaElement can't start playback until it's resumed by audio channel. + // The media element has already been paused or blocked, so it can't start + // playback again by script or user's intend until resuming by audio channel. 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()) { + // 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 +{ + return !mAudioChannelAgent->ShouldBlockMedia(); +} + static const char* VisibilityString(Visibility aVisibility) { switch(aVisibility) { case Visibility::UNTRACKED: { return "UNTRACKED"; } case Visibility::APPROXIMATELY_NONVISIBLE: { return "APPROXIMATELY_NONVISIBLE"; } @@ -6528,21 +6552,16 @@ HTMLMediaElement::OpenUnsupportedMediaWi NS_LITERAL_STRING("OpenMediaWithExternalApp"), true, true); } bool HTMLMediaElement::ShouldElementBePaused() { - // The media in the non-visited page would be blocked. - if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) { - return true; - } - // Bfcached page or inactive document. if (!IsActive()) { return true; } return false; }
--- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -1207,17 +1207,17 @@ protected: // desired, and we'll seek to the sync point (keyframe and/or start of the // next block of audio samples) preceeding seek target. already_AddRefed<Promise> Seek(double aTime, SeekTarget::Type aSeekType, ErrorResult& aRv); // A method to check if we are playing through the AudioChannel. bool IsPlayingThroughTheAudioChannel() const; // Update the audio channel playing state - void UpdateAudioChannelPlayingState(); + void UpdateAudioChannelPlayingState(bool aForcePlaying = false); // Adds to the element's list of pending text tracks each text track // in the element's list of text tracks whose text track mode is not disabled // and whose text track readiness state is loading. void PopulatePendingTextTrackList(); // Gets a reference to the MediaElement's TextTrackManager. If the // MediaElement doesn't yet have one then it will create it. @@ -1264,18 +1264,23 @@ protected: void ResumeFromAudioChannel(); void ResumeFromAudioChannelPaused(SuspendTypes aSuspend); void ResumeFromAudioChannelBlocked(); bool IsSuspendedByAudioChannel() const; void SetAudioChannelSuspended(SuspendTypes aSuspend); + // A method to check whether the media element is allowed to start playback. bool IsAllowedToPlay(); + // True if the tab which media element belongs to has been to foreground at + // least once or activated by manually clicking the unblocking tab icon. + bool IsTabActivated() const; + bool IsAudible() const; bool HaveFailedWithSourceNotSupportedError() const; void OpenUnsupportedMediaWithExtenalAppIfNeeded(); // It's used for fennec only, send the notification when the user resumes the // media which was paused by media control. void MaybeNotifyMediaResumed(SuspendTypes aSuspend);