Title: [217910] trunk
Revision
217910
Author
commit-qu...@webkit.org
Date
2017-06-07 16:27:14 -0700 (Wed, 07 Jun 2017)

Log Message

getUserMedia is prompting too often
https://bugs.webkit.org/show_bug.cgi?id=172859
<rdar://problem/32589950>

Patch by Youenn Fablet <you...@apple.com> on 2017-06-07
Reviewed by Eric Carlson.

Source/WebCore:

Tests: fast/mediastream/getUserMedia-grant-persistency-reload.html
       fast/mediastream/getUserMedia-grant-persistency.html

* loader/FrameLoaderClient.h:
* page/Frame.cpp:
(WebCore::Frame::setDocument): Allows notifying of change of main frame document.
UIProcess will use that to remove unneeded previously granted gum permission.

Source/WebKit2:

Introduce a storage of granted requests to skip prompting when needed.
This is a partial implementation as granted requests should not happen for background tabs.
This will be covered in a follow-up patch.
Covered by manual tests.

A granted request keeps its mainFrameID.
Whenever the document of the main frame changes, the granted requests for that mainFrameID will be removed.
This handles the case of navigating, reloading... while still supporting the case of granting getUserMedia after in page navigation.

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
(WebKit::UserMediaPermissionRequestManagerProxy::removeGrantedAccess):
(WebKit::UserMediaPermissionRequestManagerProxy::searchForGrantedRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::grantAccess):
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
* UIProcess/UserMediaPermissionRequestManagerProxy.h:
* UIProcess/UserMediaPermissionRequestProxy.cpp:
(WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):
* UIProcess/UserMediaPermissionRequestProxy.h:
(WebKit::UserMediaPermissionRequestProxy::create):
(WebKit::UserMediaPermissionRequestProxy::mainFrameID):
(WebKit::UserMediaPermissionRequestProxy::frameID):
(WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didChangeMainDocument):
(WebKit::WebPageProxy::backForwardGoToItem):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDidChangeMainDocument):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:

LayoutTests:

* fast/mediastream/getUserMedia-grant-persistency-expected.txt: Added.
* fast/mediastream/getUserMedia-grant-persistency-reload-expected.txt: Added.
* fast/mediastream/getUserMedia-grant-persistency-reload.html: Added.
* fast/mediastream/getUserMedia-grant-persistency.html: Added.
* http/tests/media/media-stream/get-user-media-prompt-expected.txt:
* http/tests/media/media-stream/get-user-media-prompt.html: Last gum does not need a prompt anymore.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (217909 => 217910)


--- trunk/LayoutTests/ChangeLog	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/LayoutTests/ChangeLog	2017-06-07 23:27:14 UTC (rev 217910)
@@ -1,3 +1,18 @@
+2017-06-07  Youenn Fablet  <you...@apple.com>
+
+        getUserMedia is prompting too often
+        https://bugs.webkit.org/show_bug.cgi?id=172859
+        <rdar://problem/32589950>
+
+        Reviewed by Eric Carlson.
+
+        * fast/mediastream/getUserMedia-grant-persistency-expected.txt: Added.
+        * fast/mediastream/getUserMedia-grant-persistency-reload-expected.txt: Added.
+        * fast/mediastream/getUserMedia-grant-persistency-reload.html: Added.
+        * fast/mediastream/getUserMedia-grant-persistency.html: Added.
+        * http/tests/media/media-stream/get-user-media-prompt-expected.txt:
+        * http/tests/media/media-stream/get-user-media-prompt.html: Last gum does not need a prompt anymore.
+
 2017-06-07  Daniel Bates  <daba...@apple.com>
 
         Fetching Blob URLs with XHR gives null content-type and content-length

Added: trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-expected.txt (0 => 217910)


--- trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-expected.txt	2017-06-07 23:27:14 UTC (rev 217910)
@@ -0,0 +1,6 @@
+
+PASS Testing same page getUserMedia grant persistency 
+PASS Testing same page getUserMedia grant persistency in case page capture is in muted state 
+PASS Testing same page getUserMedia grant persistency after in page navigation 
+FAIL Testing same page getUserMedia grant persistency with visibility assert_true: Resolving getUserMedia promise should wait for page to be visible expected true got false
+

Added: trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload-expected.txt (0 => 217910)


--- trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload-expected.txt	2017-06-07 23:27:14 UTC (rev 217910)
@@ -0,0 +1,2 @@
+In case of reload, getUserMedia should not be allowed based on previous getUserMedia calls but only according client logic
+PASS

Added: trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload.html (0 => 217910)


--- trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency-reload.html	2017-06-07 23:27:14 UTC (rev 217910)
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+function test() {
+    if (window.localStorage.getItem("gum-after-reload") == null) {
+        window.localStorage.setItem("gum-after-reload", "true")
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(true);
+        navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(() => {
+            internals.forceReload(true);
+        });
+    } else {
+        window.localStorage.clear();
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(() => {i
+            result.innerHTML = "FAIL";
+            if (window.testRunner)
+               testRunner.notifyDone();
+        }, () => {
+            result.innerHTML = "PASS";
+            if (window.testRunner)
+                testRunner.notifyDone();
+        });
+    };
+}
+</script>
+</head>
+<body _onload_="setTimeout(test, 0);">
+  <div>In case of reload, getUserMedia should not be allowed based on previous getUserMedia calls but only according client logic</div>
+  <div id="result"></div>
+</body>
+</html>
+
+

Added: trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency.html (0 => 217910)


--- trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getUserMedia-grant-persistency.html	2017-06-07 23:27:14 UTC (rev 217910)
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <div id="navigateToSamePage"></div>
+        <script>
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+    return navigator.mediaDevices.getUserMedia({audio:false, video:true}).then((stream) => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        return navigator.mediaDevices.getUserMedia({audio:false, video:true});
+    }).then(() => {
+        return navigator.mediaDevices.getUserMedia({audio:true, video:false}).then(assert_unreached, (e) => {
+            assert_equals(e.name, "NotAllowedError");
+        });
+    }).then(() => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(true);
+        return navigator.mediaDevices.getUserMedia({audio:true, video:false});
+    }).then(() => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        return navigator.mediaDevices.getUserMedia({audio:true, video:true});
+    });
+}, "Testing same page getUserMedia grant persistency");
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+    return navigator.mediaDevices.getUserMedia({audio:true, video:true}).then((stream) => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        return navigator.mediaDevices.getUserMedia({audio:true, video:true});
+    }).then(() => {
+        if (window.internals)
+            internals.setPageMuted("capturedevices");
+        return navigator.mediaDevices.getUserMedia({audio:true, video:true});
+    }).then(() => {
+        if (!window.internals)
+            return;
+        assert_true(internals.pageMediaState().includes("HasActiveVideoCaptureDevice"), "Check active video");
+        assert_true(internals.pageMediaState().includes("HasActiveAudioCaptureDevice"), "Check active audio");
+    });
+}, "Testing same page getUserMedia grant persistency in case page capture is in muted state");
+
+promise_test((test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+    return navigator.mediaDevices.getUserMedia({audio:false, video:true}).then((stream) => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        return navigator.mediaDevices.getUserMedia({audio:false, video:true});
+    }).then(() => {
+        window.location = "#navigateToSamePage";
+    }).then(() => {
+        return navigator.mediaDevices.getUserMedia({audio:false, video:true});
+    });
+}, "Testing same page getUserMedia grant persistency after in page navigation");
+
+promise_test((test) => {
+    var isPageVisible = true;
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+    return navigator.mediaDevices.getUserMedia({audio:false, video:true}).then((stream) => {
+        if (window.testRunner)
+            testRunner.setUserMediaPermission(false);
+        isPageVisible = false;
+        if (window.internals)
+            internals.setPageVisibility(false);
+        setTimeout(() => {
+            isPageVisible = true;
+            if (window.internals)
+                internals.setPageVisibility(true);
+        }, 100);
+        return navigator.mediaDevices.getUserMedia({audio:false, video:true});
+    }).then(() => {
+        assert_true(isPageVisible, "Resolving getUserMedia promise should wait for page to be visible");
+    });
+}, "Testing same page getUserMedia grant persistency with visibility");
+
+        </script>
+    </body>
+</html>

