Title: [245335] trunk
Revision
245335
Author
[email protected]
Date
2019-05-15 11:44:36 -0700 (Wed, 15 May 2019)

Log Message

getUserMedia sandbox extensions should not be revoked when a getUserMedia allowed request is being processed
https://bugs.webkit.org/show_bug.cgi?id=197851

Reviewed by Alex Christensen.

Source/WebCore:

Add a completion handler to create a new capture stream.
This is used by WK2 layer to acknowledge the pending capture request is completed.
Just after the completion handler, make sure to update the document media state.
This is done to ensure that, should capture failing, the UIProcess
knows about it and can manage proper sandbox extension revocation.

Test: fast/mediastream/gum-stop-track.html

* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::allow):
(WebCore::UserMediaRequest::PendingActivationMediaStream::PendingActivationMediaStream):
(WebCore::UserMediaRequest::PendingActivationMediaStream::~PendingActivationMediaStream):
* Modules/mediastream/UserMediaRequest.h:
(WebCore::UserMediaRequest::PendingActivationMediaStream::create):
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled):
* platform/mock/MockRealtimeMediaSourceCenter.h:

Source/WebKit:

Before the patch, stopping capture in a document and quickly triggering a new capture
might fail as the UIProcess would grant access and revoke sandbox access based on the fact
the page is no longer capturing.
To fix that issue, keep a state in the UIProcess to not revoke sandbox extensions in case of
capture being started.
Add an IPC message back to tell UIProcess when an allowed capture is finished.
Just after doing that, make sure the document is updating the media state to UIProcess, which will trigger proper sandbox extension handling.

This should also trigger the case of an allowed getUserMedia call that fails to start for some reason.
In that case, the patch will automatically trigger a document media state refresh which will trigger a sandbox revokation.

Covered by added test that exercise a newly added debug assertion.
This assertion ensures that we revoke extensions while a document is not capturing.

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy):
(WebKit::UserMediaPermissionRequestManagerProxy::grantAccess):
(WebKit::UserMediaPermissionRequestManagerProxy::captureStateChanged):
* UIProcess/UserMediaPermissionRequestManagerProxy.h:
* UIProcess/UserMediaProcessManager.cpp:
(WebKit::UserMediaProcessManager::willCreateMediaStream):
(WebKit::UserMediaProcessManager::revokeSandboxExtensionsIfNeeded):
* UIProcess/UserMediaProcessManager.h:
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::isCapturingAudio const):
(WebKit::WebPageProxy::isCapturingVideo const):
* WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
(WebKit::UserMediaPermissionRequestManager::userMediaAccessWasGranted):
* WebProcess/MediaStream/UserMediaPermissionRequestManager.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::userMediaAccessWasGranted):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebProcess.cpp:
(WebKit::checkDocumentsCaptureStateConsistency):
(WebKit::WebProcess::revokeUserMediaDeviceSandboxExtensions):

LayoutTests:

* fast/mediastream/gum-stop-track-expected.txt: Added.
* fast/mediastream/gum-stop-track.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (245334 => 245335)


--- trunk/LayoutTests/ChangeLog	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/LayoutTests/ChangeLog	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1,3 +1,13 @@
+2019-05-15  Youenn Fablet  <[email protected]>
+
+        getUserMedia sandbox extensions should not be revoked when a getUserMedia allowed request is being processed
+        https://bugs.webkit.org/show_bug.cgi?id=197851
+
+        Reviewed by Alex Christensen.
+
+        * fast/mediastream/gum-stop-track-expected.txt: Added.
+        * fast/mediastream/gum-stop-track.html: Added.
+
 2019-05-15  Fujii Hironori  <[email protected]>
 
         Unreviewed test gardening for WinCairo

Added: trunk/LayoutTests/fast/mediastream/gum-stop-track-expected.txt (0 => 245335)


--- trunk/LayoutTests/fast/mediastream/gum-stop-track-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/gum-stop-track-expected.txt	2019-05-15 18:44:36 UTC (rev 245335)
@@ -0,0 +1,3 @@
+
+PASS Call getUserMedia and track.stop in a loop 
+

