Improve enter and exit fullscreen transition by using two step transition.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Jun 2014 23:33:16 +0000 (23:33 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Jun 2014 23:33:16 +0000 (23:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133706

Patch by Jeremy Jones <jeremyj@apple.com> on 2014-06-17
Reviewed by Simon Fraser.

Source/WebCore:
setupFullscreen, creates the fullscreen views ready to receive the video layer.
Once they are in place, didSetupFullscreen will move the video layer into the
new view hierarchy and initiate enterFullscreen to animate.

Reverse process for exit fullscreen.

* WebCore.exp.in: Add exports.
* platform/ios/WebVideoFullscreenControllerAVKit.mm:
(-[WebVideoFullscreenController enterFullscreen:]):
Refactor into didSetupFullscreen.
(-[WebVideoFullscreenController didSetupFullscreen]):
Move the video layer once fullscreen is ready to receive it.
(-[WebVideoFullscreenController didExitFullscreen]):
Move the video layer back into we the web page, and initiate cleanup.
(-[WebVideoFullscreenController didCleanupFullscreen]):
Refactord cleanup from didExitFullscreen.
* platform/ios/WebVideoFullscreenInterfaceAVKit.h: Add delcarations.
* platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
(WebVideoFullscreenInterfaceAVKit::setupFullscreen):
Refactored from enterFullscreen. Builds views ready to receive video layer.
(WebVideoFullscreenInterfaceAVKit::enterFullscreen):
Animates into fullscreen.
(WebVideoFullscreenInterfaceAVKit::exitFullscreen):
Animates from fullscreen. Cleanup is refactored into cleanupFullscreen()
(WebVideoFullscreenInterfaceAVKit::cleanupFullscreen):
Refactored from exitFullscreen(), removes views.

Source/WebKit2:
Add setupFullscreen()/didSetupFullscreen() and cleanupFullscreen()/didCleanupFullscreen()
to the proxies. And refactor enter/exit fullscreen to do some of the work in setup/cleanup.

* UIProcess/ios/WebVideoFullscreenManagerProxy.h:
Add four methods mentioned above.
* UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
Add Setup/Cleanup functions.
* UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID): does what enterFullscreen used to do.
(WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen): forward IPC.
(WebKit::WebVideoFullscreenManagerProxy::didSetupFullscreen): forward IPC.
(WebKit::WebVideoFullscreenManagerProxy::enterFullscreenWithID): changed to enterFullscreen
* WebProcess/ios/WebVideoFullscreenManager.h: Add didSetup/didCleanup
* WebProcess/ios/WebVideoFullscreenManager.messages.in: Add didSetup/didCleanup
* WebProcess/ios/WebVideoFullscreenManager.mm:
(WebKit::WebVideoFullscreenManager::enterFullscreenForNode): refactored,
some implementation moves to didSetupFullscreen.
(WebKit::WebVideoFullscreenManager::didSetupFullscreen):
Moves the video layer over to the hosted layer, and initiates fullscreen.
(WebKit::WebVideoFullscreenManager::didExitFullscreen): refactored,
some implementation moves to didCleanupFullscreen, and initiates cleanup.
(WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
Final cleanup refactored from didExitFullscreen()

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

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h
Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in
Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in
Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm

index 50bcd7e..8c7c799 100644 (file)
@@ -1,3 +1,37 @@
+2014-06-17  Jeremy Jones  <jeremyj@apple.com>
+
+        Improve enter and exit fullscreen transition by using two step transition.
+        https://bugs.webkit.org/show_bug.cgi?id=133706
+
+        Reviewed by Simon Fraser.
+
+        setupFullscreen, creates the fullscreen views ready to receive the video layer.
+        Once they are in place, didSetupFullscreen will move the video layer into the 
+        new view hierarchy and initiate enterFullscreen to animate.
+
+        Reverse process for exit fullscreen.
+
+        * WebCore.exp.in: Add exports.
+        * platform/ios/WebVideoFullscreenControllerAVKit.mm:
+        (-[WebVideoFullscreenController enterFullscreen:]):
+        Refactor into didSetupFullscreen.
+        (-[WebVideoFullscreenController didSetupFullscreen]):
+        Move the video layer once fullscreen is ready to receive it.
+        (-[WebVideoFullscreenController didExitFullscreen]):
+        Move the video layer back into we the web page, and initiate cleanup.
+        (-[WebVideoFullscreenController didCleanupFullscreen]):
+        Refactord cleanup from didExitFullscreen.
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.h: Add delcarations.
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
+        (WebVideoFullscreenInterfaceAVKit::setupFullscreen):
+        Refactored from enterFullscreen. Builds views ready to receive video layer.
+        (WebVideoFullscreenInterfaceAVKit::enterFullscreen):
+        Animates into fullscreen.
+        (WebVideoFullscreenInterfaceAVKit::exitFullscreen):
+        Animates from fullscreen. Cleanup is refactored into cleanupFullscreen()
+        (WebVideoFullscreenInterfaceAVKit::cleanupFullscreen):
+        Refactored from exitFullscreen(), removes views.
+
 2014-06-17  Sam Weinig  <sam@webkit.org>
 
         Remove unnecessary Structure flags from generated bindings
index c1fa0d3..fc2aec6 100644 (file)
@@ -3400,7 +3400,9 @@ __ZN7WebCore32WebVideoFullscreenInterfaceAVKit10invalidateEv
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit11setDurationEd
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit14exitFullscreenENS_7IntRectE
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit14setCurrentTimeEdd
-__ZN7WebCore32WebVideoFullscreenInterfaceAVKit15enterFullscreenER7CALayerNS_7IntRectE
+__ZN7WebCore32WebVideoFullscreenInterfaceAVKit15enterFullscreenEv
+__ZN7WebCore32WebVideoFullscreenInterfaceAVKit15setupFullscreenER7CALayerNS_7IntRectE
+__ZN7WebCore32WebVideoFullscreenInterfaceAVKit17cleanupFullscreenEv
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit17setSeekableRangesERKNS_10TimeRangesE
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit18setVideoDimensionsEbff
 __ZN7WebCore32WebVideoFullscreenInterfaceAVKit19setExternalPlaybackEbNS_27WebVideoFullscreenInterface26ExternalPlaybackTargetTypeEN3WTF6StringE
index 6a23f3a..de7a6a2 100644 (file)
@@ -63,16 +63,20 @@ using namespace WebCore;
 #else
 
 @interface WebVideoFullscreenController (FullscreenObservation)
+- (void)didSetupFullscreen;
 - (void)didEnterFullscreen;
 - (void)didExitFullscreen;
+- (void)didCleanupFullscreen;
 @end
 
 class WebVideoFullscreenControllerChangeObserver : public WebVideoFullscreenChangeObserver {
     WebVideoFullscreenController* _target;
 public:
     void setTarget(WebVideoFullscreenController* target) { _target = target; }
+    virtual void didSetupFullscreen() override { [_target didSetupFullscreen]; }
     virtual void didEnterFullscreen() override { [_target didEnterFullscreen]; }
     virtual void didExitFullscreen() override { [_target didExitFullscreen]; }
+    virtual void didCleanupFullscreen() override { [_target didCleanupFullscreen]; }
 };
 
 @implementation WebVideoFullscreenController
@@ -115,15 +119,14 @@ public:
     [self retain]; // Balanced by -release in didExitFullscreen:
     
     UNUSED_PARAM(screen);
-    _videoFullscreenLayer = [CALayer layer];
     _interface = adoptRef(new WebVideoFullscreenInterfaceAVKit);
     _interface->setWebVideoFullscreenChangeObserver(&_changeObserver);
     _model = adoptRef(new WebVideoFullscreenModelMediaElement);
     _model->setWebVideoFullscreenInterface(_interface.get());
     _interface->setWebVideoFullscreenModel(_model.get());
     _model->setMediaElement(_mediaElement.get());
-    _model->setVideoFullscreenLayer(_videoFullscreenLayer.get());
-    _interface->enterFullscreen(*_videoFullscreenLayer.get(), _mediaElement->screenRect());
+    _videoFullscreenLayer = [CALayer layer];
+    _interface->setupFullscreen(*_videoFullscreenLayer.get(), _mediaElement->screenRect());
 }
 
 - (void)exitFullscreen
@@ -137,6 +140,12 @@ public:
         _interface->requestHideAndExitFullscreen();
 }
 
