Skip to content
Permalink
Browse files
[MediaStream] Don't request user permission for a device if it has al…
…ready been granted in the current browsing context

https://bugs.webkit.org/show_bug.cgi?id=164760
Source/WebKit2:

<rdar://problem/29261266>

Reviewed by Youenn Fablet.

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::FrameAuthorizationState::FrameAuthorizationState):
(WebKit::FrameAuthorizationState::hasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::setHasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::reset):
(WebKit::FrameAuthorizationState::securityOriginsAreEqual):
(WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::invalidateRequests):
(WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
* UIProcess/UserMediaPermissionRequestManagerProxy.h:
(WebKit::FrameAuthorizationState::~FrameAuthorizationState):
(WebKit::FrameAuthorizationState::frameID):
* UIProcess/UserMediaPermissionRequestProxy.cpp:
(WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):
* UIProcess/UserMediaPermissionRequestProxy.h:
(WebKit::UserMediaPermissionRequestProxy::create):
(WebKit::UserMediaPermissionRequestProxy::frameID):
(WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
(WebKit::UserMediaPermissionRequestProxy::topLevelDocumentSecurityOrigin):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didCommitLoadForFrame):
* WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
(WebKit::UserMediaPermissionRequestManager::removeMediaRequestFromMaps):

Tools:

<rdar://problem/29261266>

Reviewed by Youenn Fablet.

Allow scripts to determine the number of times the user has been prompted for capture device access.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::setUserMediaPersistentPermissionForOrigin):
(WTR::InjectedBundle::userMediaPermissionRequestCountForOrigin):
(WTR::InjectedBundle::resetUserMediaPermissionRequestCountForOrigin):
(WTR::InjectedBundle::setUserMediaPermissionForOrigin): Deleted.
* WebKitTestRunner/InjectedBundle/InjectedBundle.h:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setUserMediaPersistentPermissionForOrigin):
(WTR::TestRunner::userMediaPermissionRequestCountForOrigin):
(WTR::TestRunner::resetUserMediaPermissionRequestCountForOrigin):
(WTR::TestRunner::setUserMediaPermissionForOrigin): Deleted.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetStateToConsistentValues):
(WTR::OriginSettings::incrementRequestCount):
(WTR::OriginSettings::resetRequestCount):
(WTR::OriginSettings::requestCount):
(WTR::TestController::saltForOrigin):
(WTR::TestController::setUserMediaPersistentPermissionForOrigin):
(WTR::TestController::handleCheckOfUserMediaPermissionForOrigin):
(WTR::TestController::settingsForOrigin):
(WTR::TestController::userMediaPermissionRequestCountForOrigin):
(WTR::TestController::resetUserMediaPermissionRequestCountForOrigin):
(WTR::TestController::decidePolicyForUserMediaPermissionRequestIfPossible):
(WTR::TestController::setUserMediaPermissionForOrigin): Deleted.
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

Reviewed by Youenn Fablet.

* fast/mediastream/MediaDevices-getUserMedia-expected.txt:
* fast/mediastream/MediaDevices-getUserMedia.html:


Canonical link: https://commits.webkit.org/182772@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209082 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
eric-carlson committed Nov 29, 2016
1 parent 08d12d5 commit e69a36f5edf0dd570243f8ae9a4980d5dc8c26a7
Showing with 512 additions and 80 deletions.
  1. +10 −0 LayoutTests/ChangeLog
  2. +2 −2 LayoutTests/fast/mediastream/MediaDevices-enumerateDevices.html
  3. +3 −5 LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt
  4. +12 −9 LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html
  5. +1 −1 LayoutTests/http/tests/media/media-stream/enumerate-devices-source-id-persistent.html
  6. +29 −0 LayoutTests/http/tests/media/media-stream/get-user-media-prompt-expected.txt
  7. +68 −0 LayoutTests/http/tests/media/media-stream/get-user-media-prompt.html
  8. +35 −0 Source/WebKit2/ChangeLog
  9. +9 −0 Source/WebKit2/UIProcess/API/C/WKPage.cpp
  10. +3 −1 Source/WebKit2/UIProcess/API/C/WKPagePrivate.h
  11. +104 −18 Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp
  12. +23 −3 Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h
  13. +8 −1 Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.cpp
  14. +14 −3 Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.h
  15. +6 −0 Source/WebKit2/UIProcess/WebPageProxy.cpp
  16. +2 −0 Source/WebKit2/UIProcess/WebPageProxy.h
  17. +41 −0 Tools/ChangeLog
  18. +3 −1 Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
  19. +34 −2 Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
  20. +3 −1 Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
  21. +16 −2 Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
  22. +5 −1 Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
  23. +44 −26 Tools/WebKitTestRunner/TestController.cpp
  24. +5 −2 Tools/WebKitTestRunner/TestController.h
  25. +32 −2 Tools/WebKitTestRunner/TestInvocation.cpp
