Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (237783 => 237784)
--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2018-11-04 15:46:38 UTC (rev 237783)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2018-11-04 16:04:19 UTC (rev 237784)
@@ -133,7 +133,7 @@
return;
if (reason == UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied)
- m_deniedRequests.append(DeniedRequest { request->mainFrameID(), request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin(), request->requiresAudioCapture(), request->requiresVideoCapture() });
+ m_deniedRequests.append(DeniedRequest { request->mainFrameID(), request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin(), request->requiresAudioCapture(), request->requiresVideoCapture(), request->requiresDisplayCapture() });
denyRequest(userMediaID, reason, emptyString());
}
@@ -213,7 +213,7 @@
return nullptr;
}
-bool UserMediaPermissionRequestManagerProxy::wasRequestDenied(uint64_t mainFrameID, const SecurityOrigin& userMediaDocumentOrigin, const SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo)
+bool UserMediaPermissionRequestManagerProxy::wasRequestDenied(uint64_t mainFrameID, const SecurityOrigin& userMediaDocumentOrigin, const SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo, bool needsScreenCapture)
{
for (const auto& deniedRequest : m_deniedRequests) {
if (!deniedRequest.userMediaDocumentOrigin->isSameSchemeHostPort(userMediaDocumentOrigin))
@@ -226,6 +226,8 @@
return true;
if (deniedRequest.isVideoDenied && needsVideo)
return true;
+ if (deniedRequest.isScreenCaptureDenied && needsScreenCapture)
+ return true;
}
return false;
}
@@ -259,6 +261,26 @@
m_rejectionTimer.startOneShot(Seconds(mimimumDelayBeforeReplying + randomNumber()));
}
+UserMediaPermissionRequestManagerProxy::RequestAction UserMediaPermissionRequestManagerProxy::getRequestAction(uint64_t frameID, SecurityOrigin& userMediaDocumentOrigin, SecurityOrigin& topLevelDocumentOrigin, const MediaStreamRequest& userRequest, Vector<CaptureDevice>& audioDevices, Vector<CaptureDevice>& videoDevices)
+{
+ if (videoDevices.isEmpty() && audioDevices.isEmpty())
+ return RequestAction::Deny;
+
+ bool requestingScreenCapture = userRequest.type == MediaStreamRequest::Type::DisplayMedia;
+ ASSERT(!(requestingScreenCapture && videoDevices.isEmpty()));
+ ASSERT(!(requestingScreenCapture && !audioDevices.isEmpty()));
+ bool requestingCamera = !requestingScreenCapture && !videoDevices.isEmpty();
+ bool requestingMicrophone = !audioDevices.isEmpty();
+
+ if (wasRequestDenied(frameID, userMediaDocumentOrigin, topLevelDocumentOrigin, requestingMicrophone, requestingCamera, requestingScreenCapture))
+ return RequestAction::Deny;
+
+ if (userRequest.type == MediaStreamRequest::Type::DisplayMedia)
+ return RequestAction::Prompt;
+
+ return searchForGrantedRequest(frameID, userMediaDocumentOrigin, topLevelDocumentOrigin, requestingMicrophone, requestingCamera) ? RequestAction::Grant : RequestAction::Prompt;
+}
+
void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, const MediaStreamRequest& userRequest)
{
#if ENABLE(MEDIA_STREAM)
@@ -279,32 +301,29 @@
if (!m_page.isValid() || !m_page.mainFrame())
return;
- if (videoDevices.isEmpty() && audioDevices.isEmpty()) {
+ auto action = "" userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get(), localUserRequest, audioDevices, videoDevices);
+ if (action == RequestAction::Deny) {
denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString());
return;
}
- if (wasRequestDenied(m_page.mainFrame()->frameID(), userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get(), !audioDevices.isEmpty(), !videoDevices.isEmpty())) {
- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied, emptyString());
- return;
- }
+ if (action == RequestAction::Grant) {
+ ASSERT(localUserRequest.type != MediaStreamRequest::Type::DisplayMedia);
- auto* grantedRequest = searchForGrantedRequest(frameID, userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get(), !audioDevices.isEmpty(), !videoDevices.isEmpty());
- if (grantedRequest) {
if (m_page.isViewVisible()) {
- // We select the first available devices, but the current client API allows client to select which device to pick.
- // FIXME: Remove the possiblity for the client to do the device selection.
+ // We select the first available devices, but the current client API allows client to select which device to pick.
+ // FIXME: Remove the possiblity for the client to do the device selection.
auto audioDevice = !audioDevices.isEmpty() ? audioDevices[0] : CaptureDevice();
auto videoDevice = !videoDevices.isEmpty() ? videoDevices[0] : CaptureDevice();
- grantAccess(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), grantedRequest->deviceIdentifierHashSalt());
+ grantAccess(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(deviceIdentifierHashSalt));
} else
- m_pregrantedRequests.append(createPermissionRequest(userMediaID, m_page.mainFrame()->frameID(), frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDevices), WTFMove(videoDevices), String(grantedRequest->deviceIdentifierHashSalt()), WTFMove(localUserRequest)));
+ m_pregrantedRequests.append(createPermissionRequest(userMediaID, m_page.mainFrame()->frameID(), frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDevices), WTFMove(videoDevices), WTFMove(deviceIdentifierHashSalt), WTFMove(localUserRequest)));
return;
}
+
auto userMediaOrigin = API::SecurityOrigin::create(userMediaDocumentOrigin.get());
auto topLevelOrigin = API::SecurityOrigin::create(topLevelDocumentOrigin.get());
-
auto pendingRequest = createPermissionRequest(userMediaID, m_page.mainFrame()->frameID(), frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDevices), WTFMove(videoDevices), WTFMove(deviceIdentifierHashSalt), WTFMove(localUserRequest));
if (m_page.isControlledByAutomation()) {
Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (237783 => 237784)
--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h 2018-11-04 15:46:38 UTC (rev 237783)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h 2018-11-04 16:04:19 UTC (rev 237784)
@@ -73,10 +73,17 @@
bool grantAccess(uint64_t userMediaID, const WebCore::CaptureDevice audioDevice, const WebCore::CaptureDevice videoDevice, const String& deviceIdentifierHashSalt);
const UserMediaPermissionRequestProxy* searchForGrantedRequest(uint64_t frameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const;
- bool wasRequestDenied(uint64_t mainFrameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo);
+ bool wasRequestDenied(uint64_t mainFrameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo, bool needsScreenCapture);
#endif
void getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin);
+ enum class RequestAction {
+ Deny,
+ Grant,
+ Prompt
+ };
+ RequestAction getRequestAction(uint64_t frameID, WebCore::SecurityOrigin& userMediaDocumentOrigin, WebCore::SecurityOrigin& topLevelDocumentOrigin, const WebCore::MediaStreamRequest&, Vector<WebCore::CaptureDevice>& audioDevices, Vector<WebCore::CaptureDevice>& videoDevices);
+
void watchdogTimerFired();
HashMap<uint64_t, RefPtr<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests;
@@ -96,6 +103,7 @@
Ref<WebCore::SecurityOrigin> topLevelDocumentOrigin;
bool isAudioDenied;
bool isVideoDenied;
+ bool isScreenCaptureDenied;
};
Vector<DeniedRequest> m_deniedRequests;
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm (237783 => 237784)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm 2018-11-04 15:46:38 UTC (rev 237783)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm 2018-11-04 16:04:19 UTC (rev 237784)
@@ -38,6 +38,7 @@
#import <WebKit/WKWebViewConfiguration.h>
static bool wasPrompted = false;
+static bool shouldDeny = false;
static _WKCaptureDevices requestedDevices = 0;
static bool receivedScriptMessage = false;
static RetainPtr<WKScriptMessage> lastScriptMessage;
@@ -64,6 +65,11 @@
{
wasPrompted = true;
+ if (shouldDeny) {
+ decisionHandler(NO);
+ return;
+ }
+
requestedDevices = devices;
BOOL needsMicrophoneAuthorization = !!(requestedDevices & _WKCaptureDeviceMicrophone);
BOOL needsCameraAuthorization = !!(requestedDevices & _WKCaptureDeviceCamera);
@@ -140,7 +146,10 @@
} else {
EXPECT_STREQ([(NSString *)[lastScriptMessage body] UTF8String], "denied");
EXPECT_TRUE(haveStream(false));
- EXPECT_FALSE(wasPrompted);
+ if (shouldDeny)
+ EXPECT_TRUE(wasPrompted);
+ else
+ EXPECT_FALSE(wasPrompted);
}
}
@@ -165,6 +174,16 @@
promptForCapture(@"{ video: {width: { exact: 640} } }", false);
}
+TEST_F(GetDisplayMediaTest, PromptOnceAfterDenial)
+{
+ promptForCapture(@"{ video: true }", true);
+ shouldDeny = true;
+ promptForCapture(@"{ video: true }", false);
+ shouldDeny = false;
+ promptForCapture(@"{ video: true }", false);
+ promptForCapture(@"{ video: true }", false);
+}
+
} // namespace TestWebKitAPI
#endif // ENABLE(MEDIA_STREAM)