[GPUP] Move AVSystemController code into the GPU process
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Mar 2020 19:22:33 +0000 (19:22 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Mar 2020 19:22:33 +0000 (19:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=208727

Reviewed by Eric Carlson.

Source/WebCore:

Move AVSystemController code out of MediaSessionManageriOS and into a new
class MediaSessionHelper, which is currently iOS only. The abstract base class
will be overriden by WebKit in the WebContent process.

Drive-by fix: Don't call a virtual method (resetRestrictions()) from the constructor of a
virtual base class; the virtual function table hasn't been created yet, and the subclasses'
overridden methods won't be called. Move the call to post-creation.

* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::sharedManager):
(WebCore::PlatformMediaSessionManager::PlatformMediaSessionManager):
* platform/audio/ios/MediaSessionHelperIOS.h: Added.
* platform/audio/ios/MediaSessionHelperIOS.mm: Copied from Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm.
(sharedHelperInstance):
(MediaSessionHelper::sharedHelper):
(MediaSessionHelper::resetSharedHelper):
(MediaSessionHelper::setSharedHelper):
(MediaSessionHelper::addClient):
(MediaSessionHelper::removeClient):
(MediaSessionHelperiOS::MediaSessionHelperiOS):
(MediaSessionHelperiOS::~MediaSessionHelperiOS):
(MediaSessionHelperiOS::providePresentingApplicationPID):
(MediaSessionHelperiOS::startMonitoringWirelessRoutes):
(MediaSessionHelperiOS::stopMonitoringWirelessRoutes):
(MediaSessionHelperiOS::carPlayServerDied):
(MediaSessionHelperiOS::updateCarPlayIsConnected):
(MediaSessionHelperiOS::setIsPlayingToAutomotiveHeadUnit):
(MediaSessionHelperiOS::activeAudioRouteDidChange):
(MediaSessionHelperiOS::activeVideoRouteDidChange):
(MediaSessionHelperiOS::receivedInterruption):
(MediaSessionHelperiOS::applicationDidBecomeActive):
(MediaSessionHelperiOS::applicationDidEnterBackground):
(MediaSessionHelperiOS::applicationWillBecomeInactive):
(MediaSessionHelperiOS::applicationWillEnterForeground):
(MediaSessionHelperiOS::externalOutputDeviceAvailableDidChange):
(-[WebMediaSessionHelper initWithCallback:]):
(-[WebMediaSessionHelper dealloc]):
(-[WebMediaSessionHelper clearCallback]):
(-[WebMediaSessionHelper hasWirelessTargetsAvailable]):
(-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
(-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
(-[WebMediaSessionHelper interruption:]):
(-[WebMediaSessionHelper applicationWillEnterForeground:]):
(-[WebMediaSessionHelper applicationDidBecomeActive:]):
(-[WebMediaSessionHelper applicationWillResignActive:]):
(-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]):
(-[WebMediaSessionHelper applicationDidEnterBackground:]):
(-[WebMediaSessionHelper carPlayServerDied:]):
(-[WebMediaSessionHelper carPlayIsConnectedDidChange:]):
(-[WebMediaSessionHelper activeAudioRouteDidChange:]):
* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(WebCore::MediaSessionManageriOS::MediaSessionManageriOS):
(WebCore::MediaSessionManageriOS::~MediaSessionManageriOS):
(WebCore::MediaSessionManageriOS::hasWirelessTargetsAvailable):
(WebCore::MediaSessionManageriOS::configureWireLessTargetMonitoring):
(WebCore::MediaSessionManageriOS::providePresentingApplicationPIDIfNecessary):
(WebCore::MediaSessionManageriOS::providePresentingApplicationPID):
(WebCore::MediaSessionManageriOS::externalOutputDeviceAvailableDidChange):
(WebCore::MediaSessionManageriOS::isPlayingToAutomotiveHeadUnitDidChange):
(WebCore::MediaSessionManageriOS::activeAudioRouteDidChange):
(WebCore::MediaSessionManageriOS::activeVideoRouteDidChange):
(WebCore::MediaSessionManageriOS::receivedInterruption):
(WebCore::MediaSessionManageriOS::applicationWillEnterForeground):
(WebCore::MediaSessionManageriOS::applicationDidBecomeActive):
(WebCore::MediaSessionManageriOS::applicationDidEnterBackground):
(WebCore::MediaSessionManageriOS::applicationWillBecomeInactive):
(WebCore::MediaSessionManageriOS::carPlayServerDied): Deleted.
(WebCore::MediaSessionManageriOS::updateCarPlayIsConnected): Deleted.
(-[WebMediaSessionHelper initWithCallback:]): Deleted.
(-[WebMediaSessionHelper dealloc]): Deleted.
(-[WebMediaSessionHelper clearCallback]): Deleted.
(-[WebMediaSessionHelper hasWirelessTargetsAvailable]): Deleted.
(-[WebMediaSessionHelper startMonitoringAirPlayRoutes]): Deleted.
(-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]): Deleted.
(-[WebMediaSessionHelper interruption:]): Deleted.
(-[WebMediaSessionHelper applicationWillEnterForeground:]): Deleted.
(-[WebMediaSessionHelper applicationDidBecomeActive:]): Deleted.
(-[WebMediaSessionHelper applicationWillResignActive:]): Deleted.
(-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]): Deleted.
(-[WebMediaSessionHelper applicationDidEnterBackground:]): Deleted.
(-[WebMediaSessionHelper carPlayServerDied:]): Deleted.
(-[WebMediaSessionHelper carPlayIsConnectedDidChange:]): Deleted.
(-[WebMediaSessionHelper activeAudioRouteDidChange:]): Deleted.

Source/WebKit:

Add a new class pair RemoteMediaSessionHelper/Proxy.

* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::mediaSessionHelperProxy):
(WebKit::GPUConnectionToWebProcess::ensureMediaSessionHelper):
* GPUProcess/GPUConnectionToWebProcess.h:
* GPUProcess/GPUConnectionToWebProcess.messages.in:
* GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp: Added.
(WebKit::RemoteMediaSessionHelperProxy::RemoteMediaSessionHelperProxy):
(WebKit::RemoteMediaSessionHelperProxy::~RemoteMediaSessionHelperProxy):
(WebKit::RemoteMediaSessionHelperProxy::startMonitoringWirelessRoutes):
(WebKit::RemoteMediaSessionHelperProxy::stopMonitoringWirelessRoutes):
(WebKit::RemoteMediaSessionHelperProxy::providePresentingApplicationPID):
(WebKit::RemoteMediaSessionHelperProxy::receivedInterruption):
(WebKit::RemoteMediaSessionHelperProxy::applicationWillEnterForeground):
(WebKit::RemoteMediaSessionHelperProxy::applicationDidEnterBackground):
(WebKit::RemoteMediaSessionHelperProxy::applicationWillBecomeInactive):
(WebKit::RemoteMediaSessionHelperProxy::applicationDidBecomeActive):
(WebKit::RemoteMediaSessionHelperProxy::externalOutputDeviceAvailableDidChange):
(WebKit::RemoteMediaSessionHelperProxy::isPlayingToAutomotiveHeadUnitDidChange):
(WebKit::RemoteMediaSessionHelperProxy::activeAudioRouteDidChange):
(WebKit::RemoteMediaSessionHelperProxy::activeVideoRouteDidChange):
* GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h: Added.
* GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in: Added.
* Sources.txt:
* SourcesCocoa.txt:
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp: Added.
(WebKit::RemoteMediaSessionHelper::RemoteMediaSessionHelper):
(WebKit::RemoteMediaSessionHelper::connection):
(WebKit::RemoteMediaSessionHelper::startMonitoringWirelessRoutes):
(WebKit::RemoteMediaSessionHelper::stopMonitoringWirelessRoutes):
(WebKit::RemoteMediaSessionHelper::providePresentingApplicationPID):
(WebKit::RemoteMediaSessionHelper::receivedInterruption):
(WebKit::RemoteMediaSessionHelper::applicationWillEnterForeground):
(WebKit::RemoteMediaSessionHelper::applicationDidEnterBackground):
(WebKit::RemoteMediaSessionHelper::applicationWillBecomeInactive):
(WebKit::RemoteMediaSessionHelper::applicationDidBecomeActive):
(WebKit::RemoteMediaSessionHelper::externalOutputDeviceAvailableDidChange):
(WebKit::RemoteMediaSessionHelper::isPlayingToAutomotiveHeadUnitDidChange):
(WebKit::RemoteMediaSessionHelper::activeAudioRouteDidChange):
(WebKit::RemoteMediaSessionHelper::activeVideoRouteDidChange):
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h: Added.
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in: Added.
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::setUseGPUProcessForMedia):

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

25 files changed:
Source/WebCore/ChangeLog
Source/WebCore/SourcesCocoa.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h [new file with mode: 0644]
Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm [new file with mode: 0644]
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebKit/ChangeLog
Source/WebKit/DerivedSources-input.xcfilelist
Source/WebKit/DerivedSources-output.xcfilelist
Source/WebKit/DerivedSources.make
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.messages.in
Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp [new file with mode: 0644]
Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h [new file with mode: 0644]
Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in [new file with mode: 0644]
Source/WebKit/Sources.txt
Source/WebKit/SourcesCocoa.txt
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp [new file with mode: 0644]
Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h [new file with mode: 0644]
Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in [new file with mode: 0644]
Source/WebKit/WebProcess/WebProcess.cpp

index f57e5fb..16814d7 100644 (file)
@@ -1,3 +1,95 @@
+2020-03-06  Jer Noble  <jer.noble@apple.com>
+
+        [GPUP] Move AVSystemController code into the GPU process
+        https://bugs.webkit.org/show_bug.cgi?id=208727
+
+        Reviewed by Eric Carlson.
+
+        Move AVSystemController code out of MediaSessionManageriOS and into a new
+        class MediaSessionHelper, which is currently iOS only. The abstract base class
+        will be overriden by WebKit in the WebContent process.
+
+        Drive-by fix: Don't call a virtual method (resetRestrictions()) from the constructor of a
+        virtual base class; the virtual function table hasn't been created yet, and the subclasses'
+        overridden methods won't be called. Move the call to post-creation.
+
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::sharedManager):
+        (WebCore::PlatformMediaSessionManager::PlatformMediaSessionManager):
+        * platform/audio/ios/MediaSessionHelperIOS.h: Added.
+        * platform/audio/ios/MediaSessionHelperIOS.mm: Copied from Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm.
+        (sharedHelperInstance):
+        (MediaSessionHelper::sharedHelper):
+        (MediaSessionHelper::resetSharedHelper):
+        (MediaSessionHelper::setSharedHelper):
+        (MediaSessionHelper::addClient):
+        (MediaSessionHelper::removeClient):
+        (MediaSessionHelperiOS::MediaSessionHelperiOS):
+        (MediaSessionHelperiOS::~MediaSessionHelperiOS):
+        (MediaSessionHelperiOS::providePresentingApplicationPID):
+        (MediaSessionHelperiOS::startMonitoringWirelessRoutes):
+        (MediaSessionHelperiOS::stopMonitoringWirelessRoutes):
+        (MediaSessionHelperiOS::carPlayServerDied):
+        (MediaSessionHelperiOS::updateCarPlayIsConnected):
+        (MediaSessionHelperiOS::setIsPlayingToAutomotiveHeadUnit):
+        (MediaSessionHelperiOS::activeAudioRouteDidChange):
+        (MediaSessionHelperiOS::activeVideoRouteDidChange):
+        (MediaSessionHelperiOS::receivedInterruption):
+        (MediaSessionHelperiOS::applicationDidBecomeActive):
+        (MediaSessionHelperiOS::applicationDidEnterBackground):
+        (MediaSessionHelperiOS::applicationWillBecomeInactive):
+        (MediaSessionHelperiOS::applicationWillEnterForeground):
+        (MediaSessionHelperiOS::externalOutputDeviceAvailableDidChange):
+        (-[WebMediaSessionHelper initWithCallback:]):
+        (-[WebMediaSessionHelper dealloc]):
+        (-[WebMediaSessionHelper clearCallback]):
+        (-[WebMediaSessionHelper hasWirelessTargetsAvailable]):
+        (-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
+        (-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
+        (-[WebMediaSessionHelper interruption:]):
+        (-[WebMediaSessionHelper applicationWillEnterForeground:]):
+        (-[WebMediaSessionHelper applicationDidBecomeActive:]):
+        (-[WebMediaSessionHelper applicationWillResignActive:]):
+        (-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]):
+        (-[WebMediaSessionHelper applicationDidEnterBackground:]):
+        (-[WebMediaSessionHelper carPlayServerDied:]):
+        (-[WebMediaSessionHelper carPlayIsConnectedDidChange:]):
+        (-[WebMediaSessionHelper activeAudioRouteDidChange:]):
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (WebCore::MediaSessionManageriOS::MediaSessionManageriOS):
+        (WebCore::MediaSessionManageriOS::~MediaSessionManageriOS):
+        (WebCore::MediaSessionManageriOS::hasWirelessTargetsAvailable):
+        (WebCore::MediaSessionManageriOS::configureWireLessTargetMonitoring):
+        (WebCore::MediaSessionManageriOS::providePresentingApplicationPIDIfNecessary):
+        (WebCore::MediaSessionManageriOS::providePresentingApplicationPID):
+        (WebCore::MediaSessionManageriOS::externalOutputDeviceAvailableDidChange):
+        (WebCore::MediaSessionManageriOS::isPlayingToAutomotiveHeadUnitDidChange):
+        (WebCore::MediaSessionManageriOS::activeAudioRouteDidChange):
+        (WebCore::MediaSessionManageriOS::activeVideoRouteDidChange):
+        (WebCore::MediaSessionManageriOS::receivedInterruption):
+        (WebCore::MediaSessionManageriOS::applicationWillEnterForeground):
+        (WebCore::MediaSessionManageriOS::applicationDidBecomeActive):
+        (WebCore::MediaSessionManageriOS::applicationDidEnterBackground):
+        (WebCore::MediaSessionManageriOS::applicationWillBecomeInactive):
+        (WebCore::MediaSessionManageriOS::carPlayServerDied): Deleted.
+        (WebCore::MediaSessionManageriOS::updateCarPlayIsConnected): Deleted.
+        (-[WebMediaSessionHelper initWithCallback:]): Deleted.
+        (-[WebMediaSessionHelper dealloc]): Deleted.
+        (-[WebMediaSessionHelper clearCallback]): Deleted.
+        (-[WebMediaSessionHelper hasWirelessTargetsAvailable]): Deleted.
+        (-[WebMediaSessionHelper startMonitoringAirPlayRoutes]): Deleted.
+        (-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]): Deleted.
+        (-[WebMediaSessionHelper interruption:]): Deleted.
+        (-[WebMediaSessionHelper applicationWillEnterForeground:]): Deleted.
+        (-[WebMediaSessionHelper applicationDidBecomeActive:]): Deleted.
+        (-[WebMediaSessionHelper applicationWillResignActive:]): Deleted.
+        (-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]): Deleted.
+        (-[WebMediaSessionHelper applicationDidEnterBackground:]): Deleted.
+        (-[WebMediaSessionHelper carPlayServerDied:]): Deleted.
+        (-[WebMediaSessionHelper carPlayIsConnectedDidChange:]): Deleted.
+        (-[WebMediaSessionHelper activeAudioRouteDidChange:]): Deleted.
+
 2020-03-08  Andres Gonzalez  <andresg_22@apple.com>
 
         Fix for LayoutTests/accessibility/mac/value-change/value-change-user-info-contenteditable.html in IsolatedTree mode.