Modified: trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt-expected.txt (217909 => 217910)


--- trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt-expected.txt	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt-expected.txt	2017-06-07 23:27:14 UTC (rev 217910)
@@ -3,23 +3,23 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS numberOfTimesGetUserMediaHasBeenCalled() is 0
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() 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 numberOfTimesGetUserMediaPromptHasBeenCalled() 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 numberOfTimesGetUserMediaPromptHasBeenCalled() 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 prompted again **
+** Request a stream with video and audio, the user should not be prompted again **
 PASS navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(gotStream3); did not throw exception.
-PASS numberOfTimesGetUserMediaHasBeenCalled() is 3
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
 PASS stream.getAudioTracks().length is 1
 PASS stream.getVideoTracks().length is 1
 

Modified: trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt.html (217909 => 217910)


--- trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt.html	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/LayoutTests/http/tests/media/media-stream/get-user-media-prompt.html	2017-06-07 23:27:14 UTC (rev 217910)
@@ -7,7 +7,7 @@
         <script src=""
         <script>
 
-            function numberOfTimesGetUserMediaHasBeenCalled()
+            function numberOfTimesGetUserMediaPromptHasBeenCalled()
             {
                 return testRunner.userMediaPermissionRequestCountForOrigin(document.location.href, document.location.href);
             }
@@ -15,7 +15,7 @@
             function gotStream3(s)
             {
                 stream = s;
-                shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "3");
+                shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
                 shouldBe("stream.getAudioTracks().length", "1");
                 shouldBe("stream.getVideoTracks().length", "1");
 
@@ -26,11 +26,11 @@
             function gotStream2(s)
             {
                 stream = s;
-                shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "2");
+                shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
                 shouldBe("stream.getAudioTracks().length", "0");
                 shouldBe("stream.getVideoTracks().length", "1");
 
-                debug("<br>** Request a stream with video and audio, the user should be prompted again **");
+                debug("<br>** Request a stream with video and audio, the user should not be prompted again **");
                 shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true, video:true}).then(gotStream3);");
             }
 
@@ -37,7 +37,7 @@
             function gotStream1(s)
             {
                 stream = s;
-                shouldBe("numberOfTimesGetUserMediaHasBeenCalled()", "1");
+                shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
                 shouldBe("stream.getAudioTracks().length", "1");
                 shouldBe("stream.getVideoTracks().length", "0");
 
@@ -50,7 +50,7 @@
                 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");
+                shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "0");
 
                 debug("<br>** Request an audio-only stream, the user should be prompted **");
                 shouldNotThrow("navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1);");

Modified: trunk/Source/WebCore/ChangeLog (217909 => 217910)


--- trunk/Source/WebCore/ChangeLog	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebCore/ChangeLog	2017-06-07 23:27:14 UTC (rev 217910)
@@ -1,3 +1,19 @@
+2017-06-07  Youenn Fablet  <you...@apple.com>
+
+        getUserMedia is prompting too often
+        https://bugs.webkit.org/show_bug.cgi?id=172859
+        <rdar://problem/32589950>
+
+        Reviewed by Eric Carlson.
+
+        Tests: fast/mediastream/getUserMedia-grant-persistency-reload.html
+               fast/mediastream/getUserMedia-grant-persistency.html
+
+        * loader/FrameLoaderClient.h:
+        * page/Frame.cpp:
+        (WebCore::Frame::setDocument): Allows notifying of change of main frame document.
+        UIProcess will use that to remove unneeded previously granted gum permission.
+
 2017-06-07  Chris Dumez  <cdu...@apple.com>
 
         Align <col span>/<colgroup span> limits with the latest HTML specification

