[iOS] REGRESSION(r168075): Fullscreen web video doesn't pause on screen lock
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jul 2015 22:29:54 +0000 (22:29 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jul 2015 22:29:54 +0000 (22:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=147269

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2015-07-28
Reviewed by Andreas Kling.

Media elements should pause when the application is going to EnterBackground
under lock regardless whether it is in full screen or not.

Source/WebCore:

* platform/audio/PlatformMediaSession.h:
* platform/audio/PlatformMediaSession.cpp:
(WebCore::PlatformMediaSession::doInterruption): This code was moved from
beginInterruption().

(WebCore::PlatformMediaSession::shouldDoInterruption): Move the condition
which allows the media session interruption to a separate function.

(WebCore::PlatformMediaSession::beginInterruption): Call the functions
shouldDoInterruption() and doInterruption().

(WebCore::PlatformMediaSession::forceInterruption): This function will
be called from PlatformMediaSessionManager::applicationDidEnterBackground()
to override the decision which is made by PlatformMediaSession::beginInterruption()
if the application isSuspendedUnderLock.

* platform/audio/PlatformMediaSessionManager.h:
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::applicationDidEnterBackground):
[UIApp isSuspendedUnderLock] is only valid when it is called when the
UIApplicationDidEnterBackgroundNotification is received. We need to force
interrupting the media sessions if the application isSuspendedUnderLock
and UIApplicationWillResignActiveNotification was ignored because of PiP.

* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(-[WebMediaSessionHelper initWithCallback:]):
(-[WebMediaSessionHelper applicationDidEnterBackground:]): Listen to
UIApplicationDidEnterBackgroundNotification and make a call on the web
thread to PlatformMediaSessionManager::applicationDidEnterBackground()
and pass the isSuspendedUnderLock flag which is queried on the UIProcess.

Source/WebKit2:

* Platform/spi/ios/UIKitSPI.h: Forward declare [UIApplication isSuspendedUnderLock].

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::applicationDidEnterBackground):
[UIApp isSuspendedUnderLock] can only be called in the UIProcess. We need
to call it here and pass it to the WebPage in the WebProcess as part of the
ApplicationDidEnterBackground message.

* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in: Add the new parameter:
'isSuspendedUnderLock' to the ApplicationDidEnterBackground message.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::applicationDidEnterBackground): On iOS, the WebPage needs
to notify the MediaSessionManagerIOS that it received the message
ApplicationDidEnterBackground.

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

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/audio/PlatformMediaSession.cpp
Source/WebCore/platform/audio/PlatformMediaSession.h
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/PlatformMediaSessionManager.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebKit2/ChangeLog
Source/WebKit2/Platform/spi/ios/UIKitSPI.h
Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

index 24dcb56..df409ad 100644 (file)
@@ -1,3 +1,45 @@
+2015-07-28  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        [iOS] REGRESSION(r168075): Fullscreen web video doesn't pause on screen lock
+        https://bugs.webkit.org/show_bug.cgi?id=147269
+
+        Reviewed by Andreas Kling.
+
+        Media elements should pause when the application is going to EnterBackground
+        under lock regardless whether it is in full screen or not.
+
+        * platform/audio/PlatformMediaSession.h:
+        * platform/audio/PlatformMediaSession.cpp:
+        (WebCore::PlatformMediaSession::doInterruption): This code was moved from 
+        beginInterruption().
+                
+        (WebCore::PlatformMediaSession::shouldDoInterruption): Move the condition 
+        which allows the media session interruption to a separate function.
+        
+        (WebCore::PlatformMediaSession::beginInterruption): Call the functions
+        shouldDoInterruption() and doInterruption().
+        
+        (WebCore::PlatformMediaSession::forceInterruption): This function will
+        be called from PlatformMediaSessionManager::applicationDidEnterBackground()
+        to override the decision which is made by PlatformMediaSession::beginInterruption()
+        if the application isSuspendedUnderLock.
+        
+        * platform/audio/PlatformMediaSessionManager.h:
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::applicationDidEnterBackground):
+        [UIApp isSuspendedUnderLock] is only valid when it is called when the
+        UIApplicationDidEnterBackgroundNotification is received. We need to force
+        interrupting the media sessions if the application isSuspendedUnderLock
+        and UIApplicationWillResignActiveNotification was ignored because of PiP.
+
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (-[WebMediaSessionHelper initWithCallback:]):
+        (-[WebMediaSessionHelper applicationDidEnterBackground:]): Listen to 
+        UIApplicationDidEnterBackgroundNotification and make a call on the web
+        thread to PlatformMediaSessionManager::applicationDidEnterBackground() 
+        and pass the isSuspendedUnderLock flag which is queried on the UIProcess.
+
 2015-07-28  Tim Horton  <timothy_horton@apple.com>
 
         [iOS] Creating a TextIndicator causes the view to scroll to the current selection
