Title: [271471] trunk
Revision
271471
Author
[email protected]
Date
2021-01-13 16:01:37 -0800 (Wed, 13 Jan 2021)

Log Message

Source/WebCore:
[HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
https://bugs.webkit.org/show_bug.cgi?id=220471

Reviewed by Youenn Fablet.

Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
the CompletionHandler path by just synchronously calling the completion handler with the existing
synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
activating the AVAudioSession on a background thread, and querying that session's inputs on a background
thread as well.

* platform/mediastream/CaptureDeviceManager.h:
* platform/mediastream/RealtimeMediaSourceCenter.cpp:
(WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
* platform/mediastream/RealtimeMediaSourceCenter.h:
* platform/mediastream/RealtimeMediaSourceFactory.h:
(WebCore::AudioCaptureFactory::getSpeakerDevices const):
* platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
* platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
(WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
(WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
(WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
(WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
(WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
(WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
(WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
(WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.

Source/WebKit:
[HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
https://bugs.webkit.org/show_bug.cgi?id=220471

Reviewed by Youenn Fablet.

Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
(WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
* UIProcess/UserMediaPermissionRequestManagerProxy.h:
* UIProcess/UserMediaProcessManager.cpp:
(WebKit::UserMediaProcessManager::updateCaptureDevices):
(WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
* UIProcess/UserMediaProcessManager.h:

LayoutTests:
[Cocoa] Support key rotation with HLS-backed encrypted media streams
https://bugs.webkit.org/show_bug.cgi?id=220493
<rdar://68227709>

Reviewed by Youenn Fablet.

Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
does), then the test turns that into a video capture constraint, which fails.

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

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (271470 => 271471)


--- trunk/LayoutTests/ChangeLog	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/LayoutTests/ChangeLog	2021-01-14 00:01:37 UTC (rev 271471)
@@ -1,3 +1,18 @@
+2021-01-13  Jer Noble  <[email protected]>
+
+        [Cocoa] Support key rotation with HLS-backed encrypted media streams
+        https://bugs.webkit.org/show_bug.cgi?id=220493
+        <rdar://68227709>
+
+        Reviewed by Youenn Fablet.
+
+        Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
+        constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
+        'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
+        does), then the test turns that into a video capture constraint, which fails.
+
+        * fast/mediastream/get-user-media-device-id.html:
+
 2021-01-13  Ryan Haddad  <[email protected]>
 
         [macOS WK1] ASSERTION FAILED: !needsLayout() in WebCore::FrameView::paintContents

Modified: trunk/LayoutTests/fast/mediastream/get-user-media-device-id.html (271470 => 271471)


--- trunk/LayoutTests/fast/mediastream/get-user-media-device-id.html	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/LayoutTests/fast/mediastream/get-user-media-device-id.html	2021-01-14 00:01:37 UTC (rev 271471)
@@ -25,6 +25,8 @@
                 return navigator.mediaDevices.enumerateDevices();
             }).then(devices => {
                 devices.forEach((device) => {
+                    if (device.kind == "audiooutput")
+                        return;
                     let kind = device.kind == "audioinput" ? "audio" : "video";
                     deviceIds.push({ type: kind, id : device.deviceId});
                 });

Modified: trunk/Source/WebCore/ChangeLog (271470 => 271471)


--- trunk/Source/WebCore/ChangeLog	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/ChangeLog	2021-01-14 00:01:37 UTC (rev 271471)
@@ -1,5 +1,37 @@
 2021-01-13  Jer Noble  <[email protected]>
 
+        [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+        https://bugs.webkit.org/show_bug.cgi?id=220471
+
+        Reviewed by Youenn Fablet.
+
+        Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
+        synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
+        to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
+        the CompletionHandler path by just synchronously calling the completion handler with the existing
+        synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
+        activating the AVAudioSession on a background thread, and querying that session's inputs on a background
+        thread as well.
+
+        * platform/mediastream/CaptureDeviceManager.h:
+        * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+        (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+        * platform/mediastream/RealtimeMediaSourceCenter.h:
+        * platform/mediastream/RealtimeMediaSourceFactory.h:
+        (WebCore::AudioCaptureFactory::getSpeakerDevices const):
+        * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+        * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+        (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
+        (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+        (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
+        (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
+        (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
+        (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
+        (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
+        (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.
+
+2021-01-13  Jer Noble  <[email protected]>
+
         Facebook pauses video in PiP during scroll
         https://bugs.webkit.org/show_bug.cgi?id=220581
         <rdar://67273166>

Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -35,6 +35,7 @@
 class WEBCORE_EXPORT CaptureDeviceManager {
 public:
     virtual const Vector<CaptureDevice>& captureDevices() = 0;
+    virtual void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& callback) { callback(copyToVector(captureDevices())); };
     virtual Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return WTF::nullopt; }
 
 protected:

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-01-14 00:01:37 UTC (rev 271471)
@@ -112,27 +112,48 @@
     audioSource->whenReady(WTFMove(whenAudioSourceReady));
 }
 
-Vector<CaptureDevice> RealtimeMediaSourceCenter::getMediaStreamDevices()
+void RealtimeMediaSourceCenter::getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
 {
-    Vector<CaptureDevice> result;
-    for (auto& device : audioCaptureFactory().audioCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : audioCaptureFactory().speakerDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : videoCaptureFactory().videoCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : displayCaptureFactory().displayCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
+    class CaptureDeviceAccumulator : public RefCounted<CaptureDeviceAccumulator> {
+    public:
+        static Ref<CaptureDeviceAccumulator> create(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+        {
+            return adoptRef(*new CaptureDeviceAccumulator(WTFMove(completion)));
+        }
 
-    return result;
+        ~CaptureDeviceAccumulator()
+        {
+            m_completionHandler(WTFMove(m_results));
+        }
+
+        CompletionHandler<void(Vector<CaptureDevice>&&)> accumulate()
+        {
+            return [this, protectedThis = makeRef(*this)] (Vector<CaptureDevice>&& result) {
+                m_results.appendVector(WTFMove(result));
+            };
+        }
+
+    private:
+        explicit CaptureDeviceAccumulator(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+            : m_completionHandler(WTFMove(completion))
+        {
+        }
+
+        CompletionHandler<void(Vector<CaptureDevice>&&)> m_completionHandler;
+        Vector<CaptureDevice> m_results;
+    };
+
+    auto accumulator = CaptureDeviceAccumulator::create([completion = WTFMove(completion)] (auto&& devices) mutable {
+        devices.removeAllMatching([] (auto& captureDevice) {
+            return !captureDevice.enabled();
+        });
+        completion(WTFMove(devices));
+    });
+
+    audioCaptureFactory().audioCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    videoCaptureFactory().videoCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    displayCaptureFactory().displayCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    audioCaptureFactory().getSpeakerDevices(accumulator->accumulate());
 }
 
 static void addStringToSHA1(SHA1& sha1, const String& string)

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -66,7 +66,7 @@
     using NewMediaStreamHandler = Function<void(Expected<Ref<MediaStreamPrivate>, String>&&)>;
     void createMediaStream(Ref<const Logger>&&, NewMediaStreamHandler&&, String&&, CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, const MediaStreamRequest&);
 
-    WEBCORE_EXPORT Vector<CaptureDevice> getMediaStreamDevices();
+    WEBCORE_EXPORT void getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&);
 
     const RealtimeMediaSourceSupportedConstraints& supportedConstraints() { return m_supportedConstraints; }
 

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -27,6 +27,7 @@
 
 #if ENABLE(MEDIA_STREAM)
 
+#include <wtf/CompletionHandler.h>
 #include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
@@ -62,6 +63,7 @@
     virtual CaptureSourceOrError createAudioCaptureSource(const CaptureDevice&, String&&, const MediaConstraints*) = 0;
     virtual CaptureDeviceManager& audioCaptureDeviceManager() = 0;
     virtual const Vector<CaptureDevice>& speakerDevices() const = 0;
+    virtual void getSpeakerDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) const { completion(copyToVector(speakerDevices())); }
 
     class ExtensiveObserver : public CanMakeWeakPtr<ExtensiveObserver> { };
     virtual void addExtensiveObserver(ExtensiveObserver&) { };

Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -48,6 +48,7 @@
     static AVAudioSessionCaptureDeviceManager& singleton();
 
     const Vector<CaptureDevice>& captureDevices() final;
+    void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&) final;
     const Vector<CaptureDevice>& speakerDevices() const { return m_speakerDevices; }
     Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&);
 
@@ -63,8 +64,10 @@
     ~AVAudioSessionCaptureDeviceManager();
 
     void createAudioSession();
+    void activateAudioSession();
     void refreshAudioCaptureDevices();
-    Vector<AVAudioSessionCaptureDevice>& audioSessionCaptureDevices();
+    Vector<AVAudioSessionCaptureDevice> retrieveAudioSessionCaptureDevices() const;
+    void setAudioCaptureDevices(Vector<AVAudioSessionCaptureDevice>&&);
 
     enum class AudioSessionState { NotNeeded, Inactive, Active };
 

Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm (271470 => 271471)


--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-01-14 00:01:37 UTC (rev 271471)
@@ -136,16 +136,12 @@
     return WTF::nullopt;
 }
 
-Vector<AVAudioSessionCaptureDevice>& AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices()
+Optional<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID(const String& deviceID)
 {
     if (!m_audioSessionCaptureDevices)
         refreshAudioCaptureDevices();
-    return m_audioSessionCaptureDevices.value();
-}
 
-Optional<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID(const String& deviceID)
-{
-    for (auto& device : audioSessionCaptureDevices()) {
+    for (auto& device : *m_audioSessionCaptureDevices) {
         if (device.persistentId() == deviceID)
             return device;
     }
@@ -154,42 +150,71 @@
 
 void AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices()
 {
-    if (m_updateDeviceStateQueue.hasPendingTasks())
-        return;
-
-    m_updateDeviceStateQueue.enqueueTask([this] {
-        refreshAudioCaptureDevices();
-    });
+    getCaptureDevices([] (auto) { });
 }
 
 void AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
 {
-    {
-        // Make sure we have created the audio session.
-        auto locker = holdLock(m_lock);
+    if (m_audioSessionState == AudioSessionState::Inactive) {
+        m_audioSessionState = AudioSessionState::Active;
+
+        dispatch_sync(m_dispatchQueue, makeBlockPtr([this] {
+            activateAudioSession();
+        }).get());
     }
-    bool firstTime = !m_devices;
+
+    Vector<AVAudioSessionCaptureDevice> newAudioDevices;
+    dispatch_sync(m_dispatchQueue, makeBlockPtr([&] {
+        newAudioDevices = retrieveAudioSessionCaptureDevices();
+    }).get());
+    setAudioCaptureDevices(WTFMove(newAudioDevices));
+}
+
+void AVAudioSessionCaptureDeviceManager::getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+{
     if (m_audioSessionState == AudioSessionState::Inactive) {
         m_audioSessionState = AudioSessionState::Active;
 
-        if (!m_listener)
-            m_listener = adoptNS([[WebAVAudioSessionAvailableInputsListener alloc] initWithCallback:this audioSession:m_audioSession.get()]);
-
-        NSError *error = nil;
-        [m_audioSession setActive:YES withOptions:0 error:&error];
-        if (error)
-            RELEASE_LOG_ERROR(WebRTC, "Failed to activate audio session with error: %@.", error.localizedDescription);
+        dispatch_async(m_dispatchQueue, makeBlockPtr([this] {
+            activateAudioSession();
+        }).get());
     }
 
+    dispatch_async(m_dispatchQueue, makeBlockPtr([this, completion = WTFMove(completion)] () mutable {
+        auto newAudioDevices = retrieveAudioSessionCaptureDevices();
+        callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([this, completion = WTFMove(completion), newAudioDevices = WTFMove(newAudioDevices)] () mutable {
+            setAudioCaptureDevices(WTFMove(newAudioDevices));
+            completion(copyToVector(*m_devices));
+        }).get());
+    }).get());
+}
+
+void AVAudioSessionCaptureDeviceManager::activateAudioSession()
+{
+    if (!m_listener)
+        m_listener = adoptNS([[WebAVAudioSessionAvailableInputsListener alloc] initWithCallback:this audioSession:m_audioSession.get()]);
+
+    NSError *error = nil;
+    [m_audioSession setActive:YES withOptions:0 error:&error];
+    if (error)
+        RELEASE_LOG_ERROR(WebRTC, "Failed to activate audio session with error: %@.", error.localizedDescription);
+}
+
+Vector<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices() const
+{
     Vector<AVAudioSessionCaptureDevice> newAudioDevices;
-    Vector<CaptureDevice> newDevices;
     auto *defaultInput = [m_audioSession currentRoute].inputs.firstObject;
-    for (AVAudioSessionPortDescription *portDescription in [m_audioSession availableInputs]) {
-        auto audioDevice = AVAudioSessionCaptureDevice::create(portDescription, defaultInput);
-        newDevices.append(audioDevice);
-        newAudioDevices.append(WTFMove(audioDevice));
-    }
+    newAudioDevices.reserveInitialCapacity([m_audioSession availableInputs].count);
 
+    for (AVAudioSessionPortDescription *portDescription in [m_audioSession availableInputs])
+        newAudioDevices.uncheckedAppend(AVAudioSessionCaptureDevice::create(portDescription, defaultInput));
+
+    return newAudioDevices;
+}
+
+void AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices(Vector<AVAudioSessionCaptureDevice>&& newAudioDevices)
+{
+    bool firstTime = !m_devices;
     bool haveDeviceChanges = !m_devices || newAudioDevices.size() != m_devices->size();
     if (!haveDeviceChanges) {
         for (size_t i = 0; i < newAudioDevices.size(); ++i) {
@@ -203,6 +228,7 @@
     if (!haveDeviceChanges && !firstTime)
         return;
 
+    auto newDevices = copyToVectorOf<CaptureDevice>(newAudioDevices);
     m_audioSessionCaptureDevices = WTFMove(newAudioDevices);
     std::sort(newDevices.begin(), newDevices.end(), [] (auto& first, auto& second) -> bool {
         return first.isDefault() && !second.isDefault();

Modified: trunk/Source/WebKit/ChangeLog (271470 => 271471)


--- trunk/Source/WebKit/ChangeLog	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebKit/ChangeLog	2021-01-14 00:01:37 UTC (rev 271471)
@@ -1,3 +1,21 @@
+2021-01-13  Jer Noble  <[email protected]>
+
+        [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+        https://bugs.webkit.org/show_bug.cgi?id=220471
+
+        Reviewed by Youenn Fablet.
+
+        Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
+        (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
+        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+        * UIProcess/UserMediaProcessManager.cpp:
+        (WebKit::UserMediaProcessManager::updateCaptureDevices):
+        (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
+        * UIProcess/UserMediaProcessManager.h:
+
 2021-01-13  Per Arne Vollan  <[email protected]>
 
         [Cocoa] Network extension sandbox extensions are sometimes issued too late

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (271470 => 271471)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2021-01-14 00:01:37 UTC (rev 271471)
@@ -659,40 +659,42 @@
     });
 }
 
-Vector<CaptureDevice> UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList(bool revealIdsAndLabels)
+void UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList(bool revealIdsAndLabels, CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
 {
-    static const int defaultMaximumCameraCount = 1;
-    static const int defaultMaximumMicrophoneCount = 1;
+    static const unsigned defaultMaximumCameraCount = 1;
+    static const unsigned defaultMaximumMicrophoneCount = 1;
 
-    auto devices = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
-    int cameraCount = 0;
-    int microphoneCount = 0;
+    RealtimeMediaSourceCenter::singleton().getMediaStreamDevices([this, weakThis = makeWeakPtr(this), revealIdsAndLabels, completion = WTFMove(completion)] (auto&& devices) mutable {
+        unsigned cameraCount = 0;
+        unsigned 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 && device.type() != WebCore::CaptureDevice::DeviceType::Speaker))
-            continue;
+        Vector<CaptureDevice> filteredDevices;
+        for (const auto& device : devices) {
+            if (!device.enabled() || (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone && device.type() != WebCore::CaptureDevice::DeviceType::Speaker))
+                continue;
 
-        if (!revealIdsAndLabels) {
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount)
-                continue;
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount)
-                continue;
-            if (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)
-                continue;
-        } else {
-            // We only expose speakers tied to a microphone for the moment.
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Speaker && !haveMicrophoneDevice(devices, device.groupId()))
-                continue;
+            if (!revealIdsAndLabels) {
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount)
+                    continue;
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount)
+                    continue;
+                if (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)
+                    continue;
+            } else {
+                // We only expose speakers tied to a microphone for the moment.
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Speaker && !haveMicrophoneDevice(devices, device.groupId()))
+                    continue;
+            }
+
+            filteredDevices.append(revealIdsAndLabels ? device : CaptureDevice({ }, device.type(), { }, { }));
         }
 
-        filteredDevices.append(revealIdsAndLabels ? device : CaptureDevice({ }, device.type(), { }, { }));
-    }
+        if (weakThis)
+            m_hasFilteredDeviceList = !revealIdsAndLabels;
 
-    m_hasFilteredDeviceList = !revealIdsAndLabels;
-
-    ALWAYS_LOG(LOGIDENTIFIER, filteredDevices.size(), " devices revealed");
-    return filteredDevices;
+        ALWAYS_LOG(LOGIDENTIFIER, filteredDevices.size(), " devices revealed");
+        completion(WTFMove(filteredDevices));
+    });
 }
 #endif
 
@@ -744,7 +746,9 @@
             bool revealIdsAndLabels = originHasPersistentAccess || wasGrantedVideoOrAudioAccess(frameID, userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get());
 
             callCompletionHandler.release();
-            completionHandler(computeFilteredDeviceList(revealIdsAndLabels), deviceIDHashSalt);
+            computeFilteredDeviceList(revealIdsAndLabels, [completionHandler = WTFMove(completionHandler), deviceIDHashSalt = WTFMove(deviceIDHashSalt)] (auto&& devices) mutable {
+                completionHandler(devices, deviceIDHashSalt);
+            });
         });
     };
 

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (271470 => 271471)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -120,7 +120,7 @@
 
     bool wasGrantedVideoOrAudioAccess(WebCore::FrameIdentifier, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin);
 
-    Vector<WebCore::CaptureDevice> computeFilteredDeviceList(bool revealIdsAndLabels);
+    void computeFilteredDeviceList(bool revealIdsAndLabels, CompletionHandler<void(Vector<WebCore::CaptureDevice>&&)>&&);
 
     void processUserMediaPermissionRequest();
     void processUserMediaPermissionInvalidRequest(const String& invalidConstraint);

Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp (271470 => 271471)


--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2021-01-14 00:01:37 UTC (rev 271471)
@@ -217,41 +217,51 @@
     });
 }
 
-void UserMediaProcessManager::beginMonitoringCaptureDevices()
+void UserMediaProcessManager::updateCaptureDevices(ShouldNotify shouldNotify)
 {
-    static std::once_flag onceFlag;
+    WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices([this, shouldNotify] (auto&& newDevices) mutable {
+        auto oldDevices = WTFMove(m_captureDevices);
+        m_captureDevices = WTFMove(newDevices);
 
-    std::call_once(onceFlag, [this] {
-        m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+        if (shouldNotify == ShouldNotify::No)
+            return;
 
-        WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() {
-            auto oldDevices = WTFMove(m_captureDevices);
-            m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+        if (m_captureDevices.size() == oldDevices.size()) {
+            bool haveChanges = false;
+            for (auto &newDevice : m_captureDevices) {
+                if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone)
+                    continue;
 
-            if (m_captureDevices.size() == oldDevices.size()) {
-                bool haveChanges = false;
-                for (auto &newDevice : m_captureDevices) {
-                    if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone)
-                        continue;
+                auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) {
+                    return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled();
+                });
 
-                    auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) {
-                        return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled();
-                    });
-
-                    if (index == notFound) {
-                        haveChanges = true;
-                        break;
-                    }
+                if (index == notFound) {
+                    haveChanges = true;
+                    break;
                 }
-
-                if (!haveChanges)
-                    return;
             }
 
-            // When a device with camera and microphone is attached or detached, the CaptureDevice notification for
-            // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks.
-            if (!m_debounceTimer.isActive())
-                m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval);
+            if (!haveChanges)
+                return;
+        }
+
+        // When a device with camera and microphone is attached or detached, the CaptureDevice notification for
+        // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks.
+        if (!m_debounceTimer.isActive())
+            m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval);
+    });
+}
+
+void UserMediaProcessManager::beginMonitoringCaptureDevices()
+{
+    static std::once_flag onceFlag;
+
+    std::call_once(onceFlag, [this] {
+        updateCaptureDevices(ShouldNotify::No);
+
+        WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() {
+            updateCaptureDevices(ShouldNotify::Yes);
         });
     });
 }

Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h (271470 => 271471)


--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h	2021-01-13 23:32:21 UTC (rev 271470)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h	2021-01-14 00:01:37 UTC (rev 271471)
@@ -48,6 +48,8 @@
     void beginMonitoringCaptureDevices();
 
 private:
+    enum class ShouldNotify { Yes, No };
+    void updateCaptureDevices(ShouldNotify);
     void captureDevicesChanged();
 
     Vector<WebCore::CaptureDevice> m_captureDevices;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to