Title: [240928] trunk
Revision
240928
Author
you...@apple.com
Date
2019-02-04 09:37:01 -0800 (Mon, 04 Feb 2019)

Log Message

Capture state should be managed consistently when doing process swapping
https://bugs.webkit.org/show_bug.cgi?id=194122
<rdar://problem/47609293>

Reviewed by Eric Carlson.

Source/WebKit:

When doing PSON, WebPageProxy::resetState is called.
It resets the media state, but does not call the client delegates.
Instead of directly updating the media state, call the routine used to update it so that client delegates are called.

Covered by new API test and layout test.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _mediaCaptureState]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::resetState):
(WebKit::WebPageProxy::isPlayingMediaDidChange):
(WebKit::WebPageProxy::updatePlayingMediaDidChange):
* UIProcess/WebPageProxy.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[GetUserMediaUIDelegate _webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:]):
(-[GetUserMediaUIDelegate _webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:]):
(-[GetUserMediaUIDelegate _webView:mediaCaptureStateDidChange:]):
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::isDoingMediaCapture const):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::isDoingMediaCapture const):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::isDoingMediaCapture const):

Modified Paths

Added Paths

Diff

Added: trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping-expected.txt (0 => 240928)


--- trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping-expected.txt	2019-02-04 17:37:01 UTC (rev 240928)
@@ -0,0 +1 @@
+PASS

Added: trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping.html (0 => 240928)


--- trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/webrtc/getUserMedia-processSwapping.html	2019-02-04 17:37:01 UTC (rev 240928)
@@ -0,0 +1,41 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>getUserMedia on process swapping</title>
+<body>
+<video id="local"></video>
+<script src=""
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+async function getUserMediaAndNavigate()
+{
+    local.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
+    await local.play();
+    await new Promise(resolve => setTimeout(resolve, 1000));
+    if (window.testRunner && !testRunner.isDoingMediaCapture) {
+        document.body.innerHTML = "FAIL: no capture state";
+        testRunner.notifyDone();
+        return;
+    }
+    window.location = get_host_info().HTTPS_ORIGIN + "/WebKit/webrtc/getUserMedia-processSwapping.html";
+}
+
+function validateMediaCaptureStateAfterNavigation()
+{
+    if (!window.testRunner) {
+        document.body.innerHTML = "FAIL: Need testRunner API";
+        return;
+    }
+    document.body.innerHTML = testRunner.isDoingMediaCapture ? "FAIL" : "PASS";
+    testRunner.notifyDone();
+}
+
+if (window.location.protocol === "http:")
+    getUserMediaAndNavigate();
+else
+    validateMediaCaptureStateAfterNavigation();
+</script>
+</body>

Modified: trunk/Source/WebKit/ChangeLog (240927 => 240928)


--- trunk/Source/WebKit/ChangeLog	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Source/WebKit/ChangeLog	2019-02-04 17:37:01 UTC (rev 240928)
@@ -1,3 +1,26 @@
+2019-02-04  Youenn Fablet  <you...@apple.com>
+
+        Capture state should be managed consistently when doing process swapping
+        https://bugs.webkit.org/show_bug.cgi?id=194122
+        <rdar://problem/47609293>
+
+        Reviewed by Eric Carlson.
+
+        When doing PSON, WebPageProxy::resetState is called.
+        It resets the media state, but does not call the client delegates.
+        Instead of directly updating the media state, call the routine used to update it so that client delegates are called.
+
+        Covered by new API test and layout test.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _mediaCaptureState]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::resetState):
+        (WebKit::WebPageProxy::isPlayingMediaDidChange):
+        (WebKit::WebPageProxy::updatePlayingMediaDidChange):
+        * UIProcess/WebPageProxy.h:
+
 2019-02-04  Antoine Quint  <grao...@apple.com>
 
         Use a dedicated type instead of int32_t for pointer identifiers

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (240927 => 240928)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-02-04 17:37:01 UTC (rev 240928)
@@ -6707,7 +6707,7 @@
         editCommand->invalidate();
 
     m_activePopupMenu = nullptr;
