2-3% of main thread time under UTTypeCreatePreferredIdentifierForTag on wunderground map
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Aug 2017 20:49:47 +0000 (20:49 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Aug 2017 20:49:47 +0000 (20:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175618

Reviewed by Simon Fraser.

No new tests, just a perf win.

UTTypeCreatePreferredIdentifierForTag is fairly expensive, and is called
under every toDataURL, which the Wunderground wundermap does a /lot/.

Keep a 16-item LRU cache of MIMEType->UTI mappings.

Also, make other callers of UTTypeCreatePreferredIdentifierForTag use
the UTIUtilities version so they can share in the caching.

Also, as a drive-by, add and make other callers use mimeTypeFromUTI too,
and make the UTIUtilities operate on Strings for a slightly more WebCore-y feel.

* editing/ios/EditorIOS.mm:
(WebCore::Editor::WebContentReader::readImage):
* platform/MIMETypeRegistry.cpp:
(WebCore::initializeSupportedImageMIMETypes):
(WebCore::initializeSupportedImageMIMETypesForEncoding):
* platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
(WebCore::createFileTypesSet):
* platform/graphics/cg/ImageSourceCGMac.mm:
(WebCore::MIMETypeForImageSourceType):
Adopt newly-added MIMETypeFromUTI().

* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::utiFromImageBufferMIMEType):
(WebCore::ImageBuffer::toCFData const):
(WebCore::cfData):
(WebCore::utiFromMIMEType): Deleted.
Adopt UTIFromMIMEType, and rename the local helper that does something
different (a small static map) on iOS and Windows to not have an overlapping name.

* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::resourceMIMEType):
(WebCore::utiTypeFromCocoaType):
Adopt UTIFromMIMEType().

* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::writeObjectRepresentations):
* platform/mac/PasteboardMac.mm:
(WebCore::cocoaTypeFromHTMLClipboardType):
Adopt isDeclaredUTI and UTIFromMIMEType().

* platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
(WebCore::WebCoreAVFResourceLoader::responseReceived):
* platform/network/ios/WebCoreURLResponseIOS.mm:
(WebCore::adjustMIMETypeIfNecessary):
* platform/network/mac/WebCoreURLResponse.mm:
(WebCore::adjustMIMETypeIfNecessary):
* rendering/RenderThemeIOS.mm:
(WebCore::iconForAttachment):
* rendering/RenderThemeMac.mm:
(WebCore::iconForAttachment):
Deal with the fact that UTI utilities deal in Strings now.

* platform/network/mac/UTIUtilities.h:
* platform/network/mac/UTIUtilities.mm:
(WebCore::MIMETypeFromUTI):
Added. This doesn't crawl up the UTI tree if the first conversion fails,
which is what most of the existing code does. It's possible we want to
use MIMETypeFromUTITree's logic everywhere, but I didn't want to change
that in this patch.

(WebCore::MIMETypeFromUTITree):
(WebCore::isDeclaredUTI):
Take and return strings.

(WebCore::UTIFromMIMETypeCachePolicy::createValueForKey):
(WebCore::UTIFromMIMEType):
Add the aforementioned cache.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220808 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/WebCore/ChangeLog
Source/WebCore/editing/ios/EditorIOS.mm
Source/WebCore/platform/Pasteboard.h
Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm
Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
Source/WebCore/platform/graphics/cg/ImageSourceCGMac.mm
Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
Source/WebCore/platform/ios/PasteboardIOS.mm
Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
Source/WebCore/platform/mac/PasteboardMac.mm
Source/WebCore/platform/network/ios/WebCoreURLResponseIOS.mm
Source/WebCore/platform/network/mac/UTIUtilities.h
Source/WebCore/platform/network/mac/UTIUtilities.mm
Source/WebCore/platform/network/mac/WebCoreURLResponse.mm
Source/WebCore/rendering/RenderThemeIOS.mm
Source/WebCore/rendering/RenderThemeMac.mm

