mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1173255 - Cleanup MediaManager e10s code in prep for deviceId constraint. r=jesup
--HG-- extra : amend_source : 057f17d55cd44a700abab5595c9f4fc95cfd2419 extra : transplant_source : %B7%5C%7D%FA%E9%3F%29%F9%EBM%9E%B5%1A%A6G%29%25%01%0E- extra : histedit_source : a10d0d5106f5fffb3881604728c1933c90772622%2Cdf022706033cb19f87a8dd58376ab7800d9d2526
This commit is contained in:
parent
d9a401584e
commit
d4bc9fa237
@ -52,6 +52,7 @@
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
#include "mozilla/widget/WidgetMessageUtils.h"
|
||||
#include "mozilla/media/MediaChild.h"
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
@ -204,6 +205,7 @@ using namespace mozilla::dom::mobileconnection;
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::media;
|
||||
using namespace mozilla::embedding;
|
||||
using namespace mozilla::gmp;
|
||||
using namespace mozilla::hal_sandbox;
|
||||
@ -1750,6 +1752,18 @@ ContentChild::DeallocPVoicemailChild(PVoicemailChild* aActor)
|
||||
return true;
|
||||
}
|
||||
|
||||
media::PMediaChild*
|
||||
ContentChild::AllocPMediaChild()
|
||||
{
|
||||
return media::AllocPMediaChild();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPMediaChild(media::PMediaChild *aActor)
|
||||
{
|
||||
return media::DeallocPMediaChild(aActor);
|
||||
}
|
||||
|
||||
PStorageChild*
|
||||
ContentChild::AllocPStorageChild()
|
||||
{
|
||||
|
@ -262,6 +262,9 @@ public:
|
||||
PVoicemailChild* SendPVoicemailConstructor(PVoicemailChild* aActor);
|
||||
virtual bool DeallocPVoicemailChild(PVoicemailChild*) override;
|
||||
|
||||
virtual PMediaChild* AllocPMediaChild() override;
|
||||
virtual bool DeallocPMediaChild(PMediaChild* aActor) override;
|
||||
|
||||
virtual PStorageChild* AllocPStorageChild() override;
|
||||
virtual bool DeallocPStorageChild(PStorageChild* aActor) override;
|
||||
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "mozilla/layers/ImageBridgeParent.h"
|
||||
#include "mozilla/layers/SharedBufferManagerParent.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -258,6 +259,7 @@ using namespace mozilla::dom::mobileconnection;
|
||||
using namespace mozilla::dom::mobilemessage;
|
||||
using namespace mozilla::dom::telephony;
|
||||
using namespace mozilla::dom::voicemail;
|
||||
using namespace mozilla::media;
|
||||
using namespace mozilla::embedding;
|
||||
using namespace mozilla::gmp;
|
||||
using namespace mozilla::hal;
|
||||
@ -3807,6 +3809,18 @@ ContentParent::DeallocPVoicemailParent(PVoicemailParent* aActor)
|
||||
return true;
|
||||
}
|
||||
|
||||
media::PMediaParent*
|
||||
ContentParent::AllocPMediaParent()
|
||||
{
|
||||
return media::AllocPMediaParent();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPMediaParent(media::PMediaParent *aActor)
|
||||
{
|
||||
return media::DeallocPMediaParent(aActor);
|
||||
}
|
||||
|
||||
PStorageParent*
|
||||
ContentParent::AllocPStorageParent()
|
||||
{
|
||||
|
@ -646,6 +646,9 @@ private:
|
||||
virtual bool RecvPVoicemailConstructor(PVoicemailParent* aActor) override;
|
||||
virtual bool DeallocPVoicemailParent(PVoicemailParent* aActor) override;
|
||||
|
||||
virtual PMediaParent* AllocPMediaParent() override;
|
||||
virtual bool DeallocPMediaParent(PMediaParent* aActor) override;
|
||||
|
||||
virtual bool DeallocPStorageParent(PStorageParent* aActor) override;
|
||||
|
||||
virtual PBluetoothParent* AllocPBluetoothParent() override;
|
||||
|
@ -25,6 +25,7 @@ include protocol PHal;
|
||||
include protocol PIcc;
|
||||
include protocol PProcessHangMonitor;
|
||||
include protocol PImageBridge;
|
||||
include protocol PMedia;
|
||||
include protocol PMemoryReportRequest;
|
||||
include protocol PMobileConnection;
|
||||
include protocol PNecko;
|
||||
@ -429,6 +430,7 @@ prio(normal upto urgent) sync protocol PContent
|
||||
manages PFMRadio;
|
||||
manages PHal;
|
||||
manages PIcc;
|
||||
manages PMedia;
|
||||
manages PMemoryReportRequest;
|
||||
manages PMobileConnection;
|
||||
manages PNecko;
|
||||
@ -764,6 +766,8 @@ parent:
|
||||
|
||||
PVoicemail();
|
||||
|
||||
PMedia();
|
||||
|
||||
PBluetooth();
|
||||
|
||||
PFMRadio();
|
||||
|
@ -123,6 +123,9 @@ using dom::Sequence;
|
||||
using dom::OwningBooleanOrMediaTrackConstraints;
|
||||
using dom::SupportedAudioConstraints;
|
||||
using dom::SupportedVideoConstraints;
|
||||
using media::Pledge;
|
||||
using media::NewRunnableFrom;
|
||||
using media::NewTaskFrom;
|
||||
|
||||
static Atomic<bool> sInShutdown;
|
||||
|
||||
@ -267,150 +270,6 @@ private:
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
|
||||
/**
|
||||
* Invoke the GetUserMediaDevices success callback. Wrapped in a runnable
|
||||
* so that it may be called on the main thread. The error callback is also
|
||||
* passed so it can be released correctly.
|
||||
*/
|
||||
class DeviceSuccessCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DeviceSuccessCallbackRunnable(
|
||||
uint64_t aWindowID,
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
nsTArray<nsRefPtr<MediaDevice>>* aDevices,
|
||||
bool aIsGum)
|
||||
: mDevices(aDevices)
|
||||
, mWindowID(aWindowID)
|
||||
, mIsGum(aIsGum)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
~DeviceSuccessCallbackRunnable()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
// This can happen if the main thread processes the runnable before
|
||||
// GetUserMediaDevicesTask::Run returns.
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
|
||||
NS_ProxyRelease(mainThread, mOnSuccess);
|
||||
NS_ProxyRelease(mainThread, mOnFailure);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
AnonymizeId(nsAString& aId, const nsACString& aOriginKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIKeyObjectFactory> factory =
|
||||
do_GetService("@mozilla.org/security/keyobjectfactory;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCString rawKey;
|
||||
rv = Base64Decode(aOriginKey, rawKey);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIKeyObject> key;
|
||||
rv = factory->KeyFromString(nsIKeyObject::HMAC, rawKey, getter_AddRefs(key));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICryptoHMAC> hasher =
|
||||
do_CreateInstance(NS_CRYPTO_HMAC_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = hasher->Init(nsICryptoHMAC::SHA256, key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 id(aId);
|
||||
rv = hasher->Update(reinterpret_cast<const uint8_t*> (id.get()), id.Length());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCString mac;
|
||||
rv = hasher->Finish(true, mac);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aId = NS_ConvertUTF8toUTF16(mac);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
// Only run if window is still on our active list.
|
||||
if (!mManager->IsWindowStillActive(mWindowID)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> devices =
|
||||
do_CreateInstance("@mozilla.org/variant;1");
|
||||
|
||||
size_t len = mDevices->Length();
|
||||
|
||||
if (!len) {
|
||||
if (mIsGum) { // gUM fails on 0 devices whereas enumerateDevices doesn't.
|
||||
// XXX
|
||||
// We should in the future return an empty array, and dynamically add
|
||||
// devices to the dropdowns if things are hotplugged while the
|
||||
// requester is up.
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("NotFoundError"));
|
||||
mOnFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
devices->SetAsEmptyArray(); // SetAsArray() fails on zero length arrays.
|
||||
} else {
|
||||
nsTArray<nsIMediaDevice*> tmp(len);
|
||||
for (auto& device : *mDevices) {
|
||||
if (!mOriginKey.IsEmpty()) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
AnonymizeId(id, mOriginKey);
|
||||
device->SetId(id);
|
||||
}
|
||||
tmp.AppendElement(device);
|
||||
}
|
||||
nsresult rv = devices->SetAsArray(nsIDataType::VTYPE_INTERFACE,
|
||||
&NS_GET_IID(nsIMediaDevice),
|
||||
mDevices->Length(),
|
||||
const_cast<void*>(
|
||||
static_cast<const void*>(tmp.Elements())
|
||||
));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
mOnSuccess->OnSuccess(devices);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCString mOriginKey;
|
||||
private:
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
|
||||
uint64_t mWindowID;
|
||||
bool mIsGum;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
};
|
||||
|
||||
// Handle removing GetUserMediaCallbackMediaStreamListener from main thread
|
||||
class GetUserMediaListenerRemove: public nsRunnable
|
||||
{
|
||||
@ -440,44 +299,15 @@ protected:
|
||||
NS_IMPL_ISUPPORTS(MediaDevice, nsIMediaDevice)
|
||||
|
||||
MediaDevice::MediaDevice(MediaEngineSource* aSource)
|
||||
: mHasFacingMode(false)
|
||||
, mSource(aSource) {
|
||||
: mSource(aSource) {
|
||||
mSource->GetName(mName);
|
||||
mSource->GetUUID(mID);
|
||||
nsCString id;
|
||||
mSource->GetUUID(id);
|
||||
CopyUTF8toUTF16(id, mID);
|
||||
}
|
||||
|
||||
VideoDevice::VideoDevice(MediaEngineVideoSource* aSource)
|
||||
: MediaDevice(aSource) {
|
||||
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
|
||||
if (mName.EqualsLiteral("back")) {
|
||||
mHasFacingMode = true;
|
||||
mFacingMode = dom::VideoFacingModeEnum::Environment;
|
||||
} else if (mName.EqualsLiteral("front")) {
|
||||
mHasFacingMode = true;
|
||||
mFacingMode = dom::VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif // MOZ_B2G_CAMERA
|
||||
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||
// Names are generated. Example: "Camera 0, Facing back, Orientation 90"
|
||||
//
|
||||
// See media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/
|
||||
// webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
|
||||
|
||||
if (mName.Find(NS_LITERAL_STRING("Facing back")) != kNotFound) {
|
||||
mHasFacingMode = true;
|
||||
mFacingMode = dom::VideoFacingModeEnum::Environment;
|
||||
} else if (mName.Find(NS_LITERAL_STRING("Facing front")) != kNotFound) {
|
||||
mHasFacingMode = true;
|
||||
mFacingMode = dom::VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif // ANDROID
|
||||
#ifdef XP_MACOSX
|
||||
// Kludge to test user-facing cameras on OSX.
|
||||
if (mName.Find(NS_LITERAL_STRING("Face")) != -1) {
|
||||
mHasFacingMode = true;
|
||||
mFacingMode = dom::VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif
|
||||
mMediaSource = aSource->GetMediaSource();
|
||||
}
|
||||
|
||||
@ -492,63 +322,16 @@ uint32_t
|
||||
VideoDevice::GetBestFitnessDistance(
|
||||
const nsTArray<const MediaTrackConstraintSet*>& aConstraintSets)
|
||||
{
|
||||
// TODO: Minimal kludge to fix plain and ideal facingMode regression, for
|
||||
// smooth landing and uplift. Proper cleanup is forthcoming (1037389).
|
||||
uint64_t distance = 0;
|
||||
|
||||
// Interrogate device-inherent properties first.
|
||||
for (size_t i = 0; i < aConstraintSets.Length(); i++) {
|
||||
auto& c = *aConstraintSets[i];
|
||||
if (!c.mFacingMode.IsConstrainDOMStringParameters() ||
|
||||
c.mFacingMode.GetAsConstrainDOMStringParameters().mIdeal.WasPassed() ||
|
||||
c.mFacingMode.GetAsConstrainDOMStringParameters().mExact.WasPassed()) {
|
||||
nsString deviceFacingMode;
|
||||
GetFacingMode(deviceFacingMode);
|
||||
if (c.mFacingMode.IsString()) {
|
||||
if (c.mFacingMode.GetAsString() != deviceFacingMode) {
|
||||
if (i == 0) {
|
||||
distance = 1000;
|
||||
}
|
||||
}
|
||||
} else if (c.mFacingMode.IsStringSequence()) {
|
||||
if (!c.mFacingMode.GetAsStringSequence().Contains(deviceFacingMode)) {
|
||||
if (i == 0) {
|
||||
distance = 1000;
|
||||
}
|
||||
}
|
||||
} else if (c.mFacingMode.GetAsConstrainDOMStringParameters().mExact.WasPassed()) {
|
||||
auto& exact = c.mFacingMode.GetAsConstrainDOMStringParameters().mExact.Value();
|
||||
if (exact.IsString()) {
|
||||
if (exact.GetAsString() != deviceFacingMode) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
} else if (!exact.GetAsStringSequence().Contains(deviceFacingMode)) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
} else if (c.mFacingMode.GetAsConstrainDOMStringParameters().mIdeal.WasPassed()) {
|
||||
auto& ideal = c.mFacingMode.GetAsConstrainDOMStringParameters().mIdeal.Value();
|
||||
if (ideal.IsString()) {
|
||||
if (ideal.GetAsString() != deviceFacingMode) {
|
||||
if (i == 0) {
|
||||
distance = 1000;
|
||||
}
|
||||
}
|
||||
} else if (!ideal.GetAsStringSequence().Contains(deviceFacingMode)) {
|
||||
if (i == 0) {
|
||||
distance = 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& constraint : aConstraintSets) {
|
||||
nsString s;
|
||||
GetMediaSource(s);
|
||||
if (s != c.mMediaSource) {
|
||||
if (s != constraint->mMediaSource) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
}
|
||||
// Forward request to underlying object to interrogate per-mode capabilities.
|
||||
distance += uint64_t(GetSource()->GetBestFitnessDistance(aConstraintSets));
|
||||
return uint32_t(std::min(distance, uint64_t(UINT32_MAX)));
|
||||
return GetSource()->GetBestFitnessDistance(aConstraintSets);
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(MediaEngineAudioSource* aSource)
|
||||
@ -602,18 +385,6 @@ MediaDevice::SetId(const nsAString& aID)
|
||||
mID.Assign(aID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaDevice::GetFacingMode(nsAString& aFacingMode)
|
||||
{
|
||||
if (mHasFacingMode) {
|
||||
aFacingMode.Assign(NS_ConvertUTF8toUTF16(
|
||||
dom::VideoFacingModeEnumValues::strings[uint32_t(mFacingMode)].value));
|
||||
} else {
|
||||
aFacingMode.Truncate(0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaDevice::GetMediaSource(nsAString& aMediaSource)
|
||||
{
|
||||
@ -1439,125 +1210,76 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
class SanitizeDeviceIdsTask : public Task
|
||||
{
|
||||
public:
|
||||
explicit SanitizeDeviceIdsTask(int64_t aSinceWhen)
|
||||
: mSinceWhen(aSinceWhen) {}
|
||||
// TODO: Remove once upgraded to GCC 4.8+ on linux. Bogus error on static func:
|
||||
// error: 'this' was not captured for this lambda function
|
||||
|
||||
void // NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
nsRefPtr<media::ChildPledge<bool>> p =
|
||||
mozilla::media::SanitizeOriginKeys(mSinceWhen); // we fire and forget
|
||||
}
|
||||
private:
|
||||
int64_t mSinceWhen;
|
||||
};
|
||||
static auto& MediaManager_GetInstance = MediaManager::GetInstance;
|
||||
static auto& MediaManager_ToJSArray = MediaManager::ToJSArray;
|
||||
static auto& MediaManager_AnonymizeDevices = MediaManager::AnonymizeDevices;
|
||||
|
||||
/**
|
||||
* Similar to GetUserMediaTask, but used for the chrome-only
|
||||
* GetUserMediaDevices function. Enumerates a list of audio & video devices,
|
||||
* wraps them up in nsIMediaDevice objects and returns it to the success
|
||||
* callback.
|
||||
*
|
||||
* All code in this class runs on the MediaManager thread.
|
||||
* EnumerateRawDevices - Enumerate a list of audio & video devices that
|
||||
* satisfy passed-in constraints. List contains raw id's.
|
||||
*/
|
||||
class GetUserMediaDevicesTask : public Task
|
||||
|
||||
already_AddRefed<MediaManager::PledgeSourceSet>
|
||||
MediaManager::EnumerateRawDevices(uint64_t aWindowId,
|
||||
const MediaStreamConstraints& aConstraints)
|
||||
{
|
||||
public:
|
||||
GetUserMediaDevicesTask(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aOnSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
|
||||
uint64_t aWindowId, nsACString& aAudioLoopbackDev,
|
||||
nsACString& aVideoLoopbackDev, bool aPrivileged, const nsACString& aOrigin,
|
||||
bool aInPrivateBrowsing, bool aUseFakeDevices)
|
||||
: mConstraints(aConstraints)
|
||||
, mOnSuccess(aOnSuccess)
|
||||
, mOnFailure(aOnFailure)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
, mWindowId(aWindowId)
|
||||
, mLoopbackAudioDevice(aAudioLoopbackDev)
|
||||
, mLoopbackVideoDevice(aVideoLoopbackDev)
|
||||
, mPrivileged(aPrivileged)
|
||||
, mOrigin(aOrigin)
|
||||
, mInPrivateBrowsing(aInPrivateBrowsing)
|
||||
, mUseFakeDevices(aUseFakeDevices) {}
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsRefPtr<PledgeSourceSet> p = new PledgeSourceSet();
|
||||
uint32_t id = mOutstandingPledges.Append(*p);
|
||||
|
||||
void // NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
// Check if the preference for using audio/video loopback devices is
|
||||
// enabled. This is currently used for automated media tests only.
|
||||
auto audioLoopDev = Preferences::GetCString("media.audio_loopback_dev");
|
||||
auto videoLoopDev = Preferences::GetCString("media.video_loopback_dev");
|
||||
bool fake = Preferences::GetBool("media.navigator.streams.fake", false);
|
||||
|
||||
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aConstraints, aWindowId,
|
||||
audioLoopDev, videoLoopDev,
|
||||
fake]() mutable {
|
||||
nsRefPtr<MediaEngine> backend;
|
||||
if (mConstraints.mFake || mUseFakeDevices)
|
||||
backend = new MediaEngineDefault(mConstraints.mFakeTracks);
|
||||
else
|
||||
backend = mManager->GetBackend(mWindowId);
|
||||
|
||||
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
|
||||
if (aConstraints.mFake || fake) {
|
||||
backend = new MediaEngineDefault(aConstraints.mFakeTracks);
|
||||
} else {
|
||||
nsRefPtr<MediaManager> manager = MediaManager_GetInstance();
|
||||
backend = manager->GetBackend(aWindowId);
|
||||
}
|
||||
|
||||
ScopedDeletePtr<SourceSet> result(new SourceSet);
|
||||
if (IsOn(mConstraints.mVideo)) {
|
||||
if (IsOn(aConstraints.mVideo)) {
|
||||
nsTArray<nsRefPtr<VideoDevice>> sources;
|
||||
GetSources(backend, GetInvariant(mConstraints.mVideo),
|
||||
&MediaEngine::EnumerateVideoDevices, sources,
|
||||
mLoopbackVideoDevice.get());
|
||||
GetSources(backend, GetInvariant(aConstraints.mVideo),
|
||||
&MediaEngine::EnumerateVideoDevices, sources, videoLoopDev);
|
||||
for (auto& source : sources) {
|
||||
result->AppendElement(source);
|
||||
}
|
||||
}
|
||||
if (IsOn(mConstraints.mAudio)) {
|
||||
if (IsOn(aConstraints.mAudio)) {
|
||||
nsTArray<nsRefPtr<AudioDevice>> sources;
|
||||
GetSources(backend, GetInvariant(mConstraints.mAudio),
|
||||
&MediaEngine::EnumerateAudioDevices, sources,
|
||||
mLoopbackAudioDevice.get());
|
||||
GetSources(backend, GetInvariant(aConstraints.mAudio),
|
||||
&MediaEngine::EnumerateAudioDevices, sources, audioLoopDev);
|
||||
for (auto& source : sources) {
|
||||
result->AppendElement(source);
|
||||
}
|
||||
}
|
||||
nsRefPtr<DeviceSuccessCallbackRunnable> runnable =
|
||||
new DeviceSuccessCallbackRunnable(mWindowId, mOnSuccess, mOnFailure,
|
||||
result.forget(), mPrivileged);
|
||||
if (mPrivileged) {
|
||||
NS_DispatchToMainThread(runnable);
|
||||
} else {
|
||||
// Get persistent origin-unique uuid to anonymize deviceIds back on main.
|
||||
//
|
||||
// GetOriginKey is an async API that returns a pledge (as promise-like
|
||||
// pattern). We use .Then() to pass in a lambda to run back on this
|
||||
// thread once GetOriginKey resolves asynchronously . The "runnable"
|
||||
// pointer is "captured" (passed by value) into the lambda.
|
||||
nsRefPtr<media::ChildPledge<nsCString>> p =
|
||||
media::GetOriginKey(mOrigin, mInPrivateBrowsing);
|
||||
p->Then([runnable](nsCString result) mutable {
|
||||
runnable->mOriginKey = result;
|
||||
NS_DispatchToMainThread(runnable);
|
||||
});
|
||||
}
|
||||
// One of the Runnables have taken these.
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
|
||||
private:
|
||||
MediaStreamConstraints mConstraints;
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
uint64_t mWindowId;
|
||||
const nsString mCallId;
|
||||
// Audio & Video loopback devices to be used based on
|
||||
// the preference settings. This is currently used for
|
||||
// automated media tests only.
|
||||
nsCString mLoopbackAudioDevice;
|
||||
nsCString mLoopbackVideoDevice;
|
||||
bool mPrivileged;
|
||||
nsCString mOrigin;
|
||||
bool mInPrivateBrowsing;
|
||||
bool mUseFakeDevices;
|
||||
};
|
||||
SourceSet* handoff = result.forget();
|
||||
NS_DispatchToMainThread(NewRunnableFrom([id, handoff]() mutable {
|
||||
ScopedDeletePtr<SourceSet> result(handoff);
|
||||
nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
|
||||
if (!mgr) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
|
||||
if (p) {
|
||||
p->Resolve(result.forget());
|
||||
}
|
||||
return NS_OK;
|
||||
}));
|
||||
}));
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
MediaManager::MediaManager()
|
||||
: mMediaThread(nullptr)
|
||||
@ -1567,7 +1289,6 @@ MediaManager::MediaManager()
|
||||
mPrefs.mHeight = 0; // adaptive default
|
||||
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -1654,6 +1375,15 @@ MediaManager::GetInstance()
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
media::Parent<media::NonE10s>*
|
||||
MediaManager::GetNonE10sParent()
|
||||
{
|
||||
if (!mNonE10sParent) {
|
||||
mNonE10sParent = new media::Parent<media::NonE10s>(true);
|
||||
}
|
||||
return mNonE10sParent;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
MediaManager::PostTask(const tracked_objects::Location& from_here, Task* task)
|
||||
@ -1736,22 +1466,20 @@ MediaManager::NotifyRecordingStatusChange(nsPIDOMWindow* aWindow,
|
||||
* for handling all incoming getUserMedia calls from every window.
|
||||
*/
|
||||
nsresult
|
||||
MediaManager::GetUserMedia(
|
||||
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints,
|
||||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure)
|
||||
MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnFailure, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
|
||||
|
||||
bool privileged = nsContentUtils::IsCallerChrome();
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aOnFailure);
|
||||
MOZ_ASSERT(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
|
||||
bool privileged = nsContentUtils::IsCallerChrome();
|
||||
|
||||
MediaStreamConstraints c(aConstraints); // copy
|
||||
|
||||
static bool created = false;
|
||||
@ -1981,47 +1709,144 @@ MediaManager::GetUserMedia(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure,
|
||||
uint64_t aInnerWindowID,
|
||||
bool aPrivileged)
|
||||
/* static */ void
|
||||
MediaManager::AnonymizeDevices(SourceSet& aDevices, const nsACString& aOriginKey)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
if (!aOriginKey.IsEmpty()) {
|
||||
for (auto& device : aDevices) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
AnonymizeId(id, aOriginKey);
|
||||
device->SetId(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(aOnFailure, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(!sInShutdown, NS_ERROR_FAILURE);
|
||||
/* static */ nsresult
|
||||
MediaManager::AnonymizeId(nsAString& aId, const nsACString& aOriginKey)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIKeyObjectFactory> factory =
|
||||
do_GetService("@mozilla.org/security/keyobjectfactory;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCString rawKey;
|
||||
rv = Base64Decode(aOriginKey, rawKey);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIKeyObject> key;
|
||||
rv = factory->KeyFromString(nsIKeyObject::HMAC, rawKey, getter_AddRefs(key));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Check if the preference for using loopback devices is enabled.
|
||||
nsAdoptingCString loopbackAudioDevice =
|
||||
Preferences::GetCString("media.audio_loopback_dev");
|
||||
nsAdoptingCString loopbackVideoDevice =
|
||||
Preferences::GetCString("media.video_loopback_dev");
|
||||
bool useFakeStreams =
|
||||
Preferences::GetBool("media.navigator.streams.fake", false);
|
||||
nsCOMPtr<nsICryptoHMAC> hasher =
|
||||
do_CreateInstance(NS_CRYPTO_HMAC_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = hasher->Init(nsICryptoHMAC::SHA256, key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 id(aId);
|
||||
rv = hasher->Update(reinterpret_cast<const uint8_t*> (id.get()), id.Length());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsCString mac;
|
||||
rv = hasher->Finish(true, mac);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aId = NS_ConvertUTF8toUTF16(mac);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<nsIWritableVariant>
|
||||
MediaManager::ToJSArray(SourceSet& aDevices)
|
||||
{
|
||||
nsCOMPtr<nsIWritableVariant> var = do_CreateInstance("@mozilla.org/variant;1");
|
||||
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();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaManager::PledgeSourceSet>
|
||||
MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
|
||||
const MediaStreamConstraints& aConstraints)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// This function returns a pledge, a promise-like object with the future result
|
||||
nsRefPtr<PledgeSourceSet> pledge = new PledgeSourceSet();
|
||||
uint32_t id = mOutstandingPledges.Append(*pledge);
|
||||
|
||||
// To get a device list anonymized for a particular origin, we must:
|
||||
// 1. Get an origin-key (for either regular or private browsing)
|
||||
// 2. Get the raw devices list
|
||||
// 3. Anonymize the raw list with the origin-key.
|
||||
|
||||
nsCString origin;
|
||||
nsPrincipal::GetOriginForURI(aWindow->GetDocumentURI(), origin);
|
||||
bool inPrivateBrowsing;
|
||||
bool privateBrowsing;
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetDoc();
|
||||
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
||||
inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
|
||||
}
|
||||
MediaManager::PostTask(FROM_HERE,
|
||||
new GetUserMediaDevicesTask(
|
||||
aConstraints, onSuccess.forget(), onFailure.forget(),
|
||||
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
|
||||
loopbackAudioDevice, loopbackVideoDevice, aPrivileged, origin,
|
||||
inPrivateBrowsing, useFakeStreams));
|
||||
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
|
||||
(nsGlobalWindow::GetInnerWindowWithId(aWindowId));
|
||||
nsPrincipal::GetOriginForURI(window->GetDocumentURI(), origin);
|
||||
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIDocument> doc = window->GetDoc();
|
||||
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
||||
privateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
|
||||
}
|
||||
// GetOriginKey is an async API that returns a pledge (a promise-like
|
||||
// pattern). We use .Then() to pass in a lambda to run back on this same
|
||||
// thread later once GetOriginKey resolves. Needed variables are "captured"
|
||||
// (passed by value) safely into the lambda.
|
||||
|
||||
nsRefPtr<Pledge<nsCString>> p = media::GetOriginKey(origin, privateBrowsing);
|
||||
p->Then([id, aWindowId, aConstraints](const nsCString& aOriginKey) mutable {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
|
||||
|
||||
nsRefPtr<PledgeSourceSet> p = mgr->EnumerateRawDevices(aWindowId, aConstraints);
|
||||
p->Then([id, aWindowId, aOriginKey](SourceSet*& aDevices) mutable {
|
||||
ScopedDeletePtr<SourceSet> devices(aDevices); // secondary result
|
||||
|
||||
// Only run if window is still on our active list.
|
||||
nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
|
||||
if (!mgr) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
|
||||
if (!p || !mgr->IsWindowStillActive(aWindowId)) {
|
||||
return NS_OK;
|
||||
}
|
||||
MediaManager_AnonymizeDevices(*devices, aOriginKey);
|
||||
p->Resolve(devices.forget());
|
||||
return NS_OK;
|
||||
});
|
||||
});
|
||||
return pledge.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2029,14 +1854,68 @@ MediaManager::EnumerateDevices(nsPIDOMWindow* aWindow,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE(!sInShutdown, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
uint64_t windowId = aWindow->WindowID();
|
||||
|
||||
AddWindowID(windowId);
|
||||
|
||||
MediaStreamConstraints c;
|
||||
c.mVideo.SetAsBoolean() = true;
|
||||
c.mAudio.SetAsBoolean() = true;
|
||||
|
||||
AddWindowID(aWindow->WindowID());
|
||||
return GetUserMediaDevices(aWindow, c, aOnSuccess, aOnFailure, 0, false);
|
||||
nsRefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowId, c);
|
||||
p->Then([onSuccess](SourceSet*& aDevices) mutable {
|
||||
ScopedDeletePtr<SourceSet> devices(aDevices); // grab result
|
||||
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
|
||||
onSuccess->OnSuccess(array);
|
||||
}, [onFailure](MediaStreamError& reason) mutable {
|
||||
onFailure->OnError(&reason);
|
||||
});
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetUserMediaDevices - called by the UI-part of getUserMedia from chrome JS.
|
||||
*/
|
||||
|
||||
nsresult
|
||||
MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure,
|
||||
uint64_t aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
if (!aWindowId) {
|
||||
aWindowId = aWindow->WindowID();
|
||||
}
|
||||
|
||||
nsRefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(aWindowId, aConstraints);
|
||||
p->Then([aWindowId, onSuccess, onFailure](SourceSet*& aDevices) mutable {
|
||||
ScopedDeletePtr<SourceSet> devices(aDevices); // grab result
|
||||
|
||||
if (devices->Length()) {
|
||||
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
|
||||
onSuccess->OnSuccess(array);
|
||||
} else {
|
||||
nsRefPtr<nsGlobalWindow> window = nsGlobalWindow::GetInnerWindowWithId(aWindowId);
|
||||
if (!window) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsRefPtr<MediaStreamError> reason =
|
||||
new MediaStreamError(window, NS_LITERAL_STRING("NotFoundError"));
|
||||
onFailure->OnError(reason);
|
||||
}
|
||||
return NS_OK;
|
||||
}, [onFailure](MediaStreamError& reason) mutable {
|
||||
onFailure->OnError(&reason);
|
||||
});
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaEngine*
|
||||
@ -2550,7 +2429,7 @@ MediaManager::SanitizeDeviceIds(int64_t aSinceWhen)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
LOG(("%s: sinceWhen = %llu", __FUNCTION__, aSinceWhen));
|
||||
|
||||
MediaManager::PostTask(FROM_HERE, new SanitizeDeviceIdsTask(aSinceWhen));
|
||||
media::SanitizeOriginKeys(aSinceWhen); // we fire and forget
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "mozilla/media/MediaChild.h"
|
||||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "DOMMediaStream.h"
|
||||
|
||||
@ -468,8 +470,6 @@ protected:
|
||||
explicit MediaDevice(MediaEngineSource* aSource);
|
||||
nsString mName;
|
||||
nsString mID;
|
||||
bool mHasFacingMode;
|
||||
dom::VideoFacingModeEnum mFacingMode;
|
||||
dom::MediaSourceEnum mMediaSource;
|
||||
nsRefPtr<MediaEngineSource> mSource;
|
||||
};
|
||||
@ -534,6 +534,7 @@ public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIMEDIAMANAGERSERVICE
|
||||
|
||||
media::Parent<media::NonE10s>* GetNonE10sParent();
|
||||
MediaEngine* GetBackend(uint64_t aWindowId = 0);
|
||||
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
@ -555,11 +556,10 @@ public:
|
||||
nsIDOMGetUserMediaErrorCallback* onError);
|
||||
|
||||
nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const dom::MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError,
|
||||
uint64_t aInnerWindowID = 0,
|
||||
bool aPrivileged = true);
|
||||
const dom::MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError,
|
||||
uint64_t aInnerWindowID = 0);
|
||||
|
||||
nsresult EnumerateDevices(nsPIDOMWindow* aWindow,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
@ -572,6 +572,21 @@ public:
|
||||
MediaEnginePrefs mPrefs;
|
||||
|
||||
private:
|
||||
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
|
||||
typedef media::Pledge<SourceSet*, dom::MediaStreamError> PledgeSourceSet;
|
||||
|
||||
static nsresult AnonymizeId(nsAString& aId, const nsACString& aOriginKey);
|
||||
public: // TODO: make private once we upgrade to GCC 4.8+ on linux.
|
||||
static void AnonymizeDevices(SourceSet& aDevices, const nsACString& aOriginKey);
|
||||
static already_AddRefed<nsIWritableVariant> ToJSArray(SourceSet& aDevices);
|
||||
private:
|
||||
already_AddRefed<PledgeSourceSet>
|
||||
EnumerateRawDevices(uint64_t aWindowId,
|
||||
const dom::MediaStreamConstraints& aConstraints);
|
||||
already_AddRefed<PledgeSourceSet>
|
||||
EnumerateDevicesImpl(uint64_t aWindowId,
|
||||
const dom::MediaStreamConstraints& aConstraints);
|
||||
|
||||
StreamListeners* AddWindowID(uint64_t aWindowId);
|
||||
WindowTable *GetActiveWindows() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
@ -610,9 +625,13 @@ private:
|
||||
|
||||
static StaticRefPtr<MediaManager> sSingleton;
|
||||
|
||||
media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
|
||||
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
|
||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||
#endif
|
||||
public:
|
||||
media::CoatCheck<media::Pledge<nsCString>> mGetOriginKeyPledges;
|
||||
ScopedDeletePtr<media::Parent<media::NonE10s>> mNonE10sParent;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1004,6 +1004,7 @@ RTCPeerConnection.prototype = {
|
||||
// the name change
|
||||
this.logWarning("Deprecated RTCDataChannelInit dictionary entry outOfOrderAllowed used!", null, 0);
|
||||
}
|
||||
|
||||
if (dict.preset != undefined) {
|
||||
dict.negotiated = dict.preset;
|
||||
this.logWarning("Deprecated RTCDataChannelInit dictionary entry preset used!", null, 0);
|
||||
|
@ -5,13 +5,12 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVariant.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(bbfebbc6-76eb-407c-b77d-363a69bc5c30)]
|
||||
[scriptable, builtinclass, uuid(cebcefca-2de1-460d-b253-d0582c50b40f)]
|
||||
interface nsIMediaDevice : nsISupports
|
||||
{
|
||||
readonly attribute DOMString type;
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString id;
|
||||
readonly attribute DOMString facingMode;
|
||||
readonly attribute DOMString mediaSource;
|
||||
};
|
||||
|
||||
|
@ -5,9 +5,8 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaChild.h"
|
||||
#include "MediaParent.h"
|
||||
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/MediaManager.h"
|
||||
#include "mozilla/Logging.h"
|
||||
@ -20,84 +19,52 @@ PRLogModuleInfo *gMediaChildLog;
|
||||
namespace mozilla {
|
||||
namespace media {
|
||||
|
||||
static Child* sChild;
|
||||
|
||||
template<typename ValueType> void
|
||||
ChildPledge<ValueType>::ActorCreated(PBackgroundChild* aActor)
|
||||
{
|
||||
if (!sChild) {
|
||||
// Create PMedia by sending a message to the parent
|
||||
sChild = static_cast<Child*>(aActor->SendPMediaConstructor());
|
||||
}
|
||||
Run(sChild);
|
||||
}
|
||||
|
||||
template<typename ValueType> void
|
||||
ChildPledge<ValueType>::ActorFailed()
|
||||
{
|
||||
Pledge<ValueType>::Reject(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
template<typename ValueType> NS_IMPL_ADDREF(ChildPledge<ValueType>)
|
||||
template<typename ValueType> NS_IMPL_RELEASE(ChildPledge<ValueType>)
|
||||
template<typename ValueType> NS_INTERFACE_MAP_BEGIN(ChildPledge<ValueType>)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
already_AddRefed<ChildPledge<nsCString>>
|
||||
already_AddRefed<Pledge<nsCString>>
|
||||
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing)
|
||||
{
|
||||
class Pledge : public ChildPledge<nsCString>
|
||||
{
|
||||
public:
|
||||
explicit Pledge(const nsCString& aOrigin, bool aPrivateBrowsing)
|
||||
: mOrigin(aOrigin), mPrivateBrowsing(aPrivateBrowsing) {}
|
||||
private:
|
||||
~Pledge() {}
|
||||
void Run(PMediaChild* aChild)
|
||||
{
|
||||
Child* child = static_cast<Child*>(aChild);
|
||||
nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
|
||||
MOZ_ASSERT(mgr);
|
||||
|
||||
uint32_t id = child->AddRequestPledge(*this);
|
||||
child->SendGetOriginKey(id, mOrigin, mPrivateBrowsing);
|
||||
}
|
||||
const nsCString mOrigin;
|
||||
const bool mPrivateBrowsing;
|
||||
};
|
||||
nsRefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
|
||||
uint32_t id = mgr->mGetOriginKeyPledges.Append(*p);
|
||||
|
||||
nsRefPtr<ChildPledge<nsCString>> p = new Pledge(aOrigin, aPrivateBrowsing);
|
||||
nsCOMPtr<nsIIPCBackgroundChildCreateCallback> cb = do_QueryObject(p);
|
||||
bool ok = ipc::BackgroundChild::GetOrCreateForCurrentThread(cb);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
mgr->GetNonE10sParent()->RecvGetOriginKey(id, aOrigin, aPrivateBrowsing);
|
||||
} else {
|
||||
Child::Get()->SendGetOriginKey(id, aOrigin, aPrivateBrowsing);
|
||||
}
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ChildPledge<bool>>
|
||||
void
|
||||
SanitizeOriginKeys(const uint64_t& aSinceWhen)
|
||||
{
|
||||
class Pledge : public ChildPledge<bool>
|
||||
{
|
||||
public:
|
||||
explicit Pledge(const uint64_t& aSinceWhen) : mSinceWhen(aSinceWhen) {}
|
||||
private:
|
||||
void Run(PMediaChild* aMedia)
|
||||
{
|
||||
aMedia->SendSanitizeOriginKeys(mSinceWhen);
|
||||
mValue = true;
|
||||
LOG(("SanitizeOriginKeys since %llu", mSinceWhen));
|
||||
Resolve();
|
||||
}
|
||||
const uint64_t mSinceWhen;
|
||||
};
|
||||
LOG(("SanitizeOriginKeys since %llu", aSinceWhen));
|
||||
|
||||
nsRefPtr<ChildPledge<bool>> p = new Pledge(aSinceWhen);
|
||||
nsCOMPtr<nsIIPCBackgroundChildCreateCallback> cb = do_QueryObject(p);
|
||||
bool ok = ipc::BackgroundChild::GetOrCreateForCurrentThread(cb);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
return p.forget();
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
// Avoid opening MediaManager in this case, since this is called by
|
||||
// sanitize.js when cookies are cleared, which can happen on startup.
|
||||
ScopedDeletePtr<Parent<NonE10s>> tmpParent(new Parent<NonE10s>(true));
|
||||
tmpParent->RecvSanitizeOriginKeys(aSinceWhen);
|
||||
} else {
|
||||
Child::Get()->SendSanitizeOriginKeys(aSinceWhen);
|
||||
}
|
||||
}
|
||||
|
||||
static Child* sChild;
|
||||
|
||||
Child* Child::Get()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!sChild) {
|
||||
sChild = static_cast<Child*>(dom::ContentChild::GetSingleton()->SendPMediaConstructor());
|
||||
}
|
||||
return sChild;
|
||||
}
|
||||
|
||||
Child::Child()
|
||||
: mActorDestroyed(false)
|
||||
{
|
||||
if (!gMediaChildLog) {
|
||||
gMediaChildLog = PR_NewLogModule("MediaChild");
|
||||
@ -113,22 +80,19 @@ Child::~Child()
|
||||
MOZ_COUNT_DTOR(Child);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Child::AddRequestPledge(ChildPledge<nsCString>& aPledge)
|
||||
void Child::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
return mRequestPledges.Append(aPledge);
|
||||
}
|
||||
|
||||
already_AddRefed<ChildPledge<nsCString>>
|
||||
Child::RemoveRequestPledge(uint32_t aRequestId)
|
||||
{
|
||||
return mRequestPledges.Remove(aRequestId);
|
||||
mActorDestroyed = true;
|
||||
}
|
||||
|
||||
bool
|
||||
Child::RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey)
|
||||
{
|
||||
nsRefPtr<ChildPledge<nsCString>> pledge = RemoveRequestPledge(aRequestId);
|
||||
nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
|
||||
if (!mgr) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<Pledge<nsCString>> pledge = mgr->mGetOriginKeyPledges.Remove(aRequestId);
|
||||
if (pledge) {
|
||||
pledge->Resolve(aKey);
|
||||
}
|
||||
@ -138,15 +102,13 @@ Child::RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKe
|
||||
PMediaChild*
|
||||
AllocPMediaChild()
|
||||
{
|
||||
Child* obj = new Child();
|
||||
obj->AddRef();
|
||||
return obj;
|
||||
return new Child();
|
||||
}
|
||||
|
||||
bool
|
||||
DeallocPMediaChild(media::PMediaChild *aActor)
|
||||
{
|
||||
static_cast<Child*>(aActor)->Release();
|
||||
delete static_cast<Child*>(aActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/media/PMediaChild.h"
|
||||
#include "mozilla/media/PMediaParent.h"
|
||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
||||
#include "MediaUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -25,42 +24,26 @@ namespace media {
|
||||
// GetOriginKey and SanitizeOriginKeys are asynchronous APIs that return pledges
|
||||
// (promise-like objects) with the future value. Use pledge.Then(func) to access.
|
||||
|
||||
class Child;
|
||||
|
||||
template<typename ValueType>
|
||||
class ChildPledge : public Pledge<ValueType>,
|
||||
public nsIIPCBackgroundChildCreateCallback
|
||||
{
|
||||
friend Child;
|
||||
NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
|
||||
NS_DECL_ISUPPORTS
|
||||
public:
|
||||
explicit ChildPledge() {};
|
||||
protected:
|
||||
virtual ~ChildPledge() {}
|
||||
virtual void Run(PMediaChild* aMedia) = 0;
|
||||
};
|
||||
|
||||
already_AddRefed<ChildPledge<nsCString>>
|
||||
already_AddRefed<Pledge<nsCString>>
|
||||
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing);
|
||||
|
||||
already_AddRefed<ChildPledge<bool>>
|
||||
void
|
||||
SanitizeOriginKeys(const uint64_t& aSinceWhen);
|
||||
|
||||
class Child : public PMediaChild
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(Child)
|
||||
public:
|
||||
static Child* Get();
|
||||
|
||||
Child();
|
||||
|
||||
bool RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey);
|
||||
|
||||
uint32_t AddRequestPledge(ChildPledge<nsCString>& aPledge);
|
||||
already_AddRefed<ChildPledge<nsCString>> RemoveRequestPledge(uint32_t aRequestId);
|
||||
private:
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
virtual ~Child();
|
||||
private:
|
||||
|
||||
CoatCheck<ChildPledge<nsCString>> mRequestPledges;
|
||||
bool mActorDestroyed;
|
||||
};
|
||||
|
||||
PMediaChild* AllocPMediaChild();
|
||||
|
@ -32,13 +32,13 @@ PRLogModuleInfo *gMediaParentLog;
|
||||
namespace mozilla {
|
||||
namespace media {
|
||||
|
||||
static StaticMutex gMutex;
|
||||
static ParentSingleton* sParentSingleton = nullptr;
|
||||
static Parent<PMediaParent>* sIPCServingParent;
|
||||
|
||||
class ParentSingleton : public nsISupports
|
||||
static OriginKeyStore* sOriginKeyStore = nullptr;
|
||||
|
||||
class OriginKeyStore : public nsISupports
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
class OriginKey
|
||||
{
|
||||
public:
|
||||
@ -324,166 +324,181 @@ class ParentSingleton : public nsISupports
|
||||
};
|
||||
|
||||
private:
|
||||
virtual ~ParentSingleton()
|
||||
virtual ~OriginKeyStore()
|
||||
{
|
||||
sParentSingleton = nullptr;
|
||||
sOriginKeyStore = nullptr;
|
||||
LOG((__FUNCTION__));
|
||||
}
|
||||
|
||||
public:
|
||||
static ParentSingleton* Get()
|
||||
static OriginKeyStore* Get()
|
||||
{
|
||||
// Protect creation of singleton and access from multiple Background threads.
|
||||
//
|
||||
// Multiple Background threads happen because sanitize.js calls us from the
|
||||
// chrome process and gets a thread separate from the one servicing ipc from
|
||||
// the content process.
|
||||
|
||||
StaticMutexAutoLock lock(gMutex);
|
||||
if (!sParentSingleton) {
|
||||
sParentSingleton = new ParentSingleton();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!sOriginKeyStore) {
|
||||
sOriginKeyStore = new OriginKeyStore();
|
||||
}
|
||||
return sParentSingleton;
|
||||
return sOriginKeyStore;
|
||||
}
|
||||
|
||||
// Only accessed on StreamTS thread
|
||||
OriginKeysLoader mOriginKeys;
|
||||
OriginKeysTable mPrivateBrowsingOriginKeys;
|
||||
|
||||
// Only accessed on return thread
|
||||
CoatCheck<Pledge<nsCString>> mOutstandingPledges;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS0(ParentSingleton)
|
||||
NS_IMPL_ISUPPORTS0(OriginKeyStore)
|
||||
|
||||
bool
|
||||
Parent::RecvGetOriginKey(const uint32_t& aRequestId,
|
||||
template<> /* static */
|
||||
Parent<PMediaParent>* Parent<PMediaParent>::GetSingleton()
|
||||
{
|
||||
return sIPCServingParent;
|
||||
}
|
||||
|
||||
template<> /* static */
|
||||
Parent<NonE10s>* Parent<NonE10s>::GetSingleton()
|
||||
{
|
||||
nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
|
||||
if (!mgr) {
|
||||
return nullptr;
|
||||
}
|
||||
return mgr->GetNonE10sParent();
|
||||
}
|
||||
|
||||
// TODO: Remove once upgraded to GCC 4.8+ on linux. Bogus error on static func:
|
||||
// error: 'this' was not captured for this lambda function
|
||||
|
||||
template<class Super> static
|
||||
Parent<Super>* GccGetSingleton() { return Parent<Super>::GetSingleton(); };
|
||||
|
||||
|
||||
template<class Super> bool
|
||||
Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId,
|
||||
const nsCString& aOrigin,
|
||||
const bool& aPrivateBrowsing)
|
||||
{
|
||||
// TODO: Replace all this when moving MediaParent to PContent soon (1037389)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<ParentSingleton> singleton(mSingleton);
|
||||
nsCOMPtr<nsIThread> returnThread = NS_GetCurrentThread();
|
||||
nsRefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
|
||||
nsresult rv;
|
||||
// First, get profile dir.
|
||||
|
||||
// First, over to main thread to get profile dir.
|
||||
|
||||
// Pledges are non-threadsafe by design, so check them and pass an id instead.
|
||||
uint32_t id = singleton->mOutstandingPledges.Append(*p);
|
||||
|
||||
rv = NS_DispatchToMainThread(NewRunnableFrom([id, returnThread,
|
||||
singleton, aOrigin,
|
||||
aPrivateBrowsing]() -> nsresult {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Then from there over to stream-transport thread to do the actual file io.
|
||||
|
||||
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(sts);
|
||||
rv = sts->Dispatch(NewRunnableFrom([profileDir, id, returnThread, singleton,
|
||||
aOrigin, aPrivateBrowsing]() -> nsresult {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
singleton->mOriginKeys.SetProfileDir(profileDir);
|
||||
nsCString result;
|
||||
if (aPrivateBrowsing) {
|
||||
singleton->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
|
||||
} else {
|
||||
singleton->mOriginKeys.GetOriginKey(aOrigin, result);
|
||||
}
|
||||
|
||||
// Pass result back to original thread.
|
||||
nsresult rv;
|
||||
rv = returnThread->Dispatch(NewRunnableFrom([id, singleton,
|
||||
result]() -> nsresult {
|
||||
nsRefPtr<Pledge<nsCString>> p = singleton->mOutstandingPledges.Remove(id);
|
||||
if (!p) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
p->Resolve(result);
|
||||
return NS_OK;
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<media::Parent> keepAlive(this);
|
||||
p->Then([this, keepAlive, aRequestId](const nsCString& aKey) mutable {
|
||||
if (!mDestroyed) {
|
||||
unused << SendGetOriginKeyResponse(aRequestId, aKey);
|
||||
// Then over to stream-transport thread to do the actual file io.
|
||||
// Stash a pledge to hold the answer and get an id for this request.
|
||||
|
||||
nsRefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
|
||||
uint32_t id = mOutstandingPledges.Append(*p);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(sts);
|
||||
nsRefPtr<OriginKeyStore> store(mOriginKeyStore);
|
||||
bool sameProcess = mSameProcess;
|
||||
|
||||
rv = sts->Dispatch(NewRunnableFrom([id, profileDir, store, sameProcess,
|
||||
aOrigin, aPrivateBrowsing]() -> nsresult {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
store->mOriginKeys.SetProfileDir(profileDir);
|
||||
nsCString result;
|
||||
if (aPrivateBrowsing) {
|
||||
store->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
|
||||
} else {
|
||||
store->mOriginKeys.GetOriginKey(aOrigin, result);
|
||||
}
|
||||
|
||||
// Pass result back to main thread.
|
||||
nsresult rv;
|
||||
rv = NS_DispatchToMainThread(NewRunnableFrom([id, store, sameProcess,
|
||||
result]() -> nsresult {
|
||||
Parent* parent = GccGetSingleton<Super>(); // GetSingleton();
|
||||
if (!parent) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<Pledge<nsCString>> p = parent->mOutstandingPledges.Remove(id);
|
||||
if (!p) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
p->Resolve(result);
|
||||
return NS_OK;
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p->Then([aRequestId, sameProcess](const nsCString& aKey) mutable {
|
||||
if (!sameProcess) {
|
||||
if (!sIPCServingParent) {
|
||||
return NS_OK;
|
||||
}
|
||||
unused << sIPCServingParent->SendGetOriginKeyResponse(aRequestId, aKey);
|
||||
} else {
|
||||
nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
|
||||
if (!mgr) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<Pledge<nsCString>> pledge =
|
||||
mgr->mGetOriginKeyPledges.Remove(aRequestId);
|
||||
if (pledge) {
|
||||
pledge->Resolve(aKey);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Parent::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen)
|
||||
template<class Super> bool
|
||||
Parent<Super>::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen)
|
||||
{
|
||||
nsRefPtr<ParentSingleton> singleton(mSingleton);
|
||||
|
||||
// First, over to main to get profile dir.
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_DispatchToMainThread(NewRunnableFrom([singleton,
|
||||
aSinceWhen]() -> nsresult {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// Then from there over to stream-transport thread to do the file io.
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
// Over to stream-transport thread to do the file io.
|
||||
|
||||
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(sts);
|
||||
rv = sts->Dispatch(NewRunnableFrom([profileDir, singleton, aSinceWhen]() -> nsresult {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
singleton->mOriginKeys.SetProfileDir(profileDir);
|
||||
singleton->mPrivateBrowsingOriginKeys.Clear(aSinceWhen);
|
||||
singleton->mOriginKeys.Clear(aSinceWhen);
|
||||
return NS_OK;
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(sts);
|
||||
nsRefPtr<OriginKeyStore> store(mOriginKeyStore);
|
||||
|
||||
rv = sts->Dispatch(NewRunnableFrom([profileDir, store, aSinceWhen]() -> nsresult {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
store->mOriginKeys.SetProfileDir(profileDir);
|
||||
store->mPrivateBrowsingOriginKeys.Clear(aSinceWhen);
|
||||
store->mOriginKeys.Clear(aSinceWhen);
|
||||
return NS_OK;
|
||||
}));
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Parent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
template<class Super> void
|
||||
Parent<Super>::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
// No more IPC from here
|
||||
mDestroyed = true;
|
||||
LOG((__FUNCTION__));
|
||||
}
|
||||
|
||||
Parent::Parent()
|
||||
: mSingleton(ParentSingleton::Get())
|
||||
template<class Super>
|
||||
Parent<Super>::Parent(bool aSameProcess)
|
||||
: mOriginKeyStore(OriginKeyStore::Get())
|
||||
, mDestroyed(false)
|
||||
, mSameProcess(aSameProcess)
|
||||
{
|
||||
if (!gMediaParentLog)
|
||||
gMediaParentLog = PR_NewLogModule("MediaParent");
|
||||
@ -492,7 +507,8 @@ Parent::Parent()
|
||||
MOZ_COUNT_CTOR(Parent);
|
||||
}
|
||||
|
||||
Parent::~Parent()
|
||||
template<class Super>
|
||||
Parent<Super>::~Parent()
|
||||
{
|
||||
LOG(("~media::Parent: %p", this));
|
||||
|
||||
@ -502,17 +518,21 @@ Parent::~Parent()
|
||||
PMediaParent*
|
||||
AllocPMediaParent()
|
||||
{
|
||||
Parent* obj = new Parent();
|
||||
obj->AddRef();
|
||||
return obj;
|
||||
MOZ_ASSERT(!sIPCServingParent);
|
||||
sIPCServingParent = new Parent<PMediaParent>();
|
||||
return sIPCServingParent;
|
||||
}
|
||||
|
||||
bool
|
||||
DeallocPMediaParent(media::PMediaParent *aActor)
|
||||
{
|
||||
static_cast<Parent*>(aActor)->Release();
|
||||
MOZ_ASSERT(sIPCServingParent == static_cast<Parent<PMediaParent>*>(aActor));
|
||||
delete sIPCServingParent;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate templates to satisfy linker
|
||||
template class mozilla::media::Parent<mozilla::media::NonE10s>;
|
||||
|
@ -16,25 +16,48 @@ namespace mozilla {
|
||||
namespace media {
|
||||
|
||||
// media::Parent implements the chrome-process side of ipc for media::Child APIs
|
||||
// A "SameProcess" version may also be created to service non-e10s calls.
|
||||
|
||||
class ParentSingleton;
|
||||
class OriginKeyStore;
|
||||
|
||||
class Parent : public PMediaParent
|
||||
class NonE10s
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(Parent)
|
||||
typedef mozilla::ipc::IProtocolManager<mozilla::ipc::IProtocol>::ActorDestroyReason
|
||||
ActorDestroyReason;
|
||||
protected:
|
||||
virtual bool RecvGetOriginKey(const uint32_t& aRequestId,
|
||||
const nsCString& aOrigin,
|
||||
const bool& aPrivateBrowsing) = 0;
|
||||
virtual bool RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) = 0;
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) = 0;
|
||||
};
|
||||
|
||||
// Super = PMediaParent or NonE10s
|
||||
|
||||
template<class Super>
|
||||
class Parent : public Super
|
||||
{
|
||||
typedef mozilla::ipc::IProtocolManager<mozilla::ipc::IProtocol>::ActorDestroyReason
|
||||
ActorDestroyReason;
|
||||
public:
|
||||
static Parent* GetSingleton();
|
||||
|
||||
virtual bool RecvGetOriginKey(const uint32_t& aRequestId,
|
||||
const nsCString& aOrigin,
|
||||
const bool& aPrivateBrowsing) override;
|
||||
virtual bool RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) override;
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
Parent();
|
||||
private:
|
||||
explicit Parent(bool aSameProcess = false);
|
||||
virtual ~Parent();
|
||||
private:
|
||||
|
||||
nsRefPtr<ParentSingleton> mSingleton;
|
||||
nsRefPtr<OriginKeyStore> mOriginKeyStore;
|
||||
bool mDestroyed;
|
||||
bool mSameProcess;
|
||||
|
||||
CoatCheck<Pledge<nsCString>> mOutstandingPledges;
|
||||
};
|
||||
|
||||
PMediaParent* AllocPMediaParent();
|
||||
|
@ -40,8 +40,16 @@ namespace media {
|
||||
* See media::CoatCheck below for an example of GetFooAsynchronously().
|
||||
*/
|
||||
|
||||
template<typename ValueType>
|
||||
class Pledge
|
||||
class PledgeBase
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(PledgeBase);
|
||||
protected:
|
||||
virtual ~PledgeBase() {};
|
||||
};
|
||||
|
||||
template<typename ValueType, typename ErrorType = nsresult>
|
||||
class Pledge : public PledgeBase
|
||||
{
|
||||
// TODO: Remove workaround once mozilla allows std::function from <functional>
|
||||
// wo/std::function support, do template + virtual trick to accept lambdas
|
||||
@ -49,49 +57,50 @@ class Pledge
|
||||
{
|
||||
public:
|
||||
FunctorsBase() {}
|
||||
virtual void Succeed(const ValueType& result) = 0;
|
||||
virtual void Fail(nsresult rv) = 0;
|
||||
virtual void Succeed(ValueType& result) = 0;
|
||||
virtual void Fail(ErrorType& error) = 0;
|
||||
virtual ~FunctorsBase() {};
|
||||
};
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(Pledge);
|
||||
explicit Pledge() : mDone(false), mResult(NS_OK) {}
|
||||
explicit Pledge() : mDone(false), mError(nullptr) {}
|
||||
Pledge(const Pledge& aOther) = delete;
|
||||
Pledge& operator = (const Pledge&) = delete;
|
||||
|
||||
template<typename OnSuccessType>
|
||||
void Then(OnSuccessType aOnSuccess)
|
||||
{
|
||||
Then(aOnSuccess, [](nsresult){});
|
||||
Then(aOnSuccess, [](ErrorType&){});
|
||||
}
|
||||
|
||||
template<typename OnSuccessType, typename OnFailureType>
|
||||
void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure)
|
||||
{
|
||||
class F : public FunctorsBase
|
||||
class Functors : public FunctorsBase
|
||||
{
|
||||
public:
|
||||
F(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
|
||||
Functors(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
|
||||
: mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {}
|
||||
|
||||
void Succeed(const ValueType& result)
|
||||
void Succeed(ValueType& result)
|
||||
{
|
||||
mOnSuccess(result);
|
||||
}
|
||||
void Fail(nsresult rv)
|
||||
void Fail(ErrorType& error)
|
||||
{
|
||||
mOnFailure(rv);
|
||||
mOnFailure(error);
|
||||
};
|
||||
|
||||
OnSuccessType mOnSuccess;
|
||||
OnFailureType mOnFailure;
|
||||
};
|
||||
mFunctors = new F(aOnSuccess, aOnFailure);
|
||||
mFunctors = new Functors(aOnSuccess, aOnFailure);
|
||||
|
||||
if (mDone) {
|
||||
if (mResult == NS_OK) {
|
||||
if (!mError) {
|
||||
mFunctors->Succeed(mValue);
|
||||
} else {
|
||||
mFunctors->Fail(mResult);
|
||||
mFunctors->Fail(*mError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,34 +115,127 @@ protected:
|
||||
{
|
||||
if (!mDone) {
|
||||
mDone = true;
|
||||
MOZ_ASSERT(mResult == NS_OK);
|
||||
MOZ_ASSERT(!mError);
|
||||
if (mFunctors) {
|
||||
mFunctors->Succeed(mValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reject(nsresult rv)
|
||||
void Reject(ErrorType rv)
|
||||
{
|
||||
if (!mDone) {
|
||||
mDone = true;
|
||||
mResult = rv;
|
||||
mError = rv;
|
||||
if (mFunctors) {
|
||||
mFunctors->Fail(mResult);
|
||||
mFunctors->Fail(mError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueType mValue;
|
||||
protected:
|
||||
private:
|
||||
~Pledge() {};
|
||||
bool mDone;
|
||||
nsresult mResult;
|
||||
nsRefPtr<ErrorType> mError;
|
||||
ScopedDeletePtr<FunctorsBase> mFunctors;
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
class Pledge<ValueType, nsresult> : public PledgeBase
|
||||
{
|
||||
// TODO: Remove workaround once mozilla allows std::function from <functional>
|
||||
// wo/std::function support, do template + virtual trick to accept lambdas
|
||||
class FunctorsBase
|
||||
{
|
||||
public:
|
||||
FunctorsBase() {}
|
||||
virtual void Succeed(ValueType& result) = 0;
|
||||
virtual void Fail(nsresult error) = 0;
|
||||
virtual ~FunctorsBase() {};
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Pledge() : mDone(false), mError(NS_OK) {}
|
||||
Pledge(const Pledge& aOther) = delete;
|
||||
Pledge& operator = (const Pledge&) = delete;
|
||||
|
||||
template<typename OnSuccessType>
|
||||
void Then(OnSuccessType aOnSuccess)
|
||||
{
|
||||
Then(aOnSuccess, [](nsresult){});
|
||||
}
|
||||
|
||||
template<typename OnSuccessType, typename OnFailureType>
|
||||
void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure)
|
||||
{
|
||||
class Functors : public FunctorsBase
|
||||
{
|
||||
public:
|
||||
Functors(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
|
||||
: mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {}
|
||||
|
||||
void Succeed(ValueType& result)
|
||||
{
|
||||
mOnSuccess(result);
|
||||
}
|
||||
void Fail(nsresult rv)
|
||||
{
|
||||
mOnFailure(rv);
|
||||
};
|
||||
|
||||
OnSuccessType mOnSuccess;
|
||||
OnFailureType mOnFailure;
|
||||
};
|
||||
mFunctors = new Functors(aOnSuccess, aOnFailure);
|
||||
|
||||
if (mDone) {
|
||||
if (mError == NS_OK) {
|
||||
mFunctors->Succeed(mValue);
|
||||
} else {
|
||||
mFunctors->Fail(mError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resolve(const ValueType& aValue)
|
||||
{
|
||||
mValue = aValue;
|
||||
Resolve();
|
||||
}
|
||||
protected:
|
||||
void Resolve()
|
||||
{
|
||||
if (!mDone) {
|
||||
mDone = true;
|
||||
MOZ_ASSERT(mError == NS_OK);
|
||||
if (mFunctors) {
|
||||
mFunctors->Succeed(mValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reject(nsresult error)
|
||||
{
|
||||
if (!mDone) {
|
||||
mDone = true;
|
||||
mError = error;
|
||||
if (mFunctors) {
|
||||
mFunctors->Fail(mError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueType mValue;
|
||||
private:
|
||||
nsAutoPtr<FunctorsBase> mFunctors;
|
||||
~Pledge() {};
|
||||
bool mDone;
|
||||
nsresult mError;
|
||||
ScopedDeletePtr<FunctorsBase> mFunctors;
|
||||
};
|
||||
|
||||
/* media::NewRunnableFrom() - Create an nsRunnable from a lambda.
|
||||
* media::NewTaskFrom() - Create a Task from a lambda.
|
||||
*
|
||||
* Passing variables (closures) to an async function is clunky with nsRunnable:
|
||||
*
|
||||
@ -192,6 +294,27 @@ NewRunnableFrom(OnRunType aOnRun)
|
||||
return new LambdaRunnable<OnRunType>(aOnRun);
|
||||
}
|
||||
|
||||
template<typename OnRunType>
|
||||
class LambdaTask : public Task
|
||||
{
|
||||
public:
|
||||
explicit LambdaTask(OnRunType& aOnRun) : mOnRun(aOnRun) {}
|
||||
private:
|
||||
void
|
||||
Run()
|
||||
{
|
||||
return mOnRun();
|
||||
}
|
||||
OnRunType mOnRun;
|
||||
};
|
||||
|
||||
template<typename OnRunType>
|
||||
LambdaTask<OnRunType>*
|
||||
NewTaskFrom(OnRunType aOnRun)
|
||||
{
|
||||
return new LambdaTask<OnRunType>(aOnRun);
|
||||
}
|
||||
|
||||
/* media::CoatCheck - There and back again. Park an object in exchange for an id.
|
||||
*
|
||||
* A common problem with calling asynchronous functions that do work on other
|
||||
@ -213,7 +336,7 @@ NewRunnableFrom(OnRunType aOnRun)
|
||||
* void DoFoo()
|
||||
* {
|
||||
* nsRefPtr<Foo> foo = new Foo();
|
||||
* uint32_t requestId = mOutstandingFoos.Append(foo);
|
||||
* uint32_t requestId = mOutstandingFoos.Append(*foo);
|
||||
* sChild->SendFoo(requestId);
|
||||
* }
|
||||
*
|
||||
@ -230,13 +353,13 @@ NewRunnableFrom(OnRunType aOnRun)
|
||||
*
|
||||
* class FooGetter
|
||||
* {
|
||||
* CoatCheck<Foo> mOutstandingPledges;
|
||||
* CoatCheck<Pledge<Foo>> mOutstandingPledges;
|
||||
*
|
||||
* public:
|
||||
* already_addRefed<Pledge<Foo>> GetFooAsynchronously()
|
||||
* {
|
||||
* nsRefPtr<Pledge<Foo>> p = new Pledge<Foo>();
|
||||
* uint32_t requestId = mOutstandingPledges.Append(p);
|
||||
* uint32_t requestId = mOutstandingPledges.Append(*p);
|
||||
* sChild->SendFoo(requestId);
|
||||
* return p.forget();
|
||||
* }
|
||||
|
@ -3,14 +3,13 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PContent;
|
||||
include protocol PBackground;
|
||||
|
||||
namespace mozilla {
|
||||
namespace media {
|
||||
|
||||
protocol PMedia
|
||||
{
|
||||
manager PBackground;
|
||||
manager PContent;
|
||||
|
||||
parent:
|
||||
/**
|
||||
|
@ -23,14 +23,6 @@ var tests = [
|
||||
constraints: { audio: { somethingUnknown: { exact: 0 } },
|
||||
fake: true },
|
||||
error: null },
|
||||
{ message: "video overconstrained by facingMode fails",
|
||||
constraints: { video: { facingMode:{ exact: 'left' } },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "video overconstrained by facingMode array fails",
|
||||
constraints: { video: { facingMode:{ exact: ['left', 'right'] } },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "audio overconstrained by facingMode ignored",
|
||||
constraints: { audio: { facingMode: { exact: 'left' } },
|
||||
fake: true },
|
||||
|
@ -88,8 +88,8 @@ public:
|
||||
/* Populate the human readable name of this device in the nsAString */
|
||||
virtual void GetName(nsAString&) = 0;
|
||||
|
||||
/* Populate the UUID of this device in the nsAString */
|
||||
virtual void GetUUID(nsAString&) = 0;
|
||||
/* Populate the UUID of this device in the nsACString */
|
||||
virtual void GetUUID(nsACString&) = 0;
|
||||
|
||||
/* Release the device back to the system. */
|
||||
virtual nsresult Deallocate() = 0;
|
||||
|
@ -9,11 +9,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using dom::OwningLongOrConstrainLongRange;
|
||||
using dom::ConstrainLongRange;
|
||||
using dom::OwningDoubleOrConstrainDoubleRange;
|
||||
using dom::ConstrainDoubleRange;
|
||||
using dom::MediaTrackConstraintSet;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
extern PRLogModuleInfo* GetMediaManagerLog();
|
||||
#define LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
|
||||
@ -62,51 +58,106 @@ MediaEngineCameraVideoSource::GetCapability(size_t aIndex,
|
||||
|
||||
template<class ValueType, class ConstrainRange>
|
||||
/* static */ uint32_t
|
||||
MediaEngineCameraVideoSource::FitnessDistance(ValueType n,
|
||||
MediaEngineCameraVideoSource::FitnessDistance(ValueType aN,
|
||||
const ConstrainRange& aRange)
|
||||
{
|
||||
if ((aRange.mExact.WasPassed() && aRange.mExact.Value() != n) ||
|
||||
(aRange.mMin.WasPassed() && aRange.mMin.Value() > n) ||
|
||||
(aRange.mMax.WasPassed() && aRange.mMax.Value() < n)) {
|
||||
if ((aRange.mExact.WasPassed() && aRange.mExact.Value() != aN) ||
|
||||
(aRange.mMin.WasPassed() && aRange.mMin.Value() > aN) ||
|
||||
(aRange.mMax.WasPassed() && aRange.mMax.Value() < aN)) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
if (!aRange.mIdeal.WasPassed() || n == aRange.mIdeal.Value()) {
|
||||
if (!aRange.mIdeal.WasPassed() || aN == aRange.mIdeal.Value()) {
|
||||
return 0;
|
||||
}
|
||||
return uint32_t(ValueType((std::abs(n - aRange.mIdeal.Value()) * 1000) /
|
||||
std::max(std::abs(n), std::abs(aRange.mIdeal.Value()))));
|
||||
return uint32_t(ValueType((std::abs(aN - aRange.mIdeal.Value()) * 1000) /
|
||||
std::max(std::abs(aN), std::abs(aRange.mIdeal.Value()))));
|
||||
}
|
||||
|
||||
// Binding code doesn't templatize well...
|
||||
|
||||
/*static*/ uint32_t
|
||||
MediaEngineCameraVideoSource::FitnessDistance(int32_t n,
|
||||
MediaEngineCameraVideoSource::FitnessDistance(int32_t aN,
|
||||
const OwningLongOrConstrainLongRange& aConstraint, bool aAdvanced)
|
||||
{
|
||||
if (aConstraint.IsLong()) {
|
||||
ConstrainLongRange range;
|
||||
(aAdvanced ? range.mExact : range.mIdeal).Construct(aConstraint.GetAsLong());
|
||||
return FitnessDistance(n, range);
|
||||
return FitnessDistance(aN, range);
|
||||
} else {
|
||||
return FitnessDistance(n, aConstraint.GetAsConstrainLongRange());
|
||||
return FitnessDistance(aN, aConstraint.GetAsConstrainLongRange());
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ uint32_t
|
||||
MediaEngineCameraVideoSource::FitnessDistance(double n,
|
||||
MediaEngineCameraVideoSource::FitnessDistance(double aN,
|
||||
const OwningDoubleOrConstrainDoubleRange& aConstraint,
|
||||
bool aAdvanced)
|
||||
{
|
||||
if (aConstraint.IsDouble()) {
|
||||
ConstrainDoubleRange range;
|
||||
(aAdvanced ? range.mExact : range.mIdeal).Construct(aConstraint.GetAsDouble());
|
||||
return FitnessDistance(n, range);
|
||||
return FitnessDistance(aN, range);
|
||||
} else {
|
||||
return FitnessDistance(n, aConstraint.GetAsConstrainDoubleRange());
|
||||
return FitnessDistance(aN, aConstraint.GetAsConstrainDoubleRange());
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ uint32_t
|
||||
// Fitness distance returned as integer math * 1000. Infinity = UINT32_MAX
|
||||
|
||||
/* static */ uint32_t
|
||||
MediaEngineCameraVideoSource::FitnessDistance(nsString aN,
|
||||
const ConstrainDOMStringParameters& aParams)
|
||||
{
|
||||
struct Func
|
||||
{
|
||||
static bool
|
||||
Contains(const OwningStringOrStringSequence& aStrings, nsString aN)
|
||||
{
|
||||
return aStrings.IsString() ? aStrings.GetAsString() == aN
|
||||
: aStrings.GetAsStringSequence().Contains(aN);
|
||||
}
|
||||
};
|
||||
|
||||
if (aParams.mExact.WasPassed() && !Func::Contains(aParams.mExact.Value(), aN)) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
if (aParams.mIdeal.WasPassed() && !Func::Contains(aParams.mIdeal.Value(), aN)) {
|
||||
return 1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
MediaEngineCameraVideoSource::FitnessDistance(nsString aN,
|
||||
const OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint,
|
||||
bool aAdvanced)
|
||||
{
|
||||
if (aConstraint.IsString()) {
|
||||
ConstrainDOMStringParameters params;
|
||||
if (aAdvanced) {
|
||||
params.mExact.Construct();
|
||||
params.mExact.Value().SetAsString() = aConstraint.GetAsString();
|
||||
} else {
|
||||
params.mIdeal.Construct();
|
||||
params.mIdeal.Value().SetAsString() = aConstraint.GetAsString();
|
||||
}
|
||||
return FitnessDistance(aN, params);
|
||||
} else if (aConstraint.IsStringSequence()) {
|
||||
ConstrainDOMStringParameters params;
|
||||
if (aAdvanced) {
|
||||
params.mExact.Construct();
|
||||
params.mExact.Value().SetAsStringSequence() = aConstraint.GetAsStringSequence();
|
||||
} else {
|
||||
params.mIdeal.Construct();
|
||||
params.mIdeal.Value().SetAsStringSequence() = aConstraint.GetAsStringSequence();
|
||||
}
|
||||
return FitnessDistance(aN, params);
|
||||
} else {
|
||||
return FitnessDistance(aN, aConstraint.GetAsConstrainDOMStringParameters());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MediaEngineCameraVideoSource::GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
bool aAdvanced)
|
||||
@ -115,6 +166,7 @@ MediaEngineCameraVideoSource::GetFitnessDistance(const webrtc::CaptureCapability
|
||||
// This allows for orthogonal capabilities that are not in discrete steps.
|
||||
|
||||
uint64_t distance =
|
||||
uint64_t(FitnessDistance(mFacingMode, aConstraints.mFacingMode, aAdvanced)) +
|
||||
uint64_t(aCandidate.width? FitnessDistance(int32_t(aCandidate.width),
|
||||
aConstraints.mWidth,
|
||||
aAdvanced) : 0) +
|
||||
@ -215,7 +267,7 @@ MediaEngineCameraVideoSource::LogConstraints(
|
||||
|
||||
bool
|
||||
MediaEngineCameraVideoSource::ChooseCapability(
|
||||
const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
|
||||
@ -324,6 +376,52 @@ MediaEngineCameraVideoSource::ChooseCapability(
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineCameraVideoSource::SetName(nsString aName)
|
||||
{
|
||||
mDeviceName = aName;
|
||||
bool hasFacingMode = false;
|
||||
VideoFacingModeEnum facingMode = VideoFacingModeEnum::User;
|
||||
|
||||
// Set facing mode based on device name.
|
||||
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
|
||||
if (aName.EqualsLiteral("back")) {
|
||||
hasFacingMode = true;
|
||||
facingMode = VideoFacingModeEnum::Environment;
|
||||
} else if (aName.EqualsLiteral("front")) {
|
||||
hasFacingMode = true;
|
||||
facingMode = VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif // MOZ_B2G_CAMERA
|
||||
#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||
// Names are generated. Example: "Camera 0, Facing back, Orientation 90"
|
||||
//
|
||||
// See media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/
|
||||
// webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
|
||||
|
||||
if (aName.Find(NS_LITERAL_STRING("Facing back")) != kNotFound) {
|
||||
hasFacingMode = true;
|
||||
facingMode = VideoFacingModeEnum::Environment;
|
||||
} else if (aName.Find(NS_LITERAL_STRING("Facing front")) != kNotFound) {
|
||||
hasFacingMode = true;
|
||||
facingMode = VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif // ANDROID
|
||||
#ifdef XP_MACOSX
|
||||
// Kludge to test user-facing cameras on OSX.
|
||||
if (aName.Find(NS_LITERAL_STRING("Face")) != -1) {
|
||||
hasFacingMode = true;
|
||||
facingMode = VideoFacingModeEnum::User;
|
||||
}
|
||||
#endif
|
||||
if (hasFacingMode) {
|
||||
mFacingMode.Assign(NS_ConvertUTF8toUTF16(
|
||||
VideoFacingModeEnumValues::strings[uint32_t(facingMode)].value));
|
||||
} else {
|
||||
mFacingMode.Truncate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineCameraVideoSource::GetName(nsAString& aName)
|
||||
{
|
||||
@ -331,11 +429,24 @@ MediaEngineCameraVideoSource::GetName(nsAString& aName)
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineCameraVideoSource::GetUUID(nsAString& aUUID)
|
||||
MediaEngineCameraVideoSource::SetUUID(const char* aUUID)
|
||||
{
|
||||
mUniqueId.Assign(aUUID);
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineCameraVideoSource::GetUUID(nsACString& aUUID)
|
||||
{
|
||||
aUUID = mUniqueId;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
MediaEngineCameraVideoSource::GetUUID()
|
||||
{
|
||||
return mUniqueId;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MediaEngineCameraVideoSource::SetDirectListeners(bool aHasDirectListeners)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
|
||||
|
||||
virtual void GetName(nsAString& aName) override;
|
||||
virtual void GetUUID(nsAString& aUUID) override;
|
||||
virtual void GetUUID(nsACString& aUUID) override;
|
||||
virtual void SetDirectListeners(bool aHasListeners) override;
|
||||
virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
|
||||
bool aAgcOn, uint32_t aAGC,
|
||||
@ -81,15 +81,20 @@ protected:
|
||||
TrackID aID,
|
||||
StreamTime delta);
|
||||
template<class ValueType, class ConstrainRange>
|
||||
static uint32_t FitnessDistance(ValueType n, const ConstrainRange& aRange);
|
||||
static uint32_t FitnessDistance(int32_t n,
|
||||
static uint32_t FitnessDistance(ValueType aN, const ConstrainRange& aRange);
|
||||
static uint32_t FitnessDistance(int32_t aN,
|
||||
const dom::OwningLongOrConstrainLongRange& aConstraint, bool aAdvanced);
|
||||
static uint32_t FitnessDistance(double n,
|
||||
static uint32_t FitnessDistance(double aN,
|
||||
const dom::OwningDoubleOrConstrainDoubleRange& aConstraint, bool aAdvanced);
|
||||
static uint32_t FitnessDistance(nsString aN,
|
||||
const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint,
|
||||
bool aAdvanced);
|
||||
static uint32_t FitnessDistance(nsString aN,
|
||||
const dom::ConstrainDOMStringParameters& aParams);
|
||||
|
||||
static uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
|
||||
const dom::MediaTrackConstraintSet &aConstraints,
|
||||
bool aAdvanced);
|
||||
uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
|
||||
const dom::MediaTrackConstraintSet &aConstraints,
|
||||
bool aAdvanced);
|
||||
static void TrimLessFitCandidates(CapabilitySet& set);
|
||||
static void LogConstraints(const dom::MediaTrackConstraintSet& aConstraints,
|
||||
bool aAdvanced);
|
||||
@ -97,6 +102,9 @@ protected:
|
||||
virtual void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut);
|
||||
bool ChooseCapability(const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs);
|
||||
void SetName(nsString aName);
|
||||
void SetUUID(const char* aUUID);
|
||||
const nsCString& GetUUID(); // protected access
|
||||
|
||||
// Engine variables.
|
||||
|
||||
@ -124,8 +132,10 @@ protected:
|
||||
webrtc::CaptureCapability mCapability; // Doesn't work on OS X.
|
||||
|
||||
nsTArray<webrtc::CaptureCapability> mHardcodedCapabilities; // For OSX & B2G
|
||||
private:
|
||||
nsString mDeviceName;
|
||||
nsString mUniqueId;
|
||||
nsCString mUniqueId;
|
||||
nsString mFacingMode;
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,9 +62,9 @@ MediaEngineDefaultVideoSource::GetName(nsAString& aName)
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineDefaultVideoSource::GetUUID(nsAString& aUUID)
|
||||
MediaEngineDefaultVideoSource::GetUUID(nsACString& aUUID)
|
||||
{
|
||||
aUUID.AssignLiteral(MOZ_UTF16("1041FCBD-3F12-4F7B-9E9B-1EC556DD5676"));
|
||||
aUUID.AssignLiteral("1041FCBD-3F12-4F7B-9E9B-1EC556DD5676");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -342,9 +342,9 @@ MediaEngineDefaultAudioSource::GetName(nsAString& aName)
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineDefaultAudioSource::GetUUID(nsAString& aUUID)
|
||||
MediaEngineDefaultAudioSource::GetUUID(nsACString& aUUID)
|
||||
{
|
||||
aUUID.AssignLiteral(MOZ_UTF16("B7CBD7C1-53EF-42F9-8353-73F61C70C092"));
|
||||
aUUID.AssignLiteral("B7CBD7C1-53EF-42F9-8353-73F61C70C092");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
virtual void Shutdown() override {};
|
||||
|
||||
virtual void GetName(nsAString&) override;
|
||||
virtual void GetUUID(nsAString&) override;
|
||||
virtual void GetUUID(nsACString&) override;
|
||||
|
||||
virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs) override;
|
||||
@ -109,7 +109,7 @@ public:
|
||||
virtual void Shutdown() override {};
|
||||
|
||||
virtual void GetName(nsAString&) override;
|
||||
virtual void GetUUID(nsAString&) override;
|
||||
virtual void GetUUID(nsACString&) override;
|
||||
|
||||
virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs) override;
|
||||
|
@ -337,8 +337,8 @@ MediaEngineGonkVideoSource::Init()
|
||||
{
|
||||
nsAutoCString deviceName;
|
||||
ICameraControl::GetCameraName(mCaptureIndex, deviceName);
|
||||
CopyUTF8toUTF16(deviceName, mDeviceName);
|
||||
CopyUTF8toUTF16(deviceName, mUniqueId);
|
||||
SetName(NS_ConvertUTF8toUTF16(deviceName));
|
||||
SetUUID(deviceName.get());
|
||||
|
||||
mInitDone = true;
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ MediaEngineTabVideoSource::GetName(nsAString_internal& aName)
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineTabVideoSource::GetUUID(nsAString_internal& aUuid)
|
||||
MediaEngineTabVideoSource::GetUUID(nsACString_internal& aUuid)
|
||||
{
|
||||
aUuid.AssignLiteral(MOZ_UTF16("uuid"));
|
||||
aUuid.AssignLiteral("tab");
|
||||
}
|
||||
|
||||
#define DEFAULT_TABSHARE_VIDEO_MAX_WIDTH 4096
|
||||
|
@ -20,7 +20,7 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
|
||||
|
||||
virtual void Shutdown() override {};
|
||||
virtual void GetName(nsAString_internal&) override;
|
||||
virtual void GetUUID(nsAString_internal&) override;
|
||||
virtual void GetUUID(nsACString_internal&) override;
|
||||
virtual nsresult Allocate(const dom::MediaTrackConstraints &,
|
||||
const mozilla::MediaEnginePrefs&) override;
|
||||
virtual nsresult Deallocate() override;
|
||||
|
@ -153,12 +153,12 @@ public:
|
||||
, mNullTransport(nullptr) {
|
||||
MOZ_ASSERT(aVoiceEnginePtr);
|
||||
mDeviceName.Assign(NS_ConvertUTF8toUTF16(name));
|
||||
mDeviceUUID.Assign(NS_ConvertUTF8toUTF16(uuid));
|
||||
mDeviceUUID.Assign(uuid);
|
||||
Init();
|
||||
}
|
||||
|
||||
virtual void GetName(nsAString& aName) override;
|
||||
virtual void GetUUID(nsAString& aUUID) override;
|
||||
virtual void GetUUID(nsACString& aUUID) override;
|
||||
|
||||
virtual nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs) override;
|
||||
@ -223,7 +223,7 @@ private:
|
||||
bool mStarted;
|
||||
|
||||
nsString mDeviceName;
|
||||
nsString mDeviceUUID;
|
||||
nsCString mDeviceUUID;
|
||||
|
||||
bool mEchoOn, mAgcOn, mNoiseOn;
|
||||
webrtc::EcModes mEchoCancel;
|
||||
|
@ -187,7 +187,7 @@ MediaEngineWebRTCAudioSource::GetName(nsAString& aName)
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCAudioSource::GetUUID(nsAString& aUUID)
|
||||
MediaEngineWebRTCAudioSource::GetUUID(nsACString& aUUID)
|
||||
{
|
||||
if (mInitDone) {
|
||||
aUUID.Assign(mDeviceUUID);
|
||||
|
@ -151,9 +151,7 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
size_t
|
||||
MediaEngineWebRTCVideoSource::NumCapabilities()
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 uniqueId(mUniqueId); // TODO: optimize this?
|
||||
|
||||
int num = mViECapture->NumberOfCapabilities(uniqueId.get(), kMaxUniqueIdLength);
|
||||
int num = mViECapture->NumberOfCapabilities(GetUUID().get(), kMaxUniqueIdLength);
|
||||
if (num > 0) {
|
||||
return num;
|
||||
}
|
||||
@ -205,8 +203,7 @@ MediaEngineWebRTCVideoSource::GetCapability(size_t aIndex,
|
||||
if (!mHardcodedCapabilities.IsEmpty()) {
|
||||
MediaEngineCameraVideoSource::GetCapability(aIndex, aOut);
|
||||
}
|
||||
NS_ConvertUTF16toUTF8 uniqueId(mUniqueId); // TODO: optimize this?
|
||||
mViECapture->GetCaptureCapability(uniqueId.get(), kMaxUniqueIdLength, aIndex, aOut);
|
||||
mViECapture->GetCaptureCapability(GetUUID().get(), kMaxUniqueIdLength, aIndex, aOut);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -221,7 +218,7 @@ MediaEngineWebRTCVideoSource::Allocate(const dom::MediaTrackConstraints &aConstr
|
||||
if (!ChooseCapability(aConstraints, aPrefs)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (mViECapture->AllocateCaptureDevice(NS_ConvertUTF16toUTF8(mUniqueId).get(),
|
||||
if (mViECapture->AllocateCaptureDevice(GetUUID().get(),
|
||||
kMaxUniqueIdLength, mCaptureIndex)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -387,9 +384,8 @@ MediaEngineWebRTCVideoSource::Init()
|
||||
uniqueId, kMaxUniqueIdLength)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(deviceName, mDeviceName);
|
||||
CopyUTF8toUTF16(uniqueId, mUniqueId);
|
||||
SetName(NS_ConvertUTF8toUTF16(deviceName));
|
||||
SetUUID(uniqueId);
|
||||
|
||||
mInitDone = true;
|
||||
}
|
||||
@ -443,11 +439,9 @@ void MediaEngineWebRTCVideoSource::Refresh(int aIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(deviceName, mDeviceName);
|
||||
SetName(NS_ConvertUTF8toUTF16(deviceName));
|
||||
#ifdef DEBUG
|
||||
nsString temp;
|
||||
CopyUTF8toUTF16(uniqueId, temp);
|
||||
MOZ_ASSERT(temp.Equals(mUniqueId));
|
||||
MOZ_ASSERT(GetUUID().Equals(uniqueId));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "BroadcastChannelChild.h"
|
||||
#include "ServiceWorkerManagerChild.h"
|
||||
#include "FileDescriptorSetChild.h"
|
||||
#include "mozilla/media/MediaChild.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/PBlobChild.h"
|
||||
#include "mozilla/dom/cache/ActorUtils.h"
|
||||
@ -329,18 +328,6 @@ BackgroundChildImpl::DeallocPCacheStreamControlChild(PCacheStreamControlChild* a
|
||||
return true;
|
||||
}
|
||||
|
||||
media::PMediaChild*
|
||||
BackgroundChildImpl::AllocPMediaChild()
|
||||
{
|
||||
return media::AllocPMediaChild();
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundChildImpl::DeallocPMediaChild(media::PMediaChild *aActor)
|
||||
{
|
||||
return media::DeallocPMediaChild(aActor);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MessageChannel/MessagePort API
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -71,12 +71,6 @@ protected:
|
||||
virtual bool
|
||||
DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) override;
|
||||
|
||||
virtual PMediaChild*
|
||||
AllocPMediaChild() override;
|
||||
|
||||
virtual bool
|
||||
DeallocPMediaChild(PMediaChild* aActor) override;
|
||||
|
||||
virtual PVsyncChild*
|
||||
AllocPVsyncChild() override;
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "BroadcastChannelParent.h"
|
||||
#include "FileDescriptorSetParent.h"
|
||||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/AppProcessChecker.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
@ -494,18 +493,6 @@ BackgroundParentImpl::DeallocPServiceWorkerManagerParent(
|
||||
return true;
|
||||
}
|
||||
|
||||
media::PMediaParent*
|
||||
BackgroundParentImpl::AllocPMediaParent()
|
||||
{
|
||||
return media::AllocPMediaParent();
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundParentImpl::DeallocPMediaParent(media::PMediaParent *aActor)
|
||||
{
|
||||
return media::DeallocPMediaParent(aActor);
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar()
|
||||
{
|
||||
|
@ -92,12 +92,6 @@ protected:
|
||||
virtual bool
|
||||
DeallocPServiceWorkerManagerParent(PServiceWorkerManagerParent* aActor) override;
|
||||
|
||||
virtual PMediaParent*
|
||||
AllocPMediaParent() override;
|
||||
|
||||
virtual bool
|
||||
DeallocPMediaParent(PMediaParent* aActor) override;
|
||||
|
||||
virtual bool
|
||||
RecvShutdownServiceWorkerRegistrar() override;
|
||||
|
||||
|
@ -11,7 +11,6 @@ include protocol PCacheStorage;
|
||||
include protocol PCacheStreamControl;
|
||||
include protocol PFileDescriptorSet;
|
||||
include protocol PMessagePort;
|
||||
include protocol PMedia;
|
||||
include protocol PServiceWorkerManager;
|
||||
include protocol PUDPSocket;
|
||||
include protocol PVsync;
|
||||
@ -37,7 +36,6 @@ sync protocol PBackground
|
||||
manages PCacheStreamControl;
|
||||
manages PFileDescriptorSet;
|
||||
manages PMessagePort;
|
||||
manages PMedia;
|
||||
manages PServiceWorkerManager;
|
||||
manages PUDPSocket;
|
||||
manages PVsync;
|
||||
@ -49,7 +47,6 @@ parent:
|
||||
PBackgroundIDBFactory(LoggingInfo loggingInfo);
|
||||
|
||||
PVsync();
|
||||
PMedia();
|
||||
|
||||
PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter);
|
||||
PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel,
|
||||
|
Loading…
Reference in New Issue
Block a user