зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1046245 - enumerateDevices session-persisted hmac id. r=jesup
This commit is contained in:
Родитель
4a058ae74a
Коммит
600361d553
|
@ -127,9 +127,7 @@ public:
|
|||
Preferences::GetBool("media.navigator.permission.disabled", false)) {
|
||||
device->GetName(name);
|
||||
}
|
||||
// TODO: return anonymized origin-persistent id (1046245)
|
||||
nsRefPtr<MediaDeviceInfo> info = new MediaDeviceInfo(nsString(), kind,
|
||||
name);
|
||||
nsRefPtr<MediaDeviceInfo> info = new MediaDeviceInfo(id, kind, name);
|
||||
infos.AppendElement(info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPrincipal.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/PeerIdentity.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
@ -42,6 +43,10 @@
|
|||
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nspr.h"
|
||||
#include "nss.h"
|
||||
#include "pk11pub.h"
|
||||
|
||||
/* Using WebRTC backend on Desktops (Mac, Windows, Linux), otherwise default */
|
||||
#include "MediaEngineDefault.h"
|
||||
|
@ -194,45 +199,61 @@ HostHasPermission(nsIURI &docURI)
|
|||
return false;
|
||||
}
|
||||
|
||||
ErrorCallbackRunnable::ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError,
|
||||
uint64_t aWindowID)
|
||||
: mError(&aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
/**
|
||||
* Send an error back to content.
|
||||
* Do this only on the main thread. The onSuccess callback is also passed here
|
||||
* so it can be released correctly.
|
||||
*/
|
||||
template<class SuccessCallbackType>
|
||||
class ErrorCallbackRunnable : public nsRunnable
|
||||
{
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
public:
|
||||
ErrorCallbackRunnable(
|
||||
nsCOMPtr<SuccessCallbackType>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError,
|
||||
uint64_t aWindowID)
|
||||
: mError(&aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
ErrorCallbackRunnable::~ErrorCallbackRunnable()
|
||||
{
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
NS_IMETHODIMP
|
||||
ErrorCallbackRunnable::Run()
|
||||
{
|
||||
// Only run if the window is still active.
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
nsCOMPtr<SuccessCallbackType> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
|
||||
if (!(mManager->IsWindowStillActive(mWindowID))) {
|
||||
// Only run if the window is still active.
|
||||
if (!(mManager->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window, *mError);
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window, *mError);
|
||||
onFailure->OnError(error);
|
||||
private:
|
||||
~ErrorCallbackRunnable()
|
||||
{
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<SuccessCallbackType> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaMgrError> mError;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
|
||||
/**
|
||||
* Invoke the "onSuccess" callback in content. The callback will take a
|
||||
|
@ -516,6 +537,12 @@ MediaDevice::GetId(nsAString& aID)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDevice::SetId(const nsAString& aID)
|
||||
{
|
||||
mID.Assign(aID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaDevice::GetFacingMode(nsAString& aFacingMode)
|
||||
{
|
||||
|
@ -726,6 +753,26 @@ public:
|
|||
uint32_t mPlayoutDelay;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
MediaOperationTask::ReturnCallbackError(nsresult rv, const char* errorLog)
|
||||
{
|
||||
MM_LOG(("%s , rv=%d", errorLog, rv));
|
||||
NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(),
|
||||
mOnTracksAvailableCallback.forget()));
|
||||
nsString log;
|
||||
|
||||
log.AssignASCII(errorLog);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(
|
||||
NS_LITERAL_STRING("InternalError"), log);
|
||||
NS_DispatchToMainThread(
|
||||
new ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>(onSuccess,
|
||||
mOnFailure,
|
||||
*error,
|
||||
mWindowID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MediaStream, attaches a listener and fires off a success callback
|
||||
* to the DOM with the stream. We also pass in the error callback so it can
|
||||
|
@ -1091,8 +1138,11 @@ public:
|
|||
Fail(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString()) {
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage);
|
||||
nsRefPtr<ErrorCallbackRunnable> runnable =
|
||||
new ErrorCallbackRunnable(mOnSuccess, mOnFailure, *error, mWindowID);
|
||||
nsRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>> runnable =
|
||||
new ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>(mOnSuccess,
|
||||
mOnFailure,
|
||||
*error,
|
||||
mWindowID);
|
||||
// These should be empty now
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
|
@ -1317,13 +1367,121 @@ private:
|
|||
*/
|
||||
class GetUserMediaDevicesTask : public Task
|
||||
{
|
||||
static unsigned char* unconst_uchar_cast(const char *s) {
|
||||
return reinterpret_cast<unsigned char*>(const_cast<char*>(s));
|
||||
}
|
||||
|
||||
// Cribbed from nricectx.cpp
|
||||
static nsresult
|
||||
hmac_sha1(const char *key, int keyl, const char *buf, int bufl,
|
||||
unsigned char *result) {
|
||||
const CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC;
|
||||
PK11SlotInfo *slot = 0;
|
||||
MOZ_ASSERT(keyl > 0);
|
||||
SECItem keyi = { siBuffer, unconst_uchar_cast(key),
|
||||
static_cast<unsigned int>(keyl) };
|
||||
PK11SymKey *skey = 0;
|
||||
PK11Context *hmac_ctx = 0;
|
||||
SECStatus status;
|
||||
unsigned int hmac_len;
|
||||
SECItem param = { siBuffer, nullptr, 0 };
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
if (!slot) {
|
||||
goto abort;
|
||||
}
|
||||
skey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_SIGN, &keyi,
|
||||
nullptr);
|
||||
if (!skey) {
|
||||
goto abort;
|
||||
}
|
||||
|
||||
hmac_ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, skey, ¶m);
|
||||
if (!hmac_ctx) {
|
||||
goto abort;
|
||||
}
|
||||
status = PK11_DigestBegin(hmac_ctx);
|
||||
if (status != SECSuccess) {
|
||||
goto abort;
|
||||
}
|
||||
status = PK11_DigestOp(hmac_ctx, unconst_uchar_cast(buf), bufl);
|
||||
if (status != SECSuccess) {
|
||||
goto abort;
|
||||
}
|
||||
status = PK11_DigestFinal(hmac_ctx, result, &hmac_len, 20);
|
||||
if (status != SECSuccess) {
|
||||
goto abort;
|
||||
}
|
||||
MOZ_ASSERT(hmac_len == 20);
|
||||
rv = NS_OK;
|
||||
|
||||
abort:
|
||||
if (hmac_ctx) {
|
||||
PK11_DestroyContext(hmac_ctx, PR_TRUE);
|
||||
}
|
||||
if (skey) {
|
||||
PK11_FreeSymKey(skey);
|
||||
}
|
||||
if (slot) {
|
||||
PK11_FreeSlot(slot);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult AnonymizeId(nsAString& aId, const nsACString& origin) {
|
||||
// deviceId would be a supercookie if we returned it. Anonymize it:
|
||||
// 1. Get (or create) a persistent uuid for this origin.
|
||||
// 2. Return hmac_sha1(uuid, id) - an anonymized id unique to origin.
|
||||
|
||||
static bool loaded = false;
|
||||
if (!loaded) {
|
||||
// load OriginUuids from disk.
|
||||
}
|
||||
OriginUuid* originUuid;
|
||||
if (!mManager->mOriginUuids.Get(origin, &originUuid)) {
|
||||
char uuid[NSID_LENGTH];
|
||||
{
|
||||
nsresult rv;
|
||||
nsID id;
|
||||
{
|
||||
nsCOMPtr<nsIUUIDGenerator> uuidgen =
|
||||
do_GetService("@mozilla.org/uuid-generator;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = uuidgen->GenerateUUIDInPlace(&id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
id.ToProvidedString(uuid);
|
||||
}
|
||||
originUuid = new OriginUuid(uuid, false);
|
||||
mManager->mOriginUuids.Put(origin, originUuid);
|
||||
}
|
||||
|
||||
unsigned char mac[20];
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 id(aId);
|
||||
hmac_sha1(originUuid->mUuid.get(), originUuid->mUuid.Length(),
|
||||
id.get(), id.Length(), mac);
|
||||
}
|
||||
char hex[sizeof(mac) * 2 + 1];
|
||||
auto& m = mac;
|
||||
PR_snprintf(hex, sizeof(hex), // Use first 16 bytes of hmac as id
|
||||
"%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x"
|
||||
"%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
|
||||
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7],
|
||||
m[8], m[9], m[10],m[11], m[12], m[13], m[14], m[15]);
|
||||
aId = NS_ConvertUTF8toUTF16(hex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
public:
|
||||
GetUserMediaDevicesTask(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aOnSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
|
||||
uint64_t aWindowId, nsACString& aAudioLoopbackDev,
|
||||
nsACString& aVideoLoopbackDev, bool aUseFakeDevices)
|
||||
nsACString& aVideoLoopbackDev, bool aPrivileged, const nsACString& aOrigin,
|
||||
bool aUseFakeDevices)
|
||||
: mConstraints(aConstraints)
|
||||
, mOnSuccess(aOnSuccess)
|
||||
, mOnFailure(aOnFailure)
|
||||
|
@ -1331,6 +1489,8 @@ public:
|
|||
, mWindowId(aWindowId)
|
||||
, mLoopbackAudioDevice(aAudioLoopbackDev)
|
||||
, mLoopbackVideoDevice(aVideoLoopbackDev)
|
||||
, mPrivileged(aPrivileged)
|
||||
, mOrigin(aOrigin)
|
||||
, mUseFakeDevices(aUseFakeDevices) {}
|
||||
|
||||
void // NS_IMETHOD
|
||||
|
@ -1346,27 +1506,53 @@ public:
|
|||
|
||||
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
|
||||
|
||||
ScopedDeletePtr<SourceSet> final(new SourceSet);
|
||||
ScopedDeletePtr<SourceSet> result(new SourceSet);
|
||||
if (IsOn(mConstraints.mVideo)) {
|
||||
nsTArray<nsRefPtr<VideoDevice>> s;
|
||||
nsTArray<nsRefPtr<VideoDevice>> sources;
|
||||
GetSources(backend, GetInvariant(mConstraints.mVideo),
|
||||
&MediaEngine::EnumerateVideoDevices, s, mLoopbackVideoDevice.get());
|
||||
for (uint32_t i = 0; i < s.Length(); i++) {
|
||||
final->AppendElement(s[i]);
|
||||
&MediaEngine::EnumerateVideoDevices, sources,
|
||||
mLoopbackVideoDevice.get());
|
||||
for (auto& source : sources) {
|
||||
result->AppendElement(source);
|
||||
}
|
||||
}
|
||||
if (IsOn(mConstraints.mAudio)) {
|
||||
nsTArray<nsRefPtr<AudioDevice>> s;
|
||||
nsTArray<nsRefPtr<AudioDevice>> sources;
|
||||
GetSources(backend, GetInvariant(mConstraints.mAudio),
|
||||
&MediaEngine::EnumerateAudioDevices, s, mLoopbackAudioDevice.get());
|
||||
for (uint32_t i = 0; i < s.Length(); i++) {
|
||||
final->AppendElement(s[i]);
|
||||
&MediaEngine::EnumerateAudioDevices, sources,
|
||||
mLoopbackAudioDevice.get());
|
||||
for (auto& source : sources) {
|
||||
result->AppendElement(source);
|
||||
}
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
|
||||
mOnSuccess, mOnFailure,
|
||||
final.forget()));
|
||||
nsresult rv = NS_OK;
|
||||
if (!mPrivileged) {
|
||||
for (auto& source : *result) {
|
||||
nsString id;
|
||||
source->GetId(id);
|
||||
rv = AnonymizeId(id, mOrigin);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
source->SetId(id);
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
|
||||
mOnSuccess,
|
||||
mOnFailure,
|
||||
result.forget()));
|
||||
} else {
|
||||
nsRefPtr<MediaMgrError> error = new
|
||||
MediaMgrError(NS_LITERAL_STRING("InternalError"),
|
||||
NS_LITERAL_STRING("Unexpected error"));
|
||||
NS_DispatchToMainThread(
|
||||
new ErrorCallbackRunnable<nsIGetUserMediaDevicesSuccessCallback>(mOnSuccess,
|
||||
mOnFailure,
|
||||
*error,
|
||||
mWindowId));
|
||||
}
|
||||
// DeviceSuccessCallbackRunnable should have taken these.
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
|
@ -1383,6 +1569,8 @@ private:
|
|||
// automated media tests only.
|
||||
nsCString mLoopbackAudioDevice;
|
||||
nsCString mLoopbackVideoDevice;
|
||||
bool mPrivileged;
|
||||
nsCString mOrigin;
|
||||
bool mUseFakeDevices;
|
||||
};
|
||||
|
||||
|
@ -1793,7 +1981,8 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
|||
const MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure,
|
||||
uint64_t aInnerWindowID)
|
||||
uint64_t aInnerWindowID,
|
||||
bool aPrivileged)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
|
@ -1811,11 +2000,16 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
|||
bool useFakeStreams =
|
||||
Preferences::GetBool("media.navigator.streams.fake", false);
|
||||
|
||||
nsCString origin;
|
||||
nsPrincipal::GetOriginForURI(aWindow->GetDocumentURI(),
|
||||
getter_Copies(origin));
|
||||
|
||||
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
|
||||
new GetUserMediaDevicesTask(
|
||||
aConstraints, onSuccess.forget(), onFailure.forget(),
|
||||
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
|
||||
loopbackAudioDevice, loopbackVideoDevice, useFakeStreams));
|
||||
loopbackAudioDevice, loopbackVideoDevice, aPrivileged, origin,
|
||||
useFakeStreams));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1832,7 +2026,7 @@ MediaManager::EnumerateDevices(nsPIDOMWindow* aWindow,
|
|||
c.mAudio.SetAsBoolean() = true;
|
||||
|
||||
AddWindowID(aWindow->WindowID());
|
||||
return GetUserMediaDevices(aWindow, c, aOnSuccess, aOnFailure, 0);
|
||||
return GetUserMediaDevices(aWindow, c, aOnSuccess, aOnFailure, 0, false);
|
||||
}
|
||||
|
||||
MediaEngine*
|
||||
|
|
|
@ -300,29 +300,6 @@ typedef enum {
|
|||
class MediaManager;
|
||||
class GetUserMediaTask;
|
||||
|
||||
/**
|
||||
* Send an error back to content.
|
||||
* Do this only on the main thread. The onSuccess callback is also passed here
|
||||
* so it can be released correctly.
|
||||
*/
|
||||
class ErrorCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError, uint64_t aWindowID);
|
||||
NS_IMETHOD Run();
|
||||
private:
|
||||
~ErrorCallbackRunnable();
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaMgrError> mError;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
|
||||
class ReleaseMediaOperationResource : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -369,20 +346,7 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
ReturnCallbackError(nsresult rv, const char* errorLog)
|
||||
{
|
||||
MM_LOG(("%s , rv=%d", errorLog, rv));
|
||||
NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(),
|
||||
mOnTracksAvailableCallback.forget()));
|
||||
nsString log;
|
||||
|
||||
log.AssignASCII(errorLog);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(
|
||||
NS_LITERAL_STRING("InternalError"), log);
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(onSuccess, mOnFailure,
|
||||
*error, mWindowID));
|
||||
}
|
||||
ReturnCallbackError(nsresult rv, const char* errorLog);
|
||||
|
||||
void
|
||||
Run()
|
||||
|
@ -494,6 +458,17 @@ private:
|
|||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
};
|
||||
|
||||
class OriginUuid
|
||||
{
|
||||
public:
|
||||
OriginUuid(char *aUuid, bool aPrivateBrowsing)
|
||||
: mPrivateBrowsing(aPrivateBrowsing) {
|
||||
mUuid.Append(aUuid);
|
||||
}
|
||||
nsCString mUuid;
|
||||
bool mPrivateBrowsing;
|
||||
};
|
||||
|
||||
typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
|
||||
typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
|
||||
|
||||
|
@ -503,6 +478,7 @@ public:
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMEDIADEVICE
|
||||
|
||||
void SetId(const nsAString& aID);
|
||||
protected:
|
||||
virtual ~MediaDevice() {}
|
||||
explicit MediaDevice(MediaEngineSource* aSource);
|
||||
|
@ -544,9 +520,13 @@ typedef void (*WindowListenerCallback)(MediaManager *aThis,
|
|||
StreamListeners *aListeners,
|
||||
void *aData);
|
||||
|
||||
class GetUserMediaDevicesTask;
|
||||
|
||||
class MediaManager final : public nsIMediaManagerService,
|
||||
public nsIObserver
|
||||
{
|
||||
friend GetUserMediaDevicesTask;
|
||||
|
||||
public:
|
||||
static already_AddRefed<MediaManager> GetInstance();
|
||||
|
||||
|
@ -595,7 +575,8 @@ public:
|
|||
const dom::MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError,
|
||||
uint64_t aInnerWindowID = 0);
|
||||
uint64_t aInnerWindowID = 0,
|
||||
bool aPrivileged = true);
|
||||
|
||||
nsresult EnumerateDevices(nsPIDOMWindow* aWindow,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
|
@ -632,10 +613,14 @@ private:
|
|||
|
||||
void StopMediaStreams();
|
||||
|
||||
// ONLY access from MediaManagerThread so we don't need to lock
|
||||
nsClassHashtable<nsCStringHashKey, OriginUuid> mOriginUuids;
|
||||
|
||||
// ONLY access from MainThread so we don't need to lock
|
||||
WindowTable mActiveWindows;
|
||||
nsClassHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks;
|
||||
nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
|
||||
|
||||
// Always exists
|
||||
nsAutoPtr<base::Thread> mMediaThread;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче