Bug 1767893 resolve EnumerateRawDevices() promise if task is destroyed before run r=jib

Differential Revision: https://phabricator.services.mozilla.com/D175964
This commit is contained in:
Karl Tomlinson 2023-06-14 05:11:23 +00:00
parent 61ffa36c9d
commit 9ac4c7d32f
3 changed files with 37 additions and 5 deletions

View File

@ -185,9 +185,11 @@ using dom::Sequence;
using dom::UserActivation;
using dom::WindowGlobalChild;
using ConstDeviceSetPromise = MediaManager::ConstDeviceSetPromise;
using DeviceSetPromise = MediaManager::DeviceSetPromise;
using LocalDevicePromise = MediaManager::LocalDevicePromise;
using LocalDeviceSetPromise = MediaManager::LocalDeviceSetPromise;
using LocalMediaDeviceSetRefCnt = MediaManager::LocalMediaDeviceSetRefCnt;
using MediaDeviceSetRefCnt = MediaManager::MediaDeviceSetRefCnt;
using media::NewRunnableFrom;
using media::NewTaskFrom;
using media::Refcountable;
@ -1796,12 +1798,36 @@ void MediaManager::GuessVideoDeviceGroupIDs(MediaDeviceSet& aDevices,
}
}
namespace {
// Class to hold the promise returned by EnumerateRawDevices() and to resolve
// even if |task| does not run, either because GeckoViewPermissionProcessChild
// gets destroyed before ask-device-permission receives its
// got-device-permission reply, or because the media thread is no longer
// available. In either case, the process is shutting down so the result is
// not important. Resolve with an empty set, so that callers do not need to
// handle rejection.
class DeviceSetPromiseHolderWithFallback
: public MozPromiseHolder<DeviceSetPromise> {
public:
DeviceSetPromiseHolderWithFallback() = default;
DeviceSetPromiseHolderWithFallback(DeviceSetPromiseHolderWithFallback&&) =
default;
~DeviceSetPromiseHolderWithFallback() {
if (!IsEmpty()) {
Resolve(new MediaDeviceSetRefCnt(), __func__);
}
}
};
} // anonymous namespace
/**
* EnumerateRawDevices - Enumerate a list of audio & video devices that
* satisfy passed-in constraints. List contains raw id's.
*/
RefPtr<MediaManager::DeviceSetPromise> MediaManager::EnumerateRawDevices(
RefPtr<DeviceSetPromise> MediaManager::EnumerateRawDevices(
MediaSourceEnum aVideoInputType, MediaSourceEnum aAudioInputType,
EnumerationFlags aFlags) {
MOZ_ASSERT(NS_IsMainThread());
@ -1813,13 +1839,11 @@ RefPtr<MediaManager::DeviceSetPromise> MediaManager::EnumerateRawDevices(
static_cast<uint8_t>(aVideoInputType),
static_cast<uint8_t>(aAudioInputType));
MozPromiseHolder<DeviceSetPromise> holder;
DeviceSetPromiseHolderWithFallback holder;
RefPtr<DeviceSetPromise> promise = holder.Ensure(__func__);
if (sHasMainThreadShutdown) {
// The media thread is no longer available but the result will not be
// observable. Resolve with an empty set, so that callers do not need to
// handle rejection.
holder.Resolve(new MediaDeviceSetRefCnt(), __func__);
// observable. |holder| will resolve |promise| on destruction.
return promise;
}

View File

@ -5,3 +5,4 @@ load 1789908.html
load 1799168.html
load 1816708.html
load 1821477.html
pref(media.navigator.permission.device,true) pref(media.audio_loopback_dev,"real-device-request-with-clear-cache") load getUserMedia-audio.html # bug 1767893

View File

@ -0,0 +1,7 @@
<html class="reftest-wait">
<script>
navigator.mediaDevices.getUserMedia({ audio: true }).finally(() => {
document.documentElement.removeAttribute("class");
});
</script>
</html>