index 9df5d80..c80b21a 100644 (file)
@@ -172,6 +172,7 @@ platform/audio/cocoa/WebAudioBufferList.cpp
 platform/audio/ios/AudioDestinationIOS.cpp @no-unify
 platform/audio/ios/AudioFileReaderIOS.cpp @no-unify
 platform/audio/ios/AudioSessionIOS.mm @no-unify
+platform/audio/ios/MediaSessionHelperIOS.mm @no-unify
 platform/audio/ios/MediaSessionManagerIOS.mm @no-unify
 
 platform/audio/mac/CAAudioStreamDescription.cpp
index 822a4de..0587dec 100644 (file)
                CDA595982146DF7800A84185 /* HEVCUtilitiesCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA595962146DF7800A84185 /* HEVCUtilitiesCocoa.h */; };
                CDA79827170A279100D45C55 /* AudioSessionIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDA79825170A279000D45C55 /* AudioSessionIOS.mm */; };
                CDA7982A170A3D0000D45C55 /* AudioSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA79821170A22DC00D45C55 /* AudioSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CDA9593524123CB800910EEF /* MediaSessionHelperIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD875A752411B79800B09F58 /* MediaSessionHelperIOS.mm */; };
+               CDA9593F2412BAE000910EEF /* MediaSessionHelperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD875A742411B79800B09F58 /* MediaSessionHelperIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CDA98E0B1603CD6000FEA3B1 /* LegacyCDM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA98E091603CD5900FEA3B1 /* LegacyCDM.cpp */; };
                CDAB6D2917C7DE6C00C60B34 /* MediaControlsHost.h in Headers */ = {isa = PBXBuildFile; fileRef = CDAB6D2717C7DE6C00C60B34 /* MediaControlsHost.h */; };
                CDAB6D2E17C814EE00C60B34 /* JSMediaControlsHost.h in Headers */ = {isa = PBXBuildFile; fileRef = CDAB6D2C17C814EE00C60B34 /* JSMediaControlsHost.h */; };
                CD871C681FB52B6900F0B965 /* ISOBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISOBox.cpp; sourceTree = "<group>"; };
                CD871C691FB52B6900F0B965 /* ISOVTTCue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISOVTTCue.cpp; sourceTree = "<group>"; };
                CD871C6A1FB52B6A00F0B965 /* ISOOriginalFormatBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISOOriginalFormatBox.cpp; sourceTree = "<group>"; };
+               CD875A742411B79800B09F58 /* MediaSessionHelperIOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaSessionHelperIOS.h; sourceTree = "<group>"; };
+               CD875A752411B79800B09F58 /* MediaSessionHelperIOS.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaSessionHelperIOS.mm; sourceTree = "<group>"; };
                CD8A7BB9197735FE00CBD643 /* AudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioSourceProviderAVFObjC.mm; sourceTree = "<group>"; };
                CD8A7BBA197735FE00CBD643 /* AudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioSourceProviderAVFObjC.h; sourceTree = "<group>"; };
                CD8ACA861D237AA200ECC59E /* RemoteCommandListenerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteCommandListenerMac.mm; sourceTree = "<group>"; };
                                CD55968F1475B678001D0BD0 /* AudioFileReaderIOS.cpp */,
                                CD5596901475B678001D0BD0 /* AudioFileReaderIOS.h */,
                                CDA79825170A279000D45C55 /* AudioSessionIOS.mm */,
+                               CD875A742411B79800B09F58 /* MediaSessionHelperIOS.h */,
+                               CD875A752411B79800B09F58 /* MediaSessionHelperIOS.mm */,
                                07638A971884487200E15A1B /* MediaSessionManagerIOS.h */,
                                07638A981884487200E15A1B /* MediaSessionManagerIOS.mm */,
                        );
                                C9027F421B1D0AD200BFBFEF /* MediaSession.h in Headers */,
                                C9F87CFE1B28F40E00979B83 /* MediaSessionEvents.h in Headers */,
                                414460A22412994500814BE7 /* MediaSessionIdentifier.h in Headers */,
+                               CDA9593F2412BAE000910EEF /* MediaSessionHelperIOS.h in Headers */,
                                C96F5EC81B5872260091EA9D /* MediaSessionInterruptionProvider.h in Headers */,
                                C96F5EC51B5872260091EA9D /* MediaSessionInterruptionProviderMac.h in Headers */,
                                C90F65561B2253BE002163A1 /* MediaSessionManager.h in Headers */,
                                150524F51B712FF900696AA9 /* MediaPlayerPrivateMediaStreamAVFObjC.mm in Sources */,
                                1B124D8F1D380BB600ECDFB0 /* MediaSampleAVFObjC.mm in Sources */,
                                CDBEAEAC19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm in Sources */,
+                               CDA9593524123CB800910EEF /* MediaSessionHelperIOS.mm in Sources */,
                                C96F5EC71B5872260091EA9D /* MediaSessionInterruptionProvider.cpp in Sources */,
                                C90F65551B2253B1002163A1 /* MediaSessionManager.cpp in Sources */,
                                07638A9A1884487200E15A1B /* MediaSessionManagerIOS.mm in Sources */,
index 5f40457..1375750 100644 (file)
@@ -44,8 +44,10 @@ static std::unique_ptr<PlatformMediaSessionManager>& sharedPlatformMediaSessionM
 PlatformMediaSessionManager& PlatformMediaSessionManager::sharedManager()
 {
     auto& manager = sharedPlatformMediaSessionManager();
-    if (!manager)
+    if (!manager) {
         manager = PlatformMediaSessionManager::create();
+        manager->resetRestrictions();
+    }
     return *manager;
 }
 
@@ -72,7 +74,6 @@ PlatformMediaSessionManager::PlatformMediaSessionManager()
     : m_logger(AggregateLogger::create(this))
 #endif
 {
-    resetRestrictions();
 }
 
 static inline unsigned indexFromMediaType(PlatformMediaSession::MediaType type)
