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()));