+- (void)didSetupFullscreen
+{
+    _model->setVideoFullscreenLayer(_videoFullscreenLayer.get());
+    _interface->enterFullscreen();
+}
+
 - (void)didEnterFullscreen
 {
 }
@@ -144,9 +153,17 @@ public:
 - (void)didExitFullscreen
 {
     WebThreadRun(^{
+        _model->setVideoFullscreenLayer(nil);
+        _interface->cleanupFullscreen();
+    });
+}
+
+- (void)didCleanupFullscreen
+{
+    WebThreadRun(^{
         _interface->setWebVideoFullscreenModel(nullptr);
         _model->setWebVideoFullscreenInterface(nullptr);
-        _model->setVideoFullscreenLayer(nullptr);
+        _model->setVideoFullscreenLayer(nil);
         _model->setMediaElement(nullptr);
         _interface->setWebVideoFullscreenChangeObserver(nullptr);
         _model = nullptr;
index 09f55d9..10f3d07 100644 (file)
@@ -49,8 +49,10 @@ class WebVideoFullscreenModel;
 class WebVideoFullscreenChangeObserver {
 public:
     virtual ~WebVideoFullscreenChangeObserver() { };
+    virtual void didSetupFullscreen() = 0;
     virtual void didEnterFullscreen() = 0;
     virtual void didExitFullscreen() = 0;
+    virtual void didCleanupFullscreen() = 0;
 };
     
 class WebVideoFullscreenInterfaceAVKit
@@ -85,8 +87,10 @@ public:
     virtual void setLegibleMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex) override;
     virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, String localizedDeviceName) override;
 
-    virtual void enterFullscreen(PlatformLayer&, WebCore::IntRect initialRect);
+    virtual void setupFullscreen(PlatformLayer&, WebCore::IntRect initialRect);
+    virtual void enterFullscreen();
     virtual void exitFullscreen(WebCore::IntRect finalRect);
+    virtual void cleanupFullscreen();
     virtual void invalidate();
     virtual void requestHideAndExitFullscreen();
 };
