diff --git a/dom/media/MediaDevices.cpp b/dom/media/MediaDevices.cpp index c500bab26b69c..249721bcc8a1b 100644 --- a/dom/media/MediaDevices.cpp +++ b/dom/media/MediaDevices.cpp @@ -236,6 +236,8 @@ RefPtr MediaDevices::FilterExposedDevices( // they are exposed only when explicitly and individually allowed by the // user. } + bool outputIsDefault = true; // First output is the default. + bool haveDefaultOutput = false; nsTHashSet exposedMicrophoneGroupIds; for (const auto& device : aDevices) { switch (device->mKind) { @@ -259,8 +261,21 @@ RefPtr MediaDevices::FilterExposedDevices( (!mExplicitlyGrantedAudioOutputRawIds.Contains(device->mRawID) && // Assumes aDevices order has microphones before speakers. !exposedMicrophoneGroupIds.Contains(device->mRawGroupID))) { + outputIsDefault = false; continue; } + if (!haveDefaultOutput && !outputIsDefault) { + // Insert a virtual default device so that the first enumerated + // device is the default output. + RefPtr info = new AudioDeviceInfo( + nullptr, u""_ns, u""_ns, u""_ns, CUBEB_DEVICE_TYPE_OUTPUT, + CUBEB_DEVICE_STATE_ENABLED, CUBEB_DEVICE_PREF_ALL, + CUBEB_DEVICE_FMT_ALL, CUBEB_DEVICE_FMT_S16NE, 2, 44100, 44100, + 44100, 128, 128); + exposed->AppendElement( + new MediaDevice(new MediaEngineFake(), info, u""_ns)); + } + haveDefaultOutput = true; break; case MediaDeviceKind::EndGuard_: continue; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index e74289fd64b92..4a80d9a5efb36 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -2868,8 +2868,11 @@ RefPtr MediaManager::AnonymizeDevices( RefPtr anonymized = new LocalMediaDeviceSetRefCnt(); for (const RefPtr& device : *rawDevices) { nsString id = device->mRawID; - nsContentUtils::AnonymizeId(id, aOriginKey); - + // An empty id represents a virtual default device, for which + // the exposed deviceId is the empty string. + if (!id.IsEmpty()) { + nsContentUtils::AnonymizeId(id, aOriginKey); + } nsString groupId = device->mRawGroupID; // Use window id to salt group id in order to make it session // based as required by the spec. This does not provide unique