Title: [219135] trunk
Revision
219135
Author
eric.carl...@apple.com
Date
2017-07-05 10:41:47 -0700 (Wed, 05 Jul 2017)

Log Message

[MediaStream] Protect request and web view during gUM client callback
https://bugs.webkit.org/show_bug.cgi?id=174096
<rdar://problem/32833102>

Reviewed by Youenn Fablet.

Source/WebKit2:

Retain the message and WebView during asynchronous calls so they won't be
released if a navigation happens during a call to the UA for getUserMedia
or enumerateMediaDevices.

* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::requestUserMediaAuthorizationForDevices):
(WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest):
(WebKit::UIDelegate::UIClient::checkUserMediaPermissionForOrigin):

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2/GetUserMediaNavigation.mm: New test.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (219134 => 219135)


--- trunk/Source/WebKit2/ChangeLog	2017-07-05 16:51:59 UTC (rev 219134)
+++ trunk/Source/WebKit2/ChangeLog	2017-07-05 17:41:47 UTC (rev 219135)
@@ -1,3 +1,20 @@
+2017-07-05  Eric Carlson  <eric.carl...@apple.com>
+
+        [MediaStream] Protect request and web view during gUM client callback
+        https://bugs.webkit.org/show_bug.cgi?id=174096
+        <rdar://problem/32833102>
+
+        Reviewed by Youenn Fablet.
+
+        Retain the message and WebView during asynchronous calls so they won't be 
+        released if a navigation happens during a call to the UA for getUserMedia 
+        or enumerateMediaDevices.
+
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::requestUserMediaAuthorizationForDevices):
+        (WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest):
+        (WebKit::UIDelegate::UIClient::checkUserMediaPermissionForOrigin):
+
 2017-07-05  Matt Lewis  <jlew...@apple.com>
 
         Unreviewed, rolling out r219128.

Modified: trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm (219134 => 219135)


--- trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm	2017-07-05 16:51:59 UTC (rev 219134)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm	2017-07-05 17:41:47 UTC (rev 219135)
@@ -403,6 +403,32 @@
 }
 #endif
 
+static void requestUserMediaAuthorizationForDevices(const WebKit::WebFrameProxy& frame, WebKit::UserMediaPermissionRequestProxy& request, id <WKUIDelegatePrivate> delegate, WKWebView& webView)
+{
+    auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([protectedRequest = makeRef(request)](BOOL authorized) {
+        if (!authorized) {
+            protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
+            return;
+        }
+        const String& videoDeviceUID = protectedRequest->requiresVideo() ? protectedRequest->videoDeviceUIDs().first() : String();
+        const String& audioDeviceUID = protectedRequest->requiresAudio() ? protectedRequest->audioDeviceUIDs().first() : String();
+        protectedRequest->allow(audioDeviceUID, videoDeviceUID);
+    });
+
+    const WebFrameProxy* mainFrame = frame.page()->mainFrame();
+    WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
+    WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
+
+    _WKCaptureDevices devices = 0;
+    if (request.requiresAudio())
+        devices |= _WKCaptureDeviceMicrophone;
+    if (request.requiresVideo())
+        devices |= _WKCaptureDeviceCamera;
+
+    auto protectedWebView = RetainPtr<WKWebView>(&webView);
+    [delegate _webView:protectedWebView.get() requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:decisionHandler.get()];
+}
+
 bool UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, WebKit::UserMediaPermissionRequestProxy& request)
 {
     auto delegate = m_uiDelegate.m_delegate.get();
@@ -418,77 +444,62 @@
         return true;
     }
 
-    __block WKWebView *webView = m_uiDelegate.m_webView;
-    void (^uiDelegateAuthorizationBlock)(void) = ^ {
-        const WebFrameProxy* mainFrame = frame.page()->mainFrame();
-        WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
-        WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
+#if PLATFORM(IOS)
+    auto requestCameraAuthorization = BlockPtr<void()>::fromCallable([this, &frame, protectedRequest = makeRef(request), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)]() {
 
-        _WKCaptureDevices devices = 0;
-        if (requiresAudio)
-            devices |= _WKCaptureDeviceMicrophone;
-        if (requiresVideo)
-            devices |= _WKCaptureDeviceCamera;
+        if (!protectedRequest->requiresVideo()) {
+            requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
+            return;
+        }
+        AVAuthorizationStatus cameraAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
+        switch (cameraAuthorizationStatus) {
+        case AVAuthorizationStatusAuthorized:
+            requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
+            break;
+        case AVAuthorizationStatusDenied:
+        case AVAuthorizationStatusRestricted:
+            protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
+            return;
+        case AVAuthorizationStatusNotDetermined:
+            auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([this, &frame, protectedRequest = makeRef(protectedRequest.get()), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)](BOOL authorized) {
+                if (!authorized) {
+                    protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
+                    return;
+                }
+                requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
+            });
 
-        [(id <WKUIDelegatePrivate>)delegate _webView:webView requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:^(BOOL authorized) {
-            if (!authorized) {
-                request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
-                return;
-            }
-            const String& videoDeviceUID = requiresVideo ? request.videoDeviceUIDs().first() : String();
-            const String& audioDeviceUID = requiresAudio ? request.audioDeviceUIDs().first() : String();
-            request.allow(audioDeviceUID, videoDeviceUID);
-        }];
-    };
+            [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:decisionHandler.get()];
+            break;
+        }
+    });
 