@@ -1,3 +1,13 @@
2016-11-29 Eric Carlson <eric.carlson@apple.com>

[MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
https://bugs.webkit.org/show_bug.cgi?id=164760

Reviewed by Youenn Fablet.

* fast/mediastream/MediaDevices-getUserMedia-expected.txt:
* fast/mediastream/MediaDevices-getUserMedia.html:

2016-11-29 Ryan Haddad <ryanhaddad@apple.com>

Rebaseline fast/forms/validation-message-appearance.html for mac-wk1.
@@ -58,7 +58,7 @@
{
if (window.testRunner) {
testRunner.setUserMediaPermission(true);
testRunner.setUserMediaPermissionForOrigin(false, document.location.href, "");
testRunner.setUserMediaPersistentPermissionForOrigin(false, document.location.href, "");
}

navigator.mediaDevices
@@ -77,7 +77,7 @@
function grantPermission()
{
if (window.testRunner)
testRunner.setUserMediaPermissionForOrigin(true, document.location.href, "");
testRunner.setUserMediaPersistentPermissionForOrigin(true, document.location.href, "");

debug(`<br>*** Calling mediaDevices.enumerateDevices with persistent access, and without a media stream track<br>`);
havePermission = true;
@@ -31,11 +31,9 @@ PASS navigator.mediaDevices.getUserMedia({audio:audioConstraints, video:false}).
PASS Error callback called.
PASS navigator.mediaDevices.getUserMedia({audio:false, video:videoConstraints}).then(invalidGotStream).catch(errorWithConstraints2) did not throw exception.
PASS Error callback called.
PASS navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream, error1); did not throw exception.
PASS Error callback called.
PASS errorArg.name is "NotAllowedError"
PASS navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream).catch(error2); did not throw exception.
PASS Error callback called.
PASS errorArg.name is "Error"
PASS navigator.mediaDevices.getUserMedia({audio:true}).then(validStream, error1); did not throw exception.
PASS Stream generated because page has already authenticated.
PASS successfullyParsed is true

TEST COMPLETE
@@ -27,23 +27,26 @@
finishJSTest();
}

function error2(e) {
testPassed("Error callback called.");
function validStream(e) {
testPassed("Stream generated because page has already authenticated.");
finishJSTest();
}

function error1(e) {
errorArg = e;
testPassed("Error callback called.");
shouldBeEqualToString("errorArg.name", "NotAllowedError");

shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream).catch(error2);");
testFailed("Error callback called.");
finishJSTest();
}

function errorWithConstraints2() {
function errorWithConstraints2(e) {
testPassed("Error callback called.");
errorArg = e;
shouldBeEqualToString("errorArg.name", "Error");

// We tell LayoutTestRunner to deny user media requests but expect the gUM call to succeed
// as it should not see the request because the current browsing context has already
// successfully created a stream for the mock audio device.
setUserMediaPermission(false);
shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream, error1);");
shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(validStream, error1);");
}

function errorWithConstraints1() {
@@ -11,7 +11,7 @@

if (window.testRunner) {
testRunner.setUserMediaPermission(true);
testRunner.setUserMediaPermissionForOrigin(true, "http://localhost:8000", location.href);
testRunner.setUserMediaPersistentPermissionForOrigin(true, "http://localhost:8000", location.href);
}

function setup()
@@ -0,0 +1,29 @@
Tests that user is only prompted once per device in the current browsing context.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS numberOfTimesGetUserMediaHasBeenCalled() is 0

** Request an audio-only stream, the user should be prompted **
PASS navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1); did not throw exception.
PASS numberOfTimesGetUserMediaHasBeenCalled() is 1
PASS stream.getAudioTracks().length is 1
PASS stream.getVideoTracks().length is 0

** Request a video-only stream, the user should be prompted **
PASS navigator.mediaDevices.getUserMedia({video:true}).then(gotStream2); did not throw exception.
PASS numberOfTimesGetUserMediaHasBeenCalled() is 2
PASS stream.getAudioTracks().length is 0
PASS stream.getVideoTracks().length is 1

