2 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 #import "WebVideoFullscreenManager.h"
30 #import "Attachment.h"
31 #import "WebCoreArgumentCoders.h"
33 #import "WebProcess.h"
34 #import "WebVideoFullscreenManagerMessages.h"
35 #import "WebVideoFullscreenManagerProxyMessages.h"
36 #import <QuartzCore/CoreAnimation.h>
37 #import <WebCore/Color.h>
38 #import <WebCore/Event.h>
39 #import <WebCore/EventNames.h>
40 #import <WebCore/FrameView.h>
41 #import <WebCore/HTMLVideoElement.h>
42 #import <WebCore/PlatformCALayer.h>
43 #import <WebCore/RenderLayer.h>
44 #import <WebCore/RenderLayerBacking.h>
45 #import <WebCore/RenderView.h>
46 #import <WebCore/Settings.h>
47 #import <WebCore/TimeRanges.h>
48 #import <WebCore/WebCoreThreadRun.h>
49 #import <mach/mach_port.h>
51 using namespace WebCore;
55 static IntRect clientRectForElement(HTMLElement* element)
60 return element->clientRect();
63 PassRefPtr<WebVideoFullscreenManager> WebVideoFullscreenManager::create(PassRefPtr<WebPage> page)
65 return adoptRef(new WebVideoFullscreenManager(page));
68 WebVideoFullscreenManager::WebVideoFullscreenManager(PassRefPtr<WebPage> page)
70 , m_isAnimating(false)
71 , m_targetIsFullscreen(false)
72 , m_fullscreenMode(HTMLMediaElement::VideoFullscreenModeNone)
73 , m_isFullscreen(false)
75 setWebVideoFullscreenInterface(this);
76 WebProcess::singleton().addMessageReceiver(Messages::WebVideoFullscreenManager::messageReceiverName(), page->pageID(), *this);
79 WebVideoFullscreenManager::~WebVideoFullscreenManager()
81 WebProcess::singleton().removeMessageReceiver(Messages::WebVideoFullscreenManager::messageReceiverName(), m_page->pageID());
84 bool WebVideoFullscreenManager::supportsVideoFullscreen() const
86 return Settings::avKitEnabled();
89 void WebVideoFullscreenManager::enterVideoFullscreenForVideoElement(HTMLVideoElement* videoElement, HTMLMediaElement::VideoFullscreenMode mode)
91 ASSERT(mode != HTMLMediaElement::VideoFullscreenModeNone);
93 m_videoElement = videoElement;
95 m_targetIsFullscreen = true;
96 m_fullscreenMode = mode;
101 m_isAnimating = true;
102 setVideoElement(videoElement);
104 m_layerHostingContext = LayerHostingContext::createForExternalHostingProcess();
105 bool allowOptimizedFullscreen = m_videoElement->mediaSession().allowsAlternateFullscreen(*m_videoElement.get());
107 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetupFullscreenWithID(m_layerHostingContext->contextID(), clientRectForElement(videoElement), m_page->deviceScaleFactor(), m_fullscreenMode, allowOptimizedFullscreen), m_page->pageID());
110 void WebVideoFullscreenManager::exitVideoFullscreen()
112 RefPtr<HTMLVideoElement> videoElement = m_videoElement.release();
113 m_targetIsFullscreen = false;
118 m_isAnimating = true;
119 m_page->send(Messages::WebVideoFullscreenManagerProxy::ExitFullscreen(clientRectForElement(videoElement.get())), m_page->pageID());
122 void WebVideoFullscreenManager::resetMediaState()
124 m_page->send(Messages::WebVideoFullscreenManagerProxy::ResetMediaState(), m_page->pageID());
127 void WebVideoFullscreenManager::setDuration(double duration)
129 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetDuration(duration), m_page->pageID());
132 void WebVideoFullscreenManager::setCurrentTime(double currentTime, double anchorTime)
134 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetCurrentTime(currentTime, anchorTime), m_page->pageID());
137 void WebVideoFullscreenManager::setRate(bool isPlaying, float playbackRate)
139 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetRate(isPlaying, playbackRate), m_page->pageID());
142 void WebVideoFullscreenManager::setVideoDimensions(bool hasVideo, float width, float height)
144 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetVideoDimensions(hasVideo, width, height), m_page->pageID());
147 void WebVideoFullscreenManager::setSeekableRanges(const WebCore::TimeRanges& timeRanges)
149 Vector<std::pair<double, double>> rangesVector;
151 for (unsigned i = 0; i < timeRanges.length(); i++) {
152 ExceptionCode exceptionCode;
153 double start = timeRanges.start(i, exceptionCode);
154 double end = timeRanges.end(i, exceptionCode);
155 rangesVector.append(std::pair<double,double>(start, end));
158 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetSeekableRangesVector(WTF::move(rangesVector)), m_page->pageID());
161 void WebVideoFullscreenManager::setCanPlayFastReverse(bool value)
163 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetCanPlayFastReverse(value), m_page->pageID());
166 void WebVideoFullscreenManager::setAudioMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex)
168 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetAudioMediaSelectionOptions(options, selectedIndex), m_page->pageID());
171 void WebVideoFullscreenManager::setLegibleMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex)
173 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetLegibleMediaSelectionOptions(options, selectedIndex), m_page->pageID());
176 void WebVideoFullscreenManager::setExternalPlayback(bool enabled, WebVideoFullscreenInterface::ExternalPlaybackTargetType targetType, String localizedDeviceName)
178 m_page->send(Messages::WebVideoFullscreenManagerProxy::SetExternalPlaybackProperties(enabled, static_cast<uint32_t>(targetType), localizedDeviceName), m_page->pageID());
181 void WebVideoFullscreenManager::didSetupFullscreen()
183 PlatformLayer* videoLayer = [CALayer layer];
185 [videoLayer setName:@"Web video fullscreen manager layer"];
188 [CATransaction begin];
189 [CATransaction setDisableActions:YES];
191 [videoLayer setPosition:CGPointMake(0, 0)];
192 [videoLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent, WebCore::ColorSpaceDeviceRGB)];
194 // Set a scale factor here to make convertRect:toLayer:nil take scale factor into account. <rdar://problem/18316542>.
195 // This scale factor is inverted in the hosting process.
196 float hostingScaleFactor = m_page->deviceScaleFactor();
197 [videoLayer setTransform:CATransform3DMakeScale(hostingScaleFactor, hostingScaleFactor, 1)];
198 m_layerHostingContext->setRootLayer(videoLayer);
200 setVideoFullscreenLayer(videoLayer);
201 [CATransaction commit];
203 m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(), m_page->pageID());
206 void WebVideoFullscreenManager::didEnterFullscreen()
208 m_isAnimating = false;
209 m_isFullscreen = false;
211 if (m_targetIsFullscreen)
214 // exit fullscreen now if it was previously requested during an animation.
215 __block RefPtr<WebVideoFullscreenModelVideoElement> protect(this);
217 exitVideoFullscreen();
222 void WebVideoFullscreenManager::didExitFullscreen()
224 setVideoFullscreenLayer(nil);
225 __block RefPtr<WebVideoFullscreenModelVideoElement> protect(this);
227 dispatch_async(dispatch_get_main_queue(), ^{
228 if (m_layerHostingContext) {
229 m_layerHostingContext->setRootLayer(nullptr);
230 m_layerHostingContext = nullptr;
233 m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(), m_page->pageID());
238 void WebVideoFullscreenManager::didCleanupFullscreen()
240 m_isAnimating = false;
241 m_isFullscreen = false;
243 setVideoElement(nullptr);
245 if (!m_targetIsFullscreen)
248 // enter fullscreen now if it was previously requested during an animation.
249 __block RefPtr<WebVideoFullscreenModelVideoElement> protect(this);
251 enterVideoFullscreenForVideoElement(m_videoElement.get(), m_fullscreenMode);
256 void WebVideoFullscreenManager::setVideoLayerGravityEnum(unsigned gravity)
258 setVideoLayerGravity((WebVideoFullscreenModel::VideoGravity)gravity);
261 void WebVideoFullscreenManager::fullscreenMayReturnToInline(bool isPageVisible)
264 m_videoElement->scrollIntoViewIfNotVisible(false);
265 m_page->send(Messages::WebVideoFullscreenManagerProxy::PreparedToReturnToInline(true, clientRectForElement(m_videoElement.get())), m_page->pageID());
268 void WebVideoFullscreenManager::setVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort)
270 if (m_layerHostingContext)
271 m_layerHostingContext->setFencePort(fencePort.port());
272 setVideoLayerFrame(bounds);
273 mach_port_deallocate(mach_task_self(), fencePort.port());
276 } // namespace WebKit
278 #endif // PLATFORM(IOS)