зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1471165 - P1. Simulate required MediaCapabilities members in optional dictionary. r=bz
Summary: In order to allow for optional dictionaries with required members See https://github.com/heycam/webidl/issues/76 for more information. Reviewers: bzbarsky Tags: #secure-revision Bug #: 1471165 Differential Revision: https://phabricator.services.mozilla.com/D1833
This commit is contained in:
Родитель
cab83f1874
Коммит
138b0b299d
|
@ -262,10 +262,16 @@ MakeMediaExtendedMIMEType(const nsAString& aType)
|
||||||
Maybe<MediaExtendedMIMEType>
|
Maybe<MediaExtendedMIMEType>
|
||||||
MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig)
|
MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig)
|
||||||
{
|
{
|
||||||
if (aConfig.mContentType.IsEmpty()) {
|
MOZ_ASSERT(aConfig.mContentType.WasPassed() &&
|
||||||
|
aConfig.mFramerate.WasPassed() &&
|
||||||
|
aConfig.mWidth.WasPassed() &&
|
||||||
|
aConfig.mHeight.WasPassed() &&
|
||||||
|
aConfig.mBitrate.WasPassed(),
|
||||||
|
"All dictionary members must be present");
|
||||||
|
if (aConfig.mContentType.Value().IsEmpty()) {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
nsContentTypeParser parser(aConfig.mContentType);
|
nsContentTypeParser parser(aConfig.mContentType.Value());
|
||||||
nsAutoString mime;
|
nsAutoString mime;
|
||||||
nsresult rv = parser.GetType(mime);
|
nsresult rv = parser.GetType(mime);
|
||||||
if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
|
if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
|
||||||
|
@ -282,28 +288,30 @@ MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig)
|
||||||
bool haveCodecs = NS_SUCCEEDED(rv);
|
bool haveCodecs = NS_SUCCEEDED(rv);
|
||||||
|
|
||||||
auto framerate =
|
auto framerate =
|
||||||
MediaExtendedMIMEType::ComputeFractionalString(aConfig.mFramerate);
|
MediaExtendedMIMEType::ComputeFractionalString(aConfig.mFramerate.Value());
|
||||||
if (!framerate) {
|
if (!framerate) {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aConfig.mContentType),
|
return Some(
|
||||||
mime8,
|
MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
|
||||||
haveCodecs,
|
mime8,
|
||||||
codecs,
|
haveCodecs,
|
||||||
aConfig.mWidth,
|
codecs,
|
||||||
aConfig.mHeight,
|
aConfig.mWidth.Value(),
|
||||||
framerate.ref(),
|
aConfig.mHeight.Value(),
|
||||||
aConfig.mBitrate));
|
framerate.ref(),
|
||||||
|
aConfig.mBitrate.Value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<MediaExtendedMIMEType>
|
Maybe<MediaExtendedMIMEType>
|
||||||
MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig)
|
MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig)
|
||||||
{
|
{
|
||||||
if (aConfig.mContentType.IsEmpty()) {
|
if (!aConfig.mContentType.WasPassed() ||
|
||||||
|
aConfig.mContentType.Value().IsEmpty()) {
|
||||||
return Nothing();
|
return Nothing();
|
||||||
}
|
}
|
||||||
nsContentTypeParser parser(aConfig.mContentType);
|
nsContentTypeParser parser(aConfig.mContentType.Value());
|
||||||
nsAutoString mime;
|
nsAutoString mime;
|
||||||
nsresult rv = parser.GetType(mime);
|
nsresult rv = parser.GetType(mime);
|
||||||
if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
|
if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
|
||||||
|
@ -335,7 +343,7 @@ MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(MediaExtendedMIMEType(
|
return Some(MediaExtendedMIMEType(
|
||||||
NS_ConvertUTF16toUTF8(aConfig.mContentType),
|
NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
|
||||||
mime8,
|
mime8,
|
||||||
haveCodecs,
|
haveCodecs,
|
||||||
codecs,
|
codecs,
|
||||||
|
|
|
@ -32,6 +32,54 @@ MediaCapabilities::MediaCapabilities(nsIGlobalObject* aParent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ThrowWithMemberName(ErrorResult& aRv,
|
||||||
|
const char* aCategory,
|
||||||
|
const char* aMember)
|
||||||
|
{
|
||||||
|
auto str = nsPrintfCString("'%s' member of %s", aMember, aCategory);
|
||||||
|
aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
|
||||||
|
NS_ConvertUTF8toUTF16(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CheckVideoConfigurationSanity(const VideoConfiguration& aConfig,
|
||||||
|
const char* aCategory,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (!aConfig.mContentType.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "contentType", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!aConfig.mWidth.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "width", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!aConfig.mHeight.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "height", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!aConfig.mBitrate.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "bitrate", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!aConfig.mFramerate.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "framerate", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CheckAudioConfigurationSanity(const AudioConfiguration& aConfig,
|
||||||
|
const char* aCategory,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (!aConfig.mContentType.WasPassed()) {
|
||||||
|
ThrowWithMemberName(aRv, "contentType", aCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
already_AddRefed<Promise>
|
||||||
MediaCapabilities::DecodingInfo(
|
MediaCapabilities::DecodingInfo(
|
||||||
const MediaDecodingConfiguration& aConfiguration,
|
const MediaDecodingConfiguration& aConfiguration,
|
||||||
|
@ -52,6 +100,25 @@ MediaCapabilities::DecodingInfo(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Here we will throw rather than rejecting a promise in order to simulate
|
||||||
|
// optional dictionaries with required members (see bug 1368949)
|
||||||
|
if (aConfiguration.mVideo.IsAnyMemberPresent()) {
|
||||||
|
// Check that all VideoConfiguration required members are present.
|
||||||
|
CheckVideoConfigurationSanity(
|
||||||
|
aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
||||||
|
// Check that all AudioConfiguration required members are present.
|
||||||
|
CheckAudioConfigurationSanity(
|
||||||
|
aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool supported = true;
|
bool supported = true;
|
||||||
Maybe<MediaContainerType> videoContainer;
|
Maybe<MediaContainerType> videoContainer;
|
||||||
Maybe<MediaContainerType> audioContainer;
|
Maybe<MediaContainerType> audioContainer;
|
||||||
|
@ -68,8 +135,8 @@ MediaCapabilities::DecodingInfo(
|
||||||
// We have a video configuration and it is valid. Check if it is supported.
|
// We have a video configuration and it is valid. Check if it is supported.
|
||||||
supported &=
|
supported &=
|
||||||
aConfiguration.mType == MediaDecodingType::File
|
aConfiguration.mType == MediaDecodingType::File
|
||||||
? CheckTypeForFile(aConfiguration.mVideo.mContentType)
|
? CheckTypeForFile(aConfiguration.mVideo.mContentType.Value())
|
||||||
: CheckTypeForMediaSource(aConfiguration.mVideo.mContentType);
|
: CheckTypeForMediaSource(aConfiguration.mVideo.mContentType.Value());
|
||||||
}
|
}
|
||||||
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
||||||
audioContainer = CheckAudioConfiguration(aConfiguration.mAudio);
|
audioContainer = CheckAudioConfiguration(aConfiguration.mAudio);
|
||||||
|
@ -80,8 +147,8 @@ MediaCapabilities::DecodingInfo(
|
||||||
// We have an audio configuration and it is valid. Check if it is supported.
|
// We have an audio configuration and it is valid. Check if it is supported.
|
||||||
supported &=
|
supported &=
|
||||||
aConfiguration.mType == MediaDecodingType::File
|
aConfiguration.mType == MediaDecodingType::File
|
||||||
? CheckTypeForFile(aConfiguration.mAudio.mContentType)
|
? CheckTypeForFile(aConfiguration.mAudio.mContentType.Value())
|
||||||
: CheckTypeForMediaSource(aConfiguration.mAudio.mContentType);
|
: CheckTypeForMediaSource(aConfiguration.mAudio.mContentType.Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
|
@ -323,6 +390,25 @@ MediaCapabilities::EncodingInfo(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Here we will throw rather than rejecting a promise in order to simulate
|
||||||
|
// optional dictionaries with required members (see bug 1368949)
|
||||||
|
if (aConfiguration.mVideo.IsAnyMemberPresent()) {
|
||||||
|
// Check that all VideoConfiguration required members are present.
|
||||||
|
CheckVideoConfigurationSanity(
|
||||||
|
aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
||||||
|
// Check that all AudioConfiguration required members are present.
|
||||||
|
CheckAudioConfigurationSanity(
|
||||||
|
aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool supported = true;
|
bool supported = true;
|
||||||
|
|
||||||
// If configuration.video is present and is not a valid video configuration,
|
// If configuration.video is present and is not a valid video configuration,
|
||||||
|
@ -333,7 +419,8 @@ MediaCapabilities::EncodingInfo(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// We have a video configuration and it is valid. Check if it is supported.
|
// We have a video configuration and it is valid. Check if it is supported.
|
||||||
supported &= CheckTypeForEncoder(aConfiguration.mVideo.mContentType);
|
supported &=
|
||||||
|
CheckTypeForEncoder(aConfiguration.mVideo.mContentType.Value());
|
||||||
}
|
}
|
||||||
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
if (aConfiguration.mAudio.IsAnyMemberPresent()) {
|
||||||
if (!CheckAudioConfiguration(aConfiguration.mAudio)) {
|
if (!CheckAudioConfiguration(aConfiguration.mAudio)) {
|
||||||
|
@ -341,7 +428,8 @@ MediaCapabilities::EncodingInfo(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// We have an audio configuration and it is valid. Check if it is supported.
|
// We have an audio configuration and it is valid. Check if it is supported.
|
||||||
supported &= CheckTypeForEncoder(aConfiguration.mAudio.mContentType);
|
supported &=
|
||||||
|
CheckTypeForEncoder(aConfiguration.mAudio.mContentType.Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto info = MakeUnique<MediaCapabilitiesInfo>(supported, supported, false);
|
auto info = MakeUnique<MediaCapabilitiesInfo>(supported, supported, false);
|
||||||
|
|
|
@ -32,16 +32,22 @@ enum MediaEncodingType {
|
||||||
"transmission"
|
"transmission"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// all members are specified as required in the spec.
|
||||||
|
// We enforce that requirement in the MediaCapabilities code instead
|
||||||
|
// See https://github.com/heycam/webidl/issues/76
|
||||||
dictionary VideoConfiguration {
|
dictionary VideoConfiguration {
|
||||||
required DOMString contentType;
|
DOMString contentType;
|
||||||
required unsigned long width;
|
unsigned long width;
|
||||||
required unsigned long height;
|
unsigned long height;
|
||||||
required unsigned long long bitrate;
|
unsigned long long bitrate;
|
||||||
required DOMString framerate;
|
DOMString framerate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// contentType member is specified as required in the spec.
|
||||||
|
// We enforce that requirement in the MediaCapabilities code instead
|
||||||
|
// See https://github.com/heycam/webidl/issues/76
|
||||||
dictionary AudioConfiguration {
|
dictionary AudioConfiguration {
|
||||||
required DOMString contentType;
|
DOMString contentType;
|
||||||
DOMString channels;
|
DOMString channels;
|
||||||
unsigned long long bitrate;
|
unsigned long long bitrate;
|
||||||
unsigned long samplerate;
|
unsigned long samplerate;
|
||||||
|
@ -57,8 +63,6 @@ interface MediaCapabilitiesInfo {
|
||||||
|
|
||||||
[Exposed=(Window, Worker), Func="mozilla::dom::MediaCapabilities::Enabled"]
|
[Exposed=(Window, Worker), Func="mozilla::dom::MediaCapabilities::Enabled"]
|
||||||
interface MediaCapabilities {
|
interface MediaCapabilities {
|
||||||
// As per https://github.com/WICG/media-capabilities/issues/91 we mark the
|
|
||||||
// methods as always returning a new object.
|
|
||||||
[NewObject]
|
[NewObject]
|
||||||
Promise<MediaCapabilitiesInfo> decodingInfo(MediaDecodingConfiguration configuration);
|
Promise<MediaCapabilitiesInfo> decodingInfo(MediaDecodingConfiguration configuration);
|
||||||
[NewObject]
|
[NewObject]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче