1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <algorithm> 6#include <iterator> 7#include <map> 8#include <string> 9 10#include "base/containers/hash_tables.h" 11#include "base/lazy_instance.h" 12#include "base/logging.h" 13#include "base/stl_util.h" 14#include "base/strings/string_number_conversions.h" 15#include "base/strings/string_split.h" 16#include "base/strings/string_util.h" 17#include "base/strings/utf_string_conversions.h" 18#include "net/base/mime_util.h" 19#include "net/base/platform_mime_util.h" 20#include "net/http/http_util.h" 21 22#if defined(OS_ANDROID) 23#include "base/android/build_info.h" 24#endif 25 26using std::string; 27 28namespace { 29 30struct MediaType { 31 const char name[12]; 32 const char matcher[13]; 33}; 34 35static const MediaType kIanaMediaTypes[] = { 36 { "application", "application/" }, 37 { "audio", "audio/" }, 38 { "example", "example/" }, 39 { "image", "image/" }, 40 { "message", "message/" }, 41 { "model", "model/" }, 42 { "multipart", "multipart/" }, 43 { "text", "text/" }, 44 { "video", "video/" }, 45}; 46 47} // namespace 48 49namespace net { 50 51// Singleton utility class for mime types. 52class MimeUtil : public PlatformMimeUtil { 53 public: 54 enum Codec { 55 INVALID_CODEC, 56 PCM, 57 MP3, 58 MPEG2_AAC_LC, 59 MPEG2_AAC_MAIN, 60 MPEG2_AAC_SSR, 61 MPEG4_AAC_LC, 62 MPEG4_AAC_SBRv1, 63 VORBIS, 64 OPUS, 65 H264_BASELINE, 66 H264_MAIN, 67 H264_HIGH, 68 VP8, 69 VP9, 70 THEORA 71 }; 72 73 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 74 std::string* mime_type) const; 75 76 bool GetMimeTypeFromFile(const base::FilePath& file_path, 77 std::string* mime_type) const; 78 79 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 80 std::string* mime_type) const; 81 82 bool IsSupportedImageMimeType(const std::string& mime_type) const; 83 bool IsSupportedMediaMimeType(const std::string& mime_type) const; 84 bool IsSupportedNonImageMimeType(const std::string& mime_type) const; 85 bool IsUnsupportedTextMimeType(const std::string& mime_type) const; 86 bool IsSupportedJavascriptMimeType(const std::string& mime_type) const; 87 88 bool IsSupportedMimeType(const std::string& mime_type) const; 89 90 bool MatchesMimeType(const std::string &mime_type_pattern, 91 const std::string &mime_type) const; 92 93 bool ParseMimeTypeWithoutParameter(const std::string& type_string, 94 std::string* top_level_type, 95 std::string* subtype) const; 96 97 bool IsValidTopLevelMimeType(const std::string& type_string) const; 98 99 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; 100 101 void ParseCodecString(const std::string& codecs, 102 std::vector<std::string>* codecs_out, 103 bool strip); 104 105 bool IsStrictMediaMimeType(const std::string& mime_type) const; 106 SupportsType IsSupportedStrictMediaMimeType( 107 const std::string& mime_type, 108 const std::vector<std::string>& codecs) const; 109 110 void RemoveProprietaryMediaTypesAndCodecsForTests(); 111 112 private: 113 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; 114 115 typedef base::hash_set<std::string> MimeMappings; 116 117 typedef base::hash_set<int> CodecSet; 118 typedef std::map<std::string, CodecSet> StrictMappings; 119 struct CodecEntry { 120 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} 121 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} 122 Codec codec; 123 bool is_ambiguous; 124 }; 125 typedef std::map<std::string, CodecEntry> StringToCodecMappings; 126 127 MimeUtil(); 128 129 // Returns IsSupported if all codec IDs in |codecs| are unambiguous 130 // and are supported by the platform. MayBeSupported is returned if 131 // at least one codec ID in |codecs| is ambiguous but all the codecs 132 // are supported by the platform. IsNotSupported is returned if at 133 // least one codec ID is not supported by the platform. 134 SupportsType AreSupportedCodecs( 135 const CodecSet& supported_codecs, 136 const std::vector<std::string>& codecs) const; 137 138 // For faster lookup, keep hash sets. 139 void InitializeMimeTypeMaps(); 140 141 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, 142 bool include_platform_types, 143 std::string* mime_type) const; 144 145 // Converts a codec ID into an Codec enum value and indicates 146 // whether the conversion was ambiguous. 147 // Returns true if this method was able to map |codec_id| to a specific 148 // Codec enum value. |codec| and |is_ambiguous| are only valid if true 149 // is returned. Otherwise their value is undefined after the call. 150 // |is_ambiguous| is true if |codec_id| did not have enough information to 151 // unambiguously determine the proper Codec enum value. If |is_ambiguous| 152 // is true |codec| contains the best guess for the intended Codec enum value. 153 bool StringToCodec(const std::string& codec_id, 154 Codec* codec, 155 bool* is_ambiguous) const; 156 157 // Returns true if |codec| is supported by the platform. 158 // Note: This method will return false if the platform supports proprietary 159 // codecs but |allow_proprietary_codecs_| is set to false. 160 bool IsCodecSupported(Codec codec) const; 161 162 // Returns true if |codec| refers to a proprietary codec. 163 bool IsCodecProprietary(Codec codec) const; 164 165 // Returns true and sets |*default_codec| if |mime_type| has a 166 // default codec associated with it. 167 // Returns false otherwise and the value of |*default_codec| is undefined. 168 bool GetDefaultCodec(const std::string& mime_type, 169 Codec* default_codec) const; 170 171 // Returns true if |mime_type| has a default codec associated with it 172 // and IsCodecSupported() returns true for that particular codec. 173 bool IsDefaultCodecSupported(const std::string& mime_type) const; 174 175 MimeMappings image_map_; 176 MimeMappings media_map_; 177 MimeMappings non_image_map_; 178 MimeMappings unsupported_text_map_; 179 MimeMappings javascript_map_; 180 181 // A map of mime_types and hash map of the supported codecs for the mime_type. 182 StrictMappings strict_format_map_; 183 184 // Keeps track of whether proprietary codec support should be 185 // advertised to callers. 186 bool allow_proprietary_codecs_; 187 188 // Lookup table for string compare based string -> Codec mappings. 189 StringToCodecMappings string_to_codec_map_; 190}; // class MimeUtil 191 192// This variable is Leaky because we need to access it from WorkerPool threads. 193static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 194 LAZY_INSTANCE_INITIALIZER; 195 196struct MimeInfo { 197 const char* mime_type; 198 const char* extensions; // comma separated list 199}; 200 201static const MimeInfo primary_mappings[] = { 202 { "text/html", "html,htm,shtml,shtm" }, 203 { "text/css", "css" }, 204 { "text/xml", "xml" }, 205 { "image/gif", "gif" }, 206 { "image/jpeg", "jpeg,jpg" }, 207 { "image/webp", "webp" }, 208 { "image/png", "png" }, 209 { "video/mp4", "mp4,m4v" }, 210 { "audio/x-m4a", "m4a" }, 211 { "audio/mp3", "mp3" }, 212 { "video/ogg", "ogv,ogm" }, 213 { "audio/ogg", "ogg,oga,opus" }, 214 { "video/webm", "webm" }, 215 { "audio/webm", "webm" }, 216 { "audio/wav", "wav" }, 217 { "application/xhtml+xml", "xhtml,xht,xhtm" }, 218 { "application/x-chrome-extension", "crx" }, 219 { "multipart/related", "mhtml,mht" } 220}; 221 222static const MimeInfo secondary_mappings[] = { 223 { "application/octet-stream", "exe,com,bin" }, 224 { "application/gzip", "gz" }, 225 { "application/pdf", "pdf" }, 226 { "application/postscript", "ps,eps,ai" }, 227 { "application/javascript", "js" }, 228 { "application/font-woff", "woff" }, 229 { "image/bmp", "bmp" }, 230 { "image/x-icon", "ico" }, 231 { "image/vnd.microsoft.icon", "ico" }, 232 { "image/jpeg", "jfif,pjpeg,pjp" }, 233 { "image/tiff", "tiff,tif" }, 234 { "image/x-xbitmap", "xbm" }, 235 { "image/svg+xml", "svg,svgz" }, 236 { "image/x-png", "png"}, 237 { "message/rfc822", "eml" }, 238 { "text/plain", "txt,text" }, 239 { "text/html", "ehtml" }, 240 { "application/rss+xml", "rss" }, 241 { "application/rdf+xml", "rdf" }, 242 { "text/xml", "xsl,xbl,xslt" }, 243 { "application/vnd.mozilla.xul+xml", "xul" }, 244 { "application/x-shockwave-flash", "swf,swl" }, 245 { "application/pkcs7-mime", "p7m,p7c,p7z" }, 246 { "application/pkcs7-signature", "p7s" }, 247 { "application/x-mpegurl", "m3u8" }, 248}; 249 250static const char* FindMimeType(const MimeInfo* mappings, 251 size_t mappings_len, 252 const char* ext) { 253 size_t ext_len = strlen(ext); 254 255 for (size_t i = 0; i < mappings_len; ++i) { 256 const char* extensions = mappings[i].extensions; 257 for (;;) { 258 size_t end_pos = strcspn(extensions, ","); 259 if (end_pos == ext_len && 260 base::strncasecmp(extensions, ext, ext_len) == 0) 261 return mappings[i].mime_type; 262 extensions += end_pos; 263 if (!*extensions) 264 break; 265 extensions += 1; // skip over comma 266 } 267 } 268 return NULL; 269} 270 271bool MimeUtil::GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 272 string* result) const { 273 return GetMimeTypeFromExtensionHelper(ext, true, result); 274} 275 276bool MimeUtil::GetWellKnownMimeTypeFromExtension( 277 const base::FilePath::StringType& ext, 278 string* result) const { 279 return GetMimeTypeFromExtensionHelper(ext, false, result); 280} 281 282bool MimeUtil::GetMimeTypeFromFile(const base::FilePath& file_path, 283 string* result) const { 284 base::FilePath::StringType file_name_str = file_path.Extension(); 285 if (file_name_str.empty()) 286 return false; 287 return GetMimeTypeFromExtension(file_name_str.substr(1), result); 288} 289 290bool MimeUtil::GetMimeTypeFromExtensionHelper( 291 const base::FilePath::StringType& ext, 292 bool include_platform_types, 293 string* result) const { 294 // Avoids crash when unable to handle a long file path. See crbug.com/48733. 295 const unsigned kMaxFilePathSize = 65536; 296 if (ext.length() > kMaxFilePathSize) 297 return false; 298 299 // We implement the same algorithm as Mozilla for mapping a file extension to 300 // a mime type. That is, we first check a hard-coded list (that cannot be 301 // overridden), and then if not found there, we defer to the system registry. 302 // Finally, we scan a secondary hard-coded list to catch types that we can 303 // deduce but that we also want to allow the OS to override. 304 305 base::FilePath path_ext(ext); 306 const string ext_narrow_str = path_ext.AsUTF8Unsafe(); 307 const char* mime_type = FindMimeType(primary_mappings, 308 arraysize(primary_mappings), 309 ext_narrow_str.c_str()); 310 if (mime_type) { 311 *result = mime_type; 312 return true; 313 } 314 315 if (include_platform_types && GetPlatformMimeTypeFromExtension(ext, result)) 316 return true; 317 318 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings), 319 ext_narrow_str.c_str()); 320 if (mime_type) { 321 *result = mime_type; 322 return true; 323 } 324 325 return false; 326} 327 328// From WebKit's WebCore/platform/MIMETypeRegistry.cpp: 329 330static const char* const supported_image_types[] = { 331 "image/jpeg", 332 "image/pjpeg", 333 "image/jpg", 334 "image/webp", 335 "image/png", 336 "image/gif", 337 "image/bmp", 338 "image/vnd.microsoft.icon", // ico 339 "image/x-icon", // ico 340 "image/x-xbitmap", // xbm 341 "image/x-png" 342}; 343 344// A list of media types: http://en.wikipedia.org/wiki/Internet_media_type 345// A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php 346// This set of codecs is supported by all variations of Chromium. 347static const char* const common_media_types[] = { 348 // Ogg. 349 "audio/ogg", 350 "application/ogg", 351#if !defined(OS_ANDROID) // Android doesn't support Ogg Theora. 352 "video/ogg", 353#endif 354 355 // WebM. 356 "video/webm", 357 "audio/webm", 358 359 // Wav. 360 "audio/wav", 361 "audio/x-wav", 362 363#if defined(OS_ANDROID) 364 // HLS. Supported by Android ICS and above. 365 "application/vnd.apple.mpegurl", 366 "application/x-mpegurl", 367#endif 368}; 369 370// List of proprietary types only supported by Google Chrome. 371static const char* const proprietary_media_types[] = { 372 // MPEG-4. 373 "video/mp4", 374 "video/x-m4v", 375 "audio/mp4", 376 "audio/x-m4a", 377 378 // MP3. 379 "audio/mp3", 380 "audio/x-mp3", 381 "audio/mpeg", 382 383#if defined(ENABLE_MPEG2TS_STREAM_PARSER) 384 // MPEG-2 TS. 385 "video/mp2t", 386#endif 387}; 388 389// Note: 390// - does not include javascript types list (see supported_javascript_types) 391// - does not include types starting with "text/" (see 392// IsSupportedNonImageMimeType()) 393static const char* const supported_non_image_types[] = { 394 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type 395 "application/xml", 396 "application/atom+xml", 397 "application/rss+xml", 398 "application/xhtml+xml", 399 "application/json", 400 "multipart/related", // For MHTML support. 401 "multipart/x-mixed-replace" 402 // Note: ADDING a new type here will probably render it AS HTML. This can 403 // result in cross site scripting. 404}; 405 406// Dictionary of cryptographic file mime types. 407struct CertificateMimeTypeInfo { 408 const char* mime_type; 409 CertificateMimeType cert_type; 410}; 411 412static const CertificateMimeTypeInfo supported_certificate_types[] = { 413 { "application/x-x509-user-cert", 414 CERTIFICATE_MIME_TYPE_X509_USER_CERT }, 415#if defined(OS_ANDROID) 416 { "application/x-x509-ca-cert", CERTIFICATE_MIME_TYPE_X509_CA_CERT }, 417 { "application/x-pkcs12", CERTIFICATE_MIME_TYPE_PKCS12_ARCHIVE }, 418#endif 419}; 420 421// These types are excluded from the logic that allows all text/ types because 422// while they are technically text, it's very unlikely that a user expects to 423// see them rendered in text form. 424static const char* const unsupported_text_types[] = { 425 "text/calendar", 426 "text/x-calendar", 427 "text/x-vcalendar", 428 "text/vcalendar", 429 "text/vcard", 430 "text/x-vcard", 431 "text/directory", 432 "text/ldif", 433 "text/qif", 434 "text/x-qif", 435 "text/x-csv", 436 "text/x-vcf", 437 "text/rtf", 438 "text/comma-separated-values", 439 "text/csv", 440 "text/tab-separated-values", 441 "text/tsv", 442 "text/ofx", // http://crbug.com/162238 443 "text/vnd.sun.j2me.app-descriptor" // http://crbug.com/176450 444}; 445 446// Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript. 447// Mozilla 1.8 accepts application/javascript, application/ecmascript, and 448// application/x-javascript, but WinIE 7 doesn't. 449// WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and 450// text/livescript, but Mozilla 1.8 doesn't. 451// Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't. 452// Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a 453// whitespace-only string. 454// We want to accept all the values that either of these browsers accept, but 455// not other values. 456static const char* const supported_javascript_types[] = { 457 "text/javascript", 458 "text/ecmascript", 459 "application/javascript", 460 "application/ecmascript", 461 "application/x-javascript", 462 "text/javascript1.1", 463 "text/javascript1.2", 464 "text/javascript1.3", 465 "text/jscript", 466 "text/livescript" 467}; 468 469#if defined(OS_ANDROID) 470static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) { 471 switch (codec) { 472 case MimeUtil::INVALID_CODEC: 473 return false; 474 475 case MimeUtil::PCM: 476 case MimeUtil::MP3: 477 case MimeUtil::MPEG4_AAC_LC: 478 case MimeUtil::MPEG4_AAC_SBRv1: 479 case MimeUtil::H264_BASELINE: 480 case MimeUtil::H264_MAIN: 481 case MimeUtil::H264_HIGH: 482 case MimeUtil::VP8: 483 case MimeUtil::VORBIS: 484 return true; 485 486 case MimeUtil::MPEG2_AAC_LC: 487 case MimeUtil::MPEG2_AAC_MAIN: 488 case MimeUtil::MPEG2_AAC_SSR: 489 // MPEG-2 variants of AAC are not supported on Android. 490 return false; 491 492 case MimeUtil::VP9: 493 // VP9 is supported only in KitKat+ (API Level 19). 494 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; 495 496 case MimeUtil::OPUS: 497 // TODO(vigneshv): Change this similar to the VP9 check once Opus is 498 // supported on Android (http://crbug.com/318436). 499 return false; 500 501 case MimeUtil::THEORA: 502 return false; 503 } 504 505 return false; 506} 507 508static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { 509 // HLS codecs are supported in ICS and above (API level 14) 510 if ((!mimeType.compare("application/vnd.apple.mpegurl") || 511 !mimeType.compare("application/x-mpegurl")) && 512 base::android::BuildInfo::GetInstance()->sdk_int() < 14) { 513 return false; 514 } 515 return true; 516} 517#endif 518 519struct MediaFormatStrict { 520 const char* mime_type; 521 const char* codecs_list; 522}; 523 524// Following is the list of RFC 6381 compliant codecs: 525// mp4a.66 - MPEG-2 AAC MAIN 526// mp4a.67 - MPEG-2 AAC LC 527// mp4a.68 - MPEG-2 AAC SSR 528// mp4a.69 - MPEG-2 extension to MPEG-1 529// mp4a.6B - MPEG-1 audio 530// mp4a.40.2 - MPEG-4 AAC LC 531// mp4a.40.5 - MPEG-4 AAC SBRv1 532// 533// avc1.42E0xx - H.264 Baseline 534// avc1.4D40xx - H.264 Main 535// avc1.6400xx - H.264 High 536static const char kMP4AudioCodecsExpression[] = 537 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5"; 538static const char kMP4VideoCodecsExpression[] = 539 "avc1.42E00A,avc1.4D400A,avc1.64000A," \ 540 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5"; 541 542static const MediaFormatStrict format_codec_mappings[] = { 543 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" }, 544 { "audio/webm", "opus,vorbis" }, 545 { "audio/wav", "1" }, 546 { "audio/x-wav", "1" }, 547 { "video/ogg", "opus,theora,vorbis" }, 548 { "audio/ogg", "opus,vorbis" }, 549 { "application/ogg", "opus,theora,vorbis" }, 550 { "audio/mpeg", "mp3" }, 551 { "audio/mp3", "" }, 552 { "audio/x-mp3", "" }, 553 { "audio/mp4", kMP4AudioCodecsExpression }, 554 { "audio/x-m4a", kMP4AudioCodecsExpression }, 555 { "video/mp4", kMP4VideoCodecsExpression }, 556 { "video/x-m4v", kMP4VideoCodecsExpression }, 557 { "application/x-mpegurl", kMP4VideoCodecsExpression }, 558 { "application/vnd.apple.mpegurl", kMP4VideoCodecsExpression } 559}; 560 561struct CodecIDMappings { 562 const char* const codec_id; 563 MimeUtil::Codec codec; 564}; 565 566// List of codec IDs that provide enough information to determine the 567// codec and profile being requested. 568// 569// The "mp4a" strings come from RFC 6381. 570static const CodecIDMappings kUnambiguousCodecIDs[] = { 571 { "1", MimeUtil::PCM }, // We only allow this for WAV so it isn't ambiguous. 572 { "mp3", MimeUtil::MP3 }, 573 { "mp4a.66", MimeUtil::MPEG2_AAC_MAIN }, 574 { "mp4a.67", MimeUtil::MPEG2_AAC_LC }, 575 { "mp4a.68", MimeUtil::MPEG2_AAC_SSR }, 576 { "mp4a.69", MimeUtil::MP3 }, 577 { "mp4a.6B", MimeUtil::MP3 }, 578 { "mp4a.40.2", MimeUtil::MPEG4_AAC_LC }, 579 { "mp4a.40.5", MimeUtil::MPEG4_AAC_SBRv1 }, 580 { "vorbis", MimeUtil::VORBIS }, 581 { "opus", MimeUtil::OPUS }, 582 { "vp8", MimeUtil::VP8 }, 583 { "vp8.0", MimeUtil::VP8 }, 584 { "vp9", MimeUtil::VP9 }, 585 { "vp9.0", MimeUtil::VP9 }, 586 { "theora", MimeUtil::THEORA } 587}; 588 589// List of codec IDs that are ambiguous and don't provide 590// enough information to determine the codec and profile. 591// The codec in these entries indicate the codec and profile 592// we assume the user is trying to indicate. 593static const CodecIDMappings kAmbiguousCodecIDs[] = { 594 { "mp4a.40", MimeUtil::MPEG4_AAC_LC }, 595 { "avc1", MimeUtil::H264_BASELINE }, 596 { "avc3", MimeUtil::H264_BASELINE }, 597}; 598 599MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { 600 InitializeMimeTypeMaps(); 601} 602 603SupportsType MimeUtil::AreSupportedCodecs( 604 const CodecSet& supported_codecs, 605 const std::vector<std::string>& codecs) const { 606 DCHECK(!supported_codecs.empty()); 607 DCHECK(!codecs.empty()); 608 609 SupportsType result = IsSupported; 610 for (size_t i = 0; i < codecs.size(); ++i) { 611 bool is_ambiguous = true; 612 Codec codec = INVALID_CODEC; 613 if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) 614 return IsNotSupported; 615 616 if (!IsCodecSupported(codec) || 617 supported_codecs.find(codec) == supported_codecs.end()) { 618 return IsNotSupported; 619 } 620 621 if (is_ambiguous) 622 result = MayBeSupported; 623 } 624 625 return result; 626} 627 628void MimeUtil::InitializeMimeTypeMaps() { 629 for (size_t i = 0; i < arraysize(supported_image_types); ++i) 630 image_map_.insert(supported_image_types[i]); 631 632 // Initialize the supported non-image types. 633 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i) 634 non_image_map_.insert(supported_non_image_types[i]); 635 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) 636 non_image_map_.insert(supported_certificate_types[i].mime_type); 637 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i) 638 unsupported_text_map_.insert(unsupported_text_types[i]); 639 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 640 non_image_map_.insert(supported_javascript_types[i]); 641 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 642#if defined(OS_ANDROID) 643 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 644 continue; 645#endif 646 non_image_map_.insert(common_media_types[i]); 647 } 648#if defined(USE_PROPRIETARY_CODECS) 649 allow_proprietary_codecs_ = true; 650 651 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 652 non_image_map_.insert(proprietary_media_types[i]); 653#endif 654 655 // Initialize the supported media types. 656 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 657#if defined(OS_ANDROID) 658 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 659 continue; 660#endif 661 media_map_.insert(common_media_types[i]); 662 } 663#if defined(USE_PROPRIETARY_CODECS) 664 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 665 media_map_.insert(proprietary_media_types[i]); 666#endif 667 668 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 669 javascript_map_.insert(supported_javascript_types[i]); 670 671 for (size_t i = 0; i < arraysize(kUnambiguousCodecIDs); ++i) { 672 string_to_codec_map_[kUnambiguousCodecIDs[i].codec_id] = 673 CodecEntry(kUnambiguousCodecIDs[i].codec, false); 674 } 675 676 for (size_t i = 0; i < arraysize(kAmbiguousCodecIDs); ++i) { 677 string_to_codec_map_[kAmbiguousCodecIDs[i].codec_id] = 678 CodecEntry(kAmbiguousCodecIDs[i].codec, true); 679 } 680 681 // Initialize the strict supported media types. 682 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { 683 std::vector<std::string> mime_type_codecs; 684 ParseCodecString(format_codec_mappings[i].codecs_list, 685 &mime_type_codecs, 686 false); 687 688 CodecSet codecs; 689 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { 690 Codec codec = INVALID_CODEC; 691 bool is_ambiguous = true; 692 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous)); 693 DCHECK(!is_ambiguous); 694 codecs.insert(codec); 695 } 696 697 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; 698 } 699} 700 701bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 702 return image_map_.find(mime_type) != image_map_.end(); 703} 704 705bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 706 return media_map_.find(mime_type) != media_map_.end(); 707} 708 709bool MimeUtil::IsSupportedNonImageMimeType(const std::string& mime_type) const { 710 return non_image_map_.find(mime_type) != non_image_map_.end() || 711 (mime_type.compare(0, 5, "text/") == 0 && 712 !IsUnsupportedTextMimeType(mime_type)) || 713 (mime_type.compare(0, 12, "application/") == 0 && 714 MatchesMimeType("application/*+json", mime_type)); 715} 716 717bool MimeUtil::IsUnsupportedTextMimeType(const std::string& mime_type) const { 718 return unsupported_text_map_.find(mime_type) != unsupported_text_map_.end(); 719} 720 721bool MimeUtil::IsSupportedJavascriptMimeType( 722 const std::string& mime_type) const { 723 return javascript_map_.find(mime_type) != javascript_map_.end(); 724} 725 726// Mirrors WebViewImpl::CanShowMIMEType() 727bool MimeUtil::IsSupportedMimeType(const std::string& mime_type) const { 728 return (mime_type.compare(0, 6, "image/") == 0 && 729 IsSupportedImageMimeType(mime_type)) || 730 IsSupportedNonImageMimeType(mime_type); 731} 732 733// Tests for MIME parameter equality. Each parameter in the |mime_type_pattern| 734// must be matched by a parameter in the |mime_type|. If there are no 735// parameters in the pattern, the match is a success. 736bool MatchesMimeTypeParameters(const std::string& mime_type_pattern, 737 const std::string& mime_type) { 738 const std::string::size_type semicolon = mime_type_pattern.find(';'); 739 const std::string::size_type test_semicolon = mime_type.find(';'); 740 if (semicolon != std::string::npos) { 741 if (test_semicolon == std::string::npos) 742 return false; 743 744 std::vector<std::string> pattern_parameters; 745 base::SplitString(mime_type_pattern.substr(semicolon + 1), 746 ';', &pattern_parameters); 747 748 std::vector<std::string> test_parameters; 749 base::SplitString(mime_type.substr(test_semicolon + 1), 750 ';', &test_parameters); 751 752 sort(pattern_parameters.begin(), pattern_parameters.end()); 753 sort(test_parameters.begin(), test_parameters.end()); 754 std::vector<std::string> difference = 755 base::STLSetDifference<std::vector<std::string> >(pattern_parameters, 756 test_parameters); 757 return difference.size() == 0; 758 } 759 return true; 760} 761 762// This comparison handles absolute maching and also basic 763// wildcards. The plugin mime types could be: 764// application/x-foo 765// application/* 766// application/*+xml 767// * 768// Also tests mime parameters -- all parameters in the pattern must be present 769// in the tested type for a match to succeed. 770bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, 771 const std::string& mime_type) const { 772 // Verify caller is passing lowercase strings. 773 DCHECK_EQ(base::StringToLowerASCII(mime_type_pattern), mime_type_pattern); 774 DCHECK_EQ(base::StringToLowerASCII(mime_type), mime_type); 775 776 if (mime_type_pattern.empty()) 777 return false; 778 779 std::string::size_type semicolon = mime_type_pattern.find(';'); 780 const std::string base_pattern(mime_type_pattern.substr(0, semicolon)); 781 semicolon = mime_type.find(';'); 782 const std::string base_type(mime_type.substr(0, semicolon)); 783 784 if (base_pattern == "*" || base_pattern == "*/*") 785 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 786 787 const std::string::size_type star = base_pattern.find('*'); 788 if (star == std::string::npos) { 789 if (base_pattern == base_type) 790 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 791 else 792 return false; 793 } 794 795 // Test length to prevent overlap between |left| and |right|. 796 if (base_type.length() < base_pattern.length() - 1) 797 return false; 798 799 const std::string left(base_pattern.substr(0, star)); 800 const std::string right(base_pattern.substr(star + 1)); 801 802 if (base_type.find(left) != 0) 803 return false; 804 805 if (!right.empty() && 806 base_type.rfind(right) != base_type.length() - right.length()) 807 return false; 808 809 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 810} 811 812// See http://www.iana.org/assignments/media-types/media-types.xhtml 813static const char* legal_top_level_types[] = { 814 "application", 815 "audio", 816 "example", 817 "image", 818 "message", 819 "model", 820 "multipart", 821 "text", 822 "video", 823}; 824 825bool MimeUtil::ParseMimeTypeWithoutParameter( 826 const std::string& type_string, 827 std::string* top_level_type, 828 std::string* subtype) const { 829 std::vector<std::string> components; 830 base::SplitString(type_string, '/', &components); 831 if (components.size() != 2 || 832 !HttpUtil::IsToken(components[0]) || 833 !HttpUtil::IsToken(components[1])) 834 return false; 835 836 if (top_level_type) 837 *top_level_type = components[0]; 838 if (subtype) 839 *subtype = components[1]; 840 return true; 841} 842 843bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const { 844 std::string lower_type = base::StringToLowerASCII(type_string); 845 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { 846 if (lower_type.compare(legal_top_level_types[i]) == 0) 847 return true; 848 } 849 850 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); 851} 852 853bool MimeUtil::AreSupportedMediaCodecs( 854 const std::vector<std::string>& codecs) const { 855 for (size_t i = 0; i < codecs.size(); ++i) { 856 Codec codec = INVALID_CODEC; 857 bool is_ambiguous = true; 858 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || 859 !IsCodecSupported(codec)) { 860 return false; 861 } 862 } 863 return true; 864} 865 866void MimeUtil::ParseCodecString(const std::string& codecs, 867 std::vector<std::string>* codecs_out, 868 bool strip) { 869 std::string no_quote_codecs; 870 base::TrimString(codecs, "\"", &no_quote_codecs); 871 base::SplitString(no_quote_codecs, ',', codecs_out); 872 873 if (!strip) 874 return; 875 876 // Strip everything past the first '.' 877 for (std::vector<std::string>::iterator it = codecs_out->begin(); 878 it != codecs_out->end(); 879 ++it) { 880 size_t found = it->find_first_of('.'); 881 if (found != std::string::npos) 882 it->resize(found); 883 } 884} 885 886bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 887 return strict_format_map_.find(mime_type) != strict_format_map_.end(); 888} 889 890SupportsType MimeUtil::IsSupportedStrictMediaMimeType( 891 const std::string& mime_type, 892 const std::vector<std::string>& codecs) const { 893 StrictMappings::const_iterator it_strict_map = 894 strict_format_map_.find(mime_type); 895 if (it_strict_map == strict_format_map_.end()) 896 return codecs.empty() ? MayBeSupported : IsNotSupported; 897 898 if (it_strict_map->second.empty()) { 899 // We get here if the mimetype does not expect a codecs parameter. 900 return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ? 901 IsSupported : IsNotSupported; 902 } 903 904 if (codecs.empty()) { 905 // We get here if the mimetype expects to get a codecs parameter, 906 // but didn't get one. If |mime_type| does not have a default codec 907 // the best we can do is say "maybe" because we don't have enough 908 // information. 909 Codec default_codec = INVALID_CODEC; 910 if (!GetDefaultCodec(mime_type, &default_codec)) 911 return MayBeSupported; 912 913 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported; 914 } 915 916 return AreSupportedCodecs(it_strict_map->second, codecs); 917} 918 919void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { 920 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) { 921 non_image_map_.erase(proprietary_media_types[i]); 922 media_map_.erase(proprietary_media_types[i]); 923 } 924 allow_proprietary_codecs_ = false; 925} 926 927// Returns true iff |profile_str| conforms to hex string "42y0", where y is one 928// of [8..F]. Requiring constraint_set0_flag be set and profile_idc be 0x42 is 929// taken from ISO-14496-10 7.3.2.1, 7.4.2.1, and Annex A.2.1. 930// 931// |profile_str| is the first four characters of the H.264 suffix string 932// (ignoring the last 2 characters of the full 6 character suffix that are 933// level_idc). From ISO-14496-10 7.3.2.1, it consists of: 934// 8 bits: profile_idc: required to be 0x42 here. 935// 1 bit: constraint_set0_flag : required to be true here. 936// 1 bit: constraint_set1_flag : ignored here. 937// 1 bit: constraint_set2_flag : ignored here. 938// 1 bit: constraint_set3_flag : ignored here. 939// 4 bits: reserved : required to be 0 here. 940// 941// The spec indicates other ways, not implemented here, that a |profile_str| 942// can indicate a baseline conforming decoder is sufficient for decode in Annex 943// A.2.1: "[profile_idc not necessarily 0x42] with constraint_set0_flag set and 944// in which level_idc and constraint_set3_flag represent a level less than or 945// equal to the specified level." 946static bool IsValidH264BaselineProfile(const std::string& profile_str) { 947 uint32 constraint_set_bits; 948 if (profile_str.size() != 4 || 949 profile_str[0] != '4' || 950 profile_str[1] != '2' || 951 profile_str[3] != '0' || 952 !base::HexStringToUInt(base::StringPiece(profile_str.c_str() + 2, 1), 953 &constraint_set_bits)) { 954 return false; 955 } 956 957 return constraint_set_bits >= 8; 958} 959 960static bool IsValidH264Level(const std::string& level_str) { 961 uint32 level; 962 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level)) 963 return false; 964 965 // Valid levels taken from Table A-1 in ISO-14496-10. 966 // Essentially |level_str| is toHex(10 * level). 967 return ((level >= 10 && level <= 13) || 968 (level >= 20 && level <= 22) || 969 (level >= 30 && level <= 32) || 970 (level >= 40 && level <= 42) || 971 (level >= 50 && level <= 51)); 972} 973 974// Handle parsing H.264 codec IDs as outlined in RFC 6381 and ISO-14496-10. 975// avc1.42y0xx, y >= 8 - H.264 Baseline 976// avc1.4D40xx - H.264 Main 977// avc1.6400xx - H.264 High 978// 979// avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that are trying to 980// signal H.264 Baseline. For example, the idc_level, profile_idc and 981// constraint_set3_flag pieces may explicitly require decoder to conform to 982// baseline profile at the specified level (see Annex A and constraint_set0 in 983// ISO-14496-10). 984static bool ParseH264CodecID(const std::string& codec_id, 985 MimeUtil::Codec* codec, 986 bool* is_ambiguous) { 987 // Make sure we have avc1.xxxxxx or avc3.xxxxxx 988 if (codec_id.size() != 11 || 989 (!StartsWithASCII(codec_id, "avc1.", true) && 990 !StartsWithASCII(codec_id, "avc3.", true))) { 991 return false; 992 } 993 994 std::string profile = StringToUpperASCII(codec_id.substr(5, 4)); 995 if (IsValidH264BaselineProfile(profile)) { 996 *codec = MimeUtil::H264_BASELINE; 997 } else if (profile == "4D40") { 998 *codec = MimeUtil::H264_MAIN; 999 } else if (profile == "6400") { 1000 *codec = MimeUtil::H264_HIGH; 1001 } else { 1002 *codec = MimeUtil::H264_BASELINE; 1003 *is_ambiguous = true; 1004 return true; 1005 } 1006 1007 *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9))); 1008 return true; 1009} 1010 1011bool MimeUtil::StringToCodec(const std::string& codec_id, 1012 Codec* codec, 1013 bool* is_ambiguous) const { 1014 StringToCodecMappings::const_iterator itr = 1015 string_to_codec_map_.find(codec_id); 1016 if (itr != string_to_codec_map_.end()) { 1017 *codec = itr->second.codec; 1018 *is_ambiguous = itr->second.is_ambiguous; 1019 return true; 1020 } 1021 1022 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is 1023 // an H.264 codec ID because currently those are the only ones that can't be 1024 // stored in the |string_to_codec_map_| and require parsing. 1025 return ParseH264CodecID(codec_id, codec, is_ambiguous); 1026} 1027 1028bool MimeUtil::IsCodecSupported(Codec codec) const { 1029 DCHECK_NE(codec, INVALID_CODEC); 1030 1031#if defined(OS_ANDROID) 1032 if (!IsCodecSupportedOnAndroid(codec)) 1033 return false; 1034#endif 1035 1036 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); 1037} 1038 1039bool MimeUtil::IsCodecProprietary(Codec codec) const { 1040 switch (codec) { 1041 case INVALID_CODEC: 1042 case MP3: 1043 case MPEG2_AAC_LC: 1044 case MPEG2_AAC_MAIN: 1045 case MPEG2_AAC_SSR: 1046 case MPEG4_AAC_LC: 1047 case MPEG4_AAC_SBRv1: 1048 case H264_BASELINE: 1049 case H264_MAIN: 1050 case H264_HIGH: 1051 return true; 1052 1053 case PCM: 1054 case VORBIS: 1055 case OPUS: 1056 case VP8: 1057 case VP9: 1058 case THEORA: 1059 return false; 1060 } 1061 1062 return true; 1063} 1064 1065bool MimeUtil::GetDefaultCodec(const std::string& mime_type, 1066 Codec* default_codec) const { 1067 if (mime_type == "audio/mpeg" || 1068 mime_type == "audio/mp3" || 1069 mime_type == "audio/x-mp3") { 1070 *default_codec = MimeUtil::MP3; 1071 return true; 1072 } 1073 1074 return false; 1075} 1076 1077 1078bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const { 1079 Codec default_codec = Codec::INVALID_CODEC; 1080 if (!GetDefaultCodec(mime_type, &default_codec)) 1081 return false; 1082 return IsCodecSupported(default_codec); 1083} 1084 1085//---------------------------------------------------------------------------- 1086// Wrappers for the singleton 1087//---------------------------------------------------------------------------- 1088 1089bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 1090 std::string* mime_type) { 1091 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 1092} 1093 1094bool GetMimeTypeFromFile(const base::FilePath& file_path, 1095 std::string* mime_type) { 1096 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); 1097} 1098 1099bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 1100 std::string* mime_type) { 1101 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); 1102} 1103 1104bool GetPreferredExtensionForMimeType(const std::string& mime_type, 1105 base::FilePath::StringType* extension) { 1106 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, 1107 extension); 1108} 1109 1110bool IsSupportedImageMimeType(const std::string& mime_type) { 1111 return g_mime_util.Get().IsSupportedImageMimeType(mime_type); 1112} 1113 1114bool IsSupportedMediaMimeType(const std::string& mime_type) { 1115 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); 1116} 1117 1118bool IsSupportedNonImageMimeType(const std::string& mime_type) { 1119 return g_mime_util.Get().IsSupportedNonImageMimeType(mime_type); 1120} 1121 1122bool IsUnsupportedTextMimeType(const std::string& mime_type) { 1123 return g_mime_util.Get().IsUnsupportedTextMimeType(mime_type); 1124} 1125 1126bool IsSupportedJavascriptMimeType(const std::string& mime_type) { 1127 return g_mime_util.Get().IsSupportedJavascriptMimeType(mime_type); 1128} 1129 1130bool IsSupportedMimeType(const std::string& mime_type) { 1131 return g_mime_util.Get().IsSupportedMimeType(mime_type); 1132} 1133 1134bool MatchesMimeType(const std::string& mime_type_pattern, 1135 const std::string& mime_type) { 1136 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type); 1137} 1138 1139bool ParseMimeTypeWithoutParameter(const std::string& type_string, 1140 std::string* top_level_type, 1141 std::string* subtype) { 1142 return g_mime_util.Get().ParseMimeTypeWithoutParameter( 1143 type_string, top_level_type, subtype); 1144} 1145 1146bool IsValidTopLevelMimeType(const std::string& type_string) { 1147 return g_mime_util.Get().IsValidTopLevelMimeType(type_string); 1148} 1149 1150bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { 1151 return g_mime_util.Get().AreSupportedMediaCodecs(codecs); 1152} 1153 1154bool IsStrictMediaMimeType(const std::string& mime_type) { 1155 return g_mime_util.Get().IsStrictMediaMimeType(mime_type); 1156} 1157 1158SupportsType IsSupportedStrictMediaMimeType( 1159 const std::string& mime_type, 1160 const std::vector<std::string>& codecs) { 1161 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); 1162} 1163 1164void ParseCodecString(const std::string& codecs, 1165 std::vector<std::string>* codecs_out, 1166 const bool strip) { 1167 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); 1168} 1169 1170namespace { 1171 1172// From http://www.w3schools.com/media/media_mimeref.asp and 1173// http://plugindoc.mozdev.org/winmime.php 1174static const char* const kStandardImageTypes[] = { 1175 "image/bmp", 1176 "image/cis-cod", 1177 "image/gif", 1178 "image/ief", 1179 "image/jpeg", 1180 "image/webp", 1181 "image/pict", 1182 "image/pipeg", 1183 "image/png", 1184 "image/svg+xml", 1185 "image/tiff", 1186 "image/vnd.microsoft.icon", 1187 "image/x-cmu-raster", 1188 "image/x-cmx", 1189 "image/x-icon", 1190 "image/x-portable-anymap", 1191 "image/x-portable-bitmap", 1192 "image/x-portable-graymap", 1193 "image/x-portable-pixmap", 1194 "image/x-rgb", 1195 "image/x-xbitmap", 1196 "image/x-xpixmap", 1197 "image/x-xwindowdump" 1198}; 1199static const char* const kStandardAudioTypes[] = { 1200 "audio/aac", 1201 "audio/aiff", 1202 "audio/amr", 1203 "audio/basic", 1204 "audio/midi", 1205 "audio/mp3", 1206 "audio/mp4", 1207 "audio/mpeg", 1208 "audio/mpeg3", 1209 "audio/ogg", 1210 "audio/vorbis", 1211 "audio/wav", 1212 "audio/webm", 1213 "audio/x-m4a", 1214 "audio/x-ms-wma", 1215 "audio/vnd.rn-realaudio", 1216 "audio/vnd.wave" 1217}; 1218static const char* const kStandardVideoTypes[] = { 1219 "video/avi", 1220 "video/divx", 1221 "video/flc", 1222 "video/mp4", 1223 "video/mpeg", 1224 "video/ogg", 1225 "video/quicktime", 1226 "video/sd-video", 1227 "video/webm", 1228 "video/x-dv", 1229 "video/x-m4v", 1230 "video/x-mpeg", 1231 "video/x-ms-asf", 1232 "video/x-ms-wmv" 1233}; 1234 1235struct StandardType { 1236 const char* leading_mime_type; 1237 const char* const* standard_types; 1238 size_t standard_types_len; 1239}; 1240static const StandardType kStandardTypes[] = { 1241 { "image/", kStandardImageTypes, arraysize(kStandardImageTypes) }, 1242 { "audio/", kStandardAudioTypes, arraysize(kStandardAudioTypes) }, 1243 { "video/", kStandardVideoTypes, arraysize(kStandardVideoTypes) }, 1244 { NULL, NULL, 0 } 1245}; 1246 1247void GetExtensionsFromHardCodedMappings( 1248 const MimeInfo* mappings, 1249 size_t mappings_len, 1250 const std::string& leading_mime_type, 1251 base::hash_set<base::FilePath::StringType>* extensions) { 1252 base::FilePath::StringType extension; 1253 for (size_t i = 0; i < mappings_len; ++i) { 1254 if (StartsWithASCII(mappings[i].mime_type, leading_mime_type, false)) { 1255 std::vector<string> this_extensions; 1256 base::SplitString(mappings[i].extensions, ',', &this_extensions); 1257 for (size_t j = 0; j < this_extensions.size(); ++j) { 1258#if defined(OS_WIN) 1259 base::FilePath::StringType extension( 1260 base::UTF8ToWide(this_extensions[j])); 1261#else 1262 base::FilePath::StringType extension(this_extensions[j]); 1263#endif 1264 extensions->insert(extension); 1265 } 1266 } 1267 } 1268} 1269 1270void GetExtensionsHelper( 1271 const char* const* standard_types, 1272 size_t standard_types_len, 1273 const std::string& leading_mime_type, 1274 base::hash_set<base::FilePath::StringType>* extensions) { 1275 for (size_t i = 0; i < standard_types_len; ++i) { 1276 g_mime_util.Get().GetPlatformExtensionsForMimeType(standard_types[i], 1277 extensions); 1278 } 1279 1280 // Also look up the extensions from hard-coded mappings in case that some 1281 // supported extensions are not registered in the system registry, like ogg. 1282 GetExtensionsFromHardCodedMappings(primary_mappings, 1283 arraysize(primary_mappings), 1284 leading_mime_type, 1285 extensions); 1286 1287 GetExtensionsFromHardCodedMappings(secondary_mappings, 1288 arraysize(secondary_mappings), 1289 leading_mime_type, 1290 extensions); 1291} 1292 1293// Note that the elements in the source set will be appended to the target 1294// vector. 1295template<class T> 1296void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) { 1297 size_t old_target_size = target->size(); 1298 target->resize(old_target_size + source->size()); 1299 size_t i = 0; 1300 for (typename base::hash_set<T>::iterator iter = source->begin(); 1301 iter != source->end(); ++iter, ++i) 1302 (*target)[old_target_size + i] = *iter; 1303} 1304} 1305 1306void GetExtensionsForMimeType( 1307 const std::string& unsafe_mime_type, 1308 std::vector<base::FilePath::StringType>* extensions) { 1309 if (unsafe_mime_type == "*/*" || unsafe_mime_type == "*") 1310 return; 1311 1312 const std::string mime_type = base::StringToLowerASCII(unsafe_mime_type); 1313 base::hash_set<base::FilePath::StringType> unique_extensions; 1314 1315 if (EndsWith(mime_type, "/*", true)) { 1316 std::string leading_mime_type = mime_type.substr(0, mime_type.length() - 1); 1317 1318 // Find the matching StandardType from within kStandardTypes, or fall 1319 // through to the last (default) StandardType. 1320 const StandardType* type = NULL; 1321 for (size_t i = 0; i < arraysize(kStandardTypes); ++i) { 1322 type = &(kStandardTypes[i]); 1323 if (type->leading_mime_type && 1324 leading_mime_type == type->leading_mime_type) 1325 break; 1326 } 1327 DCHECK(type); 1328 GetExtensionsHelper(type->standard_types, 1329 type->standard_types_len, 1330 leading_mime_type, 1331 &unique_extensions); 1332 } else { 1333 g_mime_util.Get().GetPlatformExtensionsForMimeType(mime_type, 1334 &unique_extensions); 1335 1336 // Also look up the extensions from hard-coded mappings in case that some 1337 // supported extensions are not registered in the system registry, like ogg. 1338 GetExtensionsFromHardCodedMappings(primary_mappings, 1339 arraysize(primary_mappings), 1340 mime_type, 1341 &unique_extensions); 1342 1343 GetExtensionsFromHardCodedMappings(secondary_mappings, 1344 arraysize(secondary_mappings), 1345 mime_type, 1346 &unique_extensions); 1347 } 1348 1349 HashSetToVector(&unique_extensions, extensions); 1350} 1351 1352void RemoveProprietaryMediaTypesAndCodecsForTests() { 1353 g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); 1354} 1355 1356const std::string GetIANAMediaType(const std::string& mime_type) { 1357 for (size_t i = 0; i < arraysize(kIanaMediaTypes); ++i) { 1358 if (StartsWithASCII(mime_type, kIanaMediaTypes[i].matcher, true)) { 1359 return kIanaMediaTypes[i].name; 1360 } 1361 } 1362 return std::string(); 1363} 1364 1365CertificateMimeType GetCertificateMimeTypeForMimeType( 1366 const std::string& mime_type) { 1367 // Don't create a map, there is only one entry in the table, 1368 // except on Android. 1369 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) { 1370 if (mime_type == net::supported_certificate_types[i].mime_type) 1371 return net::supported_certificate_types[i].cert_type; 1372 } 1373 return CERTIFICATE_MIME_TYPE_UNKNOWN; 1374} 1375 1376bool IsSupportedCertificateMimeType(const std::string& mime_type) { 1377 CertificateMimeType file_type = 1378 GetCertificateMimeTypeForMimeType(mime_type); 1379 return file_type != CERTIFICATE_MIME_TYPE_UNKNOWN; 1380} 1381 1382void AddMultipartValueForUpload(const std::string& value_name, 1383 const std::string& value, 1384 const std::string& mime_boundary, 1385 const std::string& content_type, 1386 std::string* post_data) { 1387 DCHECK(post_data); 1388 // First line is the boundary. 1389 post_data->append("--" + mime_boundary + "\r\n"); 1390 // Next line is the Content-disposition. 1391 post_data->append("Content-Disposition: form-data; name=\"" + 1392 value_name + "\"\r\n"); 1393 if (!content_type.empty()) { 1394 // If Content-type is specified, the next line is that. 1395 post_data->append("Content-Type: " + content_type + "\r\n"); 1396 } 1397 // Leave an empty line and append the value. 1398 post_data->append("\r\n" + value + "\r\n"); 1399} 1400 1401void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, 1402 std::string* post_data) { 1403 DCHECK(post_data); 1404 post_data->append("--" + mime_boundary + "--\r\n"); 1405} 1406 1407} // namespace net 1408