Diff
Modified: trunk/LayoutTests/ChangeLog (202099 => 202100)
--- trunk/LayoutTests/ChangeLog 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/LayoutTests/ChangeLog 2016-06-15 19:32:50 UTC (rev 202100)
@@ -1,3 +1,16 @@
+2016-06-15 Eric Carlson <[email protected]>
+
+ [iOS] Make HTMLMediaElement.muted mutable
+ https://bugs.webkit.org/show_bug.cgi?id=158787
+ <rdar://problem/24452567>
+
+ Reviewed by Dean Jackson.
+
+ * media/audio-playback-restriction-removed-muted-expected.txt: Added.
+ * media/audio-playback-restriction-removed-muted.html: Added.
+ * media/audio-playback-restriction-removed-track-enabled-expected.txt: Added.
+ * media/audio-playback-restriction-removed-track-enabled.html: Added.
+
2016-06-15 Simon Fraser <[email protected]>
fast/events/ios tests are marked as flakey, but really just fail in OpenSource and WK1
Added: trunk/LayoutTests/media/audio-playback-restriction-removed-muted-expected.txt (0 => 202100)
--- trunk/LayoutTests/media/audio-playback-restriction-removed-muted-expected.txt (rev 0)
+++ trunk/LayoutTests/media/audio-playback-restriction-removed-muted-expected.txt 2016-06-15 19:32:50 UTC (rev 202100)
@@ -0,0 +1,11 @@
+Test that when RequireUserGestureForAudioRateChange is set, setting muted with a user gesture clears the restriction.
+
+
+RUN(internals.setMediaElementRestrictions(video, "RequireUserGestureForAudioRateChange"))
+RUN(video.src = "" "content/test"))
+EVENT(canplaythrough)
+RUN(video.play())
+EVENT(playing)
+RUN(video.muted = false)
+END OF TEST
+
Added: trunk/LayoutTests/media/audio-playback-restriction-removed-muted.html (0 => 202100)
--- trunk/LayoutTests/media/audio-playback-restriction-removed-muted.html (rev 0)
+++ trunk/LayoutTests/media/audio-playback-restriction-removed-muted.html 2016-06-15 19:32:50 UTC (rev 202100)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>audio-playback-restriction</title>
+ <script src=""
+ <script src=""
+
+ <script>
+ function runTest()
+ {
+ video = document.getElementsByTagName('audio')[0];
+
+ if (window.internals)
+ run('internals.setMediaElementRestrictions(video, "RequireUserGestureForAudioRateChange")');
+
+ waitForEventAndFail('error');
+ waitForEvent('canplaythrough', canplaythrough);
+ run('video.src = "" "content/test")');
+ }
+
+ function canplaythrough()
+ {
+ waitForEvent('playing', playing);
+ run('video.play()');
+ }
+
+ function playing()
+ {
+ waitForEventAndFail('pause');
+ runWithKeyDown('video.muted = false');
+ setTimeout(endTest, 250);
+ }
+ </script>
+</head>
+
+<body _onload_="runTest()">
+ <p>Test that when RequireUserGestureForAudioRateChange is set, setting muted with a user gesture clears the restriction.</p>
+ <audio muted controls></audio>
+</body>
+</html>
+
Added: trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled-expected.txt (0 => 202100)
--- trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled-expected.txt (rev 0)
+++ trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled-expected.txt 2016-06-15 19:32:50 UTC (rev 202100)
@@ -0,0 +1,12 @@
+Test that when RequireUserGestureForAudioRateChange is set, enabling an audio track with a user gesture clears the restriction.
+
+
+RUN(internals.setMediaElementRestrictions(video, 'RequireUserGestureForAudioRateChange'))
+RUN(video.src = "" 'content/audio-tracks'))
+EVENT(canplaythrough)
+RUN(video.play())
+EVENT(playing)
+RUN(audioTrack.enabled = true)
+RUN(video.muted = false)
+END OF TEST
+
Added: trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled.html (0 => 202100)
--- trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled.html (rev 0)
+++ trunk/LayoutTests/media/audio-playback-restriction-removed-track-enabled.html 2016-06-15 19:32:50 UTC (rev 202100)
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>audio-playback-restriction</title>
+ <script src=""
+ <script src=""
+
+ <script>
+
+ let audioTrack = null;
+ function runTest()
+ {
+ video = document.getElementsByTagName('audio')[0];
+
+ if (window.internals)
+ run(`internals.setMediaElementRestrictions(video, 'RequireUserGestureForAudioRateChange')`);
+
+ waitForEventAndFail('error');
+ waitForEvent('canplaythrough', canplaythrough);
+ run(`video.src = "" 'content/audio-tracks')`);
+ }
+
+ function canplaythrough()
+ {
+ waitForEvent('playing', playing);
+ video.audioTracks.addEventListener('change', setMuted, true);
+ run('video.play()');
+ }
+
+ function playing()
+ {
+ for (let i = 0; i < video.audioTracks.length; i++) {
+ if (video.audioTracks[i].enabled)
+ continue;
+
+ audioTrack = video.audioTracks[i];
+ break;
+ }
+ if (audioTrack === null)
+ failTest('Failed to find disabled audio track!');
+
+ runWithKeyDown('audioTrack.enabled = true');
+ }
+
+ function setMuted()
+ {
+ waitForEventAndFail('pause');
+ video.audioTracks.removeEventListener('change', setMuted, true);
+ run('video.muted = false');
+ setTimeout(endTest, 250);
+ }
+
+ </script>
+</head>
+
+<body _onload_='runTest()'>
+ <p>Test that when RequireUserGestureForAudioRateChange is set, enabling an audio track with a user gesture clears the restriction.</p>
+ <audio muted controls></audio>
+</body>
+</html>
+
Modified: trunk/Source/WebCore/ChangeLog (202099 => 202100)
--- trunk/Source/WebCore/ChangeLog 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/ChangeLog 2016-06-15 19:32:50 UTC (rev 202100)
@@ -1,3 +1,34 @@
+2016-06-15 Eric Carlson <[email protected]>
+
+ [iOS] Make HTMLMediaElement.muted mutable
+ https://bugs.webkit.org/show_bug.cgi?id=158787
+ <rdar://problem/24452567>
+
+ Reviewed by Dean Jackson.
+
+ Tests: media/audio-playback-restriction-removed-muted.html
+ media/audio-playback-restriction-removed-track-enabled.html
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::audioTrackEnabledChanged): Remove most behavior restrictions if
+ the track state was changed as a result of a user gesture.
+ (WebCore::HTMLMediaElement::setMuted): Ditto.
+ (WebCore::HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture): Add mask
+ parameter so caller can choose which restrictions are removed.
+ * html/HTMLMediaElement.h:
+
+ * html/MediaElementSession.cpp:
+ (WebCore::restrictionName): Drive-by fix: remove duplicate label.
+ * html/MediaElementSession.h:
+
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): Set muted on AVPlayer if setMuted
+ was called before the player was created.
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::setVolume): Drive-by fix: return early if there
+ is no AVPlayer, not if we won't have metadata yet.
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::setMuted): New.
+
2016-06-15 Romain Bellessort <[email protected]>
Enabling Shadow DOM for all platforms
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (202099 => 202100)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2016-06-15 19:32:50 UTC (rev 202100)
@@ -1757,6 +1757,8 @@
ASSERT(track);
if (m_audioTracks && m_audioTracks->contains(*track))
m_audioTracks->scheduleChangeEvent();
+ if (ScriptController::processingUserGestureForMedia())
+ removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::AllRestrictions & ~MediaElementSession::RequireUserGestureToControlControlsManager);
}
void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
@@ -3332,12 +3334,13 @@
{
LOG(Media, "HTMLMediaElement::setMuted(%p) - %s", this, boolString(muted));
-#if PLATFORM(IOS)
- UNUSED_PARAM(muted);
-#else
if (m_muted != muted || !m_explicitlyMuted) {
m_muted = muted;
m_explicitlyMuted = true;
+
+ if (ScriptController::processingUserGestureForMedia())
+ removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::AllRestrictions & ~MediaElementSession::RequireUserGestureToControlControlsManager);
+
// Avoid recursion when the player reports volume changes.
if (!processingMediaPlayerCallback()) {
if (m_player) {
@@ -3360,7 +3363,6 @@
updateMediaState(UpdateMediaState::Asynchronously);
#endif
}
-#endif
updatePlaybackControlsManager();
}
@@ -6401,9 +6403,10 @@
}
#endif
-void HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture()
+void HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::BehaviorRestrictions mask)
{
- MediaElementSession::BehaviorRestrictions restrictionsToRemove = MediaElementSession::RequireUserGestureForLoad
+ MediaElementSession::BehaviorRestrictions restrictionsToRemove = mask &
+ (MediaElementSession::RequireUserGestureForLoad
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
| MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker
| MediaElementSession::RequireUserGestureToAutoplayToExternalDevice
@@ -6413,7 +6416,8 @@
| MediaElementSession::RequireUserGestureForAudioRateChange
| MediaElementSession::RequireUserGestureForFullscreen
| MediaElementSession::InvisibleAutoplayNotPermitted
- | MediaElementSession::RequireUserGestureToControlControlsManager;
+ | MediaElementSession::RequireUserGestureToControlControlsManager);
+
m_mediaSession->removeBehaviorRestriction(restrictionsToRemove);
}
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (202099 => 202100)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2016-06-15 19:32:50 UTC (rev 202100)
@@ -721,7 +721,7 @@
void changeNetworkStateFromLoadingToIdle();
- void removeBehaviorsRestrictionsAfterFirstUserGesture();
+ void removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::BehaviorRestrictions mask = MediaElementSession::AllRestrictions);
void updateMediaController();
bool isBlocked() const;
Modified: trunk/Source/WebCore/html/MediaElementSession.cpp (202099 => 202100)
--- trunk/Source/WebCore/html/MediaElementSession.cpp 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/html/MediaElementSession.cpp 2016-06-15 19:32:50 UTC (rev 202100)
@@ -82,7 +82,6 @@
CASE(RequireUserGestureToShowPlaybackTargetPicker);
CASE(WirelessVideoPlaybackDisabled);
#endif
- CASE(RequireUserGestureForAudioRateChange);
CASE(InvisibleAutoplayNotPermitted);
CASE(OverrideUserGestureRequirementForMainContent);
Modified: trunk/Source/WebCore/html/MediaElementSession.h (202099 => 202100)
--- trunk/Source/WebCore/html/MediaElementSession.h 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/html/MediaElementSession.h 2016-06-15 19:32:50 UTC (rev 202100)
@@ -86,16 +86,15 @@
RequirePageConsentToLoadMedia = 1 << 3,
RequirePageConsentToResumeMedia = 1 << 4,
RequireUserGestureForAudioRateChange = 1 << 5,
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
RequireUserGestureToShowPlaybackTargetPicker = 1 << 6,
WirelessVideoPlaybackDisabled = 1 << 7,
RequireUserGestureToAutoplayToExternalDevice = 1 << 8,
-#endif
MetadataPreloadingNotPermitted = 1 << 9,
AutoPreloadingNotPermitted = 1 << 10,
InvisibleAutoplayNotPermitted = 1 << 11,
OverrideUserGestureRequirementForMainContent = 1 << 12,
RequireUserGestureToControlControlsManager = 1 << 13,
+ AllRestrictions = ~NoRestrictions,
};
typedef unsigned BehaviorRestrictions;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (202099 => 202100)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h 2016-06-15 19:32:50 UTC (rev 202100)
@@ -176,6 +176,8 @@
void platformPause() override;
MediaTime currentMediaTime() const override;
void setVolume(float) override;
+ bool supportsMuting() const override { return true; }
+ void setMuted(bool) override;
void setClosedCaptionsVisible(bool) override;
void paint(GraphicsContext&, const FloatRect&) override;
void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;
@@ -424,6 +426,7 @@
bool m_haveBeenAskedToCreateLayer;
bool m_cachedCanPlayFastForward;
bool m_cachedCanPlayFastReverse;
+ bool m_muted { false };
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
mutable bool m_allowsWirelessVideoPlayback;
bool m_shouldPlayToPlaybackTarget { false };
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (202099 => 202100)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2016-06-15 19:30:23 UTC (rev 202099)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2016-06-15 19:32:50 UTC (rev 202100)
@@ -1058,6 +1058,12 @@
}
#endif
+ if (m_muted) {
+ // Clear m_muted so setMuted doesn't return without doing anything.
+ m_muted = false;
+ [m_avPlayer.get() setMuted:m_muted];
+ }
+
if (player()->client().mediaPlayerIsVideo())
createAVPlayerLayer();
@@ -1395,13 +1401,28 @@
UNUSED_PARAM(volume);
return;
#else
- if (!metaDataAvailable())
+ if (!m_avPlayer)
return;
[m_avPlayer.get() setVolume:volume];
#endif
}
+void MediaPlayerPrivateAVFoundationObjC::setMuted(bool muted)
+{
+ if (m_muted == muted)
+ return;
+
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setMuted(%p) - set to %s", this, boolString(muted));
+
+ m_muted = muted;
+
+ if (!m_avPlayer)
+ return;
+
+ [m_avPlayer.get() setMuted:m_muted];
+}
+
void MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCaptionsVisible)
{
UNUSED_PARAM(closedCaptionsVisible);