Added: trunk/LayoutTests/fast/mediastream/gum-stop-track.html (0 => 245335)


--- trunk/LayoutTests/fast/mediastream/gum-stop-track.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/gum-stop-track.html	2019-05-15 18:44:36 UTC (rev 245335)
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <script>
+promise_test(async (test) => {
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    for (var cptr = 0; cptr < 5; ++cptr) {
+        const stream = await navigator.mediaDevices.getUserMedia({audio:false, video:true});
+        stream.getTracks().forEach((track) => track.stop());
+    }
+}, "Call getUserMedia and track.stop in a loop");
+        </script>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (245334 => 245335)


--- trunk/Source/WebCore/ChangeLog	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebCore/ChangeLog	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1,3 +1,28 @@
+2019-05-15  Youenn Fablet  <[email protected]>
+
+        getUserMedia sandbox extensions should not be revoked when a getUserMedia allowed request is being processed
+        https://bugs.webkit.org/show_bug.cgi?id=197851
+
+        Reviewed by Alex Christensen.
+
+        Add a completion handler to create a new capture stream.
+        This is used by WK2 layer to acknowledge the pending capture request is completed.
+        Just after the completion handler, make sure to update the document media state.
+        This is done to ensure that, should capture failing, the UIProcess
+        knows about it and can manage proper sandbox extension revocation.
+
+        Test: fast/mediastream/gum-stop-track.html
+
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::allow):
+        (WebCore::UserMediaRequest::PendingActivationMediaStream::PendingActivationMediaStream):
+        (WebCore::UserMediaRequest::PendingActivationMediaStream::~PendingActivationMediaStream):
+        * Modules/mediastream/UserMediaRequest.h:
+        (WebCore::UserMediaRequest::PendingActivationMediaStream::create):
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled):
+        * platform/mock/MockRealtimeMediaSourceCenter.h:
+
 2019-05-15  Simon Fraser  <[email protected]>
 
         Move RenderLayerCompositor's OverlapMap to its own file

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (245334 => 245335)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -47,6 +47,7 @@
 #include "SchemeRegistry.h"
 #include "Settings.h"
 #include "UserMediaController.h"
+#include <wtf/Scope.h>
 
 namespace WebCore {
 
@@ -214,11 +215,14 @@
     controller->requestUserMediaAccess(*this);
 }
 
-void UserMediaRequest::allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt)
+void UserMediaRequest::allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&& completionHandler)
 {
     RELEASE_LOG(MediaStream, "UserMediaRequest::allow %s %s", audioDevice ? audioDevice.persistentId().utf8().data() : "", videoDevice ? videoDevice.persistentId().utf8().data() : "");
 
-    auto callback = [this, protector = makePendingActivity(*this)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
+    auto callback = [this, protector = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
+        auto scopeExit = makeScopeExit([&] {
+            completionHandler();
+        });
         if (!m_scriptExecutionContext)
             return;
 
@@ -235,7 +239,8 @@
             return;
         }
 
-        m_pendingActivationMediaStream = PendingActivationMediaStream::create(WTFMove(protector), *this, WTFMove(stream));
+        scopeExit.release();
+        m_pendingActivationMediaStream = PendingActivationMediaStream::create(WTFMove(protector), *this, WTFMove(stream), WTFMove(completionHandler));
     };
 
     auto& document = downcast<Document>(*scriptExecutionContext());
@@ -330,10 +335,11 @@
     return downcast<Document>(m_scriptExecutionContext);
 }
 
-UserMediaRequest::PendingActivationMediaStream::PendingActivationMediaStream(Ref<PendingActivity<UserMediaRequest>>&& protectingUserMediaRequest, UserMediaRequest& userMediaRequest, Ref<MediaStream>&& stream)
+UserMediaRequest::PendingActivationMediaStream::PendingActivationMediaStream(Ref<PendingActivity<UserMediaRequest>>&& protectingUserMediaRequest, UserMediaRequest& userMediaRequest, Ref<MediaStream>&& stream, CompletionHandler<void()>&& completionHandler)
     : m_protectingUserMediaRequest(WTFMove(protectingUserMediaRequest))
     , m_userMediaRequest(userMediaRequest)
     , m_mediaStream(WTFMove(stream))
