[MediaStream] deviceId constraint doesn't work with getUserMedia
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 May 2017 04:42:18 +0000 (04:42 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 May 2017 04:42:18 +0000 (04:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171877
<rdar://problem/31899730>

Reviewed by Jer Noble.

Source/WebCore:

Test: fast/mediastream/get-user-media-device-id.html

* Modules/mediastream/MediaConstraintsImpl.h:
(WebCore::MediaConstraintsData::MediaConstraintsData): Add a constructor that
takes a const MediaConstraints&.

* Modules/mediastream/MediaDevicesEnumerationRequest.cpp:
(WebCore::MediaDevicesEnumerationRequest::topLevelDocumentOrigin): Don't return
NULL for the main frame so the origin matches that returned for a UserMediaRequest.

* Modules/mediastream/UserMediaController.h:
(WebCore::UserMediaController::setDeviceIDHashSalt): Deleted, not used.
(WebCore::UserMediaController::deviceIDHashSalt): Deleted, not used.

* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::allow): Add device ID hash salt parameter, set it on
constraints.
* Modules/mediastream/UserMediaRequest.h:

* platform/mediastream/MediaConstraints.h:
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::fitnessDistance): ASSERT if called for DeviceId.
(WebCore::RealtimeMediaSource::selectSettings): Special case DeviceId because it
we have to hash the device ID before comparing, and because the DeviceId can't be
changed so it should never be added to the flattened constraints.

* platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp:
(WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint): Deleted, unused.
(WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName): Deleted, unused.
* platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:

* platform/mediastream/mac/AVVideoCaptureSource.mm:
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints): Pass device
id, not empty string.

Source/WebKit2:

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<MediaConstraintsData>::encode): Encode deviceIDHashSalt.
(IPC::ArgumentCoder<MediaConstraintsData>::decode): Decode deviceIDHashSalt.

* UIProcess/UserMediaPermissionCheckProxy.cpp:
(WebKit::UserMediaPermissionCheckProxy::UserMediaPermissionCheckProxy): Initialize
completion handler, frame ID, and security origins.
(WebKit::UserMediaPermissionCheckProxy::setUserMediaAccessInfo): Complete by calling
completion handler because we now sometimes request access info before calling gUM.
(WebKit::UserMediaPermissionCheckProxy::invalidate): Clear completion handler.
* UIProcess/UserMediaPermissionCheckProxy.h:

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::FrameAuthorizationState::FrameAuthorizationState): Take security origins, not
UserMediaPermissionRequestProxy, so it can be constructed with a UserMediaPermissionCheckProxy.
(WebKit::FrameAuthorizationState::ensureSecurityOriginsAreEqual): Ditto. Clear has salt
when origins don't match.
(WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest): Templatize.
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied): Fix typo.
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted): Ditto.
Don't set state for empty UIDs. Pass hash salt to web process.
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
The device ID hash salt is now required to validate constraints, so get it first.
(WebKit::UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo): Helper
method used to get the device ID hash salt.
(WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): Restructure
to use getUserMediaPermissionInfo.
(WebKit::UserMediaPermissionRequestManagerProxy::didCompleteUserMediaPermissionCheck): Deleted.
* UIProcess/UserMediaPermissionRequestManagerProxy.h:

* WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
(WebKit::UserMediaPermissionRequestManager::userMediaAccessWasGranted): Add device ID
hash salt parameter.
* WebProcess/MediaStream/UserMediaPermissionRequestManager.h:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::userMediaAccessWasGranted): Ditto.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

* WebProcess/cocoa/UserMediaCaptureManager.cpp:
(WebKit::UserMediaCaptureManager::createCaptureSource): Use new MediaConstraintsData
constructor.

LayoutTests:

* fast/mediastream/get-user-media-device-id-expected.txt: Added.
* fast/mediastream/get-user-media-device-id.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216563 268f45cc-cd09-0410-ab3c-d52691b4dbfc

28 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/mediastream/get-user-media-device-id-expected.txt [new file with mode: 0644]
LayoutTests/fast/mediastream/get-user-media-device-id.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h
Source/WebCore/Modules/mediastream/MediaDevicesEnumerationRequest.cpp
Source/WebCore/Modules/mediastream/UserMediaController.h
Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
Source/WebCore/Modules/mediastream/UserMediaRequest.h
Source/WebCore/platform/mediastream/MediaConstraints.h
Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp
Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp
Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h
Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm
Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.cpp
Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.h
Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp
Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp
Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/cocoa/UserMediaCaptureManager.cpp

index 28a7d99..16c059c 100644 (file)
@@ -1,3 +1,14 @@
+2017-05-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] deviceId constraint doesn't work with getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=171877
+        <rdar://problem/31899730>
+
+        Reviewed by Jer Noble.
+
+        * fast/mediastream/get-user-media-device-id-expected.txt: Added.
+        * fast/mediastream/get-user-media-device-id.html: Added.
+
 2017-05-09  Matt Lewis  <jlewis3@apple.com>
 
         Mark webrtc/libwebrtc/release-while-setting-local-description.html as flaky.
diff --git a/LayoutTests/fast/mediastream/get-user-media-device-id-expected.txt b/LayoutTests/fast/mediastream/get-user-media-device-id-expected.txt
new file mode 100644 (file)
index 0000000..d187b54
--- /dev/null
@@ -0,0 +1,5 @@
+
+PASS Collect device IDs 
+PASS Pass device IDs as exact constraints 
+PASS Pass device IDs as optional constraints 
+
diff --git a/LayoutTests/fast/mediastream/get-user-media-device-id.html b/LayoutTests/fast/mediastream/get-user-media-device-id.html
new file mode 100644 (file)
index 0000000..8a0d418
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Test passing capture device IDs to getUserMedia</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script>
+    let deviceIds = [];
+
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    promise_test((test) => {
+        return navigator.mediaDevices.enumerateDevices()
+            .then((devices) => {
+                devices.forEach((device) => {
+                    let kind = device.kind == "audioinput" ? "audio" : "video";
+                    deviceIds.push({ type: kind, id : device.deviceId});
+                });
+            });
+    }, "Collect device IDs");
+    
+    let constraints = { };
+
+    promise_test((test) => {
+        deviceIds.forEach((info) => {
+            constraints[info.type] = { deviceId: { exact: info.id } };
+        });
+    
+        return navigator.mediaDevices.getUserMedia(constraints)
+            .then((stream) => {
+                assert_equals(stream.getAudioTracks().length, 1, "correct number of audio tracks");
+                assert_equals(stream.getVideoTracks().length, 1, "correct number of audio tracks");
+            })
+
+    }, "Pass device IDs as exact constraints");
+    
+    promise_test((test) => {
+        deviceIds.forEach((info) => {
+            constraints[info.type] = { deviceId: info.id };
+        });
+    
+        return navigator.mediaDevices.getUserMedia(constraints)
+            .then((stream) => {
+                assert_equals(stream.getAudioTracks().length, 1, "correct number of audio tracks");
+                assert_equals(stream.getVideoTracks().length, 1, "correct number of audio tracks");
+            })
+
+    }, "Pass device IDs as optional constraints");
+
+    </script>
+</head>
+<body>
+</body>
+</html>
index 101a9fa..7c3cf05 100644 (file)
@@ -1,3 +1,47 @@
+2017-05-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] deviceId constraint doesn't work with getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=171877
+        <rdar://problem/31899730>
+
+        Reviewed by Jer Noble.
+
+        Test: fast/mediastream/get-user-media-device-id.html
+
+        * Modules/mediastream/MediaConstraintsImpl.h:
+        (WebCore::MediaConstraintsData::MediaConstraintsData): Add a constructor that 
+        takes a const MediaConstraints&.
+
+        * Modules/mediastream/MediaDevicesEnumerationRequest.cpp:
+        (WebCore::MediaDevicesEnumerationRequest::topLevelDocumentOrigin): Don't return
+        NULL for the main frame so the origin matches that returned for a UserMediaRequest.
+
+        * Modules/mediastream/UserMediaController.h:
+        (WebCore::UserMediaController::setDeviceIDHashSalt): Deleted, not used.
+        (WebCore::UserMediaController::deviceIDHashSalt): Deleted, not used.
+
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::allow): Add device ID hash salt parameter, set it on
+        constraints.
+        * Modules/mediastream/UserMediaRequest.h:
+
+        * platform/mediastream/MediaConstraints.h:
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::fitnessDistance): ASSERT if called for DeviceId.
+        (WebCore::RealtimeMediaSource::selectSettings): Special case DeviceId because it
+        we have to hash the device ID before comparing, and because the DeviceId can't be
+        changed so it should never be added to the flattened constraints.
+
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp:
+        (WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint): Deleted, unused.
+        (WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName): Deleted, unused.
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:
+
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints): Pass device
+        id, not empty string.
+
 2017-05-09  Jeremy Jones  <jeremyj@apple.com>
 
         Video fullscreen window level should be below status bar.
index 5a75946..87b4600 100644 (file)
@@ -46,12 +46,27 @@ struct MediaConstraintsData {
         , isValid(isValid)
     {
     }
+    MediaConstraintsData(const MediaConstraints& constraints)
+        : mandatoryConstraints(constraints.mandatoryConstraints())
+        , advancedConstraints(constraints.advancedConstraints())
+        , deviceIDHashSalt(constraints.deviceIDHashSalt())
+        , isValid(constraints.isValid())
+    {
+    }
+    MediaConstraintsData(const MediaConstraintsData& constraints, const String& hashSalt)
+        : mandatoryConstraints(constraints.mandatoryConstraints)
+        , advancedConstraints(constraints.advancedConstraints)
+        , deviceIDHashSalt(hashSalt)
+        , isValid(constraints.isValid)
+    {
+    }
 
     void setDefaultVideoConstraints();
     bool isConstraintSet(std::function<bool(const MediaTrackConstraintSetMap&)>&&);
 
     MediaTrackConstraintSetMap mandatoryConstraints;
     Vector<MediaTrackConstraintSetMap> advancedConstraints;
+    String deviceIDHashSalt;
     bool isValid { false };
 };
 
@@ -66,8 +81,11 @@ public:
     const MediaTrackConstraintSetMap& mandatoryConstraints() const final { return m_data.mandatoryConstraints; }
     const Vector<MediaTrackConstraintSetMap>& advancedConstraints() const final { return m_data.advancedConstraints; }
     bool isValid() const final { return m_data.isValid; }
-    const MediaConstraintsData& data() const { return m_data; }
 
+    String deviceIDHashSalt() const final { return m_data.deviceIDHashSalt; }
+    void setDeviceIDHashSalt(const String& salt) final { m_data.deviceIDHashSalt = salt; }
+
+    const MediaConstraintsData& data() const { return m_data; }
     void setDefaultVideoConstraints() { m_data.setDefaultVideoConstraints(); }
 
 private:
index 71a4d51..789a58c 100644 (file)
@@ -65,11 +65,6 @@ SecurityOrigin* MediaDevicesEnumerationRequest::topLevelDocumentOrigin() const
     if (!scriptExecutionContext())
         return nullptr;
 
-    if (Frame* frame = downcast<Document>(*scriptExecutionContext()).frame()) {
-        if (frame->isMainFrame())
-            return nullptr;
-    }
-
     return &scriptExecutionContext()->topOrigin();
 }
 
index 8804aca..707fd8e 100644 (file)
@@ -46,15 +46,11 @@ public:
     void enumerateMediaDevices(MediaDevicesEnumerationRequest&);
     void cancelMediaDevicesEnumerationRequest(MediaDevicesEnumerationRequest&);
 
-    void setDeviceIDHashSalt(const String& salt) { m_idHashSalt = salt; }
-    String deviceIDHashSalt() const { return m_idHashSalt; }
-
     WEBCORE_EXPORT static const char* supplementName();
     static UserMediaController* from(Page* page) { return static_cast<UserMediaController*>(Supplement<Page>::from(page, supplementName())); }
 
 private:
     UserMediaClient* m_client;
