[iOS] VideoFullscreenInterfaceAVKit should not ignore errors
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 20:58:58 +0000 (20:58 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 20:58:58 +0000 (20:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182497
<rdar://problem/36986898>

Reviewed by Jer Noble.

Always call layoutIfNeeded before calling -[AVPlayerViewController enterFullScreenAnimated:completionHandler]
or -[AVPlayerViewController exitFullScreenAnimated:completionHandler] because they both fail
if the view needs layout. Also don't ignore errors returned by those calls.

No new tests, the failure is non deterministic and I was not able to reproduce in a test.

* platform/ios/VideoFullscreenInterfaceAVKit.mm:
(VideoFullscreenInterfaceAVKit::applicationDidBecomeActive):
(VideoFullscreenInterfaceAVKit::enterFullscreenStandard):
(VideoFullscreenInterfaceAVKit::exitFullscreen):
(VideoFullscreenInterfaceAVKit::cleanupFullscreen):
(VideoFullscreenInterfaceAVKit::didStartPictureInPicture):
(VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletionHandler):
(VideoFullscreenInterfaceAVKit::doEnterFullscreen):
(VideoFullscreenInterfaceAVKit::exitFullscreenHandler):
(VideoFullscreenInterfaceAVKit::enterFullscreenHandler):

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

Source/WebCore/ChangeLog
Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm

index e3cca47..6b405c6 100644 (file)
@@ -1,3 +1,28 @@
+2018-02-05  Eric Carlson  <eric.carlson@apple.com>
+
+        [iOS] VideoFullscreenInterfaceAVKit should not ignore errors
+        https://bugs.webkit.org/show_bug.cgi?id=182497
+        <rdar://problem/36986898>
+
+        Reviewed by Jer Noble.
+        
+        Always call layoutIfNeeded before calling -[AVPlayerViewController enterFullScreenAnimated:completionHandler]
+        or -[AVPlayerViewController exitFullScreenAnimated:completionHandler] because they both fail
+        if the view needs layout. Also don't ignore errors returned by those calls.
+
+        No new tests, the failure is non deterministic and I was not able to reproduce in a test.
+
+        * platform/ios/VideoFullscreenInterfaceAVKit.mm:
+        (VideoFullscreenInterfaceAVKit::applicationDidBecomeActive):
+        (VideoFullscreenInterfaceAVKit::enterFullscreenStandard):
+        (VideoFullscreenInterfaceAVKit::exitFullscreen):
+        (VideoFullscreenInterfaceAVKit::cleanupFullscreen):
+        (VideoFullscreenInterfaceAVKit::didStartPictureInPicture):
+        (VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletionHandler):
+        (VideoFullscreenInterfaceAVKit::doEnterFullscreen):
+        (VideoFullscreenInterfaceAVKit::exitFullscreenHandler):
+        (VideoFullscreenInterfaceAVKit::enterFullscreenHandler):
+
 2018-02-05  Daniel Bates  <dabates@apple.com>
 
         REGRESSION (r222795): Nike app "Refused to set unsafe header" when adding and viewing cart
index 9cb9477..711c2d1 100644 (file)
@@ -590,7 +590,13 @@ void VideoFullscreenInterfaceAVKit::applicationDidBecomeActive()
     // If we are both in PiP and in Fullscreen (i.e., via auto-PiP), and we did not stop fullscreen upon returning, it must be
     // because the originating view is not visible, so hide the fullscreen window.
     if (m_currentMode.hasFullscreen() && m_currentMode.hasPictureInPicture()) {
-        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL, NSError *) {
+        [[m_playerViewController view] layoutIfNeeded];
+        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError* error) {
+            if (!success) {
+                WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+            }
+
             [m_window setHidden:YES];
             [[m_playerViewController view] setHidden:YES];
         }];
@@ -713,8 +719,15 @@ void VideoFullscreenInterfaceAVKit::enterFullscreenStandard()
         return;
     }
 
-    [m_playerViewController enterFullScreenAnimated:YES completionHandler:[this, protectedThis = makeRefPtr(this)] (BOOL succeeded, NSError*) {
-        UNUSED_PARAM(succeeded);
+    [[m_playerViewController view] layoutIfNeeded];
+    [m_playerViewController enterFullScreenAnimated:YES completionHandler:[this, protectedThis = makeRefPtr(this)] (BOOL succeeded, NSError* error) {
+        if (!succeeded) {
+            WTFLogAlways("-[AVPlayerViewController enterFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+            ASSERT_NOT_REACHED();
+            m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, YES);
+            return;
+        }
+
         LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::enterFullscreenStandard - lambda(%p) - succeeded(%s)", this, boolString(succeeded));
         [m_playerViewController setShowsPlaybackControls:YES];
 
@@ -742,20 +755,30 @@ void VideoFullscreenInterfaceAVKit::exitFullscreen(const IntRect& finalRect)
     WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
     if ([playerLayer videoGravity] != getAVLayerVideoGravityResizeAspect())
         [playerLayer setVideoGravity:getAVLayerVideoGravityResizeAspect()];
-    [[m_playerViewController view] layoutIfNeeded];
 
+    [[m_playerViewController view] layoutIfNeeded];
     if (m_currentMode.isPictureInPicture()) {
         m_shouldReturnToFullscreenWhenStoppingPiP = false;
         [m_window setHidden:NO];
         [m_playerViewController stopPictureInPicture];
     } else if (m_currentMode.hasPictureInPicture() && m_currentMode.hasFullscreen()) {
-        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL, NSError*) {
+        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError* error) {
+            if (!success) {
+                WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+            }
+
             clearMode(HTMLMediaElementEnums::VideoFullscreenModeStandard);
             [m_window setHidden:NO];
             [m_playerViewController stopPictureInPicture];
         }];
     } else if (m_currentMode.isFullscreen()) {
-        [m_playerViewController exitFullScreenAnimated:YES completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL, NSError*) mutable {
+        [m_playerViewController exitFullScreenAnimated:YES completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError* error) mutable {
+            if (!success) {
+                WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+            }
+
             m_exitCompleted = true;
 
             [CATransaction begin];
@@ -786,8 +809,15 @@ void VideoFullscreenInterfaceAVKit::cleanupFullscreen()
     
     if (m_currentMode.hasPictureInPicture())
         [m_playerViewController stopPictureInPicture];
-    if (m_currentMode.hasFullscreen())
-        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[] (BOOL, NSError *) { }];
+    if (m_currentMode.hasFullscreen()) {
+        [[m_playerViewController view] layoutIfNeeded];
+        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[] (BOOL success, NSError* error) {
+            if (!success) {
+                WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+            }
+        }];
+    }
     
     [[m_playerViewController view] removeFromSuperview];
     if (m_viewController)
@@ -872,7 +902,12 @@ void VideoFullscreenInterfaceAVKit::didStartPictureInPicture()
 
     if (m_currentMode.hasFullscreen()) {
         if (![m_playerViewController pictureInPictureWasStartedWhenEnteringBackground]) {
-            [m_playerViewController exitFullScreenAnimated:YES completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL, NSError *) {
+            [[m_playerViewController view] layoutIfNeeded];
+            [m_playerViewController exitFullScreenAnimated:YES completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError* error) {
+                if (!success) {
+                    WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                    ASSERT_NOT_REACHED();
+                }
                 [m_window setHidden:YES];
                 [[m_playerViewController view] setHidden:YES];
             }];
@@ -954,11 +989,18 @@ void VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletion
         [m_window setHidden:NO];
         [[m_playerViewController view] setHidden:NO];
 
-        [m_playerViewController enterFullScreenAnimated:YES completionHandler:^(BOOL success, NSError *error) {
-            UNUSED_PARAM(error);
+        [[m_playerViewController view] layoutIfNeeded];
+        [m_playerViewController enterFullScreenAnimated:YES completionHandler:^(BOOL succeeded, NSError *error) {
+            if (!succeeded) {
+                WTFLogAlways("-[AVPlayerViewController enterFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+                m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, YES);
+                return;
+            }
+
             m_restoringFullscreenForPictureInPictureStop = false;
             setMode(HTMLMediaElementEnums::VideoFullscreenModeStandard);
-            completionHandler(success);
+            completionHandler(succeeded);
             if (m_fullscreenChangeObserver)
                 m_fullscreenChangeObserver->didEnterFullscreen();
         }];
@@ -1006,6 +1048,7 @@ void VideoFullscreenInterfaceAVKit::applicationDidBecomeActive()
     // If we are both in PiP and in Fullscreen (i.e., via auto-PiP), and we did not stop fullscreen upon returning, it must be
     // because the originating view is not visible, so hide the fullscreen window.
     if (m_currentMode.hasFullscreen() && m_currentMode.hasPictureInPicture()) {
+        [[m_playerViewController view] layoutIfNeeded];
         [m_playerViewController exitFullScreenAnimated:NO completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError *error) {
             exitFullscreenHandler(success, error);
         }];
@@ -1066,8 +1109,15 @@ void VideoFullscreenInterfaceAVKit::cleanupFullscreen()
     
     if (m_currentMode.hasPictureInPicture())
         [m_playerViewController stopPictureInPicture];
-    if (m_currentMode.hasFullscreen())
-        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[] (BOOL, NSError *) { }];
+    if (m_currentMode.hasFullscreen()) {
+        [[m_playerViewController view] layoutIfNeeded];
+        [m_playerViewController exitFullScreenAnimated:NO completionHandler:[] (BOOL success, NSError* error) {
+            if (!success) {
+                WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+                ASSERT_NOT_REACHED();
+            }
+        }];
+    }
     
     [[m_playerViewController view] removeFromSuperview];
     if (m_viewController)
@@ -1153,6 +1203,7 @@ void VideoFullscreenInterfaceAVKit::didStartPictureInPicture()
 
     if (m_currentMode.hasFullscreen()) {
         if (![m_playerViewController pictureInPictureWasStartedWhenEnteringBackground]) {
+            [[m_playerViewController view] layoutIfNeeded];
             [m_playerViewController exitFullScreenAnimated:YES completionHandler:[protectedThis = makeRefPtr(this), this] (BOOL success, NSError *error) {
                 exitFullscreenHandler(success, error);
             }];
@@ -1235,6 +1286,7 @@ void VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletion
         [m_window setHidden:NO];
         [[m_playerViewController view] setHidden:NO];
 
+        [[m_playerViewController view] layoutIfNeeded];
         [m_playerViewController enterFullScreenAnimated:YES completionHandler:^(BOOL success, NSError *error) {
             enterFullscreenHandler(success, error);
             completionHandler(success);
@@ -1418,6 +1470,7 @@ void VideoFullscreenInterfaceAVKit::doEnterFullscreen()
 {
     m_standby = m_targetStandby;
 
+    [[m_playerViewController view] layoutIfNeeded];
     if (m_targetMode.hasFullscreen() && !m_currentMode.hasFullscreen()) {
         m_enterFullscreenNeedsEnterFullscreen = true;
         [m_playerViewController enterFullScreenAnimated:YES completionHandler:[this, protectedThis = makeRefPtr(this)] (BOOL success, NSError *error) {
@@ -1501,8 +1554,13 @@ void VideoFullscreenInterfaceAVKit::doExitFullscreen()
     });
 }
 
-void VideoFullscreenInterfaceAVKit::exitFullscreenHandler(BOOL success, NSError *)
+void VideoFullscreenInterfaceAVKit::exitFullscreenHandler(BOOL success, NSError* error)
 {
+    if (!success) {
+        WTFLogAlways("-[AVPlayerViewController exitFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+        ASSERT_NOT_REACHED();
+    }
+
     UNUSED_PARAM(success);
     LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::didExitFullscreen(%p) - %d", this, success);
 
@@ -1526,11 +1584,16 @@ void VideoFullscreenInterfaceAVKit::exitFullscreenHandler(BOOL success, NSError
         doExitFullscreen();
 }
 
-void VideoFullscreenInterfaceAVKit::enterFullscreenHandler(BOOL success, NSError *)
+void VideoFullscreenInterfaceAVKit::enterFullscreenHandler(BOOL success, NSError* error)
 {
-    UNUSED_PARAM(success);
-    LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::enterFullscreenStandard - lambda(%p) - success(%s)", this, boolString(success));
+    if (!succeeded) {
+        WTFLogAlways("-[AVPlayerViewController enterFullScreenAnimated:completionHandler:] failed with error %s", [[error localizedDescription] UTF8String]);
+        ASSERT_NOT_REACHED();
+        m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, YES);
+        return;
+    }
 
+    LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::enterFullscreenStandard - lambda(%p)", this);
     setMode(HTMLMediaElementEnums::VideoFullscreenModeStandard);
     [m_playerViewController setShowsPlaybackControls:YES];