index f7821a2..97703f7 100644 (file)
@@ -1,3 +1,81 @@
+2017-08-16  Tim Horton  <timothy_horton@apple.com>
+
+        2-3% of main thread time under UTTypeCreatePreferredIdentifierForTag on wunderground map
+        https://bugs.webkit.org/show_bug.cgi?id=175618
+
+        Reviewed by Simon Fraser.
+
+        No new tests, just a perf win.
+
+        UTTypeCreatePreferredIdentifierForTag is fairly expensive, and is called
+        under every toDataURL, which the Wunderground wundermap does a /lot/.
+
+        Keep a 16-item LRU cache of MIMEType->UTI mappings.
+
+        Also, make other callers of UTTypeCreatePreferredIdentifierForTag use
+        the UTIUtilities version so they can share in the caching.
+
+        Also, as a drive-by, add and make other callers use mimeTypeFromUTI too,
+        and make the UTIUtilities operate on Strings for a slightly more WebCore-y feel.
+
+        * editing/ios/EditorIOS.mm:
+        (WebCore::Editor::WebContentReader::readImage):
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::initializeSupportedImageMIMETypes):
+        (WebCore::initializeSupportedImageMIMETypesForEncoding):
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
+        (WebCore::createFileTypesSet):
+        * platform/graphics/cg/ImageSourceCGMac.mm:
+        (WebCore::MIMETypeForImageSourceType):
+        Adopt newly-added MIMETypeFromUTI().
+
+        * platform/graphics/cg/ImageBufferCG.cpp:
+        (WebCore::utiFromImageBufferMIMEType):
+        (WebCore::ImageBuffer::toCFData const):
+        (WebCore::cfData):
+        (WebCore::utiFromMIMEType): Deleted.
+        Adopt UTIFromMIMEType, and rename the local helper that does something
+        different (a small static map) on iOS and Windows to not have an overlapping name.
+
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::Pasteboard::resourceMIMEType):
+        (WebCore::utiTypeFromCocoaType):
+        Adopt UTIFromMIMEType().
+
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::writeObjectRepresentations):
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::cocoaTypeFromHTMLClipboardType):
+        Adopt isDeclaredUTI and UTIFromMIMEType().
+
+        * platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
+        (WebCore::WebCoreAVFResourceLoader::responseReceived):
+        * platform/network/ios/WebCoreURLResponseIOS.mm:
+        (WebCore::adjustMIMETypeIfNecessary):
+        * platform/network/mac/WebCoreURLResponse.mm:
+        (WebCore::adjustMIMETypeIfNecessary):
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::iconForAttachment):
+        * rendering/RenderThemeMac.mm:
+        (WebCore::iconForAttachment):
+        Deal with the fact that UTI utilities deal in Strings now.
+
+        * platform/network/mac/UTIUtilities.h:
+        * platform/network/mac/UTIUtilities.mm:
+        (WebCore::MIMETypeFromUTI):
+        Added. This doesn't crawl up the UTI tree if the first conversion fails,
+        which is what most of the existing code does. It's possible we want to
+        use MIMETypeFromUTITree's logic everywhere, but I didn't want to change
+        that in this patch.
+
+        (WebCore::MIMETypeFromUTITree):
+        (WebCore::isDeclaredUTI):
+        Take and return strings.
+
+        (WebCore::UTIFromMIMETypeCachePolicy::createValueForKey):
+        (WebCore::UTIFromMIMEType):
+        Add the aforementioned cache.
+
 2017-08-16  Simon Fraser  <simon.fraser@apple.com>
 
         Make RenderLayer and RenderLayerBacking TextStream-loggable, and clean up compositing logging
index 6ee4f71..dc6e715 100644 (file)
@@ -58,6 +58,7 @@
 #import "StyleProperties.h"
 #import "Text.h"
 #import "TypingCommand.h"
+#import "UTIUtilities.h"
 #import "WAKAppKitStubs.h"
 #import "markup.h"
 #import <MobileCoreServices/MobileCoreServices.h>
