Bug 1709474 move mozGetUserMediaDevices from Navigator to GetUserMediaRequest r=jib,webidl,geckoview-reviewers,smaug,agi

Differential Revision: https://phabricator.services.mozilla.com/D111565
This commit is contained in:
Karl Tomlinson 2021-05-05 23:04:13 +00:00
Родитель 57e201057c
Коммит 10fe97e403
12 изменённых файлов: 68 добавлений и 174 удалений

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

@ -270,31 +270,14 @@ function handleGUMRequest(aSubject, aTopic, aData) {
let isHandlingUserInput = aSubject.isHandlingUserInput; let isHandlingUserInput = aSubject.isHandlingUserInput;
let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID); let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID);
contentWindow.navigator.mozGetUserMediaDevices( prompt(
function(devices) { contentWindow,
// If the window has been closed while we were waiting for the list of aSubject.windowID,
// devices, there's nothing to do in the callback anymore. aSubject.callID,
if (contentWindow.closed) { constraints,
return; aSubject.devices,
} secure,
isHandlingUserInput
prompt(
contentWindow,
aSubject.windowID,
aSubject.callID,
constraints,
devices,
secure,
isHandlingUserInput
);
},
function(error) {
// Device enumeration is done ahead of handleGUMRequest, so we're not
// responsible for handling the NotFoundError spec case.
denyGUMRequest({ callID: aSubject.callID });
},
aSubject.innerWindowID,
aSubject.callID
); );
} }

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

@ -1325,22 +1325,6 @@ void Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
}); });
} }
void Navigator::MozGetUserMediaDevices(
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError, uint64_t aInnerWindowID,
const nsAString& aCallID, ErrorResult& aRv) {
if (!mWindow || !mWindow->GetOuterWindow() ||
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return;
}
RefPtr<MediaManager> manager = MediaManager::Get();
// XXXbz aOnError seems to be unused?
nsCOMPtr<nsPIDOMWindowInner> window(mWindow);
aRv =
manager->GetUserMediaDevices(window, aOnSuccess, aInnerWindowID, aCallID);
}
//***************************************************************************** //*****************************************************************************
// Navigator::nsINavigatorBattery // Navigator::nsINavigatorBattery
//***************************************************************************** //*****************************************************************************

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

@ -67,7 +67,6 @@ class Gamepad;
class GamepadServiceTest; class GamepadServiceTest;
class NavigatorUserMediaSuccessCallback; class NavigatorUserMediaSuccessCallback;
class NavigatorUserMediaErrorCallback; class NavigatorUserMediaErrorCallback;
class MozGetUserMediaDevicesSuccessCallback;
struct MIDIOptions; struct MIDIOptions;
@ -201,11 +200,6 @@ class Navigator final : public nsISupports, public nsWrapperCache {
NavigatorUserMediaSuccessCallback& aOnSuccess, NavigatorUserMediaSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError, NavigatorUserMediaErrorCallback& aOnError,
CallerType aCallerType, ErrorResult& aRv); CallerType aCallerType, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void MozGetUserMediaDevices(MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError,
uint64_t aInnerWindowID, const nsAString& aCallID,
ErrorResult& aRv);
already_AddRefed<ServiceWorkerContainer> ServiceWorker(); already_AddRefed<ServiceWorkerContainer> ServiceWorker();

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

@ -1922,6 +1922,8 @@ addExternalIface('nsIEventTarget', nativeType='nsIEventTarget', notflattened=Tru
addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True) addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
addExternalIface('nsILoadGroup', nativeType='nsILoadGroup', addExternalIface('nsILoadGroup', nativeType='nsILoadGroup',
headerFile='nsILoadGroup.h', notflattened=True) headerFile='nsILoadGroup.h', notflattened=True)
addExternalIface('nsIMediaDevice', nativeType='nsIMediaDevice',
notflattened=True)
addExternalIface('nsIPrintSettings', nativeType='nsIPrintSettings', addExternalIface('nsIPrintSettings', nativeType='nsIPrintSettings',
notflattened=True) notflattened=True)
addExternalIface('nsISelectionListener', nativeType='nsISelectionListener') addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')

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

