Bug 1493982 move GetSinkDevice() to MediaDevices for access to device exposure history r=jib

Depends on D118443

Differential Revision: https://phabricator.services.mozilla.com/D118444
This commit is contained in:
Karl Tomlinson 2021-07-06 23:37:32 +00:00
Родитель e73a2aa7e8
Коммит 832509f1a5
5 изменённых файлов: 116 добавлений и 101 удалений

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

@ -44,6 +44,7 @@
#include "MediaStreamWindowCapturer.h"
#include "MediaTrack.h"
#include "MediaTrackList.h"
#include "Navigator.h"
#include "TimeRanges.h"
#include "VideoFrameContainer.h"
#include "VideoOutput.h"
@ -75,6 +76,7 @@
#include "mozilla/dom/HTMLSourceElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/MediaControlUtils.h"
#include "mozilla/dom/MediaDevices.h"
#include "mozilla/dom/MediaEncryptedEvent.h"
#include "mozilla/dom/MediaErrorBinding.h"
#include "mozilla/dom/MediaSource.h"
@ -160,6 +162,7 @@ using namespace mozilla::dom::HTMLMediaElement_Binding;
namespace mozilla::dom {
using AudibleState = AudioChannelService::AudibleState;
using SinkInfoPromise = MediaDevices::SinkInfoPromise;
// Number of milliseconds between progress events as defined by spec
static const uint32_t PROGRESS_MS = 350;
@ -7493,9 +7496,13 @@ already_AddRefed<Promise> HTMLMediaElement::SetSinkId(const nsAString& aSinkId,
return promise.forget();
}
RefPtr<MediaDevices> mediaDevices = win->Navigator()->GetMediaDevices(aRv);
if (aRv.Failed()) {
return nullptr;
}
nsString sinkId(aSinkId);
MediaManager::Get()
->GetSinkDevice(win, sinkId)
mediaDevices->GetSinkDevice(sinkId)
->Then(
mAbstractMainThread, __func__,
[self = RefPtr<HTMLMediaElement>(this),

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

@ -4,6 +4,7 @@
#include "mozilla/dom/MediaDevices.h"
#include "AudioDeviceInfo.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaDeviceInfo.h"
@ -23,6 +24,8 @@
namespace mozilla::dom {
using DeviceEnumerationType = MediaManager::DeviceEnumerationType;
MediaDevices::MediaDevices(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow) {}
@ -364,6 +367,74 @@ already_AddRefed<Promise> MediaDevices::SelectAudioOutput(
return p.forget();
}
static RefPtr<AudioDeviceInfo> CopyWithNullDeviceId(
AudioDeviceInfo* aDeviceInfo) {
MOZ_ASSERT(aDeviceInfo->Preferred());
nsString vendor;
aDeviceInfo->GetVendor(vendor);
uint16_t type;
aDeviceInfo->GetType(&type);
uint16_t state;
aDeviceInfo->GetState(&state);
uint16_t pref;
aDeviceInfo->GetPreferred(&pref);
uint16_t supportedFormat;
aDeviceInfo->GetSupportedFormat(&supportedFormat);
uint16_t defaultFormat;
aDeviceInfo->GetDefaultFormat(&defaultFormat);
uint32_t maxChannels;
aDeviceInfo->GetMaxChannels(&maxChannels);
uint32_t defaultRate;
aDeviceInfo->GetDefaultRate(&defaultRate);
uint32_t maxRate;
aDeviceInfo->GetMaxRate(&maxRate);
uint32_t minRate;
aDeviceInfo->GetMinRate(&minRate);
uint32_t maxLatency;
aDeviceInfo->GetMaxLatency(&maxLatency);
uint32_t minLatency;
aDeviceInfo->GetMinLatency(&minLatency);
return MakeRefPtr<AudioDeviceInfo>(
nullptr, aDeviceInfo->Name(), aDeviceInfo->GroupID(), vendor, type, state,
pref, supportedFormat, defaultFormat, maxChannels, defaultRate, maxRate,
minRate, maxLatency, minLatency);
}
RefPtr<MediaDevices::SinkInfoPromise> MediaDevices::GetSinkDevice(
const nsString& aDeviceId) {
MOZ_ASSERT(NS_IsMainThread());
auto devices = MakeRefPtr<MediaManager::MediaDeviceSetRefCnt>();
return MediaManager::Get()
->EnumerateDevicesImpl(GetOwner(), MediaSourceEnum::Other,
MediaSourceEnum::Other, MediaSinkEnum::Speaker,
DeviceEnumerationType::Normal,
DeviceEnumerationType::Normal, true, devices)
->Then(
GetCurrentSerialEventTarget(), __func__,
[aDeviceId, devices](bool) {
for (RefPtr<MediaDevice>& device : *devices) {
if (aDeviceId.IsEmpty() && device->mSinkInfo->Preferred()) {
return SinkInfoPromise::CreateAndResolve(
CopyWithNullDeviceId(device->mSinkInfo), __func__);
}
if (device->mID.Equals(aDeviceId)) {
// TODO: Check if the application is authorized to play audio
// through this device (Bug 1493982).
return SinkInfoPromise::CreateAndResolve(device->mSinkInfo,
__func__);
}
}
return SinkInfoPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
__func__);
},
[](RefPtr<MediaMgrError>&& aError) {
return SinkInfoPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
__func__);
});
}
NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MediaDevices, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN(MediaDevices)

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

@ -17,7 +17,13 @@
#include "nsITimer.h"
#include "nsTHashSet.h"
class AudioDeviceInfo;
namespace mozilla {
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MozPromise;
namespace dom {
class Promise;
@ -35,6 +41,8 @@ struct AudioOutputOptions;
class MediaDevices final : public DOMEventTargetHelper {
public:
using SinkInfoPromise = MozPromise<RefPtr<AudioDeviceInfo>, nsresult, true>;
explicit MediaDevices(nsPIDOMWindowInner* aWindow);
NS_DECL_ISUPPORTS_INHERITED
@ -61,6 +69,21 @@ class MediaDevices final : public DOMEventTargetHelper {
const AudioOutputOptions& aOptions, CallerType aCallerType,
ErrorResult& aRv);
// Get the sink that corresponds to the given device id.
// It is resposible to check if an application is
// authorized to play audio through the requested device.
// The returned promise will be resolved with the device
// information if the device id matches one and operation is
// allowed. It is pending to implement an user authorization model.
// The promise will be rejected in the following cases:
// NS_ERROR_NOT_AVAILABLE: Device id does not exist.
// NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR:
// The requested device exists but it is not allowed to be used.
// TODO, authorization model to allow an application to play audio through
// the device (Bug 1493982).
// NS_ERROR_ABORT: General error.
RefPtr<SinkInfoPromise> GetSinkDevice(const nsString& aDeviceId);
// Called when MediaManager encountered a change in its device lists.
void OnDeviceChange();

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

@ -3258,75 +3258,6 @@ RefPtr<MediaManager::DevicePromise> MediaManager::SelectAudioOutput(
});
}
RefPtr<AudioDeviceInfo> CopyWithNullDeviceId(AudioDeviceInfo* aDeviceInfo) {
MOZ_ASSERT(aDeviceInfo->Preferred());
nsString vendor;
aDeviceInfo->GetVendor(vendor);
uint16_t type;
aDeviceInfo->GetType(&type);
uint16_t state;
aDeviceInfo->GetState(&state);
uint16_t pref;
aDeviceInfo->GetPreferred(&pref);
uint16_t supportedFormat;
aDeviceInfo->GetSupportedFormat(&supportedFormat);
uint16_t defaultFormat;
aDeviceInfo->GetDefaultFormat(&defaultFormat);
uint32_t maxChannels;
aDeviceInfo->GetMaxChannels(&maxChannels);
uint32_t defaultRate;
aDeviceInfo->GetDefaultRate(&defaultRate);
uint32_t maxRate;
aDeviceInfo->GetMaxRate(&maxRate);
uint32_t minRate;
aDeviceInfo->GetMinRate(&minRate);
uint32_t maxLatency;
aDeviceInfo->GetMaxLatency(&maxLatency);
uint32_t minLatency;
aDeviceInfo->GetMinLatency(&minLatency);
return MakeRefPtr<AudioDeviceInfo>(
nullptr, aDeviceInfo->Name(), aDeviceInfo->GroupID(), vendor, type, state,
pref, supportedFormat, defaultFormat, maxChannels, defaultRate, maxRate,
minRate, maxLatency, minLatency);
}
RefPtr<SinkInfoPromise> MediaManager::GetSinkDevice(nsPIDOMWindowInner* aWindow,
const nsString& aDeviceId) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsSecureContext());
auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
return EnumerateDevicesImpl(aWindow, MediaSourceEnum::Other,
MediaSourceEnum::Other, MediaSinkEnum::Speaker,
DeviceEnumerationType::Normal,
DeviceEnumerationType::Normal, true, devices)
->Then(
GetCurrentSerialEventTarget(), __func__,
[aDeviceId, devices](bool) {
for (RefPtr<MediaDevice>& device : *devices) {
if (aDeviceId.IsEmpty() && device->mSinkInfo->Preferred()) {
return SinkInfoPromise::CreateAndResolve(
CopyWithNullDeviceId(device->mSinkInfo), __func__);
}
if (device->mID.Equals(aDeviceId)) {
// TODO: Check if the application is authorized to play audio
// through this device (Bug 1493982).
return SinkInfoPromise::CreateAndResolve(device->mSinkInfo,
__func__);
}
}
return SinkInfoPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
__func__);
},
[](RefPtr<MediaMgrError>&& aError) {
return SinkInfoPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
__func__);
});
}
MediaEngine* MediaManager::GetBackend() {
MOZ_ASSERT(MediaManager::IsInMediaThread());
// Plugin backends as appropriate. The default engine also currently

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

@ -134,7 +134,6 @@ class MediaDevice : public nsIMediaDevice {
typedef nsRefPtrHashtable<nsUint64HashKey, GetUserMediaWindowListener>
WindowTable;
typedef MozPromise<RefPtr<AudioDeviceInfo>, nsresult, true> SinkInfoPromise;
class MediaManager final : public nsIMediaManagerService,
public nsIMemoryReporter,
@ -236,24 +235,22 @@ class MediaManager final : public nsIMediaManagerService,
RefPtr<DeviceSetPromise> EnumerateDevices(nsPIDOMWindowInner* aWindow,
dom::CallerType aCallerType);
enum class DeviceEnumerationType : uint8_t {
Normal, // Enumeration should not return loopback or fake devices
Fake, // Enumeration should return fake device(s)
Loopback /* Enumeration should return loopback device(s) (possibly in
addition to normal devices) */
};
RefPtr<MgrPromise> EnumerateDevicesImpl(
nsPIDOMWindowInner* aWindow, dom::MediaSourceEnum aVideoInputType,
dom::MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
DeviceEnumerationType aVideoInputEnumType,
DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
const RefPtr<MediaDeviceSetRefCnt>& aOutDevices);
RefPtr<DevicePromise> SelectAudioOutput(
nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions,
dom::CallerType aCallerType);
// Get the sink that corresponds to the given device id.
// It is resposible to check if an application is
// authorized to play audio through the requested device.
// The returned promise will be resolved with the device
// information if the device id matches one and operation is
// allowed. It is pending to implement an user authorization model.
// The promise will be rejected in the following cases:
// NS_ERROR_NOT_AVAILABLE: Device id does not exist.
// NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR:
// The requested device exists but it is not allowed to be used.
// TODO, authorization model to allow an application to play audio through
// the device (Bug 1493982).
// NS_ERROR_ABORT: General error.
RefPtr<SinkInfoPromise> GetSinkDevice(nsPIDOMWindowInner* aWindow,
const nsString& aDeviceId);
void OnNavigation(uint64_t aWindowID);
void OnCameraMute(bool aMute);
@ -288,13 +285,6 @@ class MediaManager final : public nsIMediaManagerService,
const MediaDeviceSet& aAudios);
private:
enum class DeviceEnumerationType : uint8_t {
Normal, // Enumeration should not return loopback or fake devices
Fake, // Enumeration should return fake device(s)
Loopback /* Enumeration should return loopback device(s) (possibly in
addition to normal devices) */
};
RefPtr<MgrPromise> EnumerateRawDevices(
uint64_t aWindowId, dom::MediaSourceEnum aVideoInputType,
dom::MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
@ -302,13 +292,6 @@ class MediaManager final : public nsIMediaManagerService,
DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
const RefPtr<MediaDeviceSetRefCnt>& aOutDevices);
RefPtr<MgrPromise> EnumerateDevicesImpl(
nsPIDOMWindowInner* aWindow, dom::MediaSourceEnum aVideoInputType,
dom::MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
DeviceEnumerationType aVideoInputEnumType,
DeviceEnumerationType aAudioInputEnumType, bool aForceNoPermRequest,
const RefPtr<MediaDeviceSetRefCnt>& aOutDevices);
RefPtr<BadConstraintsPromise> SelectSettings(
const dom::MediaStreamConstraints& aConstraints,
dom::CallerType aCallerType,