+    , m_completionHandler(WTFMove(completionHandler))
 {
     m_mediaStream->privateStream().addObserver(*this);
     m_mediaStream->startProducingData();
@@ -342,6 +348,9 @@
 UserMediaRequest::PendingActivationMediaStream::~PendingActivationMediaStream()
 {
     m_mediaStream->privateStream().removeObserver(*this);
+    m_completionHandler();
+    if (auto* document = m_mediaStream->document())
+        document->updateIsPlayingMedia();
 }
 
 void UserMediaRequest::PendingActivationMediaStream::characteristicsChanged()

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h (245334 => 245335)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -40,6 +40,7 @@
 #include "MediaConstraints.h"
 #include "MediaStreamPrivate.h"
 #include "MediaStreamRequest.h"
+#include <wtf/CompletionHandler.h>
 
 namespace WebCore {
 
@@ -54,7 +55,7 @@
     void start();
 
     WEBCORE_EXPORT void setAllowedMediaDeviceUIDs(const String& audioDeviceUID, const String& videoDeviceUID);
-    WEBCORE_EXPORT void allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt);
+    WEBCORE_EXPORT void allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&&);
 
     enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, IllegalConstraint, OtherFailure };
     WEBCORE_EXPORT void deny(MediaAccessDenialReason, const String& errorMessage = emptyString());
@@ -83,14 +84,14 @@
 
     class PendingActivationMediaStream : public RefCounted<PendingActivationMediaStream>, private MediaStreamPrivate::Observer {
     public:
-        static Ref<PendingActivationMediaStream> create(Ref<PendingActivity<UserMediaRequest>>&& protectingUserMediaRequest, UserMediaRequest& userMediaRequest, Ref<MediaStream>&& stream)
+        static Ref<PendingActivationMediaStream> create(Ref<PendingActivity<UserMediaRequest>>&& protectingUserMediaRequest, UserMediaRequest& userMediaRequest, Ref<MediaStream>&& stream, CompletionHandler<void()>&& completionHandler)
         {
-            return adoptRef(*new PendingActivationMediaStream { WTFMove(protectingUserMediaRequest), userMediaRequest, WTFMove(stream) });
+            return adoptRef(*new PendingActivationMediaStream { WTFMove(protectingUserMediaRequest), userMediaRequest, WTFMove(stream), WTFMove(completionHandler) });
         }
         ~PendingActivationMediaStream();
 
     private:
-        PendingActivationMediaStream(Ref<PendingActivity<UserMediaRequest>>&&, UserMediaRequest&, Ref<MediaStream>&&);
+        PendingActivationMediaStream(Ref<PendingActivity<UserMediaRequest>>&&, UserMediaRequest&, Ref<MediaStream>&&, CompletionHandler<void()>&&);
 
         void characteristicsChanged() final;
 
@@ -97,6 +98,7 @@
         Ref<PendingActivity<UserMediaRequest>> m_protectingUserMediaRequest;
         UserMediaRequest& m_userMediaRequest;
         Ref<MediaStream> m_mediaStream;
+        CompletionHandler<void()> m_completionHandler;
     };
 
     Vector<String> m_videoDeviceUIDs;

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (245334 => 245335)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -208,6 +208,14 @@
         center.unsetDisplayCaptureFactory(mock.displayCaptureFactory());
 }
 
