OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <algorithm> | |
6 #include <iterator> | |
7 #include <map> | 5 #include <map> |
8 #include <string> | |
9 | 6 |
10 #include "base/containers/hash_tables.h" | 7 #include "base/containers/hash_tables.h" |
11 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | |
13 #include "base/stl_util.h" | |
14 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
16 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
17 #include "base/strings/utf_string_conversions.h" | 12 #include "media/base/mime_util.h" |
18 #include "net/base/mime_util.h" | |
19 #include "net/base/platform_mime_util.h" | |
20 #include "net/http/http_util.h" | |
21 | 13 |
22 #if defined(OS_ANDROID) | 14 #if defined(OS_ANDROID) |
23 #include "base/android/build_info.h" | 15 #include "base/android/build_info.h" |
24 #endif | 16 #endif |
25 | 17 |
26 using std::string; | 18 namespace media { |
27 | |
28 namespace net { | |
29 | 19 |
30 // Singleton utility class for mime types. | 20 // Singleton utility class for mime types. |
31 class MimeUtil : public PlatformMimeUtil { | 21 class MimeUtil { |
32 public: | 22 public: |
33 enum Codec { | 23 enum Codec { |
34 INVALID_CODEC, | 24 INVALID_CODEC, |
35 PCM, | 25 PCM, |
36 MP3, | 26 MP3, |
37 MPEG2_AAC_LC, | 27 MPEG2_AAC_LC, |
38 MPEG2_AAC_MAIN, | 28 MPEG2_AAC_MAIN, |
39 MPEG2_AAC_SSR, | 29 MPEG2_AAC_SSR, |
40 MPEG4_AAC_LC, | 30 MPEG4_AAC_LC, |
41 MPEG4_AAC_SBR_v1, | 31 MPEG4_AAC_SBR_v1, |
42 MPEG4_AAC_SBR_PS_v2, | 32 MPEG4_AAC_SBR_PS_v2, |
43 VORBIS, | 33 VORBIS, |
44 OPUS, | 34 OPUS, |
45 H264_BASELINE, | 35 H264_BASELINE, |
46 H264_MAIN, | 36 H264_MAIN, |
47 H264_HIGH, | 37 H264_HIGH, |
48 VP8, | 38 VP8, |
49 VP9, | 39 VP9, |
50 THEORA | 40 THEORA |
51 }; | 41 }; |
52 | 42 |
53 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, | |
54 std::string* mime_type) const; | |
55 | |
56 bool GetMimeTypeFromFile(const base::FilePath& file_path, | |
57 std::string* mime_type) const; | |
58 | |
59 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, | |
60 std::string* mime_type) const; | |
61 | |
62 bool IsSupportedMediaMimeType(const std::string& mime_type) const; | 43 bool IsSupportedMediaMimeType(const std::string& mime_type) const; |
63 | 44 |
64 bool MatchesMimeType(const std::string &mime_type_pattern, | |
65 const std::string &mime_type) const; | |
66 | |
67 bool ParseMimeTypeWithoutParameter(const std::string& type_string, | |
68 std::string* top_level_type, | |
69 std::string* subtype) const; | |
70 | |
71 bool IsValidTopLevelMimeType(const std::string& type_string) const; | |
72 | |
73 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; | 45 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; |
74 | 46 |
75 void ParseCodecString(const std::string& codecs, | 47 void ParseCodecString(const std::string& codecs, |
76 std::vector<std::string>* codecs_out, | 48 std::vector<std::string>* codecs_out, |
77 bool strip); | 49 bool strip); |
78 | 50 |
79 bool IsStrictMediaMimeType(const std::string& mime_type) const; | 51 bool IsStrictMediaMimeType(const std::string& mime_type) const; |
80 SupportsType IsSupportedStrictMediaMimeType( | 52 SupportsType IsSupportedStrictMediaMimeType( |
81 const std::string& mime_type, | 53 const std::string& mime_type, |
82 const std::vector<std::string>& codecs) const; | 54 const std::vector<std::string>& codecs) const; |
83 | 55 |
84 void RemoveProprietaryMediaTypesAndCodecsForTests(); | 56 void RemoveProprietaryMediaTypesAndCodecsForTests(); |
85 | 57 |
86 private: | 58 private: |
87 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; | 59 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; |
88 | 60 |
89 typedef base::hash_set<std::string> MimeMappings; | |
90 | |
91 typedef base::hash_set<int> CodecSet; | 61 typedef base::hash_set<int> CodecSet; |
92 typedef std::map<std::string, CodecSet> StrictMappings; | 62 typedef std::map<std::string, CodecSet> StrictMappings; |
93 struct CodecEntry { | 63 struct CodecEntry { |
94 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} | 64 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} |
95 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} | 65 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} |
96 Codec codec; | 66 Codec codec; |
97 bool is_ambiguous; | 67 bool is_ambiguous; |
98 }; | 68 }; |
99 typedef std::map<std::string, CodecEntry> StringToCodecMappings; | 69 typedef std::map<std::string, CodecEntry> StringToCodecMappings; |
100 | 70 |
101 MimeUtil(); | 71 MimeUtil(); |
102 | 72 |
| 73 // For faster lookup, keep hash sets. |
| 74 void InitializeMimeTypeMaps(); |
| 75 |
103 // Returns IsSupported if all codec IDs in |codecs| are unambiguous | 76 // Returns IsSupported if all codec IDs in |codecs| are unambiguous |
104 // and are supported by the platform. MayBeSupported is returned if | 77 // and are supported by the platform. MayBeSupported is returned if |
105 // at least one codec ID in |codecs| is ambiguous but all the codecs | 78 // at least one codec ID in |codecs| is ambiguous but all the codecs |
106 // are supported by the platform. IsNotSupported is returned if at | 79 // are supported by the platform. IsNotSupported is returned if at |
107 // least one codec ID is not supported by the platform. | 80 // least one codec ID is not supported by the platform. |
108 SupportsType AreSupportedCodecs( | 81 SupportsType AreSupportedCodecs( |
109 const CodecSet& supported_codecs, | 82 const CodecSet& supported_codecs, |
110 const std::vector<std::string>& codecs) const; | 83 const std::vector<std::string>& codecs) const; |
111 | 84 |
112 // For faster lookup, keep hash sets. | |
113 void InitializeMimeTypeMaps(); | |
114 | |
115 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, | |
116 bool include_platform_types, | |
117 std::string* mime_type) const; | |
118 | |
119 // Converts a codec ID into an Codec enum value and indicates | 85 // Converts a codec ID into an Codec enum value and indicates |
120 // whether the conversion was ambiguous. | 86 // whether the conversion was ambiguous. |
121 // Returns true if this method was able to map |codec_id| to a specific | 87 // Returns true if this method was able to map |codec_id| to a specific |
122 // Codec enum value. |codec| and |is_ambiguous| are only valid if true | 88 // Codec enum value. |codec| and |is_ambiguous| are only valid if true |
123 // is returned. Otherwise their value is undefined after the call. | 89 // is returned. Otherwise their value is undefined after the call. |
124 // |is_ambiguous| is true if |codec_id| did not have enough information to | 90 // |is_ambiguous| is true if |codec_id| did not have enough information to |
125 // unambiguously determine the proper Codec enum value. If |is_ambiguous| | 91 // unambiguously determine the proper Codec enum value. If |is_ambiguous| |
126 // is true |codec| contains the best guess for the intended Codec enum value. | 92 // is true |codec| contains the best guess for the intended Codec enum value. |
127 bool StringToCodec(const std::string& codec_id, | 93 bool StringToCodec(const std::string& codec_id, |
128 Codec* codec, | 94 Codec* codec, |
(...skipping 11 matching lines...) Expand all Loading... |
140 // associated with it. Returns false otherwise and the value of | 106 // associated with it. Returns false otherwise and the value of |
141 // |*default_codec| is undefined. | 107 // |*default_codec| is undefined. |
142 bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, | 108 bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, |
143 Codec* default_codec) const; | 109 Codec* default_codec) const; |
144 | 110 |
145 // Returns true if |mime_type_lower_case| has a default codec associated with | 111 // Returns true if |mime_type_lower_case| has a default codec associated with |
146 // it and IsCodecSupported() returns true for that particular codec. | 112 // it and IsCodecSupported() returns true for that particular codec. |
147 bool IsDefaultCodecSupportedLowerCase( | 113 bool IsDefaultCodecSupportedLowerCase( |
148 const std::string& mime_type_lower_case) const; | 114 const std::string& mime_type_lower_case) const; |
149 | 115 |
150 MimeMappings media_map_; | 116 using MimeTypes = base::hash_set<std::string>; |
| 117 MimeTypes media_map_; |
151 | 118 |
152 // A map of mime_types and hash map of the supported codecs for the mime_type. | 119 // A map of mime_types and hash map of the supported codecs for the mime_type. |
153 StrictMappings strict_format_map_; | 120 StrictMappings strict_format_map_; |
154 | 121 |
155 // Keeps track of whether proprietary codec support should be | 122 // Keeps track of whether proprietary codec support should be |
156 // advertised to callers. | 123 // advertised to callers. |
157 bool allow_proprietary_codecs_; | 124 bool allow_proprietary_codecs_; |
158 | 125 |
159 // Lookup table for string compare based string -> Codec mappings. | 126 // Lookup table for string compare based string -> Codec mappings. |
160 StringToCodecMappings string_to_codec_map_; | 127 StringToCodecMappings string_to_codec_map_; |
| 128 |
| 129 DISALLOW_COPY_AND_ASSIGN(MimeUtil); |
161 }; // class MimeUtil | 130 }; // class MimeUtil |
162 | 131 |
163 // This variable is Leaky because we need to access it from WorkerPool threads. | 132 // This variable is Leaky because it is accessed from WorkerPool threads. |
164 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = | 133 static base::LazyInstance<MimeUtil>::Leaky g_media_mime_util = |
165 LAZY_INSTANCE_INITIALIZER; | 134 LAZY_INSTANCE_INITIALIZER; |
166 | 135 |
167 struct MimeInfo { | |
168 const char* const mime_type; | |
169 const char* const extensions; // comma separated list | |
170 }; | |
171 | |
172 static const MimeInfo primary_mappings[] = { | |
173 { "text/html", "html,htm,shtml,shtm" }, | |
174 { "text/css", "css" }, | |
175 { "text/xml", "xml" }, | |
176 { "image/gif", "gif" }, | |
177 { "image/jpeg", "jpeg,jpg" }, | |
178 { "image/webp", "webp" }, | |
179 { "image/png", "png" }, | |
180 { "video/mp4", "mp4,m4v" }, | |
181 { "audio/x-m4a", "m4a" }, | |
182 { "audio/mp3", "mp3" }, | |
183 { "video/ogg", "ogv,ogm" }, | |
184 { "audio/ogg", "ogg,oga,opus" }, | |
185 { "video/webm", "webm" }, | |
186 { "audio/webm", "webm" }, | |
187 { "audio/wav", "wav" }, | |
188 { "application/xhtml+xml", "xhtml,xht,xhtm" }, | |
189 { "application/x-chrome-extension", "crx" }, | |
190 { "multipart/related", "mhtml,mht" } | |
191 }; | |
192 | |
193 static const MimeInfo secondary_mappings[] = { | |
194 { "application/octet-stream", "exe,com,bin" }, | |
195 { "application/gzip", "gz" }, | |
196 { "application/pdf", "pdf" }, | |
197 { "application/postscript", "ps,eps,ai" }, | |
198 { "application/javascript", "js" }, | |
199 { "application/font-woff", "woff" }, | |
200 { "image/bmp", "bmp" }, | |
201 { "image/x-icon", "ico" }, | |
202 { "image/vnd.microsoft.icon", "ico" }, | |
203 { "image/jpeg", "jfif,pjpeg,pjp" }, | |
204 { "image/tiff", "tiff,tif" }, | |
205 { "image/x-xbitmap", "xbm" }, | |
206 { "image/svg+xml", "svg,svgz" }, | |
207 { "image/x-png", "png"}, | |
208 { "message/rfc822", "eml" }, | |
209 { "text/plain", "txt,text" }, | |
210 { "text/html", "ehtml" }, | |
211 { "application/rss+xml", "rss" }, | |
212 { "application/rdf+xml", "rdf" }, | |
213 { "text/xml", "xsl,xbl,xslt" }, | |
214 { "application/vnd.mozilla.xul+xml", "xul" }, | |
215 { "application/x-shockwave-flash", "swf,swl" }, | |
216 { "application/pkcs7-mime", "p7m,p7c,p7z" }, | |
217 { "application/pkcs7-signature", "p7s" }, | |
218 { "application/x-mpegurl", "m3u8" }, | |
219 { "application/epub+zip", "epub" }, | |
220 }; | |
221 | |
222 static const char* FindMimeType(const MimeInfo* mappings, | |
223 size_t mappings_len, | |
224 const char* ext) { | |
225 size_t ext_len = strlen(ext); | |
226 | |
227 for (size_t i = 0; i < mappings_len; ++i) { | |
228 const char* extensions = mappings[i].extensions; | |
229 for (;;) { | |
230 size_t end_pos = strcspn(extensions, ","); | |
231 if (end_pos == ext_len && | |
232 base::strncasecmp(extensions, ext, ext_len) == 0) | |
233 return mappings[i].mime_type; | |
234 extensions += end_pos; | |
235 if (!*extensions) | |
236 break; | |
237 extensions += 1; // skip over comma | |
238 } | |
239 } | |
240 return NULL; | |
241 } | |
242 | |
243 bool MimeUtil::GetMimeTypeFromExtension(const base::FilePath::StringType& ext, | |
244 string* result) const { | |
245 return GetMimeTypeFromExtensionHelper(ext, true, result); | |
246 } | |
247 | |
248 bool MimeUtil::GetWellKnownMimeTypeFromExtension( | |
249 const base::FilePath::StringType& ext, | |
250 string* result) const { | |
251 return GetMimeTypeFromExtensionHelper(ext, false, result); | |
252 } | |
253 | |
254 bool MimeUtil::GetMimeTypeFromFile(const base::FilePath& file_path, | |
255 string* result) const { | |
256 base::FilePath::StringType file_name_str = file_path.Extension(); | |
257 if (file_name_str.empty()) | |
258 return false; | |
259 return GetMimeTypeFromExtension(file_name_str.substr(1), result); | |
260 } | |
261 | |
262 bool MimeUtil::GetMimeTypeFromExtensionHelper( | |
263 const base::FilePath::StringType& ext, | |
264 bool include_platform_types, | |
265 string* result) const { | |
266 // Avoids crash when unable to handle a long file path. See crbug.com/48733. | |
267 const unsigned kMaxFilePathSize = 65536; | |
268 if (ext.length() > kMaxFilePathSize) | |
269 return false; | |
270 | |
271 // We implement the same algorithm as Mozilla for mapping a file extension to | |
272 // a mime type. That is, we first check a hard-coded list (that cannot be | |
273 // overridden), and then if not found there, we defer to the system registry. | |
274 // Finally, we scan a secondary hard-coded list to catch types that we can | |
275 // deduce but that we also want to allow the OS to override. | |
276 | |
277 base::FilePath path_ext(ext); | |
278 const string ext_narrow_str = path_ext.AsUTF8Unsafe(); | |
279 const char* mime_type = FindMimeType(primary_mappings, | |
280 arraysize(primary_mappings), | |
281 ext_narrow_str.c_str()); | |
282 if (mime_type) { | |
283 *result = mime_type; | |
284 return true; | |
285 } | |
286 | |
287 if (include_platform_types && GetPlatformMimeTypeFromExtension(ext, result)) | |
288 return true; | |
289 | |
290 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings), | |
291 ext_narrow_str.c_str()); | |
292 if (mime_type) { | |
293 *result = mime_type; | |
294 return true; | |
295 } | |
296 | |
297 return false; | |
298 } | |
299 | 136 |
300 // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type | 137 // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type |
301 // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php | 138 // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php |
302 // This set of codecs is supported by all variations of Chromium. | 139 // This set of codecs is supported by all variations of Chromium. |
303 static const char* const common_media_types[] = { | 140 static const char* const common_media_types[] = { |
304 // Ogg. | 141 // Ogg. |
305 "audio/ogg", | 142 "audio/ogg", |
306 "application/ogg", | 143 "application/ogg", |
307 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. | 144 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. |
308 "video/ogg", | 145 "video/ogg", |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 | 392 |
556 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; | 393 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; |
557 } | 394 } |
558 } | 395 } |
559 | 396 |
560 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { | 397 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { |
561 return media_map_.find(base::StringToLowerASCII(mime_type)) != | 398 return media_map_.find(base::StringToLowerASCII(mime_type)) != |
562 media_map_.end(); | 399 media_map_.end(); |
563 } | 400 } |
564 | 401 |
565 // Tests for MIME parameter equality. Each parameter in the |mime_type_pattern| | |
566 // must be matched by a parameter in the |mime_type|. If there are no | |
567 // parameters in the pattern, the match is a success. | |
568 // | |
569 // According rfc2045 keys of parameters are case-insensitive, while values may | |
570 // or may not be case-sensitive, but they are usually case-sensitive. So, this | |
571 // function matches values in *case-sensitive* manner, however note that this | |
572 // may produce some false negatives. | |
573 bool MatchesMimeTypeParameters(const std::string& mime_type_pattern, | |
574 const std::string& mime_type) { | |
575 typedef std::map<std::string, std::string> StringPairMap; | |
576 | |
577 const std::string::size_type semicolon = mime_type_pattern.find(';'); | |
578 const std::string::size_type test_semicolon = mime_type.find(';'); | |
579 if (semicolon != std::string::npos) { | |
580 if (test_semicolon == std::string::npos) | |
581 return false; | |
582 | |
583 base::StringPairs pattern_parameters; | |
584 base::SplitStringIntoKeyValuePairs(mime_type_pattern.substr(semicolon + 1), | |
585 '=', ';', &pattern_parameters); | |
586 base::StringPairs test_parameters; | |
587 base::SplitStringIntoKeyValuePairs(mime_type.substr(test_semicolon + 1), | |
588 '=', ';', &test_parameters); | |
589 | |
590 // Put the parameters to maps with the keys converted to lower case. | |
591 StringPairMap pattern_parameter_map; | |
592 for (const auto& pair : pattern_parameters) { | |
593 pattern_parameter_map[base::StringToLowerASCII(pair.first)] = pair.second; | |
594 } | |
595 | |
596 StringPairMap test_parameter_map; | |
597 for (const auto& pair : test_parameters) { | |
598 test_parameter_map[base::StringToLowerASCII(pair.first)] = pair.second; | |
599 } | |
600 | |
601 if (pattern_parameter_map.size() > test_parameter_map.size()) | |
602 return false; | |
603 | |
604 for (const auto& parameter_pair : pattern_parameter_map) { | |
605 const auto& test_parameter_pair_it = | |
606 test_parameter_map.find(parameter_pair.first); | |
607 if (test_parameter_pair_it == test_parameter_map.end()) | |
608 return false; | |
609 if (parameter_pair.second != test_parameter_pair_it->second) | |
610 return false; | |
611 } | |
612 } | |
613 | |
614 return true; | |
615 } | |
616 | |
617 // This comparison handles absolute maching and also basic | |
618 // wildcards. The plugin mime types could be: | |
619 // application/x-foo | |
620 // application/* | |
621 // application/*+xml | |
622 // * | |
623 // Also tests mime parameters -- all parameters in the pattern must be present | |
624 // in the tested type for a match to succeed. | |
625 bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, | |
626 const std::string& mime_type) const { | |
627 if (mime_type_pattern.empty()) | |
628 return false; | |
629 | |
630 std::string::size_type semicolon = mime_type_pattern.find(';'); | |
631 const std::string base_pattern(mime_type_pattern.substr(0, semicolon)); | |
632 semicolon = mime_type.find(';'); | |
633 const std::string base_type(mime_type.substr(0, semicolon)); | |
634 | |
635 if (base_pattern == "*" || base_pattern == "*/*") | |
636 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); | |
637 | |
638 const std::string::size_type star = base_pattern.find('*'); | |
639 if (star == std::string::npos) { | |
640 if (base_pattern.size() == base_type.size() && | |
641 base::strncasecmp(base_pattern.c_str(), base_type.c_str(), | |
642 base_pattern.size()) == 0) { | |
643 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); | |
644 } else { | |
645 return false; | |
646 } | |
647 } | |
648 | |
649 // Test length to prevent overlap between |left| and |right|. | |
650 if (base_type.length() < base_pattern.length() - 1) | |
651 return false; | |
652 | |
653 const std::string left(base_pattern.substr(0, star)); | |
654 const std::string right(base_pattern.substr(star + 1)); | |
655 | |
656 if (!StartsWithASCII(base_type, left, false)) | |
657 return false; | |
658 | |
659 if (!right.empty() && !EndsWith(base_type, right, false)) | |
660 return false; | |
661 | |
662 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); | |
663 } | |
664 | |
665 // See http://www.iana.org/assignments/media-types/media-types.xhtml | |
666 static const char* const legal_top_level_types[] = { | |
667 "application", | |
668 "audio", | |
669 "example", | |
670 "image", | |
671 "message", | |
672 "model", | |
673 "multipart", | |
674 "text", | |
675 "video", | |
676 }; | |
677 | |
678 bool MimeUtil::ParseMimeTypeWithoutParameter( | |
679 const std::string& type_string, | |
680 std::string* top_level_type, | |
681 std::string* subtype) const { | |
682 std::vector<std::string> components; | |
683 base::SplitString(type_string, '/', &components); | |
684 if (components.size() != 2 || | |
685 !HttpUtil::IsToken(components[0]) || | |
686 !HttpUtil::IsToken(components[1])) | |
687 return false; | |
688 | |
689 if (top_level_type) | |
690 *top_level_type = components[0]; | |
691 if (subtype) | |
692 *subtype = components[1]; | |
693 return true; | |
694 } | |
695 | |
696 bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const { | |
697 std::string lower_type = base::StringToLowerASCII(type_string); | |
698 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { | |
699 if (lower_type.compare(legal_top_level_types[i]) == 0) | |
700 return true; | |
701 } | |
702 | |
703 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); | |
704 } | |
705 | 402 |
706 bool MimeUtil::AreSupportedMediaCodecs( | 403 bool MimeUtil::AreSupportedMediaCodecs( |
707 const std::vector<std::string>& codecs) const { | 404 const std::vector<std::string>& codecs) const { |
708 for (size_t i = 0; i < codecs.size(); ++i) { | 405 for (size_t i = 0; i < codecs.size(); ++i) { |
709 Codec codec = INVALID_CODEC; | 406 Codec codec = INVALID_CODEC; |
710 bool is_ambiguous = true; | 407 bool is_ambiguous = true; |
711 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || | 408 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || |
712 !IsCodecSupported(codec)) { | 409 !IsCodecSupported(codec)) { |
713 return false; | 410 return false; |
714 } | 411 } |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 } | 628 } |
932 | 629 |
933 bool MimeUtil::IsDefaultCodecSupportedLowerCase( | 630 bool MimeUtil::IsDefaultCodecSupportedLowerCase( |
934 const std::string& mime_type_lower_case) const { | 631 const std::string& mime_type_lower_case) const { |
935 Codec default_codec = Codec::INVALID_CODEC; | 632 Codec default_codec = Codec::INVALID_CODEC; |
936 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 633 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
937 return false; | 634 return false; |
938 return IsCodecSupported(default_codec); | 635 return IsCodecSupported(default_codec); |
939 } | 636 } |
940 | 637 |
941 //---------------------------------------------------------------------------- | |
942 // Wrappers for the singleton | |
943 //---------------------------------------------------------------------------- | |
944 | |
945 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, | |
946 std::string* mime_type) { | |
947 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); | |
948 } | |
949 | |
950 bool GetMimeTypeFromFile(const base::FilePath& file_path, | |
951 std::string* mime_type) { | |
952 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); | |
953 } | |
954 | |
955 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, | |
956 std::string* mime_type) { | |
957 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); | |
958 } | |
959 | |
960 bool GetPreferredExtensionForMimeType(const std::string& mime_type, | |
961 base::FilePath::StringType* extension) { | |
962 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, | |
963 extension); | |
964 } | |
965 | |
966 bool IsSupportedMediaMimeType(const std::string& mime_type) { | 638 bool IsSupportedMediaMimeType(const std::string& mime_type) { |
967 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); | 639 return g_media_mime_util.Get().IsSupportedMediaMimeType(mime_type); |
968 } | |
969 | |
970 bool MatchesMimeType(const std::string& mime_type_pattern, | |
971 const std::string& mime_type) { | |
972 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type); | |
973 } | |
974 | |
975 bool ParseMimeTypeWithoutParameter(const std::string& type_string, | |
976 std::string* top_level_type, | |
977 std::string* subtype) { | |
978 return g_mime_util.Get().ParseMimeTypeWithoutParameter( | |
979 type_string, top_level_type, subtype); | |
980 } | |
981 | |
982 bool IsValidTopLevelMimeType(const std::string& type_string) { | |
983 return g_mime_util.Get().IsValidTopLevelMimeType(type_string); | |
984 } | 640 } |
985 | 641 |
986 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { | 642 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { |
987 return g_mime_util.Get().AreSupportedMediaCodecs(codecs); | 643 return g_media_mime_util.Get().AreSupportedMediaCodecs(codecs); |
988 } | 644 } |
989 | 645 |
990 bool IsStrictMediaMimeType(const std::string& mime_type) { | 646 bool IsStrictMediaMimeType(const std::string& mime_type) { |
991 return g_mime_util.Get().IsStrictMediaMimeType(mime_type); | 647 return g_media_mime_util.Get().IsStrictMediaMimeType(mime_type); |
992 } | 648 } |
993 | 649 |
994 SupportsType IsSupportedStrictMediaMimeType( | 650 SupportsType IsSupportedStrictMediaMimeType( |
995 const std::string& mime_type, | 651 const std::string& mime_type, |
996 const std::vector<std::string>& codecs) { | 652 const std::vector<std::string>& codecs) { |
997 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); | 653 return g_media_mime_util.Get().IsSupportedStrictMediaMimeType( |
| 654 mime_type, codecs); |
998 } | 655 } |
999 | 656 |
1000 void ParseCodecString(const std::string& codecs, | 657 void ParseCodecString(const std::string& codecs, |
1001 std::vector<std::string>* codecs_out, | 658 std::vector<std::string>* codecs_out, |
1002 const bool strip) { | 659 const bool strip) { |
1003 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); | 660 g_media_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); |
1004 } | |
1005 | |
1006 namespace { | |
1007 | |
1008 // From http://www.w3schools.com/media/media_mimeref.asp and | |
1009 // http://plugindoc.mozdev.org/winmime.php | |
1010 static const char* const kStandardImageTypes[] = { | |
1011 "image/bmp", | |
1012 "image/cis-cod", | |
1013 "image/gif", | |
1014 "image/ief", | |
1015 "image/jpeg", | |
1016 "image/webp", | |
1017 "image/pict", | |
1018 "image/pipeg", | |
1019 "image/png", | |
1020 "image/svg+xml", | |
1021 "image/tiff", | |
1022 "image/vnd.microsoft.icon", | |
1023 "image/x-cmu-raster", | |
1024 "image/x-cmx", | |
1025 "image/x-icon", | |
1026 "image/x-portable-anymap", | |
1027 "image/x-portable-bitmap", | |
1028 "image/x-portable-graymap", | |
1029 "image/x-portable-pixmap", | |
1030 "image/x-rgb", | |
1031 "image/x-xbitmap", | |
1032 "image/x-xpixmap", | |
1033 "image/x-xwindowdump" | |
1034 }; | |
1035 static const char* const kStandardAudioTypes[] = { | |
1036 "audio/aac", | |
1037 "audio/aiff", | |
1038 "audio/amr", | |
1039 "audio/basic", | |
1040 "audio/midi", | |
1041 "audio/mp3", | |
1042 "audio/mp4", | |
1043 "audio/mpeg", | |
1044 "audio/mpeg3", | |
1045 "audio/ogg", | |
1046 "audio/vorbis", | |
1047 "audio/wav", | |
1048 "audio/webm", | |
1049 "audio/x-m4a", | |
1050 "audio/x-ms-wma", | |
1051 "audio/vnd.rn-realaudio", | |
1052 "audio/vnd.wave" | |
1053 }; | |
1054 static const char* const kStandardVideoTypes[] = { | |
1055 "video/avi", | |
1056 "video/divx", | |
1057 "video/flc", | |
1058 "video/mp4", | |
1059 "video/mpeg", | |
1060 "video/ogg", | |
1061 "video/quicktime", | |
1062 "video/sd-video", | |
1063 "video/webm", | |
1064 "video/x-dv", | |
1065 "video/x-m4v", | |
1066 "video/x-mpeg", | |
1067 "video/x-ms-asf", | |
1068 "video/x-ms-wmv" | |
1069 }; | |
1070 | |
1071 struct StandardType { | |
1072 const char* const leading_mime_type; | |
1073 const char* const* standard_types; | |
1074 size_t standard_types_len; | |
1075 }; | |
1076 static const StandardType kStandardTypes[] = { | |
1077 { "image/", kStandardImageTypes, arraysize(kStandardImageTypes) }, | |
1078 { "audio/", kStandardAudioTypes, arraysize(kStandardAudioTypes) }, | |
1079 { "video/", kStandardVideoTypes, arraysize(kStandardVideoTypes) }, | |
1080 { NULL, NULL, 0 } | |
1081 }; | |
1082 | |
1083 void GetExtensionsFromHardCodedMappings( | |
1084 const MimeInfo* mappings, | |
1085 size_t mappings_len, | |
1086 const std::string& leading_mime_type, | |
1087 base::hash_set<base::FilePath::StringType>* extensions) { | |
1088 for (size_t i = 0; i < mappings_len; ++i) { | |
1089 if (StartsWithASCII(mappings[i].mime_type, leading_mime_type, false)) { | |
1090 std::vector<string> this_extensions; | |
1091 base::SplitString(mappings[i].extensions, ',', &this_extensions); | |
1092 for (size_t j = 0; j < this_extensions.size(); ++j) { | |
1093 #if defined(OS_WIN) | |
1094 base::FilePath::StringType extension( | |
1095 base::UTF8ToWide(this_extensions[j])); | |
1096 #else | |
1097 base::FilePath::StringType extension(this_extensions[j]); | |
1098 #endif | |
1099 extensions->insert(extension); | |
1100 } | |
1101 } | |
1102 } | |
1103 } | |
1104 | |
1105 void GetExtensionsHelper( | |
1106 const char* const* standard_types, | |
1107 size_t standard_types_len, | |
1108 const std::string& leading_mime_type, | |
1109 base::hash_set<base::FilePath::StringType>* extensions) { | |
1110 for (size_t i = 0; i < standard_types_len; ++i) { | |
1111 g_mime_util.Get().GetPlatformExtensionsForMimeType(standard_types[i], | |
1112 extensions); | |
1113 } | |
1114 | |
1115 // Also look up the extensions from hard-coded mappings in case that some | |
1116 // supported extensions are not registered in the system registry, like ogg. | |
1117 GetExtensionsFromHardCodedMappings(primary_mappings, | |
1118 arraysize(primary_mappings), | |
1119 leading_mime_type, | |
1120 extensions); | |
1121 | |
1122 GetExtensionsFromHardCodedMappings(secondary_mappings, | |
1123 arraysize(secondary_mappings), | |
1124 leading_mime_type, | |
1125 extensions); | |
1126 } | |
1127 | |
1128 // Note that the elements in the source set will be appended to the target | |
1129 // vector. | |
1130 template<class T> | |
1131 void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) { | |
1132 size_t old_target_size = target->size(); | |
1133 target->resize(old_target_size + source->size()); | |
1134 size_t i = 0; | |
1135 for (typename base::hash_set<T>::iterator iter = source->begin(); | |
1136 iter != source->end(); ++iter, ++i) | |
1137 (*target)[old_target_size + i] = *iter; | |
1138 } | |
1139 | |
1140 } // namespace | |
1141 | |
1142 void GetExtensionsForMimeType( | |
1143 const std::string& unsafe_mime_type, | |
1144 std::vector<base::FilePath::StringType>* extensions) { | |
1145 if (unsafe_mime_type == "*/*" || unsafe_mime_type == "*") | |
1146 return; | |
1147 | |
1148 const std::string mime_type = base::StringToLowerASCII(unsafe_mime_type); | |
1149 base::hash_set<base::FilePath::StringType> unique_extensions; | |
1150 | |
1151 if (EndsWith(mime_type, "/*", false)) { | |
1152 std::string leading_mime_type = mime_type.substr(0, mime_type.length() - 1); | |
1153 | |
1154 // Find the matching StandardType from within kStandardTypes, or fall | |
1155 // through to the last (default) StandardType. | |
1156 const StandardType* type = NULL; | |
1157 for (size_t i = 0; i < arraysize(kStandardTypes); ++i) { | |
1158 type = &(kStandardTypes[i]); | |
1159 if (type->leading_mime_type && | |
1160 leading_mime_type == type->leading_mime_type) | |
1161 break; | |
1162 } | |
1163 DCHECK(type); | |
1164 GetExtensionsHelper(type->standard_types, | |
1165 type->standard_types_len, | |
1166 leading_mime_type, | |
1167 &unique_extensions); | |
1168 } else { | |
1169 g_mime_util.Get().GetPlatformExtensionsForMimeType(mime_type, | |
1170 &unique_extensions); | |
1171 | |
1172 // Also look up the extensions from hard-coded mappings in case that some | |
1173 // supported extensions are not registered in the system registry, like ogg. | |
1174 GetExtensionsFromHardCodedMappings(primary_mappings, | |
1175 arraysize(primary_mappings), | |
1176 mime_type, | |
1177 &unique_extensions); | |
1178 | |
1179 GetExtensionsFromHardCodedMappings(secondary_mappings, | |
1180 arraysize(secondary_mappings), | |
1181 mime_type, | |
1182 &unique_extensions); | |
1183 } | |
1184 | |
1185 HashSetToVector(&unique_extensions, extensions); | |
1186 } | 661 } |
1187 | 662 |
1188 void RemoveProprietaryMediaTypesAndCodecsForTests() { | 663 void RemoveProprietaryMediaTypesAndCodecsForTests() { |
1189 g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); | 664 g_media_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); |
1190 } | 665 } |
1191 | 666 |
1192 void AddMultipartValueForUpload(const std::string& value_name, | 667 } // namespace media |
1193 const std::string& value, | |
1194 const std::string& mime_boundary, | |
1195 const std::string& content_type, | |
1196 std::string* post_data) { | |
1197 DCHECK(post_data); | |
1198 // First line is the boundary. | |
1199 post_data->append("--" + mime_boundary + "\r\n"); | |
1200 // Next line is the Content-disposition. | |
1201 post_data->append("Content-Disposition: form-data; name=\"" + | |
1202 value_name + "\"\r\n"); | |
1203 if (!content_type.empty()) { | |
1204 // If Content-type is specified, the next line is that. | |
1205 post_data->append("Content-Type: " + content_type + "\r\n"); | |
1206 } | |
1207 // Leave an empty line and append the value. | |
1208 post_data->append("\r\n" + value + "\r\n"); | |
1209 } | |
1210 | |
1211 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, | |
1212 std::string* post_data) { | |
1213 DCHECK(post_data); | |
1214 post_data->append("--" + mime_boundary + "--\r\n"); | |
1215 } | |
1216 | |
1217 } // namespace net | |
OLD | NEW |