Title: [230490] trunk/Source/WebCore
Revision
230490
Author
commit-qu...@webkit.org
Date
2018-04-10 13:31:01 -0700 (Tue, 10 Apr 2018)

Log Message

MediaSessionManageriOS should defer creation of MPVolumeView until it needs to monitor AirPlay routes
https://bugs.webkit.org/show_bug.cgi?id=184373
<rdar://problem/35177606>

Patch by Jeremy Jones <jere...@apple.com> on 2018-04-10
Reviewed by Eric Carlson.

No change of behavior.

This delays the creation of MPVolumeView until airplay routes are monitored.
MPVolumeView is now also released when monitoring ends.
This makes sure the MP* objects are only accessed from a UI safe thread. WebCore's "MainThread" may be different that the UI thread.
Since this state change is necessarily asynchronous, starting and stopping must prevent races to keep state coherent.

* platform/audio/ios/MediaSessionManagerIOS.mm:
(-[WebMediaSessionHelper initWithCallback:]):
(-[WebMediaSessionHelper dealloc]):
(-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
(-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
(-[WebMediaSessionHelper allocateVolumeView]): Deleted.
(-[WebMediaSessionHelper setVolumeView:]): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (230489 => 230490)


--- trunk/Source/WebCore/ChangeLog	2018-04-10 19:46:40 UTC (rev 230489)
+++ trunk/Source/WebCore/ChangeLog	2018-04-10 20:31:01 UTC (rev 230490)
@@ -1,3 +1,26 @@
+2018-04-10  Jeremy Jones  <jere...@apple.com>
+
+        MediaSessionManageriOS should defer creation of MPVolumeView until it needs to monitor AirPlay routes
+        https://bugs.webkit.org/show_bug.cgi?id=184373
+        <rdar://problem/35177606>
+
+        Reviewed by Eric Carlson.
+
+        No change of behavior.
+
+        This delays the creation of MPVolumeView until airplay routes are monitored.
+        MPVolumeView is now also released when monitoring ends. 
+        This makes sure the MP* objects are only accessed from a UI safe thread. WebCore's "MainThread" may be different that the UI thread.
+        Since this state change is necessarily asynchronous, starting and stopping must prevent races to keep state coherent.
+
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (-[WebMediaSessionHelper initWithCallback:]):
+        (-[WebMediaSessionHelper dealloc]):
+        (-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
+        (-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
+        (-[WebMediaSessionHelper allocateVolumeView]): Deleted.
+        (-[WebMediaSessionHelper setVolumeView:]): Deleted.
+
 2018-04-10  Sihui Liu  <sihui_...@apple.com>
 
         Loading of multipart response was cancelled because of content policy set in WebFrameLoaderClient::dispatchDecidePolicyForResponse

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm (230489 => 230490)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2018-04-10 19:46:40 UTC (rev 230489)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2018-04-10 20:31:01 UTC (rev 230490)
@@ -106,16 +106,13 @@
 #if HAVE(MEDIA_PLAYER)
     RetainPtr<MPVolumeView> _volumeView;
     RetainPtr<MPAVRoutingController> _airPlayPresenceRoutingController;
+    bool _monitoringAirPlayRoutes;
+    bool _startMonitoringAirPlayRoutesPending;
 #endif
 }
 
 - (id)initWithCallback:(MediaSessionManageriOS*)callback;
 
-#if HAVE(MEDIA_PLAYER)
-- (void)allocateVolumeView;
-- (void)setVolumeView:(RetainPtr<MPVolumeView>)volumeView;
-#endif
-
 - (void)clearCallback;
 - (void)interruption:(NSNotification *)notification;
 - (void)applicationWillEnterForeground:(NSNotification *)notification;
@@ -325,39 +322,6 @@
 
 @implementation WebMediaSessionHelper
 
-#if HAVE(MEDIA_PLAYER)
-- (void)allocateVolumeView
-{
-    if (pthread_main_np()) {
-        [self setVolumeView:adoptNS([allocMPVolumeViewInstance() init])];
-        return;
-    }
-
-    RetainPtr<WebMediaSessionHelper> strongSelf = self;
-    dispatch_async(dispatch_get_main_queue(), [strongSelf]() {
-        BEGIN_BLOCK_OBJC_EXCEPTIONS
-        RetainPtr<MPVolumeView> volumeView = adoptNS([allocMPVolumeViewInstance() init]);
-        callOnWebThreadOrDispatchAsyncOnMainThread([strongSelf, volumeView]() {
-            BEGIN_BLOCK_OBJC_EXCEPTIONS
-            [strongSelf setVolumeView:volumeView];
-            END_BLOCK_OBJC_EXCEPTIONS
-        });
-        END_BLOCK_OBJC_EXCEPTIONS
-    });
-}
-
-- (void)setVolumeView:(RetainPtr<MPVolumeView>)volumeView
-{
-    if (_volumeView)
-        [[NSNotificationCenter defaultCenter] removeObserver:self name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:_volumeView.get()];
-
-    _volumeView = volumeView;
-
-    if (_volumeView)
-        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wirelessRoutesAvailableDidChange:) name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:_volumeView.get()];
-}
-#endif
-
 - (id)initWithCallback:(MediaSessionManageriOS*)callback
 {
     LOG(Media, "-[WebMediaSessionHelper initWithCallback]");
@@ -379,10 +343,6 @@
     [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
     [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
 
-#if HAVE(MEDIA_PLAYER)
-    [self allocateVolumeView];
-#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
@@ -393,24 +353,29 @@
     return self;
 }
 
+#if HAVE(MEDIA_PLAYER)
+static void safelyTearDown(RetainPtr<MPVolumeView> volumeView, RetainPtr<MPAVRoutingController> routingController)
+{
+    dispatch_async(dispatch_get_main_queue(), [volumeView = WTFMove(volumeView), routingController = WTFMove(routingController)] () mutable {
+        LOG(Media, "safelyTearDown - dipatched to UI thread.");
+        BEGIN_BLOCK_OBJC_EXCEPTIONS
+        [routingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
+        volumeView.clear();
+        routingController.clear();
+        END_BLOCK_OBJC_EXCEPTIONS
+    });
+}
+#endif
+
 - (void)dealloc
 {
     LOG(Media, "-[WebMediaSessionHelper dealloc]");
 
 #if HAVE(MEDIA_PLAYER)
-    if (!isMainThread()) {
-        callOnMainThread([volumeView = WTFMove(_volumeView), routingController = WTFMove(_airPlayPresenceRoutingController)] () mutable {
-            LOG(Media, "-[WebMediaSessionHelper dealloc] - dipatched to MainThread");
-
-            volumeView.clear();
-
-            if (!routingController)
-                return;
-
-            [routingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
-            routingController.clear();
-        });
-    }
+    if (!pthread_main_np())
+        safelyTearDown(WTFMove(_volumeView), WTFMove(_airPlayPresenceRoutingController));
+    else
+        [_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
 #endif
 
     [[NSNotificationCenter defaultCenter] removeObserver:self];
@@ -436,38 +401,68 @@
 #if HAVE(MEDIA_PLAYER)
 - (void)startMonitoringAirPlayRoutes
 {
-    if (_airPlayPresenceRoutingController)
+    if (_monitoringAirPlayRoutes)
         return;
 
+    _monitoringAirPlayRoutes = true;
+
+    if (_startMonitoringAirPlayRoutesPending)
+        return;
+
+    _startMonitoringAirPlayRoutesPending = true;
+
     LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes]");
 
-    callOnMainThread([protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () {
-        LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes] - dipatched to MainThread");
+    dispatch_async(dispatch_get_main_queue(), [protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () mutable {
+        LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes] - dipatched to main queue");
 
-        if (protectedSelf->_airPlayPresenceRoutingController)
-            return;
+        BEGIN_BLOCK_OBJC_EXCEPTIONS
+        RetainPtr<MPVolumeView> volumeView = adoptNS([allocMPVolumeViewInstance() init]);
+        RetainPtr<MPAVRoutingController> routingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebCore - HTML media element checking for AirPlay route presence"]);
 
-        protectedSelf->_airPlayPresenceRoutingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebCore - HTML media element checking for AirPlay route presence"]);
-        [protectedSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModePresence];
+        [routingController setDiscoveryMode:MPRouteDiscoveryModePresence];
+
+        callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(protectedSelf), volumeView = WTFMove(volumeView), routingController = WTFMove(routingController)]() mutable {
+
+            protectedSelf->_startMonitoringAirPlayRoutesPending = false;
+
+            if (!protectedSelf->_monitoringAirPlayRoutes) {
+                safelyTearDown(WTFMove(volumeView), WTFMove(routingController));
+                return;
+            }
+
+            ASSERT(!protectedSelf->_volumeView);
+            protectedSelf->_volumeView = volumeView;
+
+            [[NSNotificationCenter defaultCenter] addObserver:protectedSelf.get() selector:@selector(wirelessRoutesAvailableDidChange:) name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:volumeView.get()];
+
+            ASSERT(!protectedSelf->_airPlayPresenceRoutingController);
+            protectedSelf->_airPlayPresenceRoutingController = routingController;
+        });
+        END_BLOCK_OBJC_EXCEPTIONS
+
     });
 }
 
 - (void)stopMonitoringAirPlayRoutes
 {
-    if (!_airPlayPresenceRoutingController)
+    if (!_monitoringAirPlayRoutes)
         return;
 
+    _monitoringAirPlayRoutes = false;
+
     LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
 
-    callOnMainThread([protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () {
-        LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes] - dipatched to MainThread");
+    RetainPtr<MPVolumeView> volumeView = _volumeView;
+    RetainPtr<MPAVRoutingController> airPlayPresenceRoutingController = _airPlayPresenceRoutingController;
 
-        if (!protectedSelf->_airPlayPresenceRoutingController)
-            return;
+    _volumeView.clear();
+    _airPlayPresenceRoutingController.clear();
 
-        [protectedSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
-        protectedSelf->_airPlayPresenceRoutingController = nil;
-    });
+    if (volumeView)
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:volumeView.get()];
+
+    safelyTearDown(WTFMove(volumeView), WTFMove(airPlayPresenceRoutingController));
 }
 #endif // HAVE(MEDIA_PLAYER)
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to