• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/StdLibExtras.h>
34 #include <wtf/text/StringHash.h>
35 
36 #if USE(CG)
37 #include "ImageSourceCG.h"
38 #include <ApplicationServices/ApplicationServices.h>
39 #include <wtf/RetainPtr.h>
40 #endif
41 #if PLATFORM(QT)
42 #include <qimagereader.h>
43 #include <qimagewriter.h>
44 #endif
45 
46 #if ENABLE(WEB_ARCHIVE)
47 #include "ArchiveFactory.h"
48 #endif
49 
50 namespace WebCore {
51 
52 static HashSet<String>* supportedImageResourceMIMETypes;
53 static HashSet<String>* supportedImageMIMETypes;
54 static HashSet<String>* supportedImageMIMETypesForEncoding;
55 static HashSet<String>* supportedJavaScriptMIMETypes;
56 static HashSet<String>* supportedNonImageMIMETypes;
57 static HashSet<String>* supportedMediaMIMETypes;
58 static HashSet<String>* unsupportedTextMIMETypes;
59 
60 typedef HashMap<String, Vector<String>*, CaseFoldingHash> MediaMIMETypeMap;
61 
initializeSupportedImageMIMETypes()62 static void initializeSupportedImageMIMETypes()
63 {
64 #if USE(CG)
65     RetainPtr<CFArrayRef> supportedTypes(AdoptCF, CGImageSourceCopyTypeIdentifiers());
66     CFIndex count = CFArrayGetCount(supportedTypes.get());
67     for (CFIndex i = 0; i < count; i++) {
68         RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
69         String mimeType = MIMETypeForImageSourceType(supportedType.get());
70         if (!mimeType.isEmpty()) {
71             supportedImageMIMETypes->add(mimeType);
72             supportedImageResourceMIMETypes->add(mimeType);
73         }
74     }
75 
76     // On Tiger and Leopard, com.microsoft.bmp doesn't have a MIME type in the registry.
77     supportedImageMIMETypes->add("image/bmp");
78     supportedImageResourceMIMETypes->add("image/bmp");
79 
80     // Favicons don't have a MIME type in the registry either.
81     supportedImageMIMETypes->add("image/vnd.microsoft.icon");
82     supportedImageMIMETypes->add("image/x-icon");
83     supportedImageResourceMIMETypes->add("image/vnd.microsoft.icon");
84     supportedImageResourceMIMETypes->add("image/x-icon");
85 
86     //  We only get one MIME type per UTI, hence our need to add these manually
87     supportedImageMIMETypes->add("image/pjpeg");
88     supportedImageResourceMIMETypes->add("image/pjpeg");
89 
90     //  We don't want to try to treat all binary data as an image
91     supportedImageMIMETypes->remove("application/octet-stream");
92     supportedImageResourceMIMETypes->remove("application/octet-stream");
93 
94     //  Don't treat pdf/postscript as images directly
95     supportedImageMIMETypes->remove("application/pdf");
96     supportedImageMIMETypes->remove("application/postscript");
97 
98 #elif PLATFORM(QT)
99     QList<QByteArray> formats = QImageReader::supportedImageFormats();
100     for (size_t i = 0; i < static_cast<size_t>(formats.size()); ++i) {
101 #if ENABLE(SVG)
102         /*
103          * Qt has support for SVG, but we want to use KSVG2
104          */
105         if (formats.at(i).toLower().startsWith("svg"))
106             continue;
107 #endif
108         String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
109         if (!mimeType.isEmpty()) {
110             supportedImageMIMETypes->add(mimeType);
111             supportedImageResourceMIMETypes->add(mimeType);
112         }
113     }
114 #elif PLATFORM(ANDROID)
115     static const char* types[] = {
116         "image/jpeg",
117         "image/webp",
118         "image/png",
119         "image/gif",
120         "image/bmp",
121         "image/x-icon",    // ico
122         "image/ico",
123         "image/x-xbitmap"  // xbm
124     };
125     for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
126         supportedImageMIMETypes->add(types[i]);
127         supportedImageResourceMIMETypes->add(types[i]);
128     }
129     // Checked Safari impl, it seems that the HTTP stack returns
130     // multiple responses, the initial response, and then one for
131     // multipart segment. Each response is sent to the same ResourceLoader
132     // so for us to support this we would need to do the same.
133     supportedNonImageMIMETypes->remove("multipart/x-mixed-replace");
134 #if !ENABLE(XSLT)
135     supportedNonImageMIMETypes->remove("text/xsl");
136 #endif
137 #else
138     // assume that all implementations at least support the following standard
139     // image types:
140     static const char* types[] = {
141         "image/jpeg",
142         "image/png",
143         "image/gif",
144         "image/bmp",
145         "image/vnd.microsoft.icon",    // ico
146         "image/x-icon",    // ico
147         "image/x-xbitmap"  // xbm
148     };
149     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
150         supportedImageMIMETypes->add(types[i]);
151         supportedImageResourceMIMETypes->add(types[i]);
152     }
153 #endif
154 }
155 
initializeSupportedImageMIMETypesForEncoding()156 static void initializeSupportedImageMIMETypesForEncoding()
157 {
158     supportedImageMIMETypesForEncoding = new HashSet<String>;
159 
160 #if USE(CG)
161 #if PLATFORM(MAC)
162     RetainPtr<CFArrayRef> supportedTypes(AdoptCF, CGImageDestinationCopyTypeIdentifiers());
163     CFIndex count = CFArrayGetCount(supportedTypes.get());
164     for (CFIndex i = 0; i < count; i++) {
165         RetainPtr<CFStringRef> supportedType(AdoptCF, reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(supportedTypes.get(), i)));
166         String mimeType = MIMETypeForImageSourceType(supportedType.get());
167         if (!mimeType.isEmpty())
168             supportedImageMIMETypesForEncoding->add(mimeType);
169     }
170 #else
171     // FIXME: Add Windows support for all the supported UTI's when a way to convert from MIMEType to UTI reliably is found.
172     // For now, only support PNG, JPEG and GIF.  See <rdar://problem/6095286>.
173     supportedImageMIMETypesForEncoding->add("image/png");
174     supportedImageMIMETypesForEncoding->add("image/jpeg");
175     supportedImageMIMETypesForEncoding->add("image/gif");
176 #endif
177 #elif PLATFORM(QT)
178     QList<QByteArray> formats = QImageWriter::supportedImageFormats();
179     for (int i = 0; i < formats.size(); ++i) {
180         String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
181         if (!mimeType.isEmpty())
182             supportedImageMIMETypesForEncoding->add(mimeType);
183     }
184 #elif PLATFORM(GTK)
185     supportedImageMIMETypesForEncoding->add("image/png");
186     supportedImageMIMETypesForEncoding->add("image/jpeg");
187     supportedImageMIMETypesForEncoding->add("image/tiff");
188     supportedImageMIMETypesForEncoding->add("image/bmp");
189     supportedImageMIMETypesForEncoding->add("image/ico");
190 #elif USE(CAIRO)
191     supportedImageMIMETypesForEncoding->add("image/png");
192 #endif
193 }
194 
initializeSupportedJavaScriptMIMETypes()195 static void initializeSupportedJavaScriptMIMETypes()
196 {
197     /*
198         Mozilla 1.8 and WinIE 7 both accept text/javascript and text/ecmascript.
199         Mozilla 1.8 accepts application/javascript, application/ecmascript, and application/x-javascript, but WinIE 7 doesn't.
200         WinIE 7 accepts text/javascript1.1 - text/javascript1.3, text/jscript, and text/livescript, but Mozilla 1.8 doesn't.
201         Mozilla 1.8 allows leading and trailing whitespace, but WinIE 7 doesn't.
202         Mozilla 1.8 and WinIE 7 both accept the empty string, but neither accept a whitespace-only string.
203         We want to accept all the values that either of these browsers accept, but not other values.
204      */
205     static const char* types[] = {
206         "text/javascript",
207         "text/ecmascript",
208         "application/javascript",
209         "application/ecmascript",
210         "application/x-javascript",
211         "text/javascript1.1",
212         "text/javascript1.2",
213         "text/javascript1.3",
214         "text/jscript",
215         "text/livescript",
216     };
217     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
218       supportedJavaScriptMIMETypes->add(types[i]);
219 }
220 
initializeSupportedNonImageMimeTypes()221 static void initializeSupportedNonImageMimeTypes()
222 {
223     static const char* types[] = {
224 #if ENABLE(WML)
225         "text/vnd.wap.wml",
226         "application/vnd.wap.wmlc",
227 #endif
228         "text/html",
229         "text/xml",
230         "text/xsl",
231         "text/plain",
232         "text/",
233         "application/xml",
234         "application/xhtml+xml",
235         "application/vnd.wap.xhtml+xml",
236         "application/rss+xml",
237         "application/atom+xml",
238         "application/json",
239 #if ENABLE(SVG)
240         "image/svg+xml",
241 #endif
242 #if ENABLE(FTPDIR)
243         "application/x-ftp-directory",
244 #endif
245         "multipart/x-mixed-replace"
246         // Note: ADDING a new type here will probably render it as HTML. This can
247         // result in cross-site scripting.
248     };
249     COMPILE_ASSERT(sizeof(types) / sizeof(types[0]) <= 16,
250                    nonimage_mime_types_must_be_less_than_or_equal_to_16);
251 
252     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
253         supportedNonImageMIMETypes->add(types[i]);
254 
255 #if ENABLE(WEB_ARCHIVE)
256     ArchiveFactory::registerKnownArchiveMIMETypes();
257 #endif
258 }
259 
mediaMIMETypeMap()260 static MediaMIMETypeMap& mediaMIMETypeMap()
261 {
262     struct TypeExtensionPair {
263         const char* type;
264         const char* extension;
265     };
266 
267     // A table of common media MIME types and file extenstions used when a platform's
268     // specific MIME type lookup doesn't have a match for a media file extension.
269     static const TypeExtensionPair pairs[] = {
270 
271         // Ogg
272         { "application/ogg", "ogx" },
273         { "audio/ogg", "ogg" },
274         { "audio/ogg", "oga" },
275         { "video/ogg", "ogv" },
276 
277         // Annodex
278         { "application/annodex", "anx" },
279         { "audio/annodex", "axa" },
280         { "video/annodex", "axv" },
281         { "audio/speex", "spx" },
282 
283         // WebM
284         { "video/webm", "webm" },
285         { "audio/webm", "webm" },
286 
287         // MPEG
288         { "audio/mpeg", "m1a" },
289         { "audio/mpeg", "m2a" },
290         { "audio/mpeg", "m1s" },
291         { "audio/mpeg", "mpa" },
292         { "video/mpeg", "mpg" },
293         { "video/mpeg", "m15" },
294         { "video/mpeg", "m1s" },
295         { "video/mpeg", "m1v" },
296         { "video/mpeg", "m75" },
297         { "video/mpeg", "mpa" },
298         { "video/mpeg", "mpeg" },
299         { "video/mpeg", "mpm" },
300         { "video/mpeg", "mpv" },
301 
302         // MPEG playlist
303         { "application/vnd.apple.mpegurl", "m3u8" },
304         { "application/mpegurl", "m3u8" },
305         { "application/x-mpegurl", "m3u8" },
306         { "audio/mpegurl", "m3url" },
307         { "audio/x-mpegurl", "m3url" },
308         { "audio/mpegurl", "m3u" },
309         { "audio/x-mpegurl", "m3u" },
310 
311         // MPEG-4
312         { "video/x-m4v", "m4v" },
313         { "audio/x-m4a", "m4a" },
314         { "audio/x-m4b", "m4b" },
315         { "audio/x-m4p", "m4p" },
316         { "audio/mp4", "m4a" },
317 
318         // MP3
319         { "audio/mp3", "mp3" },
320         { "audio/x-mp3", "mp3" },
321         { "audio/x-mpeg", "mp3" },
322 
323         // MPEG-2
324         { "video/x-mpeg2", "mp2" },
325         { "video/mpeg2", "vob" },
326         { "video/mpeg2", "mod" },
327         { "video/m2ts", "m2ts" },
328         { "video/x-m2ts", "m2t" },
329         { "video/x-m2ts", "ts" },
330 
331         // 3GP/3GP2
332         { "audio/3gpp", "3gpp" },
333         { "audio/3gpp2", "3g2" },
334         { "application/x-mpeg", "amc" },
335 
336         // AAC
337         { "audio/aac", "aac" },
338         { "audio/aac", "adts" },
339         { "audio/x-aac", "m4r" },
340 
341         // CoreAudio File
342         { "audio/x-caf", "caf" },
343         { "audio/x-gsm", "gsm" },
344 
345         // ADPCM
346         { "audio/x-wav", "wav" }
347     };
348 
349     DEFINE_STATIC_LOCAL(MediaMIMETypeMap, mediaMIMETypeForExtensionMap, ());
350 
351     if (!mediaMIMETypeForExtensionMap.isEmpty())
352         return mediaMIMETypeForExtensionMap;
353 
354     const unsigned numPairs = sizeof(pairs) / sizeof(pairs[0]);
355     for (unsigned ndx = 0; ndx < numPairs; ++ndx) {
356 
357         if (mediaMIMETypeForExtensionMap.contains(pairs[ndx].extension))
358             mediaMIMETypeForExtensionMap.get(pairs[ndx].extension)->append(pairs[ndx].type);
359         else {
360             Vector<String>* synonyms = new Vector<String>;
361 
362             // If there is a system specific type for this extension, add it as the first type so
363             // getMediaMIMETypeForExtension will always return it.
364             String systemType = MIMETypeRegistry::getMIMETypeForExtension(pairs[ndx].extension);
365             if (!systemType.isEmpty() && pairs[ndx].type != systemType)
366                 synonyms->append(systemType);
367             synonyms->append(pairs[ndx].type);
368             mediaMIMETypeForExtensionMap.add(pairs[ndx].extension, synonyms);
369         }
370     }
371 
372     return mediaMIMETypeForExtensionMap;
373 }
374 
375 #if ENABLE(FILE_SYSTEM) && ENABLE(WORKERS)
getMIMETypeForExtension(const String & extension)376 String MIMETypeRegistry::getMIMETypeForExtension(const String& extension)
377 {
378     return getMIMETypeForExtensionThreadSafe(extension);
379 }
380 #endif
381 
getMediaMIMETypeForExtension(const String & ext)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 
getMediaMIMETypesForExtension(const String & ext)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 
initializeSupportedMediaMIMETypes()415 static void initializeSupportedMediaMIMETypes()
416 {
417     supportedMediaMIMETypes = new HashSet<String>;
418 #if ENABLE(VIDEO)
419     MediaPlayer::getSupportedTypes(*supportedMediaMIMETypes);
420 #endif
421 }
422 
initializeUnsupportedTextMIMETypes()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         "text/rtf",
439     };
440     for (size_t i = 0; i < WTF_ARRAY_LENGTH(types); ++i)
441       unsupportedTextMIMETypes->add(types[i]);
442 }
443 
initializeMIMETypeRegistry()444 static void initializeMIMETypeRegistry()
445 {
446     supportedJavaScriptMIMETypes = new HashSet<String>;
447     initializeSupportedJavaScriptMIMETypes();
448 
449     supportedNonImageMIMETypes = new HashSet<String>(*supportedJavaScriptMIMETypes);
450     initializeSupportedNonImageMimeTypes();
451 
452     supportedImageResourceMIMETypes = new HashSet<String>;
453     supportedImageMIMETypes = new HashSet<String>;
454     initializeSupportedImageMIMETypes();
455 
456     unsupportedTextMIMETypes = new HashSet<String>;
457     initializeUnsupportedTextMIMETypes();
458 }
459 
getMIMETypeForPath(const String & path)460 String MIMETypeRegistry::getMIMETypeForPath(const String& path)
461 {
462     size_t pos = path.reverseFind('.');
463     if (pos != notFound) {
464         String extension = path.substring(pos + 1);
465         String result = getMIMETypeForExtension(extension);
466         if (result.length())
467             return result;
468     }
469     return "application/octet-stream";
470 }
471 
isSupportedImageMIMEType(const String & mimeType)472 bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
473 {
474     if (mimeType.isEmpty())
475         return false;
476     if (!supportedImageMIMETypes)
477         initializeMIMETypeRegistry();
478     return supportedImageMIMETypes->contains(mimeType);
479 }
480 
isSupportedImageResourceMIMEType(const String & mimeType)481 bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
482 {
483     if (mimeType.isEmpty())
484         return false;
485     if (!supportedImageResourceMIMETypes)
486         initializeMIMETypeRegistry();
487     return supportedImageResourceMIMETypes->contains(mimeType);
488 }
489 
isSupportedImageMIMETypeForEncoding(const String & mimeType)490 bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
491 {
492     ASSERT(isMainThread());
493 
494     if (mimeType.isEmpty())
495         return false;
496     if (!supportedImageMIMETypesForEncoding)
497         initializeSupportedImageMIMETypesForEncoding();
498     return supportedImageMIMETypesForEncoding->contains(mimeType);
499 }
500 
isSupportedJavaScriptMIMEType(const String & mimeType)501 bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
502 {
503     if (mimeType.isEmpty())
504         return false;
505     if (!supportedJavaScriptMIMETypes)
506         initializeMIMETypeRegistry();
507     return supportedJavaScriptMIMETypes->contains(mimeType);
508 }
509 
isSupportedNonImageMIMEType(const String & mimeType)510 bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
511 {
512     if (mimeType.isEmpty())
513         return false;
514     if (!supportedNonImageMIMETypes)
515         initializeMIMETypeRegistry();
516     return supportedNonImageMIMETypes->contains(mimeType);
517 }
518 
isSupportedMediaMIMEType(const String & mimeType)519 bool MIMETypeRegistry::isSupportedMediaMIMEType(const String& mimeType)
520 {
521     if (mimeType.isEmpty())
522         return false;
523     if (!supportedMediaMIMETypes)
524         initializeSupportedMediaMIMETypes();
525     return supportedMediaMIMETypes->contains(mimeType);
526 }
527 
isUnsupportedTextMIMEType(const String & mimeType)528 bool MIMETypeRegistry::isUnsupportedTextMIMEType(const String& mimeType)
529 {
530     if (mimeType.isEmpty())
531         return false;
532     if (!unsupportedTextMIMETypes)
533         initializeMIMETypeRegistry();
534     return unsupportedTextMIMETypes->contains(mimeType);
535 }
536 
isJavaAppletMIMEType(const String & mimeType)537 bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
538 {
539     // Since this set is very limited and is likely to remain so we won't bother with the overhead
540     // of using a hash set.
541     // Any of the MIME types below may be followed by any number of specific versions of the JVM,
542     // which is why we use startsWith()
543     return mimeType.startsWith("application/x-java-applet", false)
544         || mimeType.startsWith("application/x-java-bean", false)
545         || mimeType.startsWith("application/x-java-vm", false);
546 }
547 
getSupportedImageMIMETypes()548 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypes()
549 {
550     if (!supportedImageMIMETypes)
551         initializeMIMETypeRegistry();
552     return *supportedImageMIMETypes;
553 }
554 
getSupportedImageResourceMIMETypes()555 HashSet<String>& MIMETypeRegistry::getSupportedImageResourceMIMETypes()
556 {
557     if (!supportedImageResourceMIMETypes)
558         initializeMIMETypeRegistry();
559     return *supportedImageResourceMIMETypes;
560 }
561 
getSupportedImageMIMETypesForEncoding()562 HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypesForEncoding()
563 {
564     if (!supportedImageMIMETypesForEncoding)
565         initializeSupportedImageMIMETypesForEncoding();
566     return *supportedImageMIMETypesForEncoding;
567 }
568 
getSupportedNonImageMIMETypes()569 HashSet<String>& MIMETypeRegistry::getSupportedNonImageMIMETypes()
570 {
571     if (!supportedNonImageMIMETypes)
572         initializeMIMETypeRegistry();
573     return *supportedNonImageMIMETypes;
574 }
575 
getSupportedMediaMIMETypes()576 HashSet<String>& MIMETypeRegistry::getSupportedMediaMIMETypes()
577 {
578     if (!supportedMediaMIMETypes)
579         initializeSupportedMediaMIMETypes();
580     return *supportedMediaMIMETypes;
581 }
582 
getUnsupportedTextMIMETypes()583 HashSet<String>& MIMETypeRegistry::getUnsupportedTextMIMETypes()
584 {
585     if (!unsupportedTextMIMETypes)
586         initializeMIMETypeRegistry();
587     return *unsupportedTextMIMETypes;
588 }
589 
defaultMIMEType()590 const String& defaultMIMEType()
591 {
592     DEFINE_STATIC_LOCAL(const String, defaultMIMEType, ("application/octet-stream"));
593     return defaultMIMEType;
594 }
595 
596 } // namespace WebCore
597