index 409008e..775e239 100644 (file)
@@ -688,7 +688,7 @@ void WebVideoFullscreenInterfaceAVKit::setExternalPlayback(bool enabled, Externa
     [m_videoLayerContainer.get() setHidden:enabled];
 }
 
-void WebVideoFullscreenInterfaceAVKit::enterFullscreen(PlatformLayer& videoLayer, WebCore::IntRect initialRect)
+void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer, WebCore::IntRect initialRect)
 {
     __block RefPtr<WebVideoFullscreenInterfaceAVKit> protect(this);
     
@@ -710,6 +710,7 @@ void WebVideoFullscreenInterfaceAVKit::enterFullscreen(PlatformLayer& videoLayer
         [m_videoLayerContainer setVideoRect:videoRect];
 
         m_playerViewController = adoptNS([[classAVPlayerViewController alloc] initWithVideoLayer:m_videoLayerContainer.get()]);
+        [m_playerViewController setShowsPlaybackControls:NO];
         [m_playerViewController setPlayerController:(AVPlayerController *)playerController()];
         [m_playerViewController setDelegate:playerController()];
         [m_videoLayerContainer setPlayerViewController:m_playerViewController.get()];
@@ -727,46 +728,45 @@ void WebVideoFullscreenInterfaceAVKit::enterFullscreen(PlatformLayer& videoLayer
         [m_playerViewController didMoveToParentViewController:m_viewController.get()];
         [[m_playerViewController view] layoutIfNeeded];
 
-        __block RefPtr<WebVideoFullscreenInterfaceAVKit> protect2(this);
-
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [m_playerViewController enterFullScreenWithCompletionHandler:^(BOOL, NSError*){
-                if (m_fullscreenChangeObserver)
-                    m_fullscreenChangeObserver->didEnterFullscreen();
-                protect2.clear();
-            }];
-        });
-
         [CATransaction commit];
-
+        
+        if (m_fullscreenChangeObserver)
+            m_fullscreenChangeObserver->didSetupFullscreen();
+        
         protect.clear();
     });
 }
 
-void WebVideoFullscreenInterfaceAVKit::exitFullscreen(WebCore::IntRect finalRect)
+void WebVideoFullscreenInterfaceAVKit::enterFullscreen()
 {
     __block RefPtr<WebVideoFullscreenInterfaceAVKit> protect(this);
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [m_playerViewController enterFullScreenWithCompletionHandler:^(BOOL, NSError*)
+        {
+            [m_playerViewController setShowsPlaybackControls:YES];
+            if (m_fullscreenChangeObserver)
+                m_fullscreenChangeObserver->didEnterFullscreen();
+            protect.clear();
+        }];
+    });
+}
 
