| /* |
| * Copyright (C) 2014 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "config.h" |
| #import "VideoFullscreenModelVideoElement.h" |
| |
| #if ENABLE(VIDEO_PRESENTATION_MODE) |
| |
| #import "AddEventListenerOptions.h" |
| #import "DOMWindow.h" |
| #import "Event.h" |
| #import "EventListener.h" |
| #import "EventNames.h" |
| #import "HTMLElement.h" |
| #import "HTMLVideoElement.h" |
| #import "History.h" |
| #import "Logging.h" |
| #import "MediaControlsHost.h" |
| #import "Page.h" |
| #import "PlaybackSessionModelMediaElement.h" |
| #import "TextTrackList.h" |
| #import "TimeRanges.h" |
| #import <QuartzCore/CoreAnimation.h> |
| #import <wtf/NeverDestroyed.h> |
| #import <wtf/SoftLinking.h> |
| |
| namespace WebCore { |
| |
| VideoFullscreenModelVideoElement::VideoFullscreenModelVideoElement() |
| : EventListener(EventListener::CPPEventListenerType) |
| { |
| LOG(Fullscreen, "VideoFullscreenModelVideoElement %p ctor", this); |
| } |
| |
| VideoFullscreenModelVideoElement::~VideoFullscreenModelVideoElement() |
| { |
| LOG(Fullscreen, "VideoFullscreenModelVideoElement %p dtor", this); |
| } |
| |
| void VideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoElement) |
| { |
| if (m_videoElement == videoElement) |
| return; |
| |
| LOG(Fullscreen, "VideoFullscreenModelVideoElement %p setVideoElement(%p)", this, videoElement); |
| |
| if (m_videoElement && m_videoElement->videoFullscreenLayer()) |
| m_videoElement->setVideoFullscreenLayer(nullptr); |
| |
| if (m_videoElement && m_isListening) { |
| for (auto& eventName : observedEventNames()) |
| m_videoElement->removeEventListener(eventName, *this, false); |
| } |
| m_isListening = false; |
| |
| m_videoElement = videoElement; |
| |
| if (m_videoElement) { |
| for (auto& eventName : observedEventNames()) |
| m_videoElement->addEventListener(eventName, *this, false); |
| m_isListening = true; |
| } |
| |
| updateForEventName(eventNameAll()); |
| } |
| |
| void VideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event) |
| { |
| updateForEventName(event.type()); |
| } |
| |
| void VideoFullscreenModelVideoElement::updateForEventName(const WTF::AtomString& eventName) |
| { |
| if (m_clients.isEmpty()) |
| return; |
| |
| bool all = eventName == eventNameAll(); |
| |
| if (all |
| || eventName == eventNames().resizeEvent) { |
| setHasVideo(m_videoElement); |
| setVideoDimensions(m_videoElement ? FloatSize(m_videoElement->videoWidth(), m_videoElement->videoHeight()) : FloatSize()); |
| } |
| } |
| |
| void VideoFullscreenModelVideoElement::willExitFullscreen() |
| { |
| if (m_videoElement) |
| m_videoElement->willExitFullscreen(); |
| } |
| |
| RetainPtr<PlatformLayer> VideoFullscreenModelVideoElement::createVideoFullscreenLayer() |
| { |
| if (m_videoElement) |
| return m_videoElement->createVideoFullscreenLayer(); |
| return nullptr; |
| } |
| |
| void VideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer, WTF::Function<void()>&& completionHandler) |
| { |
| if (m_videoFullscreenLayer == videoLayer) { |
| completionHandler(); |
| return; |
| } |
| |
| m_videoFullscreenLayer = videoLayer; |
| #if PLATFORM(MAC) |
| [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0, 0)]; |
| #else |
| [m_videoFullscreenLayer setAnchorPoint:CGPointMake(0.5, 0.5)]; |
| #endif |
| [m_videoFullscreenLayer setBounds:m_videoFrame]; |
| |
| if (!m_videoElement) { |
| completionHandler(); |
| return; |
| } |
| |
| m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get(), WTFMove(completionHandler)); |
| } |
| |
| void VideoFullscreenModelVideoElement::waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler) |
| { |
| if (!m_videoElement) { |
| completionHandler(); |
| return; |
| } |
| |
| m_videoElement->waitForPreparedForInlineThen(WTFMove(completionHandler)); |
| } |
| |
| void VideoFullscreenModelVideoElement::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode, bool finishedWithMedia) |
| { |
| if (m_videoElement) |
| m_videoElement->setPresentationMode(HTMLVideoElement::toPresentationMode(mode)); |
| |
| if (m_videoElement && finishedWithMedia && mode == MediaPlayer::VideoFullscreenModeNone) { |
| if (m_videoElement->document().isMediaDocument()) { |
| if (auto* window = m_videoElement->document().domWindow()) |
| window->history().back(); |
| } |
| } |
| } |
| |
| void VideoFullscreenModelVideoElement::setVideoLayerFrame(FloatRect rect) |
| { |
| m_videoFrame = rect; |
| [m_videoFullscreenLayer setBounds:CGRect(rect)]; |
| if (m_videoElement) |
| m_videoElement->setVideoFullscreenFrame(rect); |
| } |
| |
| void VideoFullscreenModelVideoElement::setVideoLayerGravity(MediaPlayer::VideoGravity gravity) |
| { |
| if (m_videoElement) |
| m_videoElement->setVideoFullscreenGravity(gravity); |
| } |
| |
| const Vector<AtomString>& VideoFullscreenModelVideoElement::observedEventNames() |
| { |
| static const auto names = makeNeverDestroyed(Vector<AtomString> { eventNames().resizeEvent }); |
| return names; |
| } |
| |
| const AtomString& VideoFullscreenModelVideoElement::eventNameAll() |
| { |
| static MainThreadNeverDestroyed<const AtomString> sEventNameAll = "allEvents"; |
| return sEventNameAll; |
| } |
| |
| void VideoFullscreenModelVideoElement::fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode) |
| { |
| if (m_videoElement) { |
| UserGestureIndicator gestureIndicator(ProcessingUserGesture, &m_videoElement->document()); |
| m_videoElement->setPresentationMode(HTMLVideoElement::toPresentationMode(videoFullscreenMode)); |
| } |
| } |
| |
| void VideoFullscreenModelVideoElement::requestRouteSharingPolicyAndContextUID(CompletionHandler<void(RouteSharingPolicy, String)>&& completionHandler) |
| { |
| auto& session = AudioSession::sharedSession(); |
| completionHandler(session.routeSharingPolicy(), session.routingContextUID()); |
| } |
| |
| void VideoFullscreenModelVideoElement::addClient(VideoFullscreenModelClient& client) |
| { |
| ASSERT(!m_clients.contains(&client)); |
| m_clients.add(&client); |
| } |
| |
| void VideoFullscreenModelVideoElement::removeClient(VideoFullscreenModelClient& client) |
| { |
| ASSERT(m_clients.contains(&client)); |
| m_clients.remove(&client); |
| } |
| |
| void VideoFullscreenModelVideoElement::setHasVideo(bool hasVideo) |
| { |
| if (hasVideo == m_hasVideo) |
| return; |
| |
| m_hasVideo = hasVideo; |
| |
| for (auto& client : copyToVector(m_clients)) |
| client->hasVideoChanged(m_hasVideo); |
| } |
| |
| void VideoFullscreenModelVideoElement::setVideoDimensions(const FloatSize& videoDimensions) |
| { |
| if (m_videoDimensions == videoDimensions) |
| return; |
| |
| m_videoDimensions = videoDimensions; |
| |
| for (auto& client : copyToVector(m_clients)) |
| client->videoDimensionsChanged(m_videoDimensions); |
| } |
| |
| void VideoFullscreenModelVideoElement::willEnterPictureInPicture() |
| { |
| for (auto& client : copyToVector(m_clients)) |
| client->willEnterPictureInPicture(); |
| } |
| |
| void VideoFullscreenModelVideoElement::didEnterPictureInPicture() |
| { |
| for (auto& client : copyToVector(m_clients)) |
| client->didEnterPictureInPicture(); |
| } |
| |
| void VideoFullscreenModelVideoElement::failedToEnterPictureInPicture() |
| { |
| for (auto& client : copyToVector(m_clients)) |
| client->failedToEnterPictureInPicture(); |
| } |
| |
| void VideoFullscreenModelVideoElement::willExitPictureInPicture() |
| { |
| for (auto& client : copyToVector(m_clients)) |
| client->willExitPictureInPicture(); |
| } |
| |
| void VideoFullscreenModelVideoElement::didExitPictureInPicture() |
| { |
| for (auto& client : copyToVector(m_clients)) |
| client->didExitPictureInPicture(); |
| } |
| |
| } // namespace WebCore |
| |
| #endif |