[Mac] Update AirPlay handling
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Mar 2015 01:54:06 +0000 (01:54 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Mar 2015 01:54:06 +0000 (01:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142541

Reviewed by Sam Weinig.

Source/WebCore:

* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::showPlaybackTargetPicker):
(WebCore::Document::addPlaybackTargetPickerClient):
(WebCore::Document::removePlaybackTargetPickerClient):
(WebCore::Document::configurePlaybackTargetMonitoring):
(WebCore::Document::requiresPlaybackTargetRouteMonitoring):
(WebCore::Document::playbackTargetAvailabilityDidChange):
(WebCore::Document::didChoosePlaybackTarget):
* dom/Document.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::registerWithDocument):
(WebCore::HTMLMediaElement::unregisterWithDocument):
(WebCore::HTMLMediaElement::parseAttribute):
* html/HTMLMediaElement.h:
* html/HTMLMediaSession.cpp:
(WebCore::HTMLMediaSession::HTMLMediaSession):
(WebCore::HTMLMediaSession::registerWithDocument):
(WebCore::HTMLMediaSession::unregisterWithDocument):
(WebCore::HTMLMediaSession::showPlaybackTargetPicker):
(WebCore::HTMLMediaSession::hasWirelessPlaybackTargets):
(WebCore::HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners):
(WebCore::HTMLMediaSession::didChoosePlaybackTarget):
(WebCore::HTMLMediaSession::externalOutputDeviceAvailableDidChange):
(WebCore::HTMLMediaSession::requiresPlaybackTargetRouteMonitoring):
* html/HTMLMediaSession.h:
* page/ChromeClient.h:
* page/Page.cpp:
(WebCore::Page::didChoosePlaybackTarget):
(WebCore::Page::playbackTargetAvailabilityDidChange):
(WebCore::Page::configurePlaybackTargetMonitoring):
* page/Page.h:
(WebCore::Page::hasWirelessPlaybackTarget):
(WebCore::Page::playbackTarget):
* platform/audio/MediaSession.cpp:
(WebCore::MediaSession::clientDataBufferingTimerFired):
(WebCore::MediaSession::wirelessRoutesAvailableDidChange): Deleted.
* platform/audio/MediaSession.h:
(WebCore::MediaSession::didChoosePlaybackTarget):
(WebCore::MediaSession::externalOutputDeviceAvailableDidChange):
(WebCore::MediaSession::requiresPlaybackTargetRouteMonitoring):
(WebCore::MediaSessionClient::setWirelessPlaybackTarget):
* platform/audio/MediaSessionManager.cpp:
(WebCore::MediaSessionManager::wirelessRoutesAvailableChanged): Deleted.
* platform/audio/MediaSessionManager.h:
(WebCore::MediaSessionManager::configureWireLessTargetMonitoring):
* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(WebCore::MediaSessionManageriOS::externalOutputDeviceAvailableDidChange):
(-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]):
* platform/graphics/AVPlaybackTarget.h: Added.
(WebCore::AVPlaybackTarget::~AVPlaybackTarget):
(WebCore::AVPlaybackTarget::AVPlaybackTarget):
(WebCore::AVPlaybackTarget::setDevicePickerContext):
(WebCore::AVPlaybackTarget::devicePickerContext):
* platform/graphics/AVPlaybackTargetPickerClient.h: Added.
(WebCore::AVPlaybackTargetPickerClient::~AVPlaybackTargetPickerClient):
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::setWirelessPlaybackTarget):
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::setWirelessPlaybackTarget):
* platform/graphics/avfoundation/AVPlaybackTargetMac.mm: Added.
(WebCore::AVPlaybackTarget::encode):
(WebCore::AVPlaybackTarget::decode):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad):
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer):
(WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer):
(WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless):
(WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetType):
(WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled):
(WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled):
(WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget):
(WebCore::MediaPlayerPrivateAVFoundationObjC::updateDisableExternalPlayback):
(-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):

Source/WebKit2:

* Shared/WebCoreArgumentCoders.h:
* Shared/mac/WebCoreArgumentCodersMac.mm:
(IPC::ArgumentCoder<AVPlaybackTarget>::encode):
(IPC::ArgumentCoder<AVPlaybackTarget>::decode):
* UIProcess/PageClient.h:
* UIProcess/WebAVPlaybackTargetPickerProxy.cpp: Added.
(WebKit::WebAVPlaybackTargetPickerProxy::WebAVPlaybackTargetPickerProxy):
(WebKit::WebAVPlaybackTargetPickerProxy::~WebAVPlaybackTargetPickerProxy):
(WebKit::WebAVPlaybackTargetPickerProxy::showPlaybackTargetPicker):
(WebKit::WebAVPlaybackTargetPickerProxy::startingMonitoringPlaybackTargets):
(WebKit::WebAVPlaybackTargetPickerProxy::stopMonitoringPlaybackTargets):
* UIProcess/WebAVPlaybackTargetPickerProxy.h: Added.
(WebKit::WebAVPlaybackTargetPickerProxy::Client::~Client):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::devicePickerProxy):
(WebKit::WebPageProxy::showPlaybackTargetPicker):
(WebKit::WebPageProxy::startingMonitoringPlaybackTargets):
(WebKit::WebPageProxy::stopMonitoringPlaybackTargets):
(WebKit::WebPageProxy::didChoosePlaybackTarget):
(WebKit::WebPageProxy::externalOutputDeviceAvailableDidChange):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/mac/PageClientImpl.h:
* UIProcess/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::createPlaybackTargetPicker):
* UIProcess/mac/WebAVPlaybackTargetPickerProxyMac.h: Added.
* UIProcess/mac/WebAVPlaybackTargetPickerProxyMac.mm: Added.
(WebKit::WebAVPlaybackTargetPickerProxyMac::create):
(WebKit::WebAVPlaybackTargetPickerProxyMac::WebAVPlaybackTargetPickerProxyMac):
(WebKit::WebAVPlaybackTargetPickerProxyMac::~WebAVPlaybackTargetPickerProxyMac):
(WebKit::WebAVPlaybackTargetPickerProxyMac::outputeDeviceAvailabilityChangedTimerFired):
(WebKit::WebAVPlaybackTargetPickerProxyMac::availableDevicesDidChange):
(WebKit::WebAVPlaybackTargetPickerProxyMac::devicePicker):
(WebKit::WebAVPlaybackTargetPickerProxyMac::showPlaybackTargetPicker):
(WebKit::WebAVPlaybackTargetPickerProxyMac::currentDeviceDidChange):
(WebKit::WebAVPlaybackTargetPickerProxyMac::startingMonitoringPlaybackTargets):
(WebKit::WebAVPlaybackTargetPickerProxyMac::stopMonitoringPlaybackTargets):
(-[WebAVOutputDevicePickerMenuControllerHelper initWithCallback:]):
(-[WebAVOutputDevicePickerMenuControllerHelper clearCallback]):
(-[WebAVOutputDevicePickerMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):
* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebAVPlaybackTargetPicker.cpp: Added.
(WebKit::WebAVPlaybackTargetPicker::WebAVPlaybackTargetPicker):
(WebKit::WebAVPlaybackTargetPicker::showPlaybackDevicePicker):
(WebKit::WebAVPlaybackTargetPicker::configureWireLessTargetMonitoring):
(WebKit::WebAVPlaybackTargetPicker::addClient):
(WebKit::WebAVPlaybackTargetPicker::removeClient):
(WebKit::WebAVPlaybackTargetPicker::didChoosePlaybackTarget):
(WebKit::WebAVPlaybackTargetPicker::playbackTargetAvailabilityDidChange):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::showPlaybackTargetPicker):
(WebKit::WebChromeClient::startingMonitoringPlaybackTargets):
(WebKit::WebChromeClient::stopMonitoringPlaybackTargets):
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::playbackTargetSelected):
(WebKit::WebPage::playbackTargetAvailabilityDidChange):
* WebProcess/com.apple.WebProcess.sb.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181423 268f45cc-cd09-0410-ab3c-d52691b4dbfc

36 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/HTMLMediaSession.cpp
Source/WebCore/html/HTMLMediaSession.h
Source/WebCore/page/ChromeClient.h
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/platform/audio/MediaSession.cpp
Source/WebCore/platform/audio/MediaSession.h
Source/WebCore/platform/audio/MediaSessionManager.cpp
Source/WebCore/platform/audio/MediaSessionManager.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebCore/platform/graphics/MediaPlaybackTarget.h [new file with mode: 0644]
Source/WebCore/platform/graphics/MediaPlaybackTargetPickerClient.h [new file with mode: 0644]
Source/WebCore/platform/graphics/MediaPlayer.cpp
Source/WebCore/platform/graphics/MediaPlayer.h
Source/WebCore/platform/graphics/MediaPlayerPrivate.h
Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetMac.mm [new file with mode: 0644]
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
Source/WebCore/testing/InternalSettings.cpp
Source/WebCore/testing/InternalSettings.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/Shared/mac/WebCoreArgumentCodersMac.mm
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.h [new file with mode: 0644]
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in