-    String m_idHashSalt;
 };
 
 inline void UserMediaController::requestUserMediaAccess(UserMediaRequest& request)
index 96125fd..b0a80b0 100644 (file)
@@ -153,7 +153,7 @@ void UserMediaRequest::start()
     m_controller->requestUserMediaAccess(*this);
 }
 
-void UserMediaRequest::allow(const String& audioDeviceUID, const String& videoDeviceUID)
+void UserMediaRequest::allow(const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt)
 {
     m_allowedAudioDeviceUID = audioDeviceUID;
     m_allowedVideoDeviceUID = videoDeviceUID;
@@ -180,6 +180,9 @@ void UserMediaRequest::allow(const String& audioDeviceUID, const String& videoDe
         m_promise.resolve(stream);
     };
 
+    m_audioConstraints->setDeviceIDHashSalt(deviceIdentifierHashSalt);
+    m_videoConstraints->setDeviceIDHashSalt(deviceIdentifierHashSalt);
+
     RealtimeMediaSourceCenter::singleton().createMediaStream(WTFMove(callback), m_allowedAudioDeviceUID, m_allowedVideoDeviceUID, &m_audioConstraints.get(), &m_videoConstraints.get());
 }
 
index a3e9690..2bf0a45 100644 (file)
@@ -53,7 +53,7 @@ public:
     void start();
 
     WEBCORE_EXPORT void setAllowedMediaDeviceUIDs(const String& audioDeviceUID, const String& videoDeviceUID);
-    WEBCORE_EXPORT void allow(const String& audioDeviceUID, const String& videoDeviceUID);
+    WEBCORE_EXPORT void allow(const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt);
 
     enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, OtherFailure };
     WEBCORE_EXPORT void deny(MediaAccessDenialReason, const String& invalidConstraint);
index 8998374..5388717 100644 (file)
@@ -811,6 +811,9 @@ public:
     virtual const Vector<MediaTrackConstraintSetMap>& advancedConstraints() const = 0;
     virtual bool isValid() const = 0;
 
+    virtual String deviceIDHashSalt() const = 0;
+    virtual void setDeviceIDHashSalt(const String&) = 0;
+
 protected:
     MediaConstraints() { }
 };
index 4b4e464..2fe68a7 100644 (file)
@@ -39,6 +39,7 @@
 #include "MediaConstraints.h"
 #include "NotImplemented.h"
 #include "RealtimeMediaSourceCapabilities.h"
+#include "RealtimeMediaSourceCenter.h"
 #include <wtf/MainThread.h>
 #include <wtf/UUID.h>
 #include <wtf/text/StringHash.h>
@@ -341,11 +342,7 @@ double RealtimeMediaSource::fitnessDistance(const MediaConstraint& constraint)
     }
 
     case MediaConstraintType::DeviceId: {
-        ASSERT(constraint.isString());
-        if (!capabilities.supportsDeviceId())
-            return 0;
-
-        return downcast<StringConstraint>(constraint).fitnessDistance(m_id);
+        ASSERT_NOT_REACHED();
         break;
     }
 
@@ -541,6 +538,23 @@ bool RealtimeMediaSource::selectSettings(const MediaConstraints& constraints, Fl
             return false;
         }
 
