Media controls don't appear when pausing a small autoplaying video
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Jul 2016 19:25:16 +0000 (19:25 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Jul 2016 19:25:16 +0000 (19:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=159972
<rdar://problem/27180657>

Reviewed by Beth Dakin.

Source/WebCore:

When pausing an autoplaying video, remove behavior restrictions for the
initial user gesture and show media controls.

New WebKit API test. See VideoControlsManagerSingleSmallAutoplayingVideo.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::pause):

Tools:

Adds a new test that verifies media controls show up when pausing a small autoplayed video. Also adds mechanisms
for simulating basic user interaction in VideoControlsManager.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm:
(-[WKWebView mouseDownAtPoint:]):
(-[DidPlayMessageHandler userContentController:didReceiveScriptMessage:]):
(-[OnLoadMessageHandler initWithWKWebView:handler:]):
(-[OnLoadMessageHandler userContentController:didReceiveScriptMessage:]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@203464 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html [new file with mode: 0644]

index 7a128a4..fac435b 100644 (file)
@@ -1,3 +1,19 @@
+2016-07-20  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Media controls don't appear when pausing a small autoplaying video
+        https://bugs.webkit.org/show_bug.cgi?id=159972
+        <rdar://problem/27180657>
+
+        Reviewed by Beth Dakin.
+
+        When pausing an autoplaying video, remove behavior restrictions for the
+        initial user gesture and show media controls.
+
+        New WebKit API test. See VideoControlsManagerSingleSmallAutoplayingVideo.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::pause):
+
 2016-07-20  Chris Dumez  <cdumez@apple.com>
 
         Fix null handling of HTMLMediaElement.mediaGroup
index dccd68e..151c8db 100644 (file)
@@ -3155,6 +3155,9 @@ void HTMLMediaElement::pause()
     if (!m_mediaSession->playbackPermitted(*this))
         return;
 
+    if (ScriptController::processingUserGestureForMedia())
+        removeBehaviorsRestrictionsAfterFirstUserGesture();
+
     pauseInternal();
 }
 
index 169694c..ab1eb75 100644 (file)
@@ -1,3 +1,23 @@
+2016-07-20  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Media controls don't appear when pausing a small autoplaying video
+        https://bugs.webkit.org/show_bug.cgi?id=159972
+        <rdar://problem/27180657>
+
+        Reviewed by Beth Dakin.
+
+        Adds a new test that verifies media controls show up when pausing a small autoplayed video. Also adds mechanisms
+        for simulating basic user interaction in VideoControlsManager.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2Cocoa/VideoControlsManager.mm:
+        (-[WKWebView mouseDownAtPoint:]):
+        (-[DidPlayMessageHandler userContentController:didReceiveScriptMessage:]):
+        (-[OnLoadMessageHandler initWithWKWebView:handler:]):
+        (-[OnLoadMessageHandler userContentController:didReceiveScriptMessage:]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html: Added.
+
 2016-07-20  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] MathML fonts are not found.
index eae30c8..e03f13d 100644 (file)
@@ -51,6 +51,7 @@
                2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
                2DC4CF771D2D9DD800ECCC94 /* DataDetection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DC4CF761D2D9DD800ECCC94 /* DataDetection.mm */; };
                2DD7D3AF178227B30026E1E3 /* lots-of-text-vertical-lr.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2DD7D3AE178227AC0026E1E3 /* lots-of-text-vertical-lr.html */; };
+               2E14A5291D3FE96B0010F35B /* autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */; };
                2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */; };
                2E7765CF16C4D81100BA2BB1 /* mainMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E7765CE16C4D81100BA2BB1 /* mainMac.mm */; };
                33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; };
                                5C9E59411D3EB5AC00E3C62E /* ApplicationCache.db in Copy Resources */,
                                5C9E59421D3EB5AC00E3C62E /* ApplicationCache.db-shm in Copy Resources */,
                                5C9E59431D3EB5AC00E3C62E /* ApplicationCache.db-wal in Copy Resources */,
+                               2E14A5291D3FE96B0010F35B /* autoplaying-video-with-audio.html in Copy Resources */,
                                7CCB99231D3B4A46003922F6 /* open-multiple-external-url.html in Copy Resources */,
                                932AE53D1D371047005DFFAF /* focus-inputs.html in Copy Resources */,
                                46C519E61D3563FD00DAA51A /* LocalStorageNullEntries.html in Copy Resources */,
                2DD355351BD08378005DF4A7 /* AutoLayoutIntegration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoLayoutIntegration.mm; sourceTree = "<group>"; };
                2DD7D3A9178205D00026E1E3 /* ResizeReversePaginatedWebView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResizeReversePaginatedWebView.cpp; sourceTree = "<group>"; };
                2DD7D3AE178227AC0026E1E3 /* lots-of-text-vertical-lr.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "lots-of-text-vertical-lr.html"; sourceTree = "<group>"; };
+               2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
                2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainIOS.mm; sourceTree = "<group>"; };
                2E7765CE16C4D81100BA2BB1 /* mainMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mainMac.mm; sourceTree = "<group>"; };
                333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = "<group>"; };
                                5C9E593E1D3EB1DE00E3C62E /* ApplicationCache.db */,
                                5C9E593F1D3EB1DE00E3C62E /* ApplicationCache.db-shm */,
                                5C9E59401D3EB1DE00E3C62E /* ApplicationCache.db-wal */,
