Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp

Issue 2852563002: Media Capabilities: stricter checks for the media configuration inputs. (Closed)
Patch Set: ready for review Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/media_capabilities/MediaCapabilities.h" 5 #include "modules/media_capabilities/MediaCapabilities.h"
6 6
7 #include "bindings/core/v8/CallbackPromiseAdapter.h" 7 #include "bindings/core/v8/CallbackPromiseAdapter.h"
8 #include "bindings/core/v8/ScriptPromise.h" 8 #include "bindings/core/v8/ScriptPromise.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "core/dom/DOMException.h" 10 #include "core/dom/DOMException.h"
11 #include "modules/media_capabilities/MediaCapabilitiesInfo.h" 11 #include "modules/media_capabilities/MediaCapabilitiesInfo.h"
12 #include "modules/media_capabilities/MediaConfiguration.h" 12 #include "modules/media_capabilities/MediaConfiguration.h"
13 #include "modules/media_capabilities/MediaDecodingConfiguration.h" 13 #include "modules/media_capabilities/MediaDecodingConfiguration.h"
14 #include "modules/media_capabilities/MediaEncodingConfiguration.h" 14 #include "modules/media_capabilities/MediaEncodingConfiguration.h"
15 #include "platform/bindings/ScriptState.h" 15 #include "platform/bindings/ScriptState.h"
16 #include "platform/network/ParsedContentType.h" 16 #include "platform/network/ParsedContentType.h"
17 #include "public/platform/Platform.h" 17 #include "public/platform/Platform.h"
18 #include "public/platform/WebMediaRecorderHandler.h" 18 #include "public/platform/WebMediaRecorderHandler.h"
19 #include "public/platform/modules/media_capabilities/WebMediaCapabilitiesClient. h" 19 #include "public/platform/modules/media_capabilities/WebMediaCapabilitiesClient. h"
20 #include "public/platform/modules/media_capabilities/WebMediaCapabilitiesInfo.h" 20 #include "public/platform/modules/media_capabilities/WebMediaCapabilitiesInfo.h"
21 #include "public/platform/modules/media_capabilities/WebMediaConfiguration.h" 21 #include "public/platform/modules/media_capabilities/WebMediaConfiguration.h"
22 22
23 namespace blink { 23 namespace blink {
24 24
25 namespace { 25 namespace {
26 26
27 constexpr const char* kAudioMimeTypePrefix = "audio/";
28 constexpr const char* kVideoMimeTypePrefix = "video/";
chcunningham 2017/05/10 21:10:13 we may need to add in the HLS prefix "application/
mlamouri (slow - plz ping) 2017/05/11 10:41:23 That means we should update the specification, rig
29 constexpr const char* kCodecsMimeTypeParam = "codecs";
30
31 bool IsValidMimeType(const String& content_type, const String& prefix) {
32 ParsedContentType parsed_content_type(content_type,
33 ParsedContentType::Mode::kStrict);
34 if (!parsed_content_type.IsValid())
35 return false;
36
37 if (!parsed_content_type.MimeType().StartsWith(prefix))
38 return false;
39
40 if (parsed_content_type.ParameterCount() > 1)
41 return false;
42
43 if (parsed_content_type.ParameterCount() == 1 &&
44 parsed_content_type.ParameterValueForName(kCodecsMimeTypeParam)
45 .IsNull()) {
46 return false;
47 }
48
49 return true;
50 }
51
52 bool IsValidMediaConfiguration(const MediaConfiguration& configuration) {
53 return configuration.hasAudio() || configuration.hasVideo();
54 }
55
56 bool IsValidVideoConfiguration(const VideoConfiguration& configuration) {
57 DCHECK(configuration.hasContentType());
58
59 if (!IsValidMimeType(configuration.contentType(), kVideoMimeTypePrefix))
60 return false;
61
62 DCHECK(configuration.hasFramerate());
63 if (!std::isfinite(configuration.framerate()) ||
64 configuration.framerate() <= 0) {
65 return false;
66 }
67
68 return true;
69 }
70
71 bool IsValidAudioConfiguration(const AudioConfiguration& configuration) {
72 DCHECK(configuration.hasContentType());
73
74 if (!IsValidMimeType(configuration.contentType(), kAudioMimeTypePrefix))
75 return false;
76
77 return true;
78 }
79
27 WebAudioConfiguration ToWebAudioConfiguration( 80 WebAudioConfiguration ToWebAudioConfiguration(
28 const AudioConfiguration& configuration) { 81 const AudioConfiguration& configuration) {
29 WebAudioConfiguration web_configuration; 82 WebAudioConfiguration web_configuration;
30 83
31 // |contentType| is mandatory. 84 // |contentType| is mandatory.
32 DCHECK(configuration.hasContentType()); 85 DCHECK(configuration.hasContentType());
33 ParsedContentType parsed_content_type(configuration.contentType(), 86 ParsedContentType parsed_content_type(configuration.contentType(),
34 ParsedContentType::Mode::kStrict); 87 ParsedContentType::Mode::kStrict);
35 88 DCHECK(parsed_content_type.IsValid());
36 // TODO(chcunningham): Throw TypeError for invalid input.
37 // DCHECK(parsed_content_type.IsValid());
38 89
39 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); 90 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
40 web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII(); 91 web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
41 web_configuration.codec = parsed_content_type.ParameterValueForName(codecs); 92 web_configuration.codec = parsed_content_type.ParameterValueForName(codecs);
42 93
43 // |channels| is optional and will be set to a null WebString if not present. 94 // |channels| is optional and will be set to a null WebString if not present.
44 web_configuration.channels = configuration.hasChannels() 95 web_configuration.channels = configuration.hasChannels()
45 ? WebString(configuration.channels()) 96 ? WebString(configuration.channels())
46 : WebString(); 97 : WebString();
47 98
48 if (configuration.hasBitrate()) 99 if (configuration.hasBitrate())
49 web_configuration.bitrate = configuration.bitrate(); 100 web_configuration.bitrate = configuration.bitrate();
50 101
51 if (configuration.hasSamplerate()) 102 if (configuration.hasSamplerate())
52 web_configuration.samplerate = configuration.samplerate(); 103 web_configuration.samplerate = configuration.samplerate();
53 104
54 return web_configuration; 105 return web_configuration;
55 } 106 }
56 107
57 WebVideoConfiguration ToWebVideoConfiguration( 108 WebVideoConfiguration ToWebVideoConfiguration(
58 const VideoConfiguration& configuration) { 109 const VideoConfiguration& configuration) {
59 WebVideoConfiguration web_configuration; 110 WebVideoConfiguration web_configuration;
60 111
61 // All the properties are mandatory. 112 // All the properties are mandatory.
62 DCHECK(configuration.hasContentType()); 113 DCHECK(configuration.hasContentType());
63 ParsedContentType parsed_content_type(configuration.contentType(), 114 ParsedContentType parsed_content_type(configuration.contentType(),
64 ParsedContentType::Mode::kStrict); 115 ParsedContentType::Mode::kStrict);
65 116 DCHECK(parsed_content_type.IsValid());
66 // TODO(chcunningham): Throw TypeError for invalid input.
67 // DCHECK(parsed_content_type.IsValid());
68 117
69 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); 118 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
70 web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII(); 119 web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
71 web_configuration.codec = parsed_content_type.ParameterValueForName(codecs); 120 web_configuration.codec = parsed_content_type.ParameterValueForName(codecs);
72 121
73 DCHECK(configuration.hasWidth()); 122 DCHECK(configuration.hasWidth());
74 web_configuration.width = configuration.width(); 123 web_configuration.width = configuration.width();
75 124
76 DCHECK(configuration.hasHeight()); 125 DCHECK(configuration.hasHeight());
77 web_configuration.height = configuration.height(); 126 web_configuration.height = configuration.height();
78 127
79 DCHECK(configuration.hasBitrate()); 128 DCHECK(configuration.hasBitrate());
80 web_configuration.bitrate = configuration.bitrate(); 129 web_configuration.bitrate = configuration.bitrate();
81 130
82 DCHECK(configuration.hasFramerate()); 131 DCHECK(configuration.hasFramerate());
83 web_configuration.framerate = configuration.framerate(); 132 web_configuration.framerate = configuration.framerate();
84 133
85 return web_configuration; 134 return web_configuration;
86 } 135 }
87 136
88 WebMediaConfiguration ToWebMediaConfiguration( 137 WebMediaConfiguration ToWebMediaConfiguration(
89 const MediaConfiguration& configuration) { 138 const MediaDecodingConfiguration& configuration) {
90 WebMediaConfiguration web_configuration; 139 WebMediaConfiguration web_configuration;
91 140
141 // |type| is mandatory.
142 DCHECK(configuration.hasType());
143 if (configuration.type() == "file")
144 web_configuration.type = MediaConfigurationType::kFile;
145 else if (configuration.type() == "media-source")
146 web_configuration.type = MediaConfigurationType::kMediaSource;
147 else
148 NOTREACHED();
149
92 if (configuration.hasAudio()) { 150 if (configuration.hasAudio()) {
93 web_configuration.audio_configuration = 151 web_configuration.audio_configuration =
94 ToWebAudioConfiguration(configuration.audio()); 152 ToWebAudioConfiguration(configuration.audio());
153 }
154
155 if (configuration.hasVideo()) {
156 web_configuration.video_configuration =
157 ToWebVideoConfiguration(configuration.video());
158 }
159
160 return web_configuration;
161 }
162
163 WebMediaConfiguration ToWebMediaConfiguration(
164 const MediaEncodingConfiguration& configuration) {
165 WebMediaConfiguration web_configuration;
166
167 // TODO(mcasas): parse and set the type for encoding.
168
169 if (configuration.hasAudio()) {
170 web_configuration.audio_configuration =
171 ToWebAudioConfiguration(configuration.audio());
95 } 172 }
96 173
97 if (configuration.hasVideo()) { 174 if (configuration.hasVideo()) {
98 web_configuration.video_configuration = 175 web_configuration.video_configuration =
99 ToWebVideoConfiguration(configuration.video()); 176 ToWebVideoConfiguration(configuration.video());
100 } 177 }
101 178
102 return web_configuration; 179 return web_configuration;
103 } 180 }
104 181
105 } // anonymous namespace 182 } // anonymous namespace
106 183
107 MediaCapabilities::MediaCapabilities() = default; 184 MediaCapabilities::MediaCapabilities() = default;
108 185
109 ScriptPromise MediaCapabilities::decodingInfo( 186 ScriptPromise MediaCapabilities::decodingInfo(
110 ScriptState* script_state, 187 ScriptState* script_state,
111 const MediaDecodingConfiguration& configuration) { 188 const MediaDecodingConfiguration& configuration) {
112 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 189 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
113 ScriptPromise promise = resolver->Promise(); 190 ScriptPromise promise = resolver->Promise();
114 191
115 // |type| is mandatory. 192 if (!IsValidMediaConfiguration(configuration)) {
116 DCHECK(configuration.hasType()); 193 resolver->Reject(V8ThrowException::CreateTypeError(
194 script_state->GetIsolate(),
195 "The configuration dictionary has neither |video| nor |audio| "
196 "specified and needs at least one of them."));
197 return promise;
198 }
199
200 if (configuration.hasVideo() &&
201 !IsValidVideoConfiguration(configuration.video())) {
202 resolver->Reject(V8ThrowException::CreateTypeError(
203 script_state->GetIsolate(),
204 "The video configuration dictionary is not valid."));
205 return promise;
206 }
207
208 if (configuration.hasAudio() &&
209 !IsValidAudioConfiguration(configuration.audio())) {
210 resolver->Reject(V8ThrowException::CreateTypeError(
211 script_state->GetIsolate(),
212 "The audio configuration dictionary is not valid."));
213 return promise;
214 }
117 215
118 Platform::Current()->MediaCapabilitiesClient()->DecodingInfo( 216 Platform::Current()->MediaCapabilitiesClient()->DecodingInfo(
119 ToWebMediaConfiguration(configuration), 217 ToWebMediaConfiguration(configuration),
120 WTF::MakeUnique<CallbackPromiseAdapter<MediaCapabilitiesInfo, void>>( 218 WTF::MakeUnique<CallbackPromiseAdapter<MediaCapabilitiesInfo, void>>(
121 resolver)); 219 resolver));
122 220
123 return promise; 221 return promise;
124 } 222 }
125 223
126 ScriptPromise MediaCapabilities::encodingInfo( 224 ScriptPromise MediaCapabilities::encodingInfo(
127 ScriptState* script_state, 225 ScriptState* script_state,
128 const MediaEncodingConfiguration& configuration) { 226 const MediaEncodingConfiguration& configuration) {
129 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 227 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
130 ScriptPromise promise = resolver->Promise(); 228 ScriptPromise promise = resolver->Promise();
131 229
132 if (!configuration.hasVideo() && !configuration.hasAudio()) { 230 if (!IsValidMediaConfiguration(configuration)) {
133 resolver->Reject(DOMException::Create( 231 resolver->Reject(V8ThrowException::CreateTypeError(
134 kSyntaxError, 232 script_state->GetIsolate(),
135 "The configuration dictionary has neither |video| nor |audio| " 233 "The configuration dictionary has neither |video| nor |audio| "
136 "specified and needs at least one of them.")); 234 "specified and needs at least one of them."));
137 return promise; 235 return promise;
138 } 236 }
139 237
238 if (configuration.hasVideo() &&
239 !IsValidVideoConfiguration(configuration.video())) {
240 resolver->Reject(V8ThrowException::CreateTypeError(
241 script_state->GetIsolate(),
242 "The video configuration dictionary is not valid."));
243 return promise;
244 }
245
246 if (configuration.hasAudio() &&
247 !IsValidAudioConfiguration(configuration.audio())) {
248 resolver->Reject(V8ThrowException::CreateTypeError(
249 script_state->GetIsolate(),
250 "The audio configuration dictionary is not valid."));
251 return promise;
252 }
253
140 std::unique_ptr<WebMediaRecorderHandler> handler = 254 std::unique_ptr<WebMediaRecorderHandler> handler =
141 Platform::Current()->CreateMediaRecorderHandler(); 255 Platform::Current()->CreateMediaRecorderHandler();
142 if (!handler) { 256 if (!handler) {
143 resolver->Reject(DOMException::Create( 257 resolver->Reject(DOMException::Create(
144 kInvalidStateError, 258 kInvalidStateError,
145 "Platform error: could not create MediaRecorderHandler.")); 259 "Platform error: could not create MediaRecorderHandler."));
146 return promise; 260 return promise;
147 } 261 }
148 262
149 handler->EncodingInfo( 263 handler->EncodingInfo(
150 ToWebMediaConfiguration(configuration), 264 ToWebMediaConfiguration(configuration),
151 WTF::MakeUnique<CallbackPromiseAdapter<MediaCapabilitiesInfo, void>>( 265 WTF::MakeUnique<CallbackPromiseAdapter<MediaCapabilitiesInfo, void>>(
152 resolver)); 266 resolver));
153 return promise; 267 return promise;
154 } 268 }
155 269
156 DEFINE_TRACE(MediaCapabilities) {} 270 DEFINE_TRACE(MediaCapabilities) {}
157 271
158 } // namespace blink 272 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698