+        // The deviceId can't be changed, and the constraint value is the hashed device ID, so verify that the
+        // device's unique ID hashes to the constraint value but don't include the constraint in the flattened
+        // constraint set.
+        if (constraint.constraintType() == MediaConstraintType::DeviceId) {
+            ASSERT(constraint.isString());
+            ASSERT(!constraints.deviceIDHashSalt().isEmpty());
+
+            auto hashedID = RealtimeMediaSourceCenter::singleton().hashStringWithSalt(m_persistentID, constraints.deviceIDHashSalt());
+            double constraintDistance = downcast<StringConstraint>(constraint).fitnessDistance(hashedID);
+            if (std::isinf(constraintDistance)) {
+                failedConstraint = constraint.name();
+                return true;
+            }
+
+            return false;
+        }
+
         double constraintDistance = fitnessDistance(constraint);
         if (std::isinf(constraintDistance)) {
             failedConstraint = constraint.name();
index 73775a0..ecbf935 100644 (file)
 
 namespace WebCore {
 
-const AtomicString& RealtimeMediaSourceSupportedConstraints::nameForConstraint(MediaConstraintType constraint)
-{
-    static NeverDestroyed<AtomicString> unknownConstraintName(emptyString());
-    static NeverDestroyed<AtomicString> widthConstraintName("width");
-    static NeverDestroyed<AtomicString> heightConstraintName("height");
-    static NeverDestroyed<AtomicString> aspectRatioConstraintName("aspectRatio");
-    static NeverDestroyed<AtomicString> frameRateConstraintName("frameRate");
-    static NeverDestroyed<AtomicString> facingModeConstraintName("facingMode");
-    static NeverDestroyed<AtomicString> volumeConstraintName("volume");
-    static NeverDestroyed<AtomicString> sampleRateConstraintName("sampleRate");
-    static NeverDestroyed<AtomicString> sampleSizeConstraintName("sampleSize");
-    static NeverDestroyed<AtomicString> echoCancellationConstraintName("echoCancellation");
-    static NeverDestroyed<AtomicString> deviceIdConstraintName("deviceId");
-    static NeverDestroyed<AtomicString> groupIdConstraintName("groupId");
-    switch (constraint) {
-    case MediaConstraintType::Unknown:
-        return unknownConstraintName;
-    case MediaConstraintType::Width:
-        return widthConstraintName;
-    case MediaConstraintType::Height:
-        return heightConstraintName;
-    case MediaConstraintType::AspectRatio:
-        return aspectRatioConstraintName;
-    case MediaConstraintType::FrameRate:
-        return frameRateConstraintName;
-    case MediaConstraintType::FacingMode:
-        return facingModeConstraintName;
-    case MediaConstraintType::Volume:
-        return volumeConstraintName;
-    case MediaConstraintType::SampleRate:
-        return sampleRateConstraintName;
-    case MediaConstraintType::SampleSize:
-        return sampleSizeConstraintName;
-    case MediaConstraintType::EchoCancellation:
-        return echoCancellationConstraintName;
-    case MediaConstraintType::DeviceId:
-        return deviceIdConstraintName;
-    case MediaConstraintType::GroupId:
-        return groupIdConstraintName;
-    }
-
-    ASSERT_NOT_REACHED();
-    return emptyAtom;
-}
-
-MediaConstraintType RealtimeMediaSourceSupportedConstraints::constraintFromName(const String& constraintName)
-{
-    static NeverDestroyed<HashMap<AtomicString, MediaConstraintType>> nameToConstraintMap;
-    HashMap<AtomicString, MediaConstraintType>& nameToConstraintMapValue = nameToConstraintMap.get();
-    if (!nameToConstraintMapValue.size()) {
-        nameToConstraintMapValue.add("width", MediaConstraintType::Width);
-        nameToConstraintMapValue.add("height", MediaConstraintType::Height);
-        nameToConstraintMapValue.add("aspectRatio", MediaConstraintType::AspectRatio);
-        nameToConstraintMapValue.add("frameRate", MediaConstraintType::FrameRate);
-        nameToConstraintMapValue.add("facingMode", MediaConstraintType::FacingMode);
-        nameToConstraintMapValue.add("volume", MediaConstraintType::Volume);
-        nameToConstraintMapValue.add("sampleRate", MediaConstraintType::SampleRate);
-        nameToConstraintMapValue.add("sampleSize", MediaConstraintType::SampleSize);
-        nameToConstraintMapValue.add("echoCancellation", MediaConstraintType::EchoCancellation);
-        nameToConstraintMapValue.add("deviceId", MediaConstraintType::DeviceId);
-        nameToConstraintMapValue.add("groupId", MediaConstraintType::GroupId);
-    }
-    auto iter = nameToConstraintMapValue.find(constraintName);
-    return iter == nameToConstraintMapValue.end() ? MediaConstraintType::Unknown : iter->value;
-}
-
 bool RealtimeMediaSourceSupportedConstraints::supportsConstraint(MediaConstraintType constraint) const
 {
     switch (constraint) {
index faf94be..4040e34 100644 (file)
@@ -93,9 +93,6 @@ public:
 
     bool supportsConstraint(MediaConstraintType) const;
 
-    static const AtomicString& nameForConstraint(MediaConstraintType);
-    static MediaConstraintType constraintFromName(const String&);
-
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static bool decode(Decoder&, RealtimeMediaSourceSupportedConstraints&);
 
index ff5c348..c502fd3 100644 (file)
@@ -116,7 +116,7 @@ public:
         AVCaptureDeviceTypedef *device = [getAVCaptureDeviceClass() deviceWithUniqueID:deviceID];
         if (!device)
             return { };
-        return AVVideoCaptureSource::create(device, emptyString(), constraints);
+        return AVVideoCaptureSource::create(device, deviceID, constraints);
     }
 
 #if PLATFORM(IOS)
index 74284e8..6a8b228 100644 (file)
@@ -191,6 +191,7 @@ Vector<String> RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints(Re
     for (auto& device : bestSources)
         sourceUIDs.uncheckedAppend(device->persistentID());
 
+    invalidConstraint = emptyString();
     return sourceUIDs;
 }
 
index 115ae08..034a03e 100644 (file)
@@ -1,3 +1,55 @@
+2017-05-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] deviceId constraint doesn't work with getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=171877
+        <rdar://problem/31899730>
+
+        Reviewed by Jer Noble.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<MediaConstraintsData>::encode): Encode deviceIDHashSalt.
+        (IPC::ArgumentCoder<MediaConstraintsData>::decode): Decode deviceIDHashSalt.
+
+        * UIProcess/UserMediaPermissionCheckProxy.cpp:
+        (WebKit::UserMediaPermissionCheckProxy::UserMediaPermissionCheckProxy): Initialize
+        completion handler, frame ID, and security origins.
+        (WebKit::UserMediaPermissionCheckProxy::setUserMediaAccessInfo): Complete by calling
+        completion handler because we now sometimes request access info before calling gUM.
+        (WebKit::UserMediaPermissionCheckProxy::invalidate): Clear completion handler.
+        * UIProcess/UserMediaPermissionCheckProxy.h:
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::FrameAuthorizationState::FrameAuthorizationState): Take security origins, not
+        UserMediaPermissionRequestProxy, so it can be constructed with a UserMediaPermissionCheckProxy.
+        (WebKit::FrameAuthorizationState::ensureSecurityOriginsAreEqual): Ditto. Clear has salt
+        when origins don't match.
+        (WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest): Templatize.
+        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied): Fix typo.
+        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted): Ditto.
+        Don't set state for empty UIDs. Pass hash salt to web process.
+        (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
+        The device ID hash salt is now required to validate constraints, so get it first.
+        (WebKit::UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo): Helper
+        method used to get the device ID hash salt.
+        (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): Restructure
+        to use getUserMediaPermissionInfo.
+        (WebKit::UserMediaPermissionRequestManagerProxy::didCompleteUserMediaPermissionCheck): Deleted.
+        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
+        (WebKit::UserMediaPermissionRequestManager::userMediaAccessWasGranted): Add device ID
+        hash salt parameter.
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.h:
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::userMediaAccessWasGranted): Ditto.
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+        (WebKit::UserMediaCaptureManager::createCaptureSource): Use new MediaConstraintsData 
+        constructor.
+
 2017-05-09  Alex Christensen  <achristensen@webkit.org>
 
         Buffer media in NetworkProcess to reduce IPC overhead
