Skip to content

Commit 93a7e4a

Browse files
committed
Media element volume changing from 0 to >0 does not activate audio session
rdar://161691743 https://bugs.webkit.org/show_bug.cgi?id=303946 Reviewed by Andy Estes. Changing the volume of a media element does not trigger a call to the PlatformMediaSession's canProduceAudioChanged() method. Because all call sites that update canProduceAudioChanged() should also update the sleep disabler, make a new private convenience method on HTMLMediaElement that does both. Tests: media/volume-activate-audio-session.html media/volume-sleep-disable.html * LayoutTests/media/volume-activate-audio-session-expected.txt: Added. * LayoutTests/media/volume-activate-audio-session.html: Added. * LayoutTests/media/volume-sleep-disable-expected.txt: Added. * LayoutTests/media/volume-sleep-disable.html: Added. * Source/WebCore/html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::didFinishInsertingNode): (WebCore::HTMLMediaElement::loadResource): (WebCore::HTMLMediaElement::setVolume): (WebCore::HTMLMediaElement::setMutedInternal): (WebCore::HTMLMediaElement::checkForAudioAndVideo): (WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget): (WebCore::HTMLMediaElement::canProduceAudioChanged): * Source/WebCore/html/HTMLMediaElement.h: Canonical link: https://commits.webkit.org/304297@main
1 parent 30ee8b0 commit 93a7e4a

File tree

8 files changed

+107
-7
lines changed

8 files changed

+107
-7
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
EXPECTED (internals.audioSessionActive() == 'false') OK
3+
RUN(video.volume = 0)
4+
RUN(video.src = findMediaFile("audio", "content/silence"))
5+
RUN(video.play())
6+
EXPECTED (internals.audioSessionActive() == 'false') OK
7+
RUN(video.volume = 1)
8+
EXPECTED (internals.audioSessionActive() == 'true') OK
9+
END OF TEST
10+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>volume-active-audio-session</title>
7+
<script src="video-test.js"></script>
8+
<script src="media-file.js"></script>
9+
<script>
10+
async function runTest() {
11+
testExpected('internals.audioSessionActive()', false);
12+
findMediaElement();
13+
run('video.volume = 0');
14+
run('video.src = findMediaFile("audio", "content/silence")');
15+
await run('video.play()');
16+
testExpected('internals.audioSessionActive()', false);
17+
run('video.volume = 1');
18+
await testExpectedEventually('internals.audioSessionActive()', true, '==', 1000);
19+
}
20+
21+
window.addEventListener('load', event => {
22+
runTest().then(endTest).catch(failTest);
23+
})
24+
</script>
25+
</head>
26+
<body>
27+
<video controls playsinline loop></video>
28+
</body>
29+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
RUN(video.volume = 0)
3+
RUN(video.src = findMediaFile("video", "content/test-25fps"))
4+
RUN(video.play())
5+
EXPECTED (internals.elementIsBlockingDisplaySleep(video) == 'false') OK
6+
RUN(video.volume = 1)
7+
EXPECTED (internals.elementIsBlockingDisplaySleep(video) == 'true') OK
8+
END OF TEST
9+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>volume-active-audio-session</title>
7+
<script src="video-test.js"></script>
8+
<script src="media-file.js"></script>
9+
<script>
10+
async function runTest() {
11+
findMediaElement();
12+
run('video.volume = 0');
13+
run('video.src = findMediaFile("video", "content/test-25fps")');
14+
await run('video.play()');
15+
testExpected('internals.elementIsBlockingDisplaySleep(video)', false);
16+
run('video.volume = 1');
17+
await testExpectedEventually('internals.elementIsBlockingDisplaySleep(video)', true, '==', 1000);
18+
}
19+
20+
window.addEventListener('load', event => {
21+
runTest().then(endTest).catch(failTest);
22+
})
23+
</script>
24+
</head>
25+
<body>
26+
<video controls playsinline></video>
27+
</body>
28+
</html>

LayoutTests/platform/glib/TestExpectations

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4850,6 +4850,9 @@ webkit.org/b/303863 imported/w3c/web-platform-tests/css/css-view-transitions/tra
48504850
webkit.org/b/303865 imported/w3c/web-platform-tests/css/css-overflow/scrollbar-gutter-fixedpos-003.html [ Pass ImageOnlyFailure ]
48514851
webkit.org/b/303873 imported/w3c/web-platform-tests/trusted-types/navigate-to-javascript-url-csp-headers.html [ Pass Failure ]
48524852

4853+
# No USE(AUDIO_SESSION) support:
4854+
media/volume-activate-audio-session.html [ Skip ]
4855+
48534856
# End: Common failures between GTK and WPE.
48544857

48554858
#////////////////////////////////////////////////////////////////////////////////////////
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
EXPECTED (internals.audioSessionActive() == 'false') OK
3+
RUN(video.volume = 0)
4+
RUN(video.src = findMediaFile("audio", "content/silence"))
5+
RUN(video.play())
6+
EXPECTED (internals.audioSessionActive() == 'false'), OBSERVED 'true' FAIL
7+
RUN(video.volume = 1)
8+
EXPECTED (internals.audioSessionActive() == 'true') OK
9+
END OF TEST
10+

Source/WebCore/html/HTMLMediaElement.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ void HTMLMediaElement::didFinishInsertingNode()
11261126
if (!m_explicitlyMuted) {
11271127
m_explicitlyMuted = true;
11281128
m_muted = hasAttributeWithoutSynchronization(mutedAttr);
1129-
protectedMediaSession()->canProduceAudioChanged();
1129+
canProduceAudioChanged();
11301130
}
11311131

11321132
configureMediaControls();
@@ -1933,7 +1933,7 @@ void HTMLMediaElement::loadResource(const URL& initialURL, const ContentType& in
19331933
if (!m_explicitlyMuted) {
19341934
m_explicitlyMuted = true;
19351935
m_muted = hasAttributeWithoutSynchronization(mutedAttr);
1936-
protectedMediaSession()->canProduceAudioChanged();
1936+
canProduceAudioChanged();
19371937
}
19381938

19391939
updateVolume();
@@ -4735,17 +4735,23 @@ ExceptionOr<void> HTMLMediaElement::setVolume(double volume)
47354735
pauseInternal();
47364736
setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
47374737
}
4738+
4739+
canProduceAudioChanged();
4740+
47384741
return { };
47394742
}
47404743

47414744
auto oldVolume = m_volume;
47424745
m_volume = volume;
47434746

4747+
canProduceAudioChanged();
4748+
47444749
if (m_volumeRevertTaskCancellationGroup.hasPendingTask())
47454750
return { };
47464751

47474752
queueCancellableTaskKeepingObjectAlive(*this, TaskSource::MediaElement, m_volumeRevertTaskCancellationGroup, [oldVolume](auto& element) {
47484753
element.m_volume = oldVolume;
4754+
element.canProduceAudioChanged();
47494755
});
47504756

47514757
return { };
@@ -4805,8 +4811,7 @@ void HTMLMediaElement::setMutedInternal(bool muted, ForceMuteChange forceChange)
48054811
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
48064812
scheduleUpdateMediaState();
48074813
#endif
4808-
protectedMediaSession()->canProduceAudioChanged();
4809-
updateSleepDisabling();
4814+
canProduceAudioChanged();
48104815
}
48114816

48124817
schedulePlaybackControlsManagerUpdate();
@@ -6576,7 +6581,7 @@ void HTMLMediaElement::checkForAudioAndVideo()
65766581
{
65776582
m_hasEverHadAudio |= hasAudio();
65786583
m_hasEverHadVideo |= hasVideo();
6579-
protectedMediaSession()->canProduceAudioChanged();
6584+
canProduceAudioChanged();
65806585
}
65816586

65826587
void HTMLMediaElement::setPlaying(bool playing)
@@ -7097,9 +7102,8 @@ void HTMLMediaElement::setIsPlayingToWirelessTarget(bool isPlayingToWirelessTarg
70977102
ALWAYS_LOG_WITH_THIS(&element, logSiteIdentifier, element.m_isPlayingToWirelessTarget);
70987103
element.configureMediaControls();
70997104
element.mediaSession().isPlayingToWirelessPlaybackTargetChanged(element.m_isPlayingToWirelessTarget);
7100-
element.mediaSession().canProduceAudioChanged();
7105+
element.canProduceAudioChanged();
71017106
element.scheduleUpdateMediaState();
7102-
element.updateSleepDisabling();
71037107

71047108
element.m_failedToPlayToWirelessTarget = false;
71057109
element.m_checkPlaybackTargetCompatibilityTimer.startOneShot(500_ms);
@@ -10245,6 +10249,12 @@ RefPtr<MediaSessionManagerInterface> HTMLMediaElement::sessionManager() const
1024510249
return nullptr;
1024610250
}
1024710251

10252+
void HTMLMediaElement::canProduceAudioChanged()
10253+
{
10254+
protectedMediaSession()->canProduceAudioChanged();
10255+
updateSleepDisabling();
10256+
}
10257+
1024810258
} // namespace WebCore
1024910259

1025010260
#endif // ENABLE(VIDEO)

Source/WebCore/html/HTMLMediaElement.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,7 @@ class HTMLMediaElement
11741174
bool limitedMatroskaSupportEnabled() const;
11751175

11761176
void maybeUpdatePlayerPreload() const;
1177+
void canProduceAudioChanged();
11771178

11781179
Timer m_progressEventTimer;
11791180
Timer m_playbackProgressTimer;

0 commit comments

Comments
 (0)