Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL
[WebKit-https.git] / Source / WebCore / platform / MIMETypeRegistry.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2009 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "MIMETypeRegistry.h"
29
30 #include "MediaPlayer.h"
31 #include <wtf/HashMap.h>
32 #include <wtf/HashSet.h>
33 #include <wtf/MainThread.h>
34 #include <wtf/NeverDestroyed.h>
35 #include <wtf/StdLibExtras.h>
36 #include <wtf/text/StringHash.h>
37
38 #if USE(CG)
39 #include "ImageSourceCG.h"
40 #if !PLATFORM(IOS)
41 #include <ApplicationServices/ApplicationServices.h>
42 #else
43 #include <ImageIO/CGImageDestination.h>
44 #endif
45 #include <wtf/RetainPtr.h>
46 #endif
47
48 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
49 #include "ArchiveFactory.h"
50 #endif
51
52 namespace WebCore {
53
54 namespace {
55 struct TypeExtensionPair {
56     const char* type;
57     const char* extension;
58 };
59 }
60
61 // A table of common media MIME types and file extenstions used when a platform's
62 // specific MIME type lookup doesn't have a match for a media file extension.
63 static const TypeExtensionPair commonMediaTypes[] = {
64
65     // Ogg
66     { "application/ogg", "ogx" },
67     { "audio/ogg", "ogg" },
68     { "audio/ogg", "oga" },
69     { "video/ogg", "ogv" },
70
71     // Annodex
72     { "application/annodex", "anx" },
73     { "audio/annodex", "axa" },
74     { "video/annodex", "axv" },
75     { "audio/speex", "spx" },
76
77     // WebM
78     { "video/webm", "webm" },
79     { "audio/webm", "webm" },
80
81     // MPEG
82     { "audio/mpeg", "m1a" },
83     { "audio/mpeg", "m2a" },
84     { "audio/mpeg", "m1s" },
85     { "audio/mpeg", "mpa" },
86     { "video/mpeg", "mpg" },
87     { "video/mpeg", "m15" },
88     { "video/mpeg", "m1s" },
89     { "video/mpeg", "m1v" },
90     { "video/mpeg", "m75" },
91     { "video/mpeg", "mpa" },
92     { "video/mpeg", "mpeg" },
93     { "video/mpeg", "mpm" },
94     { "video/mpeg", "mpv" },
95
96     // MPEG playlist
97     { "application/vnd.apple.mpegurl", "m3u8" },
98     { "application/mpegurl", "m3u8" },
99     { "application/x-mpegurl", "m3u8" },
100     { "audio/mpegurl", "m3url" },
101     { "audio/x-mpegurl", "m3url" },
102     { "audio/mpegurl", "m3u" },
103     { "audio/x-mpegurl", "m3u" },
104
105     // MPEG-4
106     { "video/x-m4v", "m4v" },
107     { "audio/x-m4a", "m4a" },
108     { "audio/x-m4b", "m4b" },
109     { "audio/x-m4p", "m4p" },
110     { "audio/mp4", "m4a" },
111
112     // MP3
113     { "audio/mp3", "mp3" },
114     { "audio/x-mp3", "mp3" },
115     { "audio/x-mpeg", "mp3" },
116
117     // MPEG-2
118     { "video/x-mpeg2", "mp2" },
119     { "video/mpeg2", "vob" },
120     { "video/mpeg2", "mod" },
121     { "video/m2ts", "m2ts" },
122     { "video/x-m2ts", "m2t" },
123     { "video/x-m2ts", "ts" },
124
125     // 3GP/3GP2
126     { "audio/3gpp", "3gpp" }, 
127     { "audio/3gpp2", "3g2" }, 
128     { "application/x-mpeg", "amc" },
129
130     // AAC
131     { "audio/aac", "aac" },
132     { "audio/aac", "adts" },
133     { "audio/x-aac", "m4r" },
134
135     // CoreAudio File
136     { "audio/x-caf", "caf" },
137     { "audio/x-gsm", "gsm" },
138
139     // ADPCM
140     { "audio/x-wav", "wav" }
141 };
142
143 static HashSet<String>* supportedImageResourceMIMETypes;
144 static HashSet<String>* supportedImageMIMETypes;
145 static HashSet<String>* supportedImageMIMETypesForEncoding;
146 static HashSet<String>* supportedJavaScriptMIMETypes;
147 static HashSet<String>* supportedNonImageMIMETypes;
148 static HashSet<String>* supportedMediaMIMETypes;
149 static HashSet<String>* pdfMIMETypes;
150 static HashSet<String>* pdfAndPostScriptMIMETypes;
151 static HashSet<String>* unsupportedTextMIMETypes;
152
153 typedef HashMap<String, Vector<String>*, CaseFoldingHash> MediaMIMETypeMap;
154     
155 static void initializeSupportedImageMIMETypes()
156 {
157 #if USE(CG)
158     RetainPtr<CFArrayRef> supportedTypes = adoptCF(CGImageSourceCopyTypeIdentifiers());
159     CFIndex count = CFArrayGetCount(supportedTypes.get());
160     for (CFIndex i = 0; i < count; i++) {
161         CFStringRef supportedType = reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i));
162         String mimeType = MIMETypeForImageSourceType(supportedType);
163         if (!mimeType.isEmpty()) {
164             supportedImageMIMETypes->add(mimeType);
165             supportedImageResourceMIMETypes->add(mimeType);
166         }
167     }
168
169     // On Tiger and Leopard, com.microsoft.bmp doesn't have a MIME type in the registry.
170     supportedImageMIMETypes->add("image/bmp");
171     supportedImageResourceMIMETypes->add("image/bmp");
172
173     // Favicons don't have a MIME type in the registry either.
174     supportedImageMIMETypes->add("image/vnd.microsoft.icon");
175     supportedImageMIMETypes->add("image/x-icon");
176     supportedImageResourceMIMETypes->add("image/vnd.microsoft.icon");
177     supportedImageResourceMIMETypes->add("image/x-icon");
178
179     //  We only get one MIME type per UTI, hence our need to add these manually
180     supportedImageMIMETypes->add("image/pjpeg");
181     supportedImageResourceMIMETypes->add("image/pjpeg");
182
183     //  We don't want to try to treat all binary data as an image
184     supportedImageMIMETypes->remove("application/octet-stream");
185     supportedImageResourceMIMETypes->remove("application/octet-stream");
186
187     //  Don't treat pdf/postscript as images directly
188     supportedImageMIMETypes->remove("application/pdf");
189     supportedImageMIMETypes->remove("application/postscript");
190
191 #if PLATFORM(IOS)
192     // Add malformed image mimetype for compatibility with Mail and to handle malformed mimetypes from the net
193     // These were removed for <rdar://problem/6564538> Re-enable UTI code in WebCore now that MobileCoreServices exists
194     // But Mail relies on at least image/tif reported as being supported (should be image/tiff).
195     // This can be removed when Mail addresses:
196     // <rdar://problem/7879510> Mail should use standard image mimetypes 
197     // and we fix sniffing so that it corrects items such as image/jpg -> image/jpeg.
198     static const char* malformedMIMETypes[] = {
199         // JPEG (image/jpeg)
200         "image/jpg", "image/jp_", "image/jpe_", "application/jpg", "application/x-jpg", "image/pipeg",
201         "image/vnd.switfview-jpeg", "image/x-xbitmap",
202         // GIF (image/gif)
203         "image/gi_",
204         // PNG (image/png)
205         "application/png", "application/x-png",
206         // TIFF (image/tiff)
207         "image/x-tif", "image/tif", "image/x-tiff", "application/tif", "application/x-tif", "application/tiff",
208         "application/x-tiff",
209         // BMP (image/bmp, image/x-bitmap)
210         "image/x-bmp", "image/x-win-bitmap", "image/x-windows-bmp", "image/ms-bmp", "image/x-ms-bmp",
211         "application/bmp", "application/x-bmp", "application/x-win-bitmap",
212     };
213     for (size_t i = 0; i < WTF_ARRAY_LENGTH(malformedMIMETypes); ++i) {
214         supportedImageMIMETypes->add(malformedMIMETypes[i]);
215         supportedImageResourceMIMETypes->add(malformedMIMETypes[i]);
216     }
217 #endif
218
219 #else
220     // assume that all implementations at least support the following standard
221     // image types:
222     static const char* types[] = {
223         "image/jpeg",
224         "image/png",
225         "image/gif",
226         "image/bmp",
227         "image/vnd.microsoft.icon",    // ico
228         "image/x-icon",    // ico
229         "image/x-xbitmap"  // xbm
230     };
231     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
232         supportedImageMIMETypes->add(types[i]);
233         supportedImageResourceMIMETypes->add(types[i]);
234     }
235
236 #if USE(WEBP)
237     supportedImageMIMETypes->add("image/webp");
238     supportedImageResourceMIMETypes->add("image/webp");
239 #endif
240
241 #endif // USE(CG)
242 }
243
244 static void initializeSupportedImageMIMETypesForEncoding()
245 {
246     supportedImageMIMETypesForEncoding = new HashSet<String>;
247
248 #if USE(CG)
249 #if PLATFORM(COCOA)
250     RetainPtr<CFArrayRef> supportedTypes = adoptCF(CGImageDestinationCopyTypeIdentifiers());
251     CFIndex count = CFArrayGetCount(supportedTypes.get());
252     for (CFIndex i = 0; i < count; i++) {
253         CFStringRef supportedType = reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i));
254         String mimeType = MIMETypeForImageSourceType(supportedType);
255         if (!mimeType.isEmpty())
256             supportedImageMIMETypesForEncoding->add(mimeType);
257     }
258 #else
259     // FIXME: Add Windows support for all the supported UTI's when a way to convert from MIMEType to UTI reliably is found.
260     // For now, only support PNG, JPEG and GIF.  See <rdar://problem/6095286>.
261     supportedImageMIMETypesForEncoding->add("image/png");
262     supportedImageMIMETypesForEncoding->add("image/jpeg");
263     supportedImageMIMETypesForEncoding->add("image/gif");
264 #endif
265 #elif PLATFORM(GTK)
266     supportedImageMIMETypesForEncoding->add("image/png");
267     supportedImageMIMETypesForEncoding->add("image/jpeg");
268     supportedImageMIMETypesForEncoding->add("image/tiff");
269     supportedImageMIMETypesForEncoding->add("image/bmp");
270     supportedImageMIMETypesForEncoding->add("image/ico");
271 #elif PLATFORM(EFL)
272     supportedImageMIMETypesForEncoding->add("image/png");
273     supportedImageMIMETypesForEncoding->add("image/jpeg");
274 #elif USE(CAIRO)
275     supportedImageMIMETypesForEncoding->add("image/png");
276 #endif
277 }
278
279 static void initializeSupportedJavaScriptMIMETypes()
280 {
281     // https://html.spec.whatwg.org/multipage/scripting.html#javascript-mime-type
282     static const char* types[] = {
283         "text/javascript",
284         "text/ecmascript",
285         "application/javascript",
286         "application/ecmascript",
287         "application/x-javascript",
288         "application/x-ecmascript",
289         "text/javascript1.0",
290         "text/javascript1.1",
291         "text/javascript1.2",
292         "text/javascript1.3",
293         "text/javascript1.4",
294         "text/javascript1.5",
295         "text/jscript",
296         "text/livescript",
297         "text/x-javascript",
298         "text/x-ecmascript"
299     };
300     for (auto* type : types)
301         supportedJavaScriptMIMETypes->add(type);
302 }
303
304 static void initializePDFMIMETypes()
305 {
306     const char* const types[] = {
307         "application/pdf",
308         "text/pdf"
309     };
310     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
311         pdfMIMETypes->add(types[i]);
312 }
313
314 static void initializePostScriptMIMETypes()
315 {
316     pdfAndPostScriptMIMETypes->add("application/postscript");
317 }
318
319 static void initializeSupportedNonImageMimeTypes()
320 {
321     static const char* types[] = {
322         "text/html",
323         "text/xml",
324         "text/xsl",
325         "text/plain",
326         "text/",
327         "application/xml",
328         "application/xhtml+xml",
329 #if !PLATFORM(IOS)
330         "application/vnd.wap.xhtml+xml",
331         "application/rss+xml",
332         "application/atom+xml",
333 #endif
334         "application/json",
335         "image/svg+xml",
336 #if ENABLE(FTPDIR)
337         "application/x-ftp-directory",
338 #endif
339         "multipart/x-mixed-replace"
340         // Note: ADDING a new type here will probably render it as HTML. This can
341         // result in cross-site scripting.
342     };
343     COMPILE_ASSERT(sizeof(types) / sizeof(types[0]) <= 16,
344                    nonimage_mime_types_must_be_less_than_or_equal_to_16);
345
346     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
347         supportedNonImageMIMETypes->add(types[i]);
348
349 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
350     ArchiveFactory::registerKnownArchiveMIMETypes();
351 #endif
352 }
353
354 static MediaMIMETypeMap& mediaMIMETypeMap()
355 {
356     static NeverDestroyed<MediaMIMETypeMap> mediaMIMETypeForExtensionMap;
357
358     if (!mediaMIMETypeForExtensionMap.get().isEmpty())
359         return mediaMIMETypeForExtensionMap;
360
361     const unsigned numPairs = sizeof(commonMediaTypes) / sizeof(commonMediaTypes[0]);
362     for (unsigned ndx = 0; ndx < numPairs; ++ndx) {
363
364         if (mediaMIMETypeForExtensionMap.get().contains(commonMediaTypes[ndx].extension))
365             mediaMIMETypeForExtensionMap.get().get(commonMediaTypes[ndx].extension)->append(commonMediaTypes[ndx].type);
366         else {
367             Vector<String>* synonyms = new Vector<String>;
368
369             // If there is a system specific type for this extension, add it as the first type so
370             // getMediaMIMETypeForExtension will always return it.
371             String systemType = MIMETypeRegistry::getMIMETypeForExtension(commonMediaTypes[ndx].extension);
372             if (!systemType.isEmpty() && commonMediaTypes[ndx].type != systemType)
373                 synonyms->append(systemType);
374             synonyms->append(commonMediaTypes[ndx].type);
375             mediaMIMETypeForExtensionMap.get().add(commonMediaTypes[ndx].extension, synonyms);
376         }
377     }
378
379     return mediaMIMETypeForExtensionMap;
380 }
381
382 String MIMETypeRegistry::getMediaMIMETypeForExtension(const String& ext)
383 {
384     // Look in the system-specific registry first.
385     String type = getMIMETypeForExtension(ext);
386     if (!type.isEmpty())
387         return type;
388
389     Vector<String>* typeList = mediaMIMETypeMap().get(ext);
390     if (typeList)
391         return (*typeList)[0];
392     
393     return String();
394 }
395     
396 Vector<String> MIMETypeRegistry::getMediaMIMETypesForExtension(const String& ext)
397 {
398     Vector<String>* typeList = mediaMIMETypeMap().get(ext);
399     if (typeList)
400         return *typeList;
401
402     // Only need to look in the system-specific registry if mediaMIMETypeMap() doesn't contain
403     // the extension at all, because it always contains the system-specific type if the
404     // extension is in the static mapping table.
405     String type = getMIMETypeForExtension(ext);
406     if (!type.isEmpty()) {
407         Vector<String> typeList;
408         typeList.append(type);
409         return typeList;
410     }
411     
412     return Vector<String>();
413 }
414
415 static void initializeSupportedMediaMIMETypes()
416 {
417     supportedMediaMIMETypes = new HashSet<String>;
418 #if ENABLE(VIDEO)
419     MediaPlayer::getSupportedTypes(*supportedMediaMIMETypes);
420 #endif
421 }
422
423 static void initializeUnsupportedTextMIMETypes()
424 {
425     static const char* types[] = {
426         "text/calendar",
427         "text/x-calendar",
428         "text/x-vcalendar",
429         "text/vcalendar",
430         "text/vcard",
431         "text/x-vcard",
432         "text/directory",
433         "text/ldif",
434         "text/qif",
435         "text/x-qif",
436         "text/x-csv",
437         "text/x-vcf",
438 #if !PLATFORM(IOS)
439         "text/rtf",
440 #else
441         "text/vnd.sun.j2me.app-descriptor",
442 #endif
443     };
444     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
445       unsupportedTextMIMETypes->add(types[i]);
446 }
447
448 static void initializeMIMETypeRegistry()
449 {
450     supportedJavaScriptMIMETypes = new HashSet<String>;
451     initializeSupportedJavaScriptMIMETypes();
452
453     supportedNonImageMIMETypes = new HashSet<String>(*supportedJavaScriptMIMETypes);
454     initializeSupportedNonImageMimeTypes();
455
456     supportedImageResourceMIMETypes = new HashSet<String>;
457     supportedImageMIMETypes = new HashSet<String>;
458     initializeSupportedImageMIMETypes();
459
460     pdfMIMETypes = new HashSet<String>;
461     initializePDFMIMETypes();
462
463     pdfAndPostScriptMIMETypes = new HashSet<String>(*pdfMIMETypes);
464     initializePostScriptMIMETypes();
465
466     unsupportedTextMIMETypes = new HashSet<String>;
467     initializeUnsupportedTextMIMETypes();
468 }
469
470 String MIMETypeRegistry::getMIMETypeForPath(const String& path)
471 {
472     size_t pos = path.reverseFind('.');
473     if (pos != notFound) {
474         String extension = path.substring(pos + 1);
475         String result = getMIMETypeForExtension(extension);
476         if (result.length())
477             return result;
478     }
479     return defaultMIMEType();
480 }
481
482 bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
483 {
484     if (mimeType.isEmpty())
485         return false;
486     if (!supportedImageMIMETypes)
487         initializeMIMETypeRegistry();
488     return supportedImageMIMETypes->contains(getNormalizedMIMEType(mimeType));
489 }
490
491 bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
492 {
493     if (mimeType.isEmpty())
494         return false;
495     if (!supportedImageResourceMIMETypes)
496         initializeMIMETypeRegistry();
497     return supportedImageResourceMIMETypes->contains(getNormalizedMIMEType(mimeType));
498 }
499
500 bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
501 {
502     ASSERT(isMainThread());
503
504     if (mimeType.isEmpty())
505         return false;
506     if (!supportedImageMIMETypesForEncoding)
507         initializeSupportedImageMIMETypesForEncoding();
508     return supportedImageMIMETypesForEncoding->contains(mimeType);
509 }
510
511 bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
512 {
513     if (mimeType.isEmpty())
514         return false;
515     if (!supportedJavaScriptMIMETypes)
516         initializeMIMETypeRegistry();
517     return supportedJavaScriptMIMETypes->contains(mimeType);
518 }
519
520 bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
521 {
522     if (mimeType.isEmpty())
523         return false;
524     if (!supportedNonImageMIMETypes)
525         initializeMIMETypeRegistry();
526     return supportedNonImageMIMETypes->contains(mimeType);
527 }
528
529 bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
530 {
531     if (mimeType.isEmpty())
532         return false;
533     if (!supportedMediaMIMETypes)
534         initializeSupportedMediaMIMETypes();
535     return supportedMediaMIMETypes->contains(mimeType);
536 }
537
538 bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
539 {
540     if (mimeType.isEmpty())
541         return false;
542     if (!unsupportedTextMIMETypes)
543         initializeMIMETypeRegistry();
544     return unsupportedTextMIMETypes->contains(mimeType);
545 }
546
547 bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
548 {
549     // Since this set is very limited and is likely to remain so we won't bother with the overhead
550     // of using a hash set.
551     // Any of the MIME types below may be followed by any number of specific versions of the JVM,
552     // which is why we use startsWith()
553     return mimeType.startsWith("application/x-java-applet", false)
554         || mimeType.startsWith("application/x-java-bean", false)
555         || mimeType.startsWith("application/x-java-vm", false);
556 }
557
558 bool MIMETypeRegistry::isPDFOrPostScriptMIMEType(const String& mimeType)
559 {
560     if (mimeType.isEmpty())
561         return false;
562     if (!pdfAndPostScriptMIMETypes)
563         initializeMIMETypeRegistry();
564     return pdfAndPostScriptMIMETypes->contains(mimeType);
565 }
566
567 bool MIMETypeRegistry::isPDFMIMEType(const String& mimeType)
568 {
569     if (mimeType.isEmpty())
570         return false;
571     if (!pdfMIMETypes)
572         initializeMIMETypeRegistry();
573     return pdfMIMETypes->contains(mimeType);
574 }
575
576 bool MIMETypeRegistry::canShowMIMEType(const String& mimeType)
577 {
578     if (isSupportedImageMIMEType(mimeType) || isSupportedNonImageMIMEType(mimeType) || isSupportedMediaMIMEType(mimeType))
579         return true;
580
581     if (mimeType.startsWith("text/", false))
582         return !MIMETypeRegistry::isUnsupportedTextMIMEType(mimeType);
583
584     return false;
585 }
586
587 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypes()
588 {
589     if (!supportedImageMIMETypes)
590         initializeMIMETypeRegistry();
591     return *supportedImageMIMETypes;
592 }
593
594 HashSet<String>& MIMETypeRegistry::getSupportedImageResourceMIMETypes()
595 {
596     if (!supportedImageResourceMIMETypes)
597         initializeMIMETypeRegistry();
598     return *supportedImageResourceMIMETypes;
599 }
600
601 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypesForEncoding()
602 {
603     if (!supportedImageMIMETypesForEncoding)
604         initializeSupportedImageMIMETypesForEncoding();
605     return *supportedImageMIMETypesForEncoding;
606 }
607
608 HashSet<String>& MIMETypeRegistry::getSupportedNonImageMIMETypes()
609 {
610     if (!supportedNonImageMIMETypes)
611         initializeMIMETypeRegistry();
612     return *supportedNonImageMIMETypes;
613 }
614
615 HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes()
616 {
617     if (!supportedMediaMIMETypes)
618         initializeSupportedMediaMIMETypes();
619     return *supportedMediaMIMETypes;
620 }
621
622
623 HashSet<String>& MIMETypeRegistry::getPDFMIMETypes()
624 {
625     if (!pdfMIMETypes)
626         initializeMIMETypeRegistry();
627     return *pdfMIMETypes;
628 }
629
630 HashSet<String>& MIMETypeRegistry::getPDFAndPostScriptMIMETypes()
631 {
632     if (!pdfAndPostScriptMIMETypes)
633         initializeMIMETypeRegistry();
634     return *pdfAndPostScriptMIMETypes;
635 }
636
637 HashSet<String>& MIMETypeRegistry::getUnsupportedTextMIMETypes()
638 {
639     if (!unsupportedTextMIMETypes)
640         initializeMIMETypeRegistry();
641     return *unsupportedTextMIMETypes;
642 }
643
644 const String& defaultMIMEType()
645 {
646     static NeverDestroyed<const String> defaultMIMEType(ASCIILiteral("application/octet-stream"));
647     return defaultMIMEType;
648 }
649
650 #if !USE(CURL)
651 String MIMETypeRegistry::getNormalizedMIMEType(const String& mimeType)
652 {
653     return mimeType;
654 }
655 #endif
656
657 #if USE(CURL)
658 typedef HashMap<String, String> MIMETypeAssociationMap;
659
660 static const MIMETypeAssociationMap& mimeTypeAssociationMap()
661 {
662     static MIMETypeAssociationMap* mimeTypeMap = 0;
663     if (mimeTypeMap)
664         return *mimeTypeMap;
665
666     mimeTypeMap = new MIMETypeAssociationMap;
667
668     mimeTypeMap->add(ASCIILiteral("image/x-ms-bmp"), ASCIILiteral("image/bmp"));
669     mimeTypeMap->add(ASCIILiteral("image/x-windows-bmp"), ASCIILiteral("image/bmp"));
670     mimeTypeMap->add(ASCIILiteral("image/x-bmp"), ASCIILiteral("image/bmp"));
671     mimeTypeMap->add(ASCIILiteral("image/x-bitmap"), ASCIILiteral("image/bmp"));
672     mimeTypeMap->add(ASCIILiteral("image/x-ms-bitmap"), ASCIILiteral("image/bmp"));
673     mimeTypeMap->add(ASCIILiteral("image/jpg"), ASCIILiteral("image/jpeg"));
674     mimeTypeMap->add(ASCIILiteral("image/pjpeg"), ASCIILiteral("image/jpeg"));
675     mimeTypeMap->add(ASCIILiteral("image/x-png"), ASCIILiteral("image/png"));
676     mimeTypeMap->add(ASCIILiteral("image/vnd.rim.png"), ASCIILiteral("image/png"));
677     mimeTypeMap->add(ASCIILiteral("image/ico"), ASCIILiteral("image/vnd.microsoft.icon"));
678     mimeTypeMap->add(ASCIILiteral("image/icon"), ASCIILiteral("image/vnd.microsoft.icon"));
679     mimeTypeMap->add(ASCIILiteral("text/ico"), ASCIILiteral("image/vnd.microsoft.icon"));
680     mimeTypeMap->add(ASCIILiteral("application/ico"), ASCIILiteral("image/vnd.microsoft.icon"));
681     mimeTypeMap->add(ASCIILiteral("image/x-icon"), ASCIILiteral("image/vnd.microsoft.icon"));
682     mimeTypeMap->add(ASCIILiteral("audio/vnd.qcelp"), ASCIILiteral("audio/qcelp"));
683     mimeTypeMap->add(ASCIILiteral("audio/qcp"), ASCIILiteral("audio/qcelp"));
684     mimeTypeMap->add(ASCIILiteral("audio/vnd.qcp"), ASCIILiteral("audio/qcelp"));
685     mimeTypeMap->add(ASCIILiteral("audio/wav"), ASCIILiteral("audio/x-wav"));
686     mimeTypeMap->add(ASCIILiteral("audio/mid"), ASCIILiteral("audio/midi"));
687     mimeTypeMap->add(ASCIILiteral("audio/sp-midi"), ASCIILiteral("audio/midi"));
688     mimeTypeMap->add(ASCIILiteral("audio/x-mid"), ASCIILiteral("audio/midi"));
689     mimeTypeMap->add(ASCIILiteral("audio/x-midi"), ASCIILiteral("audio/midi"));
690     mimeTypeMap->add(ASCIILiteral("audio/x-mpeg"), ASCIILiteral("audio/mpeg"));
691     mimeTypeMap->add(ASCIILiteral("audio/mp3"), ASCIILiteral("audio/mpeg"));
692     mimeTypeMap->add(ASCIILiteral("audio/x-mp3"), ASCIILiteral("audio/mpeg"));
693     mimeTypeMap->add(ASCIILiteral("audio/mpeg3"), ASCIILiteral("audio/mpeg"));
694     mimeTypeMap->add(ASCIILiteral("audio/x-mpeg3"), ASCIILiteral("audio/mpeg"));
695     mimeTypeMap->add(ASCIILiteral("audio/mpg3"), ASCIILiteral("audio/mpeg"));
696     mimeTypeMap->add(ASCIILiteral("audio/mpg"), ASCIILiteral("audio/mpeg"));
697     mimeTypeMap->add(ASCIILiteral("audio/x-mpg"), ASCIILiteral("audio/mpeg"));
698     mimeTypeMap->add(ASCIILiteral("audio/m4a"), ASCIILiteral("audio/mp4"));
699     mimeTypeMap->add(ASCIILiteral("audio/x-m4a"), ASCIILiteral("audio/mp4"));
700     mimeTypeMap->add(ASCIILiteral("audio/x-mp4"), ASCIILiteral("audio/mp4"));
701     mimeTypeMap->add(ASCIILiteral("audio/x-aac"), ASCIILiteral("audio/aac"));
702     mimeTypeMap->add(ASCIILiteral("audio/x-amr"), ASCIILiteral("audio/amr"));
703     mimeTypeMap->add(ASCIILiteral("audio/mpegurl"), ASCIILiteral("audio/x-mpegurl"));
704     mimeTypeMap->add(ASCIILiteral("audio/flac"), ASCIILiteral("audio/x-flac"));
705     mimeTypeMap->add(ASCIILiteral("video/3gp"), ASCIILiteral("video/3gpp"));
706     mimeTypeMap->add(ASCIILiteral("video/avi"), ASCIILiteral("video/x-msvideo"));
707     mimeTypeMap->add(ASCIILiteral("video/x-m4v"), ASCIILiteral("video/mp4"));
708     mimeTypeMap->add(ASCIILiteral("video/x-quicktime"), ASCIILiteral("video/quicktime"));
709     mimeTypeMap->add(ASCIILiteral("application/java"), ASCIILiteral("application/java-archive"));
710     mimeTypeMap->add(ASCIILiteral("application/x-java-archive"), ASCIILiteral("application/java-archive"));
711     mimeTypeMap->add(ASCIILiteral("application/x-zip-compressed"), ASCIILiteral("application/zip"));
712     mimeTypeMap->add(ASCIILiteral("text/cache-manifest"), ASCIILiteral("text/plain"));
713
714     return *mimeTypeMap;
715 }
716
717 String MIMETypeRegistry::getNormalizedMIMEType(const String& mimeType)
718 {
719     MIMETypeAssociationMap::const_iterator it = mimeTypeAssociationMap().find(mimeType);
720
721     if (it != mimeTypeAssociationMap().end())
722         return it->value;
723
724     return mimeType;
725 }
726 #endif
727
728 } // namespace WebCore