diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 4ac9f6084020..944e76783215 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -2219,14 +2219,38 @@ void MediaManager::DeviceListChanged() { // On some Windows machines, if we call EnumerateRawDevices immediately after // receiving devicechange event, we would get an outdated devices list. - PR_Sleep(PR_MillisecondsToInterval(200)); + + if (mDeviceChangeTimer) { + mDeviceChangeTimer->Cancel(); + } else { + mDeviceChangeTimer = MakeRefPtr(); + } + RefPtr self = this; auto devices = MakeRefPtr(); - EnumerateRawDevices(0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone, - MediaSinkEnum::Speaker, DeviceEnumerationType::Normal, - DeviceEnumerationType::Normal, false, devices) + mDeviceChangeTimer->WaitFor(TimeDuration::FromMilliseconds(200), __func__) ->Then( GetCurrentSerialEventTarget(), __func__, - [self = RefPtr(this), this, devices](bool) { + [self, this, devices] { + if (!MediaManager::GetIfExists()) { + return MgrPromise::CreateAndReject( + MakeRefPtr(MediaMgrError::Name::AbortError, + u"In shutdown"_ns), + __func__); + } + return EnumerateRawDevices( + 0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone, + MediaSinkEnum::Speaker, DeviceEnumerationType::Normal, + DeviceEnumerationType::Normal, false, devices); + }, + []() { + // Timer was canceled by us, or we're in shutdown. + return MgrPromise::CreateAndReject( + MakeRefPtr(MediaMgrError::Name::AbortError), + __func__); + }) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [self, this, devices](bool) { if (!MediaManager::GetIfExists()) { return; } @@ -3618,6 +3642,12 @@ void MediaManager::Shutdown() { #endif } + if (mDeviceChangeTimer) { + mDeviceChangeTimer->Cancel(); + // Drop ref to MediaTimer early to avoid blocking SharedThreadPool shutdown + mDeviceChangeTimer = nullptr; + } + { // Close off any remaining active windows. diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index ee23c67bf97e..1169288c8a87 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -41,6 +41,7 @@ class nsIPrefBranch; namespace mozilla { class TaskQueue; +class MediaTimer; namespace dom { struct MediaStreamConstraints; struct MediaTrackConstraints; @@ -343,6 +344,7 @@ class MediaManager final : public nsIMediaManagerService, public nsIObserver { nsRefPtrHashtable mActiveCallbacks; nsClassHashtable> mCallIds; nsTArray> mPendingGUMRequest; + RefPtr mDeviceChangeTimer; bool mCamerasMuted = false; bool mMicrophonesMuted = false;