[iOS] When simultaneously exiting-and-entering fullscreen, WebVideoFullscreenManager...
[WebKit-https.git] / Source / WebCore / platform / ios / WebVideoFullscreenControllerAVKit.mm
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27
28 #if PLATFORM(IOS)
29
30 #import "WebVideoFullscreenControllerAVKit.h"
31
32 #import "Logging.h"
33 #import "WebVideoFullscreenInterfaceAVKit.h"
34 #import "WebVideoFullscreenModelVideoElement.h"
35 #import <QuartzCore/CoreAnimation.h>
36 #import <WebCore/WebCoreThreadRun.h>
37
38 using namespace WebCore;
39
40 #if __IPHONE_OS_VERSION_MIN_REQUIRED <= 80200 || !HAVE(AVKIT)
41
42 @implementation WebVideoFullscreenController
43 - (void)setVideoElement:(WebCore::HTMLVideoElement*)videoElement
44 {
45     UNUSED_PARAM(videoElement);
46 }
47
48 - (WebCore::HTMLVideoElement*)videoElement
49 {
50     return nullptr;
51 }
52
53 - (void)enterFullscreen:(UIView *)view mode:(WebCore::HTMLMediaElement::VideoFullscreenMode)mode
54 {
55     UNUSED_PARAM(view);
56     UNUSED_PARAM(mode);
57 }
58
59 - (void)requestHideAndExitFullscreen
60 {
61 }
62
63 - (void)exitFullscreen
64 {
65 }
66 @end
67
68 #else
69
70 @interface WebVideoFullscreenController (FullscreenObservation)
71 - (void)didSetupFullscreen;
72 - (void)didEnterFullscreen;
73 - (void)didExitFullscreen;
74 - (void)didCleanupFullscreen;
75 - (void)fullscreenMayReturnToInline;
76 @end
77
78 class WebVideoFullscreenControllerChangeObserver : public WebVideoFullscreenChangeObserver {
79     WebVideoFullscreenController* _target;
80 public:
81     void setTarget(WebVideoFullscreenController* target) { _target = target; }
82     virtual void didSetupFullscreen() override { [_target didSetupFullscreen]; }
83     virtual void didEnterFullscreen() override { [_target didEnterFullscreen]; }
84     virtual void didExitFullscreen() override { [_target didExitFullscreen]; }
85     virtual void didCleanupFullscreen() override { [_target didCleanupFullscreen]; }
86     virtual void fullscreenMayReturnToInline() override { [_target fullscreenMayReturnToInline]; }
87 };
88
89 @implementation WebVideoFullscreenController
90 {
91     RefPtr<HTMLVideoElement> _videoElement;
92     RefPtr<WebVideoFullscreenInterfaceAVKit> _interface;
93     RefPtr<WebVideoFullscreenModelVideoElement> _model;
94     WebVideoFullscreenControllerChangeObserver _changeObserver;
95     RetainPtr<PlatformLayer> _videoFullscreenLayer;
96 }
97
98 - (instancetype)init
99 {
100     if (!(self = [super init]))
101         return nil;
102     
103     _changeObserver.setTarget(self);
104
105     return self;
106 }
107
108 - (void)dealloc
109 {
110     _videoElement = nullptr;
111     [super dealloc];
112 }
113
114 - (void)setVideoElement:(HTMLVideoElement*)videoElement
115 {
116     _videoElement = videoElement;
117 }
118
119 - (HTMLVideoElement*)videoElement
120 {
121     return _videoElement.get();
122 }
123
124 - (void)enterFullscreen:(UIView *)view mode:(HTMLMediaElement::VideoFullscreenMode)mode
125 {
126     [self retain]; // Balanced by -release in didExitFullscreen:
127     
128     _interface = WebVideoFullscreenInterfaceAVKit::create();
129     _interface->setWebVideoFullscreenChangeObserver(&_changeObserver);
130     _model = WebVideoFullscreenModelVideoElement::create();
131     _model->setWebVideoFullscreenInterface(_interface.get());
132     _interface->setWebVideoFullscreenModel(_model.get());
133     _model->setVideoElement(_videoElement.get());
134     _videoFullscreenLayer = [CALayer layer];
135     _interface->setupFullscreen(*_videoFullscreenLayer.get(), _videoElement->clientRect(), view, mode, _videoElement->mediaSession().allowsAlternateFullscreen(*_videoElement.get()));
136 }
137
138 - (void)exitFullscreen
139 {
140     _interface->exitFullscreen(_videoElement->screenRect());
141 }
142
143 - (void)requestHideAndExitFullscreen
144 {
145     if (_interface)
146         _interface->requestHideAndExitFullscreen();
147 }
148
149 - (void)didSetupFullscreen
150 {
151     WebThreadRun(^{
152         _model->setVideoFullscreenLayer(_videoFullscreenLayer.get());
153         _interface->enterFullscreen();
154     });
155 }
156
157 - (void)didEnterFullscreen
158 {
159 }
160
161 - (void)didExitFullscreen
162 {
163     WebThreadRun(^{
164         _model->setVideoFullscreenLayer(nil);
165         _interface->cleanupFullscreen();
166     });
167 }
168
169 - (void)didCleanupFullscreen
170 {
171     WebThreadRun(^{
172         _model->setVideoFullscreenLayer(nil);
173         _interface->setWebVideoFullscreenModel(nullptr);
174         _model->setWebVideoFullscreenInterface(nullptr);
175         _model->setVideoElement(nullptr);
176         _interface->setWebVideoFullscreenChangeObserver(nullptr);
177         _model = nullptr;
178         _interface = nullptr;
179         
180         [self release]; // Balance the -retain we did in enterFullscreen:
181     });
182 }
183
184 - (void)fullscreenMayReturnToInline
185 {
186     _interface->preparedToReturnToInline(true, _videoElement->clientRect());
187 }
188
189 @end
190
191 #endif // __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
192
193 #endif // PLATFORM(IOS)