diff --git a/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange-expected.txt b/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange-expected.txt new file mode 100644 index 000000000000..9764691bb570 --- /dev/null +++ b/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange-expected.txt @@ -0,0 +1,4 @@ + + +PASS Trigger configurationchange event in case OS changes microphone on its own + diff --git a/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange.html b/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange.html new file mode 100644 index 000000000000..b571976e9e67 --- /dev/null +++ b/LayoutTests/fast/mediastream/mediastreamtrack-configurationchange.html @@ -0,0 +1,35 @@ + + + + + configurationchange event. + + + + + + + + diff --git a/LayoutTests/platform/glib/TestExpectations b/LayoutTests/platform/glib/TestExpectations index 07e0b7a06265..52fd257ae3af 100644 --- a/LayoutTests/platform/glib/TestExpectations +++ b/LayoutTests/platform/glib/TestExpectations @@ -809,6 +809,8 @@ webkit.org/b/230415 fast/mediastream/RTCPeerConnection-iceconnectionstatechange- webkit.org/b/79203 fast/mediastream/RTCRtpSender-replaceTrack.html [ Failure ] webkit.org/b/187603 fast/mediastream/media-stream-track-source-failure.html [ Timeout Failure Pass ] +fast/mediastream/mediastreamtrack-configurationchange.html [ Failure ] + webkit.org/b/223508 imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https.html [ Failure Pass ] webkit.org/b/218317 media/media-source/media-source-trackid-change.html [ Failure ] diff --git a/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp b/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp index fc6a10ac566b..fee90dc46498 100644 --- a/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp +++ b/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp @@ -618,6 +618,16 @@ void MediaStreamTrack::trackSettingsChanged(MediaStreamTrackPrivate&) configureTrackRendering(); } +void MediaStreamTrack::trackConfigurationChanged(MediaStreamTrackPrivate&) +{ + queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this] { + if (!scriptExecutionContext() || scriptExecutionContext()->activeDOMObjectsAreStopped() || m_private->muted() || ended()) + return; + + dispatchEvent(Event::create(eventNames().configurationchangeEvent, Event::CanBubble::No, Event::IsCancelable::No)); + }); +} + void MediaStreamTrack::trackEnabledChanged(MediaStreamTrackPrivate&) { configureTrackRendering(); diff --git a/Source/WebCore/Modules/mediastream/MediaStreamTrack.h b/Source/WebCore/Modules/mediastream/MediaStreamTrack.h index bcafbde10724..6ede7dc01939 100644 --- a/Source/WebCore/Modules/mediastream/MediaStreamTrack.h +++ b/Source/WebCore/Modules/mediastream/MediaStreamTrack.h @@ -192,6 +192,7 @@ class MediaStreamTrack void trackMutedChanged(MediaStreamTrackPrivate&) final; void trackSettingsChanged(MediaStreamTrackPrivate&) final; void trackEnabledChanged(MediaStreamTrackPrivate&) final; + void trackConfigurationChanged(MediaStreamTrackPrivate&) final; // PlatformMediaSession::AudioCaptureSource bool isCapturingAudio() const final; diff --git a/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl b/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl index bf06541a97ee..56c3ed4da3c3 100644 --- a/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl +++ b/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl @@ -42,6 +42,7 @@ enum MediaStreamTrackState { "live", "ended" }; [ImplementedAs=mutedForBindings] readonly attribute boolean muted; attribute EventHandler onmute; attribute EventHandler onunmute; + attribute EventHandler onconfigurationchange; readonly attribute MediaStreamTrackState readyState; attribute EventHandler onended; diff --git a/Source/WebCore/dom/EventNames.h b/Source/WebCore/dom/EventNames.h index 6c1b98796d02..61aabd0895b4 100644 --- a/Source/WebCore/dom/EventNames.h +++ b/Source/WebCore/dom/EventNames.h @@ -88,6 +88,7 @@ namespace WebCore { macro(compositionend) \ macro(compositionstart) \ macro(compositionupdate) \ + macro(configurationchange) \ macro(connect) \ macro(connectionstatechange) \ macro(connecting) \ diff --git a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp index 71ed8f8d3951..3e25fdafe9c2 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp +++ b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp @@ -243,6 +243,15 @@ void MediaStreamTrackPrivate::sourceSettingsChanged() }); } +void MediaStreamTrackPrivate::sourceConfigurationChanged() +{ + ALWAYS_LOG(LOGIDENTIFIER); + + forEachObserver([this](auto& observer) { + observer.trackConfigurationChanged(*this); + }); +} + bool MediaStreamTrackPrivate::preventSourceFromStopping() { ALWAYS_LOG(LOGIDENTIFIER, m_isEnded); diff --git a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h index 6814558b30af..e607fddd0ade 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h +++ b/Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h @@ -57,6 +57,7 @@ class MediaStreamTrackPrivate final virtual void trackEnded(MediaStreamTrackPrivate&) = 0; virtual void trackMutedChanged(MediaStreamTrackPrivate&) = 0; virtual void trackSettingsChanged(MediaStreamTrackPrivate&) = 0; + virtual void trackConfigurationChanged(MediaStreamTrackPrivate&) { }; virtual void trackEnabledChanged(MediaStreamTrackPrivate&) = 0; virtual void readyStateChanged(MediaStreamTrackPrivate&) { }; }; @@ -133,6 +134,7 @@ class MediaStreamTrackPrivate final void sourceStopped() final; void sourceMutedChanged() final; void sourceSettingsChanged() final; + void sourceConfigurationChanged() final; bool preventSourceFromStopping() final; void audioUnitWillStart() final; void hasStartedProducingData() final; diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp index 50bd0a652119..fbffb66563bc 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp @@ -54,6 +54,17 @@ RealtimeMediaSource::RealtimeMediaSource(Type type, AtomString&& name, String&& , m_persistentID(WTFMove(deviceID)) , m_type(type) , m_name(WTFMove(name)) +{ + initializePersistentId(); +} + +void RealtimeMediaSource::setPersistentId(const String& persistentID) +{ + m_persistentID = persistentID; + initializePersistentId(); +} + +void RealtimeMediaSource::initializePersistentId() { if (m_persistentID.isEmpty()) m_persistentID = createVersion4UUIDString(); diff --git a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h index a81760fbbb61..1d47926bd056 100644 --- a/Source/WebCore/platform/mediastream/RealtimeMediaSource.h +++ b/Source/WebCore/platform/mediastream/RealtimeMediaSource.h @@ -85,6 +85,7 @@ class WEBCORE_EXPORT RealtimeMediaSource virtual void sourceMutedChanged() { } virtual void sourceSettingsChanged() { } virtual void audioUnitWillStart() { } + virtual void sourceConfigurationChanged() { } // Observer state queries. virtual bool preventSourceFromStopping() { return false; } @@ -137,7 +138,6 @@ class WEBCORE_EXPORT RealtimeMediaSource virtual bool interrupted() const { return false; } const AtomString& name() const { return m_name; } - void setName(const AtomString& name) { m_name = name; } unsigned fitnessScore() const { return m_fitnessScore; } @@ -259,6 +259,9 @@ class WEBCORE_EXPORT RealtimeMediaSource void setType(Type); + void setName(const AtomString&); + void setPersistentId(const String&); + private: virtual void startProducingData() { } virtual void stopProducingData() { } @@ -270,6 +273,7 @@ class WEBCORE_EXPORT RealtimeMediaSource virtual void didEnd() { } void updateHasStartedProducingData(); + void initializePersistentId(); #if !RELEASE_LOG_DISABLED RefPtr m_logger; @@ -327,6 +331,11 @@ struct CaptureSourceOrError { String convertEnumerationToString(RealtimeMediaSource::Type); +inline void RealtimeMediaSource::setName(const AtomString& name) +{ + m_name = name; +} + inline void RealtimeMediaSource::whenReady(CompletionHandler&& callback) { callback({ }); diff --git a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h index 0ff72e2bcb53..a87ade8c074d 100644 --- a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h +++ b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h @@ -72,6 +72,7 @@ class AVAudioSessionCaptureDeviceManager final : public CaptureDeviceManager { Vector retrieveAudioSessionCaptureDevices() const; void setAudioCaptureDevices(Vector&&); bool setPreferredAudioSessionDeviceUIDInternal(const String&); + void notifyNewCurrentMicrophoneDevice(CaptureDevice&&); enum class AudioSessionState { NotNeeded, Inactive, Active }; diff --git a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm index 4b62f1c3667d..e738449cca2b 100644 --- a/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm +++ b/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm @@ -29,6 +29,7 @@ #if ENABLE(MEDIA_STREAM) && PLATFORM(IOS_FAMILY) #import "AVAudioSessionCaptureDevice.h" +#import "CoreAudioSharedUnit.h" #import "Logging.h" #import "RealtimeMediaSourceCenter.h" #import @@ -277,15 +278,23 @@ - (void)routeDidChange:(NSNotification *)notification Vector AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices() const { auto defaultMicrophoneInformation = computeDefaultMicrophoneInformation(); - if (!defaultMicrophoneInformation && !m_lastDefaultMicrophone) - m_lastDefaultMicrophone = [m_audioSession currentRoute].inputs.firstObject; + auto currentInput = [m_audioSession currentRoute].inputs.firstObject; + if (currentInput) { + if (currentInput != m_lastDefaultMicrophone.get()) { + auto device = AVAudioSessionCaptureDevice::create(currentInput, currentInput); + callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([device = crossThreadCopy(WTFMove(device))] () mutable { + CoreAudioSharedUnit::singleton().handleNewCurrentMicrophoneDevice(WTFMove(device)); + }).get()); + } + m_lastDefaultMicrophone = currentInput; + } auto availableInputs = [m_audioSession availableInputs]; Vector newAudioDevices; newAudioDevices.reserveInitialCapacity(availableInputs.count); for (AVAudioSessionPortDescription *portDescription in availableInputs) { - auto device = AVAudioSessionCaptureDevice::create(portDescription, m_lastDefaultMicrophone.get()); + auto device = AVAudioSessionCaptureDevice::create(portDescription, currentInput); if (defaultMicrophoneInformation) device.setIsDefault((defaultMicrophoneInformation->isBuiltInMicrophoneDefault && portDescription.portType == getAVAudioSessionPortBuiltInMic()) || [portDescription.UID isEqualToString: defaultMicrophoneInformation->routeUID]); newAudioDevices.uncheckedAppend(WTFMove(device)); diff --git a/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp b/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp index 7a52447683f8..12ed0e5affa0 100644 --- a/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp +++ b/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.cpp @@ -294,6 +294,13 @@ void BaseAudioSharedUnit::whenAudioCaptureUnitIsNotRunning(Function&& ca m_whenNotRunningCallbacks.append(WTFMove(callback)); } +void BaseAudioSharedUnit::handleNewCurrentMicrophoneDevice(CaptureDevice&& device) +{ + forEachClient([&device](auto& client) { + client.handleNewCurrentMicrophoneDevice(device); + }); +} + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h b/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h index 6f0d3eb9d35b..68072b6c4f3b 100644 --- a/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h +++ b/Source/WebCore/platform/mediastream/mac/BaseAudioSharedUnit.h @@ -85,6 +85,8 @@ class BaseAudioSharedUnit : public CanMakeWeakPtrfirst : emptyString(); } + void handleNewCurrentMicrophoneDevice(CaptureDevice&&); + protected: void forEachClient(const Function&) const; bool hasClients() const { return !m_clients.isEmpty(); } diff --git a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp index bbe6d4a1eda6..e6695509c1be 100644 --- a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp +++ b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.cpp @@ -335,6 +335,24 @@ void CoreAudioCaptureSource::audioUnitWillStart() }); } +void CoreAudioCaptureSource::handleNewCurrentMicrophoneDevice(const CaptureDevice& device) +{ + if (!isProducingData() || persistentID() == device.persistentId()) + return; + + RELEASE_LOG_INFO(WebRTC, "CoreAudioCaptureSource switching from '%s' to '%s'", name().string().utf8().data(), device.label().utf8().data()); + + setName(AtomString { device.label() }); + setPersistentId(device.persistentId()); + + m_currentSettings = { }; + m_capabilities = { }; + + forEachObserver([](auto& observer) { + observer.sourceConfigurationChanged(); + }); +} + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h index ab3a277c4953..7a734a08eae2 100644 --- a/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h +++ b/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureSource.h @@ -59,6 +59,8 @@ class CoreAudioCaptureSource : public RealtimeMediaSource { CMClockRef timebaseClock(); + void handleNewCurrentMicrophoneDevice(const CaptureDevice&); + protected: CoreAudioCaptureSource(String&& deviceID, AtomString&& label, String&& hashSalt, uint32_t persistentID, BaseAudioSharedUnit*, PageIdentifier); virtual ~CoreAudioCaptureSource(); diff --git a/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.mm b/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.mm index 7715ec22ea83..601ae6872f30 100644 --- a/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.mm +++ b/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.mm @@ -42,11 +42,13 @@ if (!modes) return true; + RELEASE_LOG_ERROR(WebRTC, "RealtimeMediaSourceCenter::shouldInterruptAudioOnPageVisibilityChange2"); int modesCount = [modes count]; for (int i = 0; i < modesCount; i++) { if ([[modes objectAtIndex:i] isEqual: @"audio"]) return false; } + RELEASE_LOG_ERROR(WebRTC, "RealtimeMediaSourceCenter::shouldInterruptAudioOnPageVisibilityChange3"); return true; #else return false; diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp index fad8e9b156e6..e1c41fef2841 100644 --- a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp +++ b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp @@ -44,6 +44,7 @@ #if PLATFORM(COCOA) #include "CoreAudioCaptureSource.h" #include "DisplayCaptureSourceCocoa.h" +#include "MockAudioSharedUnit.h" #include "MockRealtimeVideoSourceMac.h" #endif @@ -319,6 +320,16 @@ void MockRealtimeMediaSourceCenter::setMockCaptureDevicesInterrupted(bool isCame MockRealtimeAudioSource::setIsInterrupted(isMicrophoneInterrupted); } +void MockRealtimeMediaSourceCenter::triggerMockMicrophoneConfigurationChange() +{ +#if PLATFORM(COCOA) + auto devices = audioCaptureDeviceManager().captureDevices(); + if (devices.size() <= 1) + return; + MockAudioSharedUnit::singleton().handleNewCurrentMicrophoneDevice(WTFMove(devices[1])); +#endif +} + void MockRealtimeMediaSourceCenter::setDevices(Vector&& newMockDevices) { microphoneDevices().clear(); diff --git a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h index 699884f3119c..4f545f1cd8f3 100644 --- a/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h +++ b/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h @@ -49,6 +49,8 @@ class MockRealtimeMediaSourceCenter { WEBCORE_EXPORT static void resetDevices(); WEBCORE_EXPORT static void setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted); + WEBCORE_EXPORT void triggerMockMicrophoneConfigurationChange(); + void setMockAudioCaptureEnabled(bool isEnabled) { m_isMockAudioCaptureEnabled = isEnabled; } void setMockVideoCaptureEnabled(bool isEnabled) { m_isMockVideoCaptureEnabled = isEnabled; } void setMockDisplayCaptureEnabled(bool isEnabled) { m_isMockDisplayCaptureEnabled = isEnabled; } diff --git a/Source/WebKit/GPUProcess/GPUProcess.cpp b/Source/WebKit/GPUProcess/GPUProcess.cpp index 6f6f4daec3b0..ab7d5c99e9ed 100644 --- a/Source/WebKit/GPUProcess/GPUProcess.cpp +++ b/Source/WebKit/GPUProcess/GPUProcess.cpp @@ -428,6 +428,11 @@ void GPUProcess::setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool { MockRealtimeMediaSourceCenter::setMockCaptureDevicesInterrupted(isCameraInterrupted, isMicrophoneInterrupted); } + +void GPUProcess::triggerMockMicrophoneConfigurationChange() +{ + MockRealtimeMediaSourceCenter::singleton().triggerMockMicrophoneConfigurationChange(); +} #endif // ENABLE(MEDIA_STREAM) #if HAVE(SC_CONTENT_SHARING_SESSION) diff --git a/Source/WebKit/GPUProcess/GPUProcess.h b/Source/WebKit/GPUProcess/GPUProcess.h index fb481eb9415c..d4966d261cc6 100644 --- a/Source/WebKit/GPUProcess/GPUProcess.h +++ b/Source/WebKit/GPUProcess/GPUProcess.h @@ -158,6 +158,7 @@ class GPUProcess : public AuxiliaryProcess, public ThreadSafeRefCounted GPUProcess LegacyReceiver { RemoveMockMediaDevice(String persistentId) ResetMockMediaDevices() SetMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted) + TriggerMockMicrophoneConfigurationChange() #endif #if PLATFORM(MAC) DisplayConfigurationChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags) diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp index 2d2ca701c909..a072d762383f 100644 --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp @@ -3151,6 +3151,15 @@ void WKPageSetMockCaptureDevicesInterrupted(WKPageRef pageRef, bool isCameraInte #endif } +void WKPageTriggerMockMicrophoneConfigurationChange(WKPageRef pageRef) +{ + CRASH_IF_SUSPENDED; +#if ENABLE(MEDIA_STREAM) && ENABLE(GPU_PROCESS) + auto& gpuProcess = toImpl(pageRef)->process().processPool().ensureGPUProcess(); + gpuProcess.triggerMockMicrophoneConfigurationChange(); +#endif +} + void WKPageLoadedSubresourceDomains(WKPageRef pageRef, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext) { CRASH_IF_SUSPENDED; diff --git a/Source/WebKit/UIProcess/API/C/WKPagePrivate.h b/Source/WebKit/UIProcess/API/C/WKPagePrivate.h index 0f70d7e081a1..0364a23f3007 100644 --- a/Source/WebKit/UIProcess/API/C/WKPagePrivate.h +++ b/Source/WebKit/UIProcess/API/C/WKPagePrivate.h @@ -202,6 +202,7 @@ WK_EXPORT void WKPageSetPrivateClickMeasurementAppBundleIDForTesting(WKPageRef p WK_EXPORT void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation); WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef page); WK_EXPORT void WKPageSetMockCaptureDevicesInterrupted(WKPageRef page, bool isCameraInterrupted, bool isMicrophoneInterrupted); +WK_EXPORT void WKPageTriggerMockMicrophoneConfigurationChange(WKPageRef page); typedef void (*WKPageLoadedSubresourceDomainsFunction)(WKArrayRef domains, void* functionContext); WK_EXPORT void WKPageLoadedSubresourceDomains(WKPageRef page, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext); diff --git a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp index a9435f1da129..8c34e526b95f 100644 --- a/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp +++ b/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp @@ -136,6 +136,11 @@ class UserMediaCaptureManagerProxy::SourceProxy m_connection->send(Messages::UserMediaCaptureManager::SourceSettingsChanged(m_id, m_source->settings()), 0); } + void sourceConfigurationChanged() final + { + m_connection->send(Messages::UserMediaCaptureManager::SourceConfigurationChanged(m_id, m_source->persistentID(), m_source->settings(), m_source->capabilities()), 0); + } + // May get called on a background thread. void audioSamplesAvailable(const MediaTime& time, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t numberOfFrames) final { if (m_description != description || m_shouldReset) { diff --git a/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp b/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp index 395b6a5fc10d..06f651dd1b30 100644 --- a/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp +++ b/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp @@ -350,6 +350,11 @@ void GPUProcessProxy::setMockCaptureDevicesInterrupted(bool isCameraInterrupted, { send(Messages::GPUProcess::SetMockCaptureDevicesInterrupted { isCameraInterrupted, isMicrophoneInterrupted }, 0); } + +void GPUProcessProxy::triggerMockMicrophoneConfigurationChange() +{ + send(Messages::GPUProcess::TriggerMockMicrophoneConfigurationChange { }, 0); +} #endif // ENABLE(MEDIA_STREAM) #if HAVE(SC_CONTENT_SHARING_SESSION) diff --git a/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h b/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h index 9b4106f9d6ff..f9825e923e49 100644 --- a/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h +++ b/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h @@ -87,6 +87,7 @@ class GPUProcessProxy final : public AuxiliaryProcessProxy, private ProcessThrot void removeMockMediaDevice(const String&); void resetMockMediaDevices(); void setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted); + void triggerMockMicrophoneConfigurationChange(); void updateSandboxAccess(bool allowAudioCapture, bool allowVideoCapture, bool allowDisplayCapture); #endif diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp index 2f23ca9f2d90..33dd0678c89d 100644 --- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp +++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.cpp @@ -105,6 +105,18 @@ void RemoteRealtimeMediaSource::setSettings(RealtimeMediaSourceSettings&& settin notifySettingsDidChangeObservers(changed); } +void RemoteRealtimeMediaSource::configurationChanged(String&& persistentID, WebCore::RealtimeMediaSourceSettings&& settings, WebCore::RealtimeMediaSourceCapabilities&& capabilities) +{ + setPersistentId(WTFMove(persistentID)); + setSettings(WTFMove(settings)); + setCapabilities(WTFMove(capabilities)); + setName(m_settings.label()); + + forEachObserver([](auto& observer) { + observer.sourceConfigurationChanged(); + }); +} + void RemoteRealtimeMediaSource::applyConstraintsSucceeded(WebCore::RealtimeMediaSourceSettings&& settings) { setSettings(WTFMove(settings)); diff --git a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h index 2bced27be226..65ed18ad18fe 100644 --- a/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h +++ b/Source/WebKit/WebProcess/cocoa/RemoteRealtimeMediaSource.h @@ -55,6 +55,8 @@ class RemoteRealtimeMediaSource : public WebCore::RealtimeMediaSource void captureStopped(bool didFail); void sourceMutedChanged(bool value, bool interrupted); + void configurationChanged(String&& persistentID, WebCore::RealtimeMediaSourceSettings&&, WebCore::RealtimeMediaSourceCapabilities&&); + protected: void createRemoteMediaSource(); void removeAsClient(); diff --git a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp index 98fa37d85575..3a31a74a3fc4 100644 --- a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp +++ b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp @@ -155,6 +155,19 @@ void UserMediaCaptureManager::sourceSettingsChanged(RealtimeMediaSourceIdentifie }, [](std::nullptr_t) { }); } +void UserMediaCaptureManager::sourceConfigurationChanged(RealtimeMediaSourceIdentifier identifier, String&& persistentID, RealtimeMediaSourceSettings&& settings, RealtimeMediaSourceCapabilities&& capabilities) +{ + auto iterator = m_sources.find(identifier); + if (iterator == m_sources.end()) + return; + + switchOn(iterator->value, [&](Ref& source) { + source->configurationChanged(WTFMove(persistentID), WTFMove(settings), WTFMove(capabilities)); + }, [&](Ref& source) { + source->configurationChanged(WTFMove(persistentID), WTFMove(settings), WTFMove(capabilities)); + }, [](std::nullptr_t) { }); +} + void UserMediaCaptureManager::applyConstraintsSucceeded(RealtimeMediaSourceIdentifier identifier, RealtimeMediaSourceSettings&& settings) { auto iterator = m_sources.find(identifier); diff --git a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h index 2934c5fdfcee..53e1eb4a3e87 100644 --- a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h +++ b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.h @@ -126,6 +126,8 @@ class UserMediaCaptureManager : public WebProcessSupplement, public IPC::Message void sourceMutedChanged(WebCore::RealtimeMediaSourceIdentifier, bool muted, bool interrupted); void sourceSettingsChanged(WebCore::RealtimeMediaSourceIdentifier, WebCore::RealtimeMediaSourceSettings&&); + void sourceConfigurationChanged(WebCore::RealtimeMediaSourceIdentifier, String&&, WebCore::RealtimeMediaSourceSettings&&, WebCore::RealtimeMediaSourceCapabilities&&); + void applyConstraintsSucceeded(WebCore::RealtimeMediaSourceIdentifier, WebCore::RealtimeMediaSourceSettings&&); void applyConstraintsFailed(WebCore::RealtimeMediaSourceIdentifier, String&&, String&&); diff --git a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.messages.in b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.messages.in index b036299cb371..dd63567fdcf9 100644 --- a/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.messages.in +++ b/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.messages.in @@ -27,6 +27,7 @@ messages -> UserMediaCaptureManager NotRefCounted { SourceStopped(WebCore::RealtimeMediaSourceIdentifier id, bool didFail) SourceMutedChanged(WebCore::RealtimeMediaSourceIdentifier id, bool muted, bool interrupted) SourceSettingsChanged(WebCore::RealtimeMediaSourceIdentifier id, WebCore::RealtimeMediaSourceSettings settings) + SourceConfigurationChanged(WebCore::RealtimeMediaSourceIdentifier id, String persistentID, WebCore::RealtimeMediaSourceSettings settings, WebCore::RealtimeMediaSourceCapabilities capabilities) ApplyConstraintsSucceeded(WebCore::RealtimeMediaSourceIdentifier id, WebCore::RealtimeMediaSourceSettings settings) ApplyConstraintsFailed(WebCore::RealtimeMediaSourceIdentifier id, String failedConstraint, String message) } diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl index 98f69ea6c79e..6c4a93783b97 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl @@ -388,6 +388,7 @@ interface TestRunner { undefined setMockCameraOrientation(unsigned long orientation); boolean isMockRealtimeMediaSourceCenterEnabled(); undefined setMockCaptureDevicesInterrupted(boolean isCameraInterrupted, boolean isMicrophoneInterrupted); + undefined triggerMockMicrophoneConfigurationChange(); boolean hasAppBoundSession(); undefined clearAppBoundSession(); diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp index 822557499eaf..48122e228f91 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp @@ -1837,6 +1837,11 @@ void TestRunner::setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool })); } +void TestRunner::triggerMockMicrophoneConfigurationChange() +{ + postSynchronousMessage("TriggerMockMicrophoneConfigurationChange"); +} + #if ENABLE(GAMEPAD) void TestRunner::connectMockGamepad(unsigned index) diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h index c91460a18efb..dd74ad934a2c 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h +++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h @@ -499,6 +499,7 @@ class TestRunner : public JSWrappable { void setMockCameraOrientation(unsigned); bool isMockRealtimeMediaSourceCenterEnabled(); void setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted); + void triggerMockMicrophoneConfigurationChange(); bool hasAppBoundSession(); void clearAppBoundSession(); diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp index 6473bce7ac24..2f62a74e3adb 100644 --- a/Tools/WebKitTestRunner/TestController.cpp +++ b/Tools/WebKitTestRunner/TestController.cpp @@ -3693,6 +3693,11 @@ void TestController::setMockCaptureDevicesInterrupted(bool isCameraInterrupted, WKPageSetMockCaptureDevicesInterrupted(m_mainWebView->page(), isCameraInterrupted, isMicrophoneInterrupted); } +void TestController::triggerMockMicrophoneConfigurationChange() +{ + WKPageTriggerMockMicrophoneConfigurationChange(m_mainWebView->page()); +} + struct InAppBrowserPrivacyCallbackContext { explicit InAppBrowserPrivacyCallbackContext(TestController& controller) : testController(controller) diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h index 823da69ed332..cbf39d251c78 100644 --- a/Tools/WebKitTestRunner/TestController.h +++ b/Tools/WebKitTestRunner/TestController.h @@ -320,6 +320,7 @@ class TestController { void setMockCameraOrientation(uint64_t); bool isMockRealtimeMediaSourceCenterEnabled() const; void setMockCaptureDevicesInterrupted(bool isCameraInterrupted, bool isMicrophoneInterrupted); + void triggerMockMicrophoneConfigurationChange(); bool hasAppBoundSession(); void injectUserScript(WKStringRef); diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp index c0f48c71aac7..c4a4f1c4cb6a 100644 --- a/Tools/WebKitTestRunner/TestInvocation.cpp +++ b/Tools/WebKitTestRunner/TestInvocation.cpp @@ -976,6 +976,11 @@ WKRetainPtr TestInvocation::didReceiveSynchronousMessageFromInjectedB TestController::singleton().setMockCaptureDevicesInterrupted(isCameraInterrupted, isMicrophoneInterrupted); return nullptr; } + + if (WKStringIsEqualToUTF8CString(messageName, "TriggerMockMicrophoneConfigurationChange")) { + TestController::singleton().triggerMockMicrophoneConfigurationChange(); + return nullptr; + } if (WKStringIsEqualToUTF8CString(messageName, "HasAppBoundSession")) return adoptWK(WKBooleanCreate(TestController::singleton().hasAppBoundSession()));