index 832c71e..d980f4d 100644 (file)
@@ -79,13 +79,8 @@ void PlatformMediaSession::setState(State state)
     m_state = state;
 }
 
-void PlatformMediaSession::beginInterruption(InterruptionType type)
+void PlatformMediaSession::doInterruption()
 {
-    LOG(Media, "PlatformMediaSession::beginInterruption(%p), state = %s, interruption count = %i", this, stateName(m_state), m_interruptionCount);
-
-    if (++m_interruptionCount > 1 || (type == EnteringBackground && client().overrideBackgroundPlaybackRestriction()))
-        return;
-
     m_stateToRestore = state();
     m_notifyingClient = true;
     setState(Interrupted);
@@ -93,6 +88,40 @@ void PlatformMediaSession::beginInterruption(InterruptionType type)
     m_notifyingClient = false;
 }
 
+bool PlatformMediaSession::shouldDoInterruption(InterruptionType type)
+{
+    return type != EnteringBackground || !client().overrideBackgroundPlaybackRestriction();
+}
+
+void PlatformMediaSession::beginInterruption(InterruptionType type)
+{
+    LOG(Media, "PlatformMediaSession::beginInterruption(%p), state = %s, interruption count = %i", this, stateName(m_state), m_interruptionCount);
+
+    if (++m_interruptionCount > 1 || !shouldDoInterruption(type))
+        return;
+
+    doInterruption();
+}
+
+void PlatformMediaSession::forceInterruption(InterruptionType type)
+{
+    LOG(Media, "PlatformMediaSession::forceInterruption(%p), state = %s, interruption count = %i", this, stateName(m_state), m_interruptionCount);
+
+    // beginInterruption() must have been called before calling this function.
+    if (!m_interruptionCount) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    // The purpose of this function is to override the decision which was made by
+    // beginInterruption(). If it was decided to interrupt the media session there,
+    // then nothing should be done here.
+    if (shouldDoInterruption(type))
+        return;
+
+    doInterruption();
+}
+
 void PlatformMediaSession::endInterruption(EndInterruptionFlags flags)
 {
     LOG(Media, "PlatformMediaSession::endInterruption(%p) - flags = %i, stateToRestore = %s, interruption count = %i", this, (int)flags, stateName(m_stateToRestore), m_interruptionCount);
index f6c47c9..820eadf 100644 (file)
@@ -79,11 +79,16 @@ public:
         NoFlags = 0,
         MayResumePlaying = 1 << 0,
     };
+
+    void doInterruption();
+    bool shouldDoInterruption(InterruptionType);
     void beginInterruption(InterruptionType);
+    void forceInterruption(InterruptionType);
     void endInterruption(EndInterruptionFlags);
 
     void applicationWillEnterForeground() const;
     void applicationWillEnterBackground() const;
+    void applicationDidEnterBackground(bool isSuspendedUnderLock) const;
 
     bool clientWillBeginPlayback();
     bool clientWillPausePlayback();
index de1d861..35971d5 100644 (file)
@@ -283,6 +283,20 @@ void PlatformMediaSessionManager::applicationWillEnterBackground() const
     }
 }
 
+void PlatformMediaSessionManager::applicationDidEnterBackground(bool isSuspendedUnderLock) const
+{
+    LOG(Media, "PlatformMediaSessionManager::applicationDidEnterBackground");
+
+    if (!isSuspendedUnderLock)
+        return;
+
+    Vector<PlatformMediaSession*> sessions = m_sessions;
+    for (auto* session : sessions) {
+        if (m_restrictions[session->mediaType()] & BackgroundProcessPlaybackRestricted)
+            session->forceInterruption(PlatformMediaSession::EnteringBackground);
+    }
+}
+
 void PlatformMediaSessionManager::applicationWillEnterForeground() const
 {
     LOG(Media, "PlatformMediaSessionManager::applicationWillEnterForeground");
index 01d3b1e..1996249 100644 (file)
@@ -56,6 +56,7 @@ public:
 
     WEBCORE_EXPORT void applicationWillEnterForeground() const;
     WEBCORE_EXPORT void applicationWillEnterBackground() const;
+    WEBCORE_EXPORT void applicationDidEnterBackground(bool isSuspendedUnderLock) const;
 
     void stopAllMediaPlaybackForDocument(const Document*);
     WEBCORE_EXPORT void stopAllMediaPlaybackForProcess();
index 3b2e75f..e23d7a3 100644 (file)
@@ -37,6 +37,7 @@ OBJC_CLASS WebMediaSessionHelper;
 extern NSString* WebUIApplicationWillResignActiveNotification;
 extern NSString* WebUIApplicationWillEnterForegroundNotification;
 extern NSString* WebUIApplicationDidBecomeActiveNotification;
+extern NSString* WebUIApplicationDidEnterBackgroundNotification;
 #endif
 
 namespace WebCore {
index 544feee..895c1b0 100644 (file)
@@ -61,11 +61,13 @@ SOFT_LINK_CLASS(UIKit, UIApplication)
 SOFT_LINK_POINTER(UIKit, UIApplicationWillResignActiveNotification, NSString *)
 SOFT_LINK_POINTER(UIKit, UIApplicationWillEnterForegroundNotification, NSString *)
 SOFT_LINK_POINTER(UIKit, UIApplicationDidBecomeActiveNotification, NSString *)
+SOFT_LINK_POINTER(UIKit, UIApplicationDidEnterBackgroundNotification, NSString *)
 
 #define UIApplication getUIApplicationClass()
 #define UIApplicationWillResignActiveNotification getUIApplicationWillResignActiveNotification()
 #define UIApplicationWillEnterForegroundNotification getUIApplicationWillEnterForegroundNotification()
 #define UIApplicationDidBecomeActiveNotification getUIApplicationDidBecomeActiveNotification()
+#define UIApplicationDidEnterBackgroundNotification getUIApplicationDidEnterBackgroundNotification()
 
 SOFT_LINK_FRAMEWORK(MediaPlayer)
 SOFT_LINK_CLASS(MediaPlayer, MPAVRoutingController)
@@ -87,6 +89,7 @@ SOFT_LINK_POINTER(MediaPlayer, MPVolumeViewWirelessRoutesAvailableDidChangeNotif
 WEBCORE_EXPORT NSString* WebUIApplicationWillResignActiveNotification = @"WebUIApplicationWillResignActiveNotification";
 WEBCORE_EXPORT NSString* WebUIApplicationWillEnterForegroundNotification = @"WebUIApplicationWillEnterForegroundNotification";
 WEBCORE_EXPORT NSString* WebUIApplicationDidBecomeActiveNotification = @"WebUIApplicationDidBecomeActiveNotification";
+WEBCORE_EXPORT NSString* WebUIApplicationDidEnterBackgroundNotification = @"WebUIApplicationDidEnterBackgroundNotification";
 
 using namespace WebCore;
 
@@ -103,6 +106,7 @@ using namespace WebCore;
 - (void)interruption:(NSNotification *)notification;
 - (void)applicationWillEnterForeground:(NSNotification *)notification;
 - (void)applicationWillResignActive:(NSNotification *)notification;
+- (void)applicationDidEnterBackground:(NSNotification *)notification;
 - (BOOL)hasWirelessTargetsAvailable;
 - (void)startMonitoringAirPlayRoutes;
 - (void)stopMonitoringAirPlayRoutes;
@@ -293,6 +297,8 @@ void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange()
     [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:WebUIApplicationDidBecomeActiveNotification object:nil];
     [center addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
     [center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
+    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
+    [center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
 
     [self allocateVolumeView];
 
@@ -448,7 +454,7 @@ void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange()
     WebThreadRun(^{
         if (!_callback)
             return;
-        
+
         _callback->applicationWillEnterBackground();
     });
 }
@@ -469,6 +475,23 @@ void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange()
         _callback->externalOutputDeviceAvailableDidChange();
     });
 }
+
+- (void)applicationDidEnterBackground:(NSNotification *)notification
+{
+    if (!_callback)
+        return;
+
+    LOG(Media, "-[WebMediaSessionHelper applicationDidEnterBackground]");
+
+    BOOL isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue];
+
+    WebThreadRun(^{
+        if (!_callback)
+            return;
+
+        _callback->applicationDidEnterBackground(isSuspendedUnderLock);
+    });
+}
 @end
 
 #endif // PLATFORM(IOS)
index ad2f694..9515538 100644 (file)
@@ -1,3 +1,30 @@
+2015-07-28  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        [iOS] REGRESSION(r168075): Fullscreen web video doesn't pause on screen lock
+        https://bugs.webkit.org/show_bug.cgi?id=147269
+
+        Reviewed by Andreas Kling.
+
+        Media elements should pause when the application is going to EnterBackground
+        under lock regardless whether it is in full screen or not.
+
+        * Platform/spi/ios/UIKitSPI.h: Forward declare [UIApplication isSuspendedUnderLock].
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::applicationDidEnterBackground):
+        [UIApp isSuspendedUnderLock] can only be called in the UIProcess. We need
+        to call it here and pass it to the WebPage in the WebProcess as part of the
+        ApplicationDidEnterBackground message.
+        
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in: Add the new parameter:
+        'isSuspendedUnderLock' to the ApplicationDidEnterBackground message.
+        
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::applicationDidEnterBackground): On iOS, the WebPage needs
+        to notify the MediaSessionManagerIOS that it received the message 
+        ApplicationDidEnterBackground.
+
 2015-07-28  Yongjun Zhang  <yongjun_zhang@apple.com>
 
         Bounds in InteractionInformationAtPosition should be always in main frame coordinate space.
