| Index: third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
|
| diff --git a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
|
| index 38f780fb1cb3d2a01f024ac5e298c19e10dfcc35..c5088ac65ddc6ff824ab155e63b293491da98891 100644
|
| --- a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
|
| +++ b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
|
| @@ -24,6 +24,62 @@ namespace blink {
|
|
|
| namespace {
|
|
|
| +constexpr const char* kApplicationMimeTypePrefix = "application/";
|
| +constexpr const char* kAudioMimeTypePrefix = "audio/";
|
| +constexpr const char* kVideoMimeTypePrefix = "video/";
|
| +constexpr const char* kCodecsMimeTypeParam = "codecs";
|
| +
|
| +bool IsValidMimeType(const String& content_type, const String& prefix) {
|
| + ParsedContentType parsed_content_type(content_type,
|
| + ParsedContentType::Mode::kStrict);
|
| + if (!parsed_content_type.IsValid())
|
| + return false;
|
| +
|
| + if (!parsed_content_type.MimeType().StartsWith(prefix) &&
|
| + !parsed_content_type.MimeType().StartsWith(kApplicationMimeTypePrefix)) {
|
| + return false;
|
| + }
|
| +
|
| + if (parsed_content_type.ParameterCount() > 1)
|
| + return false;
|
| +
|
| + if (parsed_content_type.ParameterCount() == 1 &&
|
| + parsed_content_type.ParameterValueForName(kCodecsMimeTypeParam)
|
| + .IsNull()) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool IsValidMediaConfiguration(const MediaConfiguration& configuration) {
|
| + return configuration.hasAudio() || configuration.hasVideo();
|
| +}
|
| +
|
| +bool IsValidVideoConfiguration(const VideoConfiguration& configuration) {
|
| + DCHECK(configuration.hasContentType());
|
| +
|
| + if (!IsValidMimeType(configuration.contentType(), kVideoMimeTypePrefix))
|
| + return false;
|
| +
|
| + DCHECK(configuration.hasFramerate());
|
| + if (!std::isfinite(configuration.framerate()) ||
|
| + configuration.framerate() <= 0) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool IsValidAudioConfiguration(const AudioConfiguration& configuration) {
|
| + DCHECK(configuration.hasContentType());
|
| +
|
| + if (!IsValidMimeType(configuration.contentType(), kAudioMimeTypePrefix))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| WebAudioConfiguration ToWebAudioConfiguration(
|
| const AudioConfiguration& configuration) {
|
| WebAudioConfiguration web_configuration;
|
| @@ -32,9 +88,7 @@ WebAudioConfiguration ToWebAudioConfiguration(
|
| DCHECK(configuration.hasContentType());
|
| ParsedContentType parsed_content_type(configuration.contentType(),
|
| ParsedContentType::Mode::kStrict);
|
| -
|
| - // TODO(chcunningham): Throw TypeError for invalid input.
|
| - // DCHECK(parsed_content_type.IsValid());
|
| + DCHECK(parsed_content_type.IsValid());
|
|
|
| DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
|
| web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
|
| @@ -62,9 +116,7 @@ WebVideoConfiguration ToWebVideoConfiguration(
|
| DCHECK(configuration.hasContentType());
|
| ParsedContentType parsed_content_type(configuration.contentType(),
|
| ParsedContentType::Mode::kStrict);
|
| -
|
| - // TODO(chcunningham): Throw TypeError for invalid input.
|
| - // DCHECK(parsed_content_type.IsValid());
|
| + DCHECK(parsed_content_type.IsValid());
|
|
|
| DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
|
| web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
|
| @@ -86,9 +138,37 @@ WebVideoConfiguration ToWebVideoConfiguration(
|
| }
|
|
|
| WebMediaConfiguration ToWebMediaConfiguration(
|
| - const MediaConfiguration& configuration) {
|
| + const MediaDecodingConfiguration& configuration) {
|
| + WebMediaConfiguration web_configuration;
|
| +
|
| + // |type| is mandatory.
|
| + DCHECK(configuration.hasType());
|
| + if (configuration.type() == "file")
|
| + web_configuration.type = MediaConfigurationType::kFile;
|
| + else if (configuration.type() == "media-source")
|
| + web_configuration.type = MediaConfigurationType::kMediaSource;
|
| + else
|
| + NOTREACHED();
|
| +
|
| + if (configuration.hasAudio()) {
|
| + web_configuration.audio_configuration =
|
| + ToWebAudioConfiguration(configuration.audio());
|
| + }
|
| +
|
| + if (configuration.hasVideo()) {
|
| + web_configuration.video_configuration =
|
| + ToWebVideoConfiguration(configuration.video());
|
| + }
|
| +
|
| + return web_configuration;
|
| +}
|
| +
|
| +WebMediaConfiguration ToWebMediaConfiguration(
|
| + const MediaEncodingConfiguration& configuration) {
|
| WebMediaConfiguration web_configuration;
|
|
|
| + // TODO(mcasas): parse and set the type for encoding.
|
| +
|
| if (configuration.hasAudio()) {
|
| web_configuration.audio_configuration =
|
| ToWebAudioConfiguration(configuration.audio());
|
| @@ -112,8 +192,29 @@ ScriptPromise MediaCapabilities::decodingInfo(
|
| ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
|
| ScriptPromise promise = resolver->Promise();
|
|
|
| - // |type| is mandatory.
|
| - DCHECK(configuration.hasType());
|
| + if (!IsValidMediaConfiguration(configuration)) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| + "The configuration dictionary has neither |video| nor |audio| "
|
| + "specified and needs at least one of them."));
|
| + return promise;
|
| + }
|
| +
|
| + if (configuration.hasVideo() &&
|
| + !IsValidVideoConfiguration(configuration.video())) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| + "The video configuration dictionary is not valid."));
|
| + return promise;
|
| + }
|
| +
|
| + if (configuration.hasAudio() &&
|
| + !IsValidAudioConfiguration(configuration.audio())) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| + "The audio configuration dictionary is not valid."));
|
| + return promise;
|
| + }
|
|
|
| Platform::Current()->MediaCapabilitiesClient()->DecodingInfo(
|
| ToWebMediaConfiguration(configuration),
|
| @@ -129,14 +230,30 @@ ScriptPromise MediaCapabilities::encodingInfo(
|
| ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
|
| ScriptPromise promise = resolver->Promise();
|
|
|
| - if (!configuration.hasVideo() && !configuration.hasAudio()) {
|
| - resolver->Reject(DOMException::Create(
|
| - kSyntaxError,
|
| + if (!IsValidMediaConfiguration(configuration)) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| "The configuration dictionary has neither |video| nor |audio| "
|
| "specified and needs at least one of them."));
|
| return promise;
|
| }
|
|
|
| + if (configuration.hasVideo() &&
|
| + !IsValidVideoConfiguration(configuration.video())) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| + "The video configuration dictionary is not valid."));
|
| + return promise;
|
| + }
|
| +
|
| + if (configuration.hasAudio() &&
|
| + !IsValidAudioConfiguration(configuration.audio())) {
|
| + resolver->Reject(V8ThrowException::CreateTypeError(
|
| + script_state->GetIsolate(),
|
| + "The audio configuration dictionary is not valid."));
|
| + return promise;
|
| + }
|
| +
|
| std::unique_ptr<WebMediaRecorderHandler> handler =
|
| Platform::Current()->CreateMediaRecorderHandler();
|
| if (!handler) {
|
|
|