Diff
Modified: trunk/Source/WTF/ChangeLog (229713 => 229714)
--- trunk/Source/WTF/ChangeLog 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WTF/ChangeLog 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,3 +1,13 @@
+2018-03-19 Eric Carlson <eric.carl...@apple.com>
+
+ [Extra zoom mode] Require fullscreen for video playback
+ https://bugs.webkit.org/show_bug.cgi?id=183742
+ <rdar://problem/38235862>
+
+ Reviewed by Jer Noble.
+
+ * wtf/Platform.h:
+
2018-03-15 Tim Horton <timothy_hor...@apple.com>
Avoid defining commonly-named system macros on all Cocoa platforms
Modified: trunk/Source/WTF/wtf/Platform.h (229713 => 229714)
--- trunk/Source/WTF/wtf/Platform.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WTF/wtf/Platform.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1042,10 +1042,13 @@
#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV) && !ENABLE(MINIMAL_SIMULATOR)
#define ENABLE_DATA_DETECTION 1
-#define HAVE_AVKIT 1
#define HAVE_PARENTAL_CONTROLS 1
#endif
+#if !PLATFORM(APPLETV) && !ENABLE(MINIMAL_SIMULATOR)
+#define HAVE_AVKIT 1
+#endif
+
#if ENABLE(WEBGL)
#if PLATFORM(MAC)
#define USE_OPENGL 1
Modified: trunk/Source/WebCore/ChangeLog (229713 => 229714)
--- trunk/Source/WebCore/ChangeLog 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/ChangeLog 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,3 +1,58 @@
+2018-03-19 Eric Carlson <eric.carl...@apple.com>
+
+ [Extra zoom mode] Require fullscreen for video playback
+ https://bugs.webkit.org/show_bug.cgi?id=183742
+ <rdar://problem/38235862>
+
+ Reviewed by Jer Noble.
+
+ * Modules/modern-media-controls/media/playback-support.js:
+ (PlaybackSupport.prototype.syncControl): Always show the play button.
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::updatePlayState): Return immediately if playback requires fullscreen
+ (WebCore::HTMLMediaElement::didBecomeFullscreenElement): Call updatePlayState in case
+ playback is pending.
+ * html/HTMLMediaElement.h:
+ * platform/cocoa/VideoFullscreenModel.h:
+ (WebCore::VideoFullscreenModel::presentingViewController): New.
+ (WebCore::VideoFullscreenModel::createVideoFullscreenViewController): New.
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerLayer):
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenMode):
+ * platform/ios/PlaybackSessionInterfaceAVKit.mm:
+ (WebCore::PlaybackSessionInterfaceAVKit::seekableRangesChanged):
+
+ * platform/ios/VideoFullscreenInterfaceAVKit.h:
+ * platform/ios/VideoFullscreenInterfaceAVKit.mm: Wrap AVPlayerLayerView so we can change its
+ behavior.
+ (WebAVPlayerLayerView_playerLayer):
+ (WebAVPlayerLayerView_videoView):
+ (allocWebAVPlayerLayerViewInstance):
+ (-[WebAVPlayerViewController initWithFullscreenInterface:]):
+ (-[WebAVPlayerViewController playerViewControllerShouldHandleDoneButtonTap:]):
+ (-[WebAVPlayerViewController enterFullScreenAnimated:completionHandler:]):
+ (-[WebAVPlayerViewController exitFullScreenAnimated:completionHandler:]):
+ (-[WebAVPlayerViewController NO_RETURN_DUE_TO_ASSERT]):
+ (-[WebAVPlayerViewController isPictureInPicturePossible]):
+ (-[WebAVPlayerViewController isPictureInPictureActive]):
+ (-[WebAVPlayerViewController isPictureInPictureSuspended]):
+ (-[WebAVPlayerViewController pictureInPictureActive]):
+ (-[WebAVPlayerViewController pictureInPictureWasStartedWhenEnteringBackground]):
+ (-[WebAVPlayerViewController view]):
+ (-[WebAVPlayerViewController showsPlaybackControls]):
+ (-[WebAVPlayerViewController setShowsPlaybackControls:]):
+ (-[WebAVPlayerViewController setAllowsPictureInPicturePlayback:]):
+ (-[WebAVPlayerViewController setDelegate:]):
+ (-[WebAVPlayerViewController setPlayerController:]):
+ (-[WebAVPlayerViewController avPlayerViewController]):
+ (-[WebAVPlayerViewController removeFromParentViewController]):
+ (VideoFullscreenInterfaceAVKit::setupFullscreen):
+ (fallbackViewController):
+ (VideoFullscreenInterfaceAVKit::presentingViewController):
+ (VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason):
+ (VideoFullscreenInterfaceAVKit::doSetup):
+ (WebCore::supportsPictureInPicture):
+
2018-03-19 Per Arne Vollan <pvol...@apple.com>
When the WebContent process is blocked from accessing the WindowServer, the call CVDisplayLinkCreateWithCGDisplay will fail.
Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/playback-support.js (229713 => 229714)
--- trunk/Source/WebCore/Modules/modern-media-controls/media/playback-support.js 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/playback-support.js 2018-03-19 21:22:15 UTC (rev 229714)
@@ -47,9 +47,9 @@
{
const isPaused = this.mediaController.media.paused;
- // We always show the play button when the media is paused with compact layout.
+ // We always show the play button with compact layout.
if (this.mediaController.layoutTraits & LayoutTraits.Compact)
- this.control.visible = isPaused;
+ this.control.visible = true;
else
this.control.playing = !isPaused;
}
Modified: trunk/Source/WebCore/PAL/ChangeLog (229713 => 229714)
--- trunk/Source/WebCore/PAL/ChangeLog 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/PAL/ChangeLog 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,3 +1,13 @@
+2018-03-19 Eric Carlson <eric.carl...@apple.com>
+
+ [Extra zoom mode] Require fullscreen for video playback
+ https://bugs.webkit.org/show_bug.cgi?id=183742
+ <rdar://problem/38235862>
+
+ Reviewed by Jer Noble.
+
+ * pal/spi/cocoa/AVKitSPI.h:
+
2018-03-19 Jiewen Tan <jiewen_...@apple.com>
Unreviewed, a quick fix for r229699
Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h (229713 => 229714)
--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -41,6 +41,53 @@
#import <AVKit/AVPlayerViewController_Private.h>
#import <AVKit/AVPlayerViewController_WebKitOnly.h>
+#if ENABLE(EXTRA_ZOOM_MODE)
+
+#import <AVFoundation/AVPlayerLayer.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AVPictureInPicturePlayerLayerView : UIView
+@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
+@end
+
+@interface __AVPlayerLayerView (Details)
+@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
+- (AVPictureInPicturePlayerLayerView*) pictureInPicturePlayerLayerView;
+- (void)startRoutingVideoToPictureInPicturePlayerLayerView;
+- (void)stopRoutingVideoToPictureInPicturePlayerLayerView;
+@end
+
+@class AVPlayerLayerView;
+@interface AVPlayerViewController (AVPlayerViewController_WebKitOnly_Internal)
+- (void)enterFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError * __nullable error))completionHandler;
+- (void)exitFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError * __nullable error))completionHandler;
+- (void)startPictureInPicture;
+- (void)stopPictureInPicture;
+
+@property (nonatomic) BOOL showsExitFullScreenButton;
+@property (nonatomic, readonly, getter=isPictureInPicturePossible) BOOL pictureInPicturePossible;
+@property (nonatomic, readonly, getter=isPictureInPictureActive) BOOL pictureInPictureActive;
+@property (nonatomic, readonly, getter=isPictureInPictureSuspended) BOOL pictureInPictureSuspended;
+@property (nonatomic, readonly) BOOL pictureInPictureWasStartedWhenEnteringBackground;
+@end
+
+@protocol AVPlayerViewControllerDelegate_WebKitOnly <AVPlayerViewControllerDelegate>
+@optional
+typedef NS_ENUM(NSInteger, AVPlayerViewControllerExitFullScreenReason) {
+ AVPlayerViewControllerExitFullScreenReasonDoneButtonTapped,
+ AVPlayerViewControllerExitFullScreenReasonFullScreenButtonTapped,
+ AVPlayerViewControllerExitFullScreenReasonPinchGestureHandled,
+ AVPlayerViewControllerExitFullScreenReasonRemoteControlStopEventReceived,
+ AVPlayerViewControllerExitFullScreenReasonPictureInPictureStarted
+};
+- (BOOL)playerViewController:(AVPlayerViewController *)playerViewController shouldExitFullScreenWithReason:(AVPlayerViewControllerExitFullScreenReason)reason;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif
+
#else
@interface AVPlayerController : UIResponder
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (229713 => 229714)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-03-19 21:22:15 UTC (rev 229714)
@@ -5255,6 +5255,14 @@
INFO_LOG(LOGIDENTIFIER, "shouldBePlaying = ", shouldBePlaying, ", playerPaused = ", playerPaused);
+ if (shouldBePlaying && playerPaused && m_mediaSession->requiresFullscreenForVideoPlayback(*this) && !isFullscreen()) {
+ enterFullscreen();
+#if ENABLE(EXTRA_ZOOM_MODE)
+ // FIXME: Investigate doing this for all builds.
+ return;
+#endif
+ }
+
if (shouldBePlaying) {
scheduleUpdatePlaybackControlsManager();
@@ -5264,9 +5272,6 @@
if (playerPaused) {
m_mediaSession->clientWillBeginPlayback();
- if (m_mediaSession->requiresFullscreenForVideoPlayback(*this) && !isFullscreen())
- enterFullscreen();
-
// Set rate, muted before calling play in case they were set before the media engine was setup.
// The media engine should just stash the rate and muted values since it isn't already playing.
m_player->setRate(requestedPlaybackRate());
@@ -5967,6 +5972,7 @@
{
if (hasMediaControls())
mediaControls()->enteredFullscreen();
+ updatePlayState(UpdateState::Asynchronously);
}
void HTMLMediaElement::willStopBeingFullscreenElement()
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (229713 => 229714)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -553,6 +553,8 @@
bool isSuspended() const final;
+ WEBCORE_EXPORT void didBecomeFullscreenElement() override;
+
protected:
HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser);
virtual void finishInitialization();
@@ -603,7 +605,6 @@
void didRecalcStyle(Style::Change) override;
void willBecomeFullscreenElement() override;
- void didBecomeFullscreenElement() override;
void willStopBeingFullscreenElement() override;
// ActiveDOMObject API.
Modified: trunk/Source/WebCore/platform/cocoa/VideoFullscreenModel.h (229713 => 229714)
--- trunk/Source/WebCore/platform/cocoa/VideoFullscreenModel.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/cocoa/VideoFullscreenModel.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -32,6 +32,11 @@
#include "HTMLMediaElementEnums.h"
#include "PlaybackSessionModel.h"
+#if PLATFORM(IOS)
+OBJC_CLASS AVPlayerViewController;
+OBJC_CLASS UIViewController;
+#endif
+
namespace WebCore {
class VideoFullscreenModelClient;
@@ -51,6 +56,11 @@
virtual bool isVisible() const = 0;
virtual FloatSize videoDimensions() const = 0;
virtual bool hasVideo() const = 0;
+
+#if PLATFORM(IOS)
+ virtual UIViewController *presentingViewController() { return nullptr; }
+ virtual UIViewController *createVideoFullscreenViewController(AVPlayerViewController *) { return nullptr; }
+#endif
};
class VideoFullscreenModelClient {
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (229713 => 229714)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -710,7 +710,7 @@
#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
m_videoFullscreenLayerManager->setVideoLayer(m_videoLayer.get(), defaultSize);
-#if PLATFORM(IOS)
+#if PLATFORM(IOS) && !ENABLE(EXTRA_ZOOM_MODE)
if ([m_videoLayer respondsToSelector:@selector(setPIPModeEnabled:)])
[m_videoLayer setPIPModeEnabled:(player()->fullscreenMode() & MediaPlayer::VideoFullscreenModePictureInPicture)];
#endif
@@ -1232,7 +1232,7 @@
void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenMode(MediaPlayer::VideoFullscreenMode mode)
{
-#if PLATFORM(IOS)
+#if PLATFORM(IOS) && !ENABLE(EXTRA_ZOOM_MODE)
if ([m_videoLayer respondsToSelector:@selector(setPIPModeEnabled:)])
[m_videoLayer setPIPModeEnabled:(mode & MediaPlayer::VideoFullscreenModePictureInPicture)];
updateDisableExternalPlayback();
Modified: trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm (229713 => 229714)
--- trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -128,6 +128,7 @@
{
RetainPtr<NSMutableArray> seekableRanges = adoptNS([[NSMutableArray alloc] init]);
+#if !ENABLE(EXTRA_ZOOM_MODE)
for (unsigned i = 0; i < timeRanges.length(); i++) {
double start = timeRanges.start(i).releaseReturnValue();
double end = timeRanges.end(i).releaseReturnValue();
@@ -135,6 +136,9 @@
CMTimeRange range = CMTimeRangeMake(CMTimeMakeWithSeconds(start, 1000), CMTimeMakeWithSeconds(end-start, 1000));
[seekableRanges addObject:[NSValue valueWithCMTimeRange:range]];
}
+#else
+ UNUSED_PARAM(timeRanges);
+#endif
[m_playerController setSeekableTimeRanges:seekableRanges.get()];
[m_playerController setSeekableTimeRangesLastModifiedTime: lastModifiedTime];
Modified: trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h (229713 => 229714)
--- trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,7 +40,6 @@
#include <wtf/RetainPtr.h>
#include <wtf/RunLoop.h>
-OBJC_CLASS AVPlayerViewController;
OBJC_CLASS UIViewController;
OBJC_CLASS UIWindow;
OBJC_CLASS UIView;
@@ -48,6 +47,7 @@
OBJC_CLASS WebAVPlayerController;
OBJC_CLASS WebAVPlayerLayerView;
OBJC_CLASS WebAVPlayerLayer;
+OBJC_CLASS WebAVPlayerViewController;
OBJC_CLASS WebAVPlayerViewControllerDelegate;
OBJC_CLASS NSError;
@@ -157,6 +157,12 @@
void clearMode(HTMLMediaElementEnums::VideoFullscreenMode);
bool hasMode(HTMLMediaElementEnums::VideoFullscreenMode mode) const { return m_currentMode.hasMode(mode); }
+#if PLATFORM(IOS)
+ UIViewController *presentingViewController();
+ UIViewController *fullscreenViewController() const { return m_viewController.get(); }
+ WebAVPlayerLayerView* playerLayerView() const { return m_playerLayerView.get(); }
+#endif
+
protected:
WEBCORE_EXPORT VideoFullscreenInterfaceAVKit(PlaybackSessionInterfaceAVKit&);
@@ -175,7 +181,7 @@
Ref<PlaybackSessionInterfaceAVKit> m_playbackSessionInterface;
RetainPtr<WebAVPlayerViewControllerDelegate> m_playerViewControllerDelegate;
- RetainPtr<AVPlayerViewController> m_playerViewController;
+ RetainPtr<WebAVPlayerViewController> m_playerViewController;
VideoFullscreenModel* m_videoFullscreenModel { nullptr };
VideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr };
Modified: trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm (229713 => 229714)
--- trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,9 +40,11 @@
#import "WebAVPlayerController.h"
#import <AVFoundation/AVTime.h>
#import <UIKit/UIKit.h>
+#import <UIKit/UIWindow.h>
#import <objc/message.h>
#import <objc/runtime.h>
#import <pal/spi/cocoa/AVKitSPI.h>
+#import <pal/spi/ios/UIKitSPI.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/CString.h>
#import <wtf/text/WTFString.h>
@@ -93,7 +95,13 @@
#endif
static const Seconds defaultWatchdogTimerInterval { 1_s };
+static bool ignoreWatchdogForDebugging = false;
+@interface AVPlayerViewController (Details)
+@property (nonatomic) BOOL showsPlaybackControls;
+@property (nonatomic) UIView* view;
+@end
+
@class WebAVMediaSelectionOption;
@interface WebAVPlayerViewControllerDelegate : NSObject <AVPlayerViewControllerDelegate_WebKitOnly> {
@@ -412,10 +420,23 @@
[webAVPlayerLayer setPlayerController: playerController];
}
+static AVPlayerLayer *WebAVPlayerLayerView_playerLayer(id aSelf, SEL)
+{
+ __AVPlayerLayerView *playerLayerView = aSelf;
+
+ if ([get__AVPlayerLayerViewClass() instancesRespondToSelector:@selector(playerLayer)]) {
+ objc_super superClass { playerLayerView, get__AVPlayerLayerViewClass() };
+ auto superClassMethod = reinterpret_cast<AVPlayerLayer *(*)(objc_super *, SEL)>(objc_msgSendSuper);
+ return superClassMethod(&superClass, @selector(playerLayer));
+ }
+
+ return (AVPlayerLayer *)[playerLayerView layer];
+}
+
static UIView *WebAVPlayerLayerView_videoView(id aSelf, SEL)
{
- __AVPlayerLayerView *playerLayer = aSelf;
- WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayer playerLayer];
+ __AVPlayerLayerView *playerLayerView = aSelf;
+ WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
CALayer* videoLayer = [webAVPlayerLayer videoSublayer];
if (!videoLayer || !videoLayer.delegate)
return nil;
@@ -486,6 +507,7 @@
static Class theClass = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
+ ASSERT(get__AVPlayerLayerViewClass());
theClass = objc_allocateClassPair(get__AVPlayerLayerViewClass(), "WebAVPlayerLayerView", 0);
class_addMethod(theClass, @selector(dealloc), (IMP)WebAVPlayerLayerView_dealloc, "v@:");
class_addMethod(theClass, @selector(setPlayerController:), (IMP)WebAVPlayerLayerView_setPlayerController, "v@:@");
@@ -492,6 +514,7 @@
class_addMethod(theClass, @selector(playerController), (IMP)WebAVPlayerLayerView_playerController, "@@:");
class_addMethod(theClass, @selector(setVideoView:), (IMP)WebAVPlayerLayerView_setVideoView, "v@:@");
class_addMethod(theClass, @selector(videoView), (IMP)WebAVPlayerLayerView_videoView, "@@:");
+ class_addMethod(theClass, @selector(playerLayer), (IMP)WebAVPlayerLayerView_playerLayer, "@@:");
class_addMethod(theClass, @selector(startRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
class_addMethod(theClass, @selector(stopRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
class_addMethod(theClass, @selector(pictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_pictureInPicturePlayerLayerView, "@@:");
@@ -505,6 +528,197 @@
return (WebAVPlayerLayerView *)[theClass alloc];
}
+NS_ASSUME_NONNULL_BEGIN
+@interface WebAVPlayerViewController : NSObject<AVPlayerViewControllerDelegate>
+- (instancetype)initWithFullscreenInterface:(VideoFullscreenInterfaceAVKit *)interface;
+- (void)enterFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
+- (void)exitFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
+- (void)startPictureInPicture;
+- (void)stopPictureInPicture;
+
+- (BOOL)playerViewControllerShouldHandleDoneButtonTap:(AVPlayerViewController *)playerViewController;
+@end
+NS_ASSUME_NONNULL_END
+
+@implementation WebAVPlayerViewController {
+ VideoFullscreenInterfaceAVKit *_fullscreenInterface;
+ RetainPtr<UIViewController> _presentingViewController;
+ RetainPtr<AVPlayerViewController> _avPlayerViewController;
+ id<AVPlayerViewControllerDelegate_WebKitOnly> _delegate;
+}
+
+- (instancetype)initWithFullscreenInterface:(VideoFullscreenInterfaceAVKit *)interface
+{
+ if (!(self = [super init]))
+ return nil;
+
+ _fullscreenInterface = interface;
+ _avPlayerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithPlayerLayerView:interface->playerLayerView()]);
+#if ENABLE(EXTRA_ZOOM_MODE)
+ _avPlayerViewController.get().delegate = self;
+#endif
+
+ return self;
+}
+
+- (BOOL)playerViewControllerShouldHandleDoneButtonTap:(AVPlayerViewController *)playerViewController
+{
+ ASSERT(playerViewController == _avPlayerViewController.get());
+ if (_delegate)
+ return [_delegate playerViewController:playerViewController shouldExitFullScreenWithReason:AVPlayerViewControllerExitFullScreenReasonDoneButtonTapped];
+
+ return YES;
+}
+
+- (void)enterFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError * __nullable error))completionHandler
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ _presentingViewController = _fullscreenInterface->presentingViewController();
+
+ _avPlayerViewController.get().view.frame = _presentingViewController.get().view.frame;
+ [_presentingViewController presentViewController:_fullscreenInterface->fullscreenViewController() animated:animated completion:^{
+ if (completionHandler)
+ completionHandler(YES, nil);
+ }];
+#else
+ [_avPlayerViewController.get() enterFullScreenAnimated:animated completionHandler:completionHandler];
+#endif
+}
+
+- (void)exitFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError * __nullable error))completionHandler
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ if (!_presentingViewController)
+ return;
+
+ [_presentingViewController dismissViewControllerAnimated:animated completion:^{
+ _presentingViewController = nil;
+ if (completionHandler)
+ completionHandler(YES, nil);
+ }];
+#else
+ [_avPlayerViewController.get() exitFullScreenAnimated:animated completionHandler:completionHandler];
+#endif
+}
+
+#if ENABLE(EXTRA_ZOOM_MODE)
+#define MY_NO_RETURN NO_RETURN_DUE_TO_ASSERT
+#else
+#define MY_NO_RETURN
+#endif
+
+- (void)startPictureInPicture MY_NO_RETURN
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ ASSERT_NOT_REACHED();
+#else
+ [_avPlayerViewController.get() startPictureInPicture];
+#endif
+}
+
+- (void)stopPictureInPicture MY_NO_RETURN
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ ASSERT_NOT_REACHED();
+#else
+ [_avPlayerViewController.get() stopPictureInPicture];
+#endif
+}
+
+- (BOOL)isPictureInPicturePossible
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ return NO;
+#else
+ return _avPlayerViewController.get().isPictureInPicturePossible;
+#endif
+}
+
+- (BOOL)isPictureInPictureActive
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ return NO;
+#else
+ return _avPlayerViewController.get().isPictureInPictureActive;
+#endif
+}
+
+- (BOOL)pictureInPictureActive
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ return NO;
+#else
+ return _avPlayerViewController.get().pictureInPictureActive;
+#endif
+}
+
+- (BOOL)pictureInPictureWasStartedWhenEnteringBackground
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ return NO;
+#else
+ return _avPlayerViewController.get().pictureInPictureWasStartedWhenEnteringBackground;
+#endif
+}
+
+- (UIView *) view
+{
+ return _avPlayerViewController.get().view;
+}
+
+- (BOOL)showsPlaybackControls
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ return YES;
+#else
+ return _avPlayerViewController.get().showsPlaybackControls;
+#endif
+}
+
+- (void)setShowsPlaybackControls:(BOOL)showsPlaybackControls
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ UNUSED_PARAM(showsPlaybackControls);
+#else
+ _avPlayerViewController.get().showsPlaybackControls = showsPlaybackControls;
+#endif
+}
+
+- (void)setAllowsPictureInPicturePlayback:(BOOL)allowsPictureInPicturePlayback
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ UNUSED_PARAM(allowsPictureInPicturePlayback);
+#else
+ _avPlayerViewController.get().allowsPictureInPicturePlayback = allowsPictureInPicturePlayback;
+#endif
+}
+
+- (void)setDelegate:(id <AVPlayerViewControllerDelegate>)delegate
+{
+#if ENABLE(EXTRA_ZOOM_MODE)
+ ASSERT(!delegate || [delegate respondsToSelector:@selector(playerViewController:shouldExitFullScreenWithReason:)]);
+ _delegate = id<AVPlayerViewControllerDelegate_WebKitOnly>(delegate);
+#else
+ _avPlayerViewController.get().delegate = delegate;
+#endif
+}
+
+- (void)setPlayerController:(AVPlayerController *)playerController
+{
+ _avPlayerViewController.get().playerController = playerController;
+}
+
+- (AVPlayerViewController *) avPlayerViewController
+{
+ return _avPlayerViewController.get();
+}
+
+- (void)removeFromParentViewController
+{
+ [_avPlayerViewController.get() removeFromParentViewController];
+}
+@end
+
Ref<VideoFullscreenInterfaceAVKit> VideoFullscreenInterfaceAVKit::create(PlaybackSessionInterfaceAVKit& playbackSessionInterface)
{
Ref<VideoFullscreenInterfaceAVKit> interface = adoptRef(*new VideoFullscreenInterfaceAVKit(playbackSessionInterface));
@@ -619,6 +833,7 @@
[CATransaction begin];
[CATransaction setDisableActions:YES];
+#if !ENABLE(EXTRA_ZOOM_MODE)
if (![[m_parentView window] _isHostedInAnotherProcess]) {
if (!m_window)
m_window = adoptNS([allocUIWindowInstance() initWithFrame:[[getUIScreenClass() mainScreen] bounds]]);
@@ -631,6 +846,7 @@
[m_window setWindowLevel:getUITextEffectsBeneathStatusBarWindowLevel() + 1];
[m_window makeKeyAndVisible];
}
+#endif
if (!m_playerLayerView)
m_playerLayerView = adoptNS([allocWebAVPlayerLayerViewInstance() init]);
@@ -643,29 +859,30 @@
}
WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
-
[playerLayer setModelVideoLayerFrame:CGRectMake(0, 0, m_inlineRect.width(), m_inlineRect.height())];
[playerLayer setVideoDimensions:[playerController() contentDimensions]];
playerLayer.fullscreenInterface = this;
if (!m_playerViewController)
- m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithPlayerLayerView:m_playerLayerView.get()]);
+ m_playerViewController = adoptNS([[WebAVPlayerViewController alloc] initWithFullscreenInterface:this]);
[m_playerViewController setShowsPlaybackControls:NO];
[m_playerViewController setPlayerController:(AVPlayerController *)playerController()];
[m_playerViewController setDelegate:m_playerViewControllerDelegate.get()];
[m_playerViewController setAllowsPictureInPicturePlayback:m_allowsPictureInPicturePlayback];
-
[playerController() setPictureInPicturePossible:m_allowsPictureInPicturePlayback];
+#if ENABLE(EXTRA_ZOOM_MODE)
+ m_viewController = model()->createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController);
+#endif
+
if (m_viewController) {
- [m_viewController addChildViewController:m_playerViewController.get()];
+ [m_viewController addChildViewController:m_playerViewController.get().avPlayerViewController];
[[m_viewController view] addSubview:[m_playerViewController view]];
} else
[m_parentView addSubview:[m_playerViewController view]];
[m_playerViewController view].frame = [m_parentView convertRect:m_inlineRect toView:[m_playerViewController view].superview];
-
[[m_playerViewController view] setBackgroundColor:clearUIColor()];
[[m_playerViewController view] setAutoresizingMask:(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin)];
@@ -706,6 +923,28 @@
failedToStartPictureInPicture();
}
+static UIViewController *fallbackViewController(UIView *view)
+{
+ for (UIView *currentView = view; currentView; currentView = currentView.superview) {
+ if (UIViewController *viewController = [getUIViewControllerClass() viewControllerForView:currentView]) {
+ if (![viewController parentViewController])
+ return viewController;
+ }
+ }
+
+ LOG_ERROR("Failed to find a view controller suitable to present fullscreen video");
+ return nil;
+}
+
+UIViewController *VideoFullscreenInterfaceAVKit::presentingViewController()
+{
+ auto *controller = model()->presentingViewController();
+ if (!controller)
+ controller = fallbackViewController(m_parentView.get());
+
+ return controller;
+}
+
void VideoFullscreenInterfaceAVKit::enterFullscreenStandard()
{
LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::enterFullscreenStandard(%p)", this);
@@ -1015,7 +1254,7 @@
BOOL finished = reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::PinchGestureHandled;
m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished);
- if (!m_watchdogTimer.isActive())
+ if (!m_watchdogTimer.isActive() && !ignoreWatchdogForDebugging)
m_watchdogTimer.startOneShot(defaultWatchdogTimerInterval);
return false;
@@ -1301,7 +1540,7 @@
BOOL finished = reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::PinchGestureHandled;
m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished);
- if (!m_watchdogTimer.isActive())
+ if (!m_watchdogTimer.isActive() && !ignoreWatchdogForDebugging)
m_watchdogTimer.startOneShot(defaultWatchdogTimerInterval);
return false;
@@ -1360,6 +1599,7 @@
}
m_setupNeedsInlineRect = false;
+#if !ENABLE(EXTRA_ZOOM_MODE)
[CATransaction begin];
[CATransaction setDisableActions:YES];
if (![[m_parentView window] _isHostedInAnotherProcess] && !m_window) {
@@ -1374,6 +1614,7 @@
[m_window setWindowLevel:getUITextEffectsBeneathStatusBarWindowLevel() + 1];
[m_window makeKeyAndVisible];
}
+#endif
if (!m_playerLayerView)
m_playerLayerView = adoptNS([allocWebAVPlayerLayerViewInstance() init]);
@@ -1392,23 +1633,25 @@
playerLayer.fullscreenInterface = this;
if (!m_playerViewController)
- m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithPlayerLayerView:m_playerLayerView.get()]);
+ m_playerViewController = adoptNS([[WebAVPlayerViewController alloc] initWithFullscreenInterface:this]);
[m_playerViewController setShowsPlaybackControls:NO];
[m_playerViewController setPlayerController:(AVPlayerController *)playerController()];
[m_playerViewController setDelegate:m_playerViewControllerDelegate.get()];
[m_playerViewController setAllowsPictureInPicturePlayback:m_allowsPictureInPicturePlayback];
-
[playerController() setPictureInPicturePossible:m_allowsPictureInPicturePlayback];
+#if ENABLE(EXTRA_ZOOM_MODE)
+ m_viewController = model()->createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController);
+#endif
+
if (m_viewController) {
- [m_viewController addChildViewController:m_playerViewController.get()];
+ [m_viewController addChildViewController:m_playerViewController.get().avPlayerViewController];
[[m_viewController view] addSubview:[m_playerViewController view]];
} else
[m_parentView addSubview:[m_playerViewController view]];
[m_playerViewController view].frame = [m_parentView convertRect:m_inlineRect toView:[m_playerViewController view].superview];
-
[[m_playerViewController view] setBackgroundColor:clearUIColor()];
[[m_playerViewController view] setAutoresizingMask:(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin)];
@@ -1629,7 +1872,7 @@
bool WebCore::supportsPictureInPicture()
{
-#if PLATFORM(IOS) && HAVE(AVKIT)
+#if PLATFORM(IOS) && HAVE(AVKIT) && !ENABLE(EXTRA_ZOOM_MODE)
return [getAVPictureInPictureControllerClass() isPictureInPictureSupported];
#else
return false;
Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm (229713 => 229714)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -878,7 +878,7 @@
m_interface->setVideoFullscreenChangeObserver(this);
m_videoFullscreenView = adoptNS([allocUIViewInstance() init]);
-
+
m_interface->setupFullscreen(*m_videoFullscreenView.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture, false);
});
}
Modified: trunk/Source/WebKit/ChangeLog (229713 => 229714)
--- trunk/Source/WebKit/ChangeLog 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebKit/ChangeLog 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,3 +1,21 @@
+2018-03-19 Eric Carlson <eric.carl...@apple.com>
+
+ [Extra zoom mode] Require fullscreen for video playback
+ https://bugs.webkit.org/show_bug.cgi?id=183742
+ <rdar://problem/38235862>
+
+ Reviewed by Jer Noble.
+
+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.h:
+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.mm:
+ (-[WKVideoFullScreenViewController initWithAVPlayerViewController:]):
+ (-[WKVideoFullScreenViewController viewDidLoad]):
+ (-[WKVideoFullScreenViewController prefersStatusBarHidden]):
+ (WebKit::VideoFullscreenModelContext::presentingViewController):
+ (WebKit::VideoFullscreenModelContext::createVideoFullscreenViewController):
+ * WebProcess/cocoa/VideoFullscreenManager.mm:
+ (WebKit::VideoFullscreenManager::didEnterFullscreen):
+
2018-03-19 Daniel Bates <daba...@apple.com>
test-webkitpy no longer runs WebKit2 tests
Modified: trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h (229713 => 229714)
--- trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h 2018-03-19 21:22:15 UTC (rev 229714)
@@ -85,6 +85,10 @@
bool isVisible() const override;
bool hasVideo() const override { return m_hasVideo; }
WebCore::FloatSize videoDimensions() const override { return m_videoDimensions; }
+#if PLATFORM(IOS)
+ UIViewController *presentingViewController() final;
+ UIViewController *createVideoFullscreenViewController(AVPlayerViewController*) final;
+#endif
// VideoFullscreenChangeObserver
void requestUpdateInlineRect() override;
Modified: trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm (229713 => 229714)
--- trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@
#import "PlaybackSessionManagerProxy.h"
#import "VideoFullscreenManagerMessages.h"
#import "VideoFullscreenManagerProxyMessages.h"
+#import "WeakObjCPtr.h"
#import "WebPageProxy.h"
#import "WebProcessProxy.h"
#import <QuartzCore/CoreAnimation.h>
@@ -44,8 +45,11 @@
#if PLATFORM(IOS)
#import "RemoteLayerTreeDrawingAreaProxy.h"
#import "UIKitSPI.h"
+#import <pal/spi/cocoa/AVKitSPI.h>
#endif
+using namespace WebKit;
+
@interface WKLayerHostView : PlatformView
@property (nonatomic, assign) uint32_t contextID;
@end
@@ -77,6 +81,48 @@
@end
+#if PLATFORM(IOS)
+@interface WKVideoFullScreenViewController : UIViewController
+- (instancetype)initWithAVPlayerViewController:(AVPlayerViewController *)viewController NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil NS_UNAVAILABLE;
+- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+@end
+
+@implementation WKVideoFullScreenViewController {
+ WeakObjCPtr<AVPlayerViewController> _avPlayerViewController;
+}
+
+- (instancetype)initWithAVPlayerViewController:(AVPlayerViewController *)controller
+{
+ if (!(self = [super initWithNibName:nil bundle:nil]))
+ return nil;
+
+ _avPlayerViewController = controller;
+ self.modalPresentationCapturesStatusBarAppearance = YES;
+ self.modalPresentationStyle = UIModalPresentationOverFullScreen;
+
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.view.frame = UIScreen.mainScreen.bounds;
+ self.view.backgroundColor = [UIColor blackColor];
+ [_avPlayerViewController view].autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+}
+
+- (BOOL)prefersStatusBarHidden
+{
+ return YES;
+}
+
+@end
+
+#endif
+
using namespace WebCore;
namespace WebKit {
@@ -167,6 +213,21 @@
return m_manager ? m_manager->isVisible() : false;
}
+#if PLATFORM(IOS)
+UIViewController *VideoFullscreenModelContext::presentingViewController()
+{
+ if (m_manager)
+ return m_manager->m_page->uiClient().presentingViewController();
+
+ return nullptr;
+}
+
+UIViewController *VideoFullscreenModelContext::createVideoFullscreenViewController(AVPlayerViewController *avPlayerViewController)
+{
+ return [[WKVideoFullScreenViewController alloc] initWithAVPlayerViewController:avPlayerViewController];
+}
+#endif
+
void VideoFullscreenModelContext::requestUpdateInlineRect()
{
if (m_manager)
Modified: trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm (229713 => 229714)
--- trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm 2018-03-19 21:16:31 UTC (rev 229713)
+++ trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm 2018-03-19 21:22:15 UTC (rev 229714)
@@ -439,13 +439,17 @@
interface->setIsAnimating(false);
interface->setIsFullscreen(false);
- if (interface->targetIsFullscreen())
- return;
-
RefPtr<HTMLVideoElement> videoElement = model->videoElement();
if (!videoElement)
return;
+ dispatch_async(dispatch_get_main_queue(), [protectedThis = makeRefPtr(this), videoElement] {
+ videoElement->didBecomeFullscreenElement();
+ });
+
+ if (interface->targetIsFullscreen())
+ return;
+
// exit fullscreen now if it was previously requested during an animation.
dispatch_async(dispatch_get_main_queue(), [protectedThis = makeRefPtr(this), videoElement] {
if (protectedThis->m_page)