18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebIconDatabaseInternal.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebIconDatabaseClient.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebIconDatabaseDelegate.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebKitLogging.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebKitNSStringExtras.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebNSFileManagerExtras.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebNSNotificationCenterExtras.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebNSURLExtras.h"
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#import "WebPreferencesPrivate.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebTypesInternal.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/IconDatabase.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/Image.h>
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/IntSize.h>
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#import <WebCore/SharedBuffer.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <WebCore/ThreadCheck.h>
4521939df44de1705786c545cd1bf519d47250322dBen Murdoch#import <runtime/InitializeThreading.h>
4621939df44de1705786c545cd1bf519d47250322dBen Murdoch#import <wtf/Threading.h>
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore;
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString * const WebIconDatabaseVersionKey =    @"WebIconDatabaseVersion";
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString * const WebURLToIconURLKey =           @"WebSiteURLToIconURLKey";
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabaseDidAddIconNotification =          @"WebIconDatabaseDidAddIconNotification";
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconNotificationUserInfoURLKey =              @"WebIconNotificationUserInfoURLKey";
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabaseDidRemoveAllIconsNotification =   @"WebIconDatabaseDidRemoveAllIconsNotification";
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabaseDirectoryDefaultsKey = @"WebIconDatabaseDirectoryDefaultsKey";
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabaseImportDirectoryDefaultsKey = @"WebIconDatabaseImportDirectoryDefaultsKey";
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabaseEnabledDefaultsKey =   @"WebIconDatabaseEnabled";
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSString *WebIconDatabasePath = @"~/Library/Icons";
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSSize WebIconSmallSize = {16, 16};
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSSize WebIconMediumSize = {32, 32};
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSSize WebIconLargeSize = {128, 128};
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define UniqueFilePathSize (34)
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic WebIconDatabaseClient* defaultClient()
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if ENABLE(ICONDATABASE)
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static WebIconDatabaseClient* defaultClient = new WebIconDatabaseClient();
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return defaultClient;
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 0;
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@interface WebIconDatabase (WebReallyInternal)
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_sendNotificationForURL:(NSString *)URL;
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_sendDidRemoveAllIconsNotification;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_iconForFileURL:(NSString *)fileURL withSize:(NSSize)size;
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_resetCachedWebPreferences:(NSNotification *)notification;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons;
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon;
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_databaseDirectory;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebIconDatabase
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9321939df44de1705786c545cd1bf519d47250322dBen Murdoch+ (void)initialize
9421939df44de1705786c545cd1bf519d47250322dBen Murdoch{
9521939df44de1705786c545cd1bf519d47250322dBen Murdoch    JSC::initializeThreading();
9621939df44de1705786c545cd1bf519d47250322dBen Murdoch    WTF::initializeMainThreadToProcessMainThread();
9721939df44de1705786c545cd1bf519d47250322dBen Murdoch}
9821939df44de1705786c545cd1bf519d47250322dBen Murdoch
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (WebIconDatabase *)sharedIconDatabase
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static WebIconDatabase *database = nil;
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!database)
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        database = [[WebIconDatabase alloc] init];
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return database;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
107967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch- (id)init
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [super init];
110563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    WebCoreThreadViolationCheckRoundOne();
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _private = [[WebIconDatabasePrivate alloc] init];
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the user defaults and see if the icon database should even be enabled.
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Inform the bridge and, if we're disabled, bail from init right here
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // <rdar://problem/4741419> - IconDatabase should be disabled by default
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSDictionary *initialDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], WebIconDatabaseEnabledDefaultsKey, nil];
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [defaults registerDefaults:initialDefaults];
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [initialDefaults release];
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    BOOL enabled = [defaults boolForKey:WebIconDatabaseEnabledDefaultsKey];
12281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().setEnabled(enabled);
123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (enabled)
124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        [self _startUpIconDatabase];
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return self;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size cache:(BOOL)cache
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!URL || ![self isEnabled])
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return [self defaultIconForURL:URL withSize:size];
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME - <rdar://problem/4697934> - Move the handling of FileURLs to WebCore and implement in ObjC++
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ([URL _webkit_isFileURL])
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return [self _iconForFileURL:URL withSize:size];
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block
1412bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (Image* image = iconDatabase().synchronousIconForPageURL(URL, IntSize(size)))
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (NSImage *icon = webGetNSImage(image, size))
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return icon;
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [self defaultIconForURL:URL withSize:size];
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [self iconForURL:URL withSize:size cache:YES];
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)iconURLForURL:(NSString *)URL
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (![self isEnabled])
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    return iconDatabase().synchronousIconURLForPageURL(URL);
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)defaultIconWithSize:(NSSize)size
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Image* image = iconDatabase().defaultIcon(IntSize(size));
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return image ? image->getNSImage() : nil;
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)defaultIconForURL:(NSString *)URL withSize:(NSSize)size
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (_private->delegateImplementsDefaultIconForURL)
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return [_private->delegate webIconDatabase:self defaultIconForURL:URL withSize:size];
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [self defaultIconWithSize:size];
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)retainIconForURL:(NSString *)URL
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(URL);
182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (![self isEnabled])
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().retainIconForPageURL(URL);
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)releaseIconForURL:(NSString *)pageURL
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(pageURL);
192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (![self isEnabled])
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().releaseIconForPageURL(pageURL);
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)delayDatabaseCleanup
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IconDatabase::delayDatabaseCleanup();
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)allowDatabaseCleanup
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IconDatabase::allowDatabaseCleanup();
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setDelegate:(id)delegate
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _private->delegate = delegate;
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _private->delegateImplementsDefaultIconForURL = [delegate respondsToSelector:@selector(webIconDatabase:defaultIconForURL:withSize:)];
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (id)delegate
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return _private->delegate;
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebIconDatabase (WebPendingPublic)
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (BOOL)isEnabled
229635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return iconDatabase().isEnabled();
231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
233635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)setEnabled:(BOOL)flag
234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
235635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    BOOL currentlyEnabled = [self isEnabled];
236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (currentlyEnabled && !flag) {
23781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        iconDatabase().setEnabled(false);
238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        [self _shutDownIconDatabase];
239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    } else if (!currentlyEnabled && flag) {
24081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        iconDatabase().setEnabled(true);
241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        [self _startUpIconDatabase];
242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)removeAllIcons
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (![self isEnabled])
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Via the IconDatabaseClient interface, removeAllIcons() will send the WebIconDatabaseDidRemoveAllIconsNotification
25281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().removeAllIcons();
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebIconDatabase (WebPrivate)
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)_checkIntegrityBeforeOpening
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block    IconDatabase::checkIntegrityBeforeOpening();
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebIconDatabase (WebInternal)
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_sendNotificationForURL:(NSString *)URL
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(URL);
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:URL
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                         forKey:WebIconNotificationUserInfoURLKey];
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidAddIconNotification
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                        object:self
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                      userInfo:userInfo];
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_sendDidRemoveAllIconsNotification
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidRemoveAllIconsNotification
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                        object:self
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                      userInfo:nil];
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)_startUpIconDatabase
288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
28981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().setClient(defaultClient());
290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Figure out the directory we should be using for the icon.db
292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    NSString *databaseDirectory = [self _databaseDirectory];
293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Rename legacy icon database files to the new icon database name
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    BOOL isDirectory = NO;
296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    NSString *legacyDB = [databaseDirectory stringByAppendingPathComponent:@"icon.db"];
297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    NSFileManager *defaultManager = [NSFileManager defaultManager];
298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if ([defaultManager fileExistsAtPath:legacyDB isDirectory:&isDirectory] && !isDirectory) {
2992bde8e466a4451c7319e3a072d118917957d6554Steve Block        NSString *newDB = [databaseDirectory stringByAppendingPathComponent:IconDatabase::defaultDatabaseFilename()];
300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (![defaultManager fileExistsAtPath:newDB])
301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            rename([legacyDB fileSystemRepresentation], [newDB fileSystemRepresentation]);
302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Set the private browsing pref then open the WebCore icon database
30581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().setPrivateBrowsingEnabled([[WebPreferences standardPreferences] privateBrowsingEnabled]);
3062bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!iconDatabase().open(databaseDirectory, IconDatabase::defaultDatabaseFilename()))
307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        LOG_ERROR("Unable to open icon database");
308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Register for important notifications
310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:self
311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                             selector:@selector(_applicationWillTerminate:)
312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                                 name:NSApplicationWillTerminateNotification
313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                               object:NSApp];
314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:self
315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                             selector:@selector(_resetCachedWebPreferences:)
3162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                                 name:WebPreferencesChangedInternalNotification
317635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                               object:nil];
318635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
319635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
320635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)_shutDownIconDatabase
321635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
322635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Unregister for important notifications
323635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    [[NSNotificationCenter defaultCenter] removeObserver:self
324635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                                    name:NSApplicationWillTerminateNotification
325635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                                  object:NSApp];
326635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    [[NSNotificationCenter defaultCenter] removeObserver:self
3272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                                    name:WebPreferencesChangedInternalNotification
328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                                                  object:nil];
329635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_applicationWillTerminate:(NSNotification *)notification
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
33381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().close();
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_iconForFileURL:(NSString *)file withSize:(NSSize)size
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *path = [[NSURL _web_URLWithDataAsString:file] path];
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *suffix = [path pathExtension];
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSImage *icon = nil;
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ([suffix _webkit_isCaseInsensitiveEqualToString:@"htm"] || [suffix _webkit_isCaseInsensitiveEqualToString:@"html"]) {
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!_private->htmlIcons) {
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            icon = [workspace iconForFileType:@"html"];
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            _private->htmlIcons = [[self _iconsBySplittingRepresentationsOfIcon:icon] retain];
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        icon = [self _iconFromDictionary:_private->htmlIcons forSize:size cache:YES];
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!path || ![path isAbsolutePath]) {
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Return the generic icon when there is no path.
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            icon = [workspace iconForFileType:NSFileTypeForHFSTypeCode(kGenericDocumentIcon)];
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            icon = [workspace iconForFile:path];
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self _scaleIcon:icon toSize:size];
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return icon;
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_resetCachedWebPreferences:(NSNotification *)notification
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    BOOL privateBrowsingEnabledNow = [[WebPreferences standardPreferences] privateBrowsingEnabled];
36981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    iconDatabase().setPrivateBrowsingEnabled(privateBrowsingEnabledNow);
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(icons);
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSEnumerator *enumerator = [icons keyEnumerator];
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSValue *currentSize, *largestSize=nil;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float largestSizeArea=0;
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((currentSize = [enumerator nextObject]) != nil) {
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSSize currentSizeSize = [currentSize sizeValue];
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float currentSizeArea = currentSizeSize.width * currentSizeSize.height;
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if(!largestSizeArea || (currentSizeArea > largestSizeArea)){
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            largestSize = currentSize;
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            largestSizeArea = currentSizeArea;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [icons objectForKey:largestSize];
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(icon);
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSMutableDictionary *icons = [NSMutableDictionary dictionary];
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSEnumerator *enumerator = [[icon representations] objectEnumerator];
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSImageRep *rep;
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((rep = [enumerator nextObject]) != nil) {
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSSize size = [rep size];
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSImage *subIcon = [[NSImage alloc] initWithSize:size];
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [subIcon addRepresentation:rep];
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [icons setObject:subIcon forKey:[NSValue valueWithSize:size]];
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [subIcon release];
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if([icons count] > 0)
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return icons;
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ERROR("icon has no representations");
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nil;
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSImage *icon = [icons objectForKey:[NSValue valueWithSize:size]];
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if(!icon){
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        icon = [[[self _largestIconFromDictionary:icons] copy] autorelease];
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self _scaleIcon:icon toSize:size];
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if(cache){
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            [icons setObject:icon forKey:[NSValue valueWithSize:size]];
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return icon;
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double start = CFAbsoluteTimeGetCurrent();
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [icon setScalesWhenResized:YES];
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [icon setSize:size];
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !LOG_DISABLED
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double duration = CFAbsoluteTimeGetCurrent() - start;
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(Timing, "scaling icon took %f seconds.", duration);
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This hashing String->filename algorithm came from WebFileDatabase.m and is what was used in the
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// WebKit Icon Database
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void legacyIconDatabaseFilePathForKey(id key, char *buffer)
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char *s;
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UInt32 hash1;
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UInt32 hash2;
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CFIndex len;
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CFIndex cnt;
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    s = [[[[key description] lowercaseString] stringByStandardizingPath] UTF8String];
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    len = strlen(s);
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // compute first hash
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    hash1 = len;
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (cnt = 0; cnt < len; cnt++) {
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hash1 += (hash1 << 8) + s[cnt];
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    hash1 += (hash1 << (len & 31));
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // compute second hash
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    hash2 = len;
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (cnt = 0; cnt < len; cnt++) {
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        hash2 = (37 * hash2) ^ s[cnt];
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef __LP64__
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    snprintf(buffer, UniqueFilePathSize, "%.2u/%.2u/%.10u-%.10u.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    snprintf(buffer, UniqueFilePathSize, "%.2lu/%.2lu/%.10lu-%.10lu.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This method of getting an object from the filesystem is taken from the old
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// WebKit Icon Database
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic id objectFromPathForKey(NSString *databasePath, id key)
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(key);
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    id result = nil;
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Use the key->filename hashing the old WebKit IconDatabase used
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char uniqueKey[UniqueFilePathSize];
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    legacyIconDatabaseFilePathForKey(key, uniqueKey);
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the data from this file and setup for the un-archiving
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *filePath = [[NSString alloc] initWithFormat:@"%@/%s", databasePath, uniqueKey];
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSUnarchiver *unarchiver = nil;
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    @try {
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data) {
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unarchiver = [[NSUnarchiver alloc] initForReadingWithData:data];
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (unarchiver) {
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                id fileKey = [unarchiver decodeObject];
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ([fileKey isEqual:key]) {
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    id object = [unarchiver decodeObject];
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (object) {
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // Decoded objects go away when the unarchiver does, so we need to
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // retain this so we can return it to our caller.
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        result = [[object retain] autorelease];
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        LOG(IconDatabase, "read disk cache file - %@", key);
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } @catch (NSException *localException) {
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG(IconDatabase, "cannot unarchive cache file - %@", key);
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = nil;
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [unarchiver release];
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [data release];
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [filePath release];
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic NSData* iconDataFromPathForIconURL(NSString *databasePath, NSString *iconURLString)
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(iconURLString);
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(databasePath);
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSData *iconData = objectFromPathForKey(databasePath, iconURLString);
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ((id)iconData == (id)[NSNull null])
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return iconData;
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (NSString *)_databaseDirectory
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Figure out the directory we should be using for the icon.db
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!databaseDirectory) {
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        databaseDirectory = WebIconDatabasePath;
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebIconDatabasePrivate
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@interface ThreadEnabler : NSObject {
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)enableThreading;
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)threadEnablingSelector:(id)arg;
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation ThreadEnabler
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)threadEnablingSelector:(id)arg
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return;
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project+ (void)enableThreading
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ThreadEnabler *enabler = [[ThreadEnabler alloc] init];
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [NSThread detachNewThreadSelector:@selector(threadEnablingSelector:) toTarget:enabler withObject:nil];
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [enabler release];
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool importToWebCoreFormat()
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Since this is running on a secondary POSIX thread and Cocoa cannot be used multithreaded unless an NSThread has been detached,
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // make sure that happens here for all WebKit clients
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (![NSThread isMultiThreaded])
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [ThreadEnabler enableThreading];
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT([NSThread isMultiThreaded]);
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the directory the old icon database *should* be in
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseImportDirectoryDefaultsKey];
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!databaseDirectory)
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!databaseDirectory) {
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        databaseDirectory = WebIconDatabasePath;
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    databaseDirectory = [databaseDirectory stringByExpandingTildeInPath];
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // With this directory, get the PageURLToIconURL map that was saved to disk
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSMutableDictionary *pageURLToIconURL = objectFromPathForKey(databaseDirectory, WebURLToIconURLKey);
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the retrieved object was not a valid NSMutableDictionary, then we have no valid
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // icons to import
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (![pageURLToIconURL isKindOfClass:[NSMutableDictionary class]])
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pageURLToIconURL = nil;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!pageURLToIconURL) {
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // We found no Safari-2-style icon database. Bail out immediately and do not delete everything
6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // in whatever directory we ended up looking in! Return true so we won't bother to check again.
6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // FIXME: We can probably delete all of the code to convert Safari-2-style icon databases now.
6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSEnumerator *enumerator = [pageURLToIconURL keyEnumerator];
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *url, *iconURL;
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // First, we'll iterate through the PageURL->IconURL map
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((url = [enumerator nextObject]) != nil) {
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        iconURL = [pageURLToIconURL objectForKey:url];
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!iconURL)
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
62981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        iconDatabase().importIconURLForPageURL(iconURL, url);
63081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (iconDatabase().shouldStopThreadActivity())
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Second, we'll get a list of the unique IconURLs we have
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSMutableSet *iconsOnDiskWithURLs = [NSMutableSet setWithArray:[pageURLToIconURL allValues]];
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    enumerator = [iconsOnDiskWithURLs objectEnumerator];
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSData *iconData;
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // And iterate through them, adding the icon data to the new icon database
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((url = [enumerator nextObject]) != nil) {
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        iconData = iconDataFromPathForIconURL(databaseDirectory, url);
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (iconData)
64381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            iconDatabase().importIconDataForIconURL(SharedBuffer::wrapNSData(iconData), url);
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This really *shouldn't* happen, so it'd be good to track down why it might happen in a debug build
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // however, we do know how to handle it gracefully in release
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOG_ERROR("%@ is marked as having an icon on disk, but we couldn't get the data for it", url);
64881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            iconDatabase().importIconDataForIconURL(0, url);
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
65081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (iconDatabase().shouldStopThreadActivity())
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // After we're done importing old style icons over to webcore icons, we delete the entire directory hierarchy
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // for the old icon DB (skipping the new iconDB if it is in the same directory)
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSFileManager *fileManager = [NSFileManager defaultManager];
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    enumerator = [[fileManager contentsOfDirectoryAtPath:databaseDirectory error:NULL] objectEnumerator];
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6592bde8e466a4451c7319e3a072d118917957d6554Steve Block    NSString *databaseFilename = IconDatabase::defaultDatabaseFilename();
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    BOOL foundIconDB = NO;
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSString *file;
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while ((file = [enumerator nextObject]) != nil) {
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if ([file caseInsensitiveCompare:databaseFilename] == NSOrderedSame) {
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            foundIconDB = YES;
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        NSString *filePath = [databaseDirectory stringByAppendingPathComponent:file];
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (![fileManager removeItemAtPath:filePath error:NULL])
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOG_ERROR("Failed to delete %@ from old icon directory", filePath);
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If the new iconDB wasn't in that directory, we can delete the directory itself
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!foundIconDB)
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        rmdir([databaseDirectory fileSystemRepresentation]);
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNSImage *webGetNSImage(Image* image, NSSize size)
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_MAIN_THREAD();
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.width);
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(size.height);
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: We're doing the resize here for now because WebCore::Image doesn't yet support resizing/multiple representations
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This makes it so there's effectively only one size of a particular icon in the system at a time. We should move this
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to WebCore::Image at some point.
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!image)
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSImage* nsImage = image->getNSImage();
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!nsImage)
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return nil;
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!NSEqualSizes([nsImage size], size)) {
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [nsImage setScalesWhenResized:YES];
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [nsImage setSize:size];
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return nsImage;
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
700