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:
Alastor Wu
2016-11-02 14:22:24 +08:00
parent 99c5935e3b
commit 01a17b2a49
2 changed files with 45 additions and 21 deletions

View File

@@ -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;