+bool MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled()
+{
+    MockRealtimeMediaSourceCenter& mock = singleton();
+    RealtimeMediaSourceCenter& center = RealtimeMediaSourceCenter::singleton();
+
+    return &center.audioCaptureFactory() == &mock.audioCaptureFactory() || &center.videoCaptureFactory() == &mock.videoCaptureFactory() || &center.displayCaptureFactory() == &mock.displayCaptureFactory();
+}
+
 static void createCaptureDevice(const MockMediaDevice& device)
 {
     deviceListForDevice(device).append(MockRealtimeMediaSourceCenter::captureDeviceWithPersistentID(device.type(), device.persistentId).value());

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h (245334 => 245335)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -41,6 +41,7 @@
     WEBCORE_EXPORT static MockRealtimeMediaSourceCenter& singleton();
 
     WEBCORE_EXPORT static void setMockRealtimeMediaSourceCenterEnabled(bool);
+    WEBCORE_EXPORT static bool mockRealtimeMediaSourceCenterEnabled();
 
     WEBCORE_EXPORT static void setDevices(Vector<MockMediaDevice>&&);
     WEBCORE_EXPORT static void addDevice(const MockMediaDevice&);

Modified: trunk/Source/WebKit/ChangeLog (245334 => 245335)


--- trunk/Source/WebKit/ChangeLog	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/ChangeLog	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1,3 +1,47 @@
+2019-05-15  Youenn Fablet  <[email protected]>
+
+        getUserMedia sandbox extensions should not be revoked when a getUserMedia allowed request is being processed
+        https://bugs.webkit.org/show_bug.cgi?id=197851
+
+        Reviewed by Alex Christensen.
+
+        Before the patch, stopping capture in a document and quickly triggering a new capture
+        might fail as the UIProcess would grant access and revoke sandbox access based on the fact
+        the page is no longer capturing.
+        To fix that issue, keep a state in the UIProcess to not revoke sandbox extensions in case of
+        capture being started.
+        Add an IPC message back to tell UIProcess when an allowed capture is finished.
+        Just after doing that, make sure the document is updating the media state to UIProcess, which will trigger proper sandbox extension handling.
+
+        This should also trigger the case of an allowed getUserMedia call that fails to start for some reason.
+        In that case, the patch will automatically trigger a document media state refresh which will trigger a sandbox revokation.
+
+        Covered by added test that exercise a newly added debug assertion.
+        This assertion ensures that we revoke extensions while a document is not capturing.
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy):
+        (WebKit::UserMediaPermissionRequestManagerProxy::grantAccess):
+        (WebKit::UserMediaPermissionRequestManagerProxy::captureStateChanged):
+        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+        * UIProcess/UserMediaProcessManager.cpp:
+        (WebKit::UserMediaProcessManager::willCreateMediaStream):
+        (WebKit::UserMediaProcessManager::revokeSandboxExtensionsIfNeeded):
+        * UIProcess/UserMediaProcessManager.h:
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::isCapturingAudio const):
+        (WebKit::WebPageProxy::isCapturingVideo const):
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
+        (WebKit::UserMediaPermissionRequestManager::userMediaAccessWasGranted):
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::userMediaAccessWasGranted):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::checkDocumentsCaptureStateConsistency):
+        (WebKit::WebProcess::revokeUserMediaDeviceSandboxExtensions):
+
 2019-05-15  Chris Dumez  <[email protected]>
 
         [WK2][iOS] UIProcess may get killed because it is taking too long to release its background task after expiration

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (245334 => 245335)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -83,7 +83,7 @@
 UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy()
 {
 #if ENABLE(MEDIA_STREAM)
-    UserMediaProcessManager::singleton().endedCaptureSession(*this);
+    UserMediaProcessManager::singleton().revokeSandboxExtensionsIfNeeded(page().process());
     proxies().remove(this);
 #endif
     invalidatePendingRequests();
@@ -295,7 +295,12 @@
         return false;
     }
 
-    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(request.userMediaID(), request.audioDevice(), request.videoDevice(), request.deviceIdentifierHashSalt()), m_page.pageID());
+    ++m_hasPendingCapture;
+    m_page.process().connection()->sendWithAsyncReply(Messages::WebPage::UserMediaAccessWasGranted { request.userMediaID(), request.audioDevice(), request.videoDevice(), request.deviceIdentifierHashSalt() }, [this, weakThis = makeWeakPtr(this)] {
+        if (!weakThis)
+            return;
+        --m_hasPendingCapture;
+    }, m_page.pageID());
     return true;
 }
 #endif
