Unreviewed, rolling out r236624 and r236671.
[WebKit-https.git] / Source / WebCore / platform / cocoa / VideoFullscreenModelVideoElement.mm
1 /*
2  * Copyright (C) 2014 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) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
29 #import "VideoFullscreenModelVideoElement.h"
30
31 #import "DOMWindow.h"
32 #import "History.h"
33 #import "Logging.h"
34 #import "MediaControlsHost.h"
35 #import "PlaybackSessionModelMediaElement.h"
36 #import <QuartzCore/CoreAnimation.h>
37 #import <WebCore/Event.h>
38 #import <WebCore/EventListener.h>
39 #import <WebCore/EventNames.h>
40 #import <WebCore/HTMLElement.h>
41 #import <WebCore/HTMLVideoElement.h>
42 #import <WebCore/Page.h>
43 #import <WebCore/TextTrackList.h>
44 #import <WebCore/TimeRanges.h>
45 #import <wtf/NeverDestroyed.h>
46 #import <wtf/SoftLinking.h>
47
48 namespace WebCore {
49
50 VideoFullscreenModelVideoElement::VideoFullscreenModelVideoElement()
51     : EventListener(EventListener::CPPEventListenerType)
52 {
53     LOG(Fullscreen, "VideoFullscreenModelVideoElement %p ctor", this);
54 }
55
56 VideoFullscreenModelVideoElement::~VideoFullscreenModelVideoElement()
57 {
58     LOG(Fullscreen, "VideoFullscreenModelVideoElement %p dtor", this);
59 }
60
61 void VideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoElement)
62 {
63     if (m_videoElement == videoElement)
64         return;
65
66     LOG(Fullscreen, "VideoFullscreenModelVideoElement %p setVideoElement(%p)", this, videoElement);
67
68     if (m_videoElement && m_videoElement->videoFullscreenLayer())
69         m_videoElement->setVideoFullscreenLayer(nullptr);
70
71     if (m_videoElement && m_isListening) {
72         for (auto& eventName : observedEventNames())
73             m_videoElement->removeEventListener(eventName, *this, false);
74     }
75     m_isListening = false;
76
77     m_videoElement = videoElement;
78
79     if (m_videoElement) {
80         for (auto& eventName : observedEventNames())
81             m_videoElement->addEventListener(eventName, *this, false);
82         m_isListening = true;
83     }
84
85     updateForEventName(eventNameAll());
86 }
87
88 void VideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event)
89 {
90     updateForEventName(event.type());
91 }
92
93 void VideoFullscreenModelVideoElement::updateForEventName(const WTF::AtomicString& eventName)
94 {
95     if (m_clients.isEmpty())
96         return;
97     
98     bool all = eventName == eventNameAll();
99
100     if (all
101         || eventName == eventNames().resizeEvent) {
102         setHasVideo(m_videoElement);
103         setVideoDimensions(m_videoElement ? FloatSize(m_videoElement->videoWidth(), m_videoElement->videoHeight()) : FloatSize());
104     }
105 }
106
107 void VideoFullscreenModelVideoElement::willExitFullscreen()
108 {
109     if (m_videoElement)
110         m_videoElement->willExitFullscreen();
111 }
112
113 void VideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer, WTF::Function<void()>&& completionHandler)
114 {
115     if (m_videoFullscreenLayer == videoLayer) {
116         completionHandler();
117         return;
118     }
119     
120     m_videoFullscreenLayer = videoLayer;
121 #if PLATFORM(MAC)
122     [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0, 0)];
123 #else
124     [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0.5, 0.5)];
125 #endif
126     [m_videoFullscreenLayer setBounds:m_videoFrame];
127     
128     if (!m_videoElement) {
129         completionHandler();
130         return;
131     }
132
133     m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get(), WTFMove(completionHandler));
134 }
135
136 void VideoFullscreenModelVideoElement::waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler)
137 {
138     if (!m_videoElement) {
139         completionHandler();
140         return;
141     }
142
143     m_videoElement->waitForPreparedForInlineThen(WTFMove(completionHandler));
144 }
145
146 void VideoFullscreenModelVideoElement::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode, bool finishedWithMedia)
147 {
148     if (m_videoElement && m_videoElement->fullscreenMode() != mode)
149         m_videoElement->setFullscreenMode(mode);
150
151     if (m_videoElement && finishedWithMedia && mode == MediaPlayerEnums::VideoFullscreenModeNone) {
152         if (m_videoElement->document().isMediaDocument()) {
153             if (DOMWindow* window = m_videoElement->document().domWindow()) {
154                 if (History* history = window->history())
155                     history->back();
156             }
157         }
158     }
159 }
160
161 void VideoFullscreenModelVideoElement::setVideoLayerFrame(FloatRect rect)
162 {
163     m_videoFrame = rect;
164     [m_videoFullscreenLayer setBounds:CGRect(rect)];
165     if (m_videoElement)
166         m_videoElement->setVideoFullscreenFrame(rect);
167 }
168
169 void VideoFullscreenModelVideoElement::setVideoLayerGravity(VideoFullscreenModel::VideoGravity gravity)
170 {
171     MediaPlayer::VideoGravity videoGravity = MediaPlayer::VideoGravityResizeAspect;
172     if (gravity == VideoFullscreenModel::VideoGravityResize)
173         videoGravity = MediaPlayer::VideoGravityResize;
174     else if (gravity == VideoFullscreenModel::VideoGravityResizeAspect)
175         videoGravity = MediaPlayer::VideoGravityResizeAspect;
176     else if (gravity == VideoFullscreenModel::VideoGravityResizeAspectFill)
177         videoGravity = MediaPlayer::VideoGravityResizeAspectFill;
178     else
179         ASSERT_NOT_REACHED();
180     
181     m_videoElement->setVideoFullscreenGravity(videoGravity);
182 }
183
184 const Vector<AtomicString>& VideoFullscreenModelVideoElement::observedEventNames()
185 {
186     static const auto names = makeNeverDestroyed(Vector<AtomicString> { eventNames().resizeEvent });
187     return names;
188 }
189
190 const AtomicString& VideoFullscreenModelVideoElement::eventNameAll()
191 {
192     static NeverDestroyed<AtomicString> sEventNameAll = "allEvents";
193     return sEventNameAll;
194 }
195
196 void VideoFullscreenModelVideoElement::fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode)
197 {
198     if (m_videoElement)
199         m_videoElement->fullscreenModeChanged(videoFullscreenMode);
200 }
201
202 void VideoFullscreenModelVideoElement::addClient(VideoFullscreenModelClient& client)
203 {
204     ASSERT(!m_clients.contains(&client));
205     m_clients.add(&client);
206 }
207
208 void VideoFullscreenModelVideoElement::removeClient(VideoFullscreenModelClient& client)
209 {
210     ASSERT(m_clients.contains(&client));
211     m_clients.remove(&client);
212 }
213
214 bool VideoFullscreenModelVideoElement::isVisible() const
215 {
216     if (!m_videoElement)
217         return false;
218
219     if (Page* page = m_videoElement->document().page())
220         return page->isVisible();
221
222     return false;
223 }
224
225 void VideoFullscreenModelVideoElement::setHasVideo(bool hasVideo)
226 {
227     if (hasVideo == m_hasVideo)
228         return;
229
230     m_hasVideo = hasVideo;
231
232     for (auto& client : m_clients)
233         client->hasVideoChanged(m_hasVideo);
234 }
235
236 void VideoFullscreenModelVideoElement::setVideoDimensions(const FloatSize& videoDimensions)
237 {
238     if (m_videoDimensions == videoDimensions)
239         return;
240
241     m_videoDimensions = videoDimensions;
242
243     for (auto& client : m_clients)
244         client->videoDimensionsChanged(m_videoDimensions);
245 }
246
247 void VideoFullscreenModelVideoElement::willEnterPictureInPicture()
248 {
249     for (auto& client : m_clients)
250         client->willEnterPictureInPicture();
251 }
252
253 void VideoFullscreenModelVideoElement::didEnterPictureInPicture()
254 {
255     for (auto& client : m_clients)
256         client->didEnterPictureInPicture();
257 }
258
259 void VideoFullscreenModelVideoElement::failedToEnterPictureInPicture()
260 {
261     for (auto& client : m_clients)
262         client->failedToEnterPictureInPicture();
263 }
264
265 void VideoFullscreenModelVideoElement::willExitPictureInPicture()
266 {
267     for (auto& client : m_clients)
268         client->willExitPictureInPicture();
269 }
270
271 void VideoFullscreenModelVideoElement::didExitPictureInPicture()
272 {
273     for (auto& client : m_clients)
274         client->didExitPictureInPicture();
275 }
276
277 } // namespace WebCore
278
279 #endif