-#if PLATFORM(IOS)
-    void (^cameraAuthorizationBlock)(void) = ^ {
-        if (requiresVideo) {
-            AVAuthorizationStatus cameraAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
-            switch (cameraAuthorizationStatus) {
-            case AVAuthorizationStatusDenied:
-            case AVAuthorizationStatusRestricted:
-                request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
-                return;
-            case AVAuthorizationStatusNotDetermined:
-                [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:^(BOOL authorized) {
-                    if (!authorized) {
-                        request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
-                        return;
-                    }
-                    uiDelegateAuthorizationBlock();
-                }];
-                break;
-            default:
-                uiDelegateAuthorizationBlock();
-            }
-        } else
-            uiDelegateAuthorizationBlock();
-    };
-
     if (requiresAudio) {
         AVAuthorizationStatus microphoneAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
         switch (microphoneAuthorizationStatus) {
+        case AVAuthorizationStatusAuthorized:
+            requestCameraAuthorization();
+            break;
         case AVAuthorizationStatusDenied:
         case AVAuthorizationStatusRestricted:
             request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
             return true;
         case AVAuthorizationStatusNotDetermined:
-            [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:^(BOOL authorized) {
+            auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([protectedRequest = makeRef(request), requestCameraAuthorization](BOOL authorized) {
                 if (!authorized) {
-                    request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
+                    protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
                     return;
                 }
-                cameraAuthorizationBlock();
-            }];
+                requestCameraAuthorization();
+            });
+
+            [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:decisionHandler.get()];
             break;
-        default:
-            cameraAuthorizationBlock();
         }
     } else
-        cameraAuthorizationBlock();
+        requestCameraAuthorization();
 #else
-    uiDelegateAuthorizationBlock();
+    requestUserMediaAuthorizationForDevices(frame, request, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *m_uiDelegate.m_webView);
 #endif
 
     return true;
@@ -507,10 +518,12 @@
     WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
     WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
 
-    [(id <WKUIDelegatePrivate>)delegate _webView:webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:^(NSString *salt, BOOL authorized) {
-        request.setUserMediaAccessInfo(String(salt), authorized);
-    }];
+    auto decisionHandler = BlockPtr<void(NSString *, BOOL)>::fromCallable([protectedRequest = makeRef(request)](NSString *salt, BOOL authorized) {
+        protectedRequest->setUserMediaAccessInfo(String(salt), authorized);
+    });
 
+    [(id <WKUIDelegatePrivate>)delegate _webView:webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:decisionHandler.get()];
+
     return true;
 }
 

Modified: trunk/Tools/ChangeLog (219134 => 219135)


--- trunk/Tools/ChangeLog	2017-07-05 16:51:59 UTC (rev 219134)
+++ trunk/Tools/ChangeLog	2017-07-05 17:41:47 UTC (rev 219135)
@@ -1,3 +1,14 @@
+2017-07-05  Eric Carlson  <eric.carl...@apple.com>
+
+        [MediaStream] Protect request and web view during gUM client callback
+        https://bugs.webkit.org/show_bug.cgi?id=174096
+        <rdar://problem/32833102>
+
+        Reviewed by Youenn Fablet.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2/GetUserMediaNavigation.mm: New test.
+
 2017-07-05  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Unreviewed, guard iOS 11-dependent UIPasteboardTests to be iOS 11+ only

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (219134 => 219135)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-07-05 16:51:59 UTC (rev 219134)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-07-05 17:41:47 UTC (rev 219135)
@@ -28,6 +28,7 @@
 		0799C3491EBA2D7B003B7532 /* UserMediaDisabled.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07EDEFAC1EB9400C00D43292 /* UserMediaDisabled.mm */; };
 		0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */; };
 		07C046CA1E4262A8007201E7 /* CARingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C046C91E42573E007201E7 /* CARingBuffer.cpp */; };
