mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1046245 - enumerateDevices (harmless interface version). r=smaug, r=jesup
This commit is contained in:
parent
9007f77036
commit
a0143ecf52
67
dom/media/MediaDeviceInfo.cpp
Normal file
67
dom/media/MediaDeviceInfo.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/MediaDeviceInfo.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/MediaManager.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
MediaDeviceInfo::MediaDeviceInfo(const nsAString& aDeviceId,
|
||||
MediaDeviceKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aGroupId)
|
||||
: mKind(aKind)
|
||||
, mDeviceId(aDeviceId)
|
||||
, mLabel(aLabel)
|
||||
, mGroupId(aGroupId) {}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(MediaDeviceInfo)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaDeviceInfo)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaDeviceInfo)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaDeviceInfo)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject*
|
||||
MediaDeviceInfo::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return MediaDeviceInfoBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* MediaDeviceInfo::GetParentObject()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MediaDeviceInfo::GetDeviceId(nsString& retval)
|
||||
{
|
||||
retval = mDeviceId;
|
||||
}
|
||||
|
||||
MediaDeviceKind
|
||||
MediaDeviceInfo::Kind()
|
||||
{
|
||||
return mKind;
|
||||
}
|
||||
|
||||
void MediaDeviceInfo::GetGroupId(nsString& retval)
|
||||
{
|
||||
retval = mGroupId;
|
||||
}
|
||||
|
||||
void MediaDeviceInfo::GetLabel(nsString& retval)
|
||||
{
|
||||
retval = mLabel;
|
||||
}
|
||||
|
||||
MediaDeviceKind Kind();
|
||||
void GetLabel(nsString& retval);
|
||||
void GetGroupId(nsString& retval);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
60
dom/media/MediaDeviceInfo.h
Normal file
60
dom/media/MediaDeviceInfo.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_MediaDeviceInfo_h
|
||||
#define mozilla_dom_MediaDeviceInfo_h
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "MediaDeviceInfoBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
struct MediaStreamConstraints;
|
||||
|
||||
#define MOZILLA_DOM_MEDIADEVICEINFO_IMPLEMENTATION_IID \
|
||||
{0x25091870, 0x84d6, 0x4acf, {0xaf, 0x97, 0x6e, 0xd5, 0x5b, 0xe0, 0x47, 0xb2}}
|
||||
|
||||
class MediaDeviceInfo final : public nsISupports, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit MediaDeviceInfo(const nsAString& aDeviceId,
|
||||
MediaDeviceKind aKind,
|
||||
const nsAString& aLabel,
|
||||
const nsAString& aGroupId = nsString());
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaDeviceInfo)
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIADEVICEINFO_IMPLEMENTATION_IID)
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
nsISupports* GetParentObject();
|
||||
|
||||
void GetDeviceId(nsString& retval);
|
||||
MediaDeviceKind Kind();
|
||||
void GetLabel(nsString& retval);
|
||||
void GetGroupId(nsString& retval);
|
||||
|
||||
private:
|
||||
MediaDeviceKind mKind;
|
||||
nsString mDeviceId;
|
||||
nsString mLabel;
|
||||
nsString mGroupId;
|
||||
|
||||
virtual ~MediaDeviceInfo() {}
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaDeviceInfo,
|
||||
MOZILLA_DOM_MEDIADEVICEINFO_IMPLEMENTATION_IID)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MediaDeviceInfo_h
|
@ -37,6 +37,67 @@ private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
class MediaDevices::EnumDevResolver : public nsIGetUserMediaDevicesSuccessCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit EnumDevResolver(Promise* aPromise) : mPromise(aPromise) {}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSuccess(nsIVariant* aDevices) override
|
||||
{
|
||||
// Cribbed from MediaPermissionGonk.cpp
|
||||
nsIID elementIID;
|
||||
uint16_t elementType;
|
||||
|
||||
// Create array for nsIMediaDevice
|
||||
nsTArray<nsCOMPtr<nsIMediaDevice>> devices;
|
||||
// Contain the fumes
|
||||
{
|
||||
void* rawArray;
|
||||
uint32_t arrayLen;
|
||||
nsresult rv;
|
||||
rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (elementType != nsIDataType::VTYPE_INTERFACE) {
|
||||
NS_Free(rawArray);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
|
||||
for (uint32_t i = 0; i < arrayLen; ++i) {
|
||||
nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
|
||||
devices.AppendElement(device);
|
||||
NS_IF_RELEASE(supportsArray[i]); // explicitly decrease refcount for rawptr
|
||||
}
|
||||
NS_Free(rawArray); // explicitly free memory from nsIVariant::GetAsArray
|
||||
}
|
||||
nsTArray<nsRefPtr<MediaDeviceInfo>> infos;
|
||||
for (auto& device : devices) {
|
||||
nsString type;
|
||||
device->GetType(type);
|
||||
bool isVideo = type.EqualsLiteral("video");
|
||||
bool isAudio = type.EqualsLiteral("audio");
|
||||
if (isVideo || isAudio) {
|
||||
MediaDeviceKind kind = isVideo ?
|
||||
MediaDeviceKind::Videoinput : MediaDeviceKind::Audioinput;
|
||||
// TODO: return anonymized id, +label (origins w/gUM permission) (1046245)
|
||||
nsRefPtr<MediaDeviceInfo> info = new MediaDeviceInfo(nsString(), kind,
|
||||
nsString());
|
||||
infos.AppendElement(info);
|
||||
}
|
||||
}
|
||||
mPromise->MaybeResolve(infos);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~EnumDevResolver() {}
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
class MediaDevices::GumRejecter : public nsIDOMGetUserMediaErrorCallback
|
||||
{
|
||||
public:
|
||||
@ -61,17 +122,17 @@ private:
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaDevices::GumResolver, nsIDOMGetUserMediaSuccessCallback)
|
||||
NS_IMPL_ISUPPORTS(MediaDevices::EnumDevResolver, nsIGetUserMediaDevicesSuccessCallback)
|
||||
NS_IMPL_ISUPPORTS(MediaDevices::GumRejecter, nsIDOMGetUserMediaErrorCallback)
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaDevices::GetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
ErrorResult &aRv)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
|
||||
nsRefPtr<Promise> p = Promise::Create(go, aRv);
|
||||
NS_ENSURE_TRUE(!rv.Failed(), nullptr);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
nsRefPtr<GumResolver> resolver = new GumResolver(p);
|
||||
nsRefPtr<GumRejecter> rejecter = new GumRejecter(p);
|
||||
@ -81,6 +142,21 @@ MediaDevices::GetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaDevices::EnumerateDevices(ErrorResult &aRv)
|
||||
{
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
|
||||
nsRefPtr<Promise> p = Promise::Create(go, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
nsRefPtr<EnumDevResolver> resolver = new EnumDevResolver(p);
|
||||
nsRefPtr<GumRejecter> rejecter = new GumRejecter(p);
|
||||
|
||||
aRv = MediaManager::Get()->EnumerateDevices(window, resolver, rejecter);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaDevices, DOMEventTargetHelper)
|
||||
NS_INTERFACE_MAP_BEGIN(MediaDevices)
|
||||
|
@ -2,8 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MediaDevices_h__
|
||||
#define MediaDevices_h__
|
||||
#ifndef mozilla_dom_MediaDevices_h
|
||||
#define mozilla_dom_MediaDevices_h
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@ -35,8 +35,12 @@ public:
|
||||
already_AddRefed<Promise>
|
||||
GetUserMedia(const MediaStreamConstraints& aConstraints, ErrorResult &aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
EnumerateDevices(ErrorResult &aRv);
|
||||
|
||||
private:
|
||||
class GumResolver;
|
||||
class EnumDevResolver;
|
||||
class GumRejecter;
|
||||
|
||||
virtual ~MediaDevices() {}
|
||||
@ -48,4 +52,4 @@ NS_DEFINE_STATIC_IID_ACCESSOR(MediaDevices,
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MediaDevices_h__
|
||||
#endif // mozilla_dom_MediaDevices_h
|
||||
|
@ -1577,16 +1577,8 @@ MediaManager::GetUserMedia(
|
||||
#endif //MOZ_B2G
|
||||
}
|
||||
|
||||
// Store the WindowID in a hash table and mark as active. The entry is removed
|
||||
// when this window is closed or navigated away from.
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(windowID);
|
||||
if (!listeners) {
|
||||
listeners = new StreamListeners;
|
||||
GetActiveWindows()->Put(windowID, listeners);
|
||||
}
|
||||
StreamListeners* listeners = AddWindowID(windowID);
|
||||
|
||||
// Create a disabled listener to act as a placeholder
|
||||
GetUserMediaCallbackMediaStreamListener* listener =
|
||||
@ -1828,6 +1820,21 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaManager::EnumerateDevices(nsPIDOMWindow* aWindow,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
MediaStreamConstraints c;
|
||||
c.mVideo.SetAsBoolean() = true;
|
||||
c.mAudio.SetAsBoolean() = true;
|
||||
|
||||
AddWindowID(aWindow->WindowID());
|
||||
return GetUserMediaDevices(aWindow, c, aOnSuccess, aOnFailure, 0);
|
||||
}
|
||||
|
||||
MediaEngine*
|
||||
MediaManager::GetBackend(uint64_t aWindowId)
|
||||
{
|
||||
@ -1896,6 +1903,22 @@ MediaManager::OnNavigation(uint64_t aWindowID)
|
||||
}
|
||||
}
|
||||
|
||||
StreamListeners*
|
||||
MediaManager::AddWindowID(uint64_t aWindowId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
// Store the WindowID in a hash table and mark as active. The entry is removed
|
||||
// when this window is closed or navigated away from.
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(aWindowId);
|
||||
if (!listeners) {
|
||||
listeners = new StreamListeners;
|
||||
GetActiveWindows()->Put(aWindowId, listeners);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
void
|
||||
MediaManager::RemoveWindowID(uint64_t aWindowId)
|
||||
{
|
||||
|
@ -596,11 +596,18 @@ public:
|
||||
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError,
|
||||
uint64_t aInnerWindowID = 0);
|
||||
|
||||
nsresult EnumerateDevices(nsPIDOMWindow* aWindow,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure);
|
||||
|
||||
nsresult EnumerateDevices(nsPIDOMWindow* aWindow, dom::Promise& aPromise);
|
||||
void OnNavigation(uint64_t aWindowID);
|
||||
|
||||
MediaEnginePrefs mPrefs;
|
||||
|
||||
private:
|
||||
StreamListeners* AddWindowID(uint64_t aWindowId);
|
||||
WindowTable *GetActiveWindows() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
return &mActiveWindows;
|
||||
|
@ -146,6 +146,7 @@ EXPORTS.mozilla.dom += [
|
||||
'AudioTrack.h',
|
||||
'AudioTrackList.h',
|
||||
'GetUserMediaRequest.h',
|
||||
'MediaDeviceInfo.h',
|
||||
'MediaDevices.h',
|
||||
'MediaStreamError.h',
|
||||
'MediaStreamTrack.h',
|
||||
@ -183,6 +184,7 @@ UNIFIED_SOURCES += [
|
||||
'MediaDecoder.cpp',
|
||||
'MediaDecoderReader.cpp',
|
||||
'MediaDecoderStateMachine.cpp',
|
||||
'MediaDeviceInfo.cpp',
|
||||
'MediaDevices.cpp',
|
||||
'MediaManager.cpp',
|
||||
'MediaRecorder.cpp',
|
||||
|
@ -644,6 +644,8 @@ var interfaceNamesInGlobalScope =
|
||||
"LocalMediaStream",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Location",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaDeviceInfo",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaDevices",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
22
dom/webidl/MediaDeviceInfo.webidl
Normal file
22
dom/webidl/MediaDeviceInfo.webidl
Normal file
@ -0,0 +1,22 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html
|
||||
*/
|
||||
|
||||
enum MediaDeviceKind {
|
||||
"audioinput",
|
||||
"audiooutput",
|
||||
"videoinput"
|
||||
};
|
||||
|
||||
[Func="Navigator::HasUserMediaSupport"]
|
||||
interface MediaDeviceInfo {
|
||||
readonly attribute DOMString deviceId;
|
||||
readonly attribute MediaDeviceKind kind;
|
||||
readonly attribute DOMString label;
|
||||
readonly attribute DOMString groupId;
|
||||
};
|
@ -12,12 +12,12 @@
|
||||
|
||||
[Func="Navigator::HasUserMediaSupport"]
|
||||
interface MediaDevices : EventTarget {
|
||||
// attribute EventHandler ondevicechange;
|
||||
//
|
||||
// void enumerateDevices (MediaDeviceInfoCallback resultCallback);
|
||||
//
|
||||
// attribute EventHandler ondevicechange;
|
||||
// static Dictionary getSupportedConstraints (DOMString kind);
|
||||
|
||||
[Throws, Func="Navigator::HasUserMediaSupport"]
|
||||
[Throws]
|
||||
Promise<sequence<MediaDeviceInfo>> enumerateDevices();
|
||||
|
||||
[Throws]
|
||||
Promise<MediaStream> getUserMedia(optional MediaStreamConstraints constraints);
|
||||
};
|
||||
|
@ -262,6 +262,7 @@ WEBIDL_FILES = [
|
||||
'ListBoxObject.webidl',
|
||||
'LocalMediaStream.webidl',
|
||||
'Location.webidl',
|
||||
'MediaDeviceInfo.webidl',
|
||||
'MediaDevices.webidl',
|
||||
'MediaElementAudioSourceNode.webidl',
|
||||
'MediaError.webidl',
|
||||
|
Loading…
Reference in New Issue
Block a user