index 7af6648..0fa39c7 100644 (file)
@@ -2393,6 +2393,7 @@ void ArgumentCoder<MediaConstraintsData>::encode(Encoder& encoder, const WebCore
 {
     encoder << constraint.mandatoryConstraints
         << constraint.advancedConstraints
+        << constraint.deviceIDHashSalt
         << constraint.isValid;
 }
 
@@ -2400,6 +2401,7 @@ bool ArgumentCoder<MediaConstraintsData>::decode(Decoder& decoder, WebCore::Medi
 {
     return decoder.decode(constraints.mandatoryConstraints)
         && decoder.decode(constraints.advancedConstraints)
+        && decoder.decode(constraints.deviceIDHashSalt)
         && decoder.decode(constraints.isValid);
 }
 
index 7045f5a..c5214eb 100644 (file)
 #include "UserMediaPermissionCheckProxy.h"
 
 #include "UserMediaPermissionRequestManagerProxy.h"
+#include <WebCore/SecurityOrigin.h>
+#include <WebCore/SecurityOriginData.h>
+
+using namespace WebCore;
 
 namespace WebKit {
 
-UserMediaPermissionCheckProxy::UserMediaPermissionCheckProxy(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID)
-    : m_manager(&manager)
-    , m_userMediaID(userMediaID)
+UserMediaPermissionCheckProxy::UserMediaPermissionCheckProxy(uint64_t userMediaID, uint64_t frameID, CompletionHandler&& handler, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier)
+    : m_userMediaID(userMediaID)
+    , m_frameID(frameID)
+    , m_completionHandler(WTFMove(handler))
+    , m_userMediaDocumentSecurityOrigin((SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier)->securityOrigin()))
+    , m_topLevelDocumentSecurityOrigin(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin())
 {
 }
 
-void UserMediaPermissionCheckProxy::setUserMediaAccessInfo(const String& mediaDeviceIdentifierHashSalt, bool allowed)
+void UserMediaPermissionCheckProxy::setUserMediaAccessInfo(String&& mediaDeviceIdentifierHashSalt, bool allowed)
 {
-    ASSERT(m_manager);
-    if (!m_manager)
+    if (!m_completionHandler)
         return;
 
-    m_manager->didCompleteUserMediaPermissionCheck(m_userMediaID, mediaDeviceIdentifierHashSalt, allowed);
-    m_manager = nullptr;
+    m_completionHandler(m_userMediaID, WTFMove(mediaDeviceIdentifierHashSalt), allowed);
+    m_completionHandler = nullptr;
 }
 
 void UserMediaPermissionCheckProxy::invalidate()
 {
-    m_manager = nullptr;
+    m_completionHandler = nullptr;
 }
 
 } // namespace WebKit
index bcce0a9..7a84271 100644 (file)
 #include "APIObject.h"
 #include <wtf/text/WTFString.h>
 
+namespace WebCore {
+class SecurityOrigin;
+}
+
 namespace WebKit {
 
 class UserMediaPermissionRequestManagerProxy;
 
 class UserMediaPermissionCheckProxy : public API::ObjectImpl<API::Object::Type::UserMediaPermissionCheck> {
 public:
-    static Ref<UserMediaPermissionCheckProxy> create(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID)
+
+    using CompletionHandler = std::function<void(uint64_t, String&&, bool allowed)>;
+
+    static Ref<UserMediaPermissionCheckProxy> create(uint64_t userMediaID, uint64_t frameID, CompletionHandler&& handler, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier)
     {
-        return adoptRef(*new UserMediaPermissionCheckProxy(manager, userMediaID));
+        return adoptRef(*new UserMediaPermissionCheckProxy(userMediaID, frameID, WTFMove(handler), userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier));
     }
 
-    void setUserMediaAccessInfo(const String&, bool allowed);
+    void setUserMediaAccessInfo(String&&, bool allowed);
     void invalidate();
 
+    uint64_t frameID() const { return m_frameID; }
+    WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin() { return &m_userMediaDocumentSecurityOrigin.get(); }
+    WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin() { return &m_topLevelDocumentSecurityOrigin.get(); }
+
 private:
-    UserMediaPermissionCheckProxy(UserMediaPermissionRequestManagerProxy&, uint64_t);
+    UserMediaPermissionCheckProxy(uint64_t userMediaID, uint64_t frameID, CompletionHandler&&, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier);
 
-    UserMediaPermissionRequestManagerProxy* m_manager;
     uint64_t m_userMediaID;
+    uint64_t m_frameID;
+    CompletionHandler m_completionHandler;
+    Ref<WebCore::SecurityOrigin> m_userMediaDocumentSecurityOrigin;
+    Ref<WebCore::SecurityOrigin> m_topLevelDocumentSecurityOrigin;
 };
 
 } // namespace WebKit
index 8384282..8d57c8f 100644 (file)
@@ -39,9 +39,9 @@ using namespace WebCore;
 
 namespace WebKit {
 
-FrameAuthorizationState::FrameAuthorizationState(UserMediaPermissionRequestProxy& request)
-    : m_userMediaDocumentSecurityOrigin(request.userMediaDocumentSecurityOrigin())
-    , m_topLevelDocumentSecurityOrigin(request.topLevelDocumentSecurityOrigin())
+FrameAuthorizationState::FrameAuthorizationState(SecurityOrigin* userMediaDocumentSecurityOrigin, SecurityOrigin* topLevelDocumentSecurityOrigin)
+    : m_userMediaDocumentSecurityOrigin(userMediaDocumentSecurityOrigin)
+    , m_topLevelDocumentSecurityOrigin(topLevelDocumentSecurityOrigin)
 {
 }
 
@@ -65,32 +65,34 @@ void FrameAuthorizationState::setHasPermissionToUseCaptureDevice(const String& d
         m_authorizedDeviceUIDs.remove(index);
 }
 
-void FrameAuthorizationState::ensureSecurityOriginsAreEqual(UserMediaPermissionRequestProxy& request)
+void FrameAuthorizationState::ensureSecurityOriginsAreEqual(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin)
 {
     do {
-        if (!m_userMediaDocumentSecurityOrigin || !m_userMediaDocumentSecurityOrigin->equal(request.userMediaDocumentSecurityOrigin()))
+        if (!m_userMediaDocumentSecurityOrigin || !m_userMediaDocumentSecurityOrigin->equal(userMediaDocumentSecurityOrigin))
             break;
 
-        if (!m_topLevelDocumentSecurityOrigin || !m_topLevelDocumentSecurityOrigin->equal(request.topLevelDocumentSecurityOrigin()))
+        if (!m_topLevelDocumentSecurityOrigin || !m_topLevelDocumentSecurityOrigin->equal(topLevelDocumentSecurityOrigin))
             break;
 
         return;
     } while (0);
 
-    m_userMediaDocumentSecurityOrigin = request.userMediaDocumentSecurityOrigin();
-    m_topLevelDocumentSecurityOrigin = request.topLevelDocumentSecurityOrigin();
+    m_userMediaDocumentSecurityOrigin = userMediaDocumentSecurityOrigin;
+    m_topLevelDocumentSecurityOrigin = topLevelDocumentSecurityOrigin;
     m_authorizedDeviceUIDs.clear();
+    m_deviceIdentifierHashSalt = emptyString();
 }
 
-FrameAuthorizationState& UserMediaPermissionRequestManagerProxy::stateForRequest(UserMediaPermissionRequestProxy& request)
+template <typename RequestType>
+FrameAuthorizationState& UserMediaPermissionRequestManagerProxy::stateForRequest(RequestType& request)
 {
     auto& state = m_frameStates.add(request.frameID(), nullptr).iterator->value;
     if (state) {
-        state->ensureSecurityOriginsAreEqual(request);
+        state->ensureSecurityOriginsAreEqual(request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin());
         return *state;
     }
 
-    state = std::make_unique<FrameAuthorizationState>(request);
+    state = std::make_unique<FrameAuthorizationState>(request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin());
     return *state;
 }
 
@@ -183,11 +185,11 @@ void UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied(uint64_t u
     if (!request)
         return;
 
-    auto fameState = stateForRequest(*request);
+    auto& frameState = stateForRequest(*request);
     for (const auto& deviceUID : request->videoDeviceUIDs())
-        fameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
+        frameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
     for (const auto& deviceUID : request->audioDeviceUIDs())
-        fameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
+        frameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
 
     denyRequest(userMediaID, reason, emptyString());
 }
@@ -216,13 +218,15 @@ void UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted(uint64_t
     if (!request)
         return;
 
-    auto& fameState = stateForRequest(*request);
-    fameState.setHasPermissionToUseCaptureDevice(audioDeviceUID, true);
-    fameState.setHasPermissionToUseCaptureDevice(videoDeviceUID, true);
+    auto& frameState = stateForRequest(*request);
+    if (!audioDeviceUID.isEmpty())
+        frameState.setHasPermissionToUseCaptureDevice(audioDeviceUID, true);
+    if (!videoDeviceUID.isEmpty())
+        frameState.setHasPermissionToUseCaptureDevice(videoDeviceUID, true);
 
     UserMediaProcessManager::singleton().willCreateMediaStream(*this, !audioDeviceUID.isEmpty(), !videoDeviceUID.isEmpty());
 
-    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID), m_page.pageID());
+    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID, frameState.deviceIdentifierHashSalt()), m_page.pageID());
 #else
     UNUSED_PARAM(userMediaID);
     UNUSED_PARAM(audioDeviceUID);