+void WebVideoFullscreenInterfaceAVKit::exitFullscreen(WebCore::IntRect finalRect)
+{
+    __block RefPtr<WebVideoFullscreenInterfaceAVKit> protect(this);
+    
     m_playerController.clear();
     
     dispatch_async(dispatch_get_main_queue(), ^{
+        [m_playerViewController setShowsPlaybackControls:NO];
         [m_playerViewController view].frame = finalRect;
         if ([m_videoLayerContainer videoLayerGravity] != AVVideoLayerGravityResizeAspect)
             [m_videoLayerContainer setVideoLayerGravity:AVVideoLayerGravityResizeAspect];
-        [m_playerViewController exitFullScreenWithCompletionHandler:^(BOOL, NSError*){
-            [m_window setHidden:YES];
-            [m_window setRootViewController:nil];
-            [m_playerViewController setDelegate:nil];
-            [m_playerViewController setPlayerController:nil];
-            m_playerViewController = nil;
-            m_viewController = nil;
-            m_window = nil;
-            [m_videoLayer removeFromSuperlayer];
-            m_videoLayer = nil;
-            [m_videoLayerContainer removeFromSuperlayer];
-            [m_videoLayerContainer setPlayerViewController:nil];
-            m_videoLayerContainer = nil;
-
+        [[m_playerViewController view] layoutIfNeeded];
+        [m_playerViewController exitFullScreenWithCompletionHandler:^(BOOL, NSError*)
+        {
+            [[m_playerViewController view] setBackgroundColor:[classUIColor clearColor]];
             if (m_fullscreenChangeObserver)
                 m_fullscreenChangeObserver->didExitFullscreen();
             protect.clear();
@@ -774,6 +774,30 @@ void WebVideoFullscreenInterfaceAVKit::exitFullscreen(WebCore::IntRect finalRect
     });
 }
 
+void WebVideoFullscreenInterfaceAVKit::cleanupFullscreen()
+{
+    __block RefPtr<WebVideoFullscreenInterfaceAVKit> protect(this);
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [m_window setHidden:YES];
+        [m_window setRootViewController:nil];
+        [m_playerViewController setDelegate:nil];
+        [m_playerViewController setPlayerController:nil];
+        m_playerViewController = nil;
+        m_viewController = nil;
+        m_window = nil;
+        [m_videoLayer removeFromSuperlayer];
+        m_videoLayer = nil;
+        [m_videoLayerContainer removeFromSuperlayer];
+        [m_videoLayerContainer setPlayerViewController:nil];
+        m_videoLayerContainer = nil;
+        
+        if (m_fullscreenChangeObserver)
+            m_fullscreenChangeObserver->didCleanupFullscreen();
+        protect.clear();
+    });
+}
+
 void WebVideoFullscreenInterfaceAVKit::invalidate()
 {
     m_playerController.clear();
index af4ad87..b4f33b6 100644 (file)
@@ -1,3 +1,34 @@
+2014-06-17  Jeremy Jones  <jeremyj@apple.com>
+
+        Improve enter and exit fullscreen transition by using two step transition.
+        https://bugs.webkit.org/show_bug.cgi?id=133706
+
+        Reviewed by Simon Fraser.
+
+        Add setupFullscreen()/didSetupFullscreen() and cleanupFullscreen()/didCleanupFullscreen()
+        to the proxies. And refactor enter/exit fullscreen to do some of the work in setup/cleanup.
+
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.h:
+        Add four methods mentioned above.
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
+        Add Setup/Cleanup functions.
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID): does what enterFullscreen used to do.
+        (WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen): forward IPC.
+        (WebKit::WebVideoFullscreenManagerProxy::didSetupFullscreen): forward IPC.
+        (WebKit::WebVideoFullscreenManagerProxy::enterFullscreenWithID): changed to enterFullscreen
+        * WebProcess/ios/WebVideoFullscreenManager.h: Add didSetup/didCleanup
+        * WebProcess/ios/WebVideoFullscreenManager.messages.in: Add didSetup/didCleanup
+        * WebProcess/ios/WebVideoFullscreenManager.mm: 
+        (WebKit::WebVideoFullscreenManager::enterFullscreenForNode): refactored,
+        some implementation moves to didSetupFullscreen.
+        (WebKit::WebVideoFullscreenManager::didSetupFullscreen):
+        Moves the video layer over to the hosted layer, and initiates fullscreen.
+        (WebKit::WebVideoFullscreenManager::didExitFullscreen): refactored,
+        some implementation moves to didCleanupFullscreen, and initiates cleanup.
+        (WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
+        Final cleanup refactored from didExitFullscreen()
+
 2014-06-17  Eric Carlson  <eric.carlson@apple.com>
 
         [iOS] enable background audio in WK2
index 6f873a0..dcf9a17 100644 (file)
@@ -55,13 +55,15 @@ private:
     virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override;
 
     // Translate to FullscreenInterface
-    void enterFullscreenWithID(uint32_t, WebCore::IntRect initialRect);
+    void setupFullscreenWithID(uint32_t, WebCore::IntRect initialRect);
     void setSeekableRangesVector(Vector<std::pair<double, double>>&);
     void setExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName);
     
     // Fullscreen Observer
-    virtual void didExitFullscreen() override;
+    virtual void didSetupFullscreen() override;
     virtual void didEnterFullscreen() override;
+    virtual void didExitFullscreen() override;
+    virtual void didCleanupFullscreen() override;
     
     // FullscreenModel
     virtual void play() override;
index 5801ff6..6afa481 100644 (file)
@@ -30,7 +30,9 @@ messages -> WebVideoFullscreenManagerProxy {
     SetExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName);
     SetDuration(double duration)
     SetRate(bool isPlaying, double rate)
-    EnterFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect)
+    SetupFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect)
+    EnterFullscreen()
     ExitFullscreen(WebCore::IntRect finalRect)
+    CleanupFullscreen()
 }
 #endif