@@ -332,9 +333,9 @@ bool Editor::WebContentReader::readImage(Ref<SharedBuffer>&& buffer, const Strin
     RetainPtr<CFStringRef> stringType = type.createCFString();
     RetainPtr<NSString> filenameExtension = adoptNS((NSString *)UTTypeCopyPreferredTagWithClass(stringType.get(), kUTTagClassFilenameExtension));
     NSString *relativeURLPart = [@"image" stringByAppendingString:filenameExtension.get()];
-    RetainPtr<NSString> mimeType = adoptNS((NSString *)UTTypeCopyPreferredTagWithClass(stringType.get(), kUTTagClassMIMEType));
+    String mimeType = MIMETypeFromUTI(type);
 
-    addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(WTFMove(buffer), URL::fakeURLWithRelativePart(relativeURLPart), mimeType.get(), emptyString(), emptyString())));
+    addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(WTFMove(buffer), URL::fakeURLWithRelativePart(relativeURLPart), mimeType, emptyString(), emptyString())));
     return fragment;
 }
 
index 01c7e0f..5e26bf2 100644 (file)
@@ -211,7 +211,7 @@ public:
     explicit Pasteboard(long changeCount);
 
     static NSArray *supportedWebContentPasteboardTypes();
-    static String resourceMIMEType(const NSString *mimeType);
+    static String resourceMIMEType(NSString *mimeType);
 #endif
 
 #if PLATFORM(COCOA)
index 58829a0..27c4922 100644 (file)
@@ -119,7 +119,7 @@ void WebCoreAVFResourceLoader::responseReceived(CachedResource& resource, const
     }
 
     if (AVAssetResourceLoadingContentInformationRequest* contentInfo = [m_avRequest.get() contentInformationRequest]) {
-        String uti = UTIFromMIMEType(response.mimeType().createCFString().get()).get();
+        String uti = UTIFromMIMEType(response.mimeType());
 
         [contentInfo setContentType:uti];
 
index 71eb83d..d24c10f 100644 (file)
@@ -47,6 +47,7 @@
 #include <wtf/text/WTFString.h>
 
 #if PLATFORM(COCOA)
+#include "UTIUtilities.h"
 #include "WebCoreSystemInterface.h"
 #endif
 
@@ -447,10 +448,11 @@ static inline CFStringRef jpegUTI()
     return kUTTypeJPEG;
 }
     
-static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
+static RetainPtr<CFStringRef> utiFromImageBufferMIMEType(const String& mimeType)
 {
+    // FIXME: Why doesn't iOS use the CoreServices version?
 #if PLATFORM(MAC)
-    return adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), 0));
+    return UTIFromMIMEType(mimeType).createCFString();
 #else
     ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe.
 