** Request a stream with video and audio, the user should be not prompted **
PASS navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(gotStream3); did not throw exception.
PASS numberOfTimesGetUserMediaHasBeenCalled() is 2
PASS stream.getAudioTracks().length is 1
PASS stream.getVideoTracks().length is 1

PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<style>
iframe { border: 1px solid black; }
</style>
<script src="../../../../resources/js-test-pre.js"></script>
<script>

function numberOfTimesGetUserMediaHasBeenCalled()
{
return testRunner.userMediaPermissionRequestCountForOrigin(document.location.href, document.location.href);
}

function gotStream3(s)
{
stream = s;
shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "2");
shouldBe("stream.getAudioTracks().length", "1");
shouldBe("stream.getVideoTracks().length", "1");

debug("");
finishJSTest();
}

function gotStream2(s)
{
stream = s;
shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "2");
shouldBe("stream.getAudioTracks().length", "0");
shouldBe("stream.getVideoTracks().length", "1");

debug("<br>** Request a stream with video and audio, the user should be not prompted **");
shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(gotStream3);");
}

function gotStream1(s)
{
stream = s;
shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "1");
shouldBe("stream.getAudioTracks().length", "1");
shouldBe("stream.getVideoTracks().length", "0");

debug("<br>** Request a video-only stream, the user should be prompted **");
shouldNotThrow("navigator.mediaDevices.getUserMedia({video:true}).then(gotStream2);")
}

function setup()
{
description("Tests that user is only prompted once per device in the current browsing context.");

testRunner.resetUserMediaPermissionRequestCountForOrigin(document.location.href, document.location.href);
shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "0");

debug("<br>** Request an audio-only stream, the user should be prompted **");
shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1);");
}

if (window.testRunner)
testRunner.setUserMediaPermission(true);
window.jsTestIsAsync = true;
window.successfullyParsed = true;
</script>
<script src="../../../../resources/js-test-post.js"></script>
</head>
<body onload="setup()">
</body>
</html>
@@ -1,3 +1,38 @@
2016-11-29 Eric Carlson <eric.carlson@apple.com>

[MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
https://bugs.webkit.org/show_bug.cgi?id=164760
<rdar://problem/29261266>

Reviewed by Youenn Fablet.

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::FrameAuthorizationState::FrameAuthorizationState):
(WebKit::FrameAuthorizationState::hasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::setHasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::reset):
(WebKit::FrameAuthorizationState::securityOriginsAreEqual):
(WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::invalidateRequests):
(WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
* UIProcess/UserMediaPermissionRequestManagerProxy.h:
(WebKit::FrameAuthorizationState::~FrameAuthorizationState):
(WebKit::FrameAuthorizationState::frameID):
* UIProcess/UserMediaPermissionRequestProxy.cpp:
(WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):
* UIProcess/UserMediaPermissionRequestProxy.h:
(WebKit::UserMediaPermissionRequestProxy::create):
(WebKit::UserMediaPermissionRequestProxy::frameID):
(WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
(WebKit::UserMediaPermissionRequestProxy::topLevelDocumentSecurityOrigin):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didCommitLoadForFrame):
* WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
(WebKit::UserMediaPermissionRequestManager::removeMediaRequestFromMaps):

2016-11-29 Wenson Hsieh <wenson_hsieh@apple.com>

Scroll snapping on Mac should use AppKit animations
@@ -2632,6 +2632,15 @@ void WKPageDidAllowPointerLock(WKPageRef page)
#endif
}

void WKPageClearUserMediaState(WKPageRef page)
{
#if ENABLE(MEDIA_STREAM)
toImpl(page)->clearUserMediaState();
#else
UNUSED_PARAM(page);
#endif
}

void WKPageDidDenyPointerLock(WKPageRef page)
{
#if ENABLE(POINTER_LOCK)
@@ -128,7 +128,9 @@ enum {
};
typedef uint32_t WKMediaMutedState;
WK_EXPORT void WKPageSetMuted(WKPageRef page, WKMediaMutedState muted);


WK_EXPORT void WKPageClearUserMediaState(WKPageRef page);

WK_EXPORT void WKPageDidAllowPointerLock(WKPageRef page);
WK_EXPORT void WKPageDidDenyPointerLock(WKPageRef page);

0 comments on commit e69a36f

Please sign in to comment.