[Qt] Set WebCore imagedecoders as default and add fallback to QImageDecoder
[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 #if PLATFORM(QT)
43 #include <QImageReader>
44 #include <QImageWriter>
45 #endif
46
47 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
48 #include "ArchiveFactory.h"
49 #endif
50
51 namespace WebCore {
52
53 namespace {
54 struct 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.
62 static 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
142 static const char textPlain[] = "text/plain";
143 static const char textHtml[] = "text/html";
144 static const char imageJpeg[] = "image/jpeg";
145 static const char octetStream[] = "application/octet-stream";
146
147 // A table of well known MIME types used when we don't want to leak to the
148 // caller information about types known to underlying platform.
149 static const TypeExtensionPair wellKnownMimeTypes[] = {
150     { textPlain, "txt" },
151     { textPlain, "text" },
152     { textHtml, "html" },
153     { textHtml, "htm" },
154     { "text/css", "css" },
155     { "text/xml", "xml" },
156     { "text/xsl", "xsl" },
157     { "image/gif", "gif" },
158     { "image/png", "png" },
159     { imageJpeg, "jpeg" },
160     { imageJpeg, "jpg" },
161     { imageJpeg, "jfif" },
162     { imageJpeg, "pjpeg" },
163     { "image/webp", "webp" },
164     { "image/bmp", "bmp" },
165     { "application/xhtml+xml", "xhtml" },
166     { "application/x-javascript", "js" },
167     { "application/json", "json" },
168     { octetStream, "exe" },
169     { octetStream, "com" },
170     { octetStream, "bin" },
171     { "application/zip", "zip" },
172     { "application/gzip", "gz" },
173     { "application/pdf", "pdf" },
174     { "application/postscript", "ps" },
175     { "image/x-icon", "ico" },
176     { "image/tiff", "tiff" },
177     { "image/x-xbitmap", "xbm" },
178     { "image/svg+xml", "svg" },
179     { "application/rss+xml", "rss" },
180     { "application/rdf+xml", "rdf" },
181     { "application/x-shockwave-flash", "swf" },
182 };
183
184 static HashSet<String>* supportedImageResourceMIMETypes;
185 static HashSet<String>* supportedImageMIMETypes;
186 static HashSet<String>* supportedImageMIMETypesForEncoding;
187 static HashSet<String>* supportedJavaScriptMIMETypes;
188 static HashSet<String>* supportedNonImageMIMETypes;
189 static HashSet<String>* supportedMediaMIMETypes;
190 static HashSet<String>* unsupportedTextMIMETypes;
191
192 typedef HashMap<String, Vector<String>*, CaseFoldingHash> MediaMIMETypeMap;
193     
194 static void initializeSupportedImageMIMETypes()
195 {
196 #if USE(CG)
197     RetainPtr<CFArrayRef> supportedTypes(AdoptCF, CGImageSourceCopyTypeIdentifiers());
198     CFIndex count = CFArrayGetCount(supportedTypes.get());
199     for (CFIndex i = 0; i < count; i++) {
200         RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
201         String mimeType = MIMETypeForImageSourceType(supportedType.get());
202         if (!mimeType.isEmpty()) {
203             supportedImageMIMETypes->add(mimeType);
204             supportedImageResourceMIMETypes->add(mimeType);
205         }
206     }
207
208     // On Tiger and Leopard, com.microsoft.bmp doesn't have a MIME type in the registry.
209     supportedImageMIMETypes->add("image/bmp");
210     supportedImageResourceMIMETypes->add("image/bmp");
211
212     // Favicons don't have a MIME type in the registry either.
213     supportedImageMIMETypes->add("image/vnd.microsoft.icon");
214     supportedImageMIMETypes->add("image/x-icon");
215     supportedImageResourceMIMETypes->add("image/vnd.microsoft.icon");
216     supportedImageResourceMIMETypes->add("image/x-icon");
217
218     //  We only get one MIME type per UTI, hence our need to add these manually
219     supportedImageMIMETypes->add("image/pjpeg");
220     supportedImageResourceMIMETypes->add("image/pjpeg");
221
222     //  We don't want to try to treat all binary data as an image
223     supportedImageMIMETypes->remove("application/octet-stream");
224     supportedImageResourceMIMETypes->remove("application/octet-stream");
225
226     //  Don't treat pdf/postscript as images directly
227     supportedImageMIMETypes->remove("application/pdf");
228     supportedImageMIMETypes->remove("application/postscript");
229
230 #else
231     // assume that all implementations at least support the following standard
232     // image types:
233     static const char* types[] = {
234         "image/jpeg",
235         "image/png",
236         "image/gif",
237         "image/bmp",
238         "image/vnd.microsoft.icon",    // ico
239         "image/x-icon",    // ico
240         "image/x-xbitmap"  // xbm
241     };
242     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
243         supportedImageMIMETypes->add(types[i]);
244         supportedImageResourceMIMETypes->add(types[i]);
245     }
246 #if PLATFORM(QT)
247     QList<QByteArray> formats = QImageReader::supportedImageFormats();
248     for (size_t i = 0; i < static_cast<size_t>(formats.size()); ++i) {
249 #if ENABLE(SVG)
250         // Qt has support for SVG, but we want to use KSVG2
251         if (formats.at(i).toLower().startsWith("svg"))
252             continue;
253 #endif // ENABLE(SVG)
254         String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
255         if (!mimeType.isEmpty()) {
256             supportedImageMIMETypes->add(mimeType);
257             supportedImageResourceMIMETypes->add(mimeType);
258         }
259     }
260 #endif // PLATFORM(QT)
261 #if PLATFORM(BLACKBERRY)
262     supportedImageMIMETypes->add("image/pjpeg");
263     supportedImageResourceMIMETypes->add("image/pjpeg");
264 #endif
265 #endif
266 }
267
268 static void initializeSupportedImageMIMETypesForEncoding()
269 {
270     supportedImageMIMETypesForEncoding = new HashSet<String>;
271
272 #if USE(CG)
273 #if PLATFORM(MAC)
274     RetainPtr<CFArrayRef> supportedTypes(AdoptCF, CGImageDestinationCopyTypeIdentifiers());
275     CFIndex count = CFArrayGetCount(supportedTypes.get());
276     for (CFIndex i = 0; i < count; i++) {
277         RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
278         String mimeType = MIMETypeForImageSourceType(supportedType.get());
279         if (!mimeType.isEmpty())
280             supportedImageMIMETypesForEncoding->add(mimeType);
281     }
282 #else
283     // FIXME: Add Windows support for all the supported UTI's when a way to convert from MIMEType to UTI reliably is found.
284     // For now, only support PNG, JPEG and GIF.  See <rdar://problem/6095286>.
285     supportedImageMIMETypesForEncoding->add("image/png");
286     supportedImageMIMETypesForEncoding->add("image/jpeg");
287     supportedImageMIMETypesForEncoding->add("image/gif");
288 #endif
289 #elif PLATFORM(QT)
290     QList<QByteArray> formats = QImageWriter::supportedImageFormats();
291     for (int i = 0; i < formats.size(); ++i) {
292         String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
293         if (!mimeType.isEmpty())
294             supportedImageMIMETypesForEncoding->add(mimeType);
295     }
296 #elif PLATFORM(GTK)
297     supportedImageMIMETypesForEncoding->add("image/png");
298     supportedImageMIMETypesForEncoding->add("image/jpeg");
299     supportedImageMIMETypesForEncoding->add("image/tiff");
300     supportedImageMIMETypesForEncoding->add("image/bmp");
301     supportedImageMIMETypesForEncoding->add("image/ico");
302 #elif USE(CAIRO)
303     supportedImageMIMETypesForEncoding->add("image/png");
304 #elif PLATFORM(BLACKBERRY)
305     supportedImageMIMETypesForEncoding->add("image/png");
306     supportedImageMIMETypesForEncoding->add("image/jpeg");
307 #endif
308 }
309
310 static void initializeSupportedJavaScriptMIMETypes()
311 {
312     /*
313         Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript.
314         Mozilla 1.8 accepts application/javascript, application/ecmascript, and application/x-javascript, but WinIE 7 doesn't.
315         WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and text/livescript, but Mozilla 1.8 doesn't.
316         Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't.
317         Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a whitespace-only string.
318         We want to accept all the values that either of these browsers accept, but not other values.
319      */
320     static const char* types[] = {
321         "text/javascript",
322         "text/ecmascript",
323         "application/javascript",
324         "application/ecmascript",
325         "application/x-javascript",
326         "text/javascript1.1",
327         "text/javascript1.2",
328         "text/javascript1.3",
329         "text/jscript",
330         "text/livescript",
331     };
332     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
333       supportedJavaScriptMIMETypes->add(types[i]);
334 }
335
336 static void initializeSupportedNonImageMimeTypes()
337 {
338     static const char* types[] = {
339         "text/html",
340         "text/xml",
341         "text/xsl",
342         "text/plain",
343         "text/",
344         "application/xml",
345         "application/xhtml+xml",
346         "application/vnd.wap.xhtml+xml",
347         "application/rss+xml",
348         "application/atom+xml",
349         "application/json",
350 #if ENABLE(SVG)
351         "image/svg+xml",
352 #endif
353 #if ENABLE(FTPDIR)
354         "application/x-ftp-directory",
355 #endif
356         "multipart/x-mixed-replace"
357         // Note: ADDING a new type here will probably render it as HTML. This can
358         // result in cross-site scripting.
359     };
360     COMPILE_ASSERT(sizeof(types) / sizeof(types[0]) <= 16,
361                    nonimage_mime_types_must_be_less_than_or_equal_to_16);
362
363     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
364         supportedNonImageMIMETypes->add(types[i]);
365
366 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
367     ArchiveFactory::registerKnownArchiveMIMETypes();
368 #endif
369 }
370
371 static MediaMIMETypeMap& mediaMIMETypeMap()
372 {
373     DEFINE_STATIC_LOCAL(MediaMIMETypeMap, mediaMIMETypeForExtensionMap, ());
374
375     if (!mediaMIMETypeForExtensionMap.isEmpty())
376         return mediaMIMETypeForExtensionMap;
377
378     const unsigned numPairs = sizeof(commonMediaTypes) / sizeof(commonMediaTypes[0]);
379     for (unsigned ndx = 0; ndx < numPairs; ++ndx) {
380
381         if (mediaMIMETypeForExtensionMap.contains(commonMediaTypes[ndx].extension))
382             mediaMIMETypeForExtensionMap.get(commonMediaTypes[ndx].extension)->append(commonMediaTypes[ndx].type);
383         else {
384             Vector<String>* synonyms = new Vector<String>;
385
386             // If there is a system specific type for this extension, add it as the first type so
387             // getMediaMIMETypeForExtension will always return it.
388             String systemType = MIMETypeRegistry::getMIMETypeForExtension(commonMediaTypes[ndx].extension);
389             if (!systemType.isEmpty() && commonMediaTypes[ndx].type != systemType)
390                 synonyms->append(systemType);
391             synonyms->append(commonMediaTypes[ndx].type);
392             mediaMIMETypeForExtensionMap.add(commonMediaTypes[ndx].extension, synonyms);
393         }
394     }
395
396     return mediaMIMETypeForExtensionMap;
397 }
398
399 String MIMETypeRegistry::getMediaMIMETypeForExtension(const String& ext)
400 {
401     // Look in the system-specific registry first.
402     String type = getMIMETypeForExtension(ext);
403     if (!type.isEmpty())
404         return type;
405
406     Vector<String>* typeList = mediaMIMETypeMap().get(ext);
407     if (typeList)
408         return (*typeList)[0];
409     
410     return String();
411 }
412     
413 Vector<String> MIMETypeRegistry::getMediaMIMETypesForExtension(const String& ext)
414 {
415     Vector<String>* typeList = mediaMIMETypeMap().get(ext);
416     if (typeList)
417         return *typeList;
418
419     // Only need to look in the system-specific registry if mediaMIMETypeMap() doesn't contain
420     // the extension at all, because it always contains the system-specific type if the
421     // extension is in the static mapping table.
422     String type = getMIMETypeForExtension(ext);
423     if (!type.isEmpty()) {
424         Vector<String> typeList;
425         typeList.append(type);
426         return typeList;
427     }
428     
429     return Vector<String>();
430 }
431
432 static void initializeSupportedMediaMIMETypes()
433 {
434     supportedMediaMIMETypes = new HashSet<String>;
435 #if ENABLE(VIDEO)
436     MediaPlayer::getSupportedTypes(*supportedMediaMIMETypes);
437 #endif
438 }
439
440 static void initializeUnsupportedTextMIMETypes()
441 {
442     static const char* types[] = {
443         "text/calendar",
444         "text/x-calendar",
445         "text/x-vcalendar",
446         "text/vcalendar",
447         "text/vcard",
448         "text/x-vcard",
449         "text/directory",
450         "text/ldif",
451         "text/qif",
452         "text/x-qif",
453         "text/x-csv",
454         "text/x-vcf",
455         "text/rtf",
456     };
457     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
458       unsupportedTextMIMETypes->add(types[i]);
459 }
460
461 static void initializeMIMETypeRegistry()
462 {
463     supportedJavaScriptMIMETypes = new HashSet<String>;
464     initializeSupportedJavaScriptMIMETypes();
465
466     supportedNonImageMIMETypes = new HashSet<String>(*supportedJavaScriptMIMETypes);
467     initializeSupportedNonImageMimeTypes();
468
469     supportedImageResourceMIMETypes = new HashSet<String>;
470     supportedImageMIMETypes = new HashSet<String>;
471     initializeSupportedImageMIMETypes();
472
473     unsupportedTextMIMETypes = new HashSet<String>;
474     initializeUnsupportedTextMIMETypes();
475 }
476
477 static String findMimeType(const TypeExtensionPair* pairs, unsigned numPairs, const String& extension)
478 {
479     if (!extension.isEmpty()) {
480       for (unsigned i = 0; i < numPairs; ++i, ++pairs) {
481           if (equalIgnoringCase(extension, pairs->extension))
482               return String(pairs->type);
483       }
484     }
485     return String();
486 }
487
488 String MIMETypeRegistry::getWellKnownMIMETypeForExtension(const String& extension)
489 {
490     // This method must be thread safe and should not consult the OS/registry.
491     String found = findMimeType(wellKnownMimeTypes, sizeof(wellKnownMimeTypes) / sizeof(wellKnownMimeTypes[0]), extension);
492     if (!found.isEmpty())
493         return found;
494     return findMimeType(commonMediaTypes, sizeof(commonMediaTypes) / sizeof(commonMediaTypes[0]), extension);
495 }
496
497 String MIMETypeRegistry::getMIMETypeForPath(const String& path)
498 {
499     size_t pos = path.reverseFind('.');
500     if (pos != notFound) {
501         String extension = path.substring(pos + 1);
502         String result = getMIMETypeForExtension(extension);
503         if (result.length())
504             return result;
505     }
506     return "application/octet-stream";
507 }
508
509 bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
510 {
511     if (mimeType.isEmpty())
512         return false;
513     if (!supportedImageMIMETypes)
514         initializeMIMETypeRegistry();
515     return supportedImageMIMETypes->contains(mimeType);
516 }
517
518 bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
519 {
520     if (mimeType.isEmpty())
521         return false;
522     if (!supportedImageResourceMIMETypes)
523         initializeMIMETypeRegistry();
524     return supportedImageResourceMIMETypes->contains(mimeType);
525 }
526
527 bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
528 {
529     ASSERT(isMainThread());
530
531     if (mimeType.isEmpty())
532         return false;
533     if (!supportedImageMIMETypesForEncoding)
534         initializeSupportedImageMIMETypesForEncoding();
535     return supportedImageMIMETypesForEncoding->contains(mimeType);
536 }
537
538 bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
539 {
540     if (mimeType.isEmpty())
541         return false;
542     if (!supportedJavaScriptMIMETypes)
543         initializeMIMETypeRegistry();
544     return supportedJavaScriptMIMETypes->contains(mimeType);
545 }
546
547 bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
548 {
549     if (mimeType.isEmpty())
550         return false;
551     if (!supportedNonImageMIMETypes)
552         initializeMIMETypeRegistry();
553     return supportedNonImageMIMETypes->contains(mimeType);
554 }
555
556 bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
557 {
558     if (mimeType.isEmpty())
559         return false;
560     if (!supportedMediaMIMETypes)
561         initializeSupportedMediaMIMETypes();
562     return supportedMediaMIMETypes->contains(mimeType);
563 }
564
565 bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
566 {
567     if (mimeType.isEmpty())
568         return false;
569     if (!unsupportedTextMIMETypes)
570         initializeMIMETypeRegistry();
571     return unsupportedTextMIMETypes->contains(mimeType);
572 }
573
574 bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
575 {
576     // Since this set is very limited and is likely to remain so we won't bother with the overhead
577     // of using a hash set.
578     // Any of the MIME types below may be followed by any number of specific versions of the JVM,
579     // which is why we use startsWith()
580     return mimeType.startsWith("application/x-java-applet", false)
581         || mimeType.startsWith("application/x-java-bean", false)
582         || mimeType.startsWith("application/x-java-vm", false);
583 }
584
585 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypes()
586 {
587     if (!supportedImageMIMETypes)
588         initializeMIMETypeRegistry();
589     return *supportedImageMIMETypes;
590 }
591
592 HashSet<String>& MIMETypeRegistry::getSupportedImageResourceMIMETypes()
593 {
594     if (!supportedImageResourceMIMETypes)
595         initializeMIMETypeRegistry();
596     return *supportedImageResourceMIMETypes;
597 }
598
599 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypesForEncoding()
600 {
601     if (!supportedImageMIMETypesForEncoding)
602         initializeSupportedImageMIMETypesForEncoding();
603     return *supportedImageMIMETypesForEncoding;
604 }
605
606 HashSet<String>& MIMETypeRegistry::getSupportedNonImageMIMETypes()
607 {
608     if (!supportedNonImageMIMETypes)
609         initializeMIMETypeRegistry();
610     return *supportedNonImageMIMETypes;
611 }
612
613 HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes()
614 {
615     if (!supportedMediaMIMETypes)
616         initializeSupportedMediaMIMETypes();
617     return *supportedMediaMIMETypes;
618 }
619
620 HashSet<String>& MIMETypeRegistry::getUnsupportedTextMIMETypes()
621 {
622     if (!unsupportedTextMIMETypes)
623         initializeMIMETypeRegistry();
624     return *unsupportedTextMIMETypes;
625 }
626
627 const String& defaultMIMEType()
628 {
629     DEFINE_STATIC_LOCAL(const String, defaultMIMEType, ("application/octet-stream"));
630     return defaultMIMEType;
631 }
632
633 } // namespace WebCore