index 1fb8f3f..7537248 100644 (file)
@@ -71,11 +71,11 @@ void WebVideoFullscreenManagerProxy::invalidate()
     m_layerHost.clear();
 }
 
-void WebVideoFullscreenManagerProxy::enterFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect)
+void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect)
 {
     ASSERT(videoLayerID);
     m_layerHost = WKMakeRenderLayer(videoLayerID);
-    enterFullscreen(*m_layerHost.get(), initialRect);
+    setupFullscreen(*m_layerHost.get(), initialRect);
 }
     
 void WebVideoFullscreenManagerProxy::setSeekableRangesVector(Vector<std::pair<double, double>>& ranges)
@@ -112,6 +112,16 @@ void WebVideoFullscreenManagerProxy::didExitFullscreen()
     [m_layerHost removeFromSuperlayer];
     m_layerHost.clear();
 }
+    
+void WebVideoFullscreenManagerProxy::didCleanupFullscreen()
+{
+    m_page->send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(), m_page->pageID());
+}
+
+void WebVideoFullscreenManagerProxy::didSetupFullscreen()
+{
+    m_page->send(Messages::WebVideoFullscreenManager::DidSetupFullscreen(), m_page->pageID());
+}
 
 void WebVideoFullscreenManagerProxy::didEnterFullscreen()
 {
index 349dd2f..ebc9db9 100644 (file)
@@ -76,8 +76,10 @@ protected:
     virtual void setExternalPlayback(bool enabled, WebVideoFullscreenInterface::ExternalPlaybackTargetType, String localizedDeviceName) override;
 
     // additional incoming
+    virtual void didSetupFullscreen();
     virtual void didEnterFullscreen();
     virtual void didExitFullscreen();
+    virtual void didCleanupFullscreen();
     virtual void setVideoLayerGravityEnum(unsigned);
     
     WebPage* m_page;
index a99bb1e..8b4d8ef 100644 (file)
@@ -33,8 +33,10 @@ messages -> WebVideoFullscreenManager {
     BeginScanningBackward()
     EndScanning()
     RequestExitFullscreen()
+    DidSetupFullscreen()
     DidExitFullscreen()
     DidEnterFullscreen()
+    DidCleanupFullscreen()
     SetVideoLayerFrame(WebCore::FloatRect bounds)
     SetVideoLayerGravityEnum(unsigned gravity)
     SelectAudioMediaOption(uint64_t index)
index 017973c..9872acc 100644 (file)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
-#include "config.h"
-#include "WebVideoFullscreenManager.h"
+#import "config.h"
+#import "WebVideoFullscreenManager.h"
 
 #if PLATFORM(IOS)
 
-#include "WebCoreArgumentCoders.h"
-#include "WebPage.h"
-#include "WebProcess.h"
-#include "WebVideoFullscreenManagerMessages.h"
-#include "WebVideoFullscreenManagerProxyMessages.h"
-#include <QuartzCore/CoreAnimation.h>
-#include <WebCore/Event.h>
-#include <WebCore/EventNames.h>
-#include <WebCore/FrameView.h>
-#include <WebCore/HTMLVideoElement.h>
-#include <WebCore/PlatformCALayer.h>
-#include <WebCore/RenderLayer.h>
-#include <WebCore/RenderLayerBacking.h>
-#include <WebCore/RenderView.h>
-#include <WebCore/Settings.h>
-#include <WebCore/TimeRanges.h>
-#include <WebCore/WebCoreThreadRun.h>
+#import "WebCoreArgumentCoders.h"
+#import "WebPage.h"
+#import "WebProcess.h"
+#import "WebVideoFullscreenManagerMessages.h"
+#import "WebVideoFullscreenManagerProxyMessages.h"
+#import <QuartzCore/CoreAnimation.h>
+#import <WebCore/Event.h>
+#import <WebCore/EventNames.h>
+#import <WebCore/FrameView.h>
+#import <WebCore/HTMLVideoElement.h>
+#import <WebCore/PlatformCALayer.h>
+#import <WebCore/RenderLayer.h>
+#import <WebCore/RenderLayerBacking.h>
+#import <WebCore/RenderView.h>
+#import <WebCore/Settings.h>
+#import <WebCore/TimeRanges.h>
+#import <WebCore/WebCoreThreadRun.h>
 
 using namespace WebCore;
 
@@ -94,15 +94,9 @@ void WebVideoFullscreenManager::enterFullscreenForNode(Node* node)
     m_isAnimating = true;
     setMediaElement(toHTMLMediaElement(node));
 
-    PlatformLayer* videoLayer = [CALayer layer];
-#ifndef NDEBUG
-    [videoLayer setName:@"Web video fullscreen manager layer"];
-#endif
     m_layerHostingContext = LayerHostingContext::createForExternalHostingProcess();
-    m_layerHostingContext->setRootLayer(videoLayer);
-    setVideoFullscreenLayer(videoLayer);
-
-    m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreenWithID(m_layerHostingContext->contextID(), screenRectForNode(node)), m_page->pageID());
+    
+    m_page->send(Messages::WebVideoFullscreenManagerProxy::SetupFullscreenWithID(m_layerHostingContext->contextID(), screenRectForNode(node)), m_page->pageID());
 }
 
 void WebVideoFullscreenManager::exitFullscreenForNode(Node* node)