@@ -532,7 +534,7 @@ RetainPtr<CFDataRef> ImageBuffer::toCFData(const String& mimeType, std::optional
     if (context().isAcceleratedContext())
         flushContext();
 
-    auto uti = utiFromMIMEType(mimeType);
+    auto uti = utiFromImageBufferMIMEType(mimeType);
     ASSERT(uti);
 
     RetainPtr<CGImageRef> image;
@@ -574,7 +576,7 @@ static RetainPtr<CFDataRef> cfData(const ImageData& source, const String& mimeTy
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
-    auto uti = utiFromMIMEType(mimeType);
+    auto uti = utiFromImageBufferMIMEType(mimeType);
     ASSERT(uti);
 
     CGImageAlphaInfo dataAlphaInfo = kCGImageAlphaLast;
index a65fbb7..df297de 100644 (file)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "ImageSourceCG.h"
 
+#import "UTIUtilities.h"
 #import <wtf/RetainPtr.h>
 #import <wtf/text/WTFString.h>
 
@@ -37,7 +38,7 @@ namespace WebCore {
 
 String MIMETypeForImageSourceType(const String& uti)
 {
-    return adoptCF(UTTypeCopyPreferredTagWithClass(uti.createCFString().get(), kUTTagClassMIMEType)).get();
+    return MIMETypeFromUTI(uti);
 }
 
 String preferredExtensionForImageSourceType(const String& uti)
index ade36c8..b32c53e 100644 (file)
@@ -39,6 +39,7 @@
 #import "QTKitSPI.h"
 #import "SecurityOrigin.h"
 #import "URL.h"
+#import "UTIUtilities.h"
 #import "WebCoreSystemInterface.h"
 #import <objc/runtime.h>
 #import <wtf/BlockObjCExceptions.h>
@@ -1243,11 +1244,11 @@ static HashSet<String, ASCIICaseInsensitiveHash> createFileTypesSet(NSArray *fil
         auto uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
         if (!uti)
             continue;
-        auto mime = adoptCF(UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
-        if (shouldRejectMIMEType(mime.get()))
+        auto mime = MIMETypeFromUTI(uti.get());
+        if (shouldRejectMIMEType(mime))
             continue;
-        if (mime)
-            set.add(mime.get());
+        if (!mime.isEmpty())
+            set.add(mime);
 
         // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single
         // quotes, eg. 'MooV', so don't bother looking at those.
index 57ac447..04fb6d3 100644 (file)
@@ -48,6 +48,7 @@
 #import "SharedBuffer.h"
 #import "Text.h"
 #import "URL.h"
+#import "UTIUtilities.h"
 #import "WebNSAttributedStringExtras.h"
 #import "markup.h"
 #import <MobileCoreServices/MobileCoreServices.h>
@@ -142,9 +143,9 @@ void Pasteboard::write(const PasteboardWebContent& content)
     platformStrategies()->pasteboardStrategy()->writeToPasteboard(content, m_pasteboardName);
 }
 
-String Pasteboard::resourceMIMEType(const NSString *mimeType)
+String Pasteboard::resourceMIMEType(NSString *mimeType)
 {
-    return String(adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)mimeType, NULL)).get());
+    return UTIFromMIMEType(mimeType);
 }
 
 void Pasteboard::write(const PasteboardImage& pasteboardImage)
index c5ee5ba..1ed9229 100644 (file)
@@ -293,12 +293,12 @@ void PlatformPasteboard::writeObjectRepresentations(const PasteboardImage& paste
         [itemsToRegister addData:data[i]->createNSData().get() forType:types[i]];
 
     if (pasteboardImage.resourceData && !pasteboardImage.resourceMIMEType.isEmpty()) {
-        auto utiOrMIMEType = pasteboardImage.resourceMIMEType.createCFString();
-        if (!UTTypeIsDeclared(utiOrMIMEType.get()))
-            utiOrMIMEType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, utiOrMIMEType.get(), nil));
+        auto utiOrMIMEType = pasteboardImage.resourceMIMEType;
+        if (!isDeclaredUTI(utiOrMIMEType))
+            utiOrMIMEType = UTIFromMIMEType(utiOrMIMEType);
 
         auto imageData = pasteboardImage.resourceData->createNSData();
-        [itemsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType.get()];
+        [itemsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType];
         [itemsToRegister setEstimatedDisplayedSize:pasteboardImage.imageSize];
         [itemsToRegister setSuggestedName:pasteboardImage.suggestedName];
     }
index 18dfabc..5fa42e1 100644 (file)
@@ -47,6 +47,7 @@
 #import "RenderImage.h"
 #import "Text.h"
 #import "URL.h"
+#import "UTIUtilities.h"
 #import "WebCoreNSStringExtras.h"
 #import "WebCoreSystemInterface.h"
 #import "WebNSAttributedStringExtras.h"
@@ -482,8 +483,9 @@ static String cocoaTypeFromHTMLClipboardType(const String& type)
     if (lowercasedType == "text/rtf" || lowercasedType == "public.rtf" || lowercasedType == "com.apple.traditional-mac-plain-text")
         return String();
 
