[iOS] Pressing 'done' in fullscreen video sometimes does nothing; stuck in fullscreen
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Jul 2015 23:17:45 +0000 (23:17 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Jul 2015 23:17:45 +0000 (23:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=147367

Reviewed by Eric Carlson.

During the request to exit fullscreen, the video element's m_videoFullscreenMode variable
is set, but no exitFullscreen() request is sent up to the UIProcess. Previous threading
issues have been discovered and fixed, but may have been re-introduced (or never fully
fixed in the first place). To solve the bad behavior this threading issue creates, add
a watchdog timer, similar to the one used in the desktop fullscreen controller, to ensure
that if an exit fullscreen request is not acted upon, the UIProcess forcibly exits fullscreen
anyway.

* platform/ios/WebVideoFullscreenInterfaceAVKit.h:
* platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
(WebVideoFullscreenInterfaceAVKit::WebVideoFullscreenInterfaceAVKit): Initialize the timer.
(WebVideoFullscreenInterfaceAVKit::exitFullscreen): Cancel the timer.
(WebVideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason): Set the timer.
(WebVideoFullscreenInterfaceAVKit::watchdogTimerFired): Forcibly exit fullscreen mode.

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

Source/WebCore/ChangeLog
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm

index 486c9ac..13de724 100644 (file)
@@ -1,3 +1,25 @@
+2015-07-30  Jer Noble  <jer.noble@apple.com>
+
+        [iOS] Pressing 'done' in fullscreen video sometimes does nothing; stuck in fullscreen
+        https://bugs.webkit.org/show_bug.cgi?id=147367
+
+        Reviewed by Eric Carlson.
+
+        During the request to exit fullscreen, the video element's m_videoFullscreenMode variable
+        is set, but no exitFullscreen() request is sent up to the UIProcess. Previous threading
+        issues have been discovered and fixed, but may have been re-introduced (or never fully
+        fixed in the first place). To solve the bad behavior this threading issue creates, add
+        a watchdog timer, similar to the one used in the desktop fullscreen controller, to ensure
+        that if an exit fullscreen request is not acted upon, the UIProcess forcibly exits fullscreen
+        anyway.
+
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.h:
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
+        (WebVideoFullscreenInterfaceAVKit::WebVideoFullscreenInterfaceAVKit): Initialize the timer.
+        (WebVideoFullscreenInterfaceAVKit::exitFullscreen): Cancel the timer.
+        (WebVideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason): Set the timer.
+        (WebVideoFullscreenInterfaceAVKit::watchdogTimerFired): Forcibly exit fullscreen mode.
+
 2015-07-30  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Clean up makeFontCascadeCacheKey()
index 66ba775..a0af57a 100644 (file)
@@ -32,6 +32,7 @@
 #include <WebCore/EventListener.h>
 #include <WebCore/HTMLMediaElementEnums.h>
 #include <WebCore/PlatformLayer.h>
+#include <WebCore/Timer.h>
 #include <WebCore/WebVideoFullscreenInterface.h>
 #include <functional>
 #include <objc/objc.h>
@@ -132,6 +133,7 @@ protected:
     void beginSession();
     void enterPictureInPicture();
     void enterFullscreenStandard();
+    void watchdogTimerFired();
 
     RetainPtr<WebAVPlayerController> m_playerController;
     RetainPtr<AVPlayerViewController> m_playerViewController;
@@ -146,6 +148,7 @@ protected:
     RetainPtr<WebAVPlayerLayerView> m_playerLayerView;
     HTMLMediaElementEnums::VideoFullscreenMode m_mode { HTMLMediaElementEnums::VideoFullscreenModeNone };
     std::function<void(bool)> m_prepareToInlineCallback;
+    Timer m_watchdogTimer;
     bool m_allowsPictureInPicturePlayback { false };
     bool m_exitRequested { false };
     bool m_exitCompleted { false };
index 352aa7f..8a3bfcc 100644 (file)
@@ -77,6 +77,7 @@ static const char* boolString(bool val)
 }
 #endif
 
+static const double DefaultWatchdogTimerInterval = 1;
 
 @class WebAVMediaSelectionOption;
 
@@ -870,6 +871,7 @@ static Class getWebAVPlayerLayerViewClass()
 
 WebVideoFullscreenInterfaceAVKit::WebVideoFullscreenInterfaceAVKit()
     : m_playerController(adoptNS([[WebAVPlayerController alloc] init]))
+    , m_watchdogTimer(*this, &WebVideoFullscreenInterfaceAVKit::watchdogTimerFired)
 {
     [m_playerController setFullscreenInterface:this];
 }
@@ -1145,6 +1147,8 @@ void WebVideoFullscreenInterfaceAVKit::enterFullscreenStandard()
 
 void WebVideoFullscreenInterfaceAVKit::exitFullscreen(const WebCore::IntRect& finalRect)
 {
+    m_watchdogTimer.stop();
+
     m_exitRequested = true;
     if (m_exitCompleted) {
         if (m_fullscreenChangeObserver)
@@ -1379,11 +1383,22 @@ bool WebVideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason(WebVideoFu
     if (reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::RemoteControlStopEventReceived)
         m_videoFullscreenModel->pause();
     
+
     m_videoFullscreenModel->requestExitFullscreen();
-    
+
+    if (!m_watchdogTimer.isActive())
+        m_watchdogTimer.startOneShot(DefaultWatchdogTimerInterval);
+
     return false;
 }
 
+NO_RETURN_DUE_TO_ASSERT void WebVideoFullscreenInterfaceAVKit::watchdogTimerFired()
+{
+    LOG(Fullscreen, "WebVideoFullscreenInterfaceAVKit::watchdogTimerFired(%p) - no exit fullscreen response in %gs; forcing exit", this);
+    ASSERT_NOT_REACHED();
+    exitFullscreen(IntRect());
+}
+
 void WebVideoFullscreenInterfaceAVKit::setMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
 {
     HTMLMediaElementEnums::VideoFullscreenMode newMode = m_mode | mode;