WebKit Bugzilla
Attachment 361347 Details for
Bug 194312
: Make sure to clear sources from UserMediaCaptureManagerProxy and UserMediaCaptureManager when no longer needed
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-194312-20190206165714.patch (text/plain), 60.46 KB, created by
youenn fablet
on 2019-02-06 16:57:15 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2019-02-06 16:57:15 PST
Size:
60.46 KB
patch
obsolete
>Subversion Revision: 241024 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 33d6584bfde7103e976f58b1fc02237b35e53aa0..c5388ae005cae8318d885e6e9a0536389e2e6963 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,17 @@ >+2019-02-06 Youenn Fablet <youenn@apple.com> >+ >+ Make to clear sources from UserMediaCaptureManagerProxy and UserMediaCaptureManager when no longer needed >+ https://bugs.webkit.org/show_bug.cgi?id=194312 >+ >+ Reviewed by Eric Carlson. >+ >+ Add a way for sources to know when they are ended, i.e. that they will never be started again. >+ No observable change of behavior. >+ >+ * platform/mediastream/RealtimeMediaSource.cpp: >+ (WebCore::RealtimeMediaSource::requestStop): >+ * platform/mediastream/RealtimeMediaSource.h: >+ > 2019-02-06 Zalan Bujtas <zalan@apple.com> > > [LFC][IFC] Move line layout code to a dedicated file >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index e6bab68afd569566b456240507bfd96d6e6e397d..ee64c0e957766af295ec40ac40dcbbdca1fef210 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,79 @@ >+2019-02-06 Youenn Fablet <youenn@apple.com> >+ >+ Make to clear sources from UserMediaCaptureManagerProxy and UserMediaCaptureManager when no longer needed >+ https://bugs.webkit.org/show_bug.cgi?id=194312 >+ >+ Reviewed by Eric Carlson. >+ >+ Sources in UserMediaCaptureManager and Proxy are never removed once added to their HashMap. >+ Use the 'ended' mechanism to do the clean-up on WebProcess side. >+ As part of this clean-up, send IPC to UIProcess to do clean-up on proxy side. >+ On WebProcess crash case, clean-up the proxy as well. >+ >+ * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp: >+ (WebKit::UserMediaCaptureManagerProxy::createMediaSourceForCaptureDeviceWithConstraints): >+ (WebKit::UserMediaCaptureManagerProxy::end): >+ (WebKit::UserMediaCaptureManagerProxy::clear): >+ * UIProcess/Cocoa/UserMediaCaptureManagerProxy.h: >+ * UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in: >+ * UIProcess/WebProcessProxy.cpp: >+ (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch): >+ * WebProcess/cocoa/UserMediaCaptureManager.cpp: >+ (WebKit::UserMediaCaptureManager::sourceEnded): >+ * WebProcess/cocoa/UserMediaCaptureManager.h: >+ >+2019-02-06 Youenn Fablet <youenn@apple.com> >+ >+ Filter out Overconstrainederror.constraint when getUserMedia is not granted >+ https://bugs.webkit.org/show_bug.cgi?id=194240 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Make sure in UIProcess to filter out constraint if either the page had not gum granted >+ or it has not persistent access. >+ >+ Refactor UserMediaPermissionRequestManagerProxy to make the implementation easier to understand. >+ Some further refactoring might follow. >+ >+ Covered by added test. >+ >+ * UIProcess/UserMediaPermissionCheckProxy.cpp: >+ (WebKit::UserMediaPermissionCheckProxy::setUserMediaAccessInfo): >+ * UIProcess/UserMediaPermissionRequestManagerProxy.cpp: >+ (WebKit::UserMediaPermissionRequestManagerProxy::captureDevicesChanged): >+ (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted): >+ (WebKit::UserMediaPermissionRequestManagerProxy::grantAccess): >+ (WebKit::UserMediaPermissionRequestManagerProxy::getRequestAction): >+ (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame): >+ (WebKit::UserMediaPermissionRequestManagerProxy::processUserMediaPermissionRequest): >+ (WebKit::UserMediaPermissionRequestManagerProxy::processUserMediaPermissionInvalidRequest): >+ (WebKit::UserMediaPermissionRequestManagerProxy::processUserMediaPermissionValidRequest): >+ (WebKit::UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo): >+ (WebKit::UserMediaPermissionRequestManagerProxy::wasGrantedVideoOrAudioAccess): >+ (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList): >+ (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): >+ (WebKit::UserMediaPermissionRequestManagerProxy::createPermissionRequest): Deleted. >+ * UIProcess/UserMediaPermissionRequestManagerProxy.h: >+ * UIProcess/UserMediaPermissionRequestProxy.h: >+ (WebKit::UserMediaPermissionRequestProxy::isPending const): >+ (WebKit::UserMediaPermissionRequestProxy::setEligibleVideoDeviceUIDs): >+ (WebKit::UserMediaPermissionRequestProxy::setEligibleAudioDeviceUIDs): >+ (WebKit::UserMediaPermissionRequestProxy::hasAudioDevice const): >+ (WebKit::UserMediaPermissionRequestProxy::hasVideoDevice const): >+ (WebKit::UserMediaPermissionRequestProxy::hasPersistentAccess const): >+ (WebKit::UserMediaPermissionRequestProxy::setHasPersistentAccess): >+ (WebKit::UserMediaPermissionRequestProxy::userMediaID const): >+ (WebKit::UserMediaPermissionRequestProxy::topLevelDocumentSecurityOrigin const): >+ (WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin const): >+ (WebKit::UserMediaPermissionRequestProxy::userRequest const): >+ (WebKit::UserMediaPermissionRequestProxy::setDeviceIdentifierHashSalt): >+ (WebKit::UserMediaPermissionRequestProxy::deviceIdentifierHashSalt const): >+ (WebKit::UserMediaPermissionRequestProxy::audioDevice const): >+ (WebKit::UserMediaPermissionRequestProxy::videoDevice const): >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::requestUserMediaPermissionForFrame): >+ * UIProcess/WebPageProxy.h: >+ > 2019-02-06 Michael Catanzaro <mcatanzaro@igalia.com> > > REGRESSION(r240785): [SOUP] Broke cookie persistent storage >diff --git a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp >index 95fa95ed4f94b84cd09d6f18bbfdf61d53f588f9..09d0db9b4c119c14fca34d3fa3aa52cc1474d47b 100644 >--- a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp >+++ b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp >@@ -137,7 +137,7 @@ void MediaStreamTrackPrivate::endTrack() > m_isEnded = true; > updateReadyState(); > >- m_source->requestStop(this); >+ m_source->requestToEnd(*this); > > forEachObserver([this](auto& observer) { > observer.trackEnded(*this); >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >index 96cf5d99c3bb25e29c2f6bb396c8b5b802679196..7f39db216da8abeec76344379e51b1a7e941852d 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp >@@ -172,7 +172,7 @@ void RealtimeMediaSource::audioSamplesAvailable(const MediaTime& time, const Pla > > void RealtimeMediaSource::start() > { >- if (m_isProducingData) >+ if (m_isProducingData || m_isEnded) > return; > > m_isProducingData = true; >@@ -195,7 +195,7 @@ void RealtimeMediaSource::stop() > stopProducingData(); > } > >-void RealtimeMediaSource::requestStop(Observer* callingObserver) >+void RealtimeMediaSource::requestToEnd(Observer& callingObserver) > { > if (!m_isProducingData) > return; >@@ -208,10 +208,14 @@ void RealtimeMediaSource::requestStop(Observer* callingObserver) > if (hasObserverPreventingStopping) > return; > >+ auto protectedThis = makeRef(*this); >+ > stop(); >+ m_isEnded = true; >+ hasEnded(); > > forEachObserver([callingObserver](auto& observer) { >- if (&observer != callingObserver) >+ if (&observer != &callingObserver) > observer.sourceStopped(); > }); > } >diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h >index 8e462c7e8869ed268a90496eb7f5bde078e9b5f4..79a79e105886df5c990894105f2e10887ceb2d00 100644 >--- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h >+++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h >@@ -100,7 +100,7 @@ public: > bool isProducingData() const { return m_isProducingData; } > void start(); > void stop(); >- void requestStop(Observer* callingObserver = nullptr); >+ void requestToEnd(Observer& callingObserver); > > bool muted() const { return m_muted; } > void setMuted(bool); >@@ -211,6 +211,8 @@ private: > virtual void stopProducingData() { } > virtual void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) { } > >+ virtual void hasEnded() { } >+ > void forEachObserver(const WTF::Function<void(Observer&)>&) const; > > bool m_muted { false }; >@@ -238,6 +240,7 @@ private: > bool m_interrupted { false }; > bool m_captureDidFailed { false }; > bool m_isRemote { false }; >+ bool m_isEnded { false }; > }; > > struct CaptureSourceOrError { >diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp >index 056d5c342dd05b529c6f26a129b7207fe41343f7..c4540e70b13770bbd7a3533e0e644f2ff7449b56 100644 >--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp >+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp >@@ -161,7 +161,8 @@ void UserMediaCaptureManagerProxy::createMediaSourceForCaptureDeviceWithConstrai > auto source = sourceOrError.source(); > source->setIsRemote(true); > settings = source->settings(); >- m_proxies.set(id, std::make_unique<SourceProxy>(id, *this, WTFMove(source))); >+ ASSERT(!m_proxies.contains(id)); >+ m_proxies.add(id, std::make_unique<SourceProxy>(id, *this, WTFMove(source))); > } else > invalidConstraints = WTFMove(sourceOrError.errorMessage); > } >@@ -180,6 +181,11 @@ void UserMediaCaptureManagerProxy::stopProducingData(uint64_t id) > iter->value->source().stop(); > } > >+void UserMediaCaptureManagerProxy::end(uint64_t id) >+{ >+ m_proxies.remove(id); >+} >+ > void UserMediaCaptureManagerProxy::capabilities(uint64_t id, WebCore::RealtimeMediaSourceCapabilities& capabilities) > { > auto iter = m_proxies.find(id); >@@ -208,6 +214,11 @@ void UserMediaCaptureManagerProxy::applyConstraints(uint64_t id, const WebCore:: > m_process.send(Messages::UserMediaCaptureManager::ApplyConstraintsFailed(id, result.value().first, result.value().second), 0); > } > >+void UserMediaCaptureManagerProxy::clear() >+{ >+ m_proxies.clear(); >+} >+ > } > > #endif >diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h >index 3bf921fe680642fcc76e1fbdabf311ea4eda73fd..a52fea25f4d5c334179214e4213705b491ffff57 100644 >--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h >+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h >@@ -40,10 +40,11 @@ class WebProcessProxy; > > class UserMediaCaptureManagerProxy : private IPC::MessageReceiver { > public: >- UserMediaCaptureManagerProxy(WebProcessProxy&); >+ explicit UserMediaCaptureManagerProxy(WebProcessProxy&); > ~UserMediaCaptureManagerProxy(); > > WebProcessProxy& process() const { return m_process; } >+ void clear(); > > private: > // IPC::MessageReceiver >@@ -53,6 +54,7 @@ private: > void createMediaSourceForCaptureDeviceWithConstraints(uint64_t id, const WebCore::CaptureDevice& deviceID, String&&, const WebCore::MediaConstraints&, bool& succeeded, String& invalidConstraints, WebCore::RealtimeMediaSourceSettings&); > void startProducingData(uint64_t); > void stopProducingData(uint64_t); >+ void end(uint64_t); > void capabilities(uint64_t, WebCore::RealtimeMediaSourceCapabilities&); > void setMuted(uint64_t, bool); > void applyConstraints(uint64_t, const WebCore::MediaConstraints&); >diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in >index 20db1762fb1682a92447e4788526545f897f9ab6..2a26de7d718e1510e01ea8f4a5e8f7e0c00f0b91 100644 >--- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in >+++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in >@@ -27,6 +27,7 @@ messages -> UserMediaCaptureManagerProxy { > CreateMediaSourceForCaptureDeviceWithConstraints(uint64_t id, WebCore::CaptureDevice device, String hashSalt, struct WebCore::MediaConstraints constraints) -> (bool success, String invalidConstraints, WebCore::RealtimeMediaSourceSettings settings) LegacySync > StartProducingData(uint64_t id) > StopProducingData(uint64_t id) >+ End(uint64_t id) > Capabilities(uint64_t id) -> (WebCore::RealtimeMediaSourceCapabilities capabilities) LegacySync > SetMuted(uint64_t id, bool muted) > ApplyConstraints(uint64_t id, struct WebCore::MediaConstraints constraints) >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.cpp b/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.cpp >index 96513eb011b000de0371bf7d222508214f2da7df..90d18e3823dd4af53468cdb2c715e60c9ceea917 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.cpp >+++ b/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.cpp >@@ -41,20 +41,28 @@ UserMediaPermissionCheckProxy::UserMediaPermissionCheckProxy(uint64_t frameID, C > { > } > >+UserMediaPermissionCheckProxy::~UserMediaPermissionCheckProxy() >+{ >+ invalidate(); >+} >+ > void UserMediaPermissionCheckProxy::setUserMediaAccessInfo(bool allowed) > { > ASSERT(m_completionHandler); > if (!m_completionHandler) > return; > >- m_completionHandler(allowed); >- m_completionHandler = nullptr; >+ auto completionHandler = WTFMove(m_completionHandler); >+ completionHandler(allowed); > } > > void UserMediaPermissionCheckProxy::invalidate() > { >- m_completionHandler = nullptr; >+ if (!m_completionHandler) >+ return; >+ >+ auto completionHandler = WTFMove(m_completionHandler); >+ completionHandler({ }); > } > > } // namespace WebKit >- >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.h b/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.h >index 6a089506cea388d1d4c3d6defda5fe0e0aee57c4..dd0205bcc4c57ea9bb7eabc679db5f35b9722fef 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.h >+++ b/Source/WebKit/UIProcess/UserMediaPermissionCheckProxy.h >@@ -27,7 +27,7 @@ > > #include "APIObject.h" > #include <WebCore/MediaConstraints.h> >-#include <wtf/Function.h> >+#include <wtf/CompletionHandler.h> > #include <wtf/text/WTFString.h> > > namespace WebCore { >@@ -39,7 +39,7 @@ namespace WebKit { > class UserMediaPermissionCheckProxy : public API::ObjectImpl<API::Object::Type::UserMediaPermissionCheck> { > public: > >- using CompletionHandler = WTF::Function<void(bool allowed)>; >+ using CompletionHandler = WTF::CompletionHandler<void(Optional<bool> allowed)>; > > static Ref<UserMediaPermissionCheckProxy> create(uint64_t frameID, CompletionHandler&& handler, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin) > { >@@ -56,6 +56,7 @@ public: > > private: > UserMediaPermissionCheckProxy(uint64_t frameID, CompletionHandler&&, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin); >+ ~UserMediaPermissionCheckProxy(); > > uint64_t m_frameID; > CompletionHandler m_completionHandler; >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >index 9fa3a50d960a42500ae4ec5bf47f5ac99047ce84..56008436d18879f82a2776f9013951568268ff8c 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >+++ b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp >@@ -75,8 +75,6 @@ void UserMediaPermissionRequestManagerProxy::invalidatePendingRequests() > request->invalidate(); > m_pendingUserMediaRequests.clear(); > >- for (auto& request : m_pendingDeviceRequests.values()) >- request->invalidate(); > m_pendingDeviceRequests.clear(); > } > >@@ -92,23 +90,18 @@ void UserMediaPermissionRequestManagerProxy::captureDevicesChanged() > if (!m_page.isValid() || !m_page.mainFrame()) > return; > >- auto requestID = generateRequestID(); >- auto handler = [this, weakThis = makeWeakPtr(*this), requestID](bool originHasPersistentAccess) mutable { >- if (!weakThis) >+ auto handler = [this](Optional<bool> originHasPersistentAccess) mutable { >+ if (!originHasPersistentAccess || !m_page.isValid()) > return; > >- auto pendingRequest = m_pendingDeviceRequests.take(requestID); >- if (!pendingRequest || !m_page.isValid()) >- return; >- >- if (m_grantedRequests.isEmpty() && !originHasPersistentAccess) >+ if (m_grantedRequests.isEmpty() && !*originHasPersistentAccess) > return; > > m_page.process().send(Messages::WebPage::CaptureDevicesChanged(), m_page.pageID()); > }; > > auto origin = WebCore::SecurityOrigin::create(m_page.mainFrame()->url()); >- getUserMediaPermissionInfo(requestID, m_page.mainFrame()->frameID(), WTFMove(handler), origin.get(), WTFMove(origin)); >+ getUserMediaPermissionInfo(m_page.mainFrame()->frameID(), origin.get(), WTFMove(origin), WTFMove(handler)); > #endif > } > >@@ -117,13 +110,6 @@ void UserMediaPermissionRequestManagerProxy::clearCachedState() > invalidatePendingRequests(); > } > >-Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createPermissionRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, Vector<CaptureDevice>&& audioDevices, Vector<CaptureDevice>&& videoDevices, MediaStreamRequest&& request) >-{ >- auto permissionRequest = UserMediaPermissionRequestProxy::create(*this, userMediaID, mainFrameID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDevices), WTFMove(videoDevices), WTFMove(request)); >- m_pendingUserMediaRequests.add(userMediaID, permissionRequest.ptr()); >- return permissionRequest; >-} >- > #if ENABLE(MEDIA_STREAM) > static uint64_t toWebCore(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason reason) > { >@@ -188,15 +174,18 @@ void UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted(uint64_t > if (!request) > return; > >- m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin(), [this, weakThis = makeWeakPtr(*this), userMediaID, audioDevice = WTFMove(audioDevice), videoDevice = WTFMove(videoDevice), localRequest = request.copyRef()] (String&& deviceIDHashSalt) mutable { >+ auto& userMediaDocumentSecurityOrigin = request->userMediaDocumentSecurityOrigin(); >+ auto& topLevelDocumentSecurityOrigin = request->topLevelDocumentSecurityOrigin(); >+ m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(userMediaDocumentSecurityOrigin, topLevelDocumentSecurityOrigin, [this, weakThis = makeWeakPtr(*this), request = request.releaseNonNull()] (String&& deviceIDHashSalt) mutable { > if (!weakThis) > return; >- if (grantAccess(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(deviceIDHashSalt))) { >- m_grantedRequests.append(localRequest.releaseNonNull()); >- if (m_hasFilteredDeviceList) >- captureDevicesChanged(); >- m_hasFilteredDeviceList = false; >- } >+ if (!grantAccess(request)) >+ return; >+ >+ m_grantedRequests.append(WTFMove(request)); >+ if (m_hasFilteredDeviceList) >+ captureDevicesChanged(); >+ m_hasFilteredDeviceList = false; > }); > #else > UNUSED_PARAM(userMediaID); >@@ -266,14 +255,14 @@ bool UserMediaPermissionRequestManagerProxy::wasRequestDenied(uint64_t mainFrame > return false; > } > >-bool UserMediaPermissionRequestManagerProxy::grantAccess(uint64_t userMediaID, const CaptureDevice audioDevice, const CaptureDevice videoDevice, const String& deviceIdentifierHashSalt) >+bool UserMediaPermissionRequestManagerProxy::grantAccess(const UserMediaPermissionRequestProxy& request) > { >- if (!UserMediaProcessManager::singleton().willCreateMediaStream(*this, !!audioDevice, !!videoDevice)) { >- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::OtherFailure, "Unable to extend sandbox."); >+ if (!UserMediaProcessManager::singleton().willCreateMediaStream(*this, request.hasAudioDevice(), request.hasVideoDevice())) { >+ denyRequest(request.userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::OtherFailure, "Unable to extend sandbox."); > return false; > } > >- m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDevice, videoDevice, deviceIdentifierHashSalt), m_page.pageID()); >+ m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(request.userMediaID(), request.audioDevice(), request.videoDevice(), request.deviceIdentifierHashSalt()), m_page.pageID()); > return true; > } > #endif >@@ -296,25 +285,26 @@ void UserMediaPermissionRequestManagerProxy::scheduleNextRejection() > } > > #if ENABLE(MEDIA_STREAM) >-UserMediaPermissionRequestManagerProxy::RequestAction UserMediaPermissionRequestManagerProxy::getRequestAction(uint64_t frameID, SecurityOrigin& userMediaDocumentOrigin, SecurityOrigin& topLevelDocumentOrigin, const MediaStreamRequest& userRequest, Vector<CaptureDevice>& audioDevices, Vector<CaptureDevice>& videoDevices) >+UserMediaPermissionRequestManagerProxy::RequestAction UserMediaPermissionRequestManagerProxy::getRequestAction(const UserMediaPermissionRequestProxy& request) > { >- bool requestingScreenCapture = userRequest.type == MediaStreamRequest::Type::DisplayMedia; >- ASSERT(!(requestingScreenCapture && videoDevices.isEmpty())); >- ASSERT(!(requestingScreenCapture && !audioDevices.isEmpty())); >- bool requestingCamera = !requestingScreenCapture && !videoDevices.isEmpty(); >- bool requestingMicrophone = !audioDevices.isEmpty(); >+ bool requestingScreenCapture = request.requestType() == MediaStreamRequest::Type::DisplayMedia; >+ bool requestingCamera = !requestingScreenCapture && request.hasVideoDevice(); >+ bool requestingMicrophone = request.hasAudioDevice(); > >- if (wasRequestDenied(frameID, userMediaDocumentOrigin, topLevelDocumentOrigin, requestingMicrophone, requestingCamera, requestingScreenCapture)) >+ ASSERT(!(requestingScreenCapture && !request.hasVideoDevice())); >+ ASSERT(!(requestingScreenCapture && requestingMicrophone)); >+ >+ if (wasRequestDenied(request.frameID(), request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin(), requestingMicrophone, requestingCamera, requestingScreenCapture)) > return RequestAction::Deny; > >- if (userRequest.type == MediaStreamRequest::Type::DisplayMedia) >+ if (request.requestType() == MediaStreamRequest::Type::DisplayMedia) > return RequestAction::Prompt; > >- return searchForGrantedRequest(frameID, userMediaDocumentOrigin, topLevelDocumentOrigin, requestingMicrophone, requestingCamera) ? RequestAction::Grant : RequestAction::Prompt; >+ return searchForGrantedRequest(request.frameID(), request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin(), requestingMicrophone, requestingCamera) ? RequestAction::Grant : RequestAction::Prompt; > } > #endif > >-void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, const MediaStreamRequest& userRequest) >+void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, MediaStreamRequest&& userRequest) > { > #if ENABLE(MEDIA_STREAM) > if (!UserMediaProcessManager::singleton().captureEnabled()) { >@@ -323,95 +313,62 @@ void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame( > return; > } > >- RealtimeMediaSourceCenter::InvalidConstraintsHandler invalidHandler = [this, userMediaID](const String& invalidConstraint) { >- if (!m_page.isValid()) >- return; >+ if (!m_page.isValid()) >+ return; > >- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::InvalidConstraint, invalidConstraint); >- }; >+ auto userMediaOrigin = API::SecurityOrigin::create(userMediaDocumentOrigin.get()); >+ auto topLevelOrigin = API::SecurityOrigin::create(topLevelDocumentOrigin.get()); > >- auto validHandler = [this, userMediaID, frameID, userMediaDocumentOrigin = userMediaDocumentOrigin.copyRef(), topLevelDocumentOrigin = topLevelDocumentOrigin.copyRef(), localUserRequest = userRequest](Vector<CaptureDevice>&& audioDevices, Vector<CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt) mutable { >- if (!m_page.isValid() || !m_page.mainFrame()) >- return; >+ auto request = m_pendingUserMediaRequests.add(userMediaID, UserMediaPermissionRequestProxy::create(*this, userMediaID, m_page.mainFrame()->frameID(), frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), { }, { }, WTFMove(userRequest))).iterator->value.copyRef(); > >- if (videoDevices.isEmpty() && audioDevices.isEmpty()) { >- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString()); >+ getUserMediaPermissionInfo(frameID, request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin(), [this, request = request.releaseNonNull()](Optional<bool> hasPersistentAccess) mutable { >+ if (!request->isPending()) > return; >- } > >- auto action = getRequestAction(m_page.mainFrame()->frameID(), userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get(), localUserRequest, audioDevices, videoDevices); >- if (action == RequestAction::Deny) { >- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied, emptyString()); >+ if (!hasPersistentAccess) { >+ request->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::OtherFailure); > return; > } > >- if (action == RequestAction::Grant) { >- ASSERT(localUserRequest.type != MediaStreamRequest::Type::DisplayMedia); >+ processUserMediaPermissionRequest(WTFMove(request), *hasPersistentAccess); >+ }); >+} > >- 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. >- auto audioDevice = !audioDevices.isEmpty() ? audioDevices[0] : CaptureDevice(); >- auto videoDevice = !videoDevices.isEmpty() ? videoDevices[0] : CaptureDevice(); >- 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), WTFMove(localUserRequest))); >+void UserMediaPermissionRequestManagerProxy::processUserMediaPermissionRequest(Ref<UserMediaPermissionRequestProxy>&& request, bool hasPersistentAccess) >+{ >+ if (hasPersistentAccess) >+ request->setHasPersistentAccess(); > >+ auto& userMediaDocumentSecurityOrigin = request->userMediaDocumentSecurityOrigin(); >+ auto& topLevelDocumentSecurityOrigin = request->topLevelDocumentSecurityOrigin(); >+ m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(userMediaDocumentSecurityOrigin, topLevelDocumentSecurityOrigin, [this, request = WTFMove(request)] (String&& deviceIDHashSalt) mutable { >+ if (!request->isPending()) > 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(localUserRequest)); >- >- if (m_page.isControlledByAutomation()) { >- if (WebAutomationSession* automationSession = m_page.process().processPool().automationSession()) { >- if (automationSession->shouldAllowGetUserMediaForPage(m_page)) >- pendingRequest->allow(); >- else >- userMediaAccessWasDenied(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied); > >+ RealtimeMediaSourceCenter::InvalidConstraintsHandler invalidHandler = [this, request = request.copyRef()](const String& invalidConstraint) { >+ if (!request->isPending()) > return; >- } >- } > >- if (m_page.preferences().mockCaptureDevicesEnabled() && !m_page.preferences().mockCaptureDevicesPromptEnabled()) { >- pendingRequest->allow(); >- return; >- } >- >- // If page navigated, there is no need to call the page client for authorization. >- auto* webFrame = m_page.process().webFrame(frameID); >- >- if (!webFrame || !SecurityOrigin::createFromString(m_page.pageLoadState().activeURL())->isSameSchemeHostPort(topLevelOrigin->securityOrigin())) { >- denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString()); >- return; >- } >+ if (!m_page.isValid()) >+ return; > >- // FIXME: Remove webFrame, userMediaOrigin and topLevelOrigin from this uiClient API call. >- m_page.uiClient().decidePolicyForUserMediaPermissionRequest(m_page, *webFrame, WTFMove(userMediaOrigin), WTFMove(topLevelOrigin), pendingRequest.get()); >- }; >+ processUserMediaPermissionInvalidRequest(request.get(), invalidConstraint); >+ }; > >- auto requestID = generateRequestID(); >- auto havePermissionInfoHandler = [this, weakThis = makeWeakPtr(*this), requestID, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), localUserRequest = userRequest](bool originHasPersistentAccess) mutable { >- if (!weakThis) >- return; >+ auto validHandler = [this, request = request.copyRef()](Vector<CaptureDevice>&& audioDevices, Vector<CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt) mutable { >+ if (!request->isPending()) >+ return; > >- auto pendingRequest = m_pendingDeviceRequests.take(requestID); >- if (!pendingRequest) >- return; >+ if (!m_page.isValid() || !m_page.mainFrame()) >+ return; > >- if (!m_page.isValid()) >- return; >+ processUserMediaPermissionValidRequest(WTFMove(request), WTFMove(audioDevices), WTFMove(videoDevices), WTFMove(deviceIdentifierHashSalt)); >+ }; > > syncWithWebCorePrefs(); > >- m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(pendingRequest.value()->userMediaDocumentSecurityOrigin(), pendingRequest.value()->topLevelDocumentSecurityOrigin(), [validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), localUserRequest = localUserRequest] (String&& deviceIDHashSalt) mutable { >- RealtimeMediaSourceCenter::singleton().validateRequestConstraints(WTFMove(validHandler), WTFMove(invalidHandler), WTFMove(localUserRequest), WTFMove(deviceIDHashSalt)); >- }); >- }; >- >- getUserMediaPermissionInfo(requestID, frameID, WTFMove(havePermissionInfoHandler), WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin)); >+ RealtimeMediaSourceCenter::singleton().validateRequestConstraints(WTFMove(validHandler), WTFMove(invalidHandler), request->userRequest(), WTFMove(deviceIDHashSalt)); >+ }); > #else > UNUSED_PARAM(userMediaID); > UNUSED_PARAM(frameID); >@@ -422,19 +379,93 @@ void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame( > } > > #if ENABLE(MEDIA_STREAM) >-void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t requestID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&& handler, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin) >+void UserMediaPermissionRequestManagerProxy::processUserMediaPermissionInvalidRequest(const UserMediaPermissionRequestProxy& request, const String& invalidConstraint) >+{ >+ bool filterConstraint = !request.hasPersistentAccess() && !wasGrantedVideoOrAudioAccess(request.frameID(), request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin()); >+ >+ denyRequest(request.userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::InvalidConstraint, filterConstraint ? String { } : invalidConstraint); >+} >+ >+void UserMediaPermissionRequestManagerProxy::processUserMediaPermissionValidRequest(Ref<UserMediaPermissionRequestProxy>&& request, Vector<CaptureDevice>&& audioDevices, Vector<CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt) >+{ >+ if (videoDevices.isEmpty() && audioDevices.isEmpty()) { >+ denyRequest(request->userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString()); >+ return; >+ } >+ >+ request->setDeviceIdentifierHashSalt(WTFMove(deviceIdentifierHashSalt)); >+ request->setEligibleVideoDeviceUIDs(WTFMove(videoDevices)); >+ request->setEligibleAudioDeviceUIDs(WTFMove(audioDevices)); >+ >+ auto action = getRequestAction(request); >+ if (action == RequestAction::Deny) { >+ denyRequest(request->userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied, emptyString()); >+ return; >+ } >+ >+ if (action == RequestAction::Grant) { >+ ASSERT(request->requestType() != MediaStreamRequest::Type::DisplayMedia); >+ >+ if (m_page.isViewVisible()) >+ grantAccess(request); >+ else >+ m_pregrantedRequests.append(WTFMove(request)); >+ >+ return; >+ } >+ >+ if (m_page.isControlledByAutomation()) { >+ if (WebAutomationSession* automationSession = m_page.process().processPool().automationSession()) { >+ if (automationSession->shouldAllowGetUserMediaForPage(m_page)) >+ request->allow(); >+ else >+ userMediaAccessWasDenied(request->userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied); >+ >+ return; >+ } >+ } >+ >+ if (m_page.preferences().mockCaptureDevicesEnabled() && !m_page.preferences().mockCaptureDevicesPromptEnabled()) { >+ request->allow(); >+ return; >+ } >+ >+ // If page navigated, there is no need to call the page client for authorization. >+ auto* webFrame = m_page.process().webFrame(request->frameID()); >+ >+ if (!webFrame || !SecurityOrigin::createFromString(m_page.pageLoadState().activeURL())->isSameSchemeHostPort(request->topLevelDocumentSecurityOrigin())) { >+ denyRequest(request->userMediaID(), UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString()); >+ return; >+ } >+ >+ // FIXME: Remove webFrame, userMediaOrigin and topLevelOrigin from this uiClient API call. >+ auto userMediaOrigin = API::SecurityOrigin::create(request->userMediaDocumentSecurityOrigin()); >+ auto topLevelOrigin = API::SecurityOrigin::create(request->topLevelDocumentSecurityOrigin()); >+ m_page.uiClient().decidePolicyForUserMediaPermissionRequest(m_page, *webFrame, WTFMove(userMediaOrigin), WTFMove(topLevelOrigin), request); >+} >+ >+void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, CompletionHandler<void(Optional<bool>)>&& handler) > { > auto* webFrame = m_page.process().webFrame(frameID); > if (!webFrame || !SecurityOrigin::createFromString(m_page.pageLoadState().activeURL())->isSameSchemeHostPort(topLevelDocumentOrigin.get())) { >- handler(false); >+ handler({ }); > return; > } > > auto userMediaOrigin = API::SecurityOrigin::create(userMediaDocumentOrigin.get()); > auto topLevelOrigin = API::SecurityOrigin::create(topLevelDocumentOrigin.get()); >- auto request = UserMediaPermissionCheckProxy::create(frameID, WTFMove(handler), WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin)); > >- m_pendingDeviceRequests.add(requestID, request.copyRef()); >+ auto requestID = generateRequestID(); >+ m_pendingDeviceRequests.add(requestID); >+ >+ auto request = UserMediaPermissionCheckProxy::create(frameID, [this, weakThis = makeWeakPtr(*this), requestID, handler = WTFMove(handler)](Optional<bool> allowed) mutable { >+ if (!weakThis || !m_pendingDeviceRequests.remove(requestID) || !allowed) { >+ handler({ }); >+ return; >+ } >+ handler(*allowed); >+ }, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin)); >+ > // FIXME: Remove webFrame, userMediaOrigin and topLevelOrigin from this uiClient API call. > m_page.uiClient().checkUserMediaPermissionForOrigin(m_page, *webFrame, userMediaOrigin.get(), topLevelOrigin.get(), request.get()); > } >@@ -457,12 +488,9 @@ bool UserMediaPermissionRequestManagerProxy::wasGrantedVideoOrAudioAccess(uint64 > > return false; > } >-#endif > >-void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin) >+Vector<CaptureDevice> UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList(bool revealIdsAndLabels, const String& deviceIDHashSalt) > { >-#if ENABLE(MEDIA_STREAM) >- > #if PLATFORM(IOS_FAMILY) > static const int defaultMaximumCameraCount = 2; > #else >@@ -470,19 +498,56 @@ void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint6 > #endif > static const int defaultMaximumMicrophoneCount = 1; > >- auto requestID = generateRequestID(); >- auto completionHandler = [this, weakThis = makeWeakPtr(*this), requestID, userMediaID, requestOrigin = userMediaDocumentOrigin.copyRef(), topOrigin = topLevelDocumentOrigin.copyRef()](bool originHasPersistentAccess) mutable { >- if (!weakThis) >+ auto devices = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices(); >+ int cameraCount = 0; >+ int microphoneCount = 0; >+ >+ Vector<CaptureDevice> filteredDevices; >+ for (const auto& device : devices) { >+ if (!device.enabled() || (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)) >+ continue; >+ >+ if (!revealIdsAndLabels) { >+ if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount) >+ continue; >+ if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount) >+ continue; >+ } >+ >+ auto label = emptyString(); >+ auto id = emptyString(); >+ auto groupId = emptyString(); >+ if (revealIdsAndLabels) { >+ label = device.label(); >+ id = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(device.persistentId(), deviceIDHashSalt); >+ groupId = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(device.groupId(), deviceIDHashSalt); >+ } >+ >+ filteredDevices.append(CaptureDevice(id, device.type(), label, groupId)); >+ } >+ >+ m_hasFilteredDeviceList = !revealIdsAndLabels; >+ return filteredDevices; >+} >+#endif >+ >+void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin) >+{ >+#if ENABLE(MEDIA_STREAM) >+ auto completionHandler = [this, userMediaID, frameID, userMediaDocumentOrigin = userMediaDocumentOrigin.copyRef(), topLevelDocumentOrigin = topLevelDocumentOrigin.copyRef()](Optional<bool> originHasPersistentAccess) mutable { >+ if (!originHasPersistentAccess) > return; > > if (!m_page.isValid()) > return; > >- m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(requestOrigin.get(), topOrigin.get(), [this, weakThis = WTFMove(weakThis), requestID, userMediaID, &originHasPersistentAccess] (String&& deviceIDHashSalt) { >- if (!weakThis) >- return; >- auto pendingRequest = m_pendingDeviceRequests.take(requestID); >- if (!pendingRequest) >+ auto requestID = generateRequestID(); >+ m_pendingDeviceRequests.add(requestID); >+ >+ auto& requestOrigin = userMediaDocumentOrigin.get(); >+ auto& topOrigin = topLevelDocumentOrigin.get(); >+ m_page.websiteDataStore().deviceIdHashSaltStorage().deviceIdHashSaltForOrigin(requestOrigin, topOrigin, [this, weakThis = makeWeakPtr(*this), requestID, frameID, userMediaID, userMediaDocumentOrigin = WTFMove(userMediaDocumentOrigin), topLevelDocumentOrigin = WTFMove(topLevelDocumentOrigin), originHasPersistentAccess = *originHasPersistentAccess] (String&& deviceIDHashSalt) { >+ if (!weakThis || !m_pendingDeviceRequests.remove(requestID)) > return; > > if (!m_page.isValid()) >@@ -490,43 +555,13 @@ void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint6 > > syncWithWebCorePrefs(); > >- auto devices = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices(); >- auto& request = *pendingRequest; >- bool revealIdsAndLabels = originHasPersistentAccess || wasGrantedVideoOrAudioAccess(request->frameID(), request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin()); >- int cameraCount = 0; >- int microphoneCount = 0; >- >- Vector<CaptureDevice> filteredDevices; >- for (const auto& device : devices) { >- if (!device.enabled() || (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)) >- continue; >- >- if (!revealIdsAndLabels) { >- if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount) >- continue; >- if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount) >- continue; >- } >- >- auto label = emptyString(); >- auto id = emptyString(); >- auto groupId = emptyString(); >- if (revealIdsAndLabels) { >- label = device.label(); >- id = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(device.persistentId(), deviceIDHashSalt); >- groupId = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(device.groupId(), deviceIDHashSalt); >- } >- >- filteredDevices.append(CaptureDevice(id, device.type(), label, groupId)); >- } >- >- m_hasFilteredDeviceList = !revealIdsAndLabels; >- >- m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration(userMediaID, WTFMove(filteredDevices), WTFMove(deviceIDHashSalt), originHasPersistentAccess), m_page.pageID()); >+ bool revealIdsAndLabels = originHasPersistentAccess || wasGrantedVideoOrAudioAccess(frameID, userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get()); >+ >+ m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration { userMediaID, computeFilteredDeviceList(revealIdsAndLabels, deviceIDHashSalt), deviceIDHashSalt, originHasPersistentAccess }, m_page.pageID()); > }); > }; > >- getUserMediaPermissionInfo(requestID, frameID, WTFMove(completionHandler), WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin)); >+ getUserMediaPermissionInfo(frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(completionHandler)); > #else > UNUSED_PARAM(userMediaID); > UNUSED_PARAM(frameID); >@@ -596,3 +631,4 @@ void UserMediaPermissionRequestManagerProxy::watchdogTimerFired() > } > > } // namespace WebKit >+ >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >index eacce6f92b65ffcc29be4d13788da81d91590558..a115c43867537ec8d53df5dfbe52e2ecd6915e1e 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >+++ b/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h >@@ -23,6 +23,7 @@ > #include "UserMediaPermissionRequestProxy.h" > #include <WebCore/MediaProducer.h> > #include <WebCore/SecurityOrigin.h> >+#include <wtf/CompletionHandler.h> > #include <wtf/HashMap.h> > #include <wtf/RunLoop.h> > #include <wtf/Seconds.h> >@@ -48,7 +49,7 @@ public: > > void invalidatePendingRequests(); > >- void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, const WebCore::MediaStreamRequest&); >+ void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, WebCore::MediaStreamRequest&&); > > void resetAccess(uint64_t mainFrameID); > void viewIsBecomingVisible(); >@@ -71,27 +72,33 @@ private: > Ref<UserMediaPermissionRequestProxy> createPermissionRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, WebCore::MediaStreamRequest&&); > void denyRequest(uint64_t userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint); > #if ENABLE(MEDIA_STREAM) >- bool grantAccess(uint64_t userMediaID, const WebCore::CaptureDevice audioDevice, const WebCore::CaptureDevice videoDevice, const String& deviceIdentifierHashSalt); >+ bool grantAccess(const UserMediaPermissionRequestProxy&); > > 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 needsScreenCapture); > >- void getUserMediaPermissionInfo(uint64_t requestID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin); >+ void getUserMediaPermissionInfo(uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, CompletionHandler<void(Optional<bool>)>&&); > > 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); >+ RequestAction getRequestAction(const UserMediaPermissionRequestProxy&); > > bool wasGrantedVideoOrAudioAccess(uint64_t, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin); >+ >+ Vector<WebCore::CaptureDevice> computeFilteredDeviceList(bool revealIdsAndLabels, const String& deviceIDHashSalt); >+ >+ void processUserMediaPermissionRequest(Ref<UserMediaPermissionRequestProxy>&&, bool hasPersistentAccess); >+ void processUserMediaPermissionInvalidRequest(const UserMediaPermissionRequestProxy&, const String& invalidConstraint); >+ void processUserMediaPermissionValidRequest(Ref<UserMediaPermissionRequestProxy>&&, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, String&& deviceIdentifierHashSalt); > #endif > > void watchdogTimerFired(); > > HashMap<uint64_t, RefPtr<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests; >- HashMap<uint64_t, Ref<UserMediaPermissionCheckProxy>> m_pendingDeviceRequests; >+ HashSet<uint64_t> m_pendingDeviceRequests; > > WebPageProxy& m_page; > >diff --git a/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h b/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h >index ac805e788be2317e0a7aaeb718909cf45bca8908..067f80203f1a5fdd3238c8ae29d7dcaca1aea12d 100644 >--- a/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h >+++ b/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h >@@ -48,21 +48,42 @@ public: > void deny(UserMediaAccessDenialReason = UserMediaAccessDenialReason::UserMediaDisabled); > > void invalidate(); >+ bool isPending() const { return m_manager; } > > bool requiresAudioCapture() const { return m_eligibleAudioDevices.size(); } > bool requiresVideoCapture() const { return !requiresDisplayCapture() && m_eligibleVideoDevices.size(); } > bool requiresDisplayCapture() const { return m_request.type == WebCore::MediaStreamRequest::Type::DisplayMedia && m_eligibleVideoDevices.size(); } > >+ void setEligibleVideoDeviceUIDs(Vector<WebCore::CaptureDevice>&& devices) { m_eligibleVideoDevices = WTFMove(devices); } >+ void setEligibleAudioDeviceUIDs(Vector<WebCore::CaptureDevice>&& devices) { m_eligibleAudioDevices = WTFMove(devices); } >+ > Vector<String> videoDeviceUIDs() const; > Vector<String> audioDeviceUIDs() const; >+ bool hasAudioDevice() const { return !m_eligibleAudioDevices.isEmpty(); } >+ bool hasVideoDevice() const { return !m_eligibleVideoDevices.isEmpty(); } >+ >+ bool hasPersistentAccess() const { return m_hasPersistentAccess; } >+ void setHasPersistentAccess() { m_hasPersistentAccess = true; } > >+ uint64_t userMediaID() const { return m_userMediaID; } > 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(); } >+ const WebCore::SecurityOrigin& topLevelDocumentSecurityOrigin() const { return m_topLevelDocumentSecurityOrigin.get(); } >+ const WebCore::SecurityOrigin& userMediaDocumentSecurityOrigin() const { return m_userMediaDocumentSecurityOrigin.get(); } >+ >+ const WebCore::MediaStreamRequest& userRequest() const { return m_request; } > > WebCore::MediaStreamRequest::Type requestType() const { return m_request.type; } > >+ void setDeviceIdentifierHashSalt(String&& salt) { m_deviceIdentifierHashSalt = WTFMove(salt); } >+ const String& deviceIdentifierHashSalt() const { return m_deviceIdentifierHashSalt; } >+ >+ WebCore::CaptureDevice audioDevice() const { return m_eligibleAudioDevices.isEmpty() ? WebCore::CaptureDevice { } : m_eligibleAudioDevices[0]; } >+ WebCore::CaptureDevice videoDevice() const { return m_eligibleVideoDevices.isEmpty() ? WebCore::CaptureDevice { } : m_eligibleVideoDevices[0]; } >+ > private: > UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, WebCore::MediaStreamRequest&&); > >@@ -75,6 +96,8 @@ private: > Vector<WebCore::CaptureDevice> m_eligibleVideoDevices; > Vector<WebCore::CaptureDevice> m_eligibleAudioDevices; > WebCore::MediaStreamRequest m_request; >+ bool m_hasPersistentAccess { false }; >+ String m_deviceIdentifierHashSalt; > }; > > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 7ab56f111e61149a6f1429f54a0d3b2aba748b37..e028f8467b3c367ee340b1f72c72a0f8eed161e5 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -7015,12 +7015,12 @@ UserMediaPermissionRequestManagerProxy& WebPageProxy::userMediaPermissionRequest > } > #endif > >-void WebPageProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData, const WebCore::MediaStreamRequest& request) >+void WebPageProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData, WebCore::MediaStreamRequest&& request) > { > #if ENABLE(MEDIA_STREAM) > MESSAGE_CHECK(m_process, m_process->webFrame(frameID)); > >- userMediaPermissionRequestManager().requestUserMediaPermissionForFrame(userMediaID, frameID, userMediaDocumentOriginData.securityOrigin(), topLevelDocumentOriginData.securityOrigin(), request); >+ userMediaPermissionRequestManager().requestUserMediaPermissionForFrame(userMediaID, frameID, userMediaDocumentOriginData.securityOrigin(), topLevelDocumentOriginData.securityOrigin(), WTFMove(request)); > #else > UNUSED_PARAM(userMediaID); > UNUSED_PARAM(frameID); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index 7be91943890b75d0e28ca3701f5b467ec08747a2..7d2b35b6289ec750f9b82c275d5916b6e0ebfa44 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1597,7 +1597,7 @@ private: > #if ENABLE(MEDIA_STREAM) > UserMediaPermissionRequestManagerProxy& userMediaPermissionRequestManager(); > #endif >- void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginIdentifier, const WebCore::SecurityOriginData& topLevelDocumentOriginIdentifier, const WebCore::MediaStreamRequest&); >+ void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginIdentifier, const WebCore::SecurityOriginData& topLevelDocumentOriginIdentifier, WebCore::MediaStreamRequest&&); > void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData); > void beginMonitoringCaptureDevices(); > >diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp >index b2da3bb8765e166f972e596de1e37ef6bed39f72..022fa72b46000405846a1b1e42e1ba89b77d53b8 100644 >--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp >@@ -571,6 +571,10 @@ void WebProcessProxy::processDidTerminateOrFailedToLaunch() > // to be deleted before we can finish our work. > Ref<WebProcessProxy> protect(*this); > >+#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) >+ m_userMediaCaptureManagerProxy->clear(); >+#endif >+ > if (auto* webConnection = this->webConnection()) > webConnection->didClose(); > >diff --git a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp >index 45b901e8ac4d908dcafbda016e53adcff8b7eaea..34bd80dac2eb565ab6a105daed3a8b6f4fe4711d 100644 >--- a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp >+++ b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp >@@ -185,6 +185,7 @@ private: > // RealtimeMediaSource > void beginConfiguration() final { } > void commitConfiguration() final { } >+ void hasEnded() final { m_manager.sourceEnded(m_id); } > > void applyConstraints(const WebCore::MediaConstraints& constraints, SuccessHandler&& successHandler, FailureHandler&& failureHandler) final { > m_manager.applyConstraints(m_id, constraints); >@@ -345,6 +346,11 @@ void UserMediaCaptureManager::applyConstraints(uint64_t id, const WebCore::Media > m_process.send(Messages::UserMediaCaptureManagerProxy::ApplyConstraints(id, constraints), 0); > } > >+void UserMediaCaptureManager::sourceEnded(uint64_t id) >+{ >+ m_process.send(Messages::UserMediaCaptureManagerProxy::End(id), 0); >+} >+ > void UserMediaCaptureManager::applyConstraintsSucceeded(uint64_t id, const WebCore::RealtimeMediaSourceSettings& settings) > { > ASSERT(m_sources.contains(id)); >diff --git a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h >index ad1be7ccedd6ae4308fc4fef028c377b4a9e0bd0..83404fa6edcf51b464e64e05f90a1adc83ef18e8 100644 >--- a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h >+++ b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h >@@ -85,6 +85,7 @@ private: > // Messages::UserMediaCaptureManager > void captureFailed(uint64_t id); > void sourceStopped(uint64_t id); >+ void sourceEnded(uint64_t id); > void sourceMutedChanged(uint64_t id, bool muted); > void sourceSettingsChanged(uint64_t id, const WebCore::RealtimeMediaSourceSettings&); > void storageChanged(uint64_t id, const SharedMemory::Handle&, const WebCore::CAAudioStreamDescription&, uint64_t numberOfFrames); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 6a505477faebd8c83727b16940583295216fa84d..545c014fbcd5849b453a0940d36a6784d4c98dae 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2019-02-06 Youenn Fablet <youenn@apple.com> >+ >+ Filter out Overconstrainederror.constraint when getUserMedia is not granted >+ https://bugs.webkit.org/show_bug.cgi?id=194240 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/mediastream/overconstrainederror-constraint-expected.txt: Added. >+ * fast/mediastream/overconstrainederror-constraint.html: Added. >+ > 2019-02-06 Antti Koivisto <antti@apple.com> > > RELEASE_ASSERT(!m_document.isResolvingTreeStyle()) in com.apple.WebKit.WebContent at WebCore: WebCore::StyleResolver::~StyleResolver >diff --git a/LayoutTests/fast/mediastream/overconstrainederror-constraint-expected.txt b/LayoutTests/fast/mediastream/overconstrainederror-constraint-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..442b5ba746cba694fd08423c5601067e48041fde >--- /dev/null >+++ b/LayoutTests/fast/mediastream/overconstrainederror-constraint-expected.txt >@@ -0,0 +1,4 @@ >+ >+PASS Before grant >+PASS After grant >+ >diff --git a/LayoutTests/fast/mediastream/overconstrainederror-constraint.html b/LayoutTests/fast/mediastream/overconstrainederror-constraint.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c176efcebe6aaaa150d5a2a1c78e9194504ddfd0 >--- /dev/null >+++ b/LayoutTests/fast/mediastream/overconstrainederror-constraint.html >@@ -0,0 +1,39 @@ >+<!doctype html> >+<html> >+ <head> >+ <meta charset="utf-8"> >+ <title>OverConstrainedError.constraint testing</title> >+ <script src="../../resources/testharness.js"></script> >+ <script src="../../resources/testharnessreport.js"></script> >+ </head> >+ <body> >+ >+ <script> >+if (window.testRunner) >+ testRunner.setUserMediaPermission(true); >+if (window.internals) >+ window.internals.setMockMediaCaptureDevicesEnabled(true); >+ >+promise_test(async () => { >+ return navigator.mediaDevices.getUserMedia({audio: {deviceId: {exact:"none"}}}).then( >+ () => assert_not_reached("gum should fail"), >+ (e) => { >+ assert_true(e instanceof OverconstrainedError); >+ assert_equals(e.constraint, "", "constraint should be the empty string"); >+ } >+ ); >+}, "Before grant"); >+ >+promise_test(async(test) => { >+ await navigator.mediaDevices.getUserMedia({audio: true}); >+ return navigator.mediaDevices.getUserMedia({audio: {deviceId: {exact:"none"}}}).then( >+ () => assert_not_reached("gum should fail"), >+ (e) => { >+ assert_true(e instanceof OverconstrainedError); >+ assert_equals(e.constraint, "deviceId", "constraint should be deviceId"); >+ } >+ ); >+}, "After grant"); >+ </script> >+ </body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194312
:
361232
|
361347
|
361412