diff --git a/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h b/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h
new file mode 100644 (file)
index 0000000..6372ed0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#include <wtf/WeakHashSet.h>
+
+namespace WebCore {
+
+class MediaPlaybackTarget;
+
+class MediaSessionHelperClient : public CanMakeWeakPtr<MediaSessionHelperClient> {
+public:
+    virtual ~MediaSessionHelperClient() = default;
+
+    enum class InterruptionType : bool { Begin, End };
+    enum class ShouldResume : bool { No, Yes };
+    virtual void receivedInterruption(InterruptionType, ShouldResume) = 0;
+
+    enum class SuspendedUnderLock : bool { No, Yes };
+    virtual void applicationWillEnterForeground(SuspendedUnderLock) = 0;
+    virtual void applicationDidEnterBackground(SuspendedUnderLock) = 0;
+    virtual void applicationWillBecomeInactive() = 0;
+    virtual void applicationDidBecomeActive() = 0;
+
+    enum class HasAvailableTargets : bool { No, Yes };
+    virtual void externalOutputDeviceAvailableDidChange(HasAvailableTargets) = 0;
+
+    enum class PlayingToAutomotiveHeadUnit : bool { No, Yes };
+    virtual void isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit) = 0;
+
+    enum class ShouldPause : bool { No, Yes };
+    virtual void activeAudioRouteDidChange(ShouldPause) = 0;
+
+    enum class SupportsAirPlayVideo : bool { No, Yes };
+    virtual void activeVideoRouteDidChange(SupportsAirPlayVideo, Ref<MediaPlaybackTarget>&&) = 0;
+};
+
+class WEBCORE_EXPORT MediaSessionHelper {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static MediaSessionHelper& sharedHelper();
+    static void setSharedHelper(UniqueRef<MediaSessionHelper>&&);
+    static void resetSharedHelper();
+
+    MediaSessionHelper() = default;
+    virtual ~MediaSessionHelper() = default;
+
+    void addClient(MediaSessionHelperClient&);
+    void removeClient(MediaSessionHelperClient&);
+
+    virtual void startMonitoringWirelessRoutes() = 0;
+    virtual void stopMonitoringWirelessRoutes() = 0;
+    virtual void providePresentingApplicationPID(int) = 0;
+
+    bool isMonitoringWirelessRoutes() const { return m_monitoringWirelessRoutesCount; }
+    bool isExternalOutputDeviceAvailable() const { return m_isExternalOutputDeviceAvailable; }
+    bool activeVideoRouteSupportsAirPlayVideo() const { return m_activeVideoRouteSupportsAirPlayVideo; }
+    bool isPlayingToAutomotiveHeadUnit() const { return m_isPlayingToAutomotiveHeadUnit; }
+
+protected:
+    WeakHashSet<MediaSessionHelperClient> m_clients;
+    uint32_t m_monitoringWirelessRoutesCount { 0 };
+    bool m_isExternalOutputDeviceAvailable { false };
+    bool m_activeVideoRouteSupportsAirPlayVideo { false };
+    bool m_isPlayingToAutomotiveHeadUnit { false };
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm b/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm
new file mode 100644 (file)
index 0000000..36689b5
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#import "config.h"
+#import "MediaSessionHelperIOS.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "Logging.h"
+#import "MediaPlaybackTargetCocoa.h"
+#import "WebCoreThreadRun.h"
+#import <AVFoundation/AVAudioSession.h>
+#import <AVFoundation/AVRouteDetector.h>
+#import <pal/spi/cocoa/AVFoundationSPI.h>
+#import <pal/spi/ios/CelestialSPI.h>
+#import <wtf/BlockObjCExceptions.h>
+#import <wtf/MainThread.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/UniqueRef.h>
+
+#import <pal/cocoa/AVFoundationSoftLink.h>
+#import <pal/ios/UIKitSoftLink.h>
+
+WEBCORE_EXPORT NSString* WebUIApplicationWillResignActiveNotification = @"WebUIApplicationWillResignActiveNotification";
+WEBCORE_EXPORT NSString* WebUIApplicationWillEnterForegroundNotification = @"WebUIApplicationWillEnterForegroundNotification";
+WEBCORE_EXPORT NSString* WebUIApplicationDidBecomeActiveNotification = @"WebUIApplicationDidBecomeActiveNotification";
+WEBCORE_EXPORT NSString* WebUIApplicationDidEnterBackgroundNotification = @"WebUIApplicationDidEnterBackgroundNotification";
+
+#if HAVE(CELESTIAL)
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(Celestial)
+SOFT_LINK_CLASS_OPTIONAL(Celestial, AVSystemController)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PIDToInheritApplicationStateFrom, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedAttribute, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedDidChangeNotification, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedNotificationParameter, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ServerConnectionDiedNotification, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotification, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PickedRouteAttribute, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo, NSString *)
+#endif
+
+using namespace WebCore;
+
+class MediaSessionHelperiOS;
+
+@interface WebMediaSessionHelper : NSObject {
+    MediaSessionHelperiOS* _callback;
+
+#if !PLATFORM(WATCHOS)
+    RetainPtr<AVRouteDetector> _routeDetector;
+#endif
+    bool _monitoringAirPlayRoutes;
+    bool _startMonitoringAirPlayRoutesPending;
+}
+
+- (id)initWithCallback:(MediaSessionHelperiOS*)callback;
+
+- (void)clearCallback;
+- (void)interruption:(NSNotification *)notification;
+- (void)applicationWillEnterForeground:(NSNotification *)notification;
+- (void)applicationWillResignActive:(NSNotification *)notification;
+- (void)applicationDidEnterBackground:(NSNotification *)notification;
+- (BOOL)hasWirelessTargetsAvailable;
+
+#if !PLATFORM(WATCHOS)
+- (void)startMonitoringAirPlayRoutes;
+- (void)stopMonitoringAirPlayRoutes;
+#endif
+
+@end
+
+class MediaSessionHelperiOS final : public MediaSessionHelper {
+public:
+    MediaSessionHelperiOS();
+    ~MediaSessionHelperiOS();
+
+    void externalOutputDeviceAvailableDidChange();
+    void receivedInterruption(MediaSessionHelperClient::InterruptionType, MediaSessionHelperClient::ShouldResume);
+    void applicationWillEnterForeground(MediaSessionHelperClient::SuspendedUnderLock);
+    void applicationDidEnterBackground(MediaSessionHelperClient::SuspendedUnderLock);
+    void applicationWillBecomeInactive();
+    void applicationDidBecomeActive();
+#if HAVE(CELESTIAL)
+    void carPlayServerDied();
+    void updateCarPlayIsConnected(Optional<bool>&&);
+    void activeAudioRouteDidChange(Optional<bool>&&);
+    void activeVideoRouteDidChange(Optional<bool>&&);
+#endif
+
+private:
+    using HasAvailableTargets = MediaSessionHelperClient::HasAvailableTargets;
+    using InterruptionType = MediaSessionHelperClient::InterruptionType;
+    using PlayingToAutomotiveHeadUnit = MediaSessionHelperClient::PlayingToAutomotiveHeadUnit;
+    using ShouldPause = MediaSessionHelperClient::ShouldPause;
+    using ShouldResume = MediaSessionHelperClient::ShouldResume;
+    using SupportsAirPlayVideo = MediaSessionHelperClient::SupportsAirPlayVideo;
+    using SuspendedUnderLock = MediaSessionHelperClient::SuspendedUnderLock;
+
+    void setIsPlayingToAutomotiveHeadUnit(bool);
+
+    void providePresentingApplicationPID(int) final;
+    void startMonitoringWirelessRoutes() final;
+    void stopMonitoringWirelessRoutes() final;
+
+    RetainPtr<WebMediaSessionHelper> m_objcObserver;
+#if HAVE(CELESTIAL)
+    bool m_havePresentedApplicationPID { false };
+#endif
+};
+
+static UniqueRef<MediaSessionHelper>& sharedHelperInstance()
+{
+    static NeverDestroyed<UniqueRef<MediaSessionHelper>> helper = makeUniqueRef<MediaSessionHelperiOS>();
+    return helper;
+}
+
+MediaSessionHelper& MediaSessionHelper::sharedHelper()
+{
+    return sharedHelperInstance();
+}
+
+void MediaSessionHelper::resetSharedHelper()
+{
+    sharedHelperInstance() = makeUniqueRef<MediaSessionHelperiOS>();
+}
+
+void MediaSessionHelper::setSharedHelper(UniqueRef<MediaSessionHelper>&& helper)
+{
+    sharedHelperInstance() = WTFMove(helper);
+}
+
+void MediaSessionHelper::addClient(MediaSessionHelperClient& client)
+{
+    ASSERT(!m_clients.contains(client));
+    m_clients.add(client);
+}
+
+void MediaSessionHelper::removeClient(MediaSessionHelperClient& client)
+{
+    ASSERT(m_clients.contains(client));
+    m_clients.remove(client);
+}
+
+MediaSessionHelperiOS::MediaSessionHelperiOS()
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    m_objcObserver = adoptNS([[WebMediaSessionHelper alloc] initWithCallback:this]);
+    m_isExternalOutputDeviceAvailable = [m_objcObserver hasWirelessTargetsAvailable];
+    END_BLOCK_OBJC_EXCEPTIONS
+
+#if HAVE(CELESTIAL)
+    updateCarPlayIsConnected(WTF::nullopt);
+#endif
+}
+
+MediaSessionHelperiOS::~MediaSessionHelperiOS()
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    [m_objcObserver clearCallback];
+    END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void MediaSessionHelperiOS::providePresentingApplicationPID(int pid)
+{
+#if HAVE(CELESTIAL)
+    if (m_havePresentedApplicationPID)
+        return;
+    m_havePresentedApplicationPID = true;
+
+    if (!canLoadAVSystemController_PIDToInheritApplicationStateFrom())
+        return;
+
+    NSError *error = nil;
+    [[getAVSystemControllerClass() sharedAVSystemController] setAttribute:@(pid) forKey:getAVSystemController_PIDToInheritApplicationStateFrom() error:&error];
+    if (error)
+        WTFLogAlways("Failed to set up PID proxying: %s", error.localizedDescription.UTF8String);
+#endif
+}
+
+void MediaSessionHelperiOS::startMonitoringWirelessRoutes()
+{
+    if (m_monitoringWirelessRoutesCount++)
+        return;
+
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    [m_objcObserver startMonitoringAirPlayRoutes];
+    END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void MediaSessionHelperiOS::stopMonitoringWirelessRoutes()
+{
+    if (!m_monitoringWirelessRoutesCount) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    if (--m_monitoringWirelessRoutesCount)
+        return;
+
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    [m_objcObserver stopMonitoringAirPlayRoutes];
+    END_BLOCK_OBJC_EXCEPTIONS
+}
+
+#if HAVE(CELESTIAL)
+void MediaSessionHelperiOS::carPlayServerDied()
+{
+    updateCarPlayIsConnected(WTF::nullopt);
+}
+
+void MediaSessionHelperiOS::updateCarPlayIsConnected(Optional<bool>&& carPlayIsConnected)
+{
+    if (carPlayIsConnected) {
+        setIsPlayingToAutomotiveHeadUnit(carPlayIsConnected.value());
+        return;
+    }
+
+    if (!canLoadAVSystemController_CarPlayIsConnectedAttribute()) {
+        setIsPlayingToAutomotiveHeadUnit(false);
+        return;
+    }
+
+    setIsPlayingToAutomotiveHeadUnit([[[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_CarPlayIsConnectedAttribute()] boolValue]);
+}
+
+void MediaSessionHelperiOS::setIsPlayingToAutomotiveHeadUnit(bool isPlaying)
+{
+    if (isPlaying == m_isPlayingToAutomotiveHeadUnit)
+        return;
+
+    m_isPlayingToAutomotiveHeadUnit = isPlaying;
+    for (auto& client : m_clients)
+        client.isPlayingToAutomotiveHeadUnitDidChange(m_isPlayingToAutomotiveHeadUnit ? PlayingToAutomotiveHeadUnit::Yes : PlayingToAutomotiveHeadUnit::No);
+}
+
+void MediaSessionHelperiOS::activeAudioRouteDidChange(Optional<bool>&& shouldPause)
+{
+    for (auto& client : m_clients)
+        client.activeAudioRouteDidChange(shouldPause.valueOr(false) ? ShouldPause::Yes : ShouldPause::No);
+}
+
+void MediaSessionHelperiOS::activeVideoRouteDidChange(Optional<bool>&& supportsAirPlayVideo)
+{
+    m_activeVideoRouteSupportsAirPlayVideo = supportsAirPlayVideo.valueOr(false);
+
+    auto playbackTarget = MediaPlaybackTargetCocoa::create([PAL::getAVOutputContextClass() sharedAudioPresentationOutputContext]);
+    for (auto& client : m_clients)
+        client.activeVideoRouteDidChange(m_activeVideoRouteSupportsAirPlayVideo ? SupportsAirPlayVideo::Yes : SupportsAirPlayVideo::No, playbackTarget.copyRef());
+}
+#endif
+
+void MediaSessionHelperiOS::receivedInterruption(MediaSessionHelperClient::InterruptionType type, MediaSessionHelperClient::ShouldResume shouldResume)
+{
+    for (auto& client : m_clients)
+        client.receivedInterruption(type, shouldResume);
+}
+
+void MediaSessionHelperiOS::applicationDidBecomeActive()
+{
+    for (auto& client : m_clients)
+        client.applicationDidBecomeActive();
+}
+
+void MediaSessionHelperiOS::applicationDidEnterBackground(MediaSessionHelperClient::SuspendedUnderLock underLock)
+{
+    for (auto& client : m_clients)
+        client.applicationDidEnterBackground(underLock);
+}
+
+void MediaSessionHelperiOS::applicationWillBecomeInactive()
+{
+    for (auto& client : m_clients)
+        client.applicationWillBecomeInactive();
+}
+
+void MediaSessionHelperiOS::applicationWillEnterForeground(MediaSessionHelperClient::SuspendedUnderLock underLock)
+{
+    for (auto& client : m_clients)
+        client.applicationWillEnterForeground(underLock);
+}
+
+void MediaSessionHelperiOS::externalOutputDeviceAvailableDidChange()
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    m_isExternalOutputDeviceAvailable = [m_objcObserver hasWirelessTargetsAvailable];
+    END_BLOCK_OBJC_EXCEPTIONS
+
+    for (auto& client : m_clients)
+        client.externalOutputDeviceAvailableDidChange(m_isExternalOutputDeviceAvailable ? HasAvailableTargets::Yes : HasAvailableTargets::No);
+}
+
+@implementation WebMediaSessionHelper
+
+- (id)initWithCallback:(MediaSessionHelperiOS*)callback
+{
+    LOG(Media, "-[WebMediaSessionHelper initWithCallback]");
+
+    if (!(self = [super init]))
+        return nil;
+
+    _callback = callback;
+
+    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+    [center addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[PAL::getAVAudioSessionClass() sharedInstance]];
+
+    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:PAL::get_UIKit_UIApplicationWillEnterForegroundNotification() object:nil];
+    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:WebUIApplicationWillEnterForegroundNotification object:nil];
+    [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:PAL::get_UIKit_UIApplicationDidBecomeActiveNotification() object:nil];
+    [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:WebUIApplicationDidBecomeActiveNotification object:nil];
+    [center addObserver:self selector:@selector(applicationWillResignActive:) name:PAL::get_UIKit_UIApplicationWillResignActiveNotification() object:nil];
+    [center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
+    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:PAL::get_UIKit_UIApplicationDidEnterBackgroundNotification() object:nil];
+    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
+#if HAVE(CELESTIAL)
+    if (canLoadAVSystemController_ServerConnectionDiedNotification())
+        [center addObserver:self selector:@selector(carPlayServerDied:) name:getAVSystemController_ServerConnectionDiedNotification() object:nil];
+    if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification())
+        [center addObserver:self selector:@selector(carPlayIsConnectedDidChange:) name:getAVSystemController_CarPlayIsConnectedDidChangeNotification() object:nil];
+    if (canLoadAVSystemController_ActiveAudioRouteDidChangeNotification())
+        [center addObserver:self selector:@selector(activeAudioRouteDidChange:) name:getAVSystemController_ActiveAudioRouteDidChangeNotification() object:nil];
+#endif
+
+    // Now playing won't work unless we turn on the delivery of remote control events.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        BEGIN_BLOCK_OBJC_EXCEPTIONS
+        [[PAL::getUIApplicationClass() sharedApplication] beginReceivingRemoteControlEvents];
+        END_BLOCK_OBJC_EXCEPTIONS
+    });
+
+    return self;
+}
+
+- (void)dealloc
+{
+    LOG(Media, "-[WebMediaSessionHelper dealloc]");
+
+#if !PLATFORM(WATCHOS)
+    if (!pthread_main_np()) {
+        dispatch_async(dispatch_get_main_queue(), [routeDetector = WTFMove(_routeDetector)] () mutable {
+            LOG(Media, "safelyTearDown - dipatched to UI thread.");
+            BEGIN_BLOCK_OBJC_EXCEPTIONS
+            routeDetector.get().routeDetectionEnabled = NO;
+            routeDetector.clear();
+            END_BLOCK_OBJC_EXCEPTIONS
+        });
+    } else
+        _routeDetector.get().routeDetectionEnabled = NO;
+#endif
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    [super dealloc];
+}
+
+- (void)clearCallback
+{
+    LOG(Media, "-[WebMediaSessionHelper clearCallback]");
+    _callback = nil;
+}
+
+- (BOOL)hasWirelessTargetsAvailable
+{
+    LOG(Media, "-[WebMediaSessionHelper hasWirelessTargetsAvailable]");
+#if !PLATFORM(WATCHOS)
+    return _routeDetector.get().multipleRoutesDetected;
+#else
+    return NO;
+#endif
+}
+
+#if !PLATFORM(WATCHOS)
+- (void)startMonitoringAirPlayRoutes
+{
+    if (_monitoringAirPlayRoutes)
+        return;
+
+    _monitoringAirPlayRoutes = true;
+
+    if (_startMonitoringAirPlayRoutesPending)
+        return;
+
+    if (_routeDetector) {
+        _routeDetector.get().routeDetectionEnabled = YES;
+        return;
+    }
+
+    _startMonitoringAirPlayRoutesPending = true;
+
+    LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes]");
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
+        ASSERT(!protectedSelf->_routeDetector);
+
+        if (protectedSelf->_callback) {
+            BEGIN_BLOCK_OBJC_EXCEPTIONS
+            protectedSelf->_routeDetector = adoptNS([PAL::allocAVRouteDetectorInstance() init]);
+            protectedSelf->_routeDetector.get().routeDetectionEnabled = protectedSelf->_monitoringAirPlayRoutes;
+            [[NSNotificationCenter defaultCenter] addObserver:protectedSelf.get() selector:@selector(wirelessRoutesAvailableDidChange:) name:AVRouteDetectorMultipleRoutesDetectedDidChangeNotification object:protectedSelf->_routeDetector.get()];
+
+            protectedSelf->_callback->externalOutputDeviceAvailableDidChange();
+            END_BLOCK_OBJC_EXCEPTIONS
+        }
+
+        protectedSelf->_startMonitoringAirPlayRoutesPending = false;
+    });
+}
+
+- (void)stopMonitoringAirPlayRoutes
+{
+    if (!_monitoringAirPlayRoutes)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
+
+    _monitoringAirPlayRoutes = false;
+    _routeDetector.get().routeDetectionEnabled = NO;
+}
+#endif // !PLATFORM(WATCHOS)
+
+- (void)interruption:(NSNotification *)notification
+{
+    using InterruptionType = MediaSessionHelperClient::InterruptionType;
+    using ShouldResume = MediaSessionHelperClient::ShouldResume;
+
+    NSUInteger type = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
+    InterruptionType interruptionType = (type == AVAudioSessionInterruptionTypeEnded ? InterruptionType::End : InterruptionType::Begin);
+    ShouldResume shouldResume = ShouldResume::No;
+
+    LOG(Media, "-[WebMediaSessionHelper interruption] - type = %i", (int)type);
+
+    if (interruptionType == InterruptionType::End && [[[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue] == AVAudioSessionInterruptionOptionShouldResume)
+        shouldResume = ShouldResume::Yes;
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), interruptionType, shouldResume]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->receivedInterruption(interruptionType, shouldResume);
+    });
+}
+
+- (void)applicationWillEnterForeground:(NSNotification *)notification
+{
+    using SuspendedUnderLock = MediaSessionHelperClient::SuspendedUnderLock;
+
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper applicationWillEnterForeground]");
+
+    auto isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue] ? SuspendedUnderLock::Yes : SuspendedUnderLock::No;
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), isSuspendedUnderLock]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->applicationWillEnterForeground(isSuspendedUnderLock);
+    });
+}
+
+- (void)applicationDidBecomeActive:(NSNotification *)notification
+{
+    UNUSED_PARAM(notification);
+
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper applicationDidBecomeActive]");
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->applicationDidBecomeActive();
+    });
+}
+
+- (void)applicationWillResignActive:(NSNotification *)notification
+{
+    UNUSED_PARAM(notification);
+
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper applicationWillResignActive]");
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->applicationWillBecomeInactive();
+    });
+}
+
+- (void)wirelessRoutesAvailableDidChange:(NSNotification *)notification
+{
+    UNUSED_PARAM(notification);
+
+    if (!_callback || !_monitoringAirPlayRoutes)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper wirelessRoutesAvailableDidChange]");
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->externalOutputDeviceAvailableDidChange();
+    });
+}
+
+- (void)applicationDidEnterBackground:(NSNotification *)notification
+{
+    using SuspendedUnderLock = MediaSessionHelperClient::SuspendedUnderLock;
+
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper applicationDidEnterBackground]");
+
+    auto isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue] ? SuspendedUnderLock::Yes : SuspendedUnderLock::No;
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), isSuspendedUnderLock]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->applicationDidEnterBackground(isSuspendedUnderLock);
+    });
+}
+
+#if HAVE(CELESTIAL)
+- (void)carPlayServerDied:(NSNotification *)notification
+{
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper carPlayServerDied:]");
+    UNUSED_PARAM(notification);
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->carPlayServerDied();
+    });
+}
+
+- (void)carPlayIsConnectedDidChange:(NSNotification *)notification
+{
+    if (!_callback)
+        return;
+
+    Optional<bool> carPlayIsConnected;
+    if (notification && canLoadAVSystemController_CarPlayIsConnectedNotificationParameter()) {
+        NSNumber *nsCarPlayIsConnected = [[notification userInfo] valueForKey:getAVSystemController_CarPlayIsConnectedNotificationParameter()];
+        if (nsCarPlayIsConnected)
+            carPlayIsConnected = [nsCarPlayIsConnected boolValue];
+    }
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), carPlayIsConnected = WTFMove(carPlayIsConnected)]() mutable {
+        if (auto* callback = protectedSelf->_callback)
+            callback->updateCarPlayIsConnected(WTFMove(carPlayIsConnected));
+    });
+}
+
+- (void)activeAudioRouteDidChange:(NSNotification *)notification
+{
+    if (!_callback)
+        return;
+
+    UNUSED_PARAM(notification);
+    Optional<bool> shouldPause;
+    if (notification && canLoadAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()) {
+        NSNumber* nsShouldPause = [notification.userInfo valueForKey:getAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()];
+        if (nsShouldPause)
+            shouldPause = nsShouldPause.boolValue;
+    }
+
+    Optional<bool> supportsAirPlayVideo;
+    if (canLoadAVSystemController_PickedRouteAttribute() && canLoadAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()) {
+        NSDictionary* pickedRoute = [[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_PickedRouteAttribute()];
+        if ([pickedRoute isKindOfClass:NSDictionary.class]) {
+            NSNumber* nsSupportsAirPlayVideo = [pickedRoute valueForKey:getAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()];
+            if (nsSupportsAirPlayVideo)
+                supportsAirPlayVideo = nsSupportsAirPlayVideo.boolValue;
+        }
+    }
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), shouldPause = WTFMove(shouldPause), supportsAirPlayVideo = WTFMove(supportsAirPlayVideo)]() mutable {
+        if (auto* callback = protectedSelf->_callback) {
+            callback->activeAudioRouteDidChange(WTFMove(shouldPause));
+            callback->activeVideoRouteDidChange(WTFMove(supportsAirPlayVideo));
+        }
+    });
+
+}
+#endif // HAVE(CELESTIAL)
+@end
+
+#endif
index 5df20a7..4dc8ff3 100644 (file)
@@ -27,6 +27,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#include "MediaSessionHelperIOS.h"
 #include "MediaSessionManagerCocoa.h"
 #include <wtf/RetainPtr.h>
 
