Bug 1180535 - Dispatch the media-playback notification when navigating away from a page that has a media element playing; r=baku

When navigating away from a document, we mute the playing media elements
through the NotifyOwnerDocumentActivityChanged() notification.
Sometimes, that function may notify the audio channel agent through its
call to AddRemoveSelfReference() which may call
UpdateAudioChannelPlayingState() and notify the agent, but when we're
navigating away from the page, playingThroughTheAudioChannel will always
be equal to mPlayingThroughTheAudioChannel, which causes us to not
notify the audio channel agent.

This patch fixes this by separating NotifyOwnerDocumentActivityChanged()
from its internal consumers, and forcefully notifying the audio channel
agent when we navigate away.
This commit is contained in:
Ehsan Akhgari
2015-07-05 18:36:49 -04:00
parent 85d7d26678
commit 1859e2fd6b
5 changed files with 123 additions and 16 deletions

View File

@@ -945,7 +945,7 @@ void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream)
if (videoHasChanged) {
// We are a video element and HasVideo() changed so update the screen
// wakelock
NotifyOwnerDocumentActivityChanged();
NotifyOwnerDocumentActivityChangedInternal();
}
mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal);
@@ -2110,7 +2110,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mPaused.SetOuter(this);
RegisterActivityObserver();
NotifyOwnerDocumentActivityChanged();
NotifyOwnerDocumentActivityChangedInternal();
MOZ_ASSERT(NS_IsMainThread());
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
@@ -2866,7 +2866,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
// We may want to suspend the new stream now.
// This will also do an AddRemoveSelfReference.
NotifyOwnerDocumentActivityChanged();
NotifyOwnerDocumentActivityChangedInternal();
if (!mPaused) {
SetPlayedOrSeeked(true);
@@ -3279,7 +3279,7 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
if (IsVideo() && aInfo->HasVideo()) {
// We are a video element playing video so update the screen wakelock
NotifyOwnerDocumentActivityChanged();
NotifyOwnerDocumentActivityChangedInternal();
}
}
@@ -4036,6 +4036,17 @@ bool HTMLMediaElement::IsBeingDestroyed()
}
void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
{
bool pauseElement = NotifyOwnerDocumentActivityChangedInternal();
if (pauseElement && mAudioChannelAgent) {
// If the element is being paused since we are navigating away from the
// document, notify the audio channel agent.
NotifyAudioChannelAgent(false);
}
}
bool
HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
{
nsIDocument* ownerDoc = OwnerDoc();
if (mDecoder && !IsBeingDestroyed()) {
@@ -4063,6 +4074,8 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
}
AddRemoveSelfReference();
return pauseElement;
}
void HTMLMediaElement::AddRemoveSelfReference()
@@ -4536,19 +4549,25 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
}
// This is needed to pass nsContentUtils::IsCallerChrome().
// AudioChannel API should not called from content but it can happen that
// this method has some content JS in its stack.
AutoNoJSAPI nojsapi;
NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
}
}
if (mPlayingThroughTheAudioChannel) {
int32_t canPlay;
mAudioChannelAgent->StartPlaying(&canPlay);
CanPlayChanged(canPlay);
} else {
mAudioChannelAgent->StopPlaying();
mAudioChannelAgent = nullptr;
}
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// This is needed to pass nsContentUtils::IsCallerChrome().
// AudioChannel API should not called from content but it can happen that
// this method has some content JS in its stack.
AutoNoJSAPI nojsapi;
if (aPlaying) {
int32_t canPlay;
mAudioChannelAgent->StartPlaying(&canPlay);
CanPlayChanged(canPlay);
} else {
mAudioChannelAgent->StopPlaying();
mAudioChannelAgent = nullptr;
}
}