Diff
Modified: trunk/Source/WebKit/ChangeLog (246927 => 246928)
--- trunk/Source/WebKit/ChangeLog 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/ChangeLog 2019-06-28 17:39:53 UTC (rev 246928)
@@ -1,3 +1,35 @@
+2019-06-28 Jer Noble <jer.no...@apple.com>
+
+ Add new -[WKWebView _closeAllMediaPresentations] SPI
+ https://bugs.webkit.org/show_bug.cgi?id=199294
+ <rdar://problem/51965958>
+
+ Reviewed by Alex Christensen.
+
+ Add a new SPI that will close all out-of-window media presentations, including
+ picture-in-picture, video fullscreen, and element fullscreen.
+
+ Drive-by fixes:
+
+ + -[WKApplicationStateTrackingView didMoveToWindow] incorrectly assumes that a WKWebView will
+ never be moved frome one window to another, and asserts.
+
+ + -[WKFullScreenWindowController close] doesn't fire the correct 'webkitfullscreenchange' event
+ when called in the middle of animating into fullscreen.
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _closeAllMediaPresentations]):
+ * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.h:
+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.mm:
+ (WebKit::VideoFullscreenManagerProxy::forEachSession):
+ * UIProcess/ios/WKApplicationStateTrackingView.mm:
+ (-[WKApplicationStateTrackingView didMoveToWindow]):
+ * UIProcess/mac/WKFullScreenWindowController.h:
+ * UIProcess/mac/WKFullScreenWindowController.mm:
+ (-[WKFullScreenWindowController exitFullScreenImmediately]):
+ (-[WKFullScreenWindowController close]):
+
2019-06-28 Antti Koivisto <an...@apple.com>
[iOS Scrolling] Propagate scrolls to non-nested UIScrollViews
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-06-28 17:39:53 UTC (rev 246928)
@@ -54,6 +54,7 @@
#import "UIDelegate.h"
#import "UserMediaProcessManager.h"
#import "VersionChecks.h"
+#import "VideoFullscreenManagerProxy.h"
#import "ViewGestureController.h"
#import "ViewSnapshotStore.h"
#import "WKBackForwardListInternal.h"
@@ -4735,6 +4736,18 @@
#endif
}
+- (void)_closeAllMediaPresentations
+{
+ if (auto videoFullscreenManager = _page->videoFullscreenManager()) {
+ videoFullscreenManager->forEachSession([] (auto& model, auto& interface) {
+ model.requestFullscreenMode(WebCore::HTMLMediaElementEnums::VideoFullscreenModeNone);
+ });
+ }
+
+ if (auto fullScreenManager = _page->fullScreenManager(); fullScreenManager && fullScreenManager->isFullScreen())
+ fullScreenManager->close();
+}
+
- (void)_stopAllMediaPlayback
{
_page->stopAllMediaPlayback();
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2019-06-28 17:39:53 UTC (rev 246928)
@@ -423,6 +423,7 @@
- (void)_stopAllMediaPlayback;
- (void)_suspendAllMediaPlayback;
- (void)_resumeAllMediaPlayback;
+- (void)_closeAllMediaPresentations;
- (void)_requestTextInputContextsInRect:(CGRect)rect completionHandler:(void(^)(NSArray<_WKTextInputContext *> *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_focusTextInputContext:(_WKTextInputContext *)textInputElement completionHandler:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
Modified: trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h 2019-06-28 17:39:53 UTC (rev 246928)
@@ -138,6 +138,8 @@
PlatformVideoFullscreenInterface* controlsManagerInterface();
+ void forEachSession(Function<void(WebCore::VideoFullscreenModel&, PlatformVideoFullscreenInterface&)>&&);
+
private:
friend class VideoFullscreenModelContext;
Modified: trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2019-06-28 17:39:53 UTC (rev 246928)
@@ -466,6 +466,30 @@
m_clientCounts.set(contextId, clientCount);
}
+void VideoFullscreenManagerProxy::forEachSession(Function<void(VideoFullscreenModel&, PlatformVideoFullscreenInterface&)>&& callback)
+{
+ if (m_contextMap.isEmpty())
+ return;
+
+ Vector<ModelInterfaceTuple> values;
+ values.reserveInitialCapacity(m_contextMap.size());
+ for (auto& value : m_contextMap.values())
+ values.uncheckedAppend(value);
+
+ for (auto& value : values) {
+ RefPtr<VideoFullscreenModelContext> model;
+ RefPtr<PlatformVideoFullscreenInterface> interface;
+ std::tie(model, interface) = value;
+
+ ASSERT(model);
+ ASSERT(interface);
+ if (!model || !interface)
+ continue;
+
+ callback(*model, *interface);
+ }
+}
+
#pragma mark Messages from VideoFullscreenManager
void VideoFullscreenManagerProxy::setupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, const WebCore::IntRect& initialRect, float hostingDeviceScaleFactor, HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode, bool allowsPictureInPicture, bool standby)
Modified: trunk/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/ios/WKApplicationStateTrackingView.mm 2019-06-28 17:39:53 UTC (rev 246928)
@@ -62,10 +62,9 @@
- (void)didMoveToWindow
{
- if (!self._contentView.window)
+ if (!self._contentView.window || _applicationStateTracker)
return;
- ASSERT(!_applicationStateTracker);
_applicationStateTracker = std::make_unique<WebKit::ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationDidFinishSnapshottingAfterEnteringBackground), @selector(_applicationWillEnterForeground));
if (_lastObservedStateWasBackground && ![self isBackground])
Modified: trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.h (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.h 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.h 2019-06-28 17:39:53 UTC (rev 246928)
@@ -77,6 +77,7 @@
- (void)enterFullScreen:(NSScreen *)screen;
- (void)exitFullScreen;
+- (void)exitFullScreenImmediately;
- (void)requestExitFullScreen;
- (void)close;
- (void)beganEnterFullScreenWithInitialFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame;
Modified: trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm (246927 => 246928)
--- trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm 2019-06-28 17:39:53 UTC (rev 246928)
@@ -420,6 +420,18 @@
[self _manager]->willExitFullScreen();
}
+- (void)exitFullScreenImmediately
+{
+ if (![self isFullScreen])
+ return;
+
+ [self _manager]->requestExitFullScreen();
+ [_webViewPlaceholder setExitWarningVisible:NO];
+ [self _manager]->willExitFullScreen();
+ _fullScreenState = ExitingFullScreen;
+ [self finishedExitFullScreenAnimation:YES];
+}
+
- (void)requestExitFullScreen
{
[self _manager]->requestExitFullScreen();
@@ -581,7 +593,7 @@
// normal exit full screen sequence, but don't wait to be called back
// in response.
if ([self isFullScreen])
- [self exitFullScreen];
+ [self exitFullScreenImmediately];
if (_fullScreenState == ExitingFullScreen)
[self finishedExitFullScreenAnimation:YES];
Modified: trunk/Tools/ChangeLog (246927 => 246928)
--- trunk/Tools/ChangeLog 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Tools/ChangeLog 2019-06-28 17:39:53 UTC (rev 246928)
@@ -1,3 +1,15 @@
+2019-06-28 Jer Noble <jer.no...@apple.com>
+
+ Add new -[WKWebView _closeAllMediaPresentations] SPI
+ https://bugs.webkit.org/show_bug.cgi?id=199294
+ <rdar://problem/51965958>
+
+ Reviewed by Alex Christensen.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewCloseAllMediaPresentations.mm: Added.
+ (TEST):
+
2019-06-28 Sihui Liu <sihui_...@apple.com>
Add a regression test for change r246901
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (246927 => 246928)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-06-28 17:35:29 UTC (rev 246927)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-06-28 17:39:53 UTC (rev 246928)
@@ -851,6 +851,7 @@
CDC9442E1EF1FC080059C3C4 /* MediaStreamTrackDetached.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDC9442C1EF1FC080059C3C4 /* MediaStreamTrackDetached.mm */; };
CDC9442F1EF205D60059C3C4 /* mediastreamtrack-detached.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDC9442B1EF1FBD20059C3C4 /* mediastreamtrack-detached.html */; };
CDCFA7AA1E45183200C2433D /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFA7A91E45122F00C2433D /* SampleMap.cpp */; };
+ CDD68F0D22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDD68F0C22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm */; };
CDE195B51CFE0B880053D256 /* FullscreenTopContentInset.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDE195B21CFE0ADE0053D256 /* FullscreenTopContentInset.html */; };
CDF0B78A216D48DC00421ECC /* CloseWebViewDuringEnterFullscreen.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDF0B789216D484300421ECC /* CloseWebViewDuringEnterFullscreen.mm */; };
CDF92237216D186400647AA7 /* CloseWebViewAfterEnterFullscreen.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDF92236216D186400647AA7 /* CloseWebViewAfterEnterFullscreen.mm */; };
@@ -2250,6 +2251,7 @@
CDC9442B1EF1FBD20059C3C4 /* mediastreamtrack-detached.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "mediastreamtrack-detached.html"; sourceTree = "<group>"; };
CDC9442C1EF1FC080059C3C4 /* MediaStreamTrackDetached.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaStreamTrackDetached.mm; sourceTree = "<group>"; };
CDCFA7A91E45122F00C2433D /* SampleMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SampleMap.cpp; sourceTree = "<group>"; };
+ CDD68F0C22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewCloseAllMediaPresentations.mm; sourceTree = "<group>"; };
CDE195B21CFE0ADE0053D256 /* FullscreenTopContentInset.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenTopContentInset.html; sourceTree = "<group>"; };
CDE195B31CFE0ADE0053D256 /* FullscreenTopContentInset.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FullscreenTopContentInset.mm; sourceTree = "<group>"; };
CDF0B789216D484300421ECC /* CloseWebViewDuringEnterFullscreen.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CloseWebViewDuringEnterFullscreen.mm; sourceTree = "<group>"; };
@@ -2813,6 +2815,7 @@
93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */,
CD7F89DB22A86CDA00D683AE /* WKWebViewSuspendAllMediaPlayback.mm */,
9984FACA1CFFAEEE008D198C /* WKWebViewTextInput.mm */,
+ CDD68F0C22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm */,
);
name = "WebKit Cocoa";
path = WebKitCocoa;
@@ -4350,6 +4353,7 @@
CA38459620AE17A900990D3B /* LocalStorageDatabaseTracker.mm in Sources */,
46C519DA1D355AB200DAA51A /* LocalStorageNullEntries.mm in Sources */,
8C10AF99206467A90018FD90 /* LocalStoragePersistence.mm in Sources */,
+ CDD68F0D22C18317000CF0AE /* WKWebViewCloseAllMediaPresentations.mm in Sources */,
7A6A2C701DCCFA8C00C0D085 /* LocalStorageQuirkTest.mm in Sources */,
076E507F1F4513D6006E9F5A /* Logging.cpp in Sources */,
CE1866491F72E8F100A0CAB6 /* MarkedText.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewCloseAllMediaPresentations.mm (0 => 246928)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewCloseAllMediaPresentations.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewCloseAllMediaPresentations.mm 2019-06-28 17:39:53 UTC (rev 246928)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 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. AND ITS CONTRIBUTORS ``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 ITS 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 "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <wtf/RetainPtr.h>
+
+TEST(WKWebViewCloseAllMediaPresentations, PictureInPicture)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ configuration.get().preferences._allowsPictureInPictureMediaPlayback = YES;
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get() addToWindow:YES]);
+
+ [webView synchronouslyLoadHTMLString:@"<video src="" webkit-playsinline></video>"];
+ [webView objectByEvaluatingJavaScript:@"document.querySelector('video').addEventListener('webkitpresentationmodechanged', event => { window.webkit.messageHandlers.testHandler.postMessage('presentationmodechanged'); });"];
+
+ __block bool presentationModeChanged = false;
+ [webView performAfterReceivingMessage:@"presentationmodechanged" action:^{ presentationModeChanged = true; }];
+
+ [webView objectByEvaluatingJavaScriptWithUserGesture:@"document.querySelector('video').webkitSetPresentationMode('picture-in-picture')"];
+
+ TestWebKitAPI::Util::run(&presentationModeChanged);
+
+ presentationModeChanged = false;
+ [webView performAfterReceivingMessage:@"presentationmodechanged" action:^{ presentationModeChanged = true; }];
+
+ [webView _closeAllMediaPresentations];
+
+ TestWebKitAPI::Util::run(&presentationModeChanged);
+
+ EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('video').webkitPresentationMode"].UTF8String, "inline");
+}
+
+TEST(WKWebViewCloseAllMediaPresentations, VideoFullscreen)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ configuration.get().preferences._fullScreenEnabled = YES;
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get() addToWindow:YES]);
+
+ [webView synchronouslyLoadHTMLString:@"<video src="" webkit-playsinline></video>"];
+ [webView objectByEvaluatingJavaScript:@"document.querySelector('video').addEventListener('webkitpresentationmodechanged', event => { window.webkit.messageHandlers.testHandler.postMessage('presentationmodechanged'); });"];
+
+ __block bool presentationModeChanged = false;
+ [webView performAfterReceivingMessage:@"presentationmodechanged" action:^{ presentationModeChanged = true; }];
+
+ [webView objectByEvaluatingJavaScriptWithUserGesture:@"document.querySelector('video').webkitEnterFullscreen()"];
+
+ TestWebKitAPI::Util::run(&presentationModeChanged);
+
+ presentationModeChanged = false;
+ [webView performAfterReceivingMessage:@"presentationmodechanged" action:^{ presentationModeChanged = true; }];
+
+ [webView _closeAllMediaPresentations];
+
+ TestWebKitAPI::Util::run(&presentationModeChanged);
+
+ EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('video').webkitPresentationMode"].UTF8String, "inline");
+}
+
+TEST(WKWebViewCloseAllMediaPresentations, ElementFullscreen)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ configuration.get().preferences._fullScreenEnabled = YES;
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get() addToWindow:YES]);
+
+ [webView synchronouslyLoadHTMLString:@"<div id=\"target\" style=\"width:100px;height:100px;background-color:red\"></div>"];
+ [webView objectByEvaluatingJavaScript:@"document.querySelector('#target').addEventListener('webkitfullscreenchange', event => { window.webkit.messageHandlers.testHandler.postMessage('fullscreenchange'); });"];
+
+ __block bool fullscreenModeChanged = false;
+ [webView performAfterReceivingMessage:@"fullscreenchange" action:^{ fullscreenModeChanged = true; }];
+
+ [webView objectByEvaluatingJavaScriptWithUserGesture:@"document.querySelector('#target').webkitRequestFullscreen()"];
+
+ TestWebKitAPI::Util::run(&fullscreenModeChanged);
+
+ fullscreenModeChanged = false;
+ [webView performAfterReceivingMessage:@"fullscreenchange" action:^{ fullscreenModeChanged = true; }];
+
+ [webView _closeAllMediaPresentations];
+
+ TestWebKitAPI::Util::run(&fullscreenModeChanged);
+
+ EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"document.webkitFullscreenElement"].UTF8String, "<null>");
+}