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 26 using std::string; 27 28 namespace { 29 30 struct MediaType { 31 const char name[12]; 32 const char matcher[13]; 33 }; 34 35 static 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 49 namespace net { 50 51 // Singleton utility class for mime types. 52 class 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. 193 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 194 LAZY_INSTANCE_INITIALIZER; 195 196 struct MimeInfo { 197 const char* mime_type; 198 const char* extensions; // comma separated list 199 }; 200 201 static 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 222 static 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 250 static 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 271 bool MimeUtil::GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 272 string* result) const { 273 return GetMimeTypeFromExtensionHelper(ext, true, result); 274 } 275 276 bool MimeUtil::GetWellKnownMimeTypeFromExtension( 277 const base::FilePath::StringType& ext, 278 string* result) const { 279 return GetMimeTypeFromExtensionHelper(ext, false, result); 280 } 281 282 bool 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 290 bool 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 330 static 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. 347 static 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. 371 static 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()) 393 static 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. 407 struct CertificateMimeTypeInfo { 408 const char* mime_type; 409 CertificateMimeType cert_type; 410 }; 411 412 static 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. 424 static 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. 456 static 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) 470 static 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 508 static 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 519 struct 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 536 static const char kMP4AudioCodecsExpression[] = 537 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5"; 538 static 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 542 static 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 561 struct 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. 570 static 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. 593 static const CodecIDMappings kAmbiguousCodecIDs[] = { 594 { "mp4a.40", MimeUtil::MPEG4_AAC_LC }, 595 { "avc1", MimeUtil::H264_BASELINE }, 596 { "avc3", MimeUtil::H264_BASELINE }, 597 }; 598 599 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { 600 InitializeMimeTypeMaps(); 601 } 602 603 SupportsType 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 628 void 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 701 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 702 return image_map_.find(mime_type) != image_map_.end(); 703 } 704 705 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 706 return media_map_.find(mime_type) != media_map_.end(); 707 } 708 709 bool 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 717 bool MimeUtil::IsUnsupportedTextMimeType(const std::string& mime_type) const { 718 return unsupported_text_map_.find(mime_type) != unsupported_text_map_.end(); 719 } 720 721 bool 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() 727 bool 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. 736 bool 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. 770 bool 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 813 static 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 825 bool 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 843 bool 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 853 bool 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 866 void 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 886 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 887 return strict_format_map_.find(mime_type) != strict_format_map_.end(); 888 } 889 890 SupportsType 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 919 void 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." 946 static 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 960 static 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). 984 static 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 1011 bool 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 1028 bool 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 1039 bool 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 1065 bool 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 1078 bool 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 1089 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 1090 std::string* mime_type) { 1091 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 1092 } 1093 1094 bool GetMimeTypeFromFile(const base::FilePath& file_path, 1095 std::string* mime_type) { 1096 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); 1097 } 1098 1099 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 1100 std::string* mime_type) { 1101 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); 1102 } 1103 1104 bool GetPreferredExtensionForMimeType(const std::string& mime_type, 1105 base::FilePath::StringType* extension) { 1106 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, 1107 extension); 1108 } 1109 1110 bool IsSupportedImageMimeType(const std::string& mime_type) { 1111 return g_mime_util.Get().IsSupportedImageMimeType(mime_type); 1112 } 1113 1114 bool IsSupportedMediaMimeType(const std::string& mime_type) { 1115 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); 1116 } 1117 1118 bool IsSupportedNonImageMimeType(const std::string& mime_type) { 1119 return g_mime_util.Get().IsSupportedNonImageMimeType(mime_type); 1120 } 1121 1122 bool IsUnsupportedTextMimeType(const std::string& mime_type) { 1123 return g_mime_util.Get().IsUnsupportedTextMimeType(mime_type); 1124 } 1125 1126 bool IsSupportedJavascriptMimeType(const std::string& mime_type) { 1127 return g_mime_util.Get().IsSupportedJavascriptMimeType(mime_type); 1128 } 1129 1130 bool IsSupportedMimeType(const std::string& mime_type) { 1131 return g_mime_util.Get().IsSupportedMimeType(mime_type); 1132 } 1133 1134 bool 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 1139 bool 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 1146 bool IsValidTopLevelMimeType(const std::string& type_string) { 1147 return g_mime_util.Get().IsValidTopLevelMimeType(type_string); 1148 } 1149 1150 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { 1151 return g_mime_util.Get().AreSupportedMediaCodecs(codecs); 1152 } 1153 1154 bool IsStrictMediaMimeType(const std::string& mime_type) { 1155 return g_mime_util.Get().IsStrictMediaMimeType(mime_type); 1156 } 1157 1158 SupportsType 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 1164 void 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 1170 namespace { 1171 1172 // From http://www.w3schools.com/media/media_mimeref.asp and 1173 // http://plugindoc.mozdev.org/winmime.php 1174 static 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 }; 1199 static 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 }; 1218 static 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 1235 struct StandardType { 1236 const char* leading_mime_type; 1237 const char* const* standard_types; 1238 size_t standard_types_len; 1239 }; 1240 static const StandardType kStandardTypes[] = { 1241 { "image/", kStandardImageTypes, arraysize(kStandardImageTypes) }, 1242 { "audio/", kStandardAudioTypes, arraysize(kStandardAudioTypes) }, 1243 { "video/", kStandardVideoTypes, arraysize(kStandardVideoTypes) }, 1244 { NULL, NULL, 0 } 1245 }; 1246 1247 void 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 1270 void 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. 1295 template<class T> 1296 void 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 1306 void 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 1352 void RemoveProprietaryMediaTypesAndCodecsForTests() { 1353 g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); 1354 } 1355 1356 const 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 1365 CertificateMimeType 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 1376 bool IsSupportedCertificateMimeType(const std::string& mime_type) { 1377 CertificateMimeType file_type = 1378 GetCertificateMimeTypeForMimeType(mime_type); 1379 return file_type != CERTIFICATE_MIME_TYPE_UNKNOWN; 1380 } 1381 1382 void 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 1401 void 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