Bug 934425 - Create a method in MediaManager to look up a given sink id. r?jib
Implement a new method in MediaManager that enumerates audio output devices and looks up for a given sink id asynchronously.
MozReview-Commit-ID: 9mhaH1Kxfbl
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -3366,30 +3366,81 @@ MediaManager::EnumerateDevices(nsPIDOMWi
audioOutputType = MediaSinkEnum::Speaker;
}
RefPtr<PledgeMediaDeviceSet> p = EnumerateDevicesImpl(windowId,
MediaSourceEnum::Camera,
MediaSourceEnum::Microphone,
audioOutputType,
videoEnumerationType,
audioEnumerationType);
- p->Then([onSuccess, windowListener, sourceListener](MediaDeviceSet*& aDevices) mutable {
+ p->Then([onSuccess, windowListener, sourceListener,
+ windowId = aWindow->WindowID()](MediaDeviceSet*& aDevices) mutable {
UniquePtr<MediaDeviceSet> devices(aDevices); // grab result
DebugOnly<bool> rv = windowListener->Remove(sourceListener);
MOZ_ASSERT(rv);
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
onSuccess->OnSuccess(array);
}, [onFailure, windowListener, sourceListener](MediaStreamError*& reason) mutable {
DebugOnly<bool> rv = windowListener->Remove(sourceListener);
MOZ_ASSERT(rv);
onFailure->OnError(reason);
});
return NS_OK;
}
+RefPtr<SinkInfoPromise>
+MediaManager::GetSinkDevice(nsPIDOMWindowInner* aWindow,
+ const nsString& aDeviceId)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aWindow);
+
+ // We have to add the window id here because enumerate methods
+ // check for that and abort silently if it does not exist.
+ uint64_t windowId = aWindow->WindowID();
+ nsIPrincipal* principal = aWindow->GetExtantDoc()->NodePrincipal();
+ RefPtr<GetUserMediaWindowListener> windowListener = GetWindowListener(windowId);
+ if (windowListener) {
+ PrincipalHandle existingPrincipalHandle =
+ windowListener->GetPrincipalHandle();
+ MOZ_ASSERT(PrincipalHandleMatches(existingPrincipalHandle, principal));
+ } else {
+ windowListener = new GetUserMediaWindowListener(mMediaThread, windowId,
+ MakePrincipalHandle(principal));
+ AddWindowID(windowId, windowListener);
+ }
+ // Create an inactive SourceListener to act as a placeholder, so the
+ // window listener doesn't clean itself up until we're done.
+ RefPtr<SourceListener> sourceListener = new SourceListener();
+ windowListener->Register(sourceListener);
+
+ RefPtr<SinkInfoPromise::Private> promise = new SinkInfoPromise::Private(__func__);
+ RefPtr<PledgeMediaDeviceSet> p =
+ EnumerateDevicesImpl(aWindow->WindowID(),
+ MediaSourceEnum::Other,
+ MediaSourceEnum::Other,
+ MediaSinkEnum::Speaker,
+ DeviceEnumerationType::Normal,
+ DeviceEnumerationType::Normal);
+ p->Then([aDeviceId, promise](MediaDeviceSet*& aDevices) mutable {
+ UniquePtr<MediaDeviceSet> devices(aDevices);
+ for (RefPtr<MediaDevice>& device : *devices) {
+ if (device->mID.Equals(aDeviceId)) {
+ promise->Resolve(device->mSinkInfo, __func__);
+ return;
+ }
+ }
+ promise->Resolve(nullptr, __func__);
+ }, [promise](MediaStreamError*& reason) mutable {
+ promise->Reject(NS_ERROR_DOM_NOT_FOUND_ERR, __func__);
+ });
+
+ return promise.forget();
+}
+
/*
* GetUserMediaDevices - called by the UI-part of getUserMedia from chrome JS.
*/
nsresult
MediaManager::GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
const MediaStreamConstraints& aConstraints,
dom::MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -133,16 +133,17 @@ public:
const bool mScary;
const nsString mType;
const nsString mName;
const nsString mID;
const nsString mRawID;
};
typedef nsRefPtrHashtable<nsUint64HashKey, GetUserMediaWindowListener> WindowTable;
+typedef MozPromise<RefPtr<AudioDeviceInfo>, nsresult, true> SinkInfoPromise;
class MediaManager final : public nsIMediaManagerService,
public nsIObserver
,public DeviceChangeCallback
{
friend SourceListener;
public:
static already_AddRefed<MediaManager> GetInstance();
@@ -222,16 +223,20 @@ public:
const nsAString& aCallID = nsString());
nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow,
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
nsIDOMGetUserMediaErrorCallback* aOnFailure,
dom::CallerType aCallerType);
nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow, dom::Promise& aPromise);
+
+ RefPtr<SinkInfoPromise> GetSinkDevice(nsPIDOMWindowInner* aWindow,
+ const nsString& aDeviceId);
+
void OnNavigation(uint64_t aWindowID);
bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId);
MediaEnginePrefs mPrefs;
typedef nsTArray<RefPtr<MediaDevice>> MediaDeviceSet;
virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;