+		07CE1CF31F06A7E000BF89F5 /* GetUserMediaNavigation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */; };
 		0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E751A423A5300F590F5 /* WeakObjCPtr.mm */; };
 		0F139E781A423A6B00F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
 		0F139E791A42457000F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
@@ -960,6 +961,7 @@
 		0766DD1F1A5AD5200023E3BB /* PendingAPIRequestURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingAPIRequestURL.cpp; sourceTree = "<group>"; };
 		0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = disableGetUserMedia.html; sourceTree = "<group>"; };
 		07C046C91E42573E007201E7 /* CARingBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CARingBuffer.cpp; sourceTree = "<group>"; };
+		07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetUserMediaNavigation.mm; sourceTree = "<group>"; };
 		07EDEFAC1EB9400C00D43292 /* UserMediaDisabled.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserMediaDisabled.mm; sourceTree = "<group>"; };
 		0BCD833414857CE400EA2003 /* HashMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashMap.cpp; sourceTree = "<group>"; };
 		0BCD85691485C98B00EA2003 /* SetForScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SetForScope.cpp; sourceTree = "<group>"; };
@@ -2240,6 +2242,7 @@
 				26F52EAA182872600023D412 /* Geolocation.cpp */,
 				F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */,
 				F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */,
+				07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */,
 				4BFDFFA8131477770061F24B /* HitTestResultNodeHandle.cpp */,
 				4BFDFFA61314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp */,
 				BC575AAC126E83B9006F0F12 /* InjectedBundleBasic.cpp */,
@@ -3109,6 +3112,7 @@
 				7A6A2C701DCCFA8C00C0D085 /* LocalStorageQuirkTest.mm in Sources */,
 				7CCE7EB21A411A5100447C4C /* MemoryCacheAddImageToCacheIOS.mm in Sources */,
 				7CCE7EC51A411A7E00447C4C /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */,
+				07CE1CF31F06A7E000BF89F5 /* GetUserMediaNavigation.mm in Sources */,
 				7CCE7EC61A411A7E00447C4C /* MemoryCachePruneWithinResourceLoadDelegate.mm in Sources */,
 				CDA315981ED53651009F60D3 /* MediaPlaybackSleepAssertion.mm in Sources */,
 				5C0BF88D1DD5964D00B00328 /* MemoryPressureHandler.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2/GetUserMediaNavigation.mm (0 => 219135)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/GetUserMediaNavigation.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/GetUserMediaNavigation.mm	2017-07-05 17:41:47 UTC (rev 219135)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 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"
+
+#if WK_API_ENABLED
+
+#if ENABLE(MEDIA_STREAM)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <WebKit/WKWebView.h>
+#import <WebKit/WKWebViewConfiguration.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+
+static bool okToProceed = false;
+static bool shouldReleaseInEnumerate = false;
+
+@interface NavigationWhileGetUserMediaPromptDisplayedUIDelegate : 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;
+@end
+
+@implementation NavigationWhileGetUserMediaPromptDisplayedUIDelegate
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler
+{
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
+    [webView release];
+    okToProceed = true;
+    decisionHandler(YES);
+}
+
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler
+{
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
+    if (shouldReleaseInEnumerate)
+        [webView release];
+    okToProceed = true;
+    decisionHandler(@"0x987654321", YES);
+}
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, NavigateDuringGetUserMediaPrompt)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    auto preferences = [configuration preferences];
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mediaDevicesEnabled = YES;
+    preferences._mockCaptureDevicesEnabled = YES;
+    auto webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()];
+    auto delegate = adoptNS([[NavigationWhileGetUserMediaPromptDisplayedUIDelegate alloc] init]);
+    webView.UIDelegate = delegate.get();
+
+    shouldReleaseInEnumerate = false;
+    [webView loadTestPageNamed:@"getUserMedia"];
+    TestWebKitAPI::Util::run(&okToProceed);
+}
+
+TEST(WebKit2, NavigateDuringDeviceEnumeration)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    auto preferences = [configuration preferences];
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mediaDevicesEnabled = YES;
+    preferences._mockCaptureDevicesEnabled = YES;
+    auto webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()];
+    auto delegate = adoptNS([[NavigationWhileGetUserMediaPromptDisplayedUIDelegate alloc] init]);
+    webView.UIDelegate = delegate.get();
+
+    shouldReleaseInEnumerate = true;
+    [webView loadTestPageNamed:@"enumerateMediaDevices"];
+    TestWebKitAPI::Util::run(&okToProceed);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // WK_API_ENABLED
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to