Modified: trunk/Source/WebCore/loader/FrameLoaderClient.h (217909 => 217910)


--- trunk/Source/WebCore/loader/FrameLoaderClient.h	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebCore/loader/FrameLoaderClient.h	2017-06-07 23:27:14 UTC (rev 217910)
@@ -152,6 +152,7 @@
     virtual void dispatchDidChangeProvisionalURL() { }
     virtual void dispatchDidCancelClientRedirect() = 0;
     virtual void dispatchWillPerformClientRedirect(const URL&, double interval, double fireDate) = 0;
+    virtual void dispatchDidChangeMainDocument() { }
     virtual void dispatchDidNavigateWithinPage() { }
     virtual void dispatchDidChangeLocationWithinPage() = 0;
     virtual void dispatchDidPushStateWithinPage() = 0;

Modified: trunk/Source/WebCore/page/Frame.cpp (217909 => 217910)


--- trunk/Source/WebCore/page/Frame.cpp	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebCore/page/Frame.cpp	2017-06-07 23:27:14 UTC (rev 217910)
@@ -271,7 +271,10 @@
         return;
 
     m_documentIsBeingReplaced = true;
-    
+
+    if (isMainFrame())
+        m_loader.client().dispatchDidChangeMainDocument();
+
     if (m_doc && m_doc->pageCacheState() != Document::InPageCache)
         m_doc->prepareForDestruction();
 

Modified: trunk/Source/WebKit2/ChangeLog (217909 => 217910)


--- trunk/Source/WebKit2/ChangeLog	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/ChangeLog	2017-06-07 23:27:14 UTC (rev 217910)
@@ -1,3 +1,44 @@
+2017-06-07  Youenn Fablet  <you...@apple.com>
+
+        getUserMedia is prompting too often
+        https://bugs.webkit.org/show_bug.cgi?id=172859
+        <rdar://problem/32589950>
+
+        Reviewed by Eric Carlson.
+
+        Introduce a storage of granted requests to skip prompting when needed.
+        This is a partial implementation as granted requests should not happen for background tabs.
+        This will be covered in a follow-up patch.
+        Covered by manual tests.
+
+        A granted request keeps its mainFrameID.
+        Whenever the document of the main frame changes, the granted requests for that mainFrameID will be removed.
+        This handles the case of navigating, reloading... while still supporting the case of granting getUserMedia after in page navigation.
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
+        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
+        (WebKit::UserMediaPermissionRequestManagerProxy::removeGrantedAccess):
+        (WebKit::UserMediaPermissionRequestManagerProxy::searchForGrantedRequest):
+        (WebKit::UserMediaPermissionRequestManagerProxy::grantAccess):
+        (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
+        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+        * UIProcess/UserMediaPermissionRequestProxy.cpp:
+        (WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):
+        * UIProcess/UserMediaPermissionRequestProxy.h:
+        (WebKit::UserMediaPermissionRequestProxy::create):
+        (WebKit::UserMediaPermissionRequestProxy::mainFrameID):
+        (WebKit::UserMediaPermissionRequestProxy::frameID):
+        (WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didChangeMainDocument):
+        (WebKit::WebPageProxy::backForwardGoToItem):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDidChangeMainDocument):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+
 2017-06-07  Dan Bernstein  <m...@apple.com>
 
         [Cocoa] additionalReadAccessAllowedURLs should be consumed before loading the injected bundle

Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2017-06-07 23:27:14 UTC (rev 217910)
@@ -79,9 +79,9 @@
     invalidatePendingRequests();
 }
 
-Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
+Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
 {
-    auto request = UserMediaPermissionRequestProxy::create(*this, userMediaID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDeviceUIDs), WTFMove(videoDeviceUIDs), WTFMove(deviceIDHashSalt));
+    auto request = UserMediaPermissionRequestProxy::create(*this, userMediaID, mainFrameID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDeviceUIDs), WTFMove(videoDeviceUIDs), WTFMove(deviceIDHashSalt));
     m_pendingUserMediaRequests.add(userMediaID, request.ptr());
     return request;
 }
@@ -154,8 +154,8 @@
     if (!request)
         return;
 
-    UserMediaProcessManager::singleton().willCreateMediaStream(*this, !audioDeviceUID.isEmpty(), !videoDeviceUID.isEmpty());
-    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID, request->deviceIdentifierHashSalt()), m_page.pageID());
+    grantAccess(userMediaID, audioDeviceUID, videoDeviceUID, request->deviceIdentifierHashSalt());
+    m_grantedRequests.append(request.releaseNonNull());
 #else
     UNUSED_PARAM(userMediaID);
     UNUSED_PARAM(audioDeviceUID);
@@ -163,6 +163,47 @@
 #endif
 }
 
+#if ENABLE(MEDIA_STREAM)
+void UserMediaPermissionRequestManagerProxy::removeGrantedAccess(uint64_t frameID)
+{
+    m_grantedRequests.removeAllMatching([frameID](const auto& grantedRequest) {
+        return grantedRequest->mainFrameID() == frameID;
+    });
+}
+
+const UserMediaPermissionRequestProxy* UserMediaPermissionRequestManagerProxy::searchForGrantedRequest(uint64_t frameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const
+{
+    bool checkForAudio = needsAudio;
+    bool checkForVideo = needsVideo;
+    for (const auto& grantedRequest : m_grantedRequests) {
+        if (!grantedRequest->userMediaDocumentSecurityOrigin().isSameSchemeHostPort(userMediaDocumentOrigin))
+            continue;
+        if (!grantedRequest->topLevelDocumentSecurityOrigin().isSameSchemeHostPort(topLevelDocumentOrigin))
+            continue;
+        if (grantedRequest->frameID() != frameID)
+            continue;
+
+        if (!grantedRequest->videoDeviceUIDs().isEmpty())
+            checkForVideo = false;
+
+        if (!grantedRequest->audioDeviceUIDs().isEmpty())
+            checkForAudio = false;
+
+        if (checkForVideo || checkForAudio)
+            continue;
+
+        return grantedRequest.ptr();
+    }
+    return nullptr;
+}
+
+void UserMediaPermissionRequestManagerProxy::grantAccess(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt)
+{
+    UserMediaProcessManager::singleton().willCreateMediaStream(*this, !audioDeviceUID.isEmpty(), !videoDeviceUID.isEmpty());
+    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID, deviceIdentifierHashSalt), m_page.pageID());
+}
+#endif
+
 void UserMediaPermissionRequestManagerProxy::rejectionTimerFired()
 {
     uint64_t userMediaID = m_pendingRejections[0];
@@ -197,7 +238,7 @@
     };
 
     WebCore::RealtimeMediaSourceCenter::ValidConstraintsHandler validHandler = [this, userMediaID, frameID, userMediaDocumentOrigin = userMediaDocumentOrigin.copyRef(), topLevelDocumentOrigin = topLevelDocumentOrigin.copyRef()](Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIdentifierHashSalt) mutable {
-        if (!m_page.isValid())
+        if (!m_page.isValid() || !m_page.mainFrame())
             return;
 
         if (videoDeviceUIDs.isEmpty() && audioDeviceUIDs.isEmpty()) {
@@ -205,10 +246,18 @@
             return;
         }
 
+        auto* grantedRequest = searchForGrantedRequest(frameID, userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get(), !audioDeviceUIDs.isEmpty(), !videoDeviceUIDs.isEmpty());
+        if (grantedRequest) {
+            // 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.
+            grantAccess(userMediaID, audioDeviceUIDs.isEmpty() ? String() : audioDeviceUIDs[0], videoDeviceUIDs.isEmpty() ? String() : videoDeviceUIDs[0], grantedRequest->deviceIdentifierHashSalt());
+            return;
+        }
         auto userMediaOrigin = API::SecurityOrigin::create(userMediaDocumentOrigin.get());
         auto topLevelOrigin = API::SecurityOrigin::create(topLevelDocumentOrigin.get());
-        auto request = createRequest(userMediaID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDeviceUIDs), WTFMove(videoDeviceUIDs), WTFMove(deviceIdentifierHashSalt));
 
+        auto request = createRequest(userMediaID, m_page.mainFrame()->frameID(), frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDeviceUIDs), WTFMove(videoDeviceUIDs), WTFMove(deviceIdentifierHashSalt));
+
         if (m_page.preferences().mockCaptureDevicesEnabled() && !m_page.preferences().mockCaptureDevicesPromptEnabled()) {
             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=172989
             // We should probably only allow this if page is already actively capturing or page is visible.

Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h	2017-06-07 23:27:14 UTC (rev 217910)
@@ -47,6 +47,8 @@
 
     void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&&  userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, const WebCore::MediaConstraints& audioConstraints, const WebCore::MediaConstraints& videoConstraints);
 
+    void removeGrantedAccess(uint64_t mainFrameID);
+
     void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID);
     void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason);
 
@@ -61,9 +63,13 @@
     void endedCaptureSession();
 
 private:
-    Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&&);
+    Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&&);
     void denyRequest(uint64_t userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint);
+#if ENABLE(MEDIA_STREAM)
+    void grantAccess(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt);
 
+    const UserMediaPermissionRequestProxy* searchForGrantedRequest(uint64_t frameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const;
+#endif
     void getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin);
 
     void syncWithWebCorePrefs() const;
@@ -75,6 +81,8 @@
 
     WebCore::Timer m_rejectionTimer;
     Vector<uint64_t> m_pendingRejections;
