Bug 1302350 - part4 : refactor the media-blocking mechanism. r=jwwang
The old way is to start playing first, and then block the media element. This way is too complicated because it involves lots of interal state and isn't intuitive. The new way is to ignore the play if the media element should be blocked. It's easy to know and we doesn't need to keep any internal states because we don't play the media element. MozReview-Commit-ID: B20e0pvXES4
This commit is contained in:
@@ -3030,6 +3030,10 @@ HTMLMediaElement::NotifyXPCOMShutdown()
|
||||
void
|
||||
HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAllowedToPlay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = PlayInternal();
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
@@ -3039,10 +3043,6 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
nsresult
|
||||
HTMLMediaElement::PlayInternal()
|
||||
{
|
||||
if (!IsAllowedToPlay()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Play was not blocked so assume user interacted with the element.
|
||||
mHasUserInteraction = true;
|
||||
|
||||
@@ -3119,6 +3119,10 @@ HTMLMediaElement::PlayInternal()
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
{
|
||||
if (!IsAllowedToPlay()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return PlayInternal();
|
||||
}
|
||||
|
||||
@@ -4979,6 +4983,10 @@ bool HTMLMediaElement::CanActivateAutoplay()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsAllowedToPlay()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasData =
|
||||
(mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
|
||||
(mSrcStream && mSrcStream->Active()) ||
|
||||
@@ -5004,9 +5012,7 @@ void HTMLMediaElement::CheckAutoplayDataReady()
|
||||
if (mCurrentPlayRangeStart == -1.0) {
|
||||
mCurrentPlayRangeStart = CurrentTime();
|
||||
}
|
||||
if (!ShouldElementBePaused()) {
|
||||
mDecoder->Play();
|
||||
}
|
||||
mDecoder->Play();
|
||||
} else if (mSrcStream) {
|
||||
SetPlayedOrSeeked(true);
|
||||
}
|
||||
@@ -5808,9 +5814,10 @@ HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::UpdateAudioChannelPlayingState()
|
||||
HTMLMediaElement::UpdateAudioChannelPlayingState(bool aForcePlaying)
|
||||
{
|
||||
bool playingThroughTheAudioChannel = IsPlayingThroughTheAudioChannel();
|
||||
bool playingThroughTheAudioChannel =
|
||||
aForcePlaying || IsPlayingThroughTheAudioChannel();
|
||||
|
||||
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
|
||||
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
|
||||
@@ -5928,7 +5935,7 @@ HTMLMediaElement::ResumeFromAudioChannelPaused(SuspendTypes aSuspend)
|
||||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE);
|
||||
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED);
|
||||
nsresult rv = PlayInternal();
|
||||
nsresult rv = Play();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@@ -5941,8 +5948,10 @@ 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
|
||||
@@ -5965,8 +5974,6 @@ HTMLMediaElement::BlockByAudioChannel()
|
||||
}
|
||||
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::SUSPENDED_BLOCK);
|
||||
mPaused = true;
|
||||
SuspendOrResumeElement(true /* suspend */, true /* pending event */);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -6013,15 +6020,32 @@ HTMLMediaElement::IsAllowedToPlay()
|
||||
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: {
|
||||
@@ -6533,11 +6557,6 @@ HTMLMediaElement::OpenUnsupportedMediaWithExtenalAppIfNeeded()
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user