mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changesets d8d01c95be03 and 5fa0c8f5ccb2 (bug 907352) for Linux64 mochitest-3 crashes.
This commit is contained in:
parent
e12bca044a
commit
d503f72d54
@ -711,12 +711,14 @@ SpeechRecognition::Start(ErrorResult& aRv)
|
||||
rv = mRecognitionService->Initialize(this->asWeakPtr());
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
MediaStreamConstraints constraints;
|
||||
constraints.mAudio.SetAsBoolean() = true;
|
||||
|
||||
if (!mTestConfig.mFakeFSMEvents) {
|
||||
MediaManager* manager = MediaManager::Get();
|
||||
manager->GetUserMedia(false,
|
||||
manager->GetUserMedia(cx,
|
||||
false,
|
||||
GetOwner(),
|
||||
constraints,
|
||||
new GetUserMediaSuccessCallback(this),
|
||||
|
@ -1294,7 +1294,8 @@ Navigator::SendBeacon(const nsAString& aUrl,
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
void
|
||||
Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
Navigator::MozGetUserMedia(JSContext* aCx,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
NavigatorUserMediaSuccessCallback& aOnSuccess,
|
||||
NavigatorUserMediaErrorCallback& aOnError,
|
||||
ErrorResult& aRv)
|
||||
@ -1317,12 +1318,12 @@ Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
bool privileged = nsContentUtils::IsChromeDoc(mWindow->GetExtantDoc());
|
||||
|
||||
MediaManager* manager = MediaManager::Get();
|
||||
aRv = manager->GetUserMedia(privileged, mWindow, aConstraints,
|
||||
aRv = manager->GetUserMedia(aCx, privileged, mWindow, aConstraints,
|
||||
onsuccess, onerror);
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
|
||||
Navigator::MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstraints,
|
||||
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
|
||||
NavigatorUserMediaErrorCallback& aOnError,
|
||||
uint64_t aInnerWindowID,
|
||||
|
@ -33,6 +33,7 @@ namespace dom {
|
||||
class Geolocation;
|
||||
class systemMessageCallback;
|
||||
class MediaStreamConstraints;
|
||||
class MediaStreamConstraintsInternal;
|
||||
class WakeLock;
|
||||
class ArrayBufferViewOrBlobOrStringOrFormData;
|
||||
}
|
||||
@ -230,11 +231,12 @@ public:
|
||||
ErrorResult& aRv);
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
void MozGetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
void MozGetUserMedia(JSContext* aCx,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
NavigatorUserMediaSuccessCallback& aOnSuccess,
|
||||
NavigatorUserMediaErrorCallback& aOnError,
|
||||
ErrorResult& aRv);
|
||||
void MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
|
||||
void MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstraints,
|
||||
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
|
||||
NavigatorUserMediaErrorCallback& aOnError,
|
||||
uint64_t aInnerWindowID,
|
||||
|
@ -16,12 +16,12 @@ namespace dom {
|
||||
GetUserMediaRequest::GetUserMediaRequest(
|
||||
nsPIDOMWindow* aInnerWindow,
|
||||
const nsAString& aCallID,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
bool aIsSecure)
|
||||
: mInnerWindowID(aInnerWindow->WindowID())
|
||||
, mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID())
|
||||
, mCallID(aCallID)
|
||||
, mConstraints(new MediaStreamConstraints(aConstraints))
|
||||
, mConstraints(new MediaStreamConstraintsInternal(aConstraints))
|
||||
, mIsSecure(aIsSecure)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
@ -67,7 +67,7 @@ bool GetUserMediaRequest::IsSecure()
|
||||
}
|
||||
|
||||
void
|
||||
GetUserMediaRequest::GetConstraints(MediaStreamConstraints &result)
|
||||
GetUserMediaRequest::GetConstraints(MediaStreamConstraintsInternal &result)
|
||||
{
|
||||
result = *mConstraints;
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class MediaStreamConstraints;
|
||||
class MediaStreamConstraintsInternal;
|
||||
|
||||
class GetUserMediaRequest : public nsISupports, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
GetUserMediaRequest(nsPIDOMWindow* aInnerWindow,
|
||||
const nsAString& aCallID,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
bool aIsSecure);
|
||||
virtual ~GetUserMediaRequest() {};
|
||||
|
||||
@ -36,12 +36,12 @@ public:
|
||||
uint64_t InnerWindowID();
|
||||
bool IsSecure();
|
||||
void GetCallID(nsString& retval);
|
||||
void GetConstraints(MediaStreamConstraints &result);
|
||||
void GetConstraints(MediaStreamConstraintsInternal &result);
|
||||
|
||||
private:
|
||||
uint64_t mInnerWindowID, mOuterWindowID;
|
||||
const nsString mCallID;
|
||||
nsAutoPtr<MediaStreamConstraints> mConstraints;
|
||||
nsAutoPtr<MediaStreamConstraintsInternal> mConstraints;
|
||||
bool mIsSecure;
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
@ -75,11 +74,53 @@ GetMediaManagerLog()
|
||||
#endif
|
||||
|
||||
using dom::MediaStreamConstraints; // Outside API (contains JSObject)
|
||||
using dom::MediaStreamConstraintsInternal; // Storable supported constraints
|
||||
using dom::MediaTrackConstraintsInternal; // Video or audio constraints
|
||||
using dom::MediaTrackConstraintSet; // Mandatory or optional constraints
|
||||
using dom::MediaTrackConstraints; // Raw mMandatory (as JSObject)
|
||||
using dom::GetUserMediaRequest;
|
||||
using dom::Sequence;
|
||||
using dom::OwningBooleanOrMediaTrackConstraints;
|
||||
using dom::OwningBooleanOrMediaTrackConstraintsInternal;
|
||||
|
||||
// Used to compare raw MediaTrackConstraintSet against normalized dictionary
|
||||
// version to detect member differences, e.g. unsupported constraints.
|
||||
|
||||
static nsresult CompareDictionaries(JSContext* aCx, JSObject *aA,
|
||||
const MediaTrackConstraintSet &aB,
|
||||
nsString *aDifference)
|
||||
{
|
||||
JS::Rooted<JSObject*> a(aCx, aA);
|
||||
JSAutoCompartment ac(aCx, aA);
|
||||
JS::Rooted<JS::Value> bval(aCx);
|
||||
aB.ToObject(aCx, &bval);
|
||||
JS::Rooted<JSObject*> b(aCx, &bval.toObject());
|
||||
|
||||
// Iterate over each property in A, and check if it is in B
|
||||
|
||||
JS::AutoIdArray props(aCx, JS_Enumerate(aCx, a));
|
||||
|
||||
for (size_t i = 0; i < props.length(); i++) {
|
||||
JS::Rooted<JS::Value> bprop(aCx);
|
||||
JS::Rooted<jsid> id(aCx, props[i]);
|
||||
if (!JS_GetPropertyById(aCx, b, id, &bprop)) {
|
||||
LOG(("Error parsing dictionary!\n"));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (bprop.isUndefined()) {
|
||||
// Unknown property found in A. Bail with name
|
||||
JS::Rooted<JS::Value> nameval(aCx);
|
||||
bool success = JS_IdToValue(aCx, props[i], &nameval);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_UNEXPECTED);
|
||||
|
||||
JS::Rooted<JSString*> namestr(aCx, JS::ToString(aCx, nameval));
|
||||
NS_ENSURE_TRUE(namestr, NS_ERROR_UNEXPECTED);
|
||||
aDifference->Assign(JS_GetStringCharsZ(aCx, namestr));
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
aDifference->Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ErrorCallbackRunnable::ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
@ -631,34 +672,25 @@ private:
|
||||
};
|
||||
|
||||
static bool
|
||||
IsOn(const dom::OwningBooleanOrMediaTrackConstraints &aUnion) {
|
||||
IsOn(const dom::OwningBooleanOrMediaTrackConstraintsInternal &aUnion) {
|
||||
return !aUnion.IsBoolean() || aUnion.GetAsBoolean();
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
GetMandatoryJSObj(const dom::OwningBooleanOrMediaTrackConstraints &aUnion) {
|
||||
return (aUnion.IsMediaTrackConstraints() &&
|
||||
aUnion.GetAsMediaTrackConstraints().mMandatory.WasPassed()) ?
|
||||
aUnion.GetAsMediaTrackConstraints().mMandatory.Value() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper functions that implement the constraints algorithm from
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
|
||||
*/
|
||||
|
||||
#define lengthof(a) (sizeof(a) / sizeof(*a))
|
||||
|
||||
static auto
|
||||
GetSupportedConstraintNames(const MediaEngineVideoSource *) ->
|
||||
decltype((dom::SupportedVideoConstraintsValues::strings)) {
|
||||
return dom::SupportedVideoConstraintsValues::strings;
|
||||
}
|
||||
|
||||
static auto
|
||||
GetSupportedConstraintNames(const MediaEngineAudioSource *) ->
|
||||
decltype((dom::SupportedAudioConstraintsValues::strings)) {
|
||||
return dom::SupportedAudioConstraintsValues::strings;
|
||||
}
|
||||
|
||||
// Reminder: add handling for new constraints both here and in GetSources below!
|
||||
|
||||
static bool SatisfyConstraintSet(const MediaEngineVideoSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
static bool SatisfyConstraint(const MediaEngineVideoSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
{
|
||||
if (aConstraints.mFacingMode.WasPassed()) {
|
||||
nsString s;
|
||||
@ -672,42 +704,14 @@ static bool SatisfyConstraintSet(const MediaEngineVideoSource *,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SatisfyConstraintSet(const MediaEngineAudioSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
static bool SatisfyConstraint(const MediaEngineAudioSource *,
|
||||
const MediaTrackConstraintSet &aConstraints,
|
||||
nsIMediaDevice &aCandidate)
|
||||
{
|
||||
// TODO: Add audio-specific constraints
|
||||
return true;
|
||||
}
|
||||
|
||||
// Triage constraints into required and nonrequired + detect missing requireds
|
||||
|
||||
class TriageHelper
|
||||
{
|
||||
public:
|
||||
TriageHelper(const nsTArray<nsString>& aRequire)
|
||||
: mRequire(aRequire)
|
||||
, mNumRequirementsMet(0) {}
|
||||
|
||||
MediaTrackConstraintSet& Triage(const nsAString &name) {
|
||||
if (mRequire.IndexOf(name) != mRequire.NoIndex) {
|
||||
mNumRequirementsMet++;
|
||||
return mRequired;
|
||||
} else {
|
||||
return mNonrequired;
|
||||
}
|
||||
}
|
||||
bool RequirementsAreMet() {
|
||||
MOZ_ASSERT(mNumRequirementsMet <= mRequire.Length());
|
||||
return mNumRequirementsMet == mRequire.Length();
|
||||
}
|
||||
MediaTrackConstraintSet mRequired;
|
||||
MediaTrackConstraintSet mNonrequired;
|
||||
private:
|
||||
const nsTArray<nsString> mRequire;
|
||||
uint32_t mNumRequirementsMet;
|
||||
};
|
||||
|
||||
typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
|
||||
|
||||
// Source getter that constrains list returned
|
||||
@ -715,7 +719,7 @@ typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
|
||||
template<class SourceType>
|
||||
static SourceSet *
|
||||
GetSources(MediaEngine *engine,
|
||||
const OwningBooleanOrMediaTrackConstraints &aConstraints,
|
||||
const OwningBooleanOrMediaTrackConstraintsInternal &aConstraints,
|
||||
void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*),
|
||||
char* media_device_name = nullptr)
|
||||
{
|
||||
@ -755,69 +759,24 @@ static SourceSet *
|
||||
}
|
||||
}
|
||||
|
||||
// If unconstrained then return the full list.
|
||||
|
||||
if (aConstraints.IsBoolean()) {
|
||||
MOZ_ASSERT(aConstraints.GetAsBoolean());
|
||||
result->MoveElementsFrom(candidateSet);
|
||||
return result.forget();
|
||||
}
|
||||
auto& constraints = aConstraints.GetAsMediaTrackConstraintsInternal();
|
||||
|
||||
// Otherwise apply constraints to the list of sources.
|
||||
// Then apply mandatory constraints
|
||||
|
||||
auto& constraints = aConstraints.GetAsMediaTrackConstraints();
|
||||
const nsTArray<nsString> empty;
|
||||
const auto &require = constraints.mRequire.WasPassed()?
|
||||
constraints.mRequire.Value() : empty;
|
||||
{
|
||||
// Check upfront the names of required constraints that are unsupported for
|
||||
// this media-type. The spec requires these to fail, so getting them out of
|
||||
// the way early provides a necessary invariant for the remaining algorithm
|
||||
// which maximizes code-reuse by ignoring constraints of the other type
|
||||
// (specifically, SatisfyConstraintSet is reused for the advanced algorithm
|
||||
// where the spec requires it to ignore constraints of the other type)
|
||||
|
||||
const auto& supported = GetSupportedConstraintNames(type);
|
||||
for (uint32_t i = 0; i < require.Length(); i++) {
|
||||
bool found = false;
|
||||
// EnumType arrays have a zero-terminator entry at the end. Skip.
|
||||
for (size_t j = 0; j < sizeof(supported)/sizeof(*supported) - 1; j++) {
|
||||
if (require[i].EqualsASCII(supported[j].value)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return result.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Before we start, triage constraints into required and nonrequired.
|
||||
// Reminder: add handling for new constraints both here & SatisfyConstraintSet
|
||||
|
||||
TriageHelper helper(require);
|
||||
|
||||
if (constraints.mFacingMode.WasPassed()) {
|
||||
helper.Triage(NS_LITERAL_STRING("facingMode")).mFacingMode.Construct(
|
||||
constraints.mFacingMode.Value());
|
||||
}
|
||||
if (!helper.RequirementsAreMet()) {
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
// Now on to the actual algorithm: First apply required constraints.
|
||||
|
||||
for (uint32_t i = 0; i < candidateSet.Length();) {
|
||||
// Note: Iterator must be signed as it can dip below zero
|
||||
for (int i = 0; i < int(candidateSet.Length()); i++) {
|
||||
// Overloading instead of template specialization keeps things local
|
||||
if (!SatisfyConstraintSet(type, helper.mRequired, *candidateSet[i])) {
|
||||
candidateSet.RemoveElementAt(i);
|
||||
} else {
|
||||
++i;
|
||||
if (!SatisfyConstraint(type, constraints.mMandatory, *candidateSet[i])) {
|
||||
candidateSet.RemoveElementAt(i--);
|
||||
}
|
||||
}
|
||||
|
||||
// Then apply advanced (formerly known as optional) constraints.
|
||||
// Then apply optional constraints.
|
||||
//
|
||||
// These are only effective when there are multiple sources to pick from.
|
||||
// Spec as-of-this-writing says to run algorithm on "all possible tracks
|
||||
@ -833,26 +792,21 @@ static SourceSet *
|
||||
|
||||
SourceSet tailSet;
|
||||
|
||||
if (constraints.mAdvanced.WasPassed()) {
|
||||
const auto &array = constraints.mAdvanced.Value();
|
||||
if (constraints.mOptional.WasPassed()) {
|
||||
const auto &array = constraints.mOptional.Value();
|
||||
for (int i = 0; i < int(array.Length()); i++) {
|
||||
SourceSet rejects;
|
||||
for (uint32_t j = 0; j < candidateSet.Length();) {
|
||||
if (!SatisfyConstraintSet(type, array[i], *candidateSet[j])) {
|
||||
// Note: Iterator must be signed as it can dip below zero
|
||||
for (int j = 0; j < int(candidateSet.Length()); j++) {
|
||||
if (!SatisfyConstraint(type, array[i], *candidateSet[j])) {
|
||||
rejects.AppendElement(candidateSet[j]);
|
||||
candidateSet.RemoveElementAt(j);
|
||||
} else {
|
||||
++j;
|
||||
candidateSet.RemoveElementAt(j--);
|
||||
}
|
||||
}
|
||||
(candidateSet.Length()? tailSet : candidateSet).MoveElementsFrom(rejects);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, order any remaining sources by how many nonrequired constraints
|
||||
// they satisfy. TODO(jib): TBD once we implement >1 constraint (Bug 907352)
|
||||
|
||||
|
||||
result->MoveElementsFrom(candidateSet);
|
||||
result->MoveElementsFrom(tailSet);
|
||||
return result.forget();
|
||||
@ -871,7 +825,7 @@ class GetUserMediaRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetUserMediaRunnable(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
@ -892,7 +846,7 @@ public:
|
||||
* using the one provided by MediaManager::GetBackend.
|
||||
*/
|
||||
GetUserMediaRunnable(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
@ -998,7 +952,7 @@ public:
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetContraints(const MediaStreamConstraints& aConstraints)
|
||||
SetContraints(const MediaStreamConstraintsInternal& aConstraints)
|
||||
{
|
||||
mConstraints = aConstraints;
|
||||
return NS_OK;
|
||||
@ -1127,7 +1081,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
MediaStreamConstraints mConstraints;
|
||||
MediaStreamConstraintsInternal mConstraints;
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
@ -1153,7 +1107,7 @@ class GetUserMediaDevicesRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
GetUserMediaDevicesRunnable(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowId, char* aAudioLoopbackDev, char* aVideoLoopbackDev)
|
||||
@ -1194,7 +1148,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
MediaStreamConstraints mConstraints;
|
||||
MediaStreamConstraintsInternal mConstraints;
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
@ -1340,8 +1294,8 @@ MediaManager::NotifyRecordingStatusChange(nsPIDOMWindow* aWindow,
|
||||
* for handling all incoming getUserMedia calls from every window.
|
||||
*/
|
||||
nsresult
|
||||
MediaManager::GetUserMedia(bool aPrivileged,
|
||||
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints,
|
||||
MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged,
|
||||
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aRawConstraints,
|
||||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError)
|
||||
{
|
||||
@ -1354,6 +1308,42 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
|
||||
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
JS::Rooted<JSObject*> audioObj (aCx, GetMandatoryJSObj(aRawConstraints.mAudio));
|
||||
JS::Rooted<JSObject*> videoObj (aCx, GetMandatoryJSObj(aRawConstraints.mVideo));
|
||||
if (audioObj || videoObj) {
|
||||
ac.construct(aCx, audioObj? audioObj : videoObj);
|
||||
}
|
||||
|
||||
// aRawConstraints may have JSObject in mMandatory, so copy everything into
|
||||
// MediaStreamConstraintsInternal which does not.
|
||||
|
||||
dom::RootedDictionary<MediaStreamConstraintsInternal> c(aCx);
|
||||
JS::Rooted<JS::Value> temp(aCx);
|
||||
// This isn't the fastest way to copy a MediaStreamConstraints into a
|
||||
// MediaStreamConstraintsInternal, but requires less code maintenance than an
|
||||
// explicit member-by-member copy, and should be safe given the circumstances.
|
||||
aRawConstraints.ToObject(aCx, &temp);
|
||||
bool success = c.Init(aCx, temp);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
||||
|
||||
// Validate mandatory constraints by detecting any unknown constraints.
|
||||
// Done by comparing the raw MediaTrackConstraints against the normalized copy
|
||||
|
||||
nsString unknownConstraintFound;
|
||||
if (audioObj) {
|
||||
nsresult rv = CompareDictionaries(aCx, audioObj,
|
||||
c.mAudio.GetAsMediaTrackConstraintsInternal().mMandatory,
|
||||
&unknownConstraintFound);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (videoObj) {
|
||||
nsresult rv = CompareDictionaries(aCx, videoObj,
|
||||
c.mVideo.GetAsMediaTrackConstraintsInternal().mMandatory,
|
||||
&unknownConstraintFound);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we were asked to get a picture, before getting a snapshot, we check if
|
||||
* the calling page is allowed to open a popup. We do this because
|
||||
@ -1404,6 +1394,23 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
GetActiveWindows()->Put(windowID, listeners);
|
||||
}
|
||||
|
||||
if (!unknownConstraintFound.IsEmpty()) {
|
||||
// An unsupported mandatory constraint was found.
|
||||
//
|
||||
// We continue to ignore these for now, because we implement just
|
||||
// facingMode, which means all existing uses of mandatory width/height would
|
||||
// fail on Firefox only otherwise, which is undesirable.
|
||||
//
|
||||
// There's also basis for always ignoring them in a new proposal.
|
||||
// TODO(jib): This is a super-low-risk fix for backport. Clean up later.
|
||||
|
||||
LOG(("Unsupported mandatory constraint: %s\n",
|
||||
NS_ConvertUTF16toUTF8(unknownConstraintFound).get()));
|
||||
|
||||
// unknown constraints existed in aRawConstraints only, which is unused
|
||||
// from here, so continuing here effectively ignores them, as is desired.
|
||||
}
|
||||
|
||||
// Ensure there's a thread for gum to proxy to off main thread
|
||||
nsIThread *mediaThread = MediaManager::GetThread();
|
||||
|
||||
@ -1414,8 +1421,6 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
// No need for locking because we always do this in the main thread.
|
||||
listeners->AppendElement(listener);
|
||||
|
||||
MediaStreamConstraints c(aConstraints); // copy
|
||||
|
||||
// Developer preference for turning off permission check.
|
||||
if (Preferences::GetBool("media.navigator.permission.disabled", false)) {
|
||||
aPrivileged = true;
|
||||
@ -1424,30 +1429,6 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
c.mVideo.SetAsBoolean() = false;
|
||||
}
|
||||
|
||||
#if defined(ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||
// Be backwards compatible only on mobile and only for facingMode.
|
||||
if (c.mVideo.IsMediaTrackConstraints()) {
|
||||
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
|
||||
|
||||
if (!tc.mRequire.WasPassed()) {
|
||||
if (tc.mMandatory.mFacingMode.WasPassed() && !tc.mFacingMode.WasPassed()) {
|
||||
tc.mFacingMode.Construct(tc.mMandatory.mFacingMode.Value());
|
||||
tc.mRequire.Construct().AppendElement(NS_LITERAL_STRING("facingMode"));
|
||||
}
|
||||
}
|
||||
if (tc.mOptional.WasPassed() && !tc.mAdvanced.WasPassed()) {
|
||||
tc.mAdvanced.Construct();
|
||||
for (uint32_t i = 0; i < tc.mOptional.Value().Length(); i++) {
|
||||
if (tc.mOptional.Value()[i].mFacingMode.WasPassed()) {
|
||||
MediaTrackConstraintSet n;
|
||||
n.mFacingMode.Construct(tc.mOptional.Value()[i].mFacingMode.Value());
|
||||
tc.mAdvanced.Value().AppendElement(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pass callbacks and MediaStreamListener along to GetUserMediaRunnable.
|
||||
nsRefPtr<GetUserMediaRunnable> runnable;
|
||||
if (c.mFake) {
|
||||
@ -1578,7 +1559,7 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
|
||||
nsresult
|
||||
MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
const MediaStreamConstraintsInternal& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError,
|
||||
uint64_t aInnerWindowID)
|
||||
|
@ -495,14 +495,14 @@ public:
|
||||
void RemoveFromWindowList(uint64_t aWindowID,
|
||||
GetUserMediaCallbackMediaStreamListener *aListener);
|
||||
|
||||
nsresult GetUserMedia(bool aPrivileged,
|
||||
nsresult GetUserMedia(JSContext* aCx, bool aPrivileged,
|
||||
nsPIDOMWindow* aWindow,
|
||||
const dom::MediaStreamConstraints& aRawConstraints,
|
||||
nsIDOMGetUserMediaSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError);
|
||||
|
||||
nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const dom::MediaStreamConstraints& aConstraints,
|
||||
const dom::MediaStreamConstraintsInternal& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* onError,
|
||||
uint64_t aInnerWindowID = 0);
|
||||
|
@ -176,7 +176,7 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
|
||||
nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
||||
: mRequest(aRequest)
|
||||
{
|
||||
dom::MediaStreamConstraints constraints;
|
||||
dom::MediaStreamConstraintsInternal constraints;
|
||||
mRequest->GetConstraints(constraints);
|
||||
|
||||
mAudio = !constraints.mAudio.IsBoolean() || constraints.mAudio.GetAsBoolean();
|
||||
@ -578,7 +578,7 @@ MediaPermissionManager::HandleRequest(nsRefPtr<dom::GetUserMediaRequest> &req)
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError =
|
||||
new MediaDeviceErrorCallback(callID);
|
||||
|
||||
dom::MediaStreamConstraints constraints;
|
||||
dom::MediaStreamConstraintsInternal constraints;
|
||||
req->GetConstraints(constraints);
|
||||
|
||||
nsRefPtr<MediaManager> MediaMgr = MediaManager::GetInstance();
|
||||
|
@ -1,78 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
Tests covering gUM constraints API for audio, video and fake video. Exercise
|
||||
successful parsing code and ensure that unknown required constraints and
|
||||
overconstraining cases produce appropriate errors.
|
||||
|
||||
TODO(jib): Merge desktop and mobile version of these tests again.
|
||||
*/
|
||||
var common_tests = [
|
||||
// Each test here tests a different constraint or codepath.
|
||||
{ message: "unknown required constraint on video fails",
|
||||
constraints: { video: { somethingUnknown:0, require:["somethingUnknown"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "unknown required constraint on audio fails",
|
||||
constraints: { audio: { somethingUnknown:0, require:["somethingUnknown"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "missing required constraint on video fails",
|
||||
constraints: { video: { require:["facingMode"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "missing required constraint on audio fails",
|
||||
constraints: { audio: { require:["facingMode"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "video overconstrained by facingMode fails",
|
||||
constraints: { video: { facingMode:'left', require:["facingMode"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "audio overconstrained by facingMode fails",
|
||||
constraints: { audio: { facingMode:'left', require:["facingMode"] } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
|
||||
constraints: { fake: true,
|
||||
audio: { facingMode:'left',
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ bar:0 }] },
|
||||
video: { // TODO: Bug 767924 sequences in unions
|
||||
//facingMode:['left', 'right', 'user', 'environment'],
|
||||
//require:["facingMode"],
|
||||
facingMode:'left',
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ bar:0 }] } },
|
||||
error: null }
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Starts the test run by running through each constraint
|
||||
* test by verifying that the right callback and error message is fired.
|
||||
*/
|
||||
|
||||
function testConstraints(tests) {
|
||||
var i = 0;
|
||||
next();
|
||||
|
||||
function Success() {
|
||||
ok(!tests[i].error, tests[i].message);
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function Failure(err) {
|
||||
ok(tests[i].error? (err === tests[i].error) : false,
|
||||
tests[i].message + " (err=" + err + ")");
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function next() {
|
||||
if (i < tests.length) {
|
||||
navigator.mozGetUserMedia(tests[i].constraints, Success, Failure);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
};
|
@ -1,7 +1,6 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
constraints.js
|
||||
mediaStreamPlayback.js
|
||||
pc.js
|
||||
templates.js
|
||||
@ -26,9 +25,6 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_getUserMedia_basicVideoAudio.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure, turned an intermittent (bug 962579) into a permanant orange
|
||||
[test_getUserMedia_constraints.html]
|
||||
skip-if = (toolkit=='gonk' || toolkit=='android') # Bug 907352, backwards-compatible behavior on mobile only
|
||||
[test_getUserMedia_constraints_mobile.html]
|
||||
skip-if = (toolkit!='gonk' && toolkit!='android') # Bug 907352, backwards-compatible behavior on mobile only
|
||||
[test_getUserMedia_exceptions.html]
|
||||
[test_getUserMedia_gumWithinGum.html]
|
||||
[test_getUserMedia_playAudioTwice.html]
|
||||
|
@ -9,10 +9,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882145
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="constraints.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=882145">Test mozGetUserMedia Constraints (desktop)</a>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=882145">Test mozGetUserMedia Constraints</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
@ -20,17 +19,67 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882145
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
See constraints.js for testConstraints() and common_tests.
|
||||
TODO(jib): Merge desktop and mobile version of these tests again (Bug 997365)
|
||||
Tests covering gUM constraints API for audio, video and fake video. Exercise
|
||||
successful parsing code and ensure that unknown mandatory constraints and
|
||||
overconstraining cases produce appropriate errors.
|
||||
*/
|
||||
var desktop_tests = [
|
||||
{ message: "legacy facingMode ignored (desktop)",
|
||||
constraints: { fake: true, video: { mandatory: { facingMode:'left' } } },
|
||||
error: null },
|
||||
var tests = [
|
||||
// Each test here tests a different constraint or codepath.
|
||||
{ message: "video overconstrained by facingMode fails",
|
||||
constraints: { video: { mandatory: { facingMode:'left' } } },
|
||||
error: "NO_DEVICES_FOUND",
|
||||
pass: false },
|
||||
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
|
||||
constraints: { fake: true,
|
||||
audio: { mandatory: { facingMode:'left' } },
|
||||
video: { mandatory: { somethingUnknown:0 },
|
||||
optional: [{ facingMode:'left' },
|
||||
{ facingMode:'right' },
|
||||
{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ foo:0 }] } },
|
||||
error: null,
|
||||
pass: false },
|
||||
{ message: null },
|
||||
];
|
||||
|
||||
/**
|
||||
* Starts the test run by running through each constraint
|
||||
* test by verifying that the right callback and error message is fired.
|
||||
*/
|
||||
|
||||
runTest(function () {
|
||||
testConstraints(common_tests.concat(desktop_tests));
|
||||
var i = 0;
|
||||
next();
|
||||
|
||||
function Success() {
|
||||
info("successcallback");
|
||||
tests[i].pass = !tests[i].error;
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function Failure(err) {
|
||||
info("errcallback: " + err);
|
||||
tests[i].pass = tests[i].error? (err === tests[i].error) : false;
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function next() {
|
||||
if (tests[i].message) {
|
||||
navigator.mozGetUserMedia(tests[i].constraints, Success, Failure);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
function finish() {
|
||||
tests.forEach(function (test) {
|
||||
if (test.message) {
|
||||
ok(test.pass, test.message);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=882145
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test mozGetUserMedia Constraints</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="constraints.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=882145">Test mozGetUserMedia Constraints (mobile)</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
See constraints.js for testConstraints() and common_tests.
|
||||
TODO(jib): Merge desktop and mobile version of these tests again (Bug 997365)
|
||||
*/
|
||||
var mobile_tests = [
|
||||
{ message: "legacy facingMode overconstrains video (mobile)",
|
||||
constraints: { video: { mandatory: { facingMode:'left' } } },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
];
|
||||
|
||||
runTest(function () {
|
||||
testConstraints(common_tests.concat(mobile_tests));
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -49,7 +49,7 @@ var exceptionTests = [
|
||||
message: "wrong object type as third parameter" },
|
||||
|
||||
// Each test here verifies constraint syntax as defined in webidl
|
||||
{ params: [{ fake: true, video: { advanced: [{ facingMode:'foo' }] } },
|
||||
{ params: [{ fake: true, video: { optional: [{ facingMode:'foo' }] } },
|
||||
unexpectedCall, unexpectedCall],
|
||||
error: "'facingMode' member of MediaTrackConstraintSet 'foo' is not a valid value for enumeration VideoFacingModeEnum.",
|
||||
message: "invalid facingMode enum value" }
|
||||
|
@ -11,6 +11,6 @@ interface GetUserMediaRequest {
|
||||
readonly attribute unsigned long long windowID;
|
||||
readonly attribute unsigned long long innerWindowID;
|
||||
readonly attribute DOMString callID;
|
||||
MediaStreamConstraints getConstraints();
|
||||
MediaStreamConstraintsInternal getConstraints();
|
||||
readonly attribute boolean isSecure;
|
||||
};
|
||||
|
@ -16,8 +16,15 @@
|
||||
dictionary MediaStreamConstraints {
|
||||
(boolean or MediaTrackConstraints) audio = false;
|
||||
(boolean or MediaTrackConstraints) video = false;
|
||||
boolean picture = false; // Mozilla legacy
|
||||
boolean fake = false; // for testing
|
||||
boolean picture = false;
|
||||
boolean fake = false;
|
||||
};
|
||||
|
||||
dictionary MediaStreamConstraintsInternal {
|
||||
(boolean or MediaTrackConstraintsInternal) audio;
|
||||
(boolean or MediaTrackConstraintsInternal) video;
|
||||
boolean picture = false;
|
||||
boolean fake = false;
|
||||
};
|
||||
|
||||
interface MediaStream {
|
||||
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
// Important! Do not ever add members that might need tracing (e.g. object)
|
||||
// to MediaTrackConstraintSet
|
||||
// to MediaTrackConstraintSet or any dictionary marked XxxInternal here
|
||||
|
||||
enum VideoFacingModeEnum {
|
||||
"user",
|
||||
@ -20,34 +20,26 @@ enum VideoFacingModeEnum {
|
||||
"right"
|
||||
};
|
||||
|
||||
enum SupportedVideoConstraints {
|
||||
"facingMode"
|
||||
};
|
||||
|
||||
enum SupportedAudioConstraints {
|
||||
"dummy"
|
||||
};
|
||||
|
||||
dictionary MediaTrackConstraintSet {
|
||||
ConstrainVideoFacingMode facingMode;
|
||||
};
|
||||
|
||||
dictionary MobileLegacyMediaTrackConstraintSet {
|
||||
VideoFacingModeEnum facingMode;
|
||||
};
|
||||
|
||||
dictionary MediaTrackConstraints : MediaTrackConstraintSet {
|
||||
sequence<DOMString> require;
|
||||
sequence<MediaTrackConstraintSet> advanced;
|
||||
// MediaTrackConstraint = single-property-subset of MediaTrackConstraintSet
|
||||
// Implemented as full set. Test Object.keys(pair).length == 1
|
||||
|
||||
// mobile-only backwards-compatibility for facingMode
|
||||
MobileLegacyMediaTrackConstraintSet mandatory;
|
||||
sequence<MobileLegacyMediaTrackConstraintSet> _optional;
|
||||
// typedef MediaTrackConstraintSet MediaTrackConstraint; // TODO: Bug 913053
|
||||
|
||||
dictionary MediaTrackConstraints {
|
||||
object mandatory; // so we can see unknown + unsupported constraints
|
||||
sequence<MediaTrackConstraintSet> _optional; // a.k.a. MediaTrackConstraint
|
||||
};
|
||||
|
||||
typedef VideoFacingModeEnum ConstrainVideoFacingMode;
|
||||
// TODO: Bug 767924 sequences in unions
|
||||
//typedef (VideoFacingModeEnum or sequence<VideoFacingModeEnum>) ConstrainVideoFacingMode;
|
||||
// Internal dictionary holds result of processing raw MediaTrackConstraints above
|
||||
|
||||
dictionary MediaTrackConstraintsInternal {
|
||||
MediaTrackConstraintSet mandatory; // holds only supported constraints
|
||||
sequence<MediaTrackConstraintSet> _optional; // a.k.a. MediaTrackConstraint
|
||||
};
|
||||
|
||||
interface MediaStreamTrack {
|
||||
readonly attribute DOMString kind;
|
||||
|
@ -337,7 +337,7 @@ partial interface Navigator {
|
||||
callback MozGetUserMediaDevicesSuccessCallback = void (nsIVariant? devices);
|
||||
partial interface Navigator {
|
||||
[Throws, ChromeOnly]
|
||||
void mozGetUserMediaDevices(MediaStreamConstraints constraints,
|
||||
void mozGetUserMediaDevices(MediaStreamConstraintsInternal constraints,
|
||||
MozGetUserMediaDevicesSuccessCallback onsuccess,
|
||||
NavigatorUserMediaErrorCallback onerror,
|
||||
// The originating innerWindowID is needed to
|
||||
|
Loading…
Reference in New Issue
Block a user