Bug 1180563 - Add pref to delay play of <video>s until they're visible. r=kinetik

This commit is contained in:
Chris Pearce 2015-07-09 11:10:16 +12:00
parent 295e380150
commit ee36a23455
3 changed files with 56 additions and 16 deletions

View File

@ -2095,6 +2095,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mAudioChannelFaded(false),
mPlayingThroughTheAudioChannel(false),
mDisableVideo(false),
mPlayBlockedBecauseHidden(false),
mElementInTreeState(ELEMENT_NOT_INTREE)
{
if (!gMediaElementLog) {
@ -2224,6 +2225,15 @@ HTMLMediaElement::Play(ErrorResult& aRv)
if (mSuspendedForPreloadNone) {
ResumeLoad(PRELOAD_ENOUGH);
}
if (Preferences::GetBool("media.block-play-until-visible", false) &&
!nsContentUtils::IsCallerChrome() &&
OwnerDoc()->Hidden()) {
LOG(LogLevel::Debug, ("%p Blocked playback because owner hidden.", this));
mPlayBlockedBecauseHidden = true;
return;
}
// Even if we just did Load() or ResumeLoad(), we could already have a decoder
// here if we managed to clone an existing decoder.
if (mDecoder) {
@ -3752,23 +3762,33 @@ bool HTMLMediaElement::CanActivateAutoplay()
void HTMLMediaElement::CheckAutoplayDataReady()
{
if (CanActivateAutoplay()) {
mPaused = false;
// We changed mPaused which can affect AddRemoveSelfReference
AddRemoveSelfReference();
if (mDecoder) {
SetPlayedOrSeeked(true);
if (mCurrentPlayRangeStart == -1.0) {
mCurrentPlayRangeStart = CurrentTime();
}
mDecoder->Play();
} else if (mSrcStream) {
SetPlayedOrSeeked(true);
GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
}
DispatchAsyncEvent(NS_LITERAL_STRING("play"));
if (!CanActivateAutoplay()) {
return;
}
if (Preferences::GetBool("media.block-play-until-visible", false) &&
OwnerDoc()->Hidden()) {
LOG(LogLevel::Debug, ("%p Blocked autoplay because owner hidden.", this));
mPlayBlockedBecauseHidden = true;
return;
}
mPaused = false;
// We changed mPaused which can affect AddRemoveSelfReference
AddRemoveSelfReference();
if (mDecoder) {
SetPlayedOrSeeked(true);
if (mCurrentPlayRangeStart == -1.0) {
mCurrentPlayRangeStart = CurrentTime();
}
mDecoder->Play();
} else if (mSrcStream) {
SetPlayedOrSeeked(true);
GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
}
DispatchAsyncEvent(NS_LITERAL_STRING("play"));
}
bool HTMLMediaElement::IsActive()
@ -3950,6 +3970,9 @@ void HTMLMediaElement::UpdateInitialMediaSize(const nsIntSize& aSize)
void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)
{
LOG(LogLevel::Debug, ("%p SuspendOrResumeElement(pause=%d, suspendEvents=%d) hidden=%d",
this, aPauseElement, aSuspendEvents, OwnerDoc()->Hidden()));
if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
mPausedForInactiveDocumentOrChannel = aPauseElement;
if (aPauseElement) {
@ -4031,6 +4054,14 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
SuspendOrResumeElement(pauseElement, !IsActive());
if (!mPausedForInactiveDocumentOrChannel &&
mPlayBlockedBecauseHidden &&
!OwnerDoc()->Hidden()) {
LOG(LogLevel::Debug, ("%p Resuming playback now that owner doc is visble.", this));
mPlayBlockedBecauseHidden = false;
Play();
}
AddRemoveSelfReference();
}

View File

@ -1374,6 +1374,11 @@ protected:
// playback.
bool mDisableVideo;
// True if we blocked either a play() call or autoplay because the
// media's owner doc was not visible. Only enforced when the pref
// media.block-play-until-visible=true.
bool mPlayBlockedBecauseHidden;
// An agent used to join audio channel service.
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;

View File

@ -276,6 +276,10 @@ pref("media.wakelock_timeout", 2000);
// opened as top-level documents, as opposed to inside a media element.
pref("media.play-stand-alone", true);
// Whether we should delay actioning a "play()" JS function call and autoplay
// attribute until the media element's owner document is visible.
pref("media.block-play-until-visible", false);
pref("media.hardware-video-decoding.enabled", true);
pref("media.decoder.heuristic.dormant.enabled", true);