@ -5,9 +5,11 @@
#include "GetUserMediaRequest.h" #include "GetUserMediaRequest.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "MediaManager.h"
#include "mozilla/dom/MediaDevicesBinding.h" #include "mozilla/dom/MediaDevicesBinding.h"
#include "mozilla/dom/MediaStreamBinding.h" #include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/GetUserMediaRequestBinding.h" #include "mozilla/dom/GetUserMediaRequestBinding.h"
#include "nsIMediaDevice.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
@ -15,11 +17,13 @@ namespace mozilla::dom {
GetUserMediaRequest::GetUserMediaRequest( GetUserMediaRequest::GetUserMediaRequest(
nsPIDOMWindowInner* aInnerWindow, const nsAString& aCallID, nsPIDOMWindowInner* aInnerWindow, const nsAString& aCallID,
RefPtr<MediaDeviceSetRefCnt> aMediaDeviceSet,
const MediaStreamConstraints& aConstraints, bool aIsSecure, const MediaStreamConstraints& aConstraints, bool aIsSecure,
bool aIsHandlingUserInput) bool aIsHandlingUserInput)
: mInnerWindowID(aInnerWindow->WindowID()), : mInnerWindowID(aInnerWindow->WindowID()),
mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID()), mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID()),
mCallID(aCallID), mCallID(aCallID),
mMediaDeviceSet(std::move(aMediaDeviceSet)),
mConstraints(new MediaStreamConstraints(aConstraints)), mConstraints(new MediaStreamConstraints(aConstraints)),
mType(GetUserMediaRequestType::Getusermedia), mType(GetUserMediaRequestType::Getusermedia),
mIsSecure(aIsSecure), mIsSecure(aIsSecure),
@ -27,11 +31,13 @@ GetUserMediaRequest::GetUserMediaRequest(
GetUserMediaRequest::GetUserMediaRequest( GetUserMediaRequest::GetUserMediaRequest(
nsPIDOMWindowInner* aInnerWindow, const nsAString& aCallID, nsPIDOMWindowInner* aInnerWindow, const nsAString& aCallID,
RefPtr<MediaDeviceSetRefCnt> aMediaDeviceSet,
const AudioOutputOptions& aAudioOutputOptions, bool aIsSecure, const AudioOutputOptions& aAudioOutputOptions, bool aIsSecure,
bool aIsHandlingUserInput) bool aIsHandlingUserInput)
: mInnerWindowID(aInnerWindow->WindowID()), : mInnerWindowID(aInnerWindow->WindowID()),
mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID()), mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID()),
mCallID(aCallID), mCallID(aCallID),
mMediaDeviceSet(std::move(aMediaDeviceSet)),
mAudioOutputOptions(new AudioOutputOptions(aAudioOutputOptions)), mAudioOutputOptions(new AudioOutputOptions(aAudioOutputOptions)),
mType(GetUserMediaRequestType::Selectaudiooutput), mType(GetUserMediaRequestType::Selectaudiooutput),
mIsSecure(aIsSecure), mIsSecure(aIsSecure),
@ -53,6 +59,8 @@ GetUserMediaRequest::GetUserMediaRequest(nsPIDOMWindowInner* aInnerWindow,
} }
} }
GetUserMediaRequest::~GetUserMediaRequest() = default;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(GetUserMediaRequest) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(GetUserMediaRequest)
NS_IMPL_CYCLE_COLLECTING_ADDREF(GetUserMediaRequest) NS_IMPL_CYCLE_COLLECTING_ADDREF(GetUserMediaRequest)
NS_IMPL_CYCLE_COLLECTING_RELEASE(GetUserMediaRequest) NS_IMPL_CYCLE_COLLECTING_RELEASE(GetUserMediaRequest)
@ -88,6 +96,17 @@ bool GetUserMediaRequest::IsHandlingUserInput() const {
return mIsHandlingUserInput; return mIsHandlingUserInput;
} }
void GetUserMediaRequest::GetDevices(
nsTArray<RefPtr<nsIMediaDevice>>& retval) const {
MOZ_ASSERT(retval.Length() == 0);
if (!mMediaDeviceSet) {
return;
}
for (const auto& device : *mMediaDeviceSet) {
retval.AppendElement(device);
}
}
void GetUserMediaRequest::GetConstraints(MediaStreamConstraints& result) { void GetUserMediaRequest::GetConstraints(MediaStreamConstraints& result) {
MOZ_ASSERT(result.mAudio.IsBoolean() && !result.mAudio.GetAsBoolean() && MOZ_ASSERT(result.mAudio.IsBoolean() && !result.mAudio.GetAsBoolean() &&
result.mVideo.IsBoolean() && !result.mVideo.GetAsBoolean(), result.mVideo.IsBoolean() && !result.mVideo.GetAsBoolean(),

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

@ -14,9 +14,18 @@
#include "nsString.h" #include "nsString.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
class nsIMediaDevice;
class nsPIDOMWindowInner; class nsPIDOMWindowInner;
namespace mozilla { namespace mozilla {
class MediaDevice;
namespace media {
template <typename T>
class Refcountable;
}
namespace dom { namespace dom {
struct AudioOutputOptions; struct AudioOutputOptions;
@ -25,14 +34,19 @@ enum class GetUserMediaRequestType : uint8_t;
class GetUserMediaRequest : public nsISupports, public nsWrapperCache { class GetUserMediaRequest : public nsISupports, public nsWrapperCache {
public: public:
using MediaDeviceSetRefCnt =
media::Refcountable<nsTArray<RefPtr<MediaDevice>>>;
// For getUserMedia "getUserMedia:request" // For getUserMedia "getUserMedia:request"
GetUserMediaRequest(nsPIDOMWindowInner* aInnerWindow, GetUserMediaRequest(nsPIDOMWindowInner* aInnerWindow,
const nsAString& aCallID, const nsAString& aCallID,
RefPtr<MediaDeviceSetRefCnt> aMediaDeviceSet,
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
bool aIsSecure, bool aIsHandlingUserInput); bool aIsSecure, bool aIsHandlingUserInput);
// For selectAudioOutput "getUserMedia:request" // For selectAudioOutput "getUserMedia:request"
GetUserMediaRequest(nsPIDOMWindowInner* aInnerWindow, GetUserMediaRequest(nsPIDOMWindowInner* aInnerWindow,
const nsAString& aCallID, const nsAString& aCallID,
RefPtr<MediaDeviceSetRefCnt> aMediaDeviceSet,
const AudioOutputOptions& aAudioOutputOptions, const AudioOutputOptions& aAudioOutputOptions,
bool aIsSecure, bool aIsHandlingUserInput); bool aIsSecure, bool aIsHandlingUserInput);
// For "recording-device-stopped" // For "recording-device-stopped"
@ -54,16 +68,18 @@ class GetUserMediaRequest : public nsISupports, public nsWrapperCache {
void GetCallID(nsString& retval); void GetCallID(nsString& retval);
void GetRawID(nsString& retval); void GetRawID(nsString& retval);
void GetMediaSource(nsString& retval); void GetMediaSource(nsString& retval);
void GetDevices(nsTArray<RefPtr<nsIMediaDevice>>& retval) const;
void GetConstraints(MediaStreamConstraints& result); void GetConstraints(MediaStreamConstraints& result);
void GetAudioOutputOptions(AudioOutputOptions& result); void GetAudioOutputOptions(AudioOutputOptions& result);
private: private:
virtual ~GetUserMediaRequest() = default; virtual ~GetUserMediaRequest();
uint64_t mInnerWindowID, mOuterWindowID; uint64_t mInnerWindowID, mOuterWindowID;
const nsString mCallID; const nsString mCallID;
const nsString mRawID; const nsString mRawID;
const nsString mMediaSource; const nsString mMediaSource;
const RefPtr<MediaDeviceSetRefCnt> mMediaDeviceSet;
UniquePtr<MediaStreamConstraints> mConstraints; UniquePtr<MediaStreamConstraints> mConstraints;
UniquePtr<AudioOutputOptions> mAudioOutputOptions; UniquePtr<AudioOutputOptions> mAudioOutputOptions;
GetUserMediaRequestType mType; GetUserMediaRequestType mType;

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

@ -57,7 +57,6 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "nsVariant.h"
#include "nspr.h" #include "nspr.h"
#include "nss.h" #include "nss.h"
#include "pk11pub.h" #include "pk11pub.h"
@ -186,7 +185,6 @@ using dom::MediaStreamTrackSource;
using dom::MediaTrackConstraints; using dom::MediaTrackConstraints;
using dom::MediaTrackConstraintSet; using dom::MediaTrackConstraintSet;
using dom::MediaTrackSettings; using dom::MediaTrackSettings;
using dom::MozGetUserMediaDevicesSuccessCallback;
using dom::OwningBooleanOrMediaTrackConstraints; using dom::OwningBooleanOrMediaTrackConstraints;
using dom::OwningStringOrStringSequence; using dom::OwningStringOrStringSequence;
using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters; using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters;
@ -1264,12 +1262,10 @@ class GetUserMediaTask {
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaTask) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaTask)
GetUserMediaTask(uint64_t aWindowID, const ipc::PrincipalInfo& aPrincipalInfo, GetUserMediaTask(uint64_t aWindowID, const ipc::PrincipalInfo& aPrincipalInfo,
CallerType aCallerType, CallerType aCallerType)
RefPtr<MediaManager::MediaDeviceSetRefCnt> aMediaDeviceSet)
: mPrincipalInfo(aPrincipalInfo), : mPrincipalInfo(aPrincipalInfo),
mWindowID(aWindowID), mWindowID(aWindowID),
mCallerType(aCallerType), mCallerType(aCallerType) {}
mMediaDeviceSet(std::move(aMediaDeviceSet)) {}
virtual void Denied(MediaMgrError::Name aName, virtual void Denied(MediaMgrError::Name aName,
const nsCString& aMessage = ""_ns) = 0; const nsCString& aMessage = ""_ns) = 0;
@ -1324,9 +1320,6 @@ class GetUserMediaTask {
const uint64_t mWindowID; const uint64_t mWindowID;
// Whether the JS caller of getUserMedia() has system (subject) principal // Whether the JS caller of getUserMedia() has system (subject) principal
const enum CallerType mCallerType; const enum CallerType mCallerType;
public:
const RefPtr<MediaManager::MediaDeviceSetRefCnt> mMediaDeviceSet;
}; };
/** /**
@ -1345,11 +1338,8 @@ class GetUserMediaStreamTask final : public GetUserMediaTask {
RefPtr<DeviceListener> aAudioDeviceListener, RefPtr<DeviceListener> aAudioDeviceListener,
RefPtr<DeviceListener> aVideoDeviceListener, RefPtr<DeviceListener> aVideoDeviceListener,
const MediaEnginePrefs& aPrefs, const ipc::PrincipalInfo& aPrincipalInfo, const MediaEnginePrefs& aPrefs, const ipc::PrincipalInfo& aPrincipalInfo,
enum CallerType aCallerType, enum CallerType aCallerType, bool aShouldFocusSource)
RefPtr<MediaManager::MediaDeviceSetRefCnt>&& aMediaDeviceSet, : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType),
bool aShouldFocusSource)
: GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType,
std::move(aMediaDeviceSet)),
mConstraints(aConstraints), mConstraints(aConstraints),
mHolder(std::move(aHolder)), mHolder(std::move(aHolder)),
mWindowListener(std::move(aWindowListener)), mWindowListener(std::move(aWindowListener)),
@ -1710,13 +1700,10 @@ void GetUserMediaStreamTask::PrepareDOMStream() {
*/ */
class SelectAudioOutputTask final : public GetUserMediaTask { class SelectAudioOutputTask final : public GetUserMediaTask {
public: public:
SelectAudioOutputTask( SelectAudioOutputTask(MozPromiseHolder<MediaManager::DevicePromise>&& aHolder,
MozPromiseHolder<MediaManager::DevicePromise>&& aHolder, uint64_t aWindowID, enum CallerType aCallerType,
uint64_t aWindowID, enum CallerType aCallerType, const ipc::PrincipalInfo& aPrincipalInfo)
const ipc::PrincipalInfo& aPrincipalInfo, : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType),
RefPtr<MediaManager::MediaDeviceSetRefCnt>&& aMediaDeviceSet)
: GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType,
std::move(aMediaDeviceSet)),
mHolder(std::move(aHolder)) {} mHolder(std::move(aHolder)) {}
void Allowed(RefPtr<MediaDevice> aAudioOutput) { void Allowed(RefPtr<MediaDevice> aAudioOutput) {
@ -2858,7 +2845,7 @@ RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
auto task = MakeRefPtr<GetUserMediaStreamTask>( auto task = MakeRefPtr<GetUserMediaStreamTask>(
c, std::move(holder), windowID, std::move(windowListener), c, std::move(holder), windowID, std::move(windowListener),
std::move(audioListener), std::move(videoListener), prefs, std::move(audioListener), std::move(videoListener), prefs,
principalInfo, aCallerType, std::move(devices), focusSource); principalInfo, aCallerType, focusSource);
size_t taskCount = size_t taskCount =
self->AddTaskAndGetCount(windowID, callID, std::move(task)); self->AddTaskAndGetCount(windowID, callID, std::move(task));
@ -2869,7 +2856,8 @@ RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
callID.get()); callID.get());
} else { } else {
auto req = MakeRefPtr<GetUserMediaRequest>( auto req = MakeRefPtr<GetUserMediaRequest>(
window, callID, c, isSecure, isHandlingUserInput); window, callID, std::move(devices), c, isSecure,
isHandlingUserInput);
if (!Preferences::GetBool("media.navigator.permission.force") && if (!Preferences::GetBool("media.navigator.permission.force") &&
taskCount > 1) { taskCount > 1) {
// there is at least 1 pending gUM request // there is at least 1 pending gUM request
@ -2971,31 +2959,6 @@ nsresult MediaManager::AnonymizeId(nsAString& aId,
return NS_OK; return NS_OK;
} }
/* static */
already_AddRefed<nsIWritableVariant> MediaManager::ToJSArray(
MediaDeviceSet& aDevices) {
MOZ_ASSERT(NS_IsMainThread());
auto var = MakeRefPtr<nsVariantCC>();
size_t len = aDevices.Length();
if (len) {
nsTArray<nsIMediaDevice*> tmp(len);
for (auto& device : aDevices) {
tmp.AppendElement(device);
}
auto* elements = static_cast<const void*>(tmp.Elements());
nsresult rv = var->SetAsArray(nsIDataType::VTYPE_INTERFACE,
&NS_GET_IID(nsIMediaDevice), len,
const_cast<void*>(elements));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
} else {
var->SetAsEmptyArray(); // because SetAsArray() fails on zero length
// arrays.
}
return var.forget();
}
RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateDevicesImpl( RefPtr<MediaManager::MgrPromise> MediaManager::EnumerateDevicesImpl(
nsPIDOMWindowInner* aWindow, MediaSourceEnum aVideoInputType, nsPIDOMWindowInner* aWindow, MediaSourceEnum aVideoInputType,
MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType, MediaSourceEnum aAudioInputType, MediaSinkEnum aAudioOutputType,
@ -3273,40 +3236,6 @@ RefPtr<SinkInfoPromise> MediaManager::GetSinkDevice(nsPIDOMWindowInner* aWindow,
}); });
} }
/*
* GetUserMediaDevices - called by the UI-part of getUserMedia from chrome JS.
*/
nsresult MediaManager::GetUserMediaDevices(
nsPIDOMWindowInner* aWindow,
MozGetUserMediaDevicesSuccessCallback& aOnSuccess, uint64_t aWindowId,
const nsAString& aCallID) {
MOZ_ASSERT(NS_IsMainThread());
if (!aWindowId) {
aWindowId = aWindow->WindowID();
}
// Locate + return already-constrained list.
nsTArray<nsString>* callIDs;
if (!mCallIds.Get(aWindowId, &callIDs)) {
return NS_ERROR_UNEXPECTED;
}
for (auto& callID : *callIDs) {
RefPtr<GetUserMediaTask> task;
if (!aCallID.Length() || aCallID == callID) {
if (mActiveCallbacks.Get(callID, getter_AddRefs(task))) {
nsCOMPtr<nsIWritableVariant> array =
MediaManager::ToJSArray(*task->mMediaDeviceSet);
aOnSuccess.Call(array);
return NS_OK;
}
}
}
return NS_ERROR_UNEXPECTED;
}
MediaEngine* MediaManager::GetBackend() { MediaEngine* MediaManager::GetBackend() {
MOZ_ASSERT(MediaManager::IsInMediaThread()); MOZ_ASSERT(MediaManager::IsInMediaThread());
// Plugin backends as appropriate. The default engine also currently // Plugin backends as appropriate. The default engine also currently

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

@ -232,11 +232,6 @@ class MediaManager final : public nsIMediaManagerService,
const dom::MediaStreamConstraints& aConstraints, const dom::MediaStreamConstraints& aConstraints,
dom::CallerType aCallerType); dom::CallerType aCallerType);
MOZ_CAN_RUN_SCRIPT
nsresult GetUserMediaDevices(
nsPIDOMWindowInner* aWindow,
dom::MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
uint64_t aInnerWindowID = 0, const nsAString& aCallID = nsString());
RefPtr<DeviceSetPromise> EnumerateDevices(nsPIDOMWindowInner* aWindow, RefPtr<DeviceSetPromise> EnumerateDevices(nsPIDOMWindowInner* aWindow,
dom::CallerType aCallerType); dom::CallerType aCallerType);
@ -281,8 +276,6 @@ class MediaManager final : public nsIMediaManagerService,
static void AnonymizeDevices(MediaDeviceSet& aDevices, static void AnonymizeDevices(MediaDeviceSet& aDevices,
const nsACString& aOriginKey, const nsACString& aOriginKey,
const uint64_t aWindowId); const uint64_t aWindowId);
static already_AddRefed<nsIWritableVariant> ToJSArray(
MediaDeviceSet& aDevices);
/** /**
* This function tries to guess the group id for a video device in aDevices * This function tries to guess the group id for a video device in aDevices

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

@ -17,17 +17,11 @@ let observe = topic => new Promise(r => Services.obs.addObserver(function o(...a
}, topic)); }, topic));
let getDevices = async constraints => { let getDevices = async constraints => {
let [{ windowID, innerWindowID, callID }] = await Promise.race([ let [{ windowID, innerWindowID, callID, devices }] = await Promise.race([
getUserMedia(constraints), getUserMedia(constraints),
observe("getUserMedia:request") observe("getUserMedia:request")
]); ]);
let window = Services.wm.getOuterWindowWithId(windowID); let window = Services.wm.getOuterWindowWithId(windowID);
let devices = await new Promise((resolve, reject) => {
resolve = SpecialPowers.wrapCallback(resolve);
reject = SpecialPowers.wrapCallback(reject);
window.navigator.mozGetUserMediaDevices(resolve, reject,
innerWindowID, callID);
});
return devices.map(SpecialPowers.wrapCallback(d => d.QueryInterface(Ci.nsIMediaDevice))); return devices.map(SpecialPowers.wrapCallback(d => d.QueryInterface(Ci.nsIMediaDevice)));
}; };

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

@ -6,6 +6,8 @@
* This is an internal IDL file * This is an internal IDL file
*/ */
interface nsIMediaDevice;
// For gUM request start (getUserMedia:request) notification, // For gUM request start (getUserMedia:request) notification,
// rawID, mediaSource and audioOutputOptions won't be set. // rawID, mediaSource and audioOutputOptions won't be set.
// For selectAudioOutput request start (getUserMedia:request) notification, // For selectAudioOutput request start (getUserMedia:request) notification,
@ -30,6 +32,9 @@ interface GetUserMediaRequest {
readonly attribute DOMString callID; readonly attribute DOMString callID;
readonly attribute DOMString rawID; readonly attribute DOMString rawID;
readonly attribute DOMString mediaSource; readonly attribute DOMString mediaSource;
// The set of devices to consider
[Constant, Cached, Frozen]
readonly attribute sequence<nsIMediaDevice> devices;
MediaStreamConstraints getConstraints(); MediaStreamConstraints getConstraints();
AudioOutputOptions getAudioOutputOptions(); AudioOutputOptions getAudioOutputOptions();
readonly attribute boolean isSecure; readonly attribute boolean isSecure;

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

@ -256,24 +256,6 @@ partial interface Navigator {
NavigatorUserMediaErrorCallback errorCallback); NavigatorUserMediaErrorCallback errorCallback);
}; };
// nsINavigatorUserMedia
callback MozGetUserMediaDevicesSuccessCallback = void (nsIVariant? devices);
partial interface Navigator {
[Throws, ChromeOnly]
void mozGetUserMediaDevices(MozGetUserMediaDevicesSuccessCallback onsuccess,
NavigatorUserMediaErrorCallback onerror,
// The originating innerWindowID is needed to
// avoid calling the callbacks if the window has
// navigated away. It is optional only as legacy.
optional unsigned long long innerWindowID = 0,
// The callID is needed in case of multiple
// concurrent requests to find the right one.
// It is optional only as legacy.
// TODO: Rewrite to not need this method anymore,
// now that devices are enumerated earlier.
optional DOMString callID = "");
};
// Service Workers/Navigation Controllers // Service Workers/Navigation Controllers
partial interface Navigator { partial interface Navigator {
[Func="ServiceWorkerContainer::IsEnabled", SameObject] [Func="ServiceWorkerContainer::IsEnabled", SameObject]

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

@ -91,23 +91,16 @@ class GeckoViewPermission {
handleMediaRequest(aRequest) { handleMediaRequest(aRequest) {
const constraints = aRequest.getConstraints(); const constraints = aRequest.getConstraints();
const callId = aRequest.callID; const { callId, devices } = aRequest;
const denyRequest = _ => { const denyRequest = _ => {
Services.obs.notifyObservers(null, "getUserMedia:response:deny", callId); Services.obs.notifyObservers(null, "getUserMedia:response:deny", callId);
}; };
const win = Services.wm.getOuterWindowWithId(aRequest.windowID); const win = Services.wm.getOuterWindowWithId(aRequest.windowID);
new Promise((resolve, reject) => { // Release the request first.
win.navigator.mozGetUserMediaDevices( aRequest = undefined;
resolve, Promise.resolve()
reject, .then(() => {
aRequest.innerWindowID,
callId
);
// Release the request first.
aRequest = undefined;
})
.then(devices => {
if (win.closed) { if (win.closed) {
return Promise.resolve(); return Promise.resolve();
} }