mime_util.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 "net/base/mime_util.h" 11#include "net/base/platform_mime_util.h" 12 13#include "base/hash_tables.h" 14#include "base/lazy_instance.h" 15#include "base/logging.h" 16#include "base/string_util.h" 17#include "base/strings/string_split.h" 18#include "base/utf_string_conversions.h" 19 20using std::string; 21 22namespace { 23 24struct MediaType { 25 const char name[12]; 26 const char matcher[13]; 27}; 28 29static const MediaType kIanaMediaTypes[] = { 30 { "application", "application/" }, 31 { "audio", "audio/" }, 32 { "example", "example/" }, 33 { "image", "image/" }, 34 { "message", "message/" }, 35 { "model", "model/" }, 36 { "multipart", "multipart/" }, 37 { "text", "text/" }, 38 { "video", "video/" }, 39}; 40 41} // namespace 42 43namespace net { 44 45// Singleton utility class for mime types. 46class MimeUtil : public PlatformMimeUtil { 47 public: 48 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 49 std::string* mime_type) const; 50 51 bool GetMimeTypeFromFile(const base::FilePath& file_path, 52 std::string* mime_type) const; 53 54 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 55 std::string* mime_type) const; 56 57 bool IsSupportedImageMimeType(const std::string& mime_type) const; 58 bool IsSupportedMediaMimeType(const std::string& mime_type) const; 59 bool IsSupportedNonImageMimeType(const std::string& mime_type) const; 60 bool IsUnsupportedTextMimeType(const std::string& mime_type) const; 61 bool IsSupportedJavascriptMimeType(const std::string& mime_type) const; 62 63 bool IsSupportedMimeType(const std::string& mime_type) const; 64 65 bool MatchesMimeType(const std::string &mime_type_pattern, 66 const std::string &mime_type) const; 67 68 bool IsMimeType(const std::string& type_string) const; 69 70 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; 71 72 void ParseCodecString(const std::string& codecs, 73 std::vector<std::string>* codecs_out, 74 bool strip); 75 76 bool IsStrictMediaMimeType(const std::string& mime_type) const; 77 bool IsSupportedStrictMediaMimeType( 78 const std::string& mime_type, 79 const std::vector<std::string>& codecs) const; 80 81 private: 82 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; 83 84 typedef base::hash_set<std::string> MimeMappings; 85 typedef std::map<std::string, MimeMappings> StrictMappings; 86 87 MimeUtil(); 88 89 // Returns true if |codecs| is nonempty and all the items in it are present in 90 // |supported_codecs|. 91 static bool AreSupportedCodecs(const MimeMappings& supported_codecs, 92 const std::vector<std::string>& codecs); 93 94 // For faster lookup, keep hash sets. 95 void InitializeMimeTypeMaps(); 96 97 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, 98 bool include_platform_types, 99 std::string* mime_type) const; 100 101 MimeMappings image_map_; 102 MimeMappings media_map_; 103 MimeMappings non_image_map_; 104 MimeMappings unsupported_text_map_; 105 MimeMappings javascript_map_; 106 MimeMappings codecs_map_; 107 108 StrictMappings strict_format_map_; 109}; // class MimeUtil 110 111// This variable is Leaky because we need to access it from WorkerPool threads. 112static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 113 LAZY_INSTANCE_INITIALIZER; 114 115struct MimeInfo { 116 const char* mime_type; 117 const char* extensions; // comma separated list 118}; 119 120static const MimeInfo primary_mappings[] = { 121 { "text/html", "html,htm" }, 122 { "text/css", "css" }, 123 { "text/xml", "xml" }, 124 { "image/gif", "gif" }, 125 { "image/jpeg", "jpeg,jpg" }, 126 { "image/webp", "webp" }, 127 { "image/png", "png" }, 128 { "video/mp4", "mp4,m4v" }, 129 { "audio/x-m4a", "m4a" }, 130 { "audio/mp3", "mp3" }, 131 { "video/ogg", "ogv,ogm" }, 132 { "audio/ogg", "ogg,oga,opus" }, 133 { "video/webm", "webm" }, 134 { "audio/webm", "webm" }, 135 { "audio/wav", "wav" }, 136 { "application/xhtml+xml", "xhtml,xht" }, 137 { "application/x-chrome-extension", "crx" }, 138 { "multipart/related", "mhtml,mht" } 139}; 140 141static const MimeInfo secondary_mappings[] = { 142 { "application/octet-stream", "exe,com,bin" }, 143 { "application/gzip", "gz" }, 144 { "application/pdf", "pdf" }, 145 { "application/postscript", "ps,eps,ai" }, 146 { "application/javascript", "js" }, 147 { "application/font-woff", "woff" }, 148 { "image/bmp", "bmp" }, 149 { "image/x-icon", "ico" }, 150 { "image/vnd.microsoft.icon", "ico" }, 151 { "image/jpeg", "jfif,pjpeg,pjp" }, 152 { "image/tiff", "tiff,tif" }, 153 { "image/x-xbitmap", "xbm" }, 154 { "image/svg+xml", "svg,svgz" }, 155 { "message/rfc822", "eml" }, 156 { "text/plain", "txt,text" }, 157 { "text/html", "shtml,ehtml" }, 158 { "application/rss+xml", "rss" }, 159 { "application/rdf+xml", "rdf" }, 160 { "text/xml", "xsl,xbl" }, 161 { "application/vnd.mozilla.xul+xml", "xul" }, 162 { "application/x-shockwave-flash", "swf,swl" }, 163 { "application/pkcs7-mime", "p7m,p7c,p7z" }, 164 { "application/pkcs7-signature", "p7s" } 165}; 166 167static const char* FindMimeType(const MimeInfo* mappings, 168 size_t mappings_len, 169 const char* ext) { 170 size_t ext_len = strlen(ext); 171 172 for (size_t i = 0; i < mappings_len; ++i) { 173 const char* extensions = mappings[i].extensions; 174 for (;;) { 175 size_t end_pos = strcspn(extensions, ","); 176 if (end_pos == ext_len && 177 base::strncasecmp(extensions, ext, ext_len) == 0) 178 return mappings[i].mime_type; 179 extensions += end_pos; 180 if (!*extensions) 181 break; 182 extensions += 1; // skip over comma 183 } 184 } 185 return NULL; 186} 187 188bool MimeUtil::GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 189 string* result) const { 190 return GetMimeTypeFromExtensionHelper(ext, true, result); 191} 192 193bool MimeUtil::GetWellKnownMimeTypeFromExtension( 194 const base::FilePath::StringType& ext, 195 string* result) const { 196 return GetMimeTypeFromExtensionHelper(ext, false, result); 197} 198 199bool MimeUtil::GetMimeTypeFromFile(const base::FilePath& file_path, 200 string* result) const { 201 base::FilePath::StringType file_name_str = file_path.Extension(); 202 if (file_name_str.empty()) 203 return false; 204 return GetMimeTypeFromExtension(file_name_str.substr(1), result); 205} 206 207bool MimeUtil::GetMimeTypeFromExtensionHelper( 208 const base::FilePath::StringType& ext, 209 bool include_platform_types, 210 string* result) const { 211 // Avoids crash when unable to handle a long file path. See crbug.com/48733. 212 const unsigned kMaxFilePathSize = 65536; 213 if (ext.length() > kMaxFilePathSize) 214 return false; 215 216 // We implement the same algorithm as Mozilla for mapping a file extension to 217 // a mime type. That is, we first check a hard-coded list (that cannot be 218 // overridden), and then if not found there, we defer to the system registry. 219 // Finally, we scan a secondary hard-coded list to catch types that we can 220 // deduce but that we also want to allow the OS to override. 221 222#if defined(OS_WIN) 223 string ext_narrow_str = WideToUTF8(ext); 224#elif defined(OS_POSIX) 225 const string& ext_narrow_str = ext; 226#endif 227 const char* mime_type; 228 229 mime_type = FindMimeType(primary_mappings, arraysize(primary_mappings), 230 ext_narrow_str.c_str()); 231 if (mime_type) { 232 *result = mime_type; 233 return true; 234 } 235 236 if (include_platform_types && GetPlatformMimeTypeFromExtension(ext, result)) 237 return true; 238 239 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings), 240 ext_narrow_str.c_str()); 241 if (mime_type) { 242 *result = mime_type; 243 return true; 244 } 245 246 return false; 247} 248 249// From WebKit's WebCore/platform/MIMETypeRegistry.cpp: 250 251static const char* const supported_image_types[] = { 252 "image/jpeg", 253 "image/pjpeg", 254 "image/jpg", 255 "image/webp", 256 "image/png", 257 "image/gif", 258 "image/bmp", 259 "image/vnd.microsoft.icon", // ico 260 "image/x-icon", // ico 261 "image/x-xbitmap" // xbm 262}; 263 264// A list of media types: http://en.wikipedia.org/wiki/Internet_media_type 265// A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php 266// This set of codecs is supported by all variations of Chromium. 267static const char* const common_media_types[] = { 268 // Ogg. 269 "audio/ogg", 270 "application/ogg", 271#if defined(ENABLE_MEDIA_CODEC_THEORA) 272 "video/ogg", 273#endif 274 275 // WebM. 276 "video/webm", 277 "audio/webm", 278 279 // Wav. 280 "audio/wav", 281 "audio/x-wav", 282}; 283 284// List of proprietary types only supported by Google Chrome. 285static const char* const proprietary_media_types[] = { 286 // MPEG-4. 287 "video/mp4", 288 "video/x-m4v", 289 "audio/mp4", 290 "audio/x-m4a", 291 292 // MP3. 293 "audio/mp3", 294 "audio/x-mp3", 295 "audio/mpeg", 296}; 297 298// List of supported codecs when passed in with <source type="...">. 299// This set of codecs is supported by all variations of Chromium. 300// 301// Refer to http://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support 302// for more information. 303// 304// The codecs for WAV are integers as defined in Appendix A of RFC2361: 305// http://tools.ietf.org/html/rfc2361 306static const char* const common_media_codecs[] = { 307#if defined(ENABLE_MEDIA_CODEC_THEORA) 308 "theora", 309#endif 310 "vorbis", 311 "vp8", 312 "1" // WAVE_FORMAT_PCM. 313}; 314 315// List of proprietary codecs only supported by Google Chrome. 316static const char* const proprietary_media_codecs[] = { 317 "avc1", 318 "mp4a" 319}; 320 321// Note: does not include javascript types list (see supported_javascript_types) 322static const char* const supported_non_image_types[] = { 323 "text/cache-manifest", 324 "text/html", 325 "text/xml", 326 "text/xsl", 327 "text/plain", 328 // Many users complained about css files served for 329 // download instead of displaying in the browser: 330 // http://code.google.com/p/chromium/issues/detail?id=7192 331 // So, by including "text/css" into this list we choose Firefox 332 // behavior - css files will be displayed: 333 "text/css", 334 "text/vnd.chromium.ftp-dir", 335 "text/", 336 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type 337 "application/xml", 338 "application/atom+xml", 339 "application/rss+xml", 340 "application/xhtml+xml", 341 "application/json", 342 "multipart/related", // For MHTML support. 343 "multipart/x-mixed-replace" 344 // Note: ADDING a new type here will probably render it AS HTML. This can 345 // result in cross site scripting. 346}; 347 348// Dictionary of cryptographic file mime types. 349struct CertificateMimeTypeInfo { 350 const char* mime_type; 351 CertificateMimeType cert_type; 352}; 353 354static const CertificateMimeTypeInfo supported_certificate_types[] = { 355 { "application/x-x509-user-cert", 356 CERTIFICATE_MIME_TYPE_X509_USER_CERT }, 357#if defined(OS_ANDROID) 358 { "application/x-x509-ca-cert", CERTIFICATE_MIME_TYPE_X509_CA_CERT }, 359 { "application/x-pkcs12", CERTIFICATE_MIME_TYPE_PKCS12_ARCHIVE }, 360#endif 361}; 362 363// These types are excluded from the logic that allows all text/ types because 364// while they are technically text, it's very unlikely that a user expects to 365// see them rendered in text form. 366static const char* const unsupported_text_types[] = { 367 "text/calendar", 368 "text/x-calendar", 369 "text/x-vcalendar", 370 "text/vcalendar", 371 "text/vcard", 372 "text/x-vcard", 373 "text/directory", 374 "text/ldif", 375 "text/qif", 376 "text/x-qif", 377 "text/x-csv", 378 "text/x-vcf", 379 "text/rtf", 380 "text/comma-separated-values", 381 "text/csv", 382 "text/tab-separated-values", 383 "text/tsv", 384 "text/ofx", // http://crbug.com/162238 385 "text/vnd.sun.j2me.app-descriptor" // http://crbug.com/176450 386}; 387 388// Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript. 389// Mozilla 1.8 accepts application/javascript, application/ecmascript, and 390// application/x-javascript, but WinIE 7 doesn't. 391// WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and 392// text/livescript, but Mozilla 1.8 doesn't. 393// Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't. 394// Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a 395// whitespace-only string. 396// We want to accept all the values that either of these browsers accept, but 397// not other values. 398static const char* const supported_javascript_types[] = { 399 "text/javascript", 400 "text/ecmascript", 401 "application/javascript", 402 "application/ecmascript", 403 "application/x-javascript", 404 "text/javascript1.1", 405 "text/javascript1.2", 406 "text/javascript1.3", 407 "text/jscript", 408 "text/livescript" 409}; 410 411struct MediaFormatStrict { 412 const char* mime_type; 413 const char* codecs_list; 414}; 415 416static const MediaFormatStrict format_codec_mappings[] = { 417 { "video/webm", "vorbis,vp8,vp8.0" }, 418 { "audio/webm", "vorbis" }, 419 { "audio/wav", "1" } 420}; 421 422MimeUtil::MimeUtil() { 423 InitializeMimeTypeMaps(); 424} 425 426// static 427bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, 428 const std::vector<std::string>& codecs) { 429 for (size_t i = 0; i < codecs.size(); ++i) { 430 if (supported_codecs.find(codecs[i]) == supported_codecs.end()) 431 return false; 432 } 433 return !codecs.empty(); 434} 435 436void MimeUtil::InitializeMimeTypeMaps() { 437 for (size_t i = 0; i < arraysize(supported_image_types); ++i) 438 image_map_.insert(supported_image_types[i]); 439 440 // Initialize the supported non-image types. 441 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i) 442 non_image_map_.insert(supported_non_image_types[i]); 443 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) 444 non_image_map_.insert(supported_certificate_types[i].mime_type); 445 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i) 446 unsupported_text_map_.insert(unsupported_text_types[i]); 447 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 448 non_image_map_.insert(supported_javascript_types[i]); 449 for (size_t i = 0; i < arraysize(common_media_types); ++i) 450 non_image_map_.insert(common_media_types[i]); 451#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) 452 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 453 non_image_map_.insert(proprietary_media_types[i]); 454#endif 455 456 // Initialize the supported media types. 457 for (size_t i = 0; i < arraysize(common_media_types); ++i) 458 media_map_.insert(common_media_types[i]); 459#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) 460 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 461 media_map_.insert(proprietary_media_types[i]); 462#endif 463 464 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 465 javascript_map_.insert(supported_javascript_types[i]); 466 467 for (size_t i = 0; i < arraysize(common_media_codecs); ++i) 468 codecs_map_.insert(common_media_codecs[i]); 469#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) 470 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 471 codecs_map_.insert(proprietary_media_codecs[i]); 472#endif 473 474 // Initialize the strict supported media types. 475 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { 476 std::vector<std::string> mime_type_codecs; 477 ParseCodecString(format_codec_mappings[i].codecs_list, 478 &mime_type_codecs, 479 false); 480 481 MimeMappings codecs; 482 for (size_t j = 0; j < mime_type_codecs.size(); ++j) 483 codecs.insert(mime_type_codecs[j]); 484 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; 485 } 486} 487 488bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 489 return image_map_.find(mime_type) != image_map_.end(); 490} 491 492bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 493 return media_map_.find(mime_type) != media_map_.end(); 494} 495 496bool MimeUtil::IsSupportedNonImageMimeType(const std::string& mime_type) const { 497 return non_image_map_.find(mime_type) != non_image_map_.end() || 498 (mime_type.compare(0, 5, "text/") == 0 && 499 !IsUnsupportedTextMimeType(mime_type)); 500} 501 502bool MimeUtil::IsUnsupportedTextMimeType(const std::string& mime_type) const { 503 return unsupported_text_map_.find(mime_type) != unsupported_text_map_.end(); 504} 505 506bool MimeUtil::IsSupportedJavascriptMimeType( 507 const std::string& mime_type) const { 508 return javascript_map_.find(mime_type) != javascript_map_.end(); 509} 510 511// Mirrors WebViewImpl::CanShowMIMEType() 512bool MimeUtil::IsSupportedMimeType(const std::string& mime_type) const { 513 return (mime_type.compare(0, 6, "image/") == 0 && 514 IsSupportedImageMimeType(mime_type)) || 515 IsSupportedNonImageMimeType(mime_type); 516} 517 518// Tests for MIME parameter equality. Each parameter in the |mime_type_pattern| 519// must be matched by a parameter in the |mime_type|. If there are no 520// parameters in the pattern, the match is a success. 521bool MatchesMimeTypeParameters(const std::string& mime_type_pattern, 522 const std::string& mime_type) { 523 const std::string::size_type semicolon = mime_type_pattern.find(';'); 524 const std::string::size_type test_semicolon = mime_type.find(';'); 525 if (semicolon != std::string::npos) { 526 if (test_semicolon == std::string::npos) 527 return false; 528 529 std::vector<std::string> pattern_parameters; 530 base::SplitString(mime_type_pattern.substr(semicolon + 1), 531 ';', &pattern_parameters); 532 533 std::vector<std::string> test_parameters; 534 base::SplitString(mime_type.substr(test_semicolon + 1), 535 ';', &test_parameters); 536 537 sort(pattern_parameters.begin(), pattern_parameters.end()); 538 sort(test_parameters.begin(), test_parameters.end()); 539 std::vector<std::string> difference; 540 std::set_difference(pattern_parameters.begin(), pattern_parameters.end(), 541 test_parameters.begin(), test_parameters.end(), 542 std::inserter(difference, difference.begin())); 543 544 return difference.size() == 0; 545 } 546 return true; 547} 548 549// This comparison handles absolute maching and also basic 550// wildcards. The plugin mime types could be: 551// application/x-foo 552// application/* 553// application/*+xml 554// * 555// Also tests mime parameters -- all parameters in the pattern must be present 556// in the tested type for a match to succeed. 557bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern, 558 const std::string& mime_type) const { 559 // Verify caller is passing lowercase strings. 560 DCHECK_EQ(StringToLowerASCII(mime_type_pattern), mime_type_pattern); 561 DCHECK_EQ(StringToLowerASCII(mime_type), mime_type); 562 563 if (mime_type_pattern.empty()) 564 return false; 565 566 std::string::size_type semicolon = mime_type_pattern.find(';'); 567 const std::string base_pattern(mime_type_pattern.substr(0, semicolon)); 568 semicolon = mime_type.find(';'); 569 const std::string base_type(mime_type.substr(0, semicolon)); 570 571 if (base_pattern == "*" || base_pattern == "*/*") 572 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 573 574 const std::string::size_type star = base_pattern.find('*'); 575 if (star == std::string::npos) { 576 if (base_pattern == base_type) 577 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 578 else 579 return false; 580 } 581 582 // Test length to prevent overlap between |left| and |right|. 583 if (base_type.length() < base_pattern.length() - 1) 584 return false; 585 586 const std::string left(base_pattern.substr(0, star)); 587 const std::string right(base_pattern.substr(star + 1)); 588 589 if (base_type.find(left) != 0) 590 return false; 591 592 if (!right.empty() && 593 base_type.rfind(right) != base_type.length() - right.length()) 594 return false; 595 596 return MatchesMimeTypeParameters(mime_type_pattern, mime_type); 597} 598 599// See http://www.iana.org/assignments/media-types/index.html 600static const char* legal_top_level_types[] = { 601 "application/", 602 "audio/", 603 "example/", 604 "image/", 605 "message/", 606 "model/", 607 "multipart/", 608 "text/", 609 "video/", 610}; 611 612bool MimeUtil::IsMimeType(const std::string& type_string) const { 613 // MIME types are always ASCII and case-insensitive (at least, the top-level 614 // and secondary types we care about). 615 if (!IsStringASCII(type_string)) 616 return false; 617 618 if (type_string == "*/*" || type_string == "*") 619 return true; 620 621 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { 622 if (StartsWithASCII(type_string, legal_top_level_types[i], false) && 623 type_string.length() > strlen(legal_top_level_types[i])) { 624 return true; 625 } 626 } 627 628 // If there's a "/" separator character, and the token before it is 629 // "x-" + (ascii characters), it is also a MIME type. 630 size_t slash = type_string.find('/'); 631 if (slash < 3 || 632 slash == std::string::npos || slash == type_string.length() - 1) { 633 return false; 634 } 635 636 if (StartsWithASCII(type_string, "x-", false)) 637 return true; 638 639 return false; 640} 641 642bool MimeUtil::AreSupportedMediaCodecs( 643 const std::vector<std::string>& codecs) const { 644 return AreSupportedCodecs(codecs_map_, codecs); 645} 646 647void MimeUtil::ParseCodecString(const std::string& codecs, 648 std::vector<std::string>* codecs_out, 649 bool strip) { 650 std::string no_quote_codecs; 651 TrimString(codecs, "\"", &no_quote_codecs); 652 base::SplitString(no_quote_codecs, ',', codecs_out); 653 654 if (!strip) 655 return; 656 657 // Strip everything past the first '.' 658 for (std::vector<std::string>::iterator it = codecs_out->begin(); 659 it != codecs_out->end(); 660 ++it) { 661 size_t found = it->find_first_of('.'); 662 if (found != std::string::npos) 663 it->resize(found); 664 } 665} 666 667bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 668 if (strict_format_map_.find(mime_type) == strict_format_map_.end()) 669 return false; 670 return true; 671} 672 673bool MimeUtil::IsSupportedStrictMediaMimeType( 674 const std::string& mime_type, 675 const std::vector<std::string>& codecs) const { 676 StrictMappings::const_iterator it = strict_format_map_.find(mime_type); 677 return (it != strict_format_map_.end()) && 678 AreSupportedCodecs(it->second, codecs); 679} 680 681//---------------------------------------------------------------------------- 682// Wrappers for the singleton 683//---------------------------------------------------------------------------- 684 685bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 686 std::string* mime_type) { 687 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 688} 689 690bool GetMimeTypeFromFile(const base::FilePath& file_path, 691 std::string* mime_type) { 692 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); 693} 694 695bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 696 std::string* mime_type) { 697 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); 698} 699 700bool GetPreferredExtensionForMimeType(const std::string& mime_type, 701 base::FilePath::StringType* extension) { 702 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, 703 extension); 704} 705 706bool IsSupportedImageMimeType(const std::string& mime_type) { 707 return g_mime_util.Get().IsSupportedImageMimeType(mime_type); 708} 709 710bool IsSupportedMediaMimeType(const std::string& mime_type) { 711 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); 712} 713 714bool IsSupportedNonImageMimeType(const std::string& mime_type) { 715 return g_mime_util.Get().IsSupportedNonImageMimeType(mime_type); 716} 717 718bool IsUnsupportedTextMimeType(const std::string& mime_type) { 719 return g_mime_util.Get().IsUnsupportedTextMimeType(mime_type); 720} 721 722bool IsSupportedJavascriptMimeType(const std::string& mime_type) { 723 return g_mime_util.Get().IsSupportedJavascriptMimeType(mime_type); 724} 725 726bool IsSupportedMimeType(const std::string& mime_type) { 727 return g_mime_util.Get().IsSupportedMimeType(mime_type); 728} 729 730bool MatchesMimeType(const std::string& mime_type_pattern, 731 const std::string& mime_type) { 732 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type); 733} 734 735bool IsMimeType(const std::string& type_string) { 736 return g_mime_util.Get().IsMimeType(type_string); 737} 738 739bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { 740 return g_mime_util.Get().AreSupportedMediaCodecs(codecs); 741} 742 743bool IsStrictMediaMimeType(const std::string& mime_type) { 744 return g_mime_util.Get().IsStrictMediaMimeType(mime_type); 745} 746 747bool IsSupportedStrictMediaMimeType(const std::string& mime_type, 748 const std::vector<std::string>& codecs) { 749 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); 750} 751 752void ParseCodecString(const std::string& codecs, 753 std::vector<std::string>* codecs_out, 754 const bool strip) { 755 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); 756} 757 758namespace { 759 760// From http://www.w3schools.com/media/media_mimeref.asp and 761// http://plugindoc.mozdev.org/winmime.php 762static const char* const kStandardImageTypes[] = { 763 "image/bmp", 764 "image/cis-cod", 765 "image/gif", 766 "image/ief", 767 "image/jpeg", 768 "image/webp", 769 "image/pict", 770 "image/pipeg", 771 "image/png", 772 "image/svg+xml", 773 "image/tiff", 774 "image/vnd.microsoft.icon", 775 "image/x-cmu-raster", 776 "image/x-cmx", 777 "image/x-icon", 778 "image/x-portable-anymap", 779 "image/x-portable-bitmap", 780 "image/x-portable-graymap", 781 "image/x-portable-pixmap", 782 "image/x-rgb", 783 "image/x-xbitmap", 784 "image/x-xpixmap", 785 "image/x-xwindowdump" 786}; 787static const char* const kStandardAudioTypes[] = { 788 "audio/aac", 789 "audio/aiff", 790 "audio/amr", 791 "audio/basic", 792 "audio/midi", 793 "audio/mp3", 794 "audio/mp4", 795 "audio/mpeg", 796 "audio/mpeg3", 797 "audio/ogg", 798 "audio/vorbis", 799 "audio/wav", 800 "audio/webm", 801 "audio/x-m4a", 802 "audio/x-ms-wma", 803 "audio/vnd.rn-realaudio", 804 "audio/vnd.wave" 805}; 806static const char* const kStandardVideoTypes[] = { 807 "video/avi", 808 "video/divx", 809 "video/flc", 810 "video/mp4", 811 "video/mpeg", 812 "video/ogg", 813 "video/quicktime", 814 "video/sd-video", 815 "video/webm", 816 "video/x-dv", 817 "video/x-m4v", 818 "video/x-mpeg", 819 "video/x-ms-asf", 820 "video/x-ms-wmv" 821}; 822 823struct StandardType { 824 const char* leading_mime_type; 825 const char* const* standard_types; 826 size_t standard_types_len; 827}; 828static const StandardType kStandardTypes[] = { 829 { "image/", kStandardImageTypes, arraysize(kStandardImageTypes) }, 830 { "audio/", kStandardAudioTypes, arraysize(kStandardAudioTypes) }, 831 { "video/", kStandardVideoTypes, arraysize(kStandardVideoTypes) }, 832 { NULL, NULL, 0 } 833}; 834 835void GetExtensionsFromHardCodedMappings( 836 const MimeInfo* mappings, 837 size_t mappings_len, 838 const std::string& leading_mime_type, 839 base::hash_set<base::FilePath::StringType>* extensions) { 840 base::FilePath::StringType extension; 841 for (size_t i = 0; i < mappings_len; ++i) { 842 if (StartsWithASCII(mappings[i].mime_type, leading_mime_type, false)) { 843 std::vector<string> this_extensions; 844 base::SplitStringUsingSubstr(mappings[i].extensions, ",", 845 &this_extensions); 846 for (size_t j = 0; j < this_extensions.size(); ++j) { 847#if defined(OS_WIN) 848 base::FilePath::StringType extension(UTF8ToWide(this_extensions[j])); 849#else 850 base::FilePath::StringType extension(this_extensions[j]); 851#endif 852 extensions->insert(extension); 853 } 854 } 855 } 856} 857 858void GetExtensionsHelper( 859 const char* const* standard_types, 860 size_t standard_types_len, 861 const std::string& leading_mime_type, 862 base::hash_set<base::FilePath::StringType>* extensions) { 863 for (size_t i = 0; i < standard_types_len; ++i) { 864 g_mime_util.Get().GetPlatformExtensionsForMimeType(standard_types[i], 865 extensions); 866 } 867 868 // Also look up the extensions from hard-coded mappings in case that some 869 // supported extensions are not registered in the system registry, like ogg. 870 GetExtensionsFromHardCodedMappings(primary_mappings, 871 arraysize(primary_mappings), 872 leading_mime_type, 873 extensions); 874 875 GetExtensionsFromHardCodedMappings(secondary_mappings, 876 arraysize(secondary_mappings), 877 leading_mime_type, 878 extensions); 879} 880 881// Note that the elements in the source set will be appended to the target 882// vector. 883template<class T> 884void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) { 885 size_t old_target_size = target->size(); 886 target->resize(old_target_size + source->size()); 887 size_t i = 0; 888 for (typename base::hash_set<T>::iterator iter = source->begin(); 889 iter != source->end(); ++iter, ++i) 890 (*target)[old_target_size + i] = *iter; 891} 892} 893 894void GetExtensionsForMimeType( 895 const std::string& unsafe_mime_type, 896 std::vector<base::FilePath::StringType>* extensions) { 897 if (unsafe_mime_type == "*/*" || unsafe_mime_type == "*") 898 return; 899 900 const std::string mime_type = StringToLowerASCII(unsafe_mime_type); 901 base::hash_set<base::FilePath::StringType> unique_extensions; 902 903 if (EndsWith(mime_type, "/*", true)) { 904 std::string leading_mime_type = mime_type.substr(0, mime_type.length() - 1); 905 906 // Find the matching StandardType from within kStandardTypes, or fall 907 // through to the last (default) StandardType. 908 const StandardType* type = NULL; 909 for (size_t i = 0; i < arraysize(kStandardTypes); ++i) { 910 type = &(kStandardTypes[i]); 911 if (type->leading_mime_type && 912 leading_mime_type == type->leading_mime_type) 913 break; 914 } 915 DCHECK(type); 916 GetExtensionsHelper(type->standard_types, 917 type->standard_types_len, 918 leading_mime_type, 919 &unique_extensions); 920 } else { 921 g_mime_util.Get().GetPlatformExtensionsForMimeType(mime_type, 922 &unique_extensions); 923 924 // Also look up the extensions from hard-coded mappings in case that some 925 // supported extensions are not registered in the system registry, like ogg. 926 GetExtensionsFromHardCodedMappings(primary_mappings, 927 arraysize(primary_mappings), 928 mime_type, 929 &unique_extensions); 930 931 GetExtensionsFromHardCodedMappings(secondary_mappings, 932 arraysize(secondary_mappings), 933 mime_type, 934 &unique_extensions); 935 } 936 937 HashSetToVector(&unique_extensions, extensions); 938} 939 940void GetMediaTypesBlacklistedForTests(std::vector<std::string>* types) { 941 types->clear(); 942 943// Unless/until WebM files are added to the media layout tests, we need to avoid 944// blacklisting mp4 and H.264 when Theora is not supported (and proprietary 945// codecs are) so that the media tests can still run. 946#if defined(ENABLE_MEDIA_CODEC_THEORA) || !defined(USE_PROPRIETARY_CODECS) 947 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 948 types->push_back(proprietary_media_types[i]); 949#endif 950} 951 952void GetMediaCodecsBlacklistedForTests(std::vector<std::string>* codecs) { 953 codecs->clear(); 954 955// Unless/until WebM files are added to the media layout tests, we need to avoid 956// blacklisting mp4 and H.264 when Theora is not supported (and proprietary 957// codecs are) so that the media tests can still run. 958#if defined(ENABLE_MEDIA_CODEC_THEORA) || !defined(USE_PROPRIETARY_CODECS) 959 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 960 codecs->push_back(proprietary_media_codecs[i]); 961#endif 962} 963 964const std::string GetIANAMediaType(const std::string& mime_type) { 965 for (size_t i = 0; i < arraysize(kIanaMediaTypes); ++i) { 966 if (StartsWithASCII(mime_type, kIanaMediaTypes[i].matcher, true)) { 967 return kIanaMediaTypes[i].name; 968 } 969 } 970 return std::string(); 971} 972 973CertificateMimeType GetCertificateMimeTypeForMimeType( 974 const std::string& mime_type) { 975 // Don't create a map, there is only one entry in the table, 976 // except on Android. 977 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) { 978 if (mime_type == net::supported_certificate_types[i].mime_type) 979 return net::supported_certificate_types[i].cert_type; 980 } 981 return CERTIFICATE_MIME_TYPE_UNKNOWN; 982} 983 984bool IsSupportedCertificateMimeType(const std::string& mime_type) { 985 CertificateMimeType file_type = 986 GetCertificateMimeTypeForMimeType(mime_type); 987 return file_type != CERTIFICATE_MIME_TYPE_UNKNOWN; 988} 989 990} // namespace net 991