index 0741e95..ee0829d 100644 (file)
@@ -1,3 +1,88 @@
+2015-03-11  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Update AirPlay handling
+        https://bugs.webkit.org/show_bug.cgi?id=142541
+
+        Reviewed by Sam Weinig.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Document.cpp:
+        (WebCore::Document::showPlaybackTargetPicker):
+        (WebCore::Document::addPlaybackTargetPickerClient):
+        (WebCore::Document::removePlaybackTargetPickerClient):
+        (WebCore::Document::configurePlaybackTargetMonitoring):
+        (WebCore::Document::requiresPlaybackTargetRouteMonitoring):
+        (WebCore::Document::playbackTargetAvailabilityDidChange):
+        (WebCore::Document::didChoosePlaybackTarget):
+        * dom/Document.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::registerWithDocument):
+        (WebCore::HTMLMediaElement::unregisterWithDocument):
+        (WebCore::HTMLMediaElement::parseAttribute):
+        * html/HTMLMediaElement.h:
+        * html/HTMLMediaSession.cpp:
+        (WebCore::HTMLMediaSession::HTMLMediaSession):
+        (WebCore::HTMLMediaSession::registerWithDocument):
+        (WebCore::HTMLMediaSession::unregisterWithDocument):
+        (WebCore::HTMLMediaSession::showPlaybackTargetPicker):
+        (WebCore::HTMLMediaSession::hasWirelessPlaybackTargets):
+        (WebCore::HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners):
+        (WebCore::HTMLMediaSession::didChoosePlaybackTarget):
+        (WebCore::HTMLMediaSession::externalOutputDeviceAvailableDidChange):
+        (WebCore::HTMLMediaSession::requiresPlaybackTargetRouteMonitoring):
+        * html/HTMLMediaSession.h:
+        * page/ChromeClient.h:
+        * page/Page.cpp:
+        (WebCore::Page::didChoosePlaybackTarget):
+        (WebCore::Page::playbackTargetAvailabilityDidChange):
+        (WebCore::Page::configurePlaybackTargetMonitoring):
+        * page/Page.h:
+        (WebCore::Page::hasWirelessPlaybackTarget):
+        (WebCore::Page::playbackTarget):
+        * platform/audio/MediaSession.cpp:
+        (WebCore::MediaSession::clientDataBufferingTimerFired):
+        (WebCore::MediaSession::wirelessRoutesAvailableDidChange): Deleted.
+        * platform/audio/MediaSession.h:
+        (WebCore::MediaSession::didChoosePlaybackTarget):
+        (WebCore::MediaSession::externalOutputDeviceAvailableDidChange):
+        (WebCore::MediaSession::requiresPlaybackTargetRouteMonitoring):
+        (WebCore::MediaSessionClient::setWirelessPlaybackTarget):
+        * platform/audio/MediaSessionManager.cpp:
+        (WebCore::MediaSessionManager::wirelessRoutesAvailableChanged): Deleted.
+        * platform/audio/MediaSessionManager.h:
+        (WebCore::MediaSessionManager::configureWireLessTargetMonitoring):
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (WebCore::MediaSessionManageriOS::externalOutputDeviceAvailableDidChange):
+        (-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]):
+        * platform/graphics/AVPlaybackTarget.h: Added.
+        (WebCore::AVPlaybackTarget::~AVPlaybackTarget):
+        (WebCore::AVPlaybackTarget::AVPlaybackTarget):
+        (WebCore::AVPlaybackTarget::setDevicePickerContext):
+        (WebCore::AVPlaybackTarget::devicePickerContext):
+        * platform/graphics/AVPlaybackTargetPickerClient.h: Added.
+        (WebCore::AVPlaybackTargetPickerClient::~AVPlaybackTargetPickerClient):
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::setWirelessPlaybackTarget):
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::setWirelessPlaybackTarget):
+        * platform/graphics/avfoundation/AVPlaybackTargetMac.mm: Added.
+        (WebCore::AVPlaybackTarget::encode):
+        (WebCore::AVPlaybackTarget::decode):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetType):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::updateDisableExternalPlayback):
+        (-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
+
 2015-03-11  Alex Christensen  <achristensen@webkit.org>
 
         [Content Extensions] Add resource type and load type triggers.
index 2a1d00d..968a72d 100644 (file)
                074E82BB18A69F0E007EF54C /* PlatformTimeRanges.h in Headers */ = {isa = PBXBuildFile; fileRef = 074E82B918A69F0E007EF54C /* PlatformTimeRanges.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0753860214489E9800B78452 /* CachedTextTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0753860014489E9800B78452 /* CachedTextTrack.cpp */; };
                0753860314489E9800B78452 /* CachedTextTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = 0753860114489E9800B78452 /* CachedTextTrack.h */; };
+               0760C17A1AA8FC7D009ED7B8 /* MediaPlaybackTargetMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07E3DFD21A9E78A500764CA8 /* MediaPlaybackTargetMac.mm */; };
                076306D017E1478D005A7C4E /* MediaStreamTrackSourcesCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 076306CC17E1478D005A7C4E /* MediaStreamTrackSourcesCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
                076306D217E1478D005A7C4E /* MediaStreamTrackSourcesRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 076306CE17E1478D005A7C4E /* MediaStreamTrackSourcesRequest.cpp */; };
                076306D317E1478D005A7C4E /* MediaStreamTrackSourcesRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 076306CF17E1478D005A7C4E /* MediaStreamTrackSourcesRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
                078E094717D16E1C00420AA1 /* RTCVoidRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 07221BB017CF0AD400848E51 /* RTCVoidRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
                078E094B17D1709600420AA1 /* MediaStreamAudioDestinationNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 078E094817D1709600420AA1 /* MediaStreamAudioDestinationNode.cpp */; };
                078E094C17D1709600420AA1 /* MediaStreamAudioDestinationNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 078E094917D1709600420AA1 /* MediaStreamAudioDestinationNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               079216551AA560AA00A3C049 /* MediaPlaybackTargetPickerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 079216531AA560AA00A3C049 /* MediaPlaybackTargetPickerClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                07941791166E855F009416C2 /* InbandTextTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0794178F166E855F009416C2 /* InbandTextTrack.cpp */; };
                07941792166E855F009416C2 /* InbandTextTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = 07941790166E855F009416C2 /* InbandTextTrack.h */; };
                07941794166EA04E009416C2 /* InbandTextTrackPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 07941793166EA04E009416C2 /* InbandTextTrackPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                07DC5FD417D3EEE90099F890 /* JSRTCStatsResponseCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07DC5FD317D3EEE90099F890 /* JSRTCStatsResponseCustom.cpp */; };
                07E116B11489C9A100EC5ACE /* JSTextTrackCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07E116B01489C9A100EC5ACE /* JSTextTrackCustom.cpp */; };
                07E117071489EBEB00EC5ACE /* JSTextTrackCueCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07E117061489EBEB00EC5ACE /* JSTextTrackCueCustom.cpp */; };
+               07E3DFD11A9E786500764CA8 /* MediaPlaybackTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 07E3DFD01A9E786500764CA8 /* MediaPlaybackTarget.h */; settings = {ATTRIBUTES = (Private, ); }; };
                07E9E12E18F5E2760011A3A4 /* InbandMetadataTextTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = 07E9E12D18F5E2760011A3A4 /* InbandMetadataTextTrackPrivateAVF.h */; };
                07E9E13018F62B370011A3A4 /* InbandMetadataTextTrackPrivateAVF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07E9E12F18F62B370011A3A4 /* InbandMetadataTextTrackPrivateAVF.cpp */; };
+               07EDC3EE1AACB75D00983EB5 /* MediaSessionManagerMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07EDC3ED1AACB75D00983EB5 /* MediaSessionManagerMac.cpp */; };
                07F944161864D046005D31CB /* MediaSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CDAE8C081746B95700532D78 /* MediaSessionManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
                07FBDE2C18FED178001A7CFF /* JSDataCueCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07FBDE2B18FED178001A7CFF /* JSDataCueCustom.cpp */; };
                07FE99DC18807A7D00256648 /* HTMLMediaSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07FE99DA18807A7D00256648 /* HTMLMediaSession.cpp */; };
                CD5393D4175E018600C07123 /* JSMemoryInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5393D2175E018600C07123 /* JSMemoryInfo.h */; };
                CD54A762180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD54A760180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.cpp */; };
                CD54A763180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CD54A761180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.h */; };
-               CD54DE4717468B6F005E5B36 /* MediaSessionManagerMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD54DE4517468B6F005E5B36 /* MediaSessionManagerMac.cpp */; };
                CD54DE4B17469C6D005E5B36 /* AudioSessionMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD54DE4917469C6D005E5B36 /* AudioSessionMac.cpp */; };
                CD5596911475B678001D0BD0 /* AudioFileReaderIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD55968F1475B678001D0BD0 /* AudioFileReaderIOS.cpp */; };
                CD5596921475B678001D0BD0 /* AudioFileReaderIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5596901475B678001D0BD0 /* AudioFileReaderIOS.h */; };
                078E094817D1709600420AA1 /* MediaStreamAudioDestinationNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamAudioDestinationNode.cpp; sourceTree = "<group>"; };
                078E094917D1709600420AA1 /* MediaStreamAudioDestinationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamAudioDestinationNode.h; sourceTree = "<group>"; };
                078E094A17D1709600420AA1 /* MediaStreamAudioDestinationNode.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaStreamAudioDestinationNode.idl; sourceTree = "<group>"; };
+               079216531AA560AA00A3C049 /* MediaPlaybackTargetPickerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MediaPlaybackTargetPickerClient.h; path = graphics/MediaPlaybackTargetPickerClient.h; sourceTree = "<group>"; };
                0794178F166E855F009416C2 /* InbandTextTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InbandTextTrack.cpp; sourceTree = "<group>"; };
                07941790166E855F009416C2 /* InbandTextTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrack.h; sourceTree = "<group>"; };
                07941793166EA04E009416C2 /* InbandTextTrackPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivate.h; sourceTree = "<group>"; };
                07DC5FD317D3EEE90099F890 /* JSRTCStatsResponseCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRTCStatsResponseCustom.cpp; sourceTree = "<group>"; };
                07E116B01489C9A100EC5ACE /* JSTextTrackCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTextTrackCustom.cpp; sourceTree = "<group>"; };
                07E117061489EBEB00EC5ACE /* JSTextTrackCueCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTextTrackCueCustom.cpp; sourceTree = "<group>"; };
+               07E3DFD01A9E786500764CA8 /* MediaPlaybackTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTarget.h; sourceTree = "<group>"; };
+               07E3DFD21A9E78A500764CA8 /* MediaPlaybackTargetMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MediaPlaybackTargetMac.mm; path = platform/graphics/avfoundation/MediaPlaybackTargetMac.mm; sourceTree = SOURCE_ROOT; };
                07E9E12D18F5E2760011A3A4 /* InbandMetadataTextTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandMetadataTextTrackPrivateAVF.h; sourceTree = "<group>"; };
                07E9E12F18F62B370011A3A4 /* InbandMetadataTextTrackPrivateAVF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InbandMetadataTextTrackPrivateAVF.cpp; sourceTree = "<group>"; };
+               07EDC3ED1AACB75D00983EB5 /* MediaSessionManagerMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaSessionManagerMac.cpp; sourceTree = "<group>"; };
                07FBDE2B18FED178001A7CFF /* JSDataCueCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDataCueCustom.cpp; sourceTree = "<group>"; };
                07FE99DA18807A7D00256648 /* HTMLMediaSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLMediaSession.cpp; sourceTree = "<group>"; };
                07FE99DB18807A7D00256648 /* HTMLMediaSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLMediaSession.h; sourceTree = "<group>"; };
                CD5393D2175E018600C07123 /* JSMemoryInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMemoryInfo.h; sourceTree = "<group>"; };
                CD54A760180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioTrackPrivateMediaSourceAVFObjC.cpp; path = objc/AudioTrackPrivateMediaSourceAVFObjC.cpp; sourceTree = "<group>"; };
                CD54A761180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioTrackPrivateMediaSourceAVFObjC.h; path = objc/AudioTrackPrivateMediaSourceAVFObjC.h; sourceTree = "<group>"; };
-               CD54DE4517468B6F005E5B36 /* MediaSessionManagerMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaSessionManagerMac.cpp; sourceTree = "<group>"; };
                CD54DE4917469C6D005E5B36 /* AudioSessionMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioSessionMac.cpp; sourceTree = "<group>"; };
                CD55968F1475B678001D0BD0 /* AudioFileReaderIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioFileReaderIOS.cpp; path = ios/AudioFileReaderIOS.cpp; sourceTree = "<group>"; };
                CD5596901475B678001D0BD0 /* AudioFileReaderIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioFileReaderIOS.h; path = ios/AudioFileReaderIOS.h; sourceTree = "<group>"; };
                B27535490B053814002CE64F /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               07E3DFD21A9E78A500764CA8 /* MediaPlaybackTargetMac.mm */,
                                EDE3A4FF0C7A430600956A37 /* ColorMac.h */,
                                B275354A0B053814002CE64F /* ColorMac.mm */,
                                37C2360E1097EE7700EF9F72 /* ComplexTextController.cpp */,
                                FBC220DD1237FBEB00BCF788 /* opengl */,
                                3721493318F0B6D600156EDC /* opentype */,
                                49E911B20EF86D27009D0CAF /* transforms */,