@@ -165,7 +159,19 @@ void WebVideoFullscreenManager::setExternalPlayback(bool enabled, WebVideoFullsc
 {
     m_page->send(Messages::WebVideoFullscreenManagerProxy::SetExternalPlaybackProperties(enabled, static_cast<uint32_t>(targetType), localizedDeviceName), m_page->pageID());
 }
-
+    
+void WebVideoFullscreenManager::didSetupFullscreen()
+{
+    PlatformLayer* videoLayer = [CALayer layer];
+#ifndef NDEBUG
+    [videoLayer setName:@"Web video fullscreen manager layer"];
+#endif
+    
+    m_layerHostingContext->setRootLayer(videoLayer);
+    setVideoFullscreenLayer(videoLayer);
+    m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(), m_page->pageID());
+}
+    
 void WebVideoFullscreenManager::didEnterFullscreen()
 {
     m_isAnimating = false;
@@ -184,13 +190,22 @@ void WebVideoFullscreenManager::didEnterFullscreen()
 
 void WebVideoFullscreenManager::didExitFullscreen()
 {
+    setVideoFullscreenLayer(nil);
+    __block RefPtr<WebVideoFullscreenModelMediaElement> protect(this);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        m_layerHostingContext->setRootLayer(nullptr);
+        m_layerHostingContext = nullptr;
+        m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(), m_page->pageID());
+        protect.clear();
+    });
+}
+    
+void WebVideoFullscreenManager::didCleanupFullscreen()
+{
     m_isAnimating = false;
     m_isFullscreen = false;
-
-    m_layerHostingContext->setRootLayer(nullptr);
-    m_layerHostingContext = nullptr;
-    setVideoFullscreenLayer(nullptr);
-
+    
     setMediaElement(nullptr);
 
     if (!m_targetIsFullscreen)