+                               2E14A5281D3FE8B80010F35B /* autoplaying-video-with-audio.html */,
                                93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */,
                                A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */,
                                5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */,
index 726f7f2..0d406f4 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #import "PlatformUtilities.h"
+#import <Carbon/Carbon.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 static bool testedControlsManagerAfterPlaying;
 static bool receivedScriptMessage;
 
+@interface WKWebView (UserInteraction)
+
+- (void)mouseDownAtPoint:(NSPoint)point;
+
+@end
+
+@implementation WKWebView (UserInteraction)
+
+- (void)mouseDownAtPoint:(NSPoint)point {
+    [self mouseDown:[NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:NSMakePoint(point.x, point.y) modifierFlags:0 timestamp:GetCurrentEventTime() windowNumber:0 context:[NSGraphicsContext currentContext] eventNumber:0 clickCount:0 pressure:0]];
+}
+
+@end
+
 @interface DidPlayMessageHandler : NSObject <WKScriptMessageHandler> {
     RetainPtr<WKWebView> _webView;
 }
@@ -61,7 +76,7 @@ static bool receivedScriptMessage;
     receivedScriptMessage = true;
 
     NSString *bodyString = (NSString *)[message body];
-    if ([bodyString isEqualToString:@"playing"]) {
+    if ([bodyString isEqualToString:@"playing"] || [bodyString isEqualToString:@"paused"]) {
         BOOL hasControlsManager = [_webView _hasActiveVideoForControlsManager];
         if (self.expectedToHaveControlsManager)
             EXPECT_TRUE(hasControlsManager);
@@ -72,6 +87,40 @@ static bool receivedScriptMessage;
 }
 @end
 
+@interface OnLoadMessageHandler : NSObject <WKScriptMessageHandler> {
+    RetainPtr<WKWebView> _webView;
+}
+
+@property (nonatomic, strong) dispatch_block_t onloadHandler;
+
+- (instancetype)initWithWKWebView:(WKWebView*)webView handler:(dispatch_block_t)handler;
+@end
+
+@implementation OnLoadMessageHandler
+
+- (instancetype)initWithWKWebView:(WKWebView*)webView handler:(dispatch_block_t)handler
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _webView = webView;
+    _onloadHandler = handler;
+
+    return self;
+}
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    if (![(NSString *)[message body] isEqualToString:@"loaded"])
+        return;
+
+    if (_onloadHandler)
+        _onloadHandler();
+
+    _onloadHandler = nil;
+}
+@end
+
 namespace TestWebKitAPI {
 
 TEST(VideoControlsManager, VideoControlsManagerSingleLargeVideo)
@@ -116,6 +165,31 @@ TEST(VideoControlsManager, VideoControlsManagerSingleSmallVideo)
     TestWebKitAPI::Util::run(&receivedScriptMessage);
 }
 
+TEST(VideoControlsManager, VideoControlsManagerSingleSmallAutoplayingVideo)
+{
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]);
+    RetainPtr<DidPlayMessageHandler> playbackHandler = adoptNS([[DidPlayMessageHandler alloc] initWithWKWebView:webView.get()]);
+    [[configuration userContentController] addScriptMessageHandler:playbackHandler.get() name:@"playingHandler"];
+
+    RetainPtr<NSWindow> window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]);
+    [[window contentView] addSubview:webView.get()];
+
+    RetainPtr<OnLoadMessageHandler> onloadHandler = adoptNS([[OnLoadMessageHandler alloc] initWithWKWebView:webView.get() handler:^() {
+        [webView mouseDownAtPoint:NSMakePoint(50, 50)];
+    }]);
+    [[configuration userContentController] addScriptMessageHandler:onloadHandler.get() name:@"onloadHandler"];
+
+    // A small video should have a controls manager after the first user gesture, which includes pausing the video. The expectation is YES.
+    [playbackHandler setExpectedToHaveControlsManager:YES];
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplaying-video-with-audio" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&testedControlsManagerAfterPlaying);
+    TestWebKitAPI::Util::run(&receivedScriptMessage);
+}
+
 TEST(VideoControlsManager, VideoControlsManagerSingleLargeVideoWithoutAudio)
 {
     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html
new file mode 100644 (file)
index 0000000..a3c2d5b
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script>
+    var timeout;
+
+    function beginTest() {
+        timeout = window.setTimeout(stillPlaying, 5000);
+        window.addEventListener("mousedown", pauseVideo);
+        try {
+            window.webkit.messageHandlers.onloadHandler.postMessage('loaded');
+        } catch(e) { }
+    }
+
+    function pauseVideo() {
+        document.getElementsByTagName('video')[0].pause();
+        window.clearTimeout(timeout);
+    }
+
+    function handlePaused() {
+        // Wait until the next runloop to allow media controls to update.
+        setTimeout(function() {
+            try {
+                window.webkit.messageHandlers.playingHandler.postMessage('paused');
+            } catch(e) { }
+        }, 0);
+    }
+
+    function stillPlaying() {
+        try {
+            window.webkit.messageHandlers.playingHandler.postMessage('playing');
+        } catch(e) { }
+    }
+
+   </script>
+</head>
+<body onload="beginTest()">
+    <video controls autoplay src="video-with-audio.mp4" webkit-playsinline onpause="handlePaused()"></video>
+</body>
+</html>