зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1006707 - change facingMode from enum to DOMString and support it as array. r=smaug, r=mt
This commit is contained in:
Родитель
dd318c4d2a
Коммит
4c8c004fd8
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1115998 - (DOMString or sequence<DOMString>) needs binding flush (Bug 1103153)
|
||||
Bug 1006707 - (DOMString or sequence<DOMString>) needs binding flush (Bug 1103153)
|
||||
|
|
|
@ -439,17 +439,22 @@ VideoDevice::SatisfiesConstraintSets(
|
|||
for (size_t i = 0; i < aConstraintSets.Length(); i++) {
|
||||
auto& c = *aConstraintSets[i];
|
||||
if (c.mFacingMode.WasPassed()) {
|
||||
auto& value = c.mFacingMode.Value();
|
||||
nsString s;
|
||||
GetFacingMode(s);
|
||||
if (!s.EqualsASCII(dom::VideoFacingModeEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mFacingMode.Value())].value)) {
|
||||
return false;
|
||||
if (value.IsString()) {
|
||||
if (s != value.GetAsString()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!value.GetAsStringSequence().Contains(s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsString s;
|
||||
GetMediaSource(s);
|
||||
if (!s.EqualsASCII(dom::MediaSourceEnumValues::strings[
|
||||
static_cast<uint32_t>(c.mMediaSource)].value)) {
|
||||
if (s != c.mMediaSource) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -956,7 +961,9 @@ static void
|
|||
{
|
||||
nsTArray<nsRefPtr<typename DeviceType::Source> > sources;
|
||||
// all MediaSourceEnums are contained in MediaSourceType
|
||||
(engine->*aEnumerate)((MediaSourceType)((int)aConstraints.mMediaSource), &sources);
|
||||
|
||||
(engine->*aEnumerate)((MediaSourceType)(aConstraints.mMediaSourceEnumValue),
|
||||
&sources);
|
||||
/**
|
||||
* We're allowing multiple tabs to access the same camera for parity
|
||||
* with Chrome. See bug 811757 for some of the issues surrounding
|
||||
|
@ -1630,15 +1637,16 @@ MediaManager::GetUserMedia(
|
|||
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
|
||||
if (!tc.mRequire.WasPassed() &&
|
||||
tc.mMandatory.mFacingMode.WasPassed() && !tc.mFacingMode.WasPassed()) {
|
||||
tc.mFacingMode.Construct(tc.mMandatory.mFacingMode.Value());
|
||||
tc.mFacingMode.Construct().SetAsString() = 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++) {
|
||||
for (size_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());
|
||||
n.mFacingMode.Construct().SetAsString() =
|
||||
tc.mOptional.Value()[i].mFacingMode.Value();
|
||||
tc.mAdvanced.Value().AppendElement(n);
|
||||
}
|
||||
}
|
||||
|
@ -1654,8 +1662,8 @@ MediaManager::GetUserMedia(
|
|||
}
|
||||
|
||||
if (tc.mAdvanced.WasPassed()) {
|
||||
uint32_t length = tc.mAdvanced.Value().Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
size_t length = tc.mAdvanced.Value().Length();
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (tc.mAdvanced.Value()[i].mBrowserWindow.WasPassed()) {
|
||||
tc.mAdvanced.Value()[i].mBrowserWindow.Construct(-1);
|
||||
}
|
||||
|
@ -1679,33 +1687,45 @@ MediaManager::GetUserMedia(
|
|||
|
||||
if (c.mVideo.IsMediaTrackConstraints()) {
|
||||
auto& tc = c.mVideo.GetAsMediaTrackConstraints();
|
||||
// deny screensharing request if support is disabled
|
||||
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
if (tc.mMediaSource == dom::MediaSourceEnum::Browser) {
|
||||
if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
} else if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
/* Deny screensharing if the requesting document is not from a host
|
||||
on the whitelist. */
|
||||
// Block screen/window sharing on Mac OSX 10.6 and WinXP until proved that they work
|
||||
if (
|
||||
MediaSourceEnum src = StringToEnum(dom::MediaSourceEnumValues::strings,
|
||||
tc.mMediaSource,
|
||||
dom::MediaSourceEnum::Other);
|
||||
switch (src) {
|
||||
case dom::MediaSourceEnum::Camera:
|
||||
break;
|
||||
|
||||
case dom::MediaSourceEnum::Browser:
|
||||
case dom::MediaSourceEnum::Screen:
|
||||
case dom::MediaSourceEnum::Application:
|
||||
case dom::MediaSourceEnum::Window:
|
||||
// Deny screensharing request if support is disabled, or
|
||||
// the requesting document is not from a host on the whitelist, or
|
||||
// we're on Mac OSX 10.6 and WinXP until proved that they work
|
||||
if (!Preferences::GetBool(((src == dom::MediaSourceEnum::Browser)?
|
||||
"media.getusermedia.browser.enabled" :
|
||||
"media.getusermedia.screensharing.enabled"),
|
||||
false) ||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
(
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms", false) &&
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms",
|
||||
false) &&
|
||||
#if defined(XP_MACOSX)
|
||||
!nsCocoaFeatures::OnLionOrLater()
|
||||
#endif
|
||||
#if defined (XP_WIN)
|
||||
!IsVistaOrLater()
|
||||
#endif
|
||||
) ||
|
||||
) ||
|
||||
#endif
|
||||
(!privileged && !HostHasPermission(*docURI))) {
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
break;
|
||||
|
||||
case dom::MediaSourceEnum::Microphone:
|
||||
case dom::MediaSourceEnum::Other:
|
||||
default:
|
||||
return task->Denied(NS_LITERAL_STRING("NotFoundError"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,24 +23,42 @@ var common_tests = [
|
|||
constraints: { video: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "video overconstrained by facingMode array fails",
|
||||
constraints: { video: { facingMode:['left', 'right'], require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "audio overconstrained by facingMode fails",
|
||||
constraints: { audio: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NotFoundError" },
|
||||
{ message: "full screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'screen' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "application screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'application' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "window screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'window' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "browser screensharing requires permission",
|
||||
constraints: { video: { mediaSource:'browser' } },
|
||||
error: "PermissionDeniedError" },
|
||||
{ message: "unknown mediaSource fails",
|
||||
constraints: { video: { mediaSource:'uncle' } },
|
||||
error: "NotFoundError" },
|
||||
{ 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"],
|
||||
audio: { mediaSource:'microphone',
|
||||
facingMode:'left',
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:'user' },
|
||||
{ bar:0 }] },
|
||||
video: { mediaSource:'camera',
|
||||
facingMode:['left', 'right', 'user', 'environment'],
|
||||
foo:0,
|
||||
advanced: [{ facingMode:'environment' },
|
||||
{ facingMode:['user'] },
|
||||
{ bar:0 }] } },
|
||||
error: null }
|
||||
];
|
||||
|
@ -63,12 +81,14 @@ function testConstraints(tests) {
|
|||
});
|
||||
}
|
||||
|
||||
var p = new Promise(function(resolve) { resolve(); });
|
||||
var p = new Promise(r => SpecialPowers.pushPrefEnv({
|
||||
set : [ ['media.getusermedia.browser.enabled', false],
|
||||
['media.getusermedia.screensharing.enabled', false] ]
|
||||
}, r));
|
||||
|
||||
tests.forEach(function(test) {
|
||||
p = testgum(p, test);
|
||||
});
|
||||
p.catch(function(reason) {
|
||||
ok(false, "Unexpected failure: " + reason.message);
|
||||
})
|
||||
p.catch(reason => ok(false, "Unexpected failure: " + reason.message))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ skip-if = (toolkit == 'gonk' && debug) # debug-only failure, turned an intermitt
|
|||
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]
|
||||
[test_getUserMedia_playVideoAudioTwice.html]
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=795367
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test mozGetUserMedia Exceptions</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>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795367">Test mozGetUserMedia Exceptions</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
These tests verify that the appropriate exception is thrown when incorrect
|
||||
values are provided to the immediate mozGetUserMedia call.
|
||||
*/
|
||||
var exceptionTests = [
|
||||
// Each test here verifies that a caller is required to have all
|
||||
// three arguments in order to call mozGetUserMedia
|
||||
{ params: undefined,
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "no arguments specified" },
|
||||
{ params: [{video: true, fake: true}],
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "one argument specified" },
|
||||
{ params: [{video: true, fake: true}, unexpectedCall],
|
||||
error: "Not enough arguments to Navigator.mozGetUserMedia.",
|
||||
message: "two arguments specified" },
|
||||
|
||||
// Each test here verifies that providing an incorret object
|
||||
// type to any mozGetUserMedia parameter should throw
|
||||
// the correct exception specified
|
||||
{ params: [1, unexpectedCall, unexpectedCall],
|
||||
error: "Argument 1 of Navigator.mozGetUserMedia can't be converted to a dictionary.",
|
||||
message: "wrong object type as first parameter" },
|
||||
{ params: [{video: true, fake: true}, 1, unexpectedCall],
|
||||
error: "Argument 2 of Navigator.mozGetUserMedia is not an object.",
|
||||
message: "wrong object type as second parameter" },
|
||||
{ params: [{video: true, fake: true}, unexpectedCall, 1],
|
||||
error: "Argument 3 of Navigator.mozGetUserMedia is not an object.",
|
||||
message: "wrong object type as third parameter" },
|
||||
|
||||
// Each test here verifies constraint syntax as defined in webidl
|
||||
{ params: [{ fake: true, video: { advanced: [{ facingMode:'foo' }] } },
|
||||
unexpectedCall, unexpectedCall],
|
||||
error: "'facingMode' member of MediaTrackConstraintSet 'foo' is not a valid value for enumeration VideoFacingModeEnum.",
|
||||
message: "invalid facingMode enum value" }
|
||||
];
|
||||
|
||||
/**
|
||||
* A callback function that is only called if a particular
|
||||
* exception was not thrown, resulting in the test failing.
|
||||
*
|
||||
* @param {MediaStream} argument ignored
|
||||
*/
|
||||
function unexpectedCall(obj) {
|
||||
ok(false, "Callback should not have been called");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the test run by running through each exception
|
||||
* test by verifying that the correct exception type specified
|
||||
* is thrown on the mozGetUserMedia call with the parameters
|
||||
* specified.
|
||||
*/
|
||||
runTest(function () {
|
||||
exceptionTests.forEach(function (test) {
|
||||
var exception = false;
|
||||
try {
|
||||
navigator.mozGetUserMedia.apply(navigator, test.params);
|
||||
} catch (e) {
|
||||
exception = (e.message === test.error);
|
||||
if(!exception) {
|
||||
info(e.message);
|
||||
}
|
||||
}
|
||||
ok(exception, "Exception for " + test.message);
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -12,6 +12,22 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
template<class EnumValuesStrings, class Enum>
|
||||
static const char* EnumToASCII(const EnumValuesStrings& aStrings, Enum aValue) {
|
||||
return aStrings[uint32_t(aValue)].value;
|
||||
}
|
||||
|
||||
template<class EnumValuesStrings, class Enum>
|
||||
static Enum StringToEnum(const EnumValuesStrings& aStrings, const nsAString& aValue,
|
||||
Enum aDefaultValue) {
|
||||
for (size_t i = 0; aStrings[i].value; i++) {
|
||||
if (aValue.EqualsASCII(aStrings[i].value)) {
|
||||
return Enum(i);
|
||||
}
|
||||
}
|
||||
return aDefaultValue;
|
||||
}
|
||||
|
||||
// Normalized internal version of MediaTrackConstraints to simplify downstream
|
||||
// processing. This implementation-only helper is included as needed by both
|
||||
// MediaManager (for gUM camera selection) and MediaEngine (for applyConstraints).
|
||||
|
@ -25,6 +41,7 @@ public:
|
|||
bool mUnsupportedRequirement;
|
||||
MediaTrackConstraintSet mRequired;
|
||||
dom::Sequence<MediaTrackConstraintSet> mNonrequired;
|
||||
dom::MediaSourceEnum mMediaSourceEnumValue;
|
||||
|
||||
MediaTrackConstraintsN(const dom::MediaTrackConstraints &aOther,
|
||||
const dom::EnumEntry* aStrings)
|
||||
|
@ -34,8 +51,8 @@ public:
|
|||
{
|
||||
if (mRequire.WasPassed()) {
|
||||
auto& array = mRequire.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
auto value = ToEnum(array[i]);
|
||||
for (size_t i = 0; i < array.Length(); i++) {
|
||||
auto value = StringToEnum(mStrings, array[i], Kind::Other);
|
||||
if (value != Kind::Other) {
|
||||
mRequireN.AppendElement(value);
|
||||
} else {
|
||||
|
@ -43,18 +60,22 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// treat MediaSource special because it's always required
|
||||
mRequired.mMediaSource = mMediaSource;
|
||||
|
||||
// we guarantee (int) equivalence from MediaSourceEnum ->MediaSourceType
|
||||
// (but not the other way)
|
||||
if (mMediaSource != dom::MediaSourceEnum::Camera && mAdvanced.WasPassed()) {
|
||||
// iterate through advanced, forcing mediaSource to match "root"
|
||||
auto& array = mAdvanced.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
if (array[i].mMediaSource == dom::MediaSourceEnum::Camera) {
|
||||
array[i].mMediaSource = mMediaSource;
|
||||
mMediaSourceEnumValue = StringToEnum(dom::MediaSourceEnumValues::strings,
|
||||
mMediaSource,
|
||||
dom::MediaSourceEnum::Other);
|
||||
if (mAdvanced.WasPassed()) {
|
||||
if(mMediaSourceEnumValue != dom::MediaSourceEnum::Camera) {
|
||||
// iterate through advanced, forcing mediaSource to match "root"
|
||||
auto& array = mAdvanced.Value();
|
||||
for (uint32_t i = 0; i < array.Length(); i++) {
|
||||
auto& ms = array[i].mMediaSource;
|
||||
if (ms.EqualsASCII(EnumToASCII(dom::MediaSourceEnumValues::strings,
|
||||
dom::MediaSourceEnum::Camera))) {
|
||||
ms = mMediaSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,14 +90,6 @@ protected:
|
|||
}
|
||||
}
|
||||
private:
|
||||
Kind ToEnum(const nsAString& aSrc) {
|
||||
for (size_t i = 0; mStrings[i].value; i++) {
|
||||
if (aSrc.EqualsASCII(mStrings[i].value)) {
|
||||
return Kind(i);
|
||||
}
|
||||
}
|
||||
return Kind::Other;
|
||||
}
|
||||
const dom::EnumEntry* mStrings;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
// These dictionaries need to be in a separate file from their use in unions
|
||||
// in MediaTrackConstraintSet.webidl due to a webidl compiler limitation.
|
||||
|
||||
// These enums are in the spec even though they're not used directly in the API
|
||||
// due to https://www.w3.org/Bugs/Public/show_bug.cgi?id=19936
|
||||
// Their binding code is quite useful though, and is used in the implementation.
|
||||
|
||||
enum VideoFacingModeEnum {
|
||||
"user",
|
||||
"environment",
|
||||
|
@ -19,7 +23,9 @@ enum MediaSourceEnum {
|
|||
"screen",
|
||||
"application",
|
||||
"window",
|
||||
"browser"
|
||||
"browser",
|
||||
"microphone",
|
||||
"other"
|
||||
};
|
||||
|
||||
dictionary ConstrainLongRange {
|
||||
|
|
|
@ -21,7 +21,7 @@ dictionary MediaTrackConstraints : MediaTrackConstraintSet {
|
|||
|
||||
// TODO(jib): Remove in 6+ weeks (Bug 997365)
|
||||
dictionary MobileLegacyMediaTrackConstraintSet {
|
||||
VideoFacingModeEnum facingMode;
|
||||
DOMString facingMode;
|
||||
};
|
||||
|
||||
interface MediaStreamTrack {
|
||||
|
|
|
@ -22,24 +22,16 @@ enum SupportedAudioConstraints {
|
|||
"other"
|
||||
};
|
||||
|
||||
|
||||
dictionary MediaTrackConstraintSet {
|
||||
ConstrainLongRange width;
|
||||
ConstrainLongRange height;
|
||||
ConstrainDoubleRange frameRate;
|
||||
ConstrainVideoFacingMode facingMode;
|
||||
ConstrainMediaSource mediaSource = "camera";
|
||||
ConstrainDOMString facingMode;
|
||||
DOMString mediaSource = "camera";
|
||||
long long browserWindow;
|
||||
boolean scrollWithPage;
|
||||
};
|
||||
|
||||
// TODO: Bug 995352 can't nest unions
|
||||
//typedef (long or ConstrainLongRange) ConstrainLong;
|
||||
//typedef (double or ConstrainDoubleRange) ConstrainDouble;
|
||||
|
||||
typedef VideoFacingModeEnum ConstrainVideoFacingMode;
|
||||
typedef MediaSourceEnum ConstrainMediaSource;
|
||||
|
||||
// TODO: Bug 767924 sequences in unions
|
||||
//typedef (VideoFacingModeEnum or sequence<VideoFacingModeEnum>) ConstrainVideoFacingMode;
|
||||
//typedef (MediaSourceEnum or sequence<MediaSourceEnum>) ConstrainMediaSource;
|
||||
typedef (long or ConstrainLongRange) ConstrainLong;
|
||||
typedef (double or ConstrainDoubleRange) ConstrainDouble;
|
||||
typedef (DOMString or sequence<DOMString>) ConstrainDOMString;
|
||||
|
|
Загрузка…
Ссылка в новой задаче