1 // Copyright 2015 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.
5 #include "components/mime_util/mime_util.h"
7 #include "base/containers/hash_tables.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/string_util.h"
10 #include "build/build_config.h"
13 // iOS doesn't use and must not depend on //media
14 #include "media/base/mime_util.h"
21 // Dictionary of cryptographic file mime types.
22 struct CertificateMimeTypeInfo
{
23 const char* const mime_type
;
24 net::CertificateMimeType cert_type
;
27 const CertificateMimeTypeInfo kSupportedCertificateTypes
[] = {
28 {"application/x-x509-user-cert", net::CERTIFICATE_MIME_TYPE_X509_USER_CERT
},
29 #if defined(OS_ANDROID)
30 {"application/x-x509-ca-cert", net::CERTIFICATE_MIME_TYPE_X509_CA_CERT
},
31 {"application/x-pkcs12", net::CERTIFICATE_MIME_TYPE_PKCS12_ARCHIVE
},
35 // From WebKit's WebCore/platform/MIMETypeRegistry.cpp:
37 const char* const kSupportedImageTypes
[] = {"image/jpeg",
44 "image/vnd.microsoft.icon", // ico
45 "image/x-icon", // ico
46 "image/x-xbitmap", // xbm
49 // Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript.
50 // Mozilla 1.8 accepts application/javascript, application/ecmascript, and
51 // application/x-javascript, but WinIE 7 doesn't.
52 // WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and
53 // text/livescript, but Mozilla 1.8 doesn't.
54 // Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't.
55 // Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a
56 // whitespace-only string.
57 // We want to accept all the values that either of these browsers accept, but
59 const char* const kSupportedJavascriptTypes
[] = {"text/javascript",
61 "application/javascript",
62 "application/ecmascript",
63 "application/x-javascript",
70 // These types are excluded from the logic that allows all text/ types because
71 // while they are technically text, it's very unlikely that a user expects to
72 // see them rendered in text form.
73 static const char* const kUnsupportedTextTypes
[] = {
87 "text/comma-separated-values",
89 "text/tab-separated-values",
91 "text/ofx", // http://crbug.com/162238
92 "text/vnd.sun.j2me.app-descriptor" // http://crbug.com/176450
96 // - does not include javascript types list (see supported_javascript_types)
97 // - does not include types starting with "text/" (see
98 // IsSupportedNonImageMimeType())
99 static const char* const kSupportedNonImageTypes
[] = {
100 "image/svg+xml", // SVG is text-based XML, even though it has an image/
103 "application/atom+xml",
104 "application/rss+xml",
105 "application/xhtml+xml",
107 "multipart/related", // For MHTML support.
108 "multipart/x-mixed-replace"
109 // Note: ADDING a new type here will probably render it AS HTML. This can
110 // result in cross site scripting.
113 // Singleton utility class for mime types
116 bool IsSupportedImageMimeType(const std::string
& mime_type
) const;
117 bool IsSupportedNonImageMimeType(const std::string
& mime_type
) const;
118 bool IsUnsupportedTextMimeType(const std::string
& mime_type
) const;
119 bool IsSupportedJavascriptMimeType(const std::string
& mime_type
) const;
121 bool IsSupportedMimeType(const std::string
& mime_type
) const;
124 friend struct base::DefaultLazyInstanceTraits
<MimeUtil
>;
126 using MimeTypes
= base::hash_set
<std::string
>;
130 MimeTypes image_types_
;
131 MimeTypes non_image_types_
;
132 MimeTypes unsupported_text_types_
;
133 MimeTypes javascript_types_
;
135 DISALLOW_COPY_AND_ASSIGN(MimeUtil
);
138 MimeUtil::MimeUtil() {
139 for (size_t i
= 0; i
< arraysize(kSupportedNonImageTypes
); ++i
)
140 non_image_types_
.insert(kSupportedNonImageTypes
[i
]);
141 for (size_t i
= 0; i
< arraysize(kSupportedImageTypes
); ++i
)
142 image_types_
.insert(kSupportedImageTypes
[i
]);
143 for (size_t i
= 0; i
< arraysize(kUnsupportedTextTypes
); ++i
)
144 unsupported_text_types_
.insert(kUnsupportedTextTypes
[i
]);
145 for (size_t i
= 0; i
< arraysize(kSupportedJavascriptTypes
); ++i
) {
146 javascript_types_
.insert(kSupportedJavascriptTypes
[i
]);
147 non_image_types_
.insert(kSupportedJavascriptTypes
[i
]);
149 for (size_t i
= 0; i
< arraysize(kSupportedCertificateTypes
); ++i
)
150 non_image_types_
.insert(kSupportedCertificateTypes
[i
].mime_type
);
153 bool MimeUtil::IsSupportedImageMimeType(const std::string
& mime_type
) const {
154 return image_types_
.find(base::ToLowerASCII(mime_type
)) != image_types_
.end();
157 bool MimeUtil::IsSupportedNonImageMimeType(const std::string
& mime_type
) const {
158 return non_image_types_
.find(base::ToLowerASCII(mime_type
)) !=
159 non_image_types_
.end() ||
161 media::IsSupportedMediaMimeType(mime_type
) ||
163 (base::StartsWith(mime_type
, "text/",
164 base::CompareCase::INSENSITIVE_ASCII
) &&
165 !IsUnsupportedTextMimeType(mime_type
)) ||
166 (base::StartsWith(mime_type
, "application/",
167 base::CompareCase::INSENSITIVE_ASCII
) &&
168 net::MatchesMimeType("application/*+json", mime_type
));
171 bool MimeUtil::IsUnsupportedTextMimeType(const std::string
& mime_type
) const {
172 return unsupported_text_types_
.find(base::ToLowerASCII(mime_type
)) !=
173 unsupported_text_types_
.end();
176 bool MimeUtil::IsSupportedJavascriptMimeType(
177 const std::string
& mime_type
) const {
178 return javascript_types_
.find(mime_type
) != javascript_types_
.end();
181 bool MimeUtil::IsSupportedMimeType(const std::string
& mime_type
) const {
182 return (base::StartsWith(mime_type
, "image/",
183 base::CompareCase::INSENSITIVE_ASCII
) &&
184 IsSupportedImageMimeType(mime_type
)) ||
185 IsSupportedNonImageMimeType(mime_type
);
188 // This variable is Leaky because it is accessed from WorkerPool threads.
189 static base::LazyInstance
<MimeUtil
>::Leaky g_mime_util
=
190 LAZY_INSTANCE_INITIALIZER
;
194 bool IsSupportedImageMimeType(const std::string
& mime_type
) {
195 return g_mime_util
.Get().IsSupportedImageMimeType(mime_type
);
198 bool IsSupportedNonImageMimeType(const std::string
& mime_type
) {
199 return g_mime_util
.Get().IsSupportedNonImageMimeType(mime_type
);
202 bool IsUnsupportedTextMimeType(const std::string
& mime_type
) {
203 return g_mime_util
.Get().IsUnsupportedTextMimeType(mime_type
);
206 bool IsSupportedJavascriptMimeType(const std::string
& mime_type
) {
207 return g_mime_util
.Get().IsSupportedJavascriptMimeType(mime_type
);
210 bool IsSupportedCertificateMimeType(const std::string
& mime_type
) {
211 net::CertificateMimeType file_type
=
212 GetCertificateMimeTypeForMimeType(mime_type
);
213 return file_type
!= net::CERTIFICATE_MIME_TYPE_UNKNOWN
;
216 bool IsSupportedMimeType(const std::string
& mime_type
) {
217 return g_mime_util
.Get().IsSupportedMimeType(mime_type
);
220 net::CertificateMimeType
GetCertificateMimeTypeForMimeType(
221 const std::string
& mime_type
) {
222 // Don't create a map, there is only one entry in the table,
223 // except on Android.
224 for (size_t i
= 0; i
< arraysize(kSupportedCertificateTypes
); ++i
) {
225 if (base::EqualsCaseInsensitiveASCII(
226 mime_type
, kSupportedCertificateTypes
[i
].mime_type
)) {
227 return kSupportedCertificateTypes
[i
].cert_type
;
231 return net::CERTIFICATE_MIME_TYPE_UNKNOWN
;
234 } // namespace mime_util