-    if (auto utiType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, lowercasedType.createCFString().get(), NULL))) {
-        if (auto pbType = adoptCF(UTTypeCopyPreferredTagWithClass(utiType.get(), kUTTagClassNSPboardType)))
+    auto utiType = UTIFromMIMEType(lowercasedType);
+    if (!utiType.isEmpty()) {
+        if (auto pbType = adoptCF(UTTypeCopyPreferredTagWithClass(utiType.createCFString().get(), kUTTagClassNSPboardType)))
             return pbType.get();
     }
 
index f6caa29..517875d 100644 (file)
@@ -57,7 +57,9 @@ void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse, bool isMainResourceL
                 RetainPtr<CFStringRef> extension = adoptCF(CFURLCopyPathExtension(url));
                 if (extension) {
                     RetainPtr<CFStringRef> uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), nullptr));
-                    quickLookMIMEType = mimeTypeFromUTITree(uti.get());
+                    String MIMEType = MIMETypeFromUTITree(uti.get());
+                    if (!MIMEType.isEmpty())
+                        quickLookMIMEType = MIMEType.createCFString();
                 }
             }
         }
index e15f69b..78b8756 100644 (file)
 #ifndef UTIUtilities_h
 #define UTIUtilities_h
 
+#import <wtf/Forward.h>
 #import <wtf/RetainPtr.h>
 
 namespace WebCore {
-RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti);
-RetainPtr<CFStringRef> UTIFromMIMEType(CFStringRef mime);
-bool isDeclaredUTI(CFStringRef UTI);
+String MIMETypeFromUTI(const String&);
+String MIMETypeFromUTITree(const String&);
+String UTIFromMIMEType(const String&);
+bool isDeclaredUTI(const String&);
 }
 
 #endif // UTIUtilities_h
index 3a42acf..8ac657a 100644 (file)
@@ -25,6 +25,9 @@
 
 #import "config.h"
 #import "UTIUtilities.h"
+#import <wtf/MainThread.h>
+#import <wtf/TinyLRUCache.h>
+#import <wtf/text/WTFString.h>
 
 #if PLATFORM(IOS)
 #import <MobileCoreServices/MobileCoreServices.h>
 
 namespace WebCore {
 
-RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti)
+String MIMETypeFromUTI(const String& uti)
 {
+    return adoptCF(UTTypeCopyPreferredTagWithClass(uti.createCFString().get(), kUTTagClassMIMEType)).get();
+}
+
+String MIMETypeFromUTITree(const String& uti)
+{
+    auto utiCF = uti.createCFString();
+
     // Check if this UTI has a MIME type.
-    RetainPtr<CFStringRef> mimeType = adoptCF(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
+    RetainPtr<CFStringRef> mimeType = adoptCF(UTTypeCopyPreferredTagWithClass(utiCF.get(), kUTTagClassMIMEType));
     if (mimeType)
         return mimeType.get();
 
     // If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find.
-    RetainPtr<CFDictionaryRef> decl = adoptCF(UTTypeCopyDeclaration(uti));
+    RetainPtr<CFDictionaryRef> decl = adoptCF(UTTypeCopyDeclaration(utiCF.get()));
     if (!decl)
-        return nil;
+        return String();
     CFTypeRef value = CFDictionaryGetValue(decl.get(), kUTTypeConformsToKey);
     if (!value)
-        return nil;
+        return String();
     CFTypeID typeID = CFGetTypeID(value);
 
     if (typeID == CFStringGetTypeID())
-        return mimeTypeFromUTITree((CFStringRef)value);
+        return MIMETypeFromUTITree((CFStringRef)value);
 
     if (typeID == CFArrayGetTypeID()) {
         CFArrayRef newTypes = (CFArrayRef)value;
         CFIndex count = CFArrayGetCount(newTypes);
         for (CFIndex i = 0; i < count; ++i) {
-        CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i);
-        if (CFGetTypeID(object) != CFStringGetTypeID())
-            continue;
+            CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i);
+            if (CFGetTypeID(object) != CFStringGetTypeID())
+                continue;
 
-        if (RetainPtr<CFStringRef> mimeType = mimeTypeFromUTITree((CFStringRef)object))
-            return mimeType;
+            String mimeType = MIMETypeFromUTITree((CFStringRef)object);
+            if (!mimeType.isEmpty())
+                return mimeType;
         }
     }
 