@@ -41,18 +42,13 @@ extern NSString* WebUIApplicationDidEnterBackgroundNotification;
 
 namespace WebCore {
 
-class MediaSessionManageriOS : public MediaSessionManagerCocoa {
+class MediaSessionManageriOS
+    : public MediaSessionManagerCocoa
+    , public MediaSessionHelperClient {
 public:
     virtual ~MediaSessionManageriOS();
 
-    void externalOutputDeviceAvailableDidChange();
     bool hasWirelessTargetsAvailable() override;
-#if HAVE(CELESTIAL)
-    void carPlayServerDied();
-    void updateCarPlayIsConnected(Optional<bool>&&);
-    void activeAudioRouteDidChange(Optional<bool>&&);
-    void activeVideoRouteDidChange(Optional<bool>&&);
-#endif
     static WEBCORE_EXPORT void providePresentingApplicationPID();
 
 private:
@@ -66,14 +62,22 @@ private:
     void providePresentingApplicationPIDIfNecessary() final;
     void sessionWillEndPlayback(PlatformMediaSession&, DelayCallingUpdateNowPlaying) final;
 
+    // MediaSessionHelperClient
+    void receivedInterruption(InterruptionType, ShouldResume) final;
+    void applicationWillEnterForeground(SuspendedUnderLock) final;
+    void applicationDidEnterBackground(SuspendedUnderLock) final;
+    void applicationWillBecomeInactive() final;
+    void applicationDidBecomeActive() final;
+    void externalOutputDeviceAvailableDidChange(HasAvailableTargets) final;
+    void activeAudioRouteDidChange(ShouldPause) final;
+    void activeVideoRouteDidChange(SupportsAirPlayVideo, Ref<MediaPlaybackTarget>&&) final;
+    void isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit) final;
 #if !RELEASE_LOG_DISABLED
     const char* logClassName() const final { return "MediaSessionManageriOS"; }
 #endif
 
-    RetainPtr<WebMediaSessionHelper> m_objcObserver;
-#if HAVE(CELESTIAL)
+    bool m_isMonitoringWirelessRoutes { false };
     bool m_havePresentedApplicationPID { false };
-#endif
 };
 
 } // namespace WebCore
index cf25fb4..80e5b70 100644 (file)
 #import "RuntimeApplicationChecks.h"
 #import "SystemMemory.h"
 #import "WebCoreThreadRun.h"
-#import <AVFoundation/AVAudioSession.h>
-#import <AVFoundation/AVRouteDetector.h>
-#import <objc/runtime.h>
-#import <pal/spi/cocoa/AVFoundationSPI.h>
-#import <pal/spi/ios/CelestialSPI.h>
-#import <pal/spi/ios/UIKitSPI.h>
-#import <wtf/BlockObjCExceptions.h>
 #import <wtf/MainThread.h>
 #import <wtf/RAMSize.h>
 #import <wtf/RetainPtr.h>
 