index d7c63c3..3142bb7 100644 (file)
 - (UIInterfaceOrientation)interfaceOrientation;
 - (void)_cancelAllTouches;
 - (CGFloat)statusBarHeight;
+- (BOOL)isSuspendedUnderLock;
 @end
 
 typedef NS_ENUM(NSInteger, UIDatePickerPrivateMode)  {
index 7c522c6..2725606 100644 (file)
@@ -36,6 +36,7 @@
 #import "RemoteLayerTreeDrawingAreaProxy.h"
 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
 #import "RemoteLayerTreeTransaction.h"
+#import "UIKitSPI.h"
 #import "UserData.h"
 #import "ViewUpdateDispatcherMessages.h"
 #import "WKBrowsingContextControllerInternal.h"
@@ -606,7 +607,8 @@ void WebPageProxy::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t fla
 
 void WebPageProxy::applicationDidEnterBackground()
 {
-    m_process->send(Messages::WebPage::ApplicationDidEnterBackground(), m_pageID);
+    bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
+    m_process->send(Messages::WebPage::ApplicationDidEnterBackground(isSuspendedUnderLock), m_pageID);
 }
 
 void WebPageProxy::applicationWillEnterForeground()
index bc87c6a..3cb6266 100644 (file)
@@ -804,7 +804,7 @@ public:
     bool scaleWasSetByUIProcess() const { return m_scaleWasSetByUIProcess; }
     void willStartUserTriggeredZooming();
     void applicationWillResignActive();
-    void applicationDidEnterBackground();
+    void applicationDidEnterBackground(bool isSuspendedUnderLock);
     void applicationWillEnterForeground();
     void applicationDidBecomeActive();
     void zoomToRect(WebCore::FloatRect, double minimumScale, double maximumScale);
index c420cd3..00ab4fd 100644 (file)
@@ -89,7 +89,7 @@ messages -> WebPage LegacyReceiver {
     SetAssistedNodeValueAsNumber(double value)
     SetAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
     ApplicationWillResignActive()
-    ApplicationDidEnterBackground()
+    ApplicationDidEnterBackground(bool isSuspendedUnderLock)
     ApplicationWillEnterForeground()
     ApplicationDidBecomeActive()
     ContentSizeCategoryDidChange(String contentSizeCategory)
index 22fa637..af61b86 100644 (file)
@@ -2846,8 +2846,10 @@ void WebPage::volatilityTimerFired()
     m_volatilityTimer.stop();
 }
 
-void WebPage::applicationDidEnterBackground()
+void WebPage::applicationDidEnterBackground(bool isSuspendedUnderLock)
 {
+    [[NSNotificationCenter defaultCenter] postNotificationName:WebUIApplicationDidEnterBackgroundNotification object:nil userInfo:@{@"isSuspendedUnderLock": [NSNumber numberWithBool:isSuspendedUnderLock]}];
+
     setLayerTreeStateIsFrozen(true);
     if (markLayersVolatileImmediatelyIfPossible())
         return;