@@ -266,21 +270,21 @@ void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(
             return;
         }
 
-        auto userMediaOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier)->securityOrigin());
-        auto topLevelOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin());
-        auto request = createRequest(userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier, audioDeviceUIDs, videoDeviceUIDs);
-
         bool authorizedForAudio = false;
         bool authorizedForVideo = false;
-        auto& fameState = stateForRequest(request);
+        auto userMediaOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier).value_or(SecurityOriginData()).securityOrigin());
+        auto topLevelOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier).value_or(SecurityOriginData()).securityOrigin());
+        auto request = createRequest(userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier, audioDeviceUIDs, videoDeviceUIDs);
+
+        auto& frameState = stateForRequest(request.get());
         for (auto deviceUID : audioDeviceUIDs) {
-            if (fameState.hasPermissionToUseCaptureDevice(deviceUID)) {
+            if (frameState.hasPermissionToUseCaptureDevice(deviceUID)) {
                 authorizedForAudio = true;
                 break;
             }
         }
         for (auto deviceUID : videoDeviceUIDs) {
-            if (fameState.hasPermissionToUseCaptureDevice(deviceUID)) {
+            if (frameState.hasPermissionToUseCaptureDevice(deviceUID)) {
                 authorizedForVideo = true;
                 break;
             }
@@ -302,11 +306,30 @@ void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(
         return;
     }
 
-    auto audioConstraints = MediaConstraintsImpl::create(MediaConstraintsData(audioConstraintsData));
-    auto videoConstraints = MediaConstraintsImpl::create(MediaConstraintsData(videoConstraintsData));
+    auto validateConstraintsHandler = [this, userMediaID, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), audioConstraintsData, videoConstraintsData](const String& deviceIdentifierHashSalt) mutable {
+        syncWithWebCorePrefs();
+
+        auto audioConstraints = MediaConstraintsImpl::create({audioConstraintsData, deviceIdentifierHashSalt});
+        auto videoConstraints = MediaConstraintsImpl::create({videoConstraintsData, deviceIdentifierHashSalt});
+
+        RealtimeMediaSourceCenter::singleton().validateRequestConstraints(WTFMove(validHandler), WTFMove(invalidHandler), audioConstraints, videoConstraints);
+    };
+
+    auto haveDeviceSaltHandler = [this, userMediaID, frameID, validateConstraintsHandler = WTFMove(validateConstraintsHandler)](uint64_t userMediaID, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess) mutable {
+
+        auto request = m_pendingDeviceRequests.take(userMediaID);
+        if (!request)
+            return;
+
+        if (!m_page.isValid())
+            return;
+
+        auto& frameState = stateForRequest(*request);
+        frameState.setDeviceIdentifierHashSalt(WTFMove(deviceIdentifierHashSalt));
+        validateConstraintsHandler(deviceIdentifierHashSalt);
+    };
 
-    syncWithWebCorePrefs();
-    RealtimeMediaSourceCenter::singleton().validateRequestConstraints(validHandler, invalidHandler, audioConstraints, videoConstraints);
+    getUserMediaPermissionInfo(userMediaID, frameID, WTFMove(haveDeviceSaltHandler), WTFMove(userMediaDocumentOriginIdentifier), WTFMove(topLevelDocumentOriginIdentifier));
 #else
     UNUSED_PARAM(userMediaID);
     UNUSED_PARAM(frameID);
@@ -317,42 +340,50 @@ void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(
 #endif
 }
 
-void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier)
-{
 #if ENABLE(MEDIA_STREAM)
-    auto request = UserMediaPermissionCheckProxy::create(*this, userMediaID);
+void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&& handler, String&& userMediaDocumentOriginIdentifier, String&& topLevelDocumentOriginIdentifier)
+{
+    auto request = UserMediaPermissionCheckProxy::create(userMediaID, frameID, WTFMove(handler), userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier);
+
     m_pendingDeviceRequests.add(userMediaID, request.ptr());
 
     auto userMediaOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier).value_or(SecurityOriginData()).securityOrigin());
     auto topLevelOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier).value_or(SecurityOriginData()).securityOrigin());
