1 // Copyright (c) 2011 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 <map>
6 #include <string>
7
8 #include "net/base/mime_util.h"
9 #include "net/base/platform_mime_util.h"
10
11 #include "base/hash_tables.h"
12 #include "base/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/string_split.h"
15 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h"
17
18 using std::string;
19
20 namespace net {
21
22 // Singleton utility class for mime types.
23 class MimeUtil : public PlatformMimeUtil {
24 public:
25 bool GetMimeTypeFromExtension(const FilePath::StringType& ext,
26 std::string* mime_type) const;
27
28 bool GetMimeTypeFromFile(const FilePath& file_path,
29 std::string* mime_type) const;
30
31 bool IsSupportedImageMimeType(const char* mime_type) const;
32 bool IsSupportedMediaMimeType(const char* mime_type) const;
33 bool IsSupportedNonImageMimeType(const char* mime_type) const;
34 bool IsSupportedJavascriptMimeType(const char* mime_type) const;
35
36 bool IsViewSourceMimeType(const char* mime_type) const;
37
38 bool IsSupportedMimeType(const std::string& mime_type) const;
39
40 bool MatchesMimeType(const std::string &mime_type_pattern,
41 const std::string &mime_type) const;
42
43 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const;
44
45 void ParseCodecString(const std::string& codecs,
46 std::vector<std::string>* codecs_out,
47 bool strip);
48
49 bool IsStrictMediaMimeType(const std::string& mime_type) const;
50 bool IsSupportedStrictMediaMimeType(const std::string& mime_type,
51 const std::vector<std::string>& codecs) const;
52
53 private:
54 friend struct base::DefaultLazyInstanceTraits<MimeUtil>;
MimeUtil()55 MimeUtil() {
56 InitializeMimeTypeMaps();
57 }
58
59 // For faster lookup, keep hash sets.
60 void InitializeMimeTypeMaps();
61
62 typedef base::hash_set<std::string> MimeMappings;
63 MimeMappings image_map_;
64 MimeMappings media_map_;
65 MimeMappings non_image_map_;
66 MimeMappings javascript_map_;
67 MimeMappings view_source_map_;
68 MimeMappings codecs_map_;
69
70 typedef std::map<std::string, base::hash_set<std::string> > StrictMappings;
71 StrictMappings strict_format_map_;
72 }; // class MimeUtil
73
74 static base::LazyInstance<MimeUtil> g_mime_util(base::LINKER_INITIALIZED);
75
76 struct MimeInfo {
77 const char* mime_type;
78 const char* extensions; // comma separated list
79 };
80
81 static const MimeInfo primary_mappings[] = {
82 { "text/html", "html,htm" },
83 { "text/css", "css" },
84 { "text/xml", "xml" },
85 { "image/gif", "gif" },
86 { "image/jpeg", "jpeg,jpg" },
87 { "image/webp", "webp" },
88 { "image/png", "png" },
89 { "video/mp4", "mp4,m4v" },
90 { "audio/x-m4a", "m4a" },
91 { "audio/mp3", "mp3" },
92 { "video/ogg", "ogv,ogm" },
93 { "audio/ogg", "ogg,oga" },
94 { "video/webm", "webm" },
95 { "audio/webm", "webm" },
96 { "audio/wav", "wav" },
97 { "application/xhtml+xml", "xhtml,xht" },
98 { "application/x-chrome-extension", "crx" }
99 };
100
101 static const MimeInfo secondary_mappings[] = {
102 { "application/octet-stream", "exe,com,bin" },
103 { "application/gzip", "gz" },
104 { "application/pdf", "pdf" },
105 { "application/postscript", "ps,eps,ai" },
106 { "application/x-javascript", "js" },
107 { "image/bmp", "bmp" },
108 { "image/x-icon", "ico" },
109 { "image/jpeg", "jfif,pjpeg,pjp" },
110 { "image/tiff", "tiff,tif" },
111 { "image/x-xbitmap", "xbm" },
112 { "image/svg+xml", "svg,svgz" },
113 { "message/rfc822", "eml" },
114 { "text/plain", "txt,text" },
115 { "text/html", "shtml,ehtml" },
116 { "application/rss+xml", "rss" },
117 { "application/rdf+xml", "rdf" },
118 { "text/xml", "xsl,xbl" },
119 { "application/vnd.mozilla.xul+xml", "xul" },
120 { "application/x-shockwave-flash", "swf,swl" }
121 };
122
FindMimeType(const MimeInfo * mappings,size_t mappings_len,const char * ext)123 static const char* FindMimeType(const MimeInfo* mappings,
124 size_t mappings_len,
125 const char* ext) {
126 size_t ext_len = strlen(ext);
127
128 for (size_t i = 0; i < mappings_len; ++i) {
129 const char* extensions = mappings[i].extensions;
130 for (;;) {
131 size_t end_pos = strcspn(extensions, ",");
132 if (end_pos == ext_len &&
133 base::strncasecmp(extensions, ext, ext_len) == 0)
134 return mappings[i].mime_type;
135 extensions += end_pos;
136 if (!*extensions)
137 break;
138 extensions += 1; // skip over comma
139 }
140 }
141 return NULL;
142 }
143
GetMimeTypeFromExtension(const FilePath::StringType & ext,string * result) const144 bool MimeUtil::GetMimeTypeFromExtension(const FilePath::StringType& ext,
145 string* result) const {
146 // Avoids crash when unable to handle a long file path. See crbug.com/48733.
147 const unsigned kMaxFilePathSize = 65536;
148 if (ext.length() > kMaxFilePathSize)
149 return false;
150
151 // We implement the same algorithm as Mozilla for mapping a file extension to
152 // a mime type. That is, we first check a hard-coded list (that cannot be
153 // overridden), and then if not found there, we defer to the system registry.
154 // Finally, we scan a secondary hard-coded list to catch types that we can
155 // deduce but that we also want to allow the OS to override.
156
157 #if defined(OS_WIN)
158 string ext_narrow_str = WideToUTF8(ext);
159 #elif defined(OS_POSIX)
160 const string& ext_narrow_str = ext;
161 #endif
162 const char* mime_type;
163
164 mime_type = FindMimeType(primary_mappings, arraysize(primary_mappings),
165 ext_narrow_str.c_str());
166 if (mime_type) {
167 *result = mime_type;
168 return true;
169 }
170
171 if (GetPlatformMimeTypeFromExtension(ext, result))
172 return true;
173
174 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings),
175 ext_narrow_str.c_str());
176 if (mime_type) {
177 *result = mime_type;
178 return true;
179 }
180
181 return false;
182 }
183
GetMimeTypeFromFile(const FilePath & file_path,string * result) const184 bool MimeUtil::GetMimeTypeFromFile(const FilePath& file_path,
185 string* result) const {
186 FilePath::StringType file_name_str = file_path.Extension();
187 if (file_name_str.empty())
188 return false;
189 return GetMimeTypeFromExtension(file_name_str.substr(1), result);
190 }
191
192 // From WebKit's WebCore/platform/MIMETypeRegistry.cpp:
193
194 static const char* const supported_image_types[] = {
195 "image/jpeg",
196 "image/pjpeg",
197 "image/jpg",
198 "image/webp",
199 "image/png",
200 "image/gif",
201 "image/bmp",
202 "image/x-icon", // ico
203 "image/x-xbitmap" // xbm
204 };
205
206 // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type
207 // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php
208 static const char* const supported_media_types[] = {
209 // Ogg.
210 "video/ogg",
211 "audio/ogg",
212 "application/ogg",
213 "video/webm",
214 "audio/webm",
215 "audio/wav",
216 "audio/x-wav",
217
218 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
219 // MPEG-4.
220 "video/mp4",
221 "video/x-m4v",
222 "audio/mp4",
223 "audio/x-m4a",
224
225 // MP3.
226 "audio/mp3",
227 "audio/x-mp3",
228 "audio/mpeg",
229 #endif
230 };
231
232 // List of supported codecs when passed in with <source type="...">.
233 //
234 // Refer to http://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support
235 // for more information.
236 static const char* const supported_media_codecs[] = {
237 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
238 "avc1",
239 "mp4a",
240 #endif
241 "theora",
242 "vorbis",
243 "vp8",
244 "1" // PCM for WAV.
245 };
246
247 // Note: does not include javascript types list (see supported_javascript_types)
248 static const char* const supported_non_image_types[] = {
249 "text/cache-manifest",
250 "text/html",
251 "text/xml",
252 "text/xsl",
253 "text/plain",
254 // Many users complained about css files served for
255 // download instead of displaying in the browser:
256 // http://code.google.com/p/chromium/issues/detail?id=7192
257 // So, by including "text/css" into this list we choose Firefox
258 // behavior - css files will be displayed:
259 "text/css",
260 "text/vnd.chromium.ftp-dir",
261 "text/",
262 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type
263 "application/xml",
264 "application/xhtml+xml",
265 "application/rss+xml",
266 "application/atom+xml",
267 "application/json",
268 "application/x-x509-user-cert",
269 "multipart/x-mixed-replace"
270 // Note: ADDING a new type here will probably render it AS HTML. This can
271 // result in cross site scripting.
272 };
273 COMPILE_ASSERT(arraysize(supported_non_image_types) == 16,
274 supported_non_images_types_must_equal_16);
275
276 // Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript.
277 // Mozilla 1.8 accepts application/javascript, application/ecmascript, and
278 // application/x-javascript, but WinIE 7 doesn't.
279 // WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and
280 // text/livescript, but Mozilla 1.8 doesn't.
281 // Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't.
282 // Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a
283 // whitespace-only string.
284 // We want to accept all the values that either of these browsers accept, but
285 // not other values.
286 static const char* const supported_javascript_types[] = {
287 "text/javascript",
288 "text/ecmascript",
289 "application/javascript",
290 "application/ecmascript",
291 "application/x-javascript",
292 "text/javascript1.1",
293 "text/javascript1.2",
294 "text/javascript1.3",
295 "text/jscript",
296 "text/livescript"
297 };
298
299 static const char* const view_source_types[] = {
300 "text/xml",
301 "text/xsl",
302 "application/xml",
303 "application/rss+xml",
304 "application/atom+xml",
305 "image/svg+xml"
306 };
307
308 struct MediaFormatStrict {
309 const char* mime_type;
310 const char* codecs_list;
311 };
312
313 static const MediaFormatStrict format_codec_mappings[] = {
314 { "video/webm", "vorbis,vp8,vp8.0" },
315 { "audio/webm", "vorbis" },
316 { "audio/wav", "1" }
317 };
318
InitializeMimeTypeMaps()319 void MimeUtil::InitializeMimeTypeMaps() {
320 for (size_t i = 0; i < arraysize(supported_image_types); ++i)
321 image_map_.insert(supported_image_types[i]);
322
323 // Initialize the supported non-image types.
324 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i)
325 non_image_map_.insert(supported_non_image_types[i]);
326 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
327 non_image_map_.insert(supported_javascript_types[i]);
328 for (size_t i = 0; i < arraysize(supported_media_types); ++i)
329 non_image_map_.insert(supported_media_types[i]);
330
331 // Initialize the supported media types.
332 for (size_t i = 0; i < arraysize(supported_media_types); ++i)
333 media_map_.insert(supported_media_types[i]);
334
335 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
336 javascript_map_.insert(supported_javascript_types[i]);
337
338 for (size_t i = 0; i < arraysize(view_source_types); ++i)
339 view_source_map_.insert(view_source_types[i]);
340
341 for (size_t i = 0; i < arraysize(supported_media_codecs); ++i)
342 codecs_map_.insert(supported_media_codecs[i]);
343
344 // Initialize the strict supported media types.
345 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
346 std::vector<std::string> mime_type_codecs;
347 ParseCodecString(format_codec_mappings[i].codecs_list,
348 &mime_type_codecs,
349 false);
350
351 MimeMappings codecs;
352 for (size_t j = 0; j < mime_type_codecs.size(); ++j)
353 codecs.insert(mime_type_codecs[j]);
354 strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
355 }
356 }
357
IsSupportedImageMimeType(const char * mime_type) const358 bool MimeUtil::IsSupportedImageMimeType(const char* mime_type) const {
359 return image_map_.find(mime_type) != image_map_.end();
360 }
361
IsSupportedMediaMimeType(const char * mime_type) const362 bool MimeUtil::IsSupportedMediaMimeType(const char* mime_type) const {
363 return media_map_.find(mime_type) != media_map_.end();
364 }
365
IsSupportedNonImageMimeType(const char * mime_type) const366 bool MimeUtil::IsSupportedNonImageMimeType(const char* mime_type) const {
367 return non_image_map_.find(mime_type) != non_image_map_.end();
368 }
369
IsSupportedJavascriptMimeType(const char * mime_type) const370 bool MimeUtil::IsSupportedJavascriptMimeType(const char* mime_type) const {
371 return javascript_map_.find(mime_type) != javascript_map_.end();
372 }
373
IsViewSourceMimeType(const char * mime_type) const374 bool MimeUtil::IsViewSourceMimeType(const char* mime_type) const {
375 return view_source_map_.find(mime_type) != view_source_map_.end();
376 }
377
378 // Mirrors WebViewImpl::CanShowMIMEType()
IsSupportedMimeType(const std::string & mime_type) const379 bool MimeUtil::IsSupportedMimeType(const std::string& mime_type) const {
380 return (mime_type.compare(0, 6, "image/") == 0 &&
381 IsSupportedImageMimeType(mime_type.c_str())) ||
382 IsSupportedNonImageMimeType(mime_type.c_str());
383 }
384
MatchesMimeType(const std::string & mime_type_pattern,const std::string & mime_type) const385 bool MimeUtil::MatchesMimeType(const std::string &mime_type_pattern,
386 const std::string &mime_type) const {
387 // verify caller is passing lowercase
388 DCHECK_EQ(StringToLowerASCII(mime_type_pattern), mime_type_pattern);
389 DCHECK_EQ(StringToLowerASCII(mime_type), mime_type);
390
391 // This comparison handles absolute maching and also basic
392 // wildcards. The plugin mime types could be:
393 // application/x-foo
394 // application/*
395 // application/*+xml
396 // *
397 if (mime_type_pattern.empty())
398 return false;
399
400 const std::string::size_type star = mime_type_pattern.find('*');
401
402 if (star == std::string::npos)
403 return mime_type_pattern == mime_type;
404
405 // Test length to prevent overlap between |left| and |right|.
406 if (mime_type.length() < mime_type_pattern.length() - 1)
407 return false;
408
409 const std::string left(mime_type_pattern.substr(0, star));
410 const std::string right(mime_type_pattern.substr(star + 1));
411
412 if (mime_type.find(left) != 0)
413 return false;
414
415 if (!right.empty() &&
416 mime_type.rfind(right) != mime_type.length() - right.length())
417 return false;
418
419 return true;
420 }
421
AreSupportedMediaCodecs(const std::vector<std::string> & codecs) const422 bool MimeUtil::AreSupportedMediaCodecs(
423 const std::vector<std::string>& codecs) const {
424 for (size_t i = 0; i < codecs.size(); ++i) {
425 if (codecs_map_.find(codecs[i]) == codecs_map_.end()) {
426 return false;
427 }
428 }
429 return true;
430 }
431
ParseCodecString(const std::string & codecs,std::vector<std::string> * codecs_out,bool strip)432 void MimeUtil::ParseCodecString(const std::string& codecs,
433 std::vector<std::string>* codecs_out,
434 bool strip) {
435 std::string no_quote_codecs;
436 TrimString(codecs, "\"", &no_quote_codecs);
437 base::SplitString(no_quote_codecs, ',', codecs_out);
438
439 if (!strip)
440 return;
441
442 // Strip everything past the first '.'
443 for (std::vector<std::string>::iterator it = codecs_out->begin();
444 it != codecs_out->end();
445 ++it) {
446 size_t found = it->find_first_of('.');
447 if (found != std::string::npos)
448 it->resize(found);
449 }
450 }
451
IsStrictMediaMimeType(const std::string & mime_type) const452 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
453 if (strict_format_map_.find(mime_type) == strict_format_map_.end())
454 return false;
455 return true;
456 }
457
IsSupportedStrictMediaMimeType(const std::string & mime_type,const std::vector<std::string> & codecs) const458 bool MimeUtil::IsSupportedStrictMediaMimeType(const std::string& mime_type,
459 const std::vector<std::string>& codecs) const {
460 StrictMappings::const_iterator it = strict_format_map_.find(mime_type);
461
462 if (it == strict_format_map_.end())
463 return false;
464
465 const MimeMappings strict_codecs_map = it->second;
466 for (size_t i = 0; i < codecs.size(); ++i) {
467 if (strict_codecs_map.find(codecs[i]) == strict_codecs_map.end()) {
468 return false;
469 }
470 }
471 return true;
472 }
473
474 //----------------------------------------------------------------------------
475 // Wrappers for the singleton
476 //----------------------------------------------------------------------------
477
GetMimeTypeFromExtension(const FilePath::StringType & ext,std::string * mime_type)478 bool GetMimeTypeFromExtension(const FilePath::StringType& ext,
479 std::string* mime_type) {
480 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
481 }
482
GetMimeTypeFromFile(const FilePath & file_path,std::string * mime_type)483 bool GetMimeTypeFromFile(const FilePath& file_path, std::string* mime_type) {
484 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type);
485 }
486
GetPreferredExtensionForMimeType(const std::string & mime_type,FilePath::StringType * extension)487 bool GetPreferredExtensionForMimeType(const std::string& mime_type,
488 FilePath::StringType* extension) {
489 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type,
490 extension);
491 }
492
IsSupportedImageMimeType(const char * mime_type)493 bool IsSupportedImageMimeType(const char* mime_type) {
494 return g_mime_util.Get().IsSupportedImageMimeType(mime_type);
495 }
496
IsSupportedMediaMimeType(const char * mime_type)497 bool IsSupportedMediaMimeType(const char* mime_type) {
498 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type);
499 }
500
IsSupportedNonImageMimeType(const char * mime_type)501 bool IsSupportedNonImageMimeType(const char* mime_type) {
502 return g_mime_util.Get().IsSupportedNonImageMimeType(mime_type);
503 }
504
IsSupportedJavascriptMimeType(const char * mime_type)505 bool IsSupportedJavascriptMimeType(const char* mime_type) {
506 return g_mime_util.Get().IsSupportedJavascriptMimeType(mime_type);
507 }
508
IsViewSourceMimeType(const char * mime_type)509 bool IsViewSourceMimeType(const char* mime_type) {
510 return g_mime_util.Get().IsViewSourceMimeType(mime_type);
511 }
512
IsSupportedMimeType(const std::string & mime_type)513 bool IsSupportedMimeType(const std::string& mime_type) {
514 return g_mime_util.Get().IsSupportedMimeType(mime_type);
515 }
516
MatchesMimeType(const std::string & mime_type_pattern,const std::string & mime_type)517 bool MatchesMimeType(const std::string &mime_type_pattern,
518 const std::string &mime_type) {
519 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type);
520 }
521
AreSupportedMediaCodecs(const std::vector<std::string> & codecs)522 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) {
523 return g_mime_util.Get().AreSupportedMediaCodecs(codecs);
524 }
525
IsStrictMediaMimeType(const std::string & mime_type)526 bool IsStrictMediaMimeType(const std::string& mime_type) {
527 return g_mime_util.Get().IsStrictMediaMimeType(mime_type);
528 }
529
IsSupportedStrictMediaMimeType(const std::string & mime_type,const std::vector<std::string> & codecs)530 bool IsSupportedStrictMediaMimeType(const std::string& mime_type,
531 const std::vector<std::string>& codecs) {
532 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs);
533 }
534
ParseCodecString(const std::string & codecs,std::vector<std::string> * codecs_out,const bool strip)535 void ParseCodecString(const std::string& codecs,
536 std::vector<std::string>* codecs_out,
537 const bool strip) {
538 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip);
539 }
540
541 namespace {
542
543 // From http://www.w3schools.com/media/media_mimeref.asp and
544 // http://plugindoc.mozdev.org/winmime.php
545 static const char* kStandardImageTypes[] = {
546 "image/bmp",
547 "image/cis-cod",
548 "image/gif",
549 "image/ief",
550 "image/jpeg",
551 "image/webp",
552 "image/pict",
553 "image/pipeg",
554 "image/png",
555 "image/svg+xml",
556 "image/tiff",
557 "image/x-cmu-raster",
558 "image/x-cmx",
559 "image/x-icon",
560 "image/x-portable-anymap",
561 "image/x-portable-bitmap",
562 "image/x-portable-graymap",
563 "image/x-portable-pixmap",
564 "image/x-rgb",
565 "image/x-xbitmap",
566 "image/x-xpixmap",
567 "image/x-xwindowdump"
568 };
569 static const char* kStandardAudioTypes[] = {
570 "audio/aac",
571 "audio/aiff",
572 "audio/amr",
573 "audio/basic",
574 "audio/midi",
575 "audio/mp3",
576 "audio/mp4",
577 "audio/mpeg",
578 "audio/mpeg3",
579 "audio/ogg",
580 "audio/vorbis",
581 "audio/wav",
582 "audio/webm",
583 "audio/x-m4a",
584 "audio/x-ms-wma",
585 "audio/vnd.rn-realaudio",
586 "audio/vnd.wave"
587 };
588 static const char* kStandardVideoTypes[] = {
589 "video/avi",
590 "video/divx",
591 "video/flc",
592 "video/mp4",
593 "video/mpeg",
594 "video/ogg",
595 "video/quicktime",
596 "video/sd-video",
597 "video/webm",
598 "video/x-dv",
599 "video/x-m4v",
600 "video/x-mpeg",
601 "video/x-ms-asf",
602 "video/x-ms-wmv"
603 };
604
GetExtensionsFromHardCodedMappings(const MimeInfo * mappings,size_t mappings_len,const std::string & leading_mime_type,base::hash_set<FilePath::StringType> * extensions)605 void GetExtensionsFromHardCodedMappings(
606 const MimeInfo* mappings,
607 size_t mappings_len,
608 const std::string& leading_mime_type,
609 base::hash_set<FilePath::StringType>* extensions) {
610 FilePath::StringType extension;
611 for (size_t i = 0; i < mappings_len; ++i) {
612 if (StartsWithASCII(mappings[i].mime_type, leading_mime_type, false)) {
613 std::vector<string> this_extensions;
614 base::SplitStringUsingSubstr(mappings[i].extensions,
615 ",",
616 &this_extensions);
617 for (size_t j = 0; j < this_extensions.size(); ++j) {
618 #if defined(OS_WIN)
619 FilePath::StringType extension(UTF8ToWide(this_extensions[j]));
620 #else
621 FilePath::StringType extension(this_extensions[j]);
622 #endif
623 extensions->insert(extension);
624 }
625 }
626 }
627 }
628
GetExtensionsHelper(const char ** standard_types,size_t standard_types_len,const std::string & leading_mime_type,base::hash_set<FilePath::StringType> * extensions)629 void GetExtensionsHelper(
630 const char** standard_types,
631 size_t standard_types_len,
632 const std::string& leading_mime_type,
633 base::hash_set<FilePath::StringType>* extensions) {
634 FilePath::StringType extension;
635 for (size_t i = 0; i < standard_types_len; ++i) {
636 if (GetPreferredExtensionForMimeType(standard_types[i], &extension))
637 extensions->insert(extension);
638 }
639
640 // Also look up the extensions from hard-coded mappings in case that some
641 // supported extensions are not registered in the system registry, like ogg.
642 GetExtensionsFromHardCodedMappings(primary_mappings,
643 arraysize(primary_mappings),
644 leading_mime_type,
645 extensions);
646
647 GetExtensionsFromHardCodedMappings(secondary_mappings,
648 arraysize(secondary_mappings),
649 leading_mime_type,
650 extensions);
651 }
652
653 // Note that the elements in the source set will be appended to the target
654 // vector.
655 template<class T>
HashSetToVector(base::hash_set<T> * source,std::vector<T> * target)656 void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) {
657 size_t old_target_size = target->size();
658 target->resize(old_target_size + source->size());
659 size_t i = 0;
660 for (typename base::hash_set<T>::iterator iter = source->begin();
661 iter != source->end(); ++iter, ++i) {
662 target->at(old_target_size + i) = *iter;
663 }
664 }
665 }
666
GetImageExtensions(std::vector<FilePath::StringType> * extensions)667 void GetImageExtensions(std::vector<FilePath::StringType>* extensions) {
668 base::hash_set<FilePath::StringType> unique_extensions;
669 GetExtensionsHelper(kStandardImageTypes,
670 arraysize(kStandardImageTypes),
671 "image/",
672 &unique_extensions);
673 HashSetToVector(&unique_extensions, extensions);
674 }
675
GetAudioExtensions(std::vector<FilePath::StringType> * extensions)676 void GetAudioExtensions(std::vector<FilePath::StringType>* extensions) {
677 base::hash_set<FilePath::StringType> unique_extensions;
678 GetExtensionsHelper(kStandardAudioTypes,
679 arraysize(kStandardAudioTypes),
680 "audio/",
681 &unique_extensions);
682 HashSetToVector(&unique_extensions, extensions);
683 }
684
GetVideoExtensions(std::vector<FilePath::StringType> * extensions)685 void GetVideoExtensions(std::vector<FilePath::StringType>* extensions) {
686 base::hash_set<FilePath::StringType> unique_extensions;
687 GetExtensionsHelper(kStandardVideoTypes,
688 arraysize(kStandardVideoTypes),
689 "video/",
690 &unique_extensions);
691 HashSetToVector(&unique_extensions, extensions);
692 }
693
GetExtensionsForMimeType(const std::string & mime_type,std::vector<FilePath::StringType> * extensions)694 void GetExtensionsForMimeType(const std::string& mime_type,
695 std::vector<FilePath::StringType>* extensions) {
696 base::hash_set<FilePath::StringType> unique_extensions;
697 FilePath::StringType extension;
698 if (GetPreferredExtensionForMimeType(mime_type, &extension))
699 unique_extensions.insert(extension);
700
701 // Also look up the extensions from hard-coded mappings in case that some
702 // supported extensions are not registered in the system registry, like ogg.
703 GetExtensionsFromHardCodedMappings(primary_mappings,
704 arraysize(primary_mappings),
705 mime_type,
706 &unique_extensions);
707
708 GetExtensionsFromHardCodedMappings(secondary_mappings,
709 arraysize(secondary_mappings),
710 mime_type,
711 &unique_extensions);
712
713 HashSetToVector(&unique_extensions, extensions);
714 }
715
716 } // namespace net
717