/*
 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "WebIconDatabaseInternal.h"

#import "WebIconDatabaseClient.h"
#import "WebIconDatabaseDelegate.h"
#import "WebKitLogging.h"
#import "WebKitNSStringExtras.h"
#import "WebNSFileManagerExtras.h"
#import "WebNSNotificationCenterExtras.h"
#import "WebNSURLExtras.h"
#import "WebPreferencesPrivate.h"
#import "WebTypesInternal.h"
#import <WebCore/IconDatabase.h>
#import <WebCore/Image.h>
#import <WebCore/IntSize.h>
#import <WebCore/SharedBuffer.h>
#import <WebCore/ThreadCheck.h>
#import <runtime/InitializeThreading.h>
#import <wtf/Threading.h>

using namespace WebCore;

NSString * const WebIconDatabaseVersionKey =    @"WebIconDatabaseVersion";
NSString * const WebURLToIconURLKey =           @"WebSiteURLToIconURLKey";

NSString *WebIconDatabaseDidAddIconNotification =          @"WebIconDatabaseDidAddIconNotification";
NSString *WebIconNotificationUserInfoURLKey =              @"WebIconNotificationUserInfoURLKey";
NSString *WebIconDatabaseDidRemoveAllIconsNotification =   @"WebIconDatabaseDidRemoveAllIconsNotification";

NSString *WebIconDatabaseDirectoryDefaultsKey = @"WebIconDatabaseDirectoryDefaultsKey";
NSString *WebIconDatabaseImportDirectoryDefaultsKey = @"WebIconDatabaseImportDirectoryDefaultsKey";
NSString *WebIconDatabaseEnabledDefaultsKey =   @"WebIconDatabaseEnabled";

NSString *WebIconDatabasePath = @"~/Library/Icons";

NSSize WebIconSmallSize = {16, 16};
NSSize WebIconMediumSize = {32, 32};
NSSize WebIconLargeSize = {128, 128};

#define UniqueFilePathSize (34)

static WebIconDatabaseClient* defaultClient()
{
#if ENABLE(ICONDATABASE)
    static WebIconDatabaseClient* defaultClient = new WebIconDatabaseClient();
    return defaultClient;
#else
    return 0;
#endif
}

@interface WebIconDatabase (WebReallyInternal)
- (void)_sendNotificationForURL:(NSString *)URL;
- (void)_sendDidRemoveAllIconsNotification;
- (NSImage *)_iconForFileURL:(NSString *)fileURL withSize:(NSSize)size;
- (void)_resetCachedWebPreferences:(NSNotification *)notification;
- (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons;
- (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon;
- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache;
- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size;
- (NSString *)_databaseDirectory;
@end

@implementation WebIconDatabase

+ (void)initialize
{
    JSC::initializeThreading();
    WTF::initializeMainThreadToProcessMainThread();
}

+ (WebIconDatabase *)sharedIconDatabase
{
    static WebIconDatabase *database = nil;
    if (!database)
        database = [[WebIconDatabase alloc] init];
    return database;
}

- (id)init
{
    [super init];
    WebCoreThreadViolationCheckRoundOne();
        
    _private = [[WebIconDatabasePrivate alloc] init];
    
    // Check the user defaults and see if the icon database should even be enabled.
    // Inform the bridge and, if we're disabled, bail from init right here
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    // <rdar://problem/4741419> - IconDatabase should be disabled by default
    NSDictionary *initialDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], WebIconDatabaseEnabledDefaultsKey, nil];
    [defaults registerDefaults:initialDefaults];
    [initialDefaults release];
    BOOL enabled = [defaults boolForKey:WebIconDatabaseEnabledDefaultsKey];
    iconDatabase().setEnabled(enabled);
    if (enabled)
        [self _startUpIconDatabase];
    return self;
}

- (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size cache:(BOOL)cache
{
    ASSERT_MAIN_THREAD();
    ASSERT(size.width);
    ASSERT(size.height);

    if (!URL || ![self isEnabled])
        return [self defaultIconForURL:URL withSize:size];

    // FIXME - <rdar://problem/4697934> - Move the handling of FileURLs to WebCore and implement in ObjC++
    if ([URL _webkit_isFileURL])
        return [self _iconForFileURL:URL withSize:size];
    
    if (Image* image = iconDatabase().synchronousIconForPageURL(URL, IntSize(size)))
        if (NSImage *icon = webGetNSImage(image, size))
            return icon;
    return [self defaultIconForURL:URL withSize:size];
}

- (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size
{
    return [self iconForURL:URL withSize:size cache:YES];
}

- (NSString *)iconURLForURL:(NSString *)URL
{
    if (![self isEnabled])
        return nil;
    ASSERT_MAIN_THREAD();

    return iconDatabase().synchronousIconURLForPageURL(URL);
}

- (NSImage *)defaultIconWithSize:(NSSize)size
{
    ASSERT_MAIN_THREAD();
    ASSERT(size.width);
    ASSERT(size.height);
    
    Image* image = iconDatabase().defaultIcon(IntSize(size));
    return image ? image->getNSImage() : nil;
}

- (NSImage *)defaultIconForURL:(NSString *)URL withSize:(NSSize)size
{
    if (_private->delegateImplementsDefaultIconForURL)
        return [_private->delegate webIconDatabase:self defaultIconForURL:URL withSize:size];
    return [self defaultIconWithSize:size];
}

- (void)retainIconForURL:(NSString *)URL
{
    ASSERT_MAIN_THREAD();
    ASSERT(URL);
    if (![self isEnabled])
        return;

    iconDatabase().retainIconForPageURL(URL);
}

- (void)releaseIconForURL:(NSString *)pageURL
{
    ASSERT_MAIN_THREAD();
    ASSERT(pageURL);
    if (![self isEnabled])
        return;

    iconDatabase().releaseIconForPageURL(pageURL);
}

+ (void)delayDatabaseCleanup
{
    ASSERT_MAIN_THREAD();

    IconDatabase::delayDatabaseCleanup();
}

+ (void)allowDatabaseCleanup
{
    ASSERT_MAIN_THREAD();

    IconDatabase::allowDatabaseCleanup();
}

- (void)setDelegate:(id)delegate
{
    _private->delegate = delegate;
    _private->delegateImplementsDefaultIconForURL = [delegate respondsToSelector:@selector(webIconDatabase:defaultIconForURL:withSize:)];
}

- (id)delegate
{
    return _private->delegate;
}

@end


@implementation WebIconDatabase (WebPendingPublic)

- (BOOL)isEnabled
{
    return iconDatabase().isEnabled();
}

- (void)setEnabled:(BOOL)flag
{
    BOOL currentlyEnabled = [self isEnabled];
    if (currentlyEnabled && !flag) {
        iconDatabase().setEnabled(false);
        [self _shutDownIconDatabase];
    } else if (!currentlyEnabled && flag) {
        iconDatabase().setEnabled(true);
        [self _startUpIconDatabase];
    }
}

- (void)removeAllIcons
{
    ASSERT_MAIN_THREAD();
    if (![self isEnabled])
        return;

    // Via the IconDatabaseClient interface, removeAllIcons() will send the WebIconDatabaseDidRemoveAllIconsNotification
    iconDatabase().removeAllIcons();
}

@end

@implementation WebIconDatabase (WebPrivate)

+ (void)_checkIntegrityBeforeOpening
{
    IconDatabase::checkIntegrityBeforeOpening();
}

@end

@implementation WebIconDatabase (WebInternal)

- (void)_sendNotificationForURL:(NSString *)URL
{
    ASSERT(URL);
    
    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:URL
                                                         forKey:WebIconNotificationUserInfoURLKey];
                                                         
    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidAddIconNotification
                                                        object:self
                                                      userInfo:userInfo];
}

- (void)_sendDidRemoveAllIconsNotification
{
    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidRemoveAllIconsNotification
                                                        object:self
                                                      userInfo:nil];
}

- (void)_startUpIconDatabase
{
    iconDatabase().setClient(defaultClient());
    
    // Figure out the directory we should be using for the icon.db
    NSString *databaseDirectory = [self _databaseDirectory];
    
    // Rename legacy icon database files to the new icon database name
    BOOL isDirectory = NO;
    NSString *legacyDB = [databaseDirectory stringByAppendingPathComponent:@"icon.db"];
    NSFileManager *defaultManager = [NSFileManager defaultManager];
    if ([defaultManager fileExistsAtPath:legacyDB isDirectory:&isDirectory] && !isDirectory) {
        NSString *newDB = [databaseDirectory stringByAppendingPathComponent:IconDatabase::defaultDatabaseFilename()];
        if (![defaultManager fileExistsAtPath:newDB])
            rename([legacyDB fileSystemRepresentation], [newDB fileSystemRepresentation]);
    }
    
    // Set the private browsing pref then open the WebCore icon database
    iconDatabase().setPrivateBrowsingEnabled([[WebPreferences standardPreferences] privateBrowsingEnabled]);
    if (!iconDatabase().open(databaseDirectory, IconDatabase::defaultDatabaseFilename()))
        LOG_ERROR("Unable to open icon database");
    
    // Register for important notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(_applicationWillTerminate:)
                                                 name:NSApplicationWillTerminateNotification
                                               object:NSApp];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(_resetCachedWebPreferences:)
                                                 name:WebPreferencesChangedInternalNotification
                                               object:nil];
}

- (void)_shutDownIconDatabase
{
    // Unregister for important notifications
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSApplicationWillTerminateNotification
                                                  object:NSApp];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:WebPreferencesChangedInternalNotification
                                                  object:nil];
}

- (void)_applicationWillTerminate:(NSNotification *)notification
{
    iconDatabase().close();
}

- (NSImage *)_iconForFileURL:(NSString *)file withSize:(NSSize)size
{
    ASSERT_MAIN_THREAD();
    ASSERT(size.width);
    ASSERT(size.height);

    NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
    NSString *path = [[NSURL _web_URLWithDataAsString:file] path];
    NSString *suffix = [path pathExtension];
    NSImage *icon = nil;
    
    if ([suffix _webkit_isCaseInsensitiveEqualToString:@"htm"] || [suffix _webkit_isCaseInsensitiveEqualToString:@"html"]) {
        if (!_private->htmlIcons) {
            icon = [workspace iconForFileType:@"html"];
            _private->htmlIcons = [[self _iconsBySplittingRepresentationsOfIcon:icon] retain];
        }
        icon = [self _iconFromDictionary:_private->htmlIcons forSize:size cache:YES];
    } else {
        if (!path || ![path isAbsolutePath]) {
            // Return the generic icon when there is no path.
            icon = [workspace iconForFileType:NSFileTypeForHFSTypeCode(kGenericDocumentIcon)];
        } else {
            icon = [workspace iconForFile:path];
        }
        [self _scaleIcon:icon toSize:size];
    }

    return icon;
}

- (void)_resetCachedWebPreferences:(NSNotification *)notification
{
    BOOL privateBrowsingEnabledNow = [[WebPreferences standardPreferences] privateBrowsingEnabled];
    iconDatabase().setPrivateBrowsingEnabled(privateBrowsingEnabledNow);
}

- (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons
{
    ASSERT(icons);
    
    NSEnumerator *enumerator = [icons keyEnumerator];
    NSValue *currentSize, *largestSize=nil;
    float largestSizeArea=0;

    while ((currentSize = [enumerator nextObject]) != nil) {
        NSSize currentSizeSize = [currentSize sizeValue];
        float currentSizeArea = currentSizeSize.width * currentSizeSize.height;
        if(!largestSizeArea || (currentSizeArea > largestSizeArea)){
            largestSize = currentSize;
            largestSizeArea = currentSizeArea;
        }
    }

    return [icons objectForKey:largestSize];
}

- (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon
{
    ASSERT(icon);

    NSMutableDictionary *icons = [NSMutableDictionary dictionary];
    NSEnumerator *enumerator = [[icon representations] objectEnumerator];
    NSImageRep *rep;

    while ((rep = [enumerator nextObject]) != nil) {
        NSSize size = [rep size];
        NSImage *subIcon = [[NSImage alloc] initWithSize:size];
        [subIcon addRepresentation:rep];
        [icons setObject:subIcon forKey:[NSValue valueWithSize:size]];
        [subIcon release];
    }

    if([icons count] > 0)
        return icons;

    LOG_ERROR("icon has no representations");
    
    return nil;
}

- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache
{
    ASSERT(size.width);
    ASSERT(size.height);

    NSImage *icon = [icons objectForKey:[NSValue valueWithSize:size]];

    if(!icon){
        icon = [[[self _largestIconFromDictionary:icons] copy] autorelease];
        [self _scaleIcon:icon toSize:size];

        if(cache){
            [icons setObject:icon forKey:[NSValue valueWithSize:size]];
        }
    }

    return icon;
}

- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size
{
    ASSERT(size.width);
    ASSERT(size.height);
    
#if !LOG_DISABLED        
    double start = CFAbsoluteTimeGetCurrent();
#endif
    
    [icon setScalesWhenResized:YES];
    [icon setSize:size];
    
#if !LOG_DISABLED
    double duration = CFAbsoluteTimeGetCurrent() - start;
    LOG(Timing, "scaling icon took %f seconds.", duration);
#endif
}

// This hashing String->filename algorithm came from WebFileDatabase.m and is what was used in the 
// WebKit Icon Database
static void legacyIconDatabaseFilePathForKey(id key, char *buffer)
{
    const char *s;
    UInt32 hash1;
    UInt32 hash2;
    CFIndex len;
    CFIndex cnt;
    
    s = [[[[key description] lowercaseString] stringByStandardizingPath] UTF8String];
    len = strlen(s);

    // compute first hash    
    hash1 = len;
    for (cnt = 0; cnt < len; cnt++) {
        hash1 += (hash1 << 8) + s[cnt];
    }
    hash1 += (hash1 << (len & 31));

    // compute second hash    
    hash2 = len;
    for (cnt = 0; cnt < len; cnt++) {
        hash2 = (37 * hash2) ^ s[cnt];
    }

#ifdef __LP64__
    snprintf(buffer, UniqueFilePathSize, "%.2u/%.2u/%.10u-%.10u.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
#else
    snprintf(buffer, UniqueFilePathSize, "%.2lu/%.2lu/%.10lu-%.10lu.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
#endif
}

// This method of getting an object from the filesystem is taken from the old 
// WebKit Icon Database
static id objectFromPathForKey(NSString *databasePath, id key)
{
    ASSERT(key);
    id result = nil;

    // Use the key->filename hashing the old WebKit IconDatabase used
    char uniqueKey[UniqueFilePathSize];    
    legacyIconDatabaseFilePathForKey(key, uniqueKey);
    
    // Get the data from this file and setup for the un-archiving
    NSString *filePath = [[NSString alloc] initWithFormat:@"%@/%s", databasePath, uniqueKey];
    NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
    NSUnarchiver *unarchiver = nil;
    
    @try {
        if (data) {
            unarchiver = [[NSUnarchiver alloc] initForReadingWithData:data];
            if (unarchiver) {
                id fileKey = [unarchiver decodeObject];
                if ([fileKey isEqual:key]) {
                    id object = [unarchiver decodeObject];
                    if (object) {
                        // Decoded objects go away when the unarchiver does, so we need to
                        // retain this so we can return it to our caller.
                        result = [[object retain] autorelease];
                        LOG(IconDatabase, "read disk cache file - %@", key);
                    }
                }
            }
        }
    } @catch (NSException *localException) {
        LOG(IconDatabase, "cannot unarchive cache file - %@", key);
        result = nil;
    }

    [unarchiver release];
    [data release];
    [filePath release];
    
    return result;
}

static NSData* iconDataFromPathForIconURL(NSString *databasePath, NSString *iconURLString)
{
    ASSERT(iconURLString);
    ASSERT(databasePath);
    
    NSData *iconData = objectFromPathForKey(databasePath, iconURLString);
    
    if ((id)iconData == (id)[NSNull null]) 
        return nil;
        
    return iconData;
}

- (NSString *)_databaseDirectory
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // Figure out the directory we should be using for the icon.db
    NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
    if (!databaseDirectory) {
        databaseDirectory = WebIconDatabasePath;
        [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
    }
    
    return [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];
}

@end

@implementation WebIconDatabasePrivate
@end

@interface ThreadEnabler : NSObject {
}
+ (void)enableThreading;

- (void)threadEnablingSelector:(id)arg;
@end

@implementation ThreadEnabler

- (void)threadEnablingSelector:(id)arg
{
    return;
}

+ (void)enableThreading
{
    ThreadEnabler *enabler = [[ThreadEnabler alloc] init];
    [NSThread detachNewThreadSelector:@selector(threadEnablingSelector:) toTarget:enabler withObject:nil];
    [enabler release];
}

@end

bool importToWebCoreFormat()
{
    // Since this is running on a secondary POSIX thread and Cocoa cannot be used multithreaded unless an NSThread has been detached,
    // make sure that happens here for all WebKit clients
    if (![NSThread isMultiThreaded])
        [ThreadEnabler enableThreading];
    ASSERT([NSThread isMultiThreaded]);    
    
    // Get the directory the old icon database *should* be in
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseImportDirectoryDefaultsKey];
    
    if (!databaseDirectory)
        databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
        
    if (!databaseDirectory) {
        databaseDirectory = WebIconDatabasePath;
        [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
    }
    databaseDirectory = [databaseDirectory stringByExpandingTildeInPath];

    // With this directory, get the PageURLToIconURL map that was saved to disk
    NSMutableDictionary *pageURLToIconURL = objectFromPathForKey(databaseDirectory, WebURLToIconURLKey);

    // If the retrieved object was not a valid NSMutableDictionary, then we have no valid
    // icons to import
    if (![pageURLToIconURL isKindOfClass:[NSMutableDictionary class]])
        pageURLToIconURL = nil;
    
    if (!pageURLToIconURL) {
        // We found no Safari-2-style icon database. Bail out immediately and do not delete everything
        // in whatever directory we ended up looking in! Return true so we won't bother to check again.
        // FIXME: We can probably delete all of the code to convert Safari-2-style icon databases now.
        return true;
    }
    
    NSEnumerator *enumerator = [pageURLToIconURL keyEnumerator];
    NSString *url, *iconURL;
    
    // First, we'll iterate through the PageURL->IconURL map
    while ((url = [enumerator nextObject]) != nil) {
        iconURL = [pageURLToIconURL objectForKey:url];
        if (!iconURL)
            continue;
        iconDatabase().importIconURLForPageURL(iconURL, url);
        if (iconDatabase().shouldStopThreadActivity())
            return false;
    }    

    // Second, we'll get a list of the unique IconURLs we have
    NSMutableSet *iconsOnDiskWithURLs = [NSMutableSet setWithArray:[pageURLToIconURL allValues]];
    enumerator = [iconsOnDiskWithURLs objectEnumerator];
    NSData *iconData;
    
    // And iterate through them, adding the icon data to the new icon database
    while ((url = [enumerator nextObject]) != nil) {
        iconData = iconDataFromPathForIconURL(databaseDirectory, url);
        if (iconData)
            iconDatabase().importIconDataForIconURL(SharedBuffer::wrapNSData(iconData), url);
        else {
            // This really *shouldn't* happen, so it'd be good to track down why it might happen in a debug build
            // however, we do know how to handle it gracefully in release
            LOG_ERROR("%@ is marked as having an icon on disk, but we couldn't get the data for it", url);
            iconDatabase().importIconDataForIconURL(0, url);
        }
        if (iconDatabase().shouldStopThreadActivity())
            return false;
    }
    
    // After we're done importing old style icons over to webcore icons, we delete the entire directory hierarchy 
    // for the old icon DB (skipping the new iconDB if it is in the same directory)
    NSFileManager *fileManager = [NSFileManager defaultManager];
    enumerator = [[fileManager contentsOfDirectoryAtPath:databaseDirectory error:NULL] objectEnumerator];

    NSString *databaseFilename = IconDatabase::defaultDatabaseFilename();

    BOOL foundIconDB = NO;
    NSString *file;
    while ((file = [enumerator nextObject]) != nil) {
        if ([file caseInsensitiveCompare:databaseFilename] == NSOrderedSame) {
            foundIconDB = YES;
            continue;
        }
        NSString *filePath = [databaseDirectory stringByAppendingPathComponent:file];
        if (![fileManager removeItemAtPath:filePath error:NULL])
            LOG_ERROR("Failed to delete %@ from old icon directory", filePath);
    }
    
    // If the new iconDB wasn't in that directory, we can delete the directory itself
    if (!foundIconDB)
        rmdir([databaseDirectory fileSystemRepresentation]);
    
    return true;
}

NSImage *webGetNSImage(Image* image, NSSize size)
{
    ASSERT_MAIN_THREAD();
    ASSERT(size.width);
    ASSERT(size.height);

    // FIXME: We're doing the resize here for now because WebCore::Image doesn't yet support resizing/multiple representations
    // This makes it so there's effectively only one size of a particular icon in the system at a time. We should move this
    // to WebCore::Image at some point.
    if (!image)
        return nil;
    NSImage* nsImage = image->getNSImage();
    if (!nsImage)
        return nil;
    if (!NSEqualSizes([nsImage size], size)) {
        [nsImage setScalesWhenResized:YES];
        [nsImage setSize:size];
    }
    return nsImage;
}