-
     if (!m_page.uiClient().checkUserMediaPermissionForOrigin(m_page, *m_page.process().webFrame(frameID), *userMediaOrigin.get(), *topLevelOrigin.get(), request.get())) {
         m_pendingDeviceRequests.take(userMediaID);
-        m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration(userMediaID, Vector<WebCore::CaptureDevice>(), emptyString(), false), m_page.pageID());
+
+        handler(userMediaID, String(), false);
     }
-#else
-    UNUSED_PARAM(userMediaID);
-    UNUSED_PARAM(frameID);
-    UNUSED_PARAM(userMediaDocumentOriginIdentifier);
-    UNUSED_PARAM(topLevelDocumentOriginIdentifier);
-#endif
 }
+#endif
 
-void UserMediaPermissionRequestManagerProxy::didCompleteUserMediaPermissionCheck(uint64_t userMediaID, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess)
+void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String&& userMediaDocumentOriginIdentifier, String&& topLevelDocumentOriginIdentifier)
 {
-    if (!m_page.isValid())
-        return;
+#if ENABLE(MEDIA_STREAM)
 
-    if (!m_pendingDeviceRequests.take(userMediaID))
-        return;
+    auto completionHandler = [this, userMediaID](uint64_t userMediaID, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess) {
+        auto request = m_pendingDeviceRequests.take(userMediaID);
+        if (!request)
+            return;
 
-#if ENABLE(MEDIA_STREAM)
-    syncWithWebCorePrefs();
-    auto deviceInfo = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
-    m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration(userMediaID, deviceInfo, deviceIdentifierHashSalt, originHasPersistentAccess), m_page.pageID());
+        if (!m_page.isValid())
+            return;
+
+        auto& frameState = stateForRequest(*request);
+        ASSERT(frameState.deviceIdentifierHashSalt().isEmpty() || frameState.deviceIdentifierHashSalt() == deviceIdentifierHashSalt);
+        frameState.setDeviceIdentifierHashSalt(WTFMove(deviceIdentifierHashSalt));
+
+        syncWithWebCorePrefs();
+        auto deviceInfo = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+        m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration(userMediaID, deviceInfo, deviceIdentifierHashSalt, originHasPersistentAccess), m_page.pageID());
+    };
+
+    getUserMediaPermissionInfo(userMediaID, frameID, WTFMove(completionHandler), WTFMove(userMediaDocumentOriginIdentifier), WTFMove(topLevelDocumentOriginIdentifier));
 #else
-    UNUSED_PARAM(deviceIdentifierHashSalt);
-    UNUSED_PARAM(originHasPersistentAccess);
+    UNUSED_PARAM(userMediaID);
+    UNUSED_PARAM(frameID);
+    UNUSED_PARAM(userMediaDocumentOriginIdentifier);
+    UNUSED_PARAM(topLevelDocumentOriginIdentifier);
 #endif
 }
 
index e12e02d..cb141b0 100644 (file)
@@ -30,6 +30,7 @@
 namespace WebCore {
 class CaptureDevice;
 struct MediaConstraintsData;
+class SecurityOrigin;
 };
 
 namespace WebKit {
@@ -38,17 +39,21 @@ class WebPageProxy;
 
 class FrameAuthorizationState {
 public:
-    explicit FrameAuthorizationState(UserMediaPermissionRequestProxy&);
+    explicit FrameAuthorizationState(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin);
 
     bool hasPermissionToUseCaptureDevice(const String& deviceUID);
     void setHasPermissionToUseCaptureDevice(const String&, bool);
 
-    void ensureSecurityOriginsAreEqual(UserMediaPermissionRequestProxy&);
+    void ensureSecurityOriginsAreEqual(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin);
+
+    void setDeviceIdentifierHashSalt(const String& hashSalt) { m_deviceIdentifierHashSalt = hashSalt; }
+    const String& deviceIdentifierHashSalt() const { return m_deviceIdentifierHashSalt; }
 
 private:
     RefPtr<WebCore::SecurityOrigin> m_userMediaDocumentSecurityOrigin;
     RefPtr<WebCore::SecurityOrigin> m_topLevelDocumentSecurityOrigin;
     Vector<String> m_authorizedDeviceUIDs;
+    String m_deviceIdentifierHashSalt;
 };
 
 class UserMediaPermissionRequestManagerProxy {
@@ -64,11 +69,11 @@ public:
 
     void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID);
     void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason);
-    FrameAuthorizationState& stateForRequest(UserMediaPermissionRequestProxy&);
 
-    void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier);
+    template <typename RequestType>
+    FrameAuthorizationState& stateForRequest(RequestType&);
 
-    void didCompleteUserMediaPermissionCheck(uint64_t, const String&, bool allow);
+    void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String&& userMediaDocumentOriginIdentifier, String&& topLevelDocumentOriginIdentifier);
 
     void stopCapture();
     void scheduleNextRejection();
