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