Diff
Modified: branches/safari-601-branch/LayoutTests/ChangeLog (195067 => 195068)
--- branches/safari-601-branch/LayoutTests/ChangeLog 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/LayoutTests/ChangeLog 2016-01-14 19:19:34 UTC (rev 195068)
@@ -1,5 +1,23 @@
2016-01-14 Matthew Hanson <matthew_han...@apple.com>
+ Merge r194672. rdar://problem/24154288
+
+ 2016-01-06 Eric Carlson <eric.carl...@apple.com>
+
+ AirPlay route availability event not always sent
+ https://bugs.webkit.org/show_bug.cgi?id=152802
+
+ Reviewed by Jer Noble.
+
+ * media/airplay-target-availability-expected.txt: Added.
+ * media/airplay-target-availability.html: Added.
+ * platform/mac/TestExpectations: Skip new test on Yosemite.
+ * platform/efl/TestExpectations: Skip new test.
+ * platform/gtk/TestExpectations: Ditto.
+ * platform/win/TestExpectations: Ditto.
+
+2016-01-14 Matthew Hanson <matthew_han...@apple.com>
+
Merge r192200. rdar://problem/24154288
2015-11-09 Eric Carlson <eric.carl...@apple.com>
Added: branches/safari-601-branch/LayoutTests/media/airplay-target-availability-expected.txt (0 => 195068)
--- branches/safari-601-branch/LayoutTests/media/airplay-target-availability-expected.txt (rev 0)
+++ branches/safari-601-branch/LayoutTests/media/airplay-target-availability-expected.txt 2016-01-14 19:19:34 UTC (rev 195068)
@@ -0,0 +1,13 @@
+
+
+Test that 'webkitplaybacktargetavailabilitychanged' event is sent when at least one video element has playable media.
+
+
+EVENT: 'webkitplaybacktargetavailabilitychanged', event.availability = 'not-available'
+
+** setting src on video that does not have event listener
+
+EVENT: 'webkitplaybacktargetavailabilitychanged', event.availability = 'available'
+
+END OF TEST
+
Added: branches/safari-601-branch/LayoutTests/media/airplay-target-availability.html (0 => 195068)
--- branches/safari-601-branch/LayoutTests/media/airplay-target-availability.html (rev 0)
+++ branches/safari-601-branch/LayoutTests/media/airplay-target-availability.html 2016-01-14 19:19:34 UTC (rev 195068)
@@ -0,0 +1,54 @@
+<html>
+ <head>
+ <script src=""
+ <script src=""
+ <script>
+ var video1;
+ var video2;
+
+ function start()
+ {
+ video1 = document.getElementsByTagName('video')[0];
+ video2 = document.getElementsByTagName('video')[1];
+
+ if (window.internals)
+ internals.setMockMediaPlaybackTargetPickerEnabled(true);
+
+ video1.addEventListener('webkitplaybacktargetavailabilitychanged', targetAvailabilityChanged);
+ setTimeout(setSource, 200);
+ }
+
+ function targetAvailabilityChanged(event)
+ {
+ consoleWrite(`<br>EVENT: '${event.type}', event.availability = '${event.availability}'<br>`);
+
+ if (event.availability != "available")
+ return;
+
+ if (event.availability == "available" && video2.src == "") {
+ failTest("Event sent before any video is a candidate for airplay");
+ return;
+ }
+
+ endTest();
+ }
+
+ function setSource()
+ {
+ consoleWrite('** setting src on video that does not have event listener');
+ if (window.internals)
+ internals.setMockMediaPlaybackTargetPickerState("Sleepy TV", "DeviceAvailable");
+ video2.src = "" 'content/test');
+ }
+
+ </script>
+ </head>
+
+ <body _onload_="start()">
+ <video controls></video>
+ <br>
+ <video controls></video>
+ <p>Test that 'webkitplaybacktargetavailabilitychanged' event is sent when at least one
+ video element has playable media.</p>
+ </body>
+</html>
Modified: branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations (195067 => 195068)
--- branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/LayoutTests/platform/efl/TestExpectations 2016-01-14 19:19:34 UTC (rev 195068)
@@ -2301,3 +2301,6 @@
# This test uses an MPEG-4 video
media/video-seek-to-current-time.html [ Skip ]
+
+# WIRELESS_PLAYBACK_TARGET not enabled.
+media/airplay-target-availability.html
Modified: branches/safari-601-branch/LayoutTests/platform/gtk/TestExpectations (195067 => 195068)
--- branches/safari-601-branch/LayoutTests/platform/gtk/TestExpectations 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/LayoutTests/platform/gtk/TestExpectations 2016-01-14 19:19:34 UTC (rev 195068)
@@ -2403,3 +2403,6 @@
# This test uses an MPEG-4 video
media/video-seek-to-current-time.html [ Skip ]
+
+# WIRELESS_PLAYBACK_TARGET not enabled.
+media/airplay-target-availability.html
Modified: branches/safari-601-branch/LayoutTests/platform/mac/TestExpectations (195067 => 195068)
--- branches/safari-601-branch/LayoutTests/platform/mac/TestExpectations 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/LayoutTests/platform/mac/TestExpectations 2016-01-14 19:19:34 UTC (rev 195068)
@@ -1381,3 +1381,6 @@
# Yosemite and El Capitan do not support font feature coverage queries.
[ Yosemite ElCapitan ] css3/font-variant-small-caps-synthesis-coverage.html [ ImageOnlyFailure ]
[ Yosemite ElCapitan ] css3/font-variant-petite-caps-synthesis-coverage.html [ ImageOnlyFailure ]
+
+# WIRELESS_PLAYBACK_TARGET not enabled on Yosemite.
+[ Yosemite ] media/airplay-target-availability.html
Modified: branches/safari-601-branch/LayoutTests/platform/win/TestExpectations (195067 => 195068)
--- branches/safari-601-branch/LayoutTests/platform/win/TestExpectations 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/LayoutTests/platform/win/TestExpectations 2016-01-14 19:19:34 UTC (rev 195068)
@@ -3140,3 +3140,6 @@
# This test uses an MPEG-4 video
media/video-seek-to-current-time.html [ Skip ]
+
+# WIRELESS_PLAYBACK_TARGET not enabled.
+media/airplay-target-availability.html
Modified: branches/safari-601-branch/Source/WebCore/ChangeLog (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/ChangeLog 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/ChangeLog 2016-01-14 19:19:34 UTC (rev 195068)
@@ -1,5 +1,44 @@
2016-01-14 Matthew Hanson <matthew_han...@apple.com>
+ Merge r194672. rdar://problem/24154288
+
+ 2016-01-06 Eric Carlson <eric.carl...@apple.com>
+
+ AirPlay route availability event not always sent
+ https://bugs.webkit.org/show_bug.cgi?id=152802
+
+ Reviewed by Jer Noble.
+
+ Test: media/airplay-target-availability.html
+
+ * Modules/mediasession/WebMediaSessionManager.cpp:
+ (WebCore::mediaProducerStateString): Log the new flags.
+ (WebCore::WebMediaSessionManager::clientStateDidChange): Schedule a client reconfiguration if
+ the 'requires monitoring', 'has listener', or 'has audio or video' flags have changed.
+ (WebCore::WebMediaSessionManager::configurePlaybackTargetMonitoring): Start monitoring if
+ at least one client has a listener and at least one has audio/video.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::mediaState): Set new flags.
+ * html/HTMLMediaElement.h:
+
+ * page/MediaProducer.h: Define new flags. Add new state enum.
+
+ * platform/graphics/MediaPlaybackTargetContext.h: Initial state is "Unknown".
+
+ * platform/mock/MediaPlaybackTargetMock.h:
+ * platform/mock/MediaPlaybackTargetPickerMock.cpp:
+ (WebCore::MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable): Enums not bitfields.
+ (WebCore::MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets): Ditto. Don't make
+ device change callback if the device state is "Unknown".
+ (WebCore::MediaPlaybackTargetPickerMock::setState): Ditto.
+ * platform/mock/MediaPlaybackTargetPickerMock.h:
+
+ * testing/Internals.cpp:
+ (WebCore::Internals::setMockMediaPlaybackTargetPickerState): Support new state.
+
+2016-01-14 Matthew Hanson <matthew_han...@apple.com>
+
Merge r192200. rdar://problem/24154288
2015-11-09 Eric Carlson <eric.carl...@apple.com>
Modified: branches/safari-601-branch/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp 2016-01-14 19:19:34 UTC (rev 195068)
@@ -74,12 +74,16 @@
string.append("IsPlayingVideo + ");
if (flags & MediaProducer::IsPlayingToExternalDevice)
string.append("IsPlayingToExternalDevice + ");
+ if (flags & MediaProducer::HasPlaybackTargetAvailabilityListener)
+ string.append("HasPlaybackTargetAvailabilityListener + ");
if (flags & MediaProducer::RequiresPlaybackTargetMonitoring)
string.append("RequiresPlaybackTargetMonitoring + ");
if (flags & MediaProducer::ExternalDeviceAutoPlayCandidate)
string.append("ExternalDeviceAutoPlayCandidate + ");
if (flags & MediaProducer::DidPlayToEnd)
string.append("DidPlayToEnd + ");
+ if (flags & MediaProducer::HasAudioOrVideo)
+ string.append("HasAudioOrVideo + ");
if (string.isEmpty())
string.append("IsNotPlaying");
else
@@ -209,7 +213,9 @@
LOG(Media, "WebMediaSessionManager::clientStateDidChange(%p + %llu) - new flags = %s, old flags = %s", &client, contextId, mediaProducerStateString(newFlags).utf8().data(), mediaProducerStateString(oldFlags).utf8().data());
changedClientState->flags = newFlags;
- if (!flagsAreSet(oldFlags, MediaProducer::RequiresPlaybackTargetMonitoring) && flagsAreSet(newFlags, MediaProducer::RequiresPlaybackTargetMonitoring))
+
+ MediaProducer::MediaStateFlags updateConfigurationFlags = MediaProducer::RequiresPlaybackTargetMonitoring | MediaProducer::HasPlaybackTargetAvailabilityListener | MediaProducer::HasAudioOrVideo;
+ if (!flagsAreSet(oldFlags, updateConfigurationFlags) && flagsAreSet(newFlags, updateConfigurationFlags))
scheduleDelayedTask(TargetMonitoringConfigurationTask);
MediaProducer::MediaStateFlags playingToTargetFlags = MediaProducer::IsPlayingToExternalDevice | MediaProducer::IsPlayingVideo;
@@ -231,7 +237,7 @@
return;
}
- // Do not take begin playing to the device unless playback has just started.
+ // Do not begin playing to the device unless playback has just started.
if (!flagsAreSet(newFlags, MediaProducer::IsPlayingVideo) || flagsAreSet(oldFlags, MediaProducer::IsPlayingVideo))
return;
@@ -339,16 +345,22 @@
void WebMediaSessionManager::configurePlaybackTargetMonitoring()
{
bool monitoringRequired = false;
+ bool hasAvailabilityListener = false;
+ bool haveClientWithMedia = false;
for (auto& state : m_clientState) {
if (state->flags & MediaProducer::RequiresPlaybackTargetMonitoring) {
monitoringRequired = true;
break;
}
+ if (state->flags & MediaProducer::HasPlaybackTargetAvailabilityListener)
+ hasAvailabilityListener = true;
+ if (state->flags & MediaProducer::HasAudioOrVideo)
+ haveClientWithMedia = true;
}
LOG(Media, "WebMediaSessionManager::configurePlaybackTargetMonitoring - monitoringRequired = %i", (int)monitoringRequired);
- if (monitoringRequired)
+ if (monitoringRequired || (hasAvailabilityListener && haveClientWithMedia))
targetPicker().startingMonitoringPlaybackTargets();
else
targetPicker().stopMonitoringPlaybackTargets();
Modified: branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.cpp (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.cpp 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.cpp 2016-01-14 19:19:34 UTC (rev 195068)
@@ -6434,7 +6434,6 @@
MediaProducer::MediaStateFlags HTMLMediaElement::mediaState() const
{
-
MediaStateFlags state = IsNotPlaying;
bool hasActiveVideo = isVideo() && hasVideo();
@@ -6443,13 +6442,19 @@
if (m_player && m_player->isCurrentPlaybackTargetWireless())
state |= IsPlayingToExternalDevice;
- if (m_player && m_hasPlaybackTargetAvailabilityListeners && !m_mediaSession->wirelessVideoPlaybackDisabled(*this))
- state |= RequiresPlaybackTargetMonitoring;
+ if (m_hasPlaybackTargetAvailabilityListeners) {
+ state |= HasPlaybackTargetAvailabilityListener;
+ if (!m_mediaSession->wirelessVideoPlaybackDisabled(*this))
+ state |= RequiresPlaybackTargetMonitoring;
+ }
bool requireUserGesture = m_mediaSession->hasBehaviorRestriction(MediaElementSession::RequireUserGestureToAutoplayToExternalDevice);
if (m_readyState >= HAVE_METADATA && !requireUserGesture && !m_failedToPlayToWirelessTarget)
state |= ExternalDeviceAutoPlayCandidate;
+ if (hasActiveVideo || hasAudio)
+ state |= HasAudioOrVideo;
+
if (hasActiveVideo && endedPlayback())
state |= DidPlayToEnd;
#endif
Modified: branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.h (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.h 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/html/HTMLMediaElement.h 2016-01-14 19:19:34 UTC (rev 195068)
@@ -745,6 +745,7 @@
Synchronously,
};
void updateMediaState(UpdateMediaState updateState = UpdateMediaState::Synchronously);
+ bool hasPlaybackTargetAvailabilityListeners() const { return m_hasPlaybackTargetAvailabilityListeners; }
#endif
Timer m_pendingActionTimer;
Modified: branches/safari-601-branch/Source/WebCore/page/MediaProducer.h (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/page/MediaProducer.h 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/page/MediaProducer.h 2016-01-14 19:19:34 UTC (rev 195068)
@@ -38,6 +38,8 @@
RequiresPlaybackTargetMonitoring = 1 << 3,
ExternalDeviceAutoPlayCandidate = 1 << 4,
DidPlayToEnd = 1 << 5,
+ HasPlaybackTargetAvailabilityListener = 1 << 9,
+ HasAudioOrVideo = 1 << 10,
};
typedef unsigned MediaStateFlags;
Modified: branches/safari-601-branch/Source/WebCore/platform/graphics/MediaPlaybackTargetContext.h (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/platform/graphics/MediaPlaybackTargetContext.h 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/platform/graphics/MediaPlaybackTargetContext.h 2016-01-14 19:19:34 UTC (rev 195068)
@@ -48,8 +48,9 @@
};
enum ContextState {
- Unavailable = 0,
- OutputDeviceAvailable = 1 << 0,
+ Unknown = 0,
+ OutputDeviceUnavailable = 1,
+ OutputDeviceAvailable = 2,
};
typedef unsigned State;
@@ -97,7 +98,7 @@
Type m_type { None };
AVOutputContext *m_outputContext { nullptr };
String m_name;
- State m_state { Unavailable };
+ State m_state { Unknown };
};
}
Modified: branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h 2016-01-14 19:19:34 UTC (rev 195068)
@@ -55,7 +55,7 @@
MediaPlaybackTargetMock(const String&, MediaPlaybackTargetContext::State);
String m_name;
- MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unavailable };
+ MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unknown };
mutable MediaPlaybackTargetContext m_context;
};
Modified: branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp 2016-01-14 19:19:34 UTC (rev 195068)
@@ -60,7 +60,7 @@
bool MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable()
{
LOG(Media, "MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable");
- return m_state & MediaPlaybackTargetContext::OutputDeviceAvailable;
+ return m_state == MediaPlaybackTargetContext::OutputDeviceAvailable;
}
Ref<MediaPlaybackTarget> MediaPlaybackTargetPickerMock::playbackTarget()
@@ -90,10 +90,10 @@
{
LOG(Media, "MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets");
- if (m_state & MediaPlaybackTargetContext::OutputDeviceAvailable)
+ if (m_state == MediaPlaybackTargetContext::OutputDeviceAvailable)
availableDevicesDidChange();
- if (!m_deviceName.isEmpty())
+ if (!m_deviceName.isEmpty() && m_state != MediaPlaybackTargetContext::Unknown)
currentDeviceDidChange();
}
@@ -105,14 +105,14 @@
void MediaPlaybackTargetPickerMock::invalidatePlaybackTargets()
{
LOG(Media, "MediaPlaybackTargetPickerMock::invalidatePlaybackTargets");
- setState(WTF::emptyString(), MediaPlaybackTargetContext::Unavailable);
+ setState(emptyString(), MediaPlaybackTargetContext::Unknown);
}
void MediaPlaybackTargetPickerMock::setState(const String& deviceName, MediaPlaybackTargetContext::State state)
{
LOG(Media, "MediaPlaybackTargetPickerMock::setState - name = %s, state = 0x%x", deviceName.utf8().data(), (unsigned)state);
- if (deviceName != m_deviceName) {
+ if (deviceName != m_deviceName && state != MediaPlaybackTargetContext::Unknown) {
m_deviceName = deviceName;
currentDeviceDidChange();
}
Modified: branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h 2016-01-14 19:19:34 UTC (rev 195068)
@@ -58,7 +58,7 @@
String m_deviceName;
RunLoop::Timer<MediaPlaybackTargetPickerMock> m_timer;
- MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unavailable };
+ MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unknown };
bool m_showingMenu { false };
};
Modified: branches/safari-601-branch/Source/WebCore/testing/Internals.cpp (195067 => 195068)
--- branches/safari-601-branch/Source/WebCore/testing/Internals.cpp 2016-01-14 19:19:28 UTC (rev 195067)
+++ branches/safari-601-branch/Source/WebCore/testing/Internals.cpp 2016-01-14 19:19:34 UTC (rev 195068)
@@ -2818,10 +2818,14 @@
Page* page = contextDocument()->frame()->page();
ASSERT(page);
- MediaPlaybackTargetContext::State state = MediaPlaybackTargetContext::Unavailable;
+ MediaPlaybackTargetContext::State state = MediaPlaybackTargetContext::Unknown;
if (equalIgnoringCase(deviceState, "DeviceAvailable"))
state = MediaPlaybackTargetContext::OutputDeviceAvailable;
+ else if (equalIgnoringCase(deviceState, "DeviceUnavailable"))
+ state = MediaPlaybackTargetContext::OutputDeviceUnavailable;
+ else if (equalIgnoringCase(deviceState, "Unknown"))
+ state = MediaPlaybackTargetContext::Unknown;
else {
ec = INVALID_ACCESS_ERR;
return;