-    return nil;
+    return String();
 }
 
-RetainPtr<CFStringRef> UTIFromMIMEType(CFStringRef mime)
+struct UTIFromMIMETypeCachePolicy : TinyLRUCachePolicy<String, String> {
+public:
+    static String createValueForKey(const String& key)
+    {
+        return String(adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, key.createCFString().get(), 0)).get());
+    }
+};
+
+String UTIFromMIMEType(const String& mimeType)
 {
-    RetainPtr<CFStringRef> uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mime, 0));
-    return uti;
+    ASSERT(isMainThread());
+    static NeverDestroyed<TinyLRUCache<String, String, 16, UTIFromMIMETypeCachePolicy>> cache;
+    return cache.get().get(mimeType);
 }
 
-bool isDeclaredUTI(CFStringRef UTI)
+bool isDeclaredUTI(const String& UTI)
 {
-    return UTTypeIsDeclared(UTI);
+    return UTTypeIsDeclared(UTI.createCFString().get());
 }
 
 }
index f1cca02..ccd9036 100644 (file)
@@ -303,13 +303,15 @@ void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse, bool isMainResourceL
                 CFMutableStringRef mutableExtension = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, extension.get());
                 CFStringLowercase(mutableExtension, NULL);
                 extension = adoptCF(mutableExtension);
-                result = (CFStringRef) CFDictionaryGetValue(extensionMap, extension.get());
+                result = (CFStringRef)CFDictionaryGetValue(extensionMap, extension.get());
                 
                 if (!result) {
                     // If the Gatekeeper-based map doesn't have a MIME type, we'll try to figure out what it should be by
                     // looking up the file extension in the UTI maps.
                     RetainPtr<CFStringRef> uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), 0));
-                    result = mimeTypeFromUTITree(uti.get());
+                    String MIMEType = MIMETypeFromUTITree(uti.get());
+                    if (!MIMEType.isEmpty())
+                        result = MIMEType.createCFString();
                 }
             }
         }
index b8c95cf..d34c195 100644 (file)
@@ -1616,14 +1616,13 @@ static RetainPtr<UIImage> iconForAttachment(const RenderAttachment& attachment,
 
     String attachmentType = attachment.attachmentElement().attachmentType();
     if (!attachmentType.isEmpty()) {
-        auto attachmentTypeCF = attachmentType.createCFString();
-        RetainPtr<CFStringRef> UTI;
-        if (isDeclaredUTI(attachmentTypeCF.get()))
-            UTI = attachmentTypeCF;
+        String UTI;
+        if (isDeclaredUTI(attachmentType))
+            UTI = attachmentType;
         else
-            UTI = UTIFromMIMEType(attachmentTypeCF.get());
+            UTI = UTIFromMIMEType(attachmentType);
 
-        [documentInteractionController setUTI:static_cast<NSString *>(UTI.get())];
+        [documentInteractionController setUTI:static_cast<NSString *>(UTI)];
     }
 
     NSArray *icons = [documentInteractionController icons];
index 5ebce80..ae534f3 100644 (file)
@@ -2420,14 +2420,13 @@ static RefPtr<Icon> iconForAttachment(const RenderAttachment& attachment)
             if (auto icon = Icon::createIconForUTI("public.directory"))
                 return icon;
         } else {
-            auto attachmentTypeCF = attachmentType.createCFString();
-            RetainPtr<CFStringRef> UTI;
-            if (isDeclaredUTI(attachmentTypeCF.get()))
-                UTI = attachmentTypeCF;
+            String UTI;
+            if (isDeclaredUTI(attachmentType))
+                UTI = attachmentType;
             else
-                UTI = UTIFromMIMEType(attachmentTypeCF.get());
+                UTI = UTIFromMIMEType(attachmentType);
 
-            if (auto icon = Icon::createIconForUTI(UTI.get()))
+            if (auto icon = Icon::createIconForUTI(UTI))
                 return icon;
         }
     }