+
+    Vector<Ref<UserMediaPermissionRequestProxy>> m_grantedRequests;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.cpp (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.cpp	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.cpp	2017-06-07 23:27:14 UTC (rev 217910)
@@ -30,9 +30,10 @@
 
 namespace WebKit {
 
-UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
+UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
     : m_manager(&manager)
     , m_userMediaID(userMediaID)
+    , m_mainFrameID(mainFrameID)
     , m_frameID(frameID)
     , m_userMediaDocumentSecurityOrigin(WTFMove(userMediaDocumentOrigin))
     , m_topLevelDocumentSecurityOrigin(WTFMove(topLevelDocumentOrigin))

Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.h (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.h	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.h	2017-06-07 23:27:14 UTC (rev 217910)
@@ -33,9 +33,9 @@
 
 class UserMediaPermissionRequestProxy : public API::ObjectImpl<API::Object::Type::UserMediaPermissionRequest> {
 public:
-    static Ref<UserMediaPermissionRequestProxy> create(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& videoDeviceUIDs, Vector<String>&& audioDeviceUIDs, String&& deviceIDHashSalt)
+    static Ref<UserMediaPermissionRequestProxy> create(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& videoDeviceUIDs, Vector<String>&& audioDeviceUIDs, String&& deviceIDHashSalt)
     {
-        return adoptRef(*new UserMediaPermissionRequestProxy(manager, userMediaID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(videoDeviceUIDs), WTFMove(audioDeviceUIDs), WTFMove(deviceIDHashSalt)));
+        return adoptRef(*new UserMediaPermissionRequestProxy(manager, userMediaID, mainFrameID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(videoDeviceUIDs), WTFMove(audioDeviceUIDs), WTFMove(deviceIDHashSalt)));
     }
 
     void allow(const String& videoDeviceUID, const String& audioDeviceUID);
@@ -51,17 +51,19 @@
     const Vector<String>& videoDeviceUIDs() const { return m_videoDeviceUIDs; }
     const Vector<String>& audioDeviceUIDs() const { return m_audioDeviceUIDs; }
 
+    uint64_t mainFrameID() const { return m_mainFrameID; }
     uint64_t frameID() const { return m_frameID; }
+    WebCore::SecurityOrigin& topLevelDocumentSecurityOrigin() { return m_topLevelDocumentSecurityOrigin.get(); }
     WebCore::SecurityOrigin& userMediaDocumentSecurityOrigin() { return m_userMediaDocumentSecurityOrigin.get(); }
-    WebCore::SecurityOrigin& topLevelDocumentSecurityOrigin() { return m_topLevelDocumentSecurityOrigin.get(); }
 
     const String& deviceIdentifierHashSalt() const { return m_deviceIdentifierHashSalt; }
 
 private:
-    UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& videoDeviceUIDs, Vector<String>&& audioDeviceUIDs, String&&);
+    UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& videoDeviceUIDs, Vector<String>&& audioDeviceUIDs, String&&);
 
     UserMediaPermissionRequestManagerProxy* m_manager;
     uint64_t m_userMediaID;
+    uint64_t m_mainFrameID;
     uint64_t m_frameID;
     Ref<WebCore::SecurityOrigin> m_userMediaDocumentSecurityOrigin;
     Ref<WebCore::SecurityOrigin> m_topLevelDocumentSecurityOrigin;

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2017-06-07 23:27:14 UTC (rev 217910)
@@ -3522,6 +3522,15 @@
         m_pageClient.didSameDocumentNavigationForMainFrame(navigationType);
 }
 
+void WebPageProxy::didChangeMainDocument(uint64_t frameID)
+{
+#if ENABLE(MEDIA_STREAM)
+    userMediaPermissionRequestManager().removeGrantedAccess(frameID);
+#else
+    UNUSED_PARAM(frameID);
+#endif
+}
+
 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
 {
     PageClientProtector protector(m_pageClient);

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2017-06-07 23:27:14 UTC (rev 217910)
@@ -1245,6 +1245,8 @@
     void didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&);
     void didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const WebCore::ResourceError&, const UserData&);
     void didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t sameDocumentNavigationType, const String&, const UserData&);
+    void didChangeMainDocument(uint64_t frameID);
+
     void didReceiveTitleForFrame(uint64_t frameID, const String&, const UserData&);
     void didFirstLayoutForFrame(uint64_t frameID, const UserData&);
     void didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData&);

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (217909 => 217910)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2017-06-07 23:27:14 UTC (rev 217910)
@@ -133,6 +133,7 @@
     DidRunInsecureContentForFrame(uint64_t frameID, WebKit::UserData userData)
     DidDetectXSSForFrame(uint64_t frameID, WebKit::UserData userData)
     DidSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t type, String url, WebKit::UserData userData)
+    DidChangeMainDocument(uint64_t frameID);
     DidDestroyNavigation(uint64_t navigationID)
 
     HasInsecureContent() -> (enum WebCore::HasInsecureContent hasInsecureContent)

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (217909 => 217910)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2017-06-07 23:27:14 UTC (rev 217910)
@@ -336,6 +336,15 @@
     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
 }
 
+void WebFrameLoaderClient::dispatchDidChangeMainDocument()
+{
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+
+    webPage->send(Messages::WebPageProxy::DidChangeMainDocument(m_frame->frameID()));
+}
+
 void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
 {
     WebPage* webPage = m_frame->page();

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h (217909 => 217910)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h	2017-06-07 22:39:06 UTC (rev 217909)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h	2017-06-07 23:27:14 UTC (rev 217910)
@@ -84,7 +84,8 @@
 #if ENABLE(DATA_DETECTION)
     void dispatchDidFinishDataDetection(NSArray *detectionResults) final;
 #endif
-    
+    void dispatchDidChangeMainDocument() final;
+
     void dispatchDidDispatchOnloadEvents() final;
     void dispatchDidReceiveServerRedirectForProvisionalLoad() final;
     void dispatchDidChangeProvisionalURL() final;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to