+                               07E3DFD01A9E786500764CA8 /* MediaPlaybackTarget.h */,
                                490707E41219C04300D90E51 /* ANGLEWebKitBridge.cpp */,
                                490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */,
                                BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
                BCF1A5BA097832090061A123 /* platform */ = {
                        isa = PBXGroup;
                        children = (
+                               079216531AA560AA00A3C049 /* MediaPlaybackTargetPickerClient.h */,
                                49E912A40EFAC8E6009D0CAF /* animation */,
                                FD31604012B026A300C1A359 /* audio */,
                                1AE42F670AA4B8CB00C8612D /* cf */,
                FD3160B012B0270700C1A359 /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               07EDC3ED1AACB75D00983EB5 /* MediaSessionManagerMac.cpp */,
                                FD3160B512B0272A00C1A359 /* AudioBusMac.mm */,
                                FD3160B612B0272A00C1A359 /* AudioDestinationMac.cpp */,
                                FD3160B712B0272A00C1A359 /* AudioDestinationMac.h */,
                                CDC734121977896C0046BFC5 /* CARingBuffer.cpp */,
                                CDC734131977896C0046BFC5 /* CARingBuffer.h */,
                                FD3160BA12B0272A00C1A359 /* FFTFrameMac.cpp */,
-                               CD54DE4517468B6F005E5B36 /* MediaSessionManagerMac.cpp */,
                        );
                        path = mac;
                        sourceTree = "<group>";
                                BCB16C1C0979C3BD00467741 /* CachedImage.h in Headers */,
                                319FBD5F15D2F464009640A6 /* CachedImageClient.h in Headers */,
                                510184690B08602A004A825F /* CachedPage.h in Headers */,
+                               07E3DFD11A9E786500764CA8 /* MediaPlaybackTarget.h in Headers */,
                                D0EDA775143E303C0028E383 /* CachedRawResource.h in Headers */,
                                E1B533491717DEE300F205F9 /* CachedRawResourceClient.h in Headers */,
                                BCB16C200979C3BD00467741 /* CachedResource.h in Headers */,
                                9391A991162746CB00297330 /* ScrollingCoordinatorMac.h in Headers */,
                                93C38BFF164473C700091EB2 /* ScrollingStateFixedNode.h in Headers */,
                                0FEA3E7B191B2FC5000F1B55 /* ScrollingStateFrameScrollingNode.h in Headers */,
+                               079216551AA560AA00A3C049 /* MediaPlaybackTargetPickerClient.h in Headers */,
                                931CBD0D161A44E900E4C874 /* ScrollingStateNode.h in Headers */,
                                0FEA3E84191B31BF000F1B55 /* ScrollingStateOverflowScrollingNode.h in Headers */,
                                931CBD0F161A44E900E4C874 /* ScrollingStateScrollingNode.h in Headers */,
                                FD315FF812B0267600C1A359 /* AudioBuffer.cpp in Sources */,
                                FD315FFB12B0267600C1A359 /* AudioBufferSourceNode.cpp in Sources */,
                                FD31607B12B026F700C1A359 /* AudioBus.cpp in Sources */,
+                               07EDC3EE1AACB75D00983EB5 /* MediaSessionManagerMac.cpp in Sources */,
                                FD3160BB12B0272A00C1A359 /* AudioBusMac.mm in Sources */,
                                FD31607D12B026F700C1A359 /* AudioChannel.cpp in Sources */,
                                FD31600412B0267600C1A359 /* AudioContext.cpp in Sources */,
                                9BAB6C6D12550631001626D4 /* EditingStyle.cpp in Sources */,
                                4B3043CC0AE0373B00A82647 /* Editor.cpp in Sources */,
                                93A38B4B0D0E5808006872C2 /* EditorCommand.cpp in Sources */,
+                               0760C17A1AA8FC7D009ED7B8 /* MediaPlaybackTargetMac.mm in Sources */,
                                FED13D3A0CEA934600D89466 /* EditorIOS.mm in Sources */,
                                ED501DC60B249F2900AE18D9 /* EditorMac.mm in Sources */,
                                A8C4A80809D563270003AC8D /* Element.cpp in Sources */,
                                070E091B1875EF71003A1D3C /* MediaSession.cpp in Sources */,
                                CDAE8C091746B95700532D78 /* MediaSessionManager.cpp in Sources */,
                                07638A9A1884487200E15A1B /* MediaSessionManagerIOS.mm in Sources */,
-                               CD54DE4717468B6F005E5B36 /* MediaSessionManagerMac.cpp in Sources */,
                                CD3A495E17A9D01B00274E42 /* MediaSource.cpp in Sources */,
                                CDC8B5A6180474F70016E685 /* MediaSourcePrivateAVFObjC.mm in Sources */,
                                CD61FE671794AADB004101EB /* MediaSourceRegistry.cpp in Sources */,
index b279193..1438b98 100644 (file)
 #include <replay/InputCursor.h>
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "HTMLVideoElement.h"
+#endif
+
 using namespace WTF;
 using namespace Unicode;
 
@@ -6451,4 +6455,82 @@ void Document::setInputCursor(PassRefPtr<InputCursor> cursor)
 }
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+void Document::showPlaybackTargetPicker(const HTMLMediaElement& element)
+{
+    Page* page = this->page();
+    if (!page)
+        return;
+
+    page->showPlaybackTargetPicker(this, view()->lastKnownMousePosition(), is<HTMLVideoElement>(element));
+}
+
+void Document::addPlaybackTargetPickerClient(MediaPlaybackTargetPickerClient& client)
+{
+    Page* page = this->page();
+    if (!page)
+        return;
+
+    m_playbackTargetClients.add(&client);
+
+    client.didChoosePlaybackTarget(page->playbackTarget());
+    client.externalOutputDeviceAvailableDidChange(page->hasWirelessPlaybackTarget());
+}
+
+void Document::removePlaybackTargetPickerClient(MediaPlaybackTargetPickerClient& client)
+{
+    m_playbackTargetClients.remove(&client);
+    configurePlaybackTargetMonitoring();
+}
+
+void Document::configurePlaybackTargetMonitoring()
+{
+    Page* page = this->page();
+    if (!page)
+        return;
+
+    page->configurePlaybackTargetMonitoring();
+}
+
+bool Document::requiresPlaybackTargetRouteMonitoring()
+{
+    for (auto* client : m_playbackTargetClients) {
+        if (client->requiresPlaybackTargetRouteMonitoring()) {
+            return true;
+            break;
+        }
+    }
+
+    return false;
+}
+
+void Document::playbackTargetAvailabilityDidChange(bool available)
+{
+    if (m_playbackTargetsAvailable == available)
+        return;
+    m_playbackTargetsAvailable = available;
+
+    for (auto* client : m_playbackTargetClients)
+        client->externalOutputDeviceAvailableDidChange(available);
+}
+
+void Document::didChoosePlaybackTarget(MediaPlaybackTarget& device)
+{
+    MediaPlaybackTargetPickerClient* clientThatRequestedPicker = nullptr;
+
+    for (auto* client : m_playbackTargetClients) {
+        if (client->requestedPlaybackTargetPicker()) {
+            clientThatRequestedPicker = client;
+            continue;
+        }
+
+        client->didChoosePlaybackTarget(device);
+    }
+
+    if (clientThatRequestedPicker)
+        clientThatRequestedPicker->didChoosePlaybackTarget(device);
+}
+
+#endif
+
 } // namespace WebCore
index ca63843..040650b 100644 (file)
@@ -124,6 +124,8 @@ class LiveNodeList;
 class JSNode;
 class Locale;
 class MediaCanStartListener;
