| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "platform/network/mime/MIMETypeRegistry.h" |
| |
| #include "base/files/file_path.h" |
| #include "base/strings/string_util.h" |
| #include "components/mime_util/mime_util.h" |
| #include "media/base/mime_util.h" |
| #include "media/filters/stream_parser_factory.h" |
| #include "net/base/mime_util.h" |
| #include "platform/wtf/text/WTFString.h" |
| #include "public/platform/FilePathConversion.h" |
| #include "public/platform/InterfaceProvider.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/mime_registry.mojom-blink.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| struct MimeRegistryPtrHolder { |
| public: |
| MimeRegistryPtrHolder() { |
| Platform::current()->interfaceProvider()->getInterface( |
| mojo::MakeRequest(&mimeRegistry)); |
| } |
| ~MimeRegistryPtrHolder() {} |
| |
| mojom::blink::MimeRegistryPtr mimeRegistry; |
| }; |
| |
| std::string ToASCIIOrEmpty(const WebString& string) { |
| return string.containsOnlyASCII() ? string.ascii() : std::string(); |
| } |
| |
| template <typename CHARTYPE, typename SIZETYPE> |
| std::string ToLowerASCIIInternal(CHARTYPE* str, SIZETYPE length) { |
| std::string lowerASCII; |
| lowerASCII.reserve(length); |
| for (CHARTYPE* p = str; p < str + length; p++) |
| lowerASCII.push_back(base::ToLowerASCII(static_cast<char>(*p))); |
| return lowerASCII; |
| } |
| |
| // Does the same as ToASCIIOrEmpty, but also makes the chars lower. |
| std::string ToLowerASCIIOrEmpty(const String& str) { |
| if (str.isEmpty() || !str.containsOnlyASCII()) |
| return std::string(); |
| if (str.is8Bit()) |
| return ToLowerASCIIInternal(str.characters8(), str.length()); |
| return ToLowerASCIIInternal(str.characters16(), str.length()); |
| } |
| |
| #define STATIC_ASSERT_ENUM(a, b) \ |
| static_assert(static_cast<int>(a) == static_cast<int>(b), \ |
| "mismatching enums: " #a) |
| STATIC_ASSERT_ENUM(MIMETypeRegistry::IsNotSupported, media::IsNotSupported); |
| STATIC_ASSERT_ENUM(MIMETypeRegistry::IsSupported, media::IsSupported); |
| STATIC_ASSERT_ENUM(MIMETypeRegistry::MayBeSupported, media::MayBeSupported); |
| |
| } // namespace |
| |
| String MIMETypeRegistry::getMIMETypeForExtension(const String& ext) { |
| // The sandbox restricts our access to the registry, so we need to proxy |
| // these calls over to the browser process. |
| DEFINE_STATIC_LOCAL(MimeRegistryPtrHolder, registryHolder, ()); |
| String mimeType; |
| if (!registryHolder.mimeRegistry->GetMimeTypeFromExtension(ext, &mimeType)) |
| return String(); |
| return mimeType; |
| } |
| |
| String MIMETypeRegistry::getWellKnownMIMETypeForExtension(const String& ext) { |
| // This method must be thread safe and should not consult the OS/registry. |
| std::string mimeType; |
| net::GetWellKnownMimeTypeFromExtension(WebStringToFilePath(ext).value(), |
| &mimeType); |
| return String::fromUTF8(mimeType.data(), mimeType.length()); |
| } |
| |
| String MIMETypeRegistry::getMIMETypeForPath(const String& path) { |
| int pos = path.reverseFind('.'); |
| if (pos < 0) |
| return "application/octet-stream"; |
| String extension = path.substring(pos + 1); |
| String mimeType = getMIMETypeForExtension(extension); |
| return mimeType.isEmpty() ? "application/octet-stream" : mimeType; |
| } |
| |
| bool MIMETypeRegistry::isSupportedMIMEType(const String& mimeType) { |
| return mime_util::IsSupportedMimeType(ToLowerASCIIOrEmpty(mimeType)); |
| } |
| |
| bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType) { |
| return mime_util::IsSupportedImageMimeType(ToLowerASCIIOrEmpty(mimeType)); |
| } |
| |
| bool MIMETypeRegistry::isSupportedImageResourceMIMEType( |
| const String& mimeType) { |
| return isSupportedImageMIMEType(mimeType); |
| } |
| |
| bool MIMETypeRegistry::isSupportedImagePrefixedMIMEType( |
| const String& mimeType) { |
| std::string asciiMimeType = ToLowerASCIIOrEmpty(mimeType); |
| return (mime_util::IsSupportedImageMimeType(asciiMimeType) || |
| (base::StartsWith(asciiMimeType, "image/", |
| base::CompareCase::SENSITIVE) && |
| mime_util::IsSupportedNonImageMimeType(asciiMimeType))); |
| } |
| |
| bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding( |
| const String& mimeType) { |
| if (equalIgnoringCase(mimeType, "image/jpeg") || |
| equalIgnoringCase(mimeType, "image/png")) |
| return true; |
| if (equalIgnoringCase(mimeType, "image/webp")) |
| return true; |
| return false; |
| } |
| |
| bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType) { |
| return mime_util::IsSupportedJavascriptMimeType( |
| ToLowerASCIIOrEmpty(mimeType)); |
| } |
| |
| bool MIMETypeRegistry::isLegacySupportedJavaScriptLanguage( |
| const String& language) { |
| // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only |
| // javascript1.1 - javascript1.3. |
| // Mozilla 1.8 and WinIE 7 both accept javascript and livescript. |
| // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. |
| // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. |
| // We want to accept all the values that either of these browsers accept, but |
| // not other values. |
| |
| // FIXME: This function is not HTML5 compliant. These belong in the MIME |
| // registry as "text/javascript<version>" entries. |
| return equalIgnoringASCIICase(language, "javascript") || |
| equalIgnoringASCIICase(language, "javascript1.0") || |
| equalIgnoringASCIICase(language, "javascript1.1") || |
| equalIgnoringASCIICase(language, "javascript1.2") || |
| equalIgnoringASCIICase(language, "javascript1.3") || |
| equalIgnoringASCIICase(language, "javascript1.4") || |
| equalIgnoringASCIICase(language, "javascript1.5") || |
| equalIgnoringASCIICase(language, "javascript1.6") || |
| equalIgnoringASCIICase(language, "javascript1.7") || |
| equalIgnoringASCIICase(language, "livescript") || |
| equalIgnoringASCIICase(language, "ecmascript") || |
| equalIgnoringASCIICase(language, "jscript"); |
| } |
| |
| bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType) { |
| return mime_util::IsSupportedNonImageMimeType(ToLowerASCIIOrEmpty(mimeType)); |
| } |
| |
| bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType, |
| const String& codecs) { |
| return supportsMediaMIMEType(mimeType, codecs) != IsNotSupported; |
| } |
| |
| MIMETypeRegistry::SupportsType MIMETypeRegistry::supportsMediaMIMEType( |
| const String& mimeType, |
| const String& codecs) { |
| const std::string asciiMimeType = ToLowerASCIIOrEmpty(mimeType); |
| std::vector<std::string> codecVector; |
| media::SplitCodecsToVector(ToASCIIOrEmpty(codecs), &codecVector, false); |
| return static_cast<SupportsType>( |
| media::IsSupportedMediaFormat(asciiMimeType, codecVector)); |
| } |
| |
| bool MIMETypeRegistry::isSupportedMediaSourceMIMEType(const String& mimeType, |
| const String& codecs) { |
| const std::string asciiMimeType = ToLowerASCIIOrEmpty(mimeType); |
| if (asciiMimeType.empty()) |
| return false; |
| std::vector<std::string> parsedCodecIds; |
| media::SplitCodecsToVector(ToASCIIOrEmpty(codecs), &parsedCodecIds, false); |
| return static_cast<MIMETypeRegistry::SupportsType>( |
| media::StreamParserFactory::IsTypeSupported(asciiMimeType, |
| parsedCodecIds)); |
| } |
| |
| bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType) { |
| // Since this set is very limited and is likely to remain so we won't bother |
| // with the overhead of using a hash set. Any of the MIME types below may be |
| // followed by any number of specific versions of the JVM, which is why we use |
| // startsWith() |
| return mimeType.startsWith("application/x-java-applet", |
| TextCaseASCIIInsensitive) || |
| mimeType.startsWith("application/x-java-bean", |
| TextCaseASCIIInsensitive) || |
| mimeType.startsWith("application/x-java-vm", TextCaseASCIIInsensitive); |
| } |
| |
| bool MIMETypeRegistry::isSupportedStyleSheetMIMEType(const String& mimeType) { |
| return equalIgnoringCase(mimeType, "text/css"); |
| } |
| |
| bool MIMETypeRegistry::isSupportedFontMIMEType(const String& mimeType) { |
| static const unsigned fontLen = 5; |
| if (!mimeType.startsWith("font/", TextCaseASCIIInsensitive)) |
| return false; |
| String subType = mimeType.substring(fontLen).lower(); |
| return subType == "woff" || subType == "woff2" || subType == "otf" || |
| subType == "ttf" || subType == "sfnt"; |
| } |
| |
| bool MIMETypeRegistry::isSupportedTextTrackMIMEType(const String& mimeType) { |
| return equalIgnoringCase(mimeType, "text/vtt"); |
| } |
| |
| } // namespace blink |