| /* |
| * Copyright (C) 2013 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" |
| |
| #if PLATFORM(IOS) |
| |
| #import "WebVideoFullscreenControllerAVKit.h" |
| |
| #import "Logging.h" |
| #import "QuartzCoreSPI.h" |
| #import "SoftLinking.h" |
| #import "TimeRanges.h" |
| #import "WebVideoFullscreenInterfaceAVKit.h" |
| #import "WebVideoFullscreenModelVideoElement.h" |
| #import <QuartzCore/CoreAnimation.h> |
| #import <WebCore/FrameView.h> |
| #import <WebCore/HTMLVideoElement.h> |
| #import <WebCore/RenderElement.h> |
| #import <WebCore/WebCoreThreadRun.h> |
| |
| SOFT_LINK_FRAMEWORK(UIKit) |
| SOFT_LINK_CLASS(UIKit, UIView) |
| |
| using namespace WebCore; |
| |
| #if !HAVE(AVKIT) |
| |
| @implementation WebVideoFullscreenController |
| - (void)setVideoElement:(WebCore::HTMLVideoElement*)videoElement |
| { |
| UNUSED_PARAM(videoElement); |
| } |
| |
| - (WebCore::HTMLVideoElement*)videoElement |
| { |
| return nullptr; |
| } |
| |
| - (void)enterFullscreen:(UIView *)view mode:(WebCore::HTMLMediaElementEnums::VideoFullscreenMode)mode |
| { |
| UNUSED_PARAM(view); |
| UNUSED_PARAM(mode); |
| } |
| |
| - (void)requestHideAndExitFullscreen |
| { |
| } |
| |
| - (void)exitFullscreen |
| { |
| } |
| @end |
| |
| #else |
| |
| static IntRect elementRectInWindow(HTMLVideoElement* videoElement) |
| { |
| if (!videoElement || !videoElement->renderer() || !videoElement->document().view()) |
| return IntRect(); |
| |
| return videoElement->document().view()->convertToContainingWindow(videoElement->renderer()->absoluteBoundingBoxRect()); |
| } |
| |
| class WebVideoFullscreenControllerContext; |
| |
| @interface WebVideoFullscreenController (delegate) |
| -(void)didFinishFullscreen:(WebVideoFullscreenControllerContext*)context; |
| @end |
| |
| class WebVideoFullscreenControllerContext final |
| : private WebVideoFullscreenInterface |
| , private WebVideoFullscreenModel |
| , private WebVideoFullscreenChangeObserver |
| , public ThreadSafeRefCounted<WebVideoFullscreenControllerContext> { |
| |
| public: |
| static Ref<WebVideoFullscreenControllerContext> create() |
| { |
| return adoptRef(*new WebVideoFullscreenControllerContext); |
| } |
| |
| void setController(WebVideoFullscreenController* controller) { m_controller = controller; } |
| void setUpFullscreen(HTMLVideoElement&, UIView *, HTMLMediaElementEnums::VideoFullscreenMode); |
| void exitFullscreen(); |
| void requestHideAndExitFullscreen(); |
| void invalidate(); |
| |
| private: |
| WebVideoFullscreenControllerContext() { } |
| |
| // WebVideoFullscreenChangeObserver |
| virtual void didSetupFullscreen() override; |
| virtual void didEnterFullscreen() override { } |
| virtual void didExitFullscreen() override; |
| virtual void didCleanupFullscreen() override; |
| virtual void fullscreenMayReturnToInline() override; |
| |
| // WebVideoFullscreenInterface |
| virtual void resetMediaState() override; |
| virtual void setDuration(double) override; |
| virtual void setCurrentTime(double currentTime, double anchorTime) override; |
| virtual void setBufferedTime(double) override; |
| virtual void setRate(bool isPlaying, float playbackRate) override; |
| virtual void setVideoDimensions(bool hasVideo, float width, float height) override; |
| virtual void setSeekableRanges(const TimeRanges&) override; |
| virtual void setCanPlayFastReverse(bool) override; |
| virtual void setAudioMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex) override; |
| virtual void setLegibleMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex) override; |
| virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, String localizedDeviceName) override; |
| virtual void setWirelessVideoPlaybackDisabled(bool) override; |
| |
| // WebVideoFullscreenModel |
| virtual void play() override; |
| virtual void pause() override; |
| virtual void togglePlayState() override; |
| virtual void beginScrubbing() override; |
| virtual void endScrubbing() override; |
| virtual void seekToTime(double time) override; |
| virtual void fastSeek(double time) override; |
| virtual void beginScanningForward() override; |
| virtual void beginScanningBackward() override; |
| virtual void endScanning() override; |
| virtual void requestExitFullscreen() override; |
| virtual void setVideoLayerFrame(FloatRect) override; |
| virtual void setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity) override; |
| virtual void selectAudioMediaOption(uint64_t index) override; |
| virtual void selectLegibleMediaOption(uint64_t index) override; |
| virtual void fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode) override; |
| |
| RefPtr<WebVideoFullscreenInterfaceAVKit> m_interface; |
| RefPtr<WebVideoFullscreenModelVideoElement> m_model; |
| RefPtr<HTMLVideoElement> m_videoElement; |
| RetainPtr<UIView> m_videoFullscreenView; |
| RetainPtr<WebVideoFullscreenController> m_controller; |
| }; |
| |
| #pragma mark WebVideoFullscreenChangeObserver |
| |
| void WebVideoFullscreenControllerContext::didSetupFullscreen() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer]; |
| WebThreadRun([strongThis, this, videoFullscreenLayer] { |
| [videoFullscreenLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent, WebCore::ColorSpaceDeviceRGB)]; |
| m_model->setVideoFullscreenLayer(videoFullscreenLayer.get()); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this] { |
| m_interface->enterFullscreen(); |
| }); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::didExitFullscreen() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| m_model->setVideoFullscreenLayer(nil); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this] { |
| m_interface->cleanupFullscreen(); |
| }); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::didCleanupFullscreen() |
| { |
| ASSERT(isUIThread()); |
| m_interface->setWebVideoFullscreenModel(nullptr); |
| m_interface->setWebVideoFullscreenChangeObserver(nullptr); |
| m_interface = nullptr; |
| m_videoFullscreenView = nil; |
| |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| m_model->setVideoFullscreenLayer(nil); |
| m_model->setWebVideoFullscreenInterface(nullptr); |
| m_model->setVideoElement(nullptr); |
| m_model = nullptr; |
| m_videoElement = nullptr; |
| |
| [m_controller didFinishFullscreen:this]; |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::fullscreenMayReturnToInline() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| IntRect clientRect = elementRectInWindow(m_videoElement.get()); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, clientRect] { |
| m_interface->preparedToReturnToInline(true, clientRect); |
| }); |
| }); |
| } |
| |
| #pragma mark WebVideoFullscreenInterface |
| |
| void WebVideoFullscreenControllerContext::resetMediaState() |
| { |
| ASSERT(WebThreadIsCurrent() || isMainThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this] { |
| if (m_interface) |
| m_interface->resetMediaState(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setDuration(double duration) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, duration] { |
| if (m_interface) |
| m_interface->setDuration(duration); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setCurrentTime(double currentTime, double anchorTime) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, currentTime, anchorTime] { |
| if (m_interface) |
| m_interface->setCurrentTime(currentTime, anchorTime); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setBufferedTime(double bufferedTime) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, bufferedTime] { |
| if (m_interface) |
| m_interface->setBufferedTime(bufferedTime); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setRate(bool isPlaying, float playbackRate) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, isPlaying, playbackRate] { |
| if (m_interface) |
| m_interface->setRate(isPlaying, playbackRate); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setVideoDimensions(bool hasVideo, float width, float height) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, hasVideo, width, height] { |
| if (m_interface) |
| m_interface->setVideoDimensions(hasVideo, width, height); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setSeekableRanges(const TimeRanges& timeRanges) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| const PlatformTimeRanges& platformTimeRanges = timeRanges.ranges(); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, platformTimeRanges] { |
| if (m_interface) |
| m_interface->setSeekableRanges(TimeRanges::create(platformTimeRanges)); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setCanPlayFastReverse(bool canPlayFastReverse) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, canPlayFastReverse] { |
| if (m_interface) |
| m_interface->setCanPlayFastReverse(canPlayFastReverse); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setAudioMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| |
| RetainPtr<NSMutableArray> optionsArray = adoptNS([[NSMutableArray alloc] initWithCapacity:options.size()]); |
| for (auto& name : options) |
| [optionsArray addObject:name]; |
| |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, optionsArray, selectedIndex] { |
| Vector<String> options; |
| for (NSString *name : optionsArray.get()) |
| options.append(name); |
| |
| if (m_interface) |
| m_interface->setAudioMediaSelectionOptions(options, selectedIndex); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setLegibleMediaSelectionOptions(const Vector<String>& options, uint64_t selectedIndex) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| |
| RetainPtr<NSMutableArray> optionsArray = adoptNS([[NSMutableArray alloc] initWithCapacity:options.size()]); |
| for (auto& name : options) |
| [optionsArray addObject:name]; |
| |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, optionsArray, selectedIndex] { |
| Vector<String> options; |
| for (NSString *name : optionsArray.get()) |
| options.append(name); |
| |
| if (m_interface) |
| m_interface->setLegibleMediaSelectionOptions(options, selectedIndex); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setExternalPlayback(bool enabled, ExternalPlaybackTargetType type, String localizedDeviceName) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| StringCapture capturedLocalizedDeviceName(localizedDeviceName); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, enabled, type, capturedLocalizedDeviceName] { |
| if (m_interface) |
| m_interface->setExternalPlayback(enabled, type, capturedLocalizedDeviceName.string()); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setWirelessVideoPlaybackDisabled(bool disabled) |
| { |
| ASSERT(WebThreadIsCurrent()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, disabled] { |
| if (m_interface) |
| m_interface->setWirelessVideoPlaybackDisabled(disabled); |
| }); |
| } |
| |
| #pragma mark WebVideoFullscreenModel |
| |
| void WebVideoFullscreenControllerContext::play() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->play(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::pause() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->pause(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::togglePlayState() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->togglePlayState(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::beginScrubbing() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->beginScrubbing(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::endScrubbing() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->endScrubbing(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::seekToTime(double time) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, time] { |
| if (m_model) |
| m_model->seekToTime(time); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::fastSeek(double time) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, time] { |
| if (m_model) |
| m_model->fastSeek(time); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::beginScanningForward() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->beginScanningForward(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::beginScanningBackward() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->beginScanningBackward(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::endScanning() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->endScanning(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::requestExitFullscreen() |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this] { |
| if (m_model) |
| m_model->requestExitFullscreen(); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setVideoLayerFrame(FloatRect frame) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer]; |
| |
| [videoFullscreenLayer setSublayerTransform:[videoFullscreenLayer transform]]; |
| |
| dispatch_async(dispatch_get_main_queue(), ^{ |
| WebThreadRun([strongThis, this, frame, videoFullscreenLayer] { |
| [CATransaction begin]; |
| [CATransaction setDisableActions:YES]; |
| [CATransaction setAnimationDuration:0]; |
| |
| [videoFullscreenLayer setSublayerTransform:CATransform3DIdentity]; |
| |
| if (m_model) |
| m_model->setVideoLayerFrame(frame); |
| [CATransaction commit]; |
| }); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity videoGravity) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, videoGravity] { |
| if (m_model) |
| m_model->setVideoLayerGravity(videoGravity); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::selectAudioMediaOption(uint64_t index) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, index] { |
| if (m_model) |
| m_model->selectAudioMediaOption(index); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::selectLegibleMediaOption(uint64_t index) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, index] { |
| if (m_model) |
| m_model->selectLegibleMediaOption(index); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode mode) |
| { |
| ASSERT(isUIThread()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, mode] { |
| if (m_model) |
| m_model->fullscreenModeChanged(mode); |
| }); |
| } |
| |
| #pragma mark Other |
| |
| void WebVideoFullscreenControllerContext::setUpFullscreen(HTMLVideoElement& videoElement, UIView *view, HTMLMediaElementEnums::VideoFullscreenMode mode) |
| { |
| ASSERT(isMainThread()); |
| RetainPtr<UIView> viewRef = view; |
| m_videoElement = &videoElement; |
| |
| m_interface = WebVideoFullscreenInterfaceAVKit::create(); |
| m_interface->setWebVideoFullscreenChangeObserver(this); |
| m_interface->setWebVideoFullscreenModel(this); |
| m_videoFullscreenView = adoptNS([[getUIViewClass() alloc] init]); |
| |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| WebThreadRun([strongThis, this, viewRef, mode] { |
| m_model = WebVideoFullscreenModelVideoElement::create(); |
| m_model->setWebVideoFullscreenInterface(this); |
| m_model->setVideoElement(m_videoElement.get()); |
| |
| bool allowsPictureInPicture = m_videoElement->mediaSession().allowsPictureInPicture(*m_videoElement.get()); |
| |
| IntRect videoElementClientRect = elementRectInWindow(m_videoElement.get()); |
| FloatRect videoLayerFrame = FloatRect(FloatPoint(), videoElementClientRect.size()); |
| m_model->setVideoLayerFrame(videoLayerFrame); |
| |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, videoElementClientRect, viewRef, mode, allowsPictureInPicture] { |
| m_interface->setupFullscreen(*m_videoFullscreenView.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture); |
| }); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::exitFullscreen() |
| { |
| ASSERT(WebThreadIsCurrent() || isMainThread()); |
| IntRect clientRect = elementRectInWindow(m_videoElement.get()); |
| RefPtr<WebVideoFullscreenControllerContext> strongThis(this); |
| dispatch_async(dispatch_get_main_queue(), [strongThis, this, clientRect] { |
| ASSERT(isUIThread()); |
| m_interface->exitFullscreen(clientRect); |
| }); |
| } |
| |
| void WebVideoFullscreenControllerContext::requestHideAndExitFullscreen() |
| { |
| ASSERT(isUIThread()); |
| m_interface->requestHideAndExitFullscreen(); |
| } |
| |
| @implementation WebVideoFullscreenController { |
| RefPtr<WebVideoFullscreenControllerContext> _context; |
| RefPtr<HTMLVideoElement> _videoElement; |
| } |
| |
| - (instancetype)init |
| { |
| if (!(self = [super init])) |
| return nil; |
| |
| return self; |
| } |
| |
| - (void)setVideoElement:(HTMLVideoElement*)videoElement |
| { |
| _videoElement = videoElement; |
| } |
| |
| - (HTMLVideoElement*)videoElement |
| { |
| return _videoElement.get(); |
| } |
| |
| - (void)enterFullscreen:(UIView *)view mode:(HTMLMediaElementEnums::VideoFullscreenMode)mode |
| { |
| ASSERT(isMainThread()); |
| _context = WebVideoFullscreenControllerContext::create(); |
| _context->setController(self); |
| _context->setUpFullscreen(*_videoElement.get(), view, mode); |
| } |
| |
| - (void)exitFullscreen |
| { |
| ASSERT(WebThreadIsCurrent() || isMainThread()); |
| _context->exitFullscreen(); |
| } |
| |
| - (void)requestHideAndExitFullscreen |
| { |
| ASSERT(isUIThread()); |
| if (_context) |
| _context->requestHideAndExitFullscreen(); |
| } |
| |
| - (void)didFinishFullscreen:(WebVideoFullscreenControllerContext*)context |
| { |
| ASSERT(WebThreadIsCurrent()); |
| ASSERT_UNUSED(context, context == _context); |
| [[self retain] autorelease]; // retain self before breaking a retain cycle. |
| _context->setController(nil); |
| _context = nullptr; |
| _videoElement = nullptr; |
| } |
| |
| @end |
| |
| #endif // !HAVE(AVKIT) |
| |
| #endif // PLATFORM(IOS) |