| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "build/build_config.h" |
| 18 #include "net/base/mime_util.h" | 13 #include "media/base/mime_util.h" |
| 19 #include "net/base/platform_mime_util.h" | |
| 20 #include "net/http/http_util.h" | |
| 21 | 14 |
| 22 #if defined(OS_ANDROID) | 15 #if defined(OS_ANDROID) |
| 23 #include "base/android/build_info.h" | 16 #include "base/android/build_info.h" |
| 24 #endif | 17 #endif |
| 25 | 18 |
| 26 using std::string; | 19 namespace media { |
| 27 | |
| 28 namespace net { | |
| 29 | 20 |
| 30 // Singleton utility class for mime types. | 21 // Singleton utility class for mime types. |
| 31 class MimeUtil : public PlatformMimeUtil { | 22 class MimeUtil { |
| 32 public: | 23 public: |
| 33 enum Codec { | 24 enum Codec { |
| 34 INVALID_CODEC, | 25 INVALID_CODEC, |
| 35 PCM, | 26 PCM, |
| 36 MP3, | 27 MP3, |
| 37 MPEG2_AAC_LC, | 28 MPEG2_AAC_LC, |
| 38 MPEG2_AAC_MAIN, | 29 MPEG2_AAC_MAIN, |
| 39 MPEG2_AAC_SSR, | 30 MPEG2_AAC_SSR, |
| 40 MPEG4_AAC_LC, | 31 MPEG4_AAC_LC, |
| 41 MPEG4_AAC_SBR_v1, | 32 MPEG4_AAC_SBR_v1, |
| 42 MPEG4_AAC_SBR_PS_v2, | 33 MPEG4_AAC_SBR_PS_v2, |
| 43 VORBIS, | 34 VORBIS, |
| 44 OPUS, | 35 OPUS, |
| 45 H264_BASELINE, | 36 H264_BASELINE, |
| 46 H264_MAIN, | 37 H264_MAIN, |
| 47 H264_HIGH, | 38 H264_HIGH, |
| 48 VP8, | 39 VP8, |
| 49 VP9, | 40 VP9, |
| 50 THEORA | 41 THEORA |
| 51 }; | 42 }; |
| 52 | 43 |
| 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; | 44 bool IsSupportedMediaMimeType(const std::string& mime_type) const; |
| 63 | 45 |
| 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; | 46 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; |
| 74 | 47 |
| 75 void ParseCodecString(const std::string& codecs, | 48 void ParseCodecString(const std::string& codecs, |
| 76 std::vector<std::string>* codecs_out, | 49 std::vector<std::string>* codecs_out, |
| 77 bool strip); | 50 bool strip); |
| 78 | 51 |
| 79 bool IsStrictMediaMimeType(const std::string& mime_type) const; | 52 bool IsStrictMediaMimeType(const std::string& mime_type) const; |
| 80 SupportsType IsSupportedStrictMediaMimeType( | 53 SupportsType IsSupportedStrictMediaMimeType( |
| 81 const std::string& mime_type, | 54 const std::string& mime_type, |
| 82 const std::vector<std::string>& codecs) const; | 55 const std::vector<std::string>& codecs) const; |
| 83 | 56 |
| 84 void RemoveProprietaryMediaTypesAndCodecsForTests(); | 57 void RemoveProprietaryMediaTypesAndCodecsForTests(); |
| 85 | 58 |
| 86 private: | 59 private: |
| 87 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; | 60 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; |
| 88 | 61 |
| 89 typedef base::hash_set<std::string> MimeMappings; | |
| 90 | |
| 91 typedef base::hash_set<int> CodecSet; | 62 typedef base::hash_set<int> CodecSet; |
| 92 typedef std::map<std::string, CodecSet> StrictMappings; | 63 typedef std::map<std::string, CodecSet> StrictMappings; |
| 93 struct CodecEntry { | 64 struct CodecEntry { |
| 94 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} | 65 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} |
| 95 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} | 66 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} |
| 96 Codec codec; | 67 Codec codec; |
| 97 bool is_ambiguous; | 68 bool is_ambiguous; |
| 98 }; | 69 }; |
| 99 typedef std::map<std::string, CodecEntry> StringToCodecMappings; | 70 typedef std::map<std::string, CodecEntry> StringToCodecMappings; |
| 100 | 71 |
| 101 MimeUtil(); | 72 MimeUtil(); |
| 102 | 73 |
| 74 // For faster lookup, keep hash sets. |
| 75 void InitializeMimeTypeMaps(); |
| 76 |
| 103 // Returns IsSupported if all codec IDs in |codecs| are unambiguous | 77 // Returns IsSupported if all codec IDs in |codecs| are unambiguous |
| 104 // and are supported by the platform. MayBeSupported is returned if | 78 // and are supported by the platform. MayBeSupported is returned if |
| 105 // at least one codec ID in |codecs| is ambiguous but all the codecs | 79 // at least one codec ID in |codecs| is ambiguous but all the codecs |
| 106 // are supported by the platform. IsNotSupported is returned if at | 80 // are supported by the platform. IsNotSupported is returned if at |
| 107 // least one codec ID is not supported by the platform. | 81 // least one codec ID is not supported by the platform. |
| 108 SupportsType AreSupportedCodecs( | 82 SupportsType AreSupportedCodecs( |
| 109 const CodecSet& supported_codecs, | 83 const CodecSet& supported_codecs, |
| 110 const std::vector<std::string>& codecs) const; | 84 const std::vector<std::string>& codecs) const; |
| 111 | 85 |
| 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 | 86 // Converts a codec ID into an Codec enum value and indicates |
| 120 // whether the conversion was ambiguous. | 87 // whether the conversion was ambiguous. |
| 121 // Returns true if this method was able to map |codec_id| to a specific | 88 // 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 | 89 // Codec enum value. |codec| and |is_ambiguous| are only valid if true |
| 123 // is returned. Otherwise their value is undefined after the call. | 90 // is returned. Otherwise their value is undefined after the call. |
| 124 // |is_ambiguous| is true if |codec_id| did not have enough information to | 91 // |is_ambiguous| is true if |codec_id| did not have enough information to |
| 125 // unambiguously determine the proper Codec enum value. If |is_ambiguous| | 92 // unambiguously determine the proper Codec enum value. If |is_ambiguous| |
| 126 // is true |codec| contains the best guess for the intended Codec enum value. | 93 // is true |codec| contains the best guess for the intended Codec enum value. |
| 127 bool StringToCodec(const std::string& codec_id, | 94 bool StringToCodec(const std::string& codec_id, |
| 128 Codec* codec, | 95 Codec* codec, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 140 // associated with it. Returns false otherwise and the value of | 107 // associated with it. Returns false otherwise and the value of |
| 141 // |*default_codec| is undefined. | 108 // |*default_codec| is undefined. |
| 142 bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, | 109 bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, |
| 143 Codec* default_codec) const; | 110 Codec* default_codec) const; |
| 144 | 111 |
| 145 // Returns true if |mime_type_lower_case| has a default codec associated with | 112 // Returns true if |mime_type_lower_case| has a default codec associated with |
| 146 // it and IsCodecSupported() returns true for that particular codec. | 113 // it and IsCodecSupported() returns true for that particular codec. |
| 147 bool IsDefaultCodecSupportedLowerCase( | 114 bool IsDefaultCodecSupportedLowerCase( |
| 148 const std::string& mime_type_lower_case) const; | 115 const std::string& mime_type_lower_case) const; |
| 149 | 116 |
| 150 MimeMappings media_map_; | 117 using MimeTypes = base::hash_set<std::string>; |
| 118 MimeTypes media_map_; |
| 151 | 119 |
| 152 // A map of mime_types and hash map of the supported codecs for the mime_type. | 120 // A map of mime_types and hash map of the supported codecs for the mime_type. |
| 153 StrictMappings strict_format_map_; | 121 StrictMappings strict_format_map_; |
| 154 | 122 |
| 155 // Keeps track of whether proprietary codec support should be | 123 // Keeps track of whether proprietary codec support should be |
| 156 // advertised to callers. | 124 // advertised to callers. |
| 157 bool allow_proprietary_codecs_; | 125 bool allow_proprietary_codecs_; |
| 158 | 126 |
| 159 // Lookup table for string compare based string -> Codec mappings. | 127 // Lookup table for string compare based string -> Codec mappings. |
| 160 StringToCodecMappings string_to_codec_map_; | 128 StringToCodecMappings string_to_codec_map_; |
| 129 |
| 130 DISALLOW_COPY_AND_ASSIGN(MimeUtil); |
| 161 }; // class MimeUtil | 131 }; // class MimeUtil |
| 162 | 132 |
| 163 // This variable is Leaky because we need to access it from WorkerPool threads. | 133 // This variable is Leaky because it is accessed from WorkerPool threads. |
| 164 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = | 134 static base::LazyInstance<MimeUtil>::Leaky g_media_mime_util = |
| 165 LAZY_INSTANCE_INITIALIZER; | 135 LAZY_INSTANCE_INITIALIZER; |
| 166 | 136 |
| 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 | 137 |
| 300 // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type | 138 // 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 | 139 // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php |
| 302 // This set of codecs is supported by all variations of Chromium. | 140 // This set of codecs is supported by all variations of Chromium. |
| 303 static const char* const common_media_types[] = { | 141 static const char* const common_media_types[] = { |
| 304 // Ogg. | 142 // Ogg. |
| 305 "audio/ogg", | 143 "audio/ogg", |
| 306 "application/ogg", | 144 "application/ogg", |
| 307 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. | 145 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. |
| 308 "video/ogg", | 146 "video/ogg", |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 | 393 |
| 556 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; | 394 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; |
| 557 } | 395 } |
| 558 } | 396 } |
| 559 | 397 |
| 560 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { | 398 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { |
| 561 return media_map_.find(base::StringToLowerASCII(mime_type)) != | 399 return media_map_.find(base::StringToLowerASCII(mime_type)) != |
| 562 media_map_.end(); | 400 media_map_.end(); |
| 563 } | 401 } |
| 564 | 402 |
| 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 | 403 |
| 706 bool MimeUtil::AreSupportedMediaCodecs( | 404 bool MimeUtil::AreSupportedMediaCodecs( |
| 707 const std::vector<std::string>& codecs) const { | 405 const std::vector<std::string>& codecs) const { |
| 708 for (size_t i = 0; i < codecs.size(); ++i) { | 406 for (size_t i = 0; i < codecs.size(); ++i) { |
| 709 Codec codec = INVALID_CODEC; | 407 Codec codec = INVALID_CODEC; |
| 710 bool is_ambiguous = true; | 408 bool is_ambiguous = true; |
| 711 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || | 409 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || |
| 712 !IsCodecSupported(codec)) { | 410 !IsCodecSupported(codec)) { |
| 713 return false; | 411 return false; |
| 714 } | 412 } |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 } | 629 } |
| 932 | 630 |
| 933 bool MimeUtil::IsDefaultCodecSupportedLowerCase( | 631 bool MimeUtil::IsDefaultCodecSupportedLowerCase( |
| 934 const std::string& mime_type_lower_case) const { | 632 const std::string& mime_type_lower_case) const { |
| 935 Codec default_codec = Codec::INVALID_CODEC; | 633 Codec default_codec = Codec::INVALID_CODEC; |
| 936 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 634 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 937 return false; | 635 return false; |
| 938 return IsCodecSupported(default_codec); | 636 return IsCodecSupported(default_codec); |
| 939 } | 637 } |
| 940 | 638 |
| 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) { | 639 bool IsSupportedMediaMimeType(const std::string& mime_type) { |
| 967 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); | 640 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 } | 641 } |
| 985 | 642 |
| 986 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { | 643 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { |
| 987 return g_mime_util.Get().AreSupportedMediaCodecs(codecs); | 644 return g_media_mime_util.Get().AreSupportedMediaCodecs(codecs); |
| 988 } | 645 } |
| 989 | 646 |
| 990 bool IsStrictMediaMimeType(const std::string& mime_type) { | 647 bool IsStrictMediaMimeType(const std::string& mime_type) { |
| 991 return g_mime_util.Get().IsStrictMediaMimeType(mime_type); | 648 return g_media_mime_util.Get().IsStrictMediaMimeType(mime_type); |
| 992 } | 649 } |
| 993 | 650 |
| 994 SupportsType IsSupportedStrictMediaMimeType( | 651 SupportsType IsSupportedStrictMediaMimeType( |
| 995 const std::string& mime_type, | 652 const std::string& mime_type, |
| 996 const std::vector<std::string>& codecs) { | 653 const std::vector<std::string>& codecs) { |
| 997 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); | 654 return g_media_mime_util.Get().IsSupportedStrictMediaMimeType( |
| 655 mime_type, codecs); |
| 998 } | 656 } |
| 999 | 657 |
| 1000 void ParseCodecString(const std::string& codecs, | 658 void ParseCodecString(const std::string& codecs, |
| 1001 std::vector<std::string>* codecs_out, | 659 std::vector<std::string>* codecs_out, |
| 1002 const bool strip) { | 660 const bool strip) { |
| 1003 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); | 661 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 } | 662 } |
| 1187 | 663 |
| 1188 void RemoveProprietaryMediaTypesAndCodecsForTests() { | 664 void RemoveProprietaryMediaTypesAndCodecsForTests() { |
| 1189 g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); | 665 g_media_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); |
| 1190 } | 666 } |
| 1191 | 667 |
| 1192 void AddMultipartValueForUpload(const std::string& value_name, | 668 } // 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 |