@@ -632,14 +637,9 @@
         return;
 
 #if ENABLE(MEDIA_STREAM)
-    bool wasCapturingAudio = oldState & MediaProducer::AudioCaptureMask;
-    bool wasCapturingVideo = oldState & MediaProducer::VideoCaptureMask;
-    bool isCapturingAudio = newState & MediaProducer::AudioCaptureMask;
-    bool isCapturingVideo = newState & MediaProducer::VideoCaptureMask;
+    if (!m_hasPendingCapture)
+        UserMediaProcessManager::singleton().revokeSandboxExtensionsIfNeeded(page().process());
 
-    if ((wasCapturingAudio && !isCapturingAudio) || (wasCapturingVideo && !isCapturingVideo))
-        UserMediaProcessManager::singleton().endedCaptureSession(*this);
-
     if (m_captureState == (newState & activeCaptureMask))
         return;
 

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (245334 => 245335)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -144,6 +144,7 @@
     const void* m_logIdentifier;
 #endif
     bool m_hasFilteredDeviceList { false };
+    uint64_t m_hasPendingCapture { 0 };
 };
 
 String convertEnumerationToString(UserMediaPermissionRequestManagerProxy::RequestAction);

Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp (245334 => 245335)


--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -72,27 +72,27 @@
     }
     
 #if ENABLE(SANDBOX_EXTENSIONS) && USE(APPLE_INTERNAL_SDK)
-    if (!proxy.page().preferences().mockCaptureDevicesEnabled()) {
-        auto& process = proxy.page().process();
-        size_t extensionCount = 0;
+    auto& process = proxy.page().process();
+    size_t extensionCount = 0;
 
-        if (withAudio && !process.hasAudioCaptureExtension())
-            extensionCount++;
-        else
-            withAudio = false;
+    if (withAudio && !process.hasAudioCaptureExtension())
+        extensionCount++;
+    else
+        withAudio = false;
 
-        if (withVideo && !process.hasVideoCaptureExtension())
-            extensionCount++;
-        else
-            withVideo = false;
+    if (withVideo && !process.hasVideoCaptureExtension())
+        extensionCount++;
+    else
+        withVideo = false;
 
-        if (extensionCount) {
-            SandboxExtension::HandleArray handles;
+    if (extensionCount) {
+        SandboxExtension::HandleArray handles;
+        Vector<String> ids;
+
+        if (!proxy.page().preferences().mockCaptureDevicesEnabled()) {
             handles.allocate(extensionCount);
+            ids.reserveInitialCapacity(extensionCount);
 
-            Vector<String> ids;
-            ids.reserveCapacity(extensionCount);
-
             if (withAudio && SandboxExtension::createHandleForGenericExtension(audioExtensionPath, handles[--extensionCount]))
                 ids.append(audioExtensionPath);
 
@@ -103,16 +103,16 @@
                 WTFLogAlways("Could not create a required sandbox extension, capture will fail!");
                 return false;
             }
+        }
 
-            for (const auto& id : ids)
-                RELEASE_LOG(WebRTC, "UserMediaProcessManager::willCreateMediaStream - granting extension %s", id.utf8().data());
+        for (const auto& id : ids)
+            RELEASE_LOG(WebRTC, "UserMediaProcessManager::willCreateMediaStream - granting extension %s", id.utf8().data());
 
-            if (withAudio)
-                process.grantAudioCaptureExtension();
-            if (withVideo)
-                process.grantVideoCaptureExtension();
-            process.send(Messages::WebProcess::GrantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions(ids, WTFMove(handles))), proxy.page().pageID());
-        }
+        if (withAudio)
+            process.grantAudioCaptureExtension();
+        if (withVideo)
+            process.grantVideoCaptureExtension();
+        process.send(Messages::WebProcess::GrantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions(ids, WTFMove(handles))), 0);
     }
 #else
     UNUSED_PARAM(proxy);
