Bug 1625615 - part2 : suspend or resume media element according to docShell's SuspendMediaWhenInactive r=bryce

If docShell's `SuspendMediaWhenInactive` is true, then we should suspend or resume the media element according to the docshell active state when the docshell changes it active state.

Differential Revision: https://phabricator.services.mozilla.com/D69671
This commit is contained in:
alwu
2020-04-20 21:19:56 +00:00
parent dab94fd1fa
commit 3d49e8b2f8
2 changed files with 32 additions and 13 deletions

View File

@@ -4304,7 +4304,7 @@ void HTMLMediaElement::PlayInternal(bool aHandlingUserInput) {
if (mDecoder->IsEnded()) { if (mDecoder->IsEnded()) {
SetCurrentTime(0); SetCurrentTime(0);
} }
if (!mSuspendedForInactiveDocument) { if (!mSuspendedByInactiveDocOrDocshell) {
mDecoder->Play(); mDecoder->Play();
} }
} }
@@ -5048,13 +5048,13 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (mSuspendedForInactiveDocument) { if (mSuspendedByInactiveDocOrDocshell) {
mDecoder->Suspend(); mDecoder->Suspend();
} }
if (!mPaused) { if (!mPaused) {
SetPlayedOrSeeked(true); SetPlayedOrSeeked(true);
if (!mSuspendedForInactiveDocument) { if (!mSuspendedByInactiveDocOrDocshell) {
mDecoder->Play(); mDecoder->Play();
} }
} }
@@ -5070,7 +5070,7 @@ void HTMLMediaElement::UpdateSrcMediaStreamPlaying(uint32_t aFlags) {
} }
bool shouldPlay = !(aFlags & REMOVING_SRC_STREAM) && !mPaused && bool shouldPlay = !(aFlags & REMOVING_SRC_STREAM) && !mPaused &&
!mSuspendedForInactiveDocument; !mSuspendedByInactiveDocOrDocshell;
if (shouldPlay == mSrcStreamIsPlaying) { if (shouldPlay == mSrcStreamIsPlaying) {
return; return;
} }
@@ -5944,7 +5944,7 @@ void HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) {
if (oldState < HAVE_FUTURE_DATA && mReadyState >= HAVE_FUTURE_DATA) { if (oldState < HAVE_FUTURE_DATA && mReadyState >= HAVE_FUTURE_DATA) {
DispatchAsyncEvent(NS_LITERAL_STRING("canplay")); DispatchAsyncEvent(NS_LITERAL_STRING("canplay"));
if (!mPaused) { if (!mPaused) {
if (mDecoder && !mSuspendedForInactiveDocument) { if (mDecoder && !mSuspendedByInactiveDocOrDocshell) {
MOZ_ASSERT(AutoplayPolicy::IsAllowedToPlay(*this)); MOZ_ASSERT(AutoplayPolicy::IsAllowedToPlay(*this));
mDecoder->Play(); mDecoder->Play();
} }
@@ -6019,7 +6019,7 @@ bool HTMLMediaElement::CanActivateAutoplay() {
return false; return false;
} }
if (mSuspendedForInactiveDocument) { if (mSuspendedByInactiveDocOrDocshell) {
return false; return false;
} }
@@ -6063,7 +6063,7 @@ void HTMLMediaElement::CheckAutoplayDataReady() {
if (mCurrentPlayRangeStart == -1.0) { if (mCurrentPlayRangeStart == -1.0) {
mCurrentPlayRangeStart = CurrentTime(); mCurrentPlayRangeStart = CurrentTime();
} }
MOZ_ASSERT(!mSuspendedForInactiveDocument); MOZ_ASSERT(!mSuspendedByInactiveDocOrDocshell);
mDecoder->Play(); mDecoder->Play();
} else if (mSrcStream) { } else if (mSrcStream) {
SetPlayedOrSeeked(true); SetPlayedOrSeeked(true);
@@ -6362,11 +6362,11 @@ void HTMLMediaElement::UpdateMediaSize(const nsIntSize& aSize) {
void HTMLMediaElement::SuspendOrResumeElement(bool aSuspendElement) { void HTMLMediaElement::SuspendOrResumeElement(bool aSuspendElement) {
LOG(LogLevel::Debug, ("%p SuspendOrResumeElement(suspend=%d) hidden=%d", this, LOG(LogLevel::Debug, ("%p SuspendOrResumeElement(suspend=%d) hidden=%d", this,
aSuspendElement, OwnerDoc()->Hidden())); aSuspendElement, OwnerDoc()->Hidden()));
if (aSuspendElement == mSuspendedForInactiveDocument) { if (aSuspendElement == mSuspendedByInactiveDocOrDocshell) {
return; return;
} }
mSuspendedForInactiveDocument = aSuspendElement; mSuspendedByInactiveDocOrDocshell = aSuspendElement;
UpdateSrcMediaStreamPlaying(); UpdateSrcMediaStreamPlaying();
UpdateAudioChannelPlayingState(); UpdateAudioChannelPlayingState();
@@ -6432,6 +6432,16 @@ bool HTMLMediaElement::IsBeingDestroyed() {
return isBeingDestroyed; return isBeingDestroyed;
} }
bool HTMLMediaElement::ShouldBeSuspendedByInactiveDocShell() const {
nsIDocShell* docShell = OwnerDoc()->GetDocShell();
if (!docShell) {
return false;
}
bool isDocShellActive = false;
docShell->GetIsActive(&isDocShellActive);
return !isDocShellActive && docShell->GetSuspendMediaWhenInactive();
}
void HTMLMediaElement::NotifyOwnerDocumentActivityChanged() { void HTMLMediaElement::NotifyOwnerDocumentActivityChanged() {
bool visible = !IsHidden(); bool visible = !IsHidden();
if (visible) { if (visible) {
@@ -6446,7 +6456,11 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged() {
NotifyDecoderActivityChanges(); NotifyDecoderActivityChanges();
} }
SuspendOrResumeElement(!IsActive()); // We would suspend media when the document is inactive, or its docshell has
// been set to hidden and explicitly wants to suspend media. In those cases,
// the media would be not visible and we don't want them to continue playing.
bool shouldSuspend = !IsActive() || ShouldBeSuspendedByInactiveDocShell();
SuspendOrResumeElement(shouldSuspend);
// If the owning document has become inactive we should shutdown the CDM. // If the owning document has become inactive we should shutdown the CDM.
if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) { if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) {

View File

@@ -1625,10 +1625,11 @@ class HTMLMediaElement : public nsGenericHTMLElement,
// to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification. // to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification.
bool mPlayingBeforeSeek = false; bool mPlayingBeforeSeek = false;
// True if this element is suspended because the document is inactive. // True if this element is suspended because the document is inactive or the
bool mSuspendedForInactiveDocument = false; // inactive docshell is not allowing media to play.
bool mSuspendedByInactiveDocOrDocshell = false;
// True if event delivery is suspended (mSuspendedForInactiveDocument // True if event delivery is suspended (mSuspendedByInactiveDocOrDocshell
// must also be true). // must also be true).
bool mEventDeliveryPaused = false; bool mEventDeliveryPaused = false;
@@ -1898,6 +1899,10 @@ class HTMLMediaElement : public nsGenericHTMLElement,
// AsyncRejectSeekDOMPromiseIfExists() methods. // AsyncRejectSeekDOMPromiseIfExists() methods.
RefPtr<dom::Promise> mSeekDOMPromise; RefPtr<dom::Promise> mSeekDOMPromise;
// Return true if the docshell is inactive and explicitly wants to stop media
// playing in that shell.
bool ShouldBeSuspendedByInactiveDocShell() const;
// For debugging bug 1407148. // For debugging bug 1407148.
void AssertReadyStateIsNothing(); void AssertReadyStateIsNothing();