Bug 1654430 - Fix mDeviceIDs to only track real devices and not be overwritten by other enumerateDevices requests. r=pehrsons

Differential Revision: https://phabricator.services.mozilla.com/D89231
This commit is contained in:
Jan-Ivar Bruaroey 2020-09-22 21:28:47 +00:00
Родитель 199d9e5953
Коммит 9dcf1f976c
3 изменённых файлов: 45 добавлений и 19 удалений

Просмотреть файл

@ -2217,8 +2217,12 @@ void MediaManager::DeviceListChanged() {
}
mDeviceListChangeEvent.Notify();
// On some Windows machines, if we call EnumerateRawDevices immediately after
// receiving devicechange event, we would get an outdated devices list.
// Wait 200 ms, because
// A) on some Windows machines, if we call EnumerateRawDevices immediately
// after receiving devicechange event, we'd get an outdated devices list.
// B) Waiting helps coalesce multiple calls on us into one, which can happen
// if a device with both audio input and output is attached or removed.
// We want to react & fire a devicechange event only once in that case.
if (mDeviceChangeTimer) {
mDeviceChangeTimer->Cancel();
@ -2255,18 +2259,18 @@ void MediaManager::DeviceListChanged() {
return;
}
nsTArray<nsString> deviceIDs;
MediaManager::DeviceIdSet deviceIDs;
for (auto& device : *devices) {
nsString id;
device->GetId(id);
if (!deviceIDs.Contains(id)) {
deviceIDs.AppendElement(id);
}
MOZ_ALWAYS_TRUE(deviceIDs.put(std::move(id)));
}
// For any removed devices, notify their listeners cleanly that the
// source has stopped, so JS knows and usage indicators update.
for (auto& id : mDeviceIDs) {
if (deviceIDs.Contains(id)) {
// For any real removed cameras, microphones or speakers, notify
// their listeners cleanly that the source has stopped, so JS knows
// and usage indicators update.
for (auto iter = mDeviceIDs.iter(); !iter.done(); iter.next()) {
const auto& id = iter.get();
if (deviceIDs.has(id)) {
// Device has not been removed
continue;
}
@ -3127,7 +3131,8 @@ RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateDevicesImpl(
})
->Then(
GetMainThreadSerialEventTarget(), __func__,
[aWindowId, originKey, aOutDevices](bool) {
[aWindowId, originKey, aVideoInputEnumType, aAudioInputEnumType,
aOutDevices](bool) {
// Only run if window is still on our active list.
MediaManager* mgr = MediaManager::GetIfExists();
if (!mgr || !mgr->IsWindowStillActive(aWindowId)) {
@ -3136,12 +3141,17 @@ RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateDevicesImpl(
__func__);
}
mgr->mDeviceIDs.Clear();
for (auto& device : *aOutDevices) {
nsString id;
device->GetId(id);
if (!mgr->mDeviceIDs.Contains(id)) {
mgr->mDeviceIDs.AppendElement(id);
if (device->mKind == MediaDeviceKind::Audiooutput ||
(device->mKind == MediaDeviceKind::Audioinput &&
aAudioInputEnumType != DeviceEnumerationType::Fake &&
device->GetMediaSource() == MediaSourceEnum::Microphone) ||
(device->mKind == MediaDeviceKind::Videoinput &&
aVideoInputEnumType != DeviceEnumerationType::Fake &&
device->GetMediaSource() == MediaSourceEnum::Camera)) {
nsString id;
device->GetId(id);
MOZ_ALWAYS_TRUE(mgr->mDeviceIDs.put(std::move(id)));
}
}
@ -3670,7 +3680,7 @@ void MediaManager::Shutdown() {
mActiveCallbacks.Clear();
mCallIds.Clear();
mPendingGUMRequest.Clear();
mDeviceIDs.Clear();
mDeviceIDs.clear();
#ifdef MOZ_WEBRTC
StopWebRtcLog();
#endif

Просмотреть файл

@ -358,7 +358,21 @@ class MediaManager final : public nsIMediaManagerService, public nsIObserver {
static StaticRefPtr<MediaManager> sSingleton;
static StaticMutex sSingletonMutex;
nsTArray<nsString> mDeviceIDs;
struct nsStringHasher {
using Key = nsString;
using Lookup = nsString;
static HashNumber hash(const Lookup& aLookup) {
return HashString(aLookup.get());
}
static bool match(const Key& aKey, const Lookup& aLookup) {
return aKey == aLookup;
}
};
using DeviceIdSet = HashSet<nsString, nsStringHasher, InfallibleAllocPolicy>;
DeviceIdSet mDeviceIDs;
// Connect/Disconnect on media thread only
MediaEventListener mDeviceListChangeListener;

Просмотреть файл

@ -47,7 +47,9 @@ class MediaEngine {
virtual void Shutdown() = 0;
virtual void SetFakeDeviceChangeEventsEnabled(bool aEnable) {}
virtual void SetFakeDeviceChangeEventsEnabled(bool aEnable) {
MOZ_DIAGNOSTIC_ASSERT(false, "Fake events may not have started/stopped");
}
virtual MediaEventSource<void>& DeviceListChangeEvent() = 0;