@@ -125,20 +125,17 @@
     return true;
 }
 
-void UserMediaProcessManager::endedCaptureSession(UserMediaPermissionRequestManagerProxy& proxy)
+void UserMediaProcessManager::revokeSandboxExtensionsIfNeeded(WebProcessProxy& process)
 {
 #if ENABLE(SANDBOX_EXTENSIONS)
     bool hasAudioCapture = false;
     bool hasVideoCapture = false;
 
-    auto& process = proxy.page().process();
-    UserMediaPermissionRequestManagerProxy::forEach([&hasAudioCapture, &hasVideoCapture, &proxy, &process](auto& managerProxy) {
-        if (&proxy == &managerProxy || &process != &managerProxy.page().process())
+    UserMediaPermissionRequestManagerProxy::forEach([&hasAudioCapture, &hasVideoCapture, &process](auto& managerProxy) {
+        if (&process != &managerProxy.page().process())
             return;
-        if (managerProxy.page().hasActiveAudioStream())
-            hasAudioCapture = true;
-        if (managerProxy.page().hasActiveVideoStream())
-            hasVideoCapture = true;
+        hasAudioCapture |= managerProxy.page().isCapturingAudio();
+        hasVideoCapture |= managerProxy.page().isCapturingVideo();
     });
 
     if (hasAudioCapture && hasVideoCapture)
@@ -160,7 +157,7 @@
     for (const auto& id : params)
         RELEASE_LOG(WebRTC, "UserMediaProcessManager::endedCaptureSession - revoking extension %s", id.utf8().data());
 
-    process.send(Messages::WebProcess::RevokeUserMediaDeviceSandboxExtensions(params), proxy.page().pageID());
+    process.send(Messages::WebProcess::RevokeUserMediaDeviceSandboxExtensions(params), 0);
 #endif
 }
 

Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h (245334 => 245335)


--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -38,7 +38,7 @@
     bool willCreateMediaStream(UserMediaPermissionRequestManagerProxy&, bool withAudio, bool withVideo);
     void muteCaptureMediaStreamsExceptIn(WebPageProxy&);
 
-    void endedCaptureSession(UserMediaPermissionRequestManagerProxy&);
+    void revokeSandboxExtensionsIfNeeded(WebProcessProxy&);
 
     void setCaptureEnabled(bool);
     bool captureEnabled() const { return m_captureEnabled; }

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (245334 => 245335)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1297,6 +1297,8 @@
     bool isPlayingAudio() const { return !!(m_mediaState & WebCore::MediaProducer::IsPlayingAudio); }
     void isPlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags, uint64_t);
     void updatePlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags);
+    bool isCapturingAudio() const { return m_mediaState & WebCore::MediaProducer::AudioCaptureMask; }
+    bool isCapturingVideo() const { return m_mediaState & WebCore::MediaProducer::VideoCaptureMask; }
     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/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -137,7 +137,7 @@
     m_userMediaRequestToIDMap.remove(&request);
 }
 
-void UserMediaPermissionRequestManager::userMediaAccessWasGranted(uint64_t requestID, CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt)
+void UserMediaPermissionRequestManager::userMediaAccessWasGranted(uint64_t requestID, CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&& completionHandler)
 {
     auto request = m_idToUserMediaRequestMap.take(requestID);
     if (!request)
@@ -144,7 +144,7 @@
         return;
     removeMediaRequestFromMaps(*request);
 
-    request->allow(WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(deviceIdentifierHashSalt));
+    request->allow(WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(deviceIdentifierHashSalt), WTFMove(completionHandler));
 }
 
 void UserMediaPermissionRequestManager::userMediaAccessWasDenied(uint64_t requestID, WebCore::UserMediaRequest::MediaAccessDenialReason reason, String&& invalidConstraint)

Modified: trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -42,7 +42,7 @@
 
     void startUserMediaRequest(WebCore::UserMediaRequest&);
     void cancelUserMediaRequest(WebCore::UserMediaRequest&);