-    m_mediaState = MediaProducer::IsNotPlaying;
+    updatePlayingMediaDidChange(MediaProducer::IsNotPlaying);
 
 #if ENABLE(POINTER_LOCK)
     requestPointerUnlock();
@@ -7762,7 +7762,11 @@
     ASSERT(focusManager);
     focusManager->updatePlaybackAttributesFromMediaState(this, sourceElementID, newState);
 #endif
+    updatePlayingMediaDidChange(newState);
+}
 
+void WebPageProxy::updatePlayingMediaDidChange(MediaProducer::MediaStateFlags newState)
+{
     if (newState == m_mediaState)
         return;
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (240927 => 240928)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-02-04 17:37:01 UTC (rev 240928)
@@ -1248,6 +1248,7 @@
 
     bool isPlayingAudio() const { return !!(m_mediaState & WebCore::MediaProducer::IsPlayingAudio); }
     void isPlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags, uint64_t);
+    void updatePlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags);
     bool hasActiveAudioStream() const { return m_mediaState & WebCore::MediaProducer::HasActiveAudioCaptureDevice; }
     bool hasActiveVideoStream() const { return m_mediaState & WebCore::MediaProducer::HasActiveVideoCaptureDevice; }
     WebCore::MediaProducer::MediaStateFlags mediaStateFlags() const { return m_mediaState; }

Modified: trunk/Tools/ChangeLog (240927 => 240928)


--- trunk/Tools/ChangeLog	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/ChangeLog	2019-02-04 17:37:01 UTC (rev 240928)
@@ -1,3 +1,27 @@
+2019-02-04  Youenn Fablet  <you...@apple.com>
+
+        Capture state should be managed consistently when doing process swapping
+        https://bugs.webkit.org/show_bug.cgi?id=194122
+        <rdar://problem/47609293>
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[GetUserMediaUIDelegate _webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:]):
+        (-[GetUserMediaUIDelegate _webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:]):
+        (-[GetUserMediaUIDelegate _webView:mediaCaptureStateDidChange:]):
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::isDoingMediaCapture const):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::isDoingMediaCapture const):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
+        (WTR::TestController::isDoingMediaCapture const):
+
 2019-02-03  Fujii Hironori  <hironori.fu...@sony.com>
 
         [Win] WebKitTestRunners is failing to create the IndexedDB directory.

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (240927 => 240928)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-02-04 17:37:01 UTC (rev 240928)
@@ -28,6 +28,7 @@
 #import "PlatformUtilities.h"
 #import "Test.h"
 #import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
 #import <WebKit/WKContentRuleListStore.h>
 #import <WebKit/WKNavigationDelegatePrivate.h>
 #import <WebKit/WKNavigationPrivate.h>
@@ -4719,4 +4720,88 @@
     done = false;
 }
 
