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) { |