-    void userMediaAccessWasGranted(uint64_t, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt);
+    void userMediaAccessWasGranted(uint64_t, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&&);
     void userMediaAccessWasDenied(uint64_t, WebCore::UserMediaRequest::MediaAccessDenialReason, String&&);
 
     void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -4153,9 +4153,9 @@
 
 #if ENABLE(MEDIA_STREAM)
 
-void WebPage::userMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice, String&& mediaDeviceIdentifierHashSalt)
+void WebPage::userMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice, String&& mediaDeviceIdentifierHashSalt, CompletionHandler<void()>&& completionHandler)
 {
-    m_userMediaPermissionRequestManager->userMediaAccessWasGranted(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(mediaDeviceIdentifierHashSalt));
+    m_userMediaPermissionRequestManager->userMediaAccessWasGranted(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(mediaDeviceIdentifierHashSalt), WTFMove(completionHandler));
 }
 
 void WebPage::userMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String&& invalidConstraint)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1445,7 +1445,7 @@
     void didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed);
 
 #if ENABLE(MEDIA_STREAM)
-    void userMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice&& audioDeviceUID, WebCore::CaptureDevice&& videoDeviceUID, String&& mediaDeviceIdentifierHashSalt);
+    void userMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice&& audioDeviceUID, WebCore::CaptureDevice&& videoDeviceUID, String&& mediaDeviceIdentifierHashSalt, CompletionHandler<void()>&&);
     void userMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String&& invalidConstraint);
 
     void didCompleteMediaDeviceEnumeration(uint64_t userMediaID, const Vector<WebCore::CaptureDevice>& devices, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-05-15 18:44:36 UTC (rev 245335)
@@ -351,7 +351,7 @@
 
 #if ENABLE(MEDIA_STREAM)
     # MediaSteam
-    UserMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice audioDevice, WebCore::CaptureDevice videoDevice, String mediaDeviceIdentifierHashSalt)
+    UserMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice audioDevice, WebCore::CaptureDevice videoDevice, String mediaDeviceIdentifierHashSalt) -> () Async
     UserMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint)
     DidCompleteMediaDeviceEnumeration(uint64_t userMediaID, Vector<WebCore::CaptureDevice> devices, String mediaDeviceIdentifierHashSalt, bool hasPersistentAccess)
     CaptureDevicesChanged()

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (245334 => 245335)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2019-05-15 18:29:40 UTC (rev 245334)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2019-05-15 18:44:36 UTC (rev 245335)
@@ -1857,11 +1857,30 @@
     }
 }
 
+static inline void checkDocumentsCaptureStateConsistency(const Vector<String>& extensionIDs)
+{
+#if !ASSERT_DISABLED
+    bool isCapturingAudio = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
+        return document->mediaState() & MediaProducer::AudioCaptureMask;
+    });
+    bool isCapturingVideo = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
+        return document->mediaState() & MediaProducer::VideoCaptureMask;
+    });
+
+    if (isCapturingAudio)
+        ASSERT(extensionIDs.findMatching([](auto& id) { return id.contains("microphone"); }) == notFound);
+    if (isCapturingVideo)
+        ASSERT(extensionIDs.findMatching([](auto& id) { return id.contains("camera"); }) == notFound);
+#endif
+}
+
 void WebProcess::revokeUserMediaDeviceSandboxExtensions(const Vector<String>& extensionIDs)
 {
+    checkDocumentsCaptureStateConsistency(extensionIDs);
+
     for (const auto& extensionID : extensionIDs) {
         auto extension = m_mediaCaptureSandboxExtensions.take(extensionID);
-        ASSERT(extension);
+        ASSERT(extension || MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled());
         if (extension) {
             extension->revoke();
             RELEASE_LOG(WebRTC, "UserMediaPermissionRequestManager::revokeUserMediaDeviceSandboxExtensions - revoked extension %s", extensionID.utf8().data());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to