+static bool isCapturing = false;
+@interface GetUserMediaUIDelegate : NSObject<WKUIDelegate>
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler;
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler;
+- (void)_webView:(WKWebView *)webView mediaCaptureStateDidChange:(_WKMediaCaptureState)state;
+@end
+
+@implementation GetUserMediaUIDelegate
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler
+{
+    decisionHandler(YES);
+}
+
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler
+{
+    decisionHandler(@"0x987654321", YES);
+}
+
+- (void)_webView:(WKWebView *)webView mediaCaptureStateDidChange:(_WKMediaCaptureState)state
+{
+    isCapturing = state == _WKMediaCaptureStateActiveCamera;
+}
+@end
+
+static const char* getUserMediaBytes = R"PSONRESOURCE(
+<head>
+<body>
+<script>
+navigator.mediaDevices.getUserMedia({video: true});
+</script>
+</body>
+</head>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, GetUserMediaCaptureState)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    processPoolConfiguration.get().processSwapsOnNavigation = YES;
+    processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
+
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto preferences = [webViewConfiguration.get() preferences];
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mediaDevicesEnabled = YES;
+    preferences._mockCaptureDevicesEnabled = YES;
+
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/getUserMedia.html" toData:getUserMediaBytes];
+    [handler addMappingFromURLString:@"pson://www.apple.org/test.html" toData:""];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    auto uiDelegate = adoptNS([[GetUserMediaUIDelegate alloc] init]);
+    [webView setUIDelegate: uiDelegate.get()];
+
+    auto request = adoptNS([NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/getUserMedia.html"]]);
+    [webView loadRequest:request.get()];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    TestWebKitAPI::Util::run(&isCapturing);
+
+    auto pid1 = [webView _webProcessIdentifier];
+
+    request = adoptNS([NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.org/test.html"]]);
+    [webView loadRequest:request.get()];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid2 = [webView _webProcessIdentifier];
+
+    EXPECT_FALSE(isCapturing);
+    EXPECT_FALSE(pid1 == pid2);
+}
+
 #endif // WK_API_ENABLED

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2019-02-04 17:37:01 UTC (rev 240928)
@@ -217,6 +217,7 @@
     void setUserMediaPersistentPermissionForOrigin(boolean permission, DOMString origin, DOMString parentOrigin);
     unsigned long userMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin);
     void resetUserMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin);
+    readonly attribute boolean isDoingMediaCapture;
 
     // Audio testing.
     [PassContext] void setAudioResult(object data);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-02-04 17:37:01 UTC (rev 240928)
@@ -1094,6 +1094,15 @@
     InjectedBundle::singleton().resetUserMediaPermission();
 }
 
+bool TestRunner::isDoingMediaCapture() const
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsDoingMediaCapture"));
+    WKTypeRef returnData = nullptr;
+    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), nullptr, &returnData);
+    ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
+    return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
+}
+
 void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
 {
     WKRetainPtr<WKStringRef> originWK = toWK(origin);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-02-04 17:37:01 UTC (rev 240928)
@@ -319,6 +319,7 @@
     void setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin);
     unsigned userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const;
     void resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin);
+    bool isDoingMediaCapture() const;
 
     void setPageVisibility(JSStringRef state);
     void resetPageVisibility();

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2019-02-04 17:37:01 UTC (rev 240928)
@@ -2900,6 +2900,12 @@
 {
     // FIXME: To implement.
 }
+
+bool TestController::isDoingMediaCapture() const
+{
+    return false;
+}
+
 #endif
 
 struct ResourceStatisticsCallbackContext {

Modified: trunk/Tools/WebKitTestRunner/TestController.h (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/TestController.h	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2019-02-04 17:37:01 UTC (rev 240928)
@@ -287,6 +287,8 @@
     void setShouldDismissJavaScriptAlertsAsynchronously(bool);
     void handleJavaScriptAlert(WKPageRunJavaScriptAlertResultListenerRef);
 
+    bool isDoingMediaCapture() const;
+
 private:
     WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
     WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration(const TestOptions&) const;

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2019-02-04 17:37:01 UTC (rev 240928)
@@ -1034,6 +1034,10 @@
         WKRetainPtr<WKUInt64Ref> result(AdoptWK, WKUInt64Create(count));
         return result;
     }
+    if (WKStringIsEqualToUTF8CString(messageName, "IsDoingMediaCapture")) {
+        WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(TestController::singleton().isDoingMediaCapture()));
+        return result;
+    }
 
     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsDebugMode")) {
         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());

Modified: trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm (240927 => 240928)


--- trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm	2019-02-04 16:22:49 UTC (rev 240927)
+++ trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm	2019-02-04 17:37:01 UTC (rev 240928)
@@ -414,4 +414,13 @@
 #endif
 }
 
+bool TestController::isDoingMediaCapture() const
+{
+#if WK_API_ENABLED
+    return m_mainWebView->platformView()._mediaCaptureState != _WKMediaCaptureStateNone;
+#else
+    return false;
+#endif
+}
+
 } // namespace WTR
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to