b47dedafce6650a5889646daa14f4b62a376865c
[WebKit-https.git] / Source / WebCore / platform / ios / VideoFullscreenInterfaceAVKit.h
1 /*
2  * Copyright (C) 2014-2018 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
27 #pragma once
28
29 #if PLATFORM(IOS)
30
31 #include "EventListener.h"
32 #include "HTMLMediaElementEnums.h"
33 #include "PlatformLayer.h"
34 #include "PlaybackSessionInterfaceAVKit.h"
35 #include "VideoFullscreenModel.h"
36 #include <objc/objc.h>
37 #include <wtf/Forward.h>
38 #include <wtf/Function.h>
39 #include <wtf/RefCounted.h>
40 #include <wtf/RefPtr.h>
41 #include <wtf/RetainPtr.h>
42 #include <wtf/RunLoop.h>
43
44 OBJC_CLASS UIViewController;
45 OBJC_CLASS UIWindow;
46 OBJC_CLASS UIView;
47 OBJC_CLASS CALayer;
48 OBJC_CLASS WebAVPlayerController;
49 OBJC_CLASS WebAVPlayerLayerView;
50 OBJC_CLASS WebAVPlayerLayer;
51 OBJC_CLASS WebAVPlayerViewController;
52 OBJC_CLASS WebAVPlayerViewControllerDelegate;
53 OBJC_CLASS NSError;
54
55 namespace WebCore {
56 class IntRect;
57 class FloatSize;
58 class VideoFullscreenModel;
59 class VideoFullscreenChangeObserver;
60     
61 class WEBCORE_EXPORT VideoFullscreenInterfaceAVKit final
62     : public VideoFullscreenModelClient
63     , public PlaybackSessionModelClient
64     , public ThreadSafeRefCounted<VideoFullscreenInterfaceAVKit> {
65
66 public:
67     static Ref<VideoFullscreenInterfaceAVKit> create(PlaybackSessionInterfaceAVKit&);
68     virtual ~VideoFullscreenInterfaceAVKit();
69     WEBCORE_EXPORT void setVideoFullscreenModel(VideoFullscreenModel*);
70     WEBCORE_EXPORT void setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver*);
71     PlaybackSessionModel* playbackSessionModel() const { return m_playbackSessionInterface->playbackSessionModel(); }
72
73     // VideoFullscreenModelClient
74     WEBCORE_EXPORT void hasVideoChanged(bool) final;
75     WEBCORE_EXPORT void videoDimensionsChanged(const FloatSize&) final;
76
77     // PlaybackSessionModelClient
78     WEBCORE_EXPORT void externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType, const String& localizedDeviceName) final;
79
80     WEBCORE_EXPORT void setupFullscreen(UIView&, const IntRect& initialRect, UIView *, HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicturePlayback, bool standby);
81     WEBCORE_EXPORT void enterFullscreen();
82     WEBCORE_EXPORT void exitFullscreen(const IntRect& finalRect);
83     WEBCORE_EXPORT void cleanupFullscreen();
84     WEBCORE_EXPORT void invalidate();
85     WEBCORE_EXPORT void requestHideAndExitFullscreen();
86     WEBCORE_EXPORT void preparedToReturnToInline(bool visible, const IntRect& inlineRect);
87     WEBCORE_EXPORT void preparedToExitFullscreen();
88 #if ENABLE(FULLSCREEN_API)
89     WEBCORE_EXPORT void setHasVideoContentLayer(bool);
90     WEBCORE_EXPORT void setInlineRect(const IntRect&, bool visible);
91 #endif
92
93     enum class ExitFullScreenReason {
94         DoneButtonTapped,
95         FullScreenButtonTapped,
96         PinchGestureHandled,
97         RemoteControlStopEventReceived,
98         PictureInPictureStarted
99     };
100
101     class Mode {
102         HTMLMediaElementEnums::VideoFullscreenMode m_mode { HTMLMediaElementEnums::VideoFullscreenModeNone };
103
104     public:
105         Mode() = default;
106         Mode(const Mode&) = default;
107         Mode(HTMLMediaElementEnums::VideoFullscreenMode mode) : m_mode(mode) { }
108         void operator=(HTMLMediaElementEnums::VideoFullscreenMode mode) { m_mode = mode; }
109         HTMLMediaElementEnums::VideoFullscreenMode mode() const { return m_mode; }
110
111         void setModeValue(HTMLMediaElementEnums::VideoFullscreenMode mode, bool value) { value ? setMode(mode) : clearMode(mode); }
112         void setMode(HTMLMediaElementEnums::VideoFullscreenMode mode) { m_mode |= mode; }
113         void clearMode(HTMLMediaElementEnums::VideoFullscreenMode mode) { m_mode &= ~mode; }
114         bool hasMode(HTMLMediaElementEnums::VideoFullscreenMode mode) const { return m_mode & mode; }
115
116         bool isPictureInPicture() const { return m_mode == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture; }
117         bool isFullscreen() const { return m_mode == HTMLMediaElementEnums::VideoFullscreenModeStandard; }
118
119         void setPictureInPicture(bool value) { setModeValue(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture, value); }
120         void setFullscreen(bool value) { setModeValue(HTMLMediaElementEnums::VideoFullscreenModeStandard, value); }
121
122         bool hasFullscreen() const { return hasMode(HTMLMediaElementEnums::VideoFullscreenModeStandard); }
123         bool hasPictureInPicture() const { return hasMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture); }
124
125         bool hasVideo() const { return m_mode & (HTMLMediaElementEnums::VideoFullscreenModeStandard | HTMLMediaElementEnums::VideoFullscreenModePictureInPicture); }
126     };
127
128     Mode m_currentMode;
129 #if ENABLE(FULLSCREEN_API)
130     Mode m_targetMode;
131 #endif
132
133     VideoFullscreenModel* model() const { return m_videoFullscreenModel; }
134     bool shouldExitFullscreenWithReason(ExitFullScreenReason);
135     HTMLMediaElementEnums::VideoFullscreenMode mode() const { return m_currentMode.mode(); }
136     bool allowsPictureInPicturePlayback() const { return m_allowsPictureInPicturePlayback; }
137     WEBCORE_EXPORT bool mayAutomaticallyShowVideoPictureInPicture() const;
138     void fullscreenMayReturnToInline(WTF::Function<void(bool)>&& callback);
139     bool wirelessVideoPlaybackDisabled() const;
140     void applicationDidBecomeActive();
141
142     void willStartPictureInPicture();
143     void didStartPictureInPicture();
144     void failedToStartPictureInPicture();
145     void willStopPictureInPicture();
146     void didStopPictureInPicture();
147     void prepareForPictureInPictureStopWithCompletionHandler(void (^)(BOOL));
148 #if ENABLE(FULLSCREEN_API)
149     void exitFullscreenHandler(BOOL success, NSError *);
150     void enterFullscreenHandler(BOOL success, NSError *);
151 #endif
152     bool isPlayingVideoInEnhancedFullscreen() const;
153
154     void setMode(HTMLMediaElementEnums::VideoFullscreenMode);
155     void clearMode(HTMLMediaElementEnums::VideoFullscreenMode);
156     bool hasMode(HTMLMediaElementEnums::VideoFullscreenMode mode) const { return m_currentMode.hasMode(mode); }
157
158 #if PLATFORM(IOS)
159     UIViewController *presentingViewController();
160     UIViewController *fullscreenViewController() const { return m_viewController.get(); }
161     WebAVPlayerLayerView* playerLayerView() const { return m_playerLayerView.get(); }
162 #endif
163
164 protected:
165     WEBCORE_EXPORT VideoFullscreenInterfaceAVKit(PlaybackSessionInterfaceAVKit&);
166
167 #if ENABLE(FULLSCREEN_API)
168     void doSetup();
169     void finalizeSetup();
170     void doExitFullscreen();
171     void returnToStandby();
172 #else
173     void enterPictureInPicture();
174     void enterFullscreenStandard();
175 #endif
176     void doEnterFullscreen();
177     void watchdogTimerFired();
178     WebAVPlayerController *playerController() const;
179
180     Ref<PlaybackSessionInterfaceAVKit> m_playbackSessionInterface;
181     RetainPtr<WebAVPlayerViewControllerDelegate> m_playerViewControllerDelegate;
182     RetainPtr<WebAVPlayerViewController> m_playerViewController;
183     VideoFullscreenModel* m_videoFullscreenModel { nullptr };
184     VideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr };
185
186     // These are only used when fullscreen is presented in a separate window.
187     RetainPtr<UIWindow> m_window;
188     RetainPtr<UIViewController> m_viewController;
189     RetainPtr<UIView> m_videoView;
190     RetainPtr<UIView> m_parentView;
191     RetainPtr<UIWindow> m_parentWindow;
192     RetainPtr<WebAVPlayerLayerView> m_playerLayerView;
193     WTF::Function<void(bool)> m_prepareToInlineCallback;
194     RunLoop::Timer<VideoFullscreenInterfaceAVKit> m_watchdogTimer;
195     FloatRect m_inlineRect;
196     bool m_allowsPictureInPicturePlayback { false };
197     bool m_wirelessVideoPlaybackDisabled { true };
198     bool m_shouldReturnToFullscreenWhenStoppingPiP { false };
199     bool m_restoringFullscreenForPictureInPictureStop { false };
200
201 #if ENABLE(FULLSCREEN_API)
202     bool m_setupNeedsInlineRect { false };
203     bool m_exitFullscreenNeedInlineRect { false };
204
205     bool m_finalizeSetupNeedsVideoContentLayer { false };
206     bool m_cleanupNeedsReturnVideoContentLayer { false };
207
208     bool m_returnToStandbyNeedsReturnVideoContentLayer { false };
209     bool m_finalizeSetupNeedsReturnVideoContentLayer { false };
210
211     bool m_exitFullscreenNeedsExitFullscreen { false };
212     bool m_exitFullscreenNeedsExitPictureInPicture { false };
213     bool m_exitFullscreenNeedsReturnContentLayer { false };
214
215     bool m_enterFullscreenNeedsEnterFullscreen { false };
216     bool m_enterFullscreenNeedsExitFullscreen { false };
217     bool m_enterFullscreenNeedsEnterPictureInPicture { false };
218     bool m_enterFullscreenNeedsExitPictureInPicture { false };
219
220     bool m_hasVideoContentLayer { false };
221
222     bool m_hasUpdatedInlineRect { false };
223     bool m_inlineIsVisible { false };
224     bool m_standby { false };
225     bool m_targetStandby { false };
226 #else
227     bool m_exitRequested { false };
228     bool m_exitCompleted { false };
229     bool m_enterRequested { false };
230     bool m_shouldReturnToFullscreenAfterEnteringForeground { false };
231     bool m_waitingForPreparedToExit { false };
232 #endif
233 };
234
235 }
236
237 #endif // PLATFORM(IOS)
238