-#import <pal/cocoa/AVFoundationSoftLink.h>
-#import <pal/ios/UIKitSoftLink.h>
-
-WEBCORE_EXPORT NSString* WebUIApplicationWillResignActiveNotification = @"WebUIApplicationWillResignActiveNotification";
-WEBCORE_EXPORT NSString* WebUIApplicationWillEnterForegroundNotification = @"WebUIApplicationWillEnterForegroundNotification";
-WEBCORE_EXPORT NSString* WebUIApplicationDidBecomeActiveNotification = @"WebUIApplicationDidBecomeActiveNotification";
-WEBCORE_EXPORT NSString* WebUIApplicationDidEnterBackgroundNotification = @"WebUIApplicationDidEnterBackgroundNotification";
-
-#if HAVE(CELESTIAL)
-SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(Celestial)
-SOFT_LINK_CLASS_OPTIONAL(Celestial, AVSystemController)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PIDToInheritApplicationStateFrom, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedAttribute, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedDidChangeNotification, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedNotificationParameter, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ServerConnectionDiedNotification, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotification, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PickedRouteAttribute, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo, NSString *)
-#endif
-
-using namespace WebCore;
-
-@interface WebMediaSessionHelper : NSObject {
-    MediaSessionManageriOS* _callback;
-
-#if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-    RetainPtr<AVRouteDetector> _routeDetector;
-#endif
-    bool _monitoringAirPlayRoutes;
-    bool _startMonitoringAirPlayRoutesPending;
-}
-
-- (id)initWithCallback:(MediaSessionManageriOS*)callback;
-
-- (void)clearCallback;
-- (void)interruption:(NSNotification *)notification;
-- (void)applicationWillEnterForeground:(NSNotification *)notification;
-- (void)applicationWillResignActive:(NSNotification *)notification;
-- (void)applicationDidEnterBackground:(NSNotification *)notification;
-- (BOOL)hasWirelessTargetsAvailable;
-
-#if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-- (void)startMonitoringAirPlayRoutes;
-- (void)stopMonitoringAirPlayRoutes;
-#endif
-
-@end
-
 namespace WebCore {
 
 std::unique_ptr<PlatformMediaSessionManager> PlatformMediaSessionManager::create()
 {
-    return std::unique_ptr<MediaSessionManageriOS>(new MediaSessionManageriOS);
+    auto manager = std::unique_ptr<MediaSessionManageriOS>(new MediaSessionManageriOS);
+    MediaSessionHelper::sharedHelper().addClient(*manager);
+    return WTFMove(manager);
 }
 
 MediaSessionManageriOS::MediaSessionManageriOS()
     : MediaSessionManagerCocoa()
 {
-    BEGIN_BLOCK_OBJC_EXCEPTIONS
-    m_objcObserver = adoptNS([[WebMediaSessionHelper alloc] initWithCallback:this]);
-    END_BLOCK_OBJC_EXCEPTIONS
-    resetRestrictions();
-
-#if HAVE(CELESTIAL)
-    updateCarPlayIsConnected(WTF::nullopt);
-#endif
 }
 
 MediaSessionManageriOS::~MediaSessionManageriOS()
 {
-    BEGIN_BLOCK_OBJC_EXCEPTIONS
-    [m_objcObserver clearCallback];
-    m_objcObserver = nil;
-    END_BLOCK_OBJC_EXCEPTIONS
+    if (m_isMonitoringWirelessRoutes)
+        MediaSessionHelper::sharedHelper().stopMonitoringWirelessRoutes();
+    MediaSessionHelper::sharedHelper().removeClient(*this);
 }
 
 void MediaSessionManageriOS::resetRestrictions()
@@ -143,9 +79,7 @@ void MediaSessionManageriOS::resetRestrictions()
 
 bool MediaSessionManageriOS::hasWirelessTargetsAvailable()
 {
-    BEGIN_BLOCK_OBJC_EXCEPTIONS
-    return [m_objcObserver hasWirelessTargetsAvailable];
-    END_BLOCK_OBJC_EXCEPTIONS
+    return MediaSessionHelper::sharedHelper().isExternalOutputDeviceAvailable();
 }
 
 void MediaSessionManageriOS::configureWireLessTargetMonitoring()
@@ -155,16 +89,17 @@ void MediaSessionManageriOS::configureWireLessTargetMonitoring()
         return session.requiresPlaybackTargetRouteMonitoring();
     });
 
-    ALWAYS_LOG(LOGIDENTIFIER, "requiresMonitoring = ", requiresMonitoring);
+    if (requiresMonitoring == m_isMonitoringWirelessRoutes)
+        return;
 
-    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    m_isMonitoringWirelessRoutes = requiresMonitoring;
+
+    ALWAYS_LOG(LOGIDENTIFIER, "requiresMonitoring = ", requiresMonitoring);
 
     if (requiresMonitoring)
-        [m_objcObserver startMonitoringAirPlayRoutes];
+        MediaSessionHelper::sharedHelper().startMonitoringWirelessRoutes();
     else
-        [m_objcObserver stopMonitoringAirPlayRoutes];
-
-    END_BLOCK_OBJC_EXCEPTIONS
+        MediaSessionHelper::sharedHelper().stopMonitoringWirelessRoutes();
 #endif
 }
 
@@ -174,21 +109,13 @@ void MediaSessionManageriOS::providePresentingApplicationPIDIfNecessary()
     if (m_havePresentedApplicationPID)
         return;
     m_havePresentedApplicationPID = true;
-    providePresentingApplicationPID();
+    MediaSessionHelper::sharedHelper().providePresentingApplicationPID(presentingApplicationPID());
 #endif
 }
 
 void MediaSessionManageriOS::providePresentingApplicationPID()
 {
-#if HAVE(CELESTIAL)
-    if (!canLoadAVSystemController_PIDToInheritApplicationStateFrom())
-        return;
-
-    NSError *error = nil;
-    [[getAVSystemControllerClass() sharedAVSystemController] setAttribute:@(presentingApplicationPID()) forKey:getAVSystemController_PIDToInheritApplicationStateFrom() error:&error];
-    if (error)
-        WTFLogAlways("Failed to set up PID proxying: %s", error.localizedDescription.UTF8String);
-#endif
+    MediaSessionHelper::sharedHelper().providePresentingApplicationPID(presentingApplicationPID());
 }
 
 void MediaSessionManageriOS::sessionWillEndPlayback(PlatformMediaSession& session, DelayCallingUpdateNowPlaying delayCallingUpdateNowPlaying)
@@ -201,45 +128,25 @@ void MediaSessionManageriOS::sessionWillEndPlayback(PlatformMediaSession& sessio
 #endif
 }
 
-void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange()
+void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange(HasAvailableTargets haveTargets)
 {
-    BEGIN_BLOCK_OBJC_EXCEPTIONS
-
-    bool haveTargets = [m_objcObserver hasWirelessTargetsAvailable];
     ALWAYS_LOG(LOGIDENTIFIER, haveTargets);
 
     forEachSession([haveTargets] (auto& session) {
-        session.externalOutputDeviceAvailableDidChange(haveTargets);
+        session.externalOutputDeviceAvailableDidChange(haveTargets == HasAvailableTargets::Yes);
     });
-
-    END_BLOCK_OBJC_EXCEPTIONS
 }
 
-#if HAVE(CELESTIAL)
-void MediaSessionManageriOS::carPlayServerDied()
+void MediaSessionManageriOS::isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit playingToAutomotiveHeadUnit)
 {
-    ALWAYS_LOG(LOGIDENTIFIER);
-    updateCarPlayIsConnected(WTF::nullopt);
+    setIsPlayingToAutomotiveHeadUnit(playingToAutomotiveHeadUnit == PlayingToAutomotiveHeadUnit::Yes);
 }
 
-void MediaSessionManageriOS::updateCarPlayIsConnected(Optional<bool>&& carPlayIsConnected)
+void MediaSessionManageriOS::activeAudioRouteDidChange(ShouldPause shouldPause)
 {
-    if (carPlayIsConnected) {
-        setIsPlayingToAutomotiveHeadUnit(carPlayIsConnected.value());
-        return;
-    }
+    ALWAYS_LOG(LOGIDENTIFIER, shouldPause);
 
-    if (!canLoadAVSystemController_CarPlayIsConnectedAttribute()) {
-        setIsPlayingToAutomotiveHeadUnit(false);
-        return;
-    }
-
-    setIsPlayingToAutomotiveHeadUnit([[[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_CarPlayIsConnectedAttribute()] boolValue]);
-}
-
-void MediaSessionManageriOS::activeAudioRouteDidChange(Optional<bool>&& shouldPause)
-{
-    if (!shouldPause || !shouldPause.value())
+    if (shouldPause != ShouldPause::Yes)
         return;
 
     forEachSession([](auto& session) {
@@ -248,313 +155,63 @@ void MediaSessionManageriOS::activeAudioRouteDidChange(Optional<bool>&& shouldPa
     });
 }
 
-void MediaSessionManageriOS::activeVideoRouteDidChange(Optional<bool>&& supportsAirPlayVideo)
+void MediaSessionManageriOS::activeVideoRouteDidChange(SupportsAirPlayVideo supportsAirPlayVideo, Ref<MediaPlaybackTarget>&& playbackTarget)
 {
+    ALWAYS_LOG(LOGIDENTIFIER, supportsAirPlayVideo);
     auto nowPlayingSession = nowPlayingEligibleSession();
     if (!nowPlayingSession)
         return;
 
-    auto shouldPlayToPlaybackTarget = supportsAirPlayVideo.valueOr(false);
-    auto playbackTarget = MediaPlaybackTargetCocoa::create([PAL::getAVOutputContextClass() sharedAudioPresentationOutputContext]);
-    nowPlayingSession->setShouldPlayToPlaybackTarget(shouldPlayToPlaybackTarget);
+    nowPlayingSession->setShouldPlayToPlaybackTarget(supportsAirPlayVideo == SupportsAirPlayVideo::Yes);
     nowPlayingSession->setPlaybackTarget(WTFMove(playbackTarget));
 }
-#endif
-
-} // namespace WebCore
-
-@implementation WebMediaSessionHelper
-
-- (id)initWithCallback:(MediaSessionManageriOS*)callback
-{
-    LOG(Media, "-[WebMediaSessionHelper initWithCallback]");
-
-    if (!(self = [super init]))
-        return nil;
-    
-    _callback = callback;
-
-    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
-    [center addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[PAL::getAVAudioSessionClass() sharedInstance]];
-
-    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:PAL::get_UIKit_UIApplicationWillEnterForegroundNotification() object:nil];
-    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:WebUIApplicationWillEnterForegroundNotification object:nil];
-    [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:PAL::get_UIKit_UIApplicationDidBecomeActiveNotification() object:nil];
-    [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:WebUIApplicationDidBecomeActiveNotification object:nil];
-    [center addObserver:self selector:@selector(applicationWillResignActive:) name:PAL::get_UIKit_UIApplicationWillResignActiveNotification() object:nil];
-    [center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
-    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:PAL::get_UIKit_UIApplicationDidEnterBackgroundNotification() object:nil];
-    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
-#if HAVE(CELESTIAL)
-    if (canLoadAVSystemController_ServerConnectionDiedNotification())
-        [center addObserver:self selector:@selector(carPlayServerDied:) name:getAVSystemController_ServerConnectionDiedNotification() object:nil];
-    if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification())
-        [center addObserver:self selector:@selector(carPlayIsConnectedDidChange:) name:getAVSystemController_CarPlayIsConnectedDidChangeNotification() object:nil];
-    if (canLoadAVSystemController_ActiveAudioRouteDidChangeNotification())
-        [center addObserver:self selector:@selector(activeAudioRouteDidChange:) name:getAVSystemController_ActiveAudioRouteDidChangeNotification() object:nil];
-#endif
-
-    // Now playing won't work unless we turn on the delivery of remote control events.
-    dispatch_async(dispatch_get_main_queue(), ^ {
-        BEGIN_BLOCK_OBJC_EXCEPTIONS
-        [[PAL::getUIApplicationClass() sharedApplication] beginReceivingRemoteControlEvents];
-        END_BLOCK_OBJC_EXCEPTIONS
-    });
-
-    return self;
-}
-
-- (void)dealloc
-{
-    LOG(Media, "-[WebMediaSessionHelper dealloc]");
-
-#if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-    if (!pthread_main_np()) {
-        dispatch_async(dispatch_get_main_queue(), [routeDetector = WTFMove(_routeDetector)] () mutable {
-            LOG(Media, "safelyTearDown - dipatched to UI thread.");
-            BEGIN_BLOCK_OBJC_EXCEPTIONS
-            routeDetector.get().routeDetectionEnabled = NO;
-            routeDetector.clear();
-            END_BLOCK_OBJC_EXCEPTIONS
-        });
-    } else
-        _routeDetector.get().routeDetectionEnabled = NO;
-#endif
-
-    [[NSNotificationCenter defaultCenter] removeObserver:self];
-    [super dealloc];
-}
-
-- (void)clearCallback
-{
-    LOG(Media, "-[WebMediaSessionHelper clearCallback]");
-    _callback = nil;
-}
-
-- (BOOL)hasWirelessTargetsAvailable
-{
-    LOG(Media, "-[WebMediaSessionHelper hasWirelessTargetsAvailable]");
-#if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-    return _routeDetector.get().multipleRoutesDetected;
-#else
-    return NO;
-#endif
-}
-
-#if HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-- (void)startMonitoringAirPlayRoutes
-{
-    if (_monitoringAirPlayRoutes)
-        return;
-
-    _monitoringAirPlayRoutes = true;
-
-    if (_startMonitoringAirPlayRoutesPending)
-        return;
-
-    if (_routeDetector) {
-        _routeDetector.get().routeDetectionEnabled = YES;
-        return;
-    }
-
-    _startMonitoringAirPlayRoutesPending = true;
-
-    LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes]");
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
-        ASSERT(!protectedSelf->_routeDetector);
-
-        if (protectedSelf->_callback) {
-            BEGIN_BLOCK_OBJC_EXCEPTIONS
-            protectedSelf->_routeDetector = adoptNS([PAL::allocAVRouteDetectorInstance() init]);
-            protectedSelf->_routeDetector.get().routeDetectionEnabled = protectedSelf->_monitoringAirPlayRoutes;
-            [[NSNotificationCenter defaultCenter] addObserver:protectedSelf.get() selector:@selector(wirelessRoutesAvailableDidChange:) name:AVRouteDetectorMultipleRoutesDetectedDidChangeNotification object:protectedSelf->_routeDetector.get()];
-
-            protectedSelf->_callback->externalOutputDeviceAvailableDidChange();
-            END_BLOCK_OBJC_EXCEPTIONS
-        }
-
-        protectedSelf->_startMonitoringAirPlayRoutesPending = false;
-    });
-}
-
-- (void)stopMonitoringAirPlayRoutes
-{
-    if (!_monitoringAirPlayRoutes)
-        return;
-
-    LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
-
-    _monitoringAirPlayRoutes = false;
-    _routeDetector.get().routeDetectionEnabled = NO;
-}
-#endif // HAVE(MEDIA_PLAYER) && !PLATFORM(WATCHOS)
-
-- (void)interruption:(NSNotification *)notification
-{
-    if (!_callback || _callback->willIgnoreSystemInterruptions())
-        return;
-
-    NSUInteger type = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
-    PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
-
-    LOG(Media, "-[WebMediaSessionHelper interruption] - type = %i", (int)type);
-
-    if (type == AVAudioSessionInterruptionTypeEnded && [[[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue] == AVAudioSessionInterruptionOptionShouldResume)
-        flags = PlatformMediaSession::MayResumePlaying;
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), type, flags]() mutable {
-        auto* callback = protectedSelf->_callback;
-        if (!callback)
-            return;
-
-        if (type == AVAudioSessionInterruptionTypeBegan)
-            callback->beginInterruption(PlatformMediaSession::SystemInterruption);
-        else
-            callback->endInterruption(flags);
-
-    });
-}
 