+class MediaPlaybackTarget;
+class MediaPlaybackTargetPickerClient;
 class MediaQueryList;
 class MediaQueryMatcher;
 class MouseEventWithHitTestResults;
@@ -1218,6 +1220,16 @@ public:
     void pageMutedStateDidChange();
     WeakPtr<Document> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    void showPlaybackTargetPicker(const HTMLMediaElement&);
+    void didChoosePlaybackTarget(MediaPlaybackTarget&);
+    void addPlaybackTargetPickerClient(MediaPlaybackTargetPickerClient&);
+    void removePlaybackTargetPickerClient(MediaPlaybackTargetPickerClient&);
+    bool requiresPlaybackTargetRouteMonitoring();
+    void configurePlaybackTargetMonitoring();
+    void playbackTargetAvailabilityDidChange(bool);
+#endif
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1655,6 +1667,11 @@ private:
 
     HashSet<AudioProducer*> m_audioProducers;
     bool m_isPlayingAudio;
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    HashSet<WebCore::MediaPlaybackTargetPickerClient*> m_playbackTargetClients;
+    bool m_playbackTargetsAvailable { false };
+#endif
 };
 
 inline void Document::notifyRemovePendingSheetIfNeeded()
index 71dd636..c7e69f3 100644 (file)
@@ -426,6 +426,8 @@ HTMLMediaElement::~HTMLMediaElement()
 
 void HTMLMediaElement::registerWithDocument(Document& document)
 {
+    m_mediaSession->registerWithDocument(document);
+
     if (m_isWaitingUntilMediaCanStart)
         document.addMediaCanStartListener(this);
 
@@ -451,6 +453,8 @@ void HTMLMediaElement::registerWithDocument(Document& document)
 
 void HTMLMediaElement::unregisterWithDocument(Document& document)
 {
+    m_mediaSession->unregisterWithDocument(document);
+
     if (m_isWaitingUntilMediaCanStart)
         document.removeMediaCanStartListener(this);
 
@@ -2471,6 +2475,9 @@ void HTMLMediaElement::refreshCachedTime() const
 
 void HTMLMediaElement::invalidateCachedTime() const
 {
+    if (!m_player->maximumDurationToCacheMediaTime())
+        return;
+
 #if !LOG_DISABLED
     if (m_cachedTime.isValid())
         LOG(Media, "HTMLMediaElement::invalidateCachedTime(%p)", this);
@@ -4856,6 +4863,13 @@ void HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent()
     event->setTarget(this);
     m_asyncEventQueue.enqueueEvent(event.release());
 }
+
+void HTMLMediaElement::setWirelessPlaybackTarget(const MediaPlaybackTarget& device)
+{
+    LOG(Media, "HTMLMediaElement::setWirelessPlaybackTarget(%p)", this);
+    if (m_player)
+        m_player->setWirelessPlaybackTarget(device);
+}
 #endif
 
 double HTMLMediaElement::minFastReverseRate() const
index 41590ad..9e6190b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -357,7 +357,9 @@ public:
 
     virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) override;
     virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) override;
+
     virtual void wirelessRoutesAvailableDidChange() override;
+    virtual void setWirelessPlaybackTarget(const MediaPlaybackTarget&) override;
 #endif
 
     // EventTarget function.
index f35654e..513e6a7 100644 (file)
@@ -31,7 +31,9 @@
 
 #include "Chrome.h"
 #include "ChromeClient.h"
+#include "Document.h"
 #include "Frame.h"
+#include "FrameView.h"
 #include "HTMLMediaElement.h"
 #include "HTMLNames.h"
 #include "Logging.h"
@@ -72,8 +74,28 @@ static const char* restrictionName(HTMLMediaSession::BehaviorRestrictions restri
 HTMLMediaSession::HTMLMediaSession(MediaSessionClient& client)
     : MediaSession(client)
     , m_restrictions(NoRestrictions)
-    , m_hasPlaybackTargetAvailabilityListeners(false)
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    , m_targetAvailabilityChangedTimer(*this, &HTMLMediaSession::targetAvailabilityChangedTimerFired)
+#endif
+{
+}
+
+void HTMLMediaSession::registerWithDocument(Document& document)
 {
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    document.addPlaybackTargetPickerClient(*this);
+#else
+    UNUSED_PARAM(document);
+#endif
+}
+
+void HTMLMediaSession::unregisterWithDocument(Document& document)
+{
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    document.removePlaybackTargetPickerClient(*this);
+#else
+    UNUSED_PARAM(document);
+#endif
 }
 
 void HTMLMediaSession::addBehaviorRestriction(BehaviorRestrictions restriction)
@@ -177,19 +199,20 @@ void HTMLMediaSession::showPlaybackTargetPicker(const HTMLMediaElement& element)
     if (!showingPlaybackTargetPickerPermitted(element))
         return;
 
-#if PLATFORM(IOS)
-    element.document().frame()->page()->chrome().client().showPlaybackTargetPicker(element.hasVideo());
-#endif
+    m_haveRequestedPlaybackTargetPicker = true;
+    element.document().showPlaybackTargetPicker(element);
 }
 
-bool HTMLMediaSession::hasWirelessPlaybackTargets(const HTMLMediaElement& element) const
+bool HTMLMediaSession::hasWirelessPlaybackTargets(const HTMLMediaElement&) const
 {
-    UNUSED_PARAM(element);
+#if PLATFORM(IOS)
+    // FIXME: consolidate Mac and iOS implementations
+    m_hasPlaybackTargets = MediaSessionManager::sharedManager().hasWirelessTargetsAvailable();
+#endif
 
-    bool hasTargets = MediaSessionManager::sharedManager().hasWirelessTargetsAvailable();
-    LOG(Media, "HTMLMediaSession::hasWirelessPlaybackTargets - returning %s", hasTargets ? "TRUE" : "FALSE");
+    LOG(Media, "HTMLMediaSession::hasWirelessPlaybackTargets - returning %s", m_hasPlaybackTargets ? "TRUE" : "FALSE");
 
-    return hasTargets;
+    return m_hasPlaybackTargets;
 }
 
 bool HTMLMediaSession::wirelessVideoPlaybackDisabled(const HTMLMediaElement& element) const
@@ -244,7 +267,38 @@ void HTMLMediaSession::setHasPlaybackTargetAvailabilityListeners(const HTMLMedia
     UNUSED_PARAM(element);
 
     m_hasPlaybackTargetAvailabilityListeners = hasListeners;
+
+#if PLATFORM(IOS)
     MediaSessionManager::sharedManager().configureWireLessTargetMonitoring();
+#else
+    element.document().configurePlaybackTargetMonitoring();
+#endif
+}
+
+void HTMLMediaSession::didChoosePlaybackTarget(MediaPlaybackTarget& device)
+{
+    m_haveRequestedPlaybackTargetPicker = false;
+    client().setWirelessPlaybackTarget(device);
+}
+
+void HTMLMediaSession::targetAvailabilityChangedTimerFired()
+{
+    client().wirelessRoutesAvailableDidChange();
+}
+
+void HTMLMediaSession::externalOutputDeviceAvailableDidChange(bool hasTargets) const
+{
+    if (m_hasPlaybackTargets == hasTargets)
+        return;
+
+    m_hasPlaybackTargets = hasTargets;
+    if (!m_targetAvailabilityChangedTimer.isActive())
+        m_targetAvailabilityChangedTimer.startOneShot(0);
+}
+
+bool HTMLMediaSession::requiresPlaybackTargetRouteMonitoring() const
+{
+    return m_hasPlaybackTargetAvailabilityListeners;
 }
 #endif
 
index a361e8f..da3f26c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "MediaPlayer.h"
 #include "MediaSession.h"
+#include "Timer.h"
 
 namespace WebCore {
 
+class Document;
 class HTMLMediaElement;
 class SourceBuffer;
 
@@ -41,14 +43,17 @@ public:
     explicit HTMLMediaSession(MediaSessionClient&);
     virtual ~HTMLMediaSession() { }
 
+    void registerWithDocument(Document&);
+    void unregisterWithDocument(Document&);
+
     bool playbackPermitted(const HTMLMediaElement&) const;
     bool dataLoadingPermitted(const HTMLMediaElement&) const;
     bool fullscreenPermitted(const HTMLMediaElement&) const;
     bool pageAllowsDataLoading(const HTMLMediaElement&) const;
     bool pageAllowsPlaybackAfterResuming(const HTMLMediaElement&) const;
+
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     bool showingPlaybackTargetPickerPermitted(const HTMLMediaElement&) const;
-
     bool currentPlaybackTargetIsWireless(const HTMLMediaElement&) const;
     void showPlaybackTargetPicker(const HTMLMediaElement&);
     bool hasWirelessPlaybackTargets(const HTMLMediaElement&) const;
@@ -58,6 +63,7 @@ public:
 
     void setHasPlaybackTargetAvailabilityListeners(const HTMLMediaElement&, bool);
 #endif
+
     bool requiresFullscreenForVideoPlayback(const HTMLMediaElement&) const;
     WEBCORE_EXPORT bool allowsAlternateFullscreen(const HTMLMediaElement&) const;
     MediaPlayer::Preload effectivePreloadForElement(const HTMLMediaElement&) const;
@@ -87,10 +93,25 @@ public:
 #endif
 
 private:
-    virtual bool requiresPlaybackTargetRouteMonitoring() const override { return m_hasPlaybackTargetAvailabilityListeners; }
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    void targetAvailabilityChangedTimerFired();
+
+    // MediaPlaybackTargetPickerClient
+    virtual void didChoosePlaybackTarget(MediaPlaybackTarget&) override;
+    virtual void externalOutputDeviceAvailableDidChange(bool) const override;
+    virtual bool requiresPlaybackTargetRouteMonitoring() const override;
+    virtual bool requestedPlaybackTargetPicker() const override { return m_haveRequestedPlaybackTargetPicker; }
+#endif
 
     BehaviorRestrictions m_restrictions;
-    bool m_hasPlaybackTargetAvailabilityListeners;
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    mutable Timer m_targetAvailabilityChangedTimer;
+    bool m_hasPlaybackTargetAvailabilityListeners { false };
+    mutable bool m_hasPlaybackTargets { false };
+    mutable bool m_haveRequestedPlaybackTargetPicker { false };
+#endif
 };
 
 }
