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