@@ -81,7 +86,9 @@ public:
 private:
     Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t userMediaID, uint64_t frameID, const String&userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs);
     void denyRequest(uint64_t userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint);
-    Ref<UserMediaPermissionCheckProxy> createUserMediaPermissionCheck(uint64_t userMediaID);
+
+    void getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, String&& userMediaDocumentOriginIdentifier, String&& topLevelDocumentOriginIdentifier);
+
     void syncWithWebCorePrefs() const;
 
     HashMap<uint64_t, RefPtr<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests;
index 625307e..b80003d 100644 (file)
@@ -5779,7 +5779,7 @@ void WebPageProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t
     WebFrameProxy* frame = m_process->webFrame(frameID);
     MESSAGE_CHECK(frame);
 
-    userMediaPermissionRequestManager().enumerateMediaDevicesForFrame(userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier);
+    userMediaPermissionRequestManager().enumerateMediaDevicesForFrame(userMediaID, frameID, WTFMove(userMediaDocumentOriginIdentifier), WTFMove(topLevelDocumentOriginIdentifier));
 #else
     UNUSED_PARAM(userMediaID);
     UNUSED_PARAM(frameID);
index fa3bdac..c5d2709 100644 (file)
@@ -154,14 +154,14 @@ void UserMediaPermissionRequestManager::removeMediaRequestFromMaps(UserMediaRequ
     m_userMediaRequestToIDMap.remove(&request);
 }
 
-void UserMediaPermissionRequestManager::userMediaAccessWasGranted(uint64_t requestID, const String& audioDeviceUID, const String& videoDeviceUID)
+void UserMediaPermissionRequestManager::userMediaAccessWasGranted(uint64_t requestID, const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt)
 {
     auto request = m_idToUserMediaRequestMap.take(requestID);
     if (!request)
         return;
     removeMediaRequestFromMaps(*request);
 
-    request->allow(audioDeviceUID, videoDeviceUID);
+    request->allow(audioDeviceUID, videoDeviceUID, deviceIdentifierHashSalt);
 }
 
 void UserMediaPermissionRequestManager::userMediaAccessWasDenied(uint64_t requestID, WebCore::UserMediaRequest::MediaAccessDenialReason reason, const String& invalidConstraint)
index 6b441f1..a8dffad 100644 (file)
@@ -45,7 +45,7 @@ public:
 
     void startUserMediaRequest(WebCore::UserMediaRequest&);
     void cancelUserMediaRequest(WebCore::UserMediaRequest&);
-    void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID);
+    void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID, const String& deviceIdentifierHashSalt);
     void userMediaAccessWasDenied(uint64_t, WebCore::UserMediaRequest::MediaAccessDenialReason, const String&);
 
     void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&);
index 153e4ce..58ad6f3 100644 (file)
@@ -3864,9 +3864,9 @@ void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID,
 }
 
 #if ENABLE(MEDIA_STREAM)
-void WebPage::userMediaAccessWasGranted(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID)
+void WebPage::userMediaAccessWasGranted(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID, const String& mediaDeviceIdentifierHashSalt)
 {
-    m_userMediaPermissionRequestManager->userMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID);
+    m_userMediaPermissionRequestManager->userMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID, mediaDeviceIdentifierHashSalt);
 }
 
 void WebPage::userMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint)
index 2c6d8b8..a04ffe8 100644 (file)
@@ -1174,7 +1174,7 @@ private:
     void didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed);
 
 #if ENABLE(MEDIA_STREAM)
-    void userMediaAccessWasGranted(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID);
+    void userMediaAccessWasGranted(uint64_t userMediaID, const String& audioDeviceUID, const String& videoDeviceUID, const String& mediaDeviceIdentifierHashSalt);
     void userMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint);
 
     void didCompleteMediaDeviceEnumeration(uint64_t userMediaID, const Vector<WebCore::CaptureDevice>& devices, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess);
index ef11513..22f4edb 100644 (file)
@@ -298,7 +298,7 @@ messages -> WebPage LegacyReceiver {
 
 #if ENABLE(MEDIA_STREAM)
     # MediaSteam
-    UserMediaAccessWasGranted(uint64_t userMediaID, String audioDeviceUID, String videoDeviceUID)
+    UserMediaAccessWasGranted(uint64_t userMediaID, String audioDeviceUID, String videoDeviceUID, String mediaDeviceIdentifierHashSalt)
     UserMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint)
     DidCompleteMediaDeviceEnumeration(uint64_t userMediaID, Vector<WebCore::CaptureDevice> devices, String mediaDeviceIdentifierHashSalt, bool hasPersistentAccess)
 #if ENABLE(SANDBOX_EXTENSIONS)
index a93737e..3e35c27 100644 (file)
@@ -212,15 +212,11 @@ WebCore::CaptureSourceOrError UserMediaCaptureManager::createCaptureSource(const
         return { };
 
     uint64_t id = nextSessionID();
-    MediaConstraintsData constraintsData;
-    constraintsData.mandatoryConstraints = constraints->mandatoryConstraints();
-    constraintsData.advancedConstraints = constraints->advancedConstraints();
-    constraintsData.isValid = constraints->isValid();
     bool succeeded;
 
     RealtimeMediaSourceSettings settings;
     String errorMessage;
-    if (!m_process.sendSync(Messages::UserMediaCaptureManagerProxy::CreateMediaSourceForCaptureDeviceWithConstraints(id, deviceID, sourceType, constraintsData), Messages::UserMediaCaptureManagerProxy::CreateMediaSourceForCaptureDeviceWithConstraints::Reply(succeeded, errorMessage, settings), 0))
+    if (!m_process.sendSync(Messages::UserMediaCaptureManagerProxy::CreateMediaSourceForCaptureDeviceWithConstraints(id, deviceID, sourceType, *constraints), Messages::UserMediaCaptureManagerProxy::CreateMediaSourceForCaptureDeviceWithConstraints::Reply(succeeded, errorMessage, settings), 0))
         return WTFMove(errorMessage);
 
     auto source = adoptRef(*new Source(String::number(id), sourceType, emptyString(), id, *this));