index 74204c3..b9293b5 100644 (file)
@@ -447,6 +447,12 @@ public:
 
     virtual void handleAutoFillButtonClick(HTMLInputElement&) { }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    virtual void showPlaybackTargetPicker(const WebCore::IntPoint&, bool) { }
+    virtual void startingMonitoringPlaybackTargets() { }
+    virtual void stopMonitoringPlaybackTargets() { }
+#endif
+
 protected:
     virtual ~ChromeClient() { }
 };
index 9e5cada..4d3d5e3 100644 (file)
 #include <replay/InputCursor.h>
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "HTMLVideoElement.h"
+#include "MediaPlaybackTarget.h"
+#include "MediaPlaybackTargetPickerClient.h"
+#endif
+
 namespace WebCore {
 
 static HashSet<Page*>* allPages;
@@ -1691,4 +1697,67 @@ void Page::setSessionID(SessionID sessionID)
         view->privateBrowsingStateChanged(sessionID.isEphemeral());
 }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+void Page::showPlaybackTargetPicker(Document* document, const WebCore::IntPoint& location, bool isVideo)
+{
+
+    m_documentRequestingPlaybackTargetPicker = document;
+#if PLATFORM(IOS)
+    // FIXME: refactor iOS implementation.
+    UNUSED_PARAM(location);
+    chrome().client().showPlaybackTargetPicker(isVideo);
+#else
+    chrome().client().showPlaybackTargetPicker(location, isVideo);
+#endif
+}
+
+void Page::didChoosePlaybackTarget(MediaPlaybackTarget& target)
+{
+    Document* documentThatRequestedPicker = nullptr;
+
+    m_playbackTarget = std::make_unique<MediaPlaybackTarget>(target.devicePickerContext());
+    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        Document* document = frame->document();
+        if (frame->document() == m_documentRequestingPlaybackTargetPicker) {
+            documentThatRequestedPicker = document;
+            continue;
+        }
+        frame->document()->didChoosePlaybackTarget(target);
+    }
+
+    if (documentThatRequestedPicker)
+        documentThatRequestedPicker->didChoosePlaybackTarget(target);
+
+    m_documentRequestingPlaybackTargetPicker = nullptr;
+}
+
+void Page::playbackTargetAvailabilityDidChange(bool available)
+{
+    m_hasWirelessPlaybackTarget = available;
+    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
+        frame->document()->playbackTargetAvailabilityDidChange(available);
+}
+
+void Page::configurePlaybackTargetMonitoring()
+{
+    bool monitoringRequired = false;
+    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        if (frame->document()->requiresPlaybackTargetRouteMonitoring()) {
+            monitoringRequired = true;
+            break;
+        }
+    }
+
+    if (m_requiresPlaybackTargetMonitoring == monitoringRequired)
+        return;
+    m_requiresPlaybackTargetMonitoring = monitoringRequired;
+
+
+    if (monitoringRequired)
+        chrome().client().startingMonitoringPlaybackTargets();
+    else
+        chrome().client().stopMonitoringPlaybackTargets();
+}
+#endif
+
 } // namespace WebCore
index 4b53783..afd5dc0 100644 (file)
@@ -76,11 +76,13 @@ class FocusController;
 class Frame;
 class FrameLoaderClient;
 class HistoryItem;
+class HTMLMediaElement;
 class UserInputBridge;
 class InspectorClient;
 class InspectorController;
 class MainFrame;
 class MediaCanStartListener;
+class MediaPlaybackTarget;
 class PageConfiguration;
 class PageConsoleClient;
 class PageDebuggable;
@@ -422,6 +424,16 @@ public:
     bool isMuted() const { return m_muted; }
     WEBCORE_EXPORT void setMuted(bool);
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    void showPlaybackTargetPicker(Document*, const WebCore::IntPoint&, bool);
+    bool hasWirelessPlaybackTarget() const { return m_hasWirelessPlaybackTarget; }
+    MediaPlaybackTarget& playbackTarget() const { return *m_playbackTarget.get(); }
+    void configurePlaybackTargetMonitoring();
+
+    WEBCORE_EXPORT void didChoosePlaybackTarget(MediaPlaybackTarget&);
+    WEBCORE_EXPORT void playbackTargetAvailabilityDidChange(bool);
+#endif
+
 private:
     WEBCORE_EXPORT void initGroup();
 
@@ -581,6 +593,13 @@ private:
 
     SessionID m_sessionID;
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    Document* m_documentRequestingPlaybackTargetPicker { nullptr };
+    std::unique_ptr<MediaPlaybackTarget> m_playbackTarget;
+    bool m_requiresPlaybackTargetMonitoring { false };
+    bool m_hasWirelessPlaybackTarget { false };
+#endif
+
     bool m_isClosing;
 
     bool m_isPlayingAudio;
index 5ca6efb..6f68d70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -190,7 +190,7 @@ void MediaSession::visibilityChanged()
 
 void MediaSession::clientDataBufferingTimerFired()
 {
-    LOG(Media, "MediaSession::visibilityChanged(%p)- visible = %s", this, m_client.elementIsHidden() ? "false" : "true");
+    LOG(Media, "MediaSession::clientDataBufferingTimerFired(%p)- visible = %s", this, m_client.elementIsHidden() ? "false" : "true");
 
     updateClientDataBuffering();
 
@@ -220,11 +220,6 @@ MediaSession::DisplayType MediaSession::displayType() const
     return m_client.displayType();
 }
 
-void MediaSession::wirelessRoutesAvailableDidChange() const
-{
-    m_client.wirelessRoutesAvailableDidChange();
-}
-
 String MediaSessionClient::mediaSessionTitle() const
 {
     return String();
index 3d54c46..c2ef3c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <wtf/Noncopyable.h>
 #include <wtf/text/WTFString.h>
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "MediaPlaybackTargetPickerClient.h"
+#endif
+
 namespace WebCore {
 
+class MediaPlaybackTarget;
 class MediaSessionClient;
 
-class MediaSession {
+class MediaSession
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    : public MediaPlaybackTargetPickerClient
+#endif
+{
 public:
     static std::unique_ptr<MediaSession> create(MediaSessionClient&);
 
@@ -99,9 +108,6 @@ public:
     bool canReceiveRemoteControlCommands() const;
     void didReceiveRemoteControlCommand(RemoteControlCommandType);
 
-    virtual bool requiresPlaybackTargetRouteMonitoring() const { return false; }
-    void wirelessRoutesAvailableDidChange() const;
-
     enum DisplayType {
         Normal,
         Fullscreen,
@@ -111,6 +117,14 @@ public:
 
     bool isHidden() const;
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    // MediaPlaybackTargetPickerClient
+    virtual void didChoosePlaybackTarget(MediaPlaybackTarget&) override { }
+    virtual void externalOutputDeviceAvailableDidChange(bool) const override { }
+    virtual bool requiresPlaybackTargetRouteMonitoring() const override { return false; }
+    virtual bool requestedPlaybackTargetPicker() const override { return false; }
+#endif
+
 protected:
     MediaSessionClient& client() const { return m_client; }
 
@@ -150,7 +164,10 @@ public:
 
     virtual bool overrideBackgroundPlaybackRestriction() const = 0;
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
     virtual void wirelessRoutesAvailableDidChange() { }
+    virtual void setWirelessPlaybackTarget(const MediaPlaybackTarget&) { }
+#endif
 
 protected:
     virtual ~MediaSessionClient() { }
index 2a01997..e130c2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -285,14 +285,6 @@ void MediaSessionManager::applicationWillEnterForeground() const
     }
 }
 
-void MediaSessionManager::wirelessRoutesAvailableChanged()
-{
-    LOG(Media, "MediaSessionManager::wirelessRoutesAvailableChanged");
-    Vector<MediaSession*> sessions = m_sessions;
-    for (auto* session : sessions)
-        session->wirelessRoutesAvailableDidChange();
-}
-
 #if !PLATFORM(COCOA)
 void MediaSessionManager::updateSessionState()
 {
index a03c5f3..c45595e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,7 +54,6 @@ public:
 
     WEBCORE_EXPORT void applicationWillEnterForeground() const;
     WEBCORE_EXPORT void applicationWillEnterBackground() const;
-    void wirelessRoutesAvailableChanged();
 
     enum SessionRestrictionFlags {
         NoRestrictions = 0,
@@ -79,9 +78,8 @@ public:
 
     virtual bool sessionCanLoadMedia(const MediaSession&) const;
 
+#if PLATFORM(IOS)
     virtual void configureWireLessTargetMonitoring() { }
-
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
     virtual bool hasWirelessTargetsAvailable() { return false; }
 #endif
 
index 9657d1a..61cc021 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,9 +45,14 @@ class MediaSessionManageriOS : public MediaSessionManager {
 public:
     virtual ~MediaSessionManageriOS();
 
+    void externalOutputDeviceAvailableDidChange();
+    virtual bool hasWirelessTargetsAvailable() override;
+
 private:
     friend class MediaSessionManager;
 
+    MediaSessionManageriOS();
+
     virtual void sessionWillBeginPlayback(MediaSession&) override;
     virtual void sessionWillEndPlayback(MediaSession&) override;
     
@@ -55,14 +60,10 @@ private:
     
     virtual void resetRestrictions() override;
 
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
-    virtual bool hasWirelessTargetsAvailable() override;
     virtual void configureWireLessTargetMonitoring() override;
-#endif
 
     virtual bool sessionCanLoadMedia(const MediaSession&) const override;
-
-    MediaSessionManageriOS();
+    
     RetainPtr<WebMediaSessionHelper> m_objcObserver;
 };
 
index d845c46..9a6a0e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -159,7 +159,6 @@ void MediaSessionManageriOS::resetRestrictions()
     addRestriction(MediaSession::Video, AutoPreloadingNotPermitted);
 }
 
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
 bool MediaSessionManageriOS::hasWirelessTargetsAvailable()
 {
     return [m_objcObserver hasWirelessTargetsAvailable];
@@ -184,8 +183,7 @@ void MediaSessionManageriOS::configureWireLessTargetMonitoring()
     else
         [m_objcObserver stopMonitoringAirPlayRoutes];
 }
-#endif
-    
+
 void MediaSessionManageriOS::sessionWillBeginPlayback(MediaSession& session)
 {
     MediaSessionManager::sessionWillBeginPlayback(session);
@@ -233,6 +231,14 @@ bool MediaSessionManageriOS::sessionCanLoadMedia(const MediaSession& session) co
     return session.state() == MediaSession::Playing || !session.isHidden() || session.displayType() == MediaSession::Optimized;
 }
 
+void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange()
+{
+    Vector<MediaSession*> sessionList = sessions();
+    bool haveTargets = [m_objcObserver hasWirelessTargetsAvailable];
+    for (auto* session : sessionList)
+        session->externalOutputDeviceAvailableDidChange(haveTargets);
+}
+
 } // namespace WebCore
 
 @implementation WebMediaSessionHelper
@@ -445,7 +451,7 @@ bool MediaSessionManageriOS::sessionCanLoadMedia(const MediaSession& session) co
         if (!_callback)
             return;
 
-        _callback->wirelessRoutesAvailableChanged();
+        _callback->externalOutputDeviceAvailableDidChange();
     });
 }
 @end
diff --git a/Source/WebCore/platform/graphics/MediaPlaybackTarget.h b/Source/WebCore/platform/graphics/MediaPlaybackTarget.h
new file mode 100644 (file)
index 0000000..85d5952
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MediaPlaybackTarget_h
+#define MediaPlaybackTarget_h
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#include <wtf/RetainPtr.h>
+
+#if PLATFORM(COCOA)
+OBJC_CLASS NSKeyedArchiver;
+OBJC_CLASS NSKeyedUnarchiver;
+OBJC_CLASS AVOutputDevicePickerContext;
+#endif
+
+namespace WebCore {
+
+class MediaPlaybackTarget {
+public:
+    virtual ~MediaPlaybackTarget() { }
+
+#if PLATFORM(COCOA)
+    WEBCORE_EXPORT MediaPlaybackTarget(AVOutputDevicePickerContext *context = nil) { m_devicePickerContext = context; }
+
+    WEBCORE_EXPORT void encode(NSKeyedArchiver *) const;
+    WEBCORE_EXPORT static bool decode(NSKeyedUnarchiver *, MediaPlaybackTarget&);
+
+    void setDevicePickerContext(AVOutputDevicePickerContext *context) { m_devicePickerContext = context; }
+    AVOutputDevicePickerContext *devicePickerContext() const { return m_devicePickerContext.get(); }
+#endif
+
+protected:
+#if PLATFORM(COCOA)
+    RetainPtr<AVOutputDevicePickerContext> m_devicePickerContext;
+#endif
+};
+
+}
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/MediaPlaybackTargetPickerClient.h b/Source/WebCore/platform/graphics/MediaPlaybackTargetPickerClient.h
new file mode 100644 (file)
index 0000000..6d8fceb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaPlaybackTargetPickerClient_h
+#define MediaPlaybackTargetPickerClient_h
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#include "MediaPlaybackTarget.h"
+
+namespace WebCore {
+
+class MediaPlaybackTarget;
+
+class MediaPlaybackTargetPickerClient {
+public:
+    virtual ~MediaPlaybackTargetPickerClient() { }
+
+    virtual void didChoosePlaybackTarget(MediaPlaybackTarget&) = 0;
+    virtual void externalOutputDeviceAvailableDidChange(bool) const = 0;
+
+    virtual bool requiresPlaybackTargetRouteMonitoring() const = 0;
+    virtual bool requestedPlaybackTargetPicker() const = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#endif // MediaPlaybackTargetPickerClient_h
index 7a7684c..ecb5729 100644 (file)
@@ -867,6 +867,11 @@ void MediaPlayer::currentPlaybackTargetIsWirelessChanged()
 {
     m_client.mediaPlayerCurrentPlaybackTargetIsWirelessChanged(this);
 }
+
+void MediaPlayer::setWirelessPlaybackTarget(const MediaPlaybackTarget& device)
+{
+    m_private->setWirelessPlaybackTarget(device);
+}
 #endif
 
 double MediaPlayer::maxFastForwardRate() const
index bc54a59..41b4be0 100644 (file)
@@ -71,6 +71,7 @@ namespace WebCore {
 
 class AudioSourceProvider;
 class AuthenticationChallenge;
+class MediaPlaybackTarget;
 #if ENABLE(MEDIA_SOURCE)
 class MediaSourcePrivateClient;
 #endif
@@ -476,6 +477,8 @@ public:
 
     void currentPlaybackTargetIsWirelessChanged();
     void playbackTargetAvailabilityChanged();
+
+    void setWirelessPlaybackTarget(const MediaPlaybackTarget&);
 #endif
 
     double minFastReverseRate() const;
index 12f6fd8..70f4156 100644 (file)
@@ -36,6 +36,7 @@ namespace WebCore {
 
 class IntRect;
 class IntSize;
+class MediaPlaybackTarget;
 class PlatformTextTrack;
 
 class MediaPlayerPrivateInterface {
@@ -166,6 +167,8 @@ public:
 
     virtual bool wirelessVideoPlaybackDisabled() const { return false; }
     virtual void setWirelessVideoPlaybackDisabled(bool) { }
+
+    virtual void setWirelessPlaybackTarget(const MediaPlaybackTarget&) { }
 #endif
 
 #if USE(NATIVE_FULLSCREEN_VIDEO)
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetMac.mm b/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetMac.mm
new file mode 100644 (file)
index 0000000..4450475
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "config.h"
+#import "MediaPlaybackTarget.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#import <AVFoundation/AVOutputDevicePickerContext.h>
+#import <WebCore/MediaPlaybackTarget.h>
+#import <WebCore/SoftLinking.h>
+#import <objc/runtime.h>
+
+typedef AVOutputDevicePickerContext AVOutputDevicePickerContextType;
+
+SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
+SOFT_LINK_CLASS(AVFoundation, AVOutputDevicePickerContext)
+
+namespace WebCore {
+
+static NSString * const deviceContextKey = @"deviceContext";
+
+void MediaPlaybackTarget::encode(NSKeyedArchiver *archiver) const
+{
+    if ([getAVOutputDevicePickerContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
+        [archiver encodeObject:m_devicePickerContext.get() forKey:deviceContextKey];
+}
+
+bool MediaPlaybackTarget::decode(NSKeyedUnarchiver *unarchiver, MediaPlaybackTarget& playbackTarget)
+{
+    if (![getAVOutputDevicePickerContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
+        return false;
+
+    AVOutputDevicePickerContext *context = nil;
+
+    @try {
+        context = [unarchiver decodeObjectOfClass:getAVOutputDevicePickerContextClass() forKey:deviceContextKey];
+    } @catch (NSException *exception) {
+        LOG_ERROR("The target picker being decoded is not a AVOutputDevicePickerContext.");
+    }
+
+    playbackTarget.m_devicePickerContext = context;
+
+    return context;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
index c40bcaa..ee661b8 100644 (file)
@@ -34,6 +34,7 @@
 OBJC_CLASS AVAssetImageGenerator;
 OBJC_CLASS AVAssetResourceLoadingRequest;
 OBJC_CLASS AVMediaSelectionGroup;
+OBJC_CLASS AVOutputDevicePickerContext;
 OBJC_CLASS AVPlayer;
 OBJC_CLASS AVPlayerItem;
 OBJC_CLASS AVPlayerItemLegibleOutput;
@@ -59,13 +60,14 @@ typedef struct OpaqueVTPixelTransferSession* VTPixelTransferSessionRef;
 
 namespace WebCore {
 
-class WebCoreAVFResourceLoader;
-class InbandMetadataTextTrackPrivateAVF;
-class InbandTextTrackPrivateAVFObjC;
 class AudioSourceProviderAVFObjC;
 class AudioTrackPrivateAVFObjC;
+class InbandMetadataTextTrackPrivateAVF;
+class InbandTextTrackPrivateAVFObjC;
+class MediaPlaybackTarget;
 class MediaSelectionGroupAVFObjC;
 class VideoTrackPrivateAVFObjC;
+class WebCoreAVFResourceLoader;
 
 class MediaPlayerPrivateAVFoundationObjC : public MediaPlayerPrivateAVFoundation {
 public:
@@ -274,6 +276,9 @@ private:
     virtual String wirelessPlaybackTargetName() const override;
     virtual MediaPlayer::WirelessPlaybackTargetType wirelessPlaybackTargetType() const override;
     virtual bool wirelessVideoPlaybackDisabled() const override;
+#if !PLATFORM(IOS)
+    virtual void setWirelessPlaybackTarget(const MediaPlaybackTarget&) override;
+#endif
     virtual void setWirelessVideoPlaybackDisabled(bool) override;
     void updateDisableExternalPlayback();
 #endif
@@ -345,6 +350,10 @@ private:
     RefPtr<InbandMetadataTextTrackPrivateAVF> m_metadataTrack;
 #endif
 
+#if PLATFORM(MAC) && ENABLE(WIRELESS_PLAYBACK_TARGET)
+    RetainPtr<AVOutputDevicePickerContext> m_outputDevicePickerContext;
+#endif
+
     mutable RetainPtr<NSArray> m_cachedSeekableRanges;
     mutable RetainPtr<NSArray> m_cachedLoadedRanges;
     RetainPtr<NSArray> m_cachedTracks;
index 6367817..d7f7717 100644 (file)
@@ -46,6 +46,7 @@
 #import "OutOfBandTextTrackPrivateAVF.h"
 #import "URL.h"
 #import "Logging.h"
+#import "MediaPlaybackTarget.h"
 #import "MediaSelectionGroupAVFObjC.h"
 #import "MediaTimeAVFoundation.h"
 #import "PlatformTimeRanges.h"
@@ -135,6 +136,14 @@ template <> struct iterator_traits<HashSet<RefPtr<WebCore::MediaSelectionOptionA
 @property (nonatomic, readonly) NSURL *resolvedURL;
 @end
 
+#if PLATFORM(MAC) && ENABLE(WIRELESS_PLAYBACK_TARGET)
+typedef AVOutputDevicePickerContext AVOutputDevicePickerContextType;
+
+@interface AVPlayer (WebKitExtensions)
+@property (nonatomic) AVOutputDevicePickerContext *outputDevicePickerContext;
+@end
+#endif
+
 typedef AVPlayer AVPlayerType;
 typedef AVPlayerItem AVPlayerItemType;
 typedef AVPlayerItemLegibleOutput AVPlayerItemLegibleOutputType;
@@ -546,6 +555,7 @@ void MediaPlayerPrivateAVFoundationObjC::cancelLoad()
         [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"rate"];
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
         [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"externalPlaybackActive"];
+        [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"outputDevicePickerContext"];
 #endif
         m_avPlayer = nil;
     }
@@ -927,6 +937,10 @@ void MediaPlayerPrivateAVFoundationObjC::createAVPlayer()
     [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"externalPlaybackActive" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+    [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"outputDevicePickerContext" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+#endif
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
     updateDisableExternalPlayback();
 #endif
 
@@ -938,6 +952,11 @@ void MediaPlayerPrivateAVFoundationObjC::createAVPlayer()
     [m_avPlayer.get() setAllowsExternalPlayback:m_allowsWirelessVideoPlayback];
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    if (m_outputDevicePickerContext)
+        m_avPlayer.get().outputDevicePickerContext = m_outputDevicePickerContext.get();
+#endif
+
     if (player()->client().mediaPlayerIsVideo())
         createAVPlayerLayer();
 
@@ -1134,9 +1153,8 @@ void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer(PlatformLayer*
         syncTextTrackBounds();
         [m_videoFullscreenLayer addSublayer:m_textTrackRepresentationLayer.get()];
     }
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+
     updateDisableExternalPlayback();
-#endif
 }
 
 void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenFrame(FloatRect frame)
@@ -2687,8 +2705,9 @@ bool MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless() const
     if (!m_avPlayer)
         return false;
 
-    bool wirelessTarget = [m_avPlayer.get() isExternalPlaybackActive];
+    bool wirelessTarget = m_avPlayer.get().externalPlaybackActive;
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless(%p) - returning %s", this, boolString(wirelessTarget));
+
     return wirelessTarget;
 }
 
@@ -2697,6 +2716,7 @@ MediaPlayer::WirelessPlaybackTargetType MediaPlayerPrivateAVFoundationObjC::wire
     if (!m_avPlayer)
         return MediaPlayer::TargetTypeNone;
 
+#if PLATFORM(IOS)
     switch (wkExernalDeviceTypeForPlayer(m_avPlayer.get())) {
     case wkExternalPlaybackTypeNone:
         return MediaPlayer::TargetTypeNone;
@@ -2708,6 +2728,10 @@ MediaPlayer::WirelessPlaybackTargetType MediaPlayerPrivateAVFoundationObjC::wire
 
     ASSERT_NOT_REACHED();
     return MediaPlayer::TargetTypeNone;
+
+#else
+    return MediaPlayer::TargetTypeAirPlay;
+#endif
 }
 
 String MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetName() const
@@ -2725,7 +2749,7 @@ bool MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled() const
 {
     if (!m_avPlayer)
         return !m_allowsWirelessVideoPlayback;
-    
+
     m_allowsWirelessVideoPlayback = [m_avPlayer.get() allowsExternalPlayback];
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::wirelessVideoPlaybackDisabled(%p) - returning %s", this, boolString(!m_allowsWirelessVideoPlayback));
 
@@ -2738,16 +2762,32 @@ void MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled(bool d
     m_allowsWirelessVideoPlayback = !disabled;
     if (!m_avPlayer)
         return;
-    
+
     [m_avPlayer.get() setAllowsExternalPlayback:!disabled];
 }
 
+#if !PLATFORM(IOS)
+void MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget(const MediaPlaybackTarget& target)
+{
+    m_outputDevicePickerContext = target.devicePickerContext();
+
+    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget(%p) - target = %p", this, m_outputDevicePickerContext.get());
+
+    if (!m_avPlayer)
+        return;
+
+    m_avPlayer.get().outputDevicePickerContext = m_outputDevicePickerContext.get();
+}
+#endif
+
 void MediaPlayerPrivateAVFoundationObjC::updateDisableExternalPlayback()
 {
     if (!m_avPlayer)
         return;
 
+#if PLATFORM(IOS)
     [m_avPlayer setUsesExternalPlaybackWhileExternalScreenIsActive:m_videoFullscreenLayer != nil];
+#endif
 }
 #endif
 
@@ -3169,6 +3209,8 @@ NSArray* assetTrackMetadataKeyNames()
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
         else if ([keyPath isEqualToString:@"externalPlaybackActive"])
             function = WTF::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
+        else if ([keyPath isEqualToString:@"outputDevicePickerContext"])
+            function = WTF::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
 #endif
     }
     
index 5ba50b8..7477ad6 100644 (file)
@@ -97,6 +97,9 @@ InternalSettings::Backup::Backup(Settings& settings)
 #if ENABLE(TOUCH_EVENTS)
     , m_touchEventEmulationEnabled(settings.isTouchEventEmulationEnabled())
 #endif
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    , m_mediaPlaybackAllowsAirPlay(settings.mediaPlaybackAllowsAirPlay())
+#endif
 {
 }
 
@@ -201,6 +204,9 @@ InternalSettings::InternalSettings(Page* page)
     , m_page(page)
     , m_backup(page->settings())
 {
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    page->settings().setMediaPlaybackAllowsAirPlay(false);
+#endif
 }
 
 void InternalSettings::resetToConsistentState()
index b78b81e..fb97b67 100644 (file)
@@ -95,6 +95,9 @@ public:
 #if ENABLE(TOUCH_EVENTS)
         bool m_touchEventEmulationEnabled;
 #endif
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+        bool m_mediaPlaybackAllowsAirPlay;
+#endif
     };
 
     static PassRefPtr<InternalSettings> create(Page* page)
index 6c340f9..9d1ca2b 100644 (file)
@@ -1,3 +1,71 @@
+2015-03-11  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Update AirPlay handling
+        https://bugs.webkit.org/show_bug.cgi?id=142541
+
+        Reviewed by Sam Weinig.
+
+        * Shared/WebCoreArgumentCoders.h:
+        * Shared/mac/WebCoreArgumentCodersMac.mm:
+        (IPC::ArgumentCoder<AVPlaybackTarget>::encode):
+        (IPC::ArgumentCoder<AVPlaybackTarget>::decode):
+        * UIProcess/PageClient.h:
+        * UIProcess/WebAVPlaybackTargetPickerProxy.cpp: Added.
+        (WebKit::WebAVPlaybackTargetPickerProxy::WebAVPlaybackTargetPickerProxy):
+        (WebKit::WebAVPlaybackTargetPickerProxy::~WebAVPlaybackTargetPickerProxy):
+        (WebKit::WebAVPlaybackTargetPickerProxy::showPlaybackTargetPicker):
+        (WebKit::WebAVPlaybackTargetPickerProxy::startingMonitoringPlaybackTargets):
+        (WebKit::WebAVPlaybackTargetPickerProxy::stopMonitoringPlaybackTargets):
+        * UIProcess/WebAVPlaybackTargetPickerProxy.h: Added.
+        (WebKit::WebAVPlaybackTargetPickerProxy::Client::~Client):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::devicePickerProxy):
+        (WebKit::WebPageProxy::showPlaybackTargetPicker):
+        (WebKit::WebPageProxy::startingMonitoringPlaybackTargets):
+        (WebKit::WebPageProxy::stopMonitoringPlaybackTargets):
+        (WebKit::WebPageProxy::didChoosePlaybackTarget):
+        (WebKit::WebPageProxy::externalOutputDeviceAvailableDidChange):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/mac/PageClientImpl.h:
+        * UIProcess/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::createPlaybackTargetPicker):
+        * UIProcess/mac/WebAVPlaybackTargetPickerProxyMac.h: Added.
+        * UIProcess/mac/WebAVPlaybackTargetPickerProxyMac.mm: Added.
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::create):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::WebAVPlaybackTargetPickerProxyMac):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::~WebAVPlaybackTargetPickerProxyMac):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::outputeDeviceAvailabilityChangedTimerFired):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::availableDevicesDidChange):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::devicePicker):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::showPlaybackTargetPicker):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::currentDeviceDidChange):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::startingMonitoringPlaybackTargets):
+        (WebKit::WebAVPlaybackTargetPickerProxyMac::stopMonitoringPlaybackTargets):
+        (-[WebAVOutputDevicePickerMenuControllerHelper initWithCallback:]):
+        (-[WebAVOutputDevicePickerMenuControllerHelper clearCallback]):
+        (-[WebAVOutputDevicePickerMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebAVPlaybackTargetPicker.cpp: Added.
+        (WebKit::WebAVPlaybackTargetPicker::WebAVPlaybackTargetPicker):
+        (WebKit::WebAVPlaybackTargetPicker::showPlaybackDevicePicker):
+        (WebKit::WebAVPlaybackTargetPicker::configureWireLessTargetMonitoring):
+        (WebKit::WebAVPlaybackTargetPicker::addClient):
+        (WebKit::WebAVPlaybackTargetPicker::removeClient):
+        (WebKit::WebAVPlaybackTargetPicker::didChoosePlaybackTarget):
+        (WebKit::WebAVPlaybackTargetPicker::playbackTargetAvailabilityDidChange):
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::showPlaybackTargetPicker):
+        (WebKit::WebChromeClient::startingMonitoringPlaybackTargets):
+        (WebKit::WebChromeClient::stopMonitoringPlaybackTargets):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::playbackTargetSelected):
+        (WebKit::WebPage::playbackTargetAvailabilityDidChange):
+        * WebProcess/com.apple.WebProcess.sb.in:
+
 2015-03-11  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Fix the build
index 4fe3157..81e83be 100644 (file)
@@ -115,6 +115,12 @@ class ContentFilterUnblockHandler;
 }
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+namespace WebCore {
+class MediaPlaybackTarget;
+}
+#endif
+
 namespace IPC {
 
 template<> struct ArgumentCoder<WebCore::AffineTransform> {
@@ -454,6 +460,13 @@ template<> struct ArgumentCoder<WebCore::TextIndicatorData> {
     static bool decode(ArgumentDecoder&, WebCore::TextIndicatorData&);
 };
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+template<> struct ArgumentCoder<WebCore::MediaPlaybackTarget> {
+    static void encode(ArgumentEncoder&, const WebCore::MediaPlaybackTarget&);
+    static bool decode(ArgumentDecoder&, WebCore::MediaPlaybackTarget&);
+};
+#endif
+
 } // namespace IPC
 
 #endif // WebCoreArgumentCoders_h
index a1acdda..aaff000 100644 (file)
 #import <WebCore/ProtectionSpace.h>
 #import <WebCore/ResourceError.h>
 #import <WebCore/ResourceRequest.h>
+#import <WebCore/SoftLinking.h>
+#import <objc/runtime.h>
 
 #if USE(CFNETWORK)
 #import <CFNetwork/CFURLRequest.h>
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#import <WebCore/MediaPlaybackTarget.h>
+#endif
+
 using namespace WebCore;
 
 namespace IPC {
@@ -432,4 +438,31 @@ bool ArgumentCoder<ContentFilterUnblockHandler>::decode(ArgumentDecoder& decoder
     return true;
 }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+void ArgumentCoder<MediaPlaybackTarget>::encode(ArgumentEncoder& encoder, const MediaPlaybackTarget& target)
+{
+    RetainPtr<NSMutableData> data = adoptNS([[NSMutableData alloc] init]);
+    RetainPtr<NSKeyedArchiver> archiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
+    [archiver setRequiresSecureCoding:YES];
+    target.encode(archiver.get());
+    [archiver finishEncoding];
+    IPC::encode(encoder, reinterpret_cast<CFDataRef>(data.get()));
+}
+
+bool ArgumentCoder<MediaPlaybackTarget>::decode(ArgumentDecoder& decoder, MediaPlaybackTarget& target)
+{
+    RetainPtr<CFDataRef> data;
+    if (!IPC::decode(decoder, data))
+        return false;
+
+    RetainPtr<NSKeyedUnarchiver> unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)data.get()]);
+    [unarchiver setRequiresSecureCoding:YES];
+    if (!MediaPlaybackTarget::decode(unarchiver.get(), target))
+        return false;
+    
+    [unarchiver finishDecoding];
+    return true;
+}
+#endif
+
 } // namespace IPC
index dc71b0a..6706755 100644 (file)
 #include <WebCore/EditorClient.h>
 #include <wtf/Forward.h>
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "WebMediaPlaybackTargetPickerProxy.h"
+#endif
+
 #if PLATFORM(COCOA)
 #include "PluginComplexTextInputState.h"
 
@@ -313,6 +317,11 @@ public:
 #if PLATFORM(MAC)
     virtual void didPerformActionMenuHitTest(const ActionMenuHitTestResult&, bool forImmediateAction, API::Object*) = 0;
 #endif
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    virtual std::unique_ptr<WebMediaPlaybackTargetPickerProxy> createPlaybackTargetPicker(WebPageProxy*) = 0;
+#endif
+
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.cpp b/Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.cpp
new file mode 100644 (file)
index 0000000..6c1f9f6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebMediaPlaybackTargetPickerProxy.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+namespace WebKit {
+
+WebMediaPlaybackTargetPickerProxy::WebMediaPlaybackTargetPickerProxy(Client& client)
+    : m_client(&client)
+{
+}
+
+WebMediaPlaybackTargetPickerProxy::~WebMediaPlaybackTargetPickerProxy()
+{
+    m_client = 0;
+}
+
+void WebMediaPlaybackTargetPickerProxy::showPlaybackTargetPicker(const WebCore::FloatRect&, bool)
+{
+    ASSERT_NOT_REACHED();
+    return;
+}
+
+void WebMediaPlaybackTargetPickerProxy::startingMonitoringPlaybackTargets()
+{
+    ASSERT_NOT_REACHED();
+    return;
+}
+
+void WebMediaPlaybackTargetPickerProxy::stopMonitoringPlaybackTargets()
+{
+    ASSERT_NOT_REACHED();
+    return;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
diff --git a/Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.h b/Source/WebKit2/UIProcess/WebMediaPlaybackTargetPickerProxy.h
new file mode 100644 (file)
index 0000000..c930dc1
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebMediaPlaybackTargetPickerProxy_h
+#define WebMediaPlaybackTargetPickerProxy_h
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+class FloatRect;
+class MediaPlaybackTarget;
+}
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebMediaPlaybackTargetPickerProxy {
+public:
+    class Client {
+    protected:
+        virtual ~Client() { }
+
+    public:
+        virtual void didChoosePlaybackTarget(const WebCore::MediaPlaybackTarget&) = 0;
+        virtual void externalOutputDeviceAvailableDidChange(bool) = 0;
+
+        void invalidate();
+    };
+
+    virtual ~WebMediaPlaybackTargetPickerProxy();
+
+    virtual void showPlaybackTargetPicker(const WebCore::FloatRect&, bool);
+    virtual void startingMonitoringPlaybackTargets();
+    virtual void stopMonitoringPlaybackTargets();
+
+protected:
+    explicit WebMediaPlaybackTargetPickerProxy(Client&);
+
+    Client* m_client;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
+
+#endif // WebMediaPlaybackTargetPickerProxy_h
index 076b577..27b9b09 100644 (file)
@@ -5597,4 +5597,47 @@ void WebPageProxy::handleAutoFillButtonClick(const UserData& userData)
     m_uiClient->didClickAutoFillButton(*this, m_process->transformHandlesToObjects(userData.object()).get());
 }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+WebMediaPlaybackTargetPickerProxy& WebPageProxy::devicePickerProxy()
+{
+    if (!m_playbackTargetPicker)
+        m_playbackTargetPicker = m_pageClient.createPlaybackTargetPicker(this);
+
+    return *m_playbackTargetPicker.get();
+}
+
+void WebPageProxy::showPlaybackTargetPicker(const WebCore::FloatRect& rect, bool hasVideo)
+{
+    devicePickerProxy().showPlaybackTargetPicker(m_pageClient.rootViewToScreen(IntRect(rect)), hasVideo);
+}
+
+void WebPageProxy::startingMonitoringPlaybackTargets()
+{
+    devicePickerProxy().startingMonitoringPlaybackTargets();
+}
+
+void WebPageProxy::stopMonitoringPlaybackTargets()
+{
+    devicePickerProxy().stopMonitoringPlaybackTargets();
+}
+
+void WebPageProxy::didChoosePlaybackTarget(const WebCore::MediaPlaybackTarget& target)
+{
+    if (!isValid())
+        return;
+
+    m_process->send(Messages::WebPage::PlaybackTargetSelected(target), m_pageID);
+}
+
+void WebPageProxy::externalOutputDeviceAvailableDidChange(bool available)
+{
+    if (!isValid())
+        return;
+
+    m_process->send(Messages::WebPage::PlaybackTargetAvailabilityDidChange(available), m_pageID);
+}
+
+#endif
+
 } // namespace WebKit
index c0398cb..2d2fc27 100644 (file)
 #include "ArgumentCodersGtk.h"
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+#include "WebMediaPlaybackTargetPickerProxy.h"
+#endif
+
 namespace API {
 class ContextMenuClient;
 class FindClient;
@@ -258,6 +262,9 @@ class WebPageProxy : public API::ObjectImpl<API::Object::Type::Page>
 #if ENABLE(INPUT_TYPE_COLOR)
     , public WebColorPicker::Client
 #endif
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    , public WebMediaPlaybackTargetPickerProxy::Client
+#endif
     , public WebPopupMenuProxy::Client
     , public IPC::MessageReceiver
     , public IPC::MessageSender {
@@ -999,6 +1006,17 @@ public:
     void logDiagnosticMessageWithResult(const String& message, const String& description, uint32_t result, bool shouldSample);
     void logDiagnosticMessageWithValue(const String& message, const String& description, const String& value, bool shouldSample);
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    WebMediaPlaybackTargetPickerProxy& devicePickerProxy();
+    void showPlaybackTargetPicker(const WebCore::FloatRect&, bool hasVideo);
+    void startingMonitoringPlaybackTargets();
+    void stopMonitoringPlaybackTargets();
+
+    // WebMediaPlaybackTargetPickerProxy::Client
+    virtual void didChoosePlaybackTarget(const WebCore::MediaPlaybackTarget&) override;
+    virtual void externalOutputDeviceAvailableDidChange(bool) override;
+#endif
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, const WebPageConfiguration&);
     void platformInitialize();
@@ -1664,6 +1682,10 @@ private:
     bool m_viewStateChangeWantsSynchronousReply;
     Vector<uint64_t> m_nextViewStateChangeCallbacks;
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    std::unique_ptr<WebMediaPlaybackTargetPickerProxy> m_playbackTargetPicker;
+#endif
+
     bool m_isPlayingAudio;
 };
 
index 0b85c21..f046d77 100644 (file)
@@ -425,4 +425,11 @@ messages -> WebPageProxy {
 #endif
 
     HandleAutoFillButtonClick(WebKit::UserData userData);
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+    ShowPlaybackTargetPicker(WebCore::FloatRect pickerLocation, bool hasVideo)
+    StartingMonitoringPlaybackTargets()
+    StopMonitoringPlaybackTargets()
+#endif
+
 }