-- (void)applicationWillEnterForeground:(NSNotification *)notification
+void MediaSessionManageriOS::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
 {
-    UNUSED_PARAM(notification);
-
-    if (!_callback || _callback->willIgnoreSystemInterruptions())
+    if (willIgnoreSystemInterruptions())
         return;
 
-    LOG(Media, "-[WebMediaSessionHelper applicationWillEnterForeground]");
-
-    BOOL isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue];
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), isSuspendedUnderLock]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->applicationWillEnterForeground(isSuspendedUnderLock);
-    });
-}
+    auto flags = shouldResume == ShouldResume::Yes ? PlatformMediaSession::MayResumePlaying : PlatformMediaSession::NoFlags;
 
-- (void)applicationDidBecomeActive:(NSNotification *)notification
-{
-    UNUSED_PARAM(notification);
-
-    if (!_callback || _callback->willIgnoreSystemInterruptions())
-        return;
-
-    LOG(Media, "-[WebMediaSessionHelper applicationDidBecomeActive]");
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->applicationDidBecomeActive();
-    });
+    if (type == InterruptionType::Begin)
+        beginInterruption(PlatformMediaSession::SystemInterruption);
+    else
+        endInterruption(flags);
 }
 
-- (void)applicationWillResignActive:(NSNotification *)notification
+void MediaSessionManageriOS::applicationWillEnterForeground(SuspendedUnderLock isSuspendedUnderLock)
 {
-    UNUSED_PARAM(notification);
-
-    if (!_callback || _callback->willIgnoreSystemInterruptions())
+    if (willIgnoreSystemInterruptions())
         return;
 
-    LOG(Media, "-[WebMediaSessionHelper applicationWillResignActive]");
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->applicationWillBecomeInactive();
-    });
+    MediaSessionManagerCocoa::applicationWillEnterForeground(isSuspendedUnderLock == SuspendedUnderLock::Yes);
 }
 
-- (void)wirelessRoutesAvailableDidChange:(NSNotification *)notification
+void MediaSessionManageriOS::applicationDidBecomeActive()
 {
-    UNUSED_PARAM(notification);
-
-    if (!_callback || !_monitoringAirPlayRoutes)
+    if (willIgnoreSystemInterruptions())
         return;
 
-    LOG(Media, "-[WebMediaSessionHelper wirelessRoutesAvailableDidChange]");
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->externalOutputDeviceAvailableDidChange();
-    });
+    MediaSessionManagerCocoa::applicationDidBecomeActive();
 }
 
-- (void)applicationDidEnterBackground:(NSNotification *)notification
+void MediaSessionManageriOS::applicationDidEnterBackground(SuspendedUnderLock isSuspendedUnderLock)
 {
-    if (!_callback || _callback->willIgnoreSystemInterruptions())
+    if (willIgnoreSystemInterruptions())
         return;
 
-    LOG(Media, "-[WebMediaSessionHelper applicationDidEnterBackground]");
-
-    BOOL isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue];
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), isSuspendedUnderLock]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->applicationDidEnterBackground(isSuspendedUnderLock);
-    });
+    MediaSessionManagerCocoa::applicationDidEnterBackground(isSuspendedUnderLock == SuspendedUnderLock::Yes);
 }
 
-#if HAVE(CELESTIAL)
-- (void)carPlayServerDied:(NSNotification *)notification
+void MediaSessionManageriOS::applicationWillBecomeInactive()
 {
-    if (!_callback)
+    if (willIgnoreSystemInterruptions())
         return;
 
-    LOG(Media, "-[WebMediaSessionHelper carPlayServerDied:]");
-    UNUSED_PARAM(notification);
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->carPlayServerDied();
-    });
+    MediaSessionManagerCocoa::applicationWillBecomeInactive();
 }
 
-- (void)carPlayIsConnectedDidChange:(NSNotification *)notification
-{
-    if (!_callback)
-        return;
-
-    Optional<bool> carPlayIsConnected;
-    if (notification && canLoadAVSystemController_CarPlayIsConnectedNotificationParameter()) {
-        NSNumber *nsCarPlayIsConnected = [[notification userInfo] valueForKey:getAVSystemController_CarPlayIsConnectedNotificationParameter()];
-        if (nsCarPlayIsConnected)
-            carPlayIsConnected = [nsCarPlayIsConnected boolValue];
-    }
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), carPlayIsConnected = WTFMove(carPlayIsConnected)]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->updateCarPlayIsConnected(WTFMove(carPlayIsConnected));
-    });
-}
-
-- (void)activeAudioRouteDidChange:(NSNotification *)notification
-{
-    if (!_callback)
-        return;
-
-    UNUSED_PARAM(notification);
-    Optional<bool> shouldPause;
-    if (notification && canLoadAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()) {
-        NSNumber* nsShouldPause = [notification.userInfo valueForKey:getAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()];
-        if (nsShouldPause)
-            shouldPause = nsShouldPause.boolValue;
-    }
-
-    Optional<bool> supportsAirPlayVideo;
-    if (canLoadAVSystemController_PickedRouteAttribute() && canLoadAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()) {
-        NSDictionary* pickedRoute = [[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_PickedRouteAttribute()];
-        if ([pickedRoute isKindOfClass:NSDictionary.class]) {
-            NSNumber* nsSupportsAirPlayVideo = [pickedRoute valueForKey:getAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()];
-            if (nsSupportsAirPlayVideo)
-                supportsAirPlayVideo = nsSupportsAirPlayVideo.boolValue;
-        }
-    }
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), shouldPause = WTFMove(shouldPause), supportsAirPlayVideo = WTFMove(supportsAirPlayVideo)]() mutable {
-        if (auto* callback = protectedSelf->_callback) {
-            callback->activeAudioRouteDidChange(WTFMove(shouldPause));
-            callback->activeVideoRouteDidChange(WTFMove(supportsAirPlayVideo));
-        }
-    });
+} // namespace WebCore
 
-}
-#endif // HAVE(CELESTIAL)
-@end
 
 #endif // PLATFORM(IOS_FAMILY)
index 53be26e..a88fd65 100644 (file)
@@ -1,3 +1,60 @@
+2020-03-06  Jer Noble  <jer.noble@apple.com>
+
+        [GPUP] Move AVSystemController code into the GPU process
+        https://bugs.webkit.org/show_bug.cgi?id=208727
+
+        Reviewed by Eric Carlson.
+
+        Add a new class pair RemoteMediaSessionHelper/Proxy.
+
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * GPUProcess/GPUConnectionToWebProcess.cpp:
+        (WebKit::GPUConnectionToWebProcess::mediaSessionHelperProxy):
+        (WebKit::GPUConnectionToWebProcess::ensureMediaSessionHelper):
+        * GPUProcess/GPUConnectionToWebProcess.h:
+        * GPUProcess/GPUConnectionToWebProcess.messages.in:
+        * GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp: Added.
+        (WebKit::RemoteMediaSessionHelperProxy::RemoteMediaSessionHelperProxy):
+        (WebKit::RemoteMediaSessionHelperProxy::~RemoteMediaSessionHelperProxy):
+        (WebKit::RemoteMediaSessionHelperProxy::startMonitoringWirelessRoutes):
+        (WebKit::RemoteMediaSessionHelperProxy::stopMonitoringWirelessRoutes):
+        (WebKit::RemoteMediaSessionHelperProxy::providePresentingApplicationPID):
+        (WebKit::RemoteMediaSessionHelperProxy::receivedInterruption):
+        (WebKit::RemoteMediaSessionHelperProxy::applicationWillEnterForeground):
+        (WebKit::RemoteMediaSessionHelperProxy::applicationDidEnterBackground):
+        (WebKit::RemoteMediaSessionHelperProxy::applicationWillBecomeInactive):
+        (WebKit::RemoteMediaSessionHelperProxy::applicationDidBecomeActive):
+        (WebKit::RemoteMediaSessionHelperProxy::externalOutputDeviceAvailableDidChange):
+        (WebKit::RemoteMediaSessionHelperProxy::isPlayingToAutomotiveHeadUnitDidChange):
+        (WebKit::RemoteMediaSessionHelperProxy::activeAudioRouteDidChange):
+        (WebKit::RemoteMediaSessionHelperProxy::activeVideoRouteDidChange):
+        * GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h: Added.
+        * GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in: Added.
+        * Sources.txt:
+        * SourcesCocoa.txt:
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp: Added.
+        (WebKit::RemoteMediaSessionHelper::RemoteMediaSessionHelper):
+        (WebKit::RemoteMediaSessionHelper::connection):
+        (WebKit::RemoteMediaSessionHelper::startMonitoringWirelessRoutes):
+        (WebKit::RemoteMediaSessionHelper::stopMonitoringWirelessRoutes):
+        (WebKit::RemoteMediaSessionHelper::providePresentingApplicationPID):
+        (WebKit::RemoteMediaSessionHelper::receivedInterruption):
+        (WebKit::RemoteMediaSessionHelper::applicationWillEnterForeground):
+        (WebKit::RemoteMediaSessionHelper::applicationDidEnterBackground):
+        (WebKit::RemoteMediaSessionHelper::applicationWillBecomeInactive):
+        (WebKit::RemoteMediaSessionHelper::applicationDidBecomeActive):
+        (WebKit::RemoteMediaSessionHelper::externalOutputDeviceAvailableDidChange):
+        (WebKit::RemoteMediaSessionHelper::isPlayingToAutomotiveHeadUnitDidChange):
+        (WebKit::RemoteMediaSessionHelper::activeAudioRouteDidChange):
+        (WebKit::RemoteMediaSessionHelper::activeVideoRouteDidChange):
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h: Added.
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in: Added.
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::setUseGPUProcessForMedia):
+
 2020-03-08  Jer Noble  <jer.noble@apple.com>
 
         [GPUP] Null-dereference crash in GPUProcessProxy::openGPUProcessConnection()
index d749b2d..ee040b1 100644 (file)
@@ -27,6 +27,7 @@ $(PROJECT_DIR)/GPUProcess/media/RemoteCDMProxy.messages.in
 $(PROJECT_DIR)/GPUProcess/media/RemoteMediaPlayerManagerProxy.messages.in
 $(PROJECT_DIR)/GPUProcess/media/RemoteMediaPlayerProxy.messages.in
 $(PROJECT_DIR)/GPUProcess/media/RemoteMediaResourceManager.messages.in
+$(PROJECT_DIR)/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in
 $(PROJECT_DIR)/GPUProcess/webrtc/LibWebRTCCodecsProxy.messages.in
 $(PROJECT_DIR)/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRenderer.messages.in
 $(PROJECT_DIR)/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.messages.in
@@ -122,6 +123,7 @@ $(PROJECT_DIR)/WebProcess/GPU/media/RemoteAudioSession.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/media/RemoteCDMInstanceSession.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/media/RemoteMediaPlayerManager.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/media/TextTrackPrivateRemote.messages.in
+$(PROJECT_DIR)/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/webrtc/LibWebRTCCodecs.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/webrtc/LibWebRTCRemoteCodecs.messages.in
 $(PROJECT_DIR)/WebProcess/GPU/webrtc/SampleBufferDisplayLayer.messages.in
index 9950351..0b85736 100644 (file)
@@ -183,6 +183,12 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaRecordersMessagesReplies
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaResourceManagerMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaResourceManagerMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaResourceManagerMessagesReplies.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperMessageReceiver.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperMessages.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperMessagesReplies.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperProxyMessageReceiver.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperProxyMessages.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteMediaSessionHelperProxyMessagesReplies.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteObjectRegistryMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteObjectRegistryMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteObjectRegistryMessagesReplies.h
index 1c3d1a2..cb7152f 100644 (file)
@@ -26,6 +26,7 @@ VPATH = \
     $(WebKit2)/GPUProcess/graphics \
     $(WebKit2)/GPUProcess/mac \
     $(WebKit2)/GPUProcess/media \
+    $(WebKit2)/GPUProcess/media/ios \
     $(WebKit2)/GPUProcess/webrtc \
     $(WebKit2)/NetworkProcess \
     $(WebKit2)/NetworkProcess/Cookies \
@@ -54,6 +55,7 @@ VPATH = \
     $(WebKit2)/WebProcess/GPU \
     $(WebKit2)/WebProcess/GPU/graphics \
     $(WebKit2)/WebProcess/GPU/media \
+    $(WebKit2)/WebProcess/GPU/media/ios \
     $(WebKit2)/WebProcess/GPU/webrtc \
     $(WebKit2)/WebProcess/IconDatabase \
     $(WebKit2)/WebProcess/Inspector \
@@ -164,6 +166,8 @@ MESSAGE_RECEIVERS = \
     RemoteMediaRecorder \
     RemoteMediaRecorderManager \
     RemoteMediaResourceManager \
+    RemoteMediaSessionHelper \
+    RemoteMediaSessionHelperProxy \
     RemoteObjectRegistry \
     RemoteRenderingBackend \
     RemoteRenderingBackendProxy \
index 73c9708..df56781 100644 (file)
 #include "RemoteAudioSessionProxyMessages.h"
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+#include "RemoteMediaSessionHelperProxy.h"
+#endif
+
 namespace WebKit {
 using namespace WebCore;
 
@@ -289,6 +293,20 @@ void GPUConnectionToWebProcess::ensureAudioSession(EnsureAudioSessionCompletion&
 }
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+RemoteMediaSessionHelperProxy& GPUConnectionToWebProcess::mediaSessionHelperProxy()
+{
+    if (!m_mediaSessionHelperProxy)
+        m_mediaSessionHelperProxy = makeUnique<RemoteMediaSessionHelperProxy>(*this);
+    return *m_mediaSessionHelperProxy;
+}
+
+void GPUConnectionToWebProcess::ensureMediaSessionHelper()
+{
+    mediaSessionHelperProxy();
+}
+#endif
+
 bool GPUConnectionToWebProcess::dispatchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
 {
     if (decoder.messageReceiverName() == Messages::RemoteAudioDestinationManager::messageReceiverName()) {
index 80156d1..368b0bf 100644 (file)
@@ -51,6 +51,7 @@ class RemoteCDMFactoryProxy;
 class RemoteMediaPlayerManagerProxy;
 class RemoteMediaRecorderManager;
 class RemoteMediaResourceManager;
+class RemoteMediaSessionHelperProxy;
 class RemoteSampleBufferDisplayLayerManager;
 class UserMediaCaptureManagerProxy;
 struct RemoteAudioSessionConfiguration;
@@ -87,7 +88,9 @@ public:
 #if ENABLE(ENCRYPTED_MEDIA)
     RemoteCDMFactoryProxy& cdmFactoryProxy();
 #endif
-
+#if PLATFORM(IOS_FAMILY)
+    RemoteMediaSessionHelperProxy& mediaSessionHelperProxy();
+#endif
     RemoteMediaPlayerManagerProxy& remoteMediaPlayerManagerProxy();
 #if ENABLE(GPU_PROCESS) && USE(AUDIO_SESSION)
     RemoteAudioSessionProxyManager& audioSessionManager();
@@ -124,6 +127,10 @@ private:
     void ensureAudioSession(EnsureAudioSessionCompletion&&);
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+    void ensureMediaSessionHelper();
+#endif
+
     // IPC::Connection::Client
     void didClose(IPC::Connection&) final;
     void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) final;
@@ -167,6 +174,9 @@ private:
 #if ENABLE(GPU_PROCESS) && USE(AUDIO_SESSION)
     std::unique_ptr<RemoteAudioSessionProxy> m_audioSessionProxy;
 #endif
+#if PLATFORM(IOS_FAMILY)
+    std::unique_ptr<RemoteMediaSessionHelperProxy> m_mediaSessionHelperProxy;
+#endif
 };
 
 } // namespace WebKit
index 5ab4172..d87d761 100644 (file)
@@ -30,6 +30,9 @@ messages -> GPUConnectionToWebProcess WantsDispatchMessage {
     void SetNowPlayingInfo(bool setAsNowPlayingApplication, struct WebCore::NowPlayingInfo nowPlayingInfo);
 #endif
     EnsureAudioSession() -> (struct WebKit::RemoteAudioSessionConfiguration configuration) Synchronous
+#if PLATFORM(IOS_FAMILY)
+    EnsureMediaSessionHelper()
+#endif
 }
 
 #endif // ENABLE(GPU_PROCESS)
diff --git a/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp b/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp
new file mode 100644 (file)
index 0000000..6e60b44
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 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 "RemoteMediaSessionHelperProxy.h"
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+#include "Connection.h"
+#include "GPUConnectionToWebProcess.h"
+#include "RemoteMediaSessionHelperMessages.h"
+
+namespace WebKit {
+using namespace WebCore;
+
+RemoteMediaSessionHelperProxy::RemoteMediaSessionHelperProxy(GPUConnectionToWebProcess& gpuConnection)
+    : m_gpuConnection(gpuConnection)
+{
+    MediaSessionHelper::sharedHelper().addClient(*this);
+}
+
+RemoteMediaSessionHelperProxy::~RemoteMediaSessionHelperProxy()
+{
+    stopMonitoringWirelessRoutes();
+    MediaSessionHelper::sharedHelper().removeClient(*this);
+}
+
+void RemoteMediaSessionHelperProxy::startMonitoringWirelessRoutes()
+{
+    if (m_isMonitoringWirelessRoutes)
+        return;
+
+    m_isMonitoringWirelessRoutes = true;
+    MediaSessionHelper::sharedHelper().startMonitoringWirelessRoutes();
+}
+
+void RemoteMediaSessionHelperProxy::stopMonitoringWirelessRoutes()
+{
+    if (!m_isMonitoringWirelessRoutes)
+        return;
+
+    m_isMonitoringWirelessRoutes = false;
+    MediaSessionHelper::sharedHelper().stopMonitoringWirelessRoutes();
+}
+
+void RemoteMediaSessionHelperProxy::providePresentingApplicationPID(int pid)
+{
+    if (m_providedApplicationPID)
+        return;
+
+    m_providedApplicationPID = true;
+    MediaSessionHelper::sharedHelper().providePresentingApplicationPID(pid);
+}
+
+void RemoteMediaSessionHelperProxy::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ReceivedInterruption(type, shouldResume), { });
+}
+
+void RemoteMediaSessionHelperProxy::applicationWillEnterForeground(SuspendedUnderLock suspendedUnderLock)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ApplicationWillEnterForeground(suspendedUnderLock), { });
+}
+
+void RemoteMediaSessionHelperProxy::applicationDidEnterBackground(SuspendedUnderLock suspendedUnderLock)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ApplicationDidEnterBackground(suspendedUnderLock), { });
+}
+
+void RemoteMediaSessionHelperProxy::applicationWillBecomeInactive()
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ApplicationWillBecomeInactive(), { });
+}
+
+void RemoteMediaSessionHelperProxy::applicationDidBecomeActive()
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ApplicationDidBecomeActive(), { });
+}
+
+void RemoteMediaSessionHelperProxy::externalOutputDeviceAvailableDidChange(HasAvailableTargets hasAvailableTargets)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ExternalOutputDeviceAvailableDidChange(hasAvailableTargets), { });
+}
+
+void RemoteMediaSessionHelperProxy::isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit playing)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::IsPlayingToAutomotiveHeadUnitDidChange(playing), { });
+}
+
+void RemoteMediaSessionHelperProxy::activeAudioRouteDidChange(ShouldPause shouldPause)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ActiveAudioRouteDidChange(shouldPause), { });
+}
+
+void RemoteMediaSessionHelperProxy::activeVideoRouteDidChange(SupportsAirPlayVideo supportsAirPlayVideo, Ref<WebCore::MediaPlaybackTarget>&& target)
+{
+    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ActiveVideoRouteDidChange(supportsAirPlayVideo, target->targetContext()), { });
+}
+
+}
+
+#endif
diff --git a/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h b/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h
new file mode 100644 (file)
index 0000000..4ab50f0
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+#include "MessageReceiver.h"
+#include <WebCore/MediaSessionHelperIOS.h>
+
+namespace WebKit {
+
+class GPUConnectionToWebProcess;
+
+class RemoteMediaSessionHelperProxy
+    : public WebCore::MediaSessionHelperClient
+    , public IPC::MessageReceiver {
+    WTF_MAKE_FAST_ALLOCATED();
+public:
+    RemoteMediaSessionHelperProxy(GPUConnectionToWebProcess&);
+    virtual ~RemoteMediaSessionHelperProxy();
+
+private:
+    // IPC::MessageReceiver
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
+
+    // Messages
+    void startMonitoringWirelessRoutes();
+    void stopMonitoringWirelessRoutes();
+    void providePresentingApplicationPID(int);
+
+    // MediaSessionHelperClient
+    void receivedInterruption(InterruptionType, ShouldResume) final;
+    void applicationWillEnterForeground(SuspendedUnderLock) final;
+    void applicationDidEnterBackground(SuspendedUnderLock) final;
+    void applicationWillBecomeInactive() final;
+    void applicationDidBecomeActive() final;
+    void externalOutputDeviceAvailableDidChange(HasAvailableTargets) final;
+    void isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit) final;
+    void activeAudioRouteDidChange(ShouldPause) final;
+    void activeVideoRouteDidChange(SupportsAirPlayVideo, Ref<WebCore::MediaPlaybackTarget>&&) final;
+
+    bool m_providedApplicationPID { false };
+    bool m_isMonitoringWirelessRoutes { false };
+    GPUConnectionToWebProcess& m_gpuConnection;
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in b/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.messages.in
new file mode 100644 (file)
index 0000000..af26c48
--- /dev/null
@@ -0,0 +1,32 @@
+# Copyright (C) 2020 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.
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+messages -> RemoteMediaSessionHelperProxy NotRefCounted {
+    StartMonitoringWirelessRoutes()
+    StopMonitoringWirelessRoutes()
+    ProvidePresentingApplicationPID(int pid)
+}
+
+#endif
index 1056b9e..1c9245e 100644 (file)
@@ -40,6 +40,7 @@ GPUProcess/media/RemoteMediaResourceLoader.cpp
 GPUProcess/media/RemoteMediaResourceManager.cpp
 GPUProcess/media/RemoteTextTrackProxy.cpp
 GPUProcess/media/RemoteVideoTrackProxy.cpp
+GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp
 GPUProcess/webrtc/RemoteAudioMediaStreamTrackRenderer.cpp
 GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.cpp
 GPUProcess/webrtc/RemoteMediaRecorder.cpp
@@ -560,6 +561,7 @@ WebProcess/GPU/media/RemoteMediaResourceProxy.cpp
 WebProcess/GPU/media/TextTrackPrivateRemote.cpp
 WebProcess/GPU/media/VideoTrackPrivateRemote.cpp
 WebProcess/GPU/media/WebMediaStrategy.cpp
+WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp
 WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp
 WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp
 WebProcess/GPU/webrtc/MediaRecorderProvider.cpp
index ed9f44b..f9323fb 100644 (file)
@@ -662,6 +662,8 @@ RemoteAudioMediaStreamTrackRendererManagerMessageReceiver.cpp
 RemoteAudioMediaStreamTrackRendererMessageReceiver.cpp
 RemoteMediaRecorderMessageReceiver.cpp
 RemoteMediaRecorderManagerMessageReceiver.cpp
+RemoteMediaSessionHelperMessageReceiver.cpp
+RemoteMediaSessionHelperProxyMessageReceiver.cpp
 RemoteRenderingBackendMessageReceiver.cpp
 RemoteRenderingBackendProxyMessageReceiver.cpp
 RemoteSampleBufferDisplayLayerManagerMessageReceiver.cpp
index dd41ce8..0e32684 100644 (file)
                CDA29A271CBEB67A00901CCF /* PlaybackSessionManagerProxyMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaybackSessionManagerProxyMessages.h; path = DerivedSources/WebKit2/PlaybackSessionManagerProxyMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
                CDA93DAE22F8BCF300490A69 /* FullscreenTouchSecheuristicParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FullscreenTouchSecheuristicParameters.h; path = ios/fullscreen/FullscreenTouchSecheuristicParameters.h; sourceTree = "<group>"; };
                CDA93DAF22F8BCF400490A69 /* FullscreenTouchSecheuristicParameters.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FullscreenTouchSecheuristicParameters.cpp; path = ios/fullscreen/FullscreenTouchSecheuristicParameters.cpp; sourceTree = "<group>"; };
+               CDA9593A2412B17500910EEF /* RemoteMediaSessionHelper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteMediaSessionHelper.cpp; sourceTree = "<group>"; };
+               CDA9593B2412B17500910EEF /* RemoteMediaSessionHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteMediaSessionHelper.h; sourceTree = "<group>"; };
+               CDA9593C2412B64500910EEF /* RemoteMediaSessionHelper.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteMediaSessionHelper.messages.in; sourceTree = "<group>"; };
+               CDA959452412C4F500910EEF /* RemoteMediaSessionHelperProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteMediaSessionHelperProxy.h; sourceTree = "<group>"; };
+               CDA959462412C4F500910EEF /* RemoteMediaSessionHelperProxy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteMediaSessionHelperProxy.cpp; sourceTree = "<group>"; };
+               CDA959472412C91900910EEF /* RemoteMediaSessionHelperProxy.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteMediaSessionHelperProxy.messages.in; sourceTree = "<group>"; };
                CDAC207823FB1E210021DEE3 /* RemoteCDMFactoryProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteCDMFactoryProxy.h; sourceTree = "<group>"; };
                CDAC207923FB1E210021DEE3 /* RemoteCDMFactoryProxy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteCDMFactoryProxy.cpp; sourceTree = "<group>"; };
                CDAC207C23FB1EF90021DEE3 /* RemoteCDMFactoryProxy.messages.in */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteCDMFactoryProxy.messages.in; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                1DAF5A4D23EC9F7900B7B518 /* cocoa */,
+                               CDA959392412B17500910EEF /* ios */,
                                071BC57923C93BB900680D7C /* AudioTrackPrivateRemote.cpp */,
                                071BC57723C93BB700680D7C /* AudioTrackPrivateRemote.h */,
                                07923131239B3B0C009598E2 /* MediaPlayerPrivateRemote.cpp */,
                        isa = PBXGroup;
                        children = (
                                1D0ECEA923FC84BB00D172F6 /* cocoa */,
+                               CDA959442412C4DA00910EEF /* ios */,
                                9B1229CC23FF25F2008CA751 /* RemoteAudioDestinationManager.cpp */,
                                9B1229CB23FF25F2008CA751 /* RemoteAudioDestinationManager.h */,
                                9B1229CF23FF2814008CA751 /* RemoteAudioDestinationManager.messages.in */,
                        name = FullScreen;
                        sourceTree = "<group>";
                };
+               CDA959392412B17500910EEF /* ios */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CDA9593A2412B17500910EEF /* RemoteMediaSessionHelper.cpp */,
+                               CDA9593B2412B17500910EEF /* RemoteMediaSessionHelper.h */,
+                               CDA9593C2412B64500910EEF /* RemoteMediaSessionHelper.messages.in */,
+                       );
+                       path = ios;
+                       sourceTree = "<group>";
+               };
+               CDA959442412C4DA00910EEF /* ios */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CDA959462412C4F500910EEF /* RemoteMediaSessionHelperProxy.cpp */,
+                               CDA959452412C4F500910EEF /* RemoteMediaSessionHelperProxy.h */,
+                               CDA959472412C91900910EEF /* RemoteMediaSessionHelperProxy.messages.in */,
+                       );
+                       path = ios;
+                       sourceTree = "<group>";
+               };
                CDC2831A201BD75600E6E745 /* fullscreen */ = {
                        isa = PBXGroup;
                        children = (
diff --git a/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp b/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp
new file mode 100644 (file)
index 0000000..fef4d75
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 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 "RemoteMediaSessionHelper.h"
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+#include "Connection.h"
+#include "RemoteMediaSessionHelperProxyMessages.h"
+#include "WebProcess.h"
+#include <WebCore/MediaPlaybackTargetCocoa.h>
+#include <WebCore/MediaPlaybackTargetContext.h>
+#include <WebCore/MediaPlaybackTargetMock.h>
+
+namespace WebKit {
+
+using namespace WebCore;
+
+RemoteMediaSessionHelper::RemoteMediaSessionHelper(WebProcess& process)
+    : m_process(process)
+{
+    connection().send(Messages::GPUConnectionToWebProcess::EnsureMediaSessionHelper(), { });
+}
+
+IPC::Connection& RemoteMediaSessionHelper::connection()
+{
+    return m_process.ensureGPUProcessConnection().connection();
+}
+
+void RemoteMediaSessionHelper::startMonitoringWirelessRoutes()
+{
+    if (m_monitoringWirelessRoutesCount++)
+        return;
+
+    connection().send(Messages::RemoteMediaSessionHelperProxy::StartMonitoringWirelessRoutes(), { });
+}
+
+void RemoteMediaSessionHelper::stopMonitoringWirelessRoutes()
+{
+    if (!m_monitoringWirelessRoutesCount) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    if (--m_monitoringWirelessRoutesCount)
+        return;
+
+    connection().send(Messages::RemoteMediaSessionHelperProxy::StopMonitoringWirelessRoutes(), { });
+}
+
+void RemoteMediaSessionHelper::providePresentingApplicationPID(int pid)
+{
+    connection().send(Messages::RemoteMediaSessionHelperProxy::ProvidePresentingApplicationPID(pid), { });
+}
+
+void RemoteMediaSessionHelper::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
+{
+    for (auto& client : m_clients)
+        client.receivedInterruption(type, shouldResume);
+}
+
+void RemoteMediaSessionHelper::applicationWillEnterForeground(SuspendedUnderLock suspendedUnderLock)
+{
+    for (auto& client : m_clients)
+        client.applicationWillEnterForeground(suspendedUnderLock);
+}
+
+void RemoteMediaSessionHelper::applicationDidEnterBackground(SuspendedUnderLock suspendedUnderLock)
+{
+    for (auto& client : m_clients)
+        client.applicationDidEnterBackground(suspendedUnderLock);
+}
+
+void RemoteMediaSessionHelper::applicationWillBecomeInactive()
+{
+    for (auto& client : m_clients)
+        client.applicationWillBecomeInactive();
+}
+
+void RemoteMediaSessionHelper::applicationDidBecomeActive()
+{
+    for (auto& client : m_clients)
+        client.applicationDidBecomeActive();
+}
+
+void RemoteMediaSessionHelper::externalOutputDeviceAvailableDidChange(HasAvailableTargets hasAvailableTargets)
+{
+    for (auto& client : m_clients)
+        client.externalOutputDeviceAvailableDidChange(hasAvailableTargets);
+}
+
+void RemoteMediaSessionHelper::isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit playingToAutomotiveHeadUnit)
+{
+    for (auto& client : m_clients)
+        client.isPlayingToAutomotiveHeadUnitDidChange(playingToAutomotiveHeadUnit);
+}
+
+void RemoteMediaSessionHelper::activeAudioRouteDidChange(ShouldPause shouldPause)
+{
+    for (auto& client : m_clients)
+        client.activeAudioRouteDidChange(shouldPause);
+}
+
+void RemoteMediaSessionHelper::activeVideoRouteDidChange(SupportsAirPlayVideo supportsAirPlayVideo, MediaPlaybackTargetContext&& targetContext)
+{
+    RefPtr<MediaPlaybackTarget> targetObject;
+    if (targetContext.type() == MediaPlaybackTargetContext::AVOutputContextType)
+        targetObject = WebCore::MediaPlaybackTargetCocoa::create(targetContext.avOutputContext());
+    else {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    for (auto& client : m_clients)
+        client.activeVideoRouteDidChange(supportsAirPlayVideo, targetObject.copyRef().releaseNonNull());
+}
+
+}
+
+#endif
+
diff --git a/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h b/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h
new file mode 100644 (file)
index 0000000..cd0f098
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+#include "MessageReceiver.h"
+#include <WebCore/MediaSessionHelperIOS.h>
+
+namespace WebKit {
+
+class WebProcess;
+
+class RemoteMediaSessionHelper final
+    : public WebCore::MediaSessionHelper
+    , public IPC::MessageReceiver {
+public:
+    RemoteMediaSessionHelper(WebProcess&);
+    virtual ~RemoteMediaSessionHelper() = default;
+
+    IPC::Connection& connection();
+
+    using HasAvailableTargets = WebCore::MediaSessionHelperClient::HasAvailableTargets;
+    using InterruptionType = WebCore::MediaSessionHelperClient::InterruptionType;
+    using PlayingToAutomotiveHeadUnit = WebCore::MediaSessionHelperClient::PlayingToAutomotiveHeadUnit;
+    using ShouldPause = WebCore::MediaSessionHelperClient::ShouldPause;
+    using ShouldResume = WebCore::MediaSessionHelperClient::ShouldResume;
+    using SupportsAirPlayVideo = WebCore::MediaSessionHelperClient::SupportsAirPlayVideo;
+    using SuspendedUnderLock = WebCore::MediaSessionHelperClient::SuspendedUnderLock;
+
+private:
+    // IPC::MessageReceiver
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
+
+    // MediaSessionHelper
+    void startMonitoringWirelessRoutes() final;
+    void stopMonitoringWirelessRoutes() final;
+    void providePresentingApplicationPID(int) final;
+
+    // Messages
+    void receivedInterruption(InterruptionType, ShouldResume);
+    void applicationWillEnterForeground(SuspendedUnderLock);
+    void applicationDidEnterBackground(SuspendedUnderLock);
+    void applicationWillBecomeInactive();
+    void applicationDidBecomeActive();
+    void externalOutputDeviceAvailableDidChange(HasAvailableTargets);
+    void isPlayingToAutomotiveHeadUnitDidChange(PlayingToAutomotiveHeadUnit);
+    void activeAudioRouteDidChange(ShouldPause);
+    void activeVideoRouteDidChange(SupportsAirPlayVideo, WebCore::MediaPlaybackTargetContext&&);
+
+    WebProcess& m_process;
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in b/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in
new file mode 100644 (file)
index 0000000..8e3c57c
--- /dev/null
@@ -0,0 +1,38 @@
+# Copyright (C) 2020 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.
+
+#if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
+
+messages -> RemoteMediaSessionHelper NotRefCounted {
+    ReceivedInterruption(enum:bool WebKit::RemoteMediaSessionHelper::InterruptionType type, enum:bool WebKit::RemoteMediaSessionHelper::ShouldResume shouldResume)
+    ApplicationWillEnterForeground(enum:bool WebKit::RemoteMediaSessionHelper::SuspendedUnderLock suspendedUnderLock)
+    ApplicationDidEnterBackground(enum:bool WebKit::RemoteMediaSessionHelper::SuspendedUnderLock suspendedUnderLock)
+    ApplicationWillBecomeInactive()
+    ApplicationDidBecomeActive()
+    ExternalOutputDeviceAvailableDidChange(enum:bool WebKit::RemoteMediaSessionHelper::HasAvailableTargets hasAvailableTargets)
+    IsPlayingToAutomotiveHeadUnitDidChange(enum:bool WebKit::RemoteMediaSessionHelper::PlayingToAutomotiveHeadUnit isPlayingToAutomotiveHeadUnit)
+    ActiveAudioRouteDidChange(enum:bool WebKit::RemoteMediaSessionHelper::ShouldPause shouldPause)
+    ActiveVideoRouteDidChange(enum:bool WebKit::RemoteMediaSessionHelper::SupportsAirPlayVideo supportsAirPlayVideo, WebCore::MediaPlaybackTargetContext target)
+}
+
+#endif
index cc1a32d..dd12d01 100644 (file)
 #include "RemoteCDMFactory.h"
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+#include "RemoteMediaSessionHelper.h"
+#endif
+
 #define RELEASE_LOG_SESSION_ID (m_sessionID ? m_sessionID->toUInt64() : 0)
 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [sessionID=%" PRIu64 "] WebProcess::" fmt, this, RELEASE_LOG_SESSION_ID, ##__VA_ARGS__)
 
@@ -2014,6 +2018,13 @@ void WebProcess::setUseGPUProcessForMedia(bool useGPUProcessForMedia)
     else
         AudioSession::setSharedSession(AudioSession::create());
 #endif
+
+#if PLATFORM(IOS_FAMILY)
+    if (useGPUProcessForMedia)
+        MediaSessionHelper::setSharedHelper(makeUniqueRef<RemoteMediaSessionHelper>(*this));
+    else
+        MediaSessionHelper::resetSharedHelper();
+#endif
 }
 #endif