зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
cc1bfa080c
Коммит
59e89cba9d
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<audio src="audio.ogg" autoplay="true" loop>
|
|
@ -237,6 +237,7 @@ support-files =
|
|||
referrerHelper.js
|
||||
test_performance_user_timing.js
|
||||
img_referrer_testserver.sjs
|
||||
file_audioLoop.html
|
||||
file_webaudioLoop.html
|
||||
file_webaudioLoop2.html
|
||||
|
||||
|
@ -248,6 +249,8 @@ support-files =
|
|||
[test_audioWindowUtils.html]
|
||||
[test_audioNotification.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationStopOnNavigation.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_bug1091883.html]
|
||||
[test_bug116083.html]
|
||||
[test_bug793311.html]
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for audio controller in windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<iframe></iframe>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var expectedNotification = null;
|
||||
var iframe = null;
|
||||
|
||||
var observer = {
|
||||
observe: function(subject, topic, data) {
|
||||
is(topic, "media-playback", "media-playback received");
|
||||
is(data, expectedNotification, "This is the right notification");
|
||||
runTest();
|
||||
}
|
||||
};
|
||||
|
||||
var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
iframe = document.querySelector("iframe");
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.addObserver(observer, "media-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
},
|
||||
|
||||
function() {
|
||||
expectedNotification = 'active';
|
||||
iframe.src = "file_audioLoop.html";
|
||||
},
|
||||
|
||||
function() {
|
||||
expectedNotification = 'inactive';
|
||||
iframe.src = "data:text/html,page without audio";
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.removeObserver(observer, "media-playback");
|
||||
ok(true, "Observer removed");
|
||||
runTest();
|
||||
}
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
onload = runTest;
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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);
|
||||
|
@ -2101,7 +2101,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
mPaused.SetOuter(this);
|
||||
|
||||
RegisterActivityObserver();
|
||||
NotifyOwnerDocumentActivityChanged();
|
||||
NotifyOwnerDocumentActivityChangedInternal();
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mWatchManager.Watch(mDownloadSuspendedByCache, &HTMLMediaElement::UpdateReadyStateInternal);
|
||||
|
@ -2857,7 +2857,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);
|
||||
|
@ -3270,7 +3270,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4027,6 +4027,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()) {
|
||||
|
@ -4047,6 +4058,8 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
|||
}
|
||||
|
||||
AddRemoveSelfReference();
|
||||
|
||||
return pauseElement;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::AddRemoveSelfReference()
|
||||
|
@ -4510,12 +4523,19 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
|||
this);
|
||||
}
|
||||
|
||||
NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
|
||||
}
|
||||
}
|
||||
|
||||
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 (mPlayingThroughTheAudioChannel) {
|
||||
if (aPlaying) {
|
||||
float volume = 0.0;
|
||||
bool muted = true;
|
||||
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
|
||||
|
@ -4525,7 +4545,6 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
|
|||
mAudioChannelAgent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
{
|
||||
|
|
|
@ -150,7 +150,12 @@ public:
|
|||
* Call this to reevaluate whether we should start/stop due to our owner
|
||||
* document being active, inactive, visible or hidden.
|
||||
*/
|
||||
virtual void NotifyOwnerDocumentActivityChanged();
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
// This method does the work necessary for the
|
||||
// NotifyOwnerDocumentActivityChanged() notification. It returns true if the
|
||||
// media element was paused as a result.
|
||||
virtual bool NotifyOwnerDocumentActivityChangedInternal();
|
||||
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// when it has read the metadata containing video dimensions,
|
||||
|
@ -1031,6 +1036,9 @@ protected:
|
|||
// Recomputes ready state and fires events as necessary based on current state.
|
||||
void UpdateReadyStateInternal();
|
||||
|
||||
// Notifies the audio channel agent when the element starts or stops playing.
|
||||
void NotifyAudioChannelAgent(bool aPlaying);
|
||||
|
||||
class nsAsyncEventRunner;
|
||||
using nsGenericHTMLElement::DispatchEvent;
|
||||
// For nsAsyncEventRunner.
|
||||
|
|
|
@ -192,11 +192,12 @@ HTMLVideoElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
return HTMLVideoElementBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLVideoElement::NotifyOwnerDocumentActivityChanged()
|
||||
bool
|
||||
HTMLVideoElement::NotifyOwnerDocumentActivityChangedInternal()
|
||||
{
|
||||
HTMLMediaElement::NotifyOwnerDocumentActivityChanged();
|
||||
bool pauseElement = HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal();
|
||||
UpdateScreenWakeLock();
|
||||
return pauseElement;
|
||||
}
|
||||
|
||||
already_AddRefed<VideoPlaybackQuality>
|
||||
|
|
|
@ -105,7 +105,7 @@ public:
|
|||
|
||||
bool MozHasAudio() const;
|
||||
|
||||
void NotifyOwnerDocumentActivityChanged() override;
|
||||
bool NotifyOwnerDocumentActivityChangedInternal() override;
|
||||
|
||||
already_AddRefed<VideoPlaybackQuality> GetVideoPlaybackQuality();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче