initial import
[vuplus_webkit] / Source / WebKit / mac / Misc / WebIconDatabase.mm
1 /*
2  * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "WebIconDatabaseInternal.h"
30
31 #import "WebIconDatabaseClient.h"
32 #import "WebIconDatabaseDelegate.h"
33 #import "WebKitLogging.h"
34 #import "WebKitNSStringExtras.h"
35 #import "WebNSFileManagerExtras.h"
36 #import "WebNSNotificationCenterExtras.h"
37 #import "WebNSURLExtras.h"
38 #import "WebPreferencesPrivate.h"
39 #import "WebTypesInternal.h"
40 #import <WebCore/IconDatabase.h>
41 #import <WebCore/Image.h>
42 #import <WebCore/IntSize.h>
43 #import <WebCore/SharedBuffer.h>
44 #import <WebCore/ThreadCheck.h>
45 #import <runtime/InitializeThreading.h>
46 #import <wtf/MainThread.h>
47
48 using namespace WebCore;
49
50 NSString * const WebIconDatabaseVersionKey =    @"WebIconDatabaseVersion";
51 NSString * const WebURLToIconURLKey =           @"WebSiteURLToIconURLKey";
52
53 NSString *WebIconDatabaseDidAddIconNotification =          @"WebIconDatabaseDidAddIconNotification";
54 NSString *WebIconNotificationUserInfoURLKey =              @"WebIconNotificationUserInfoURLKey";
55 NSString *WebIconDatabaseDidRemoveAllIconsNotification =   @"WebIconDatabaseDidRemoveAllIconsNotification";
56
57 NSString *WebIconDatabaseDirectoryDefaultsKey = @"WebIconDatabaseDirectoryDefaultsKey";
58 NSString *WebIconDatabaseImportDirectoryDefaultsKey = @"WebIconDatabaseImportDirectoryDefaultsKey";
59 NSString *WebIconDatabaseEnabledDefaultsKey =   @"WebIconDatabaseEnabled";
60
61 NSString *WebIconDatabasePath = @"~/Library/Icons";
62
63 NSSize WebIconSmallSize = {16, 16};
64 NSSize WebIconMediumSize = {32, 32};
65 NSSize WebIconLargeSize = {128, 128};
66
67 #define UniqueFilePathSize (34)
68
69 static WebIconDatabaseClient* defaultClient()
70 {
71 #if ENABLE(ICONDATABASE)
72     static WebIconDatabaseClient* defaultClient = new WebIconDatabaseClient();
73     return defaultClient;
74 #else
75     return 0;
76 #endif
77 }
78
79 @interface WebIconDatabase (WebReallyInternal)
80 - (void)_sendNotificationForURL:(NSString *)URL;
81 - (void)_sendDidRemoveAllIconsNotification;
82 - (NSImage *)_iconForFileURL:(NSString *)fileURL withSize:(NSSize)size;
83 - (void)_resetCachedWebPreferences:(NSNotification *)notification;
84 - (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons;
85 - (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon;
86 - (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache;
87 - (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size;
88 - (NSString *)_databaseDirectory;
89 @end
90
91 @implementation WebIconDatabase
92
93 + (void)initialize
94 {
95     JSC::initializeThreading();
96     WTF::initializeMainThreadToProcessMainThread();
97 }
98
99 + (WebIconDatabase *)sharedIconDatabase
100 {
101     static WebIconDatabase *database = nil;
102     if (!database)
103         database = [[WebIconDatabase alloc] init];
104     return database;
105 }
106
107 - (id)init
108 {
109     self = [super init];
110     if (!self)
111         return nil;
112     WebCoreThreadViolationCheckRoundOne();
113         
114     _private = [[WebIconDatabasePrivate alloc] init];
115     
116     // Check the user defaults and see if the icon database should even be enabled.
117     // Inform the bridge and, if we're disabled, bail from init right here
118     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
119     // <rdar://problem/4741419> - IconDatabase should be disabled by default
120     NSDictionary *initialDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], WebIconDatabaseEnabledDefaultsKey, nil];
121     [defaults registerDefaults:initialDefaults];
122     [initialDefaults release];
123     BOOL enabled = [defaults boolForKey:WebIconDatabaseEnabledDefaultsKey];
124     iconDatabase().setEnabled(enabled);
125     if (enabled)
126         [self _startUpIconDatabase];
127     return self;
128 }
129
130 - (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size cache:(BOOL)cache
131 {
132     ASSERT_MAIN_THREAD();
133     ASSERT(size.width);
134     ASSERT(size.height);
135
136     if (!URL || ![self isEnabled])
137         return [self defaultIconForURL:URL withSize:size];
138
139     // FIXME - <rdar://problem/4697934> - Move the handling of FileURLs to WebCore and implement in ObjC++
140     if ([URL _webkit_isFileURL])
141         return [self _iconForFileURL:URL withSize:size];
142     
143     if (Image* image = iconDatabase().synchronousIconForPageURL(URL, IntSize(size)))
144         if (NSImage *icon = webGetNSImage(image, size))
145             return icon;
146     return [self defaultIconForURL:URL withSize:size];
147 }
148
149 - (NSImage *)iconForURL:(NSString *)URL withSize:(NSSize)size
150 {
151     return [self iconForURL:URL withSize:size cache:YES];
152 }
153
154 - (NSString *)iconURLForURL:(NSString *)URL
155 {
156     if (![self isEnabled])
157         return nil;
158     ASSERT_MAIN_THREAD();
159
160     return iconDatabase().synchronousIconURLForPageURL(URL);
161 }
162
163 - (NSImage *)defaultIconWithSize:(NSSize)size
164 {
165     ASSERT_MAIN_THREAD();
166     ASSERT(size.width);
167     ASSERT(size.height);
168     
169     Image* image = iconDatabase().defaultIcon(IntSize(size));
170     return image ? image->getNSImage() : nil;
171 }
172
173 - (NSImage *)defaultIconForURL:(NSString *)URL withSize:(NSSize)size
174 {
175     if (_private->delegateImplementsDefaultIconForURL)
176         return [_private->delegate webIconDatabase:self defaultIconForURL:URL withSize:size];
177     return [self defaultIconWithSize:size];
178 }
179
180 - (void)retainIconForURL:(NSString *)URL
181 {
182     ASSERT_MAIN_THREAD();
183     ASSERT(URL);
184     if (![self isEnabled])
185         return;
186
187     iconDatabase().retainIconForPageURL(URL);
188 }
189
190 - (void)releaseIconForURL:(NSString *)pageURL
191 {
192     ASSERT_MAIN_THREAD();
193     ASSERT(pageURL);
194     if (![self isEnabled])
195         return;
196
197     iconDatabase().releaseIconForPageURL(pageURL);
198 }
199
200 + (void)delayDatabaseCleanup
201 {
202     ASSERT_MAIN_THREAD();
203
204     IconDatabase::delayDatabaseCleanup();
205 }
206
207 + (void)allowDatabaseCleanup
208 {
209     ASSERT_MAIN_THREAD();
210
211     IconDatabase::allowDatabaseCleanup();
212 }
213
214 - (void)setDelegate:(id)delegate
215 {
216     _private->delegate = delegate;
217     _private->delegateImplementsDefaultIconForURL = [delegate respondsToSelector:@selector(webIconDatabase:defaultIconForURL:withSize:)];
218 }
219
220 - (id)delegate
221 {
222     return _private->delegate;
223 }
224
225 @end
226
227
228 @implementation WebIconDatabase (WebPendingPublic)
229
230 - (BOOL)isEnabled
231 {
232     return iconDatabase().isEnabled();
233 }
234
235 - (void)setEnabled:(BOOL)flag
236 {
237     BOOL currentlyEnabled = [self isEnabled];
238     if (currentlyEnabled && !flag) {
239         iconDatabase().setEnabled(false);
240         [self _shutDownIconDatabase];
241     } else if (!currentlyEnabled && flag) {
242         iconDatabase().setEnabled(true);
243         [self _startUpIconDatabase];
244     }
245 }
246
247 - (void)removeAllIcons
248 {
249     ASSERT_MAIN_THREAD();
250     if (![self isEnabled])
251         return;
252
253     // Via the IconDatabaseClient interface, removeAllIcons() will send the WebIconDatabaseDidRemoveAllIconsNotification
254     iconDatabase().removeAllIcons();
255 }
256
257 @end
258
259 @implementation WebIconDatabase (WebPrivate)
260
261 + (void)_checkIntegrityBeforeOpening
262 {
263     IconDatabase::checkIntegrityBeforeOpening();
264 }
265
266 @end
267
268 @implementation WebIconDatabase (WebInternal)
269
270 - (void)_sendNotificationForURL:(NSString *)URL
271 {
272     ASSERT(URL);
273     
274     NSDictionary *userInfo = [NSDictionary dictionaryWithObject:URL
275                                                          forKey:WebIconNotificationUserInfoURLKey];
276                                                          
277     [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidAddIconNotification
278                                                         object:self
279                                                       userInfo:userInfo];
280 }
281
282 - (void)_sendDidRemoveAllIconsNotification
283 {
284     [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:WebIconDatabaseDidRemoveAllIconsNotification
285                                                         object:self
286                                                       userInfo:nil];
287 }
288
289 - (void)_startUpIconDatabase
290 {
291     iconDatabase().setClient(defaultClient());
292     
293     // Figure out the directory we should be using for the icon.db
294     NSString *databaseDirectory = [self _databaseDirectory];
295     
296     // Rename legacy icon database files to the new icon database name
297     BOOL isDirectory = NO;
298     NSString *legacyDB = [databaseDirectory stringByAppendingPathComponent:@"icon.db"];
299     NSFileManager *defaultManager = [NSFileManager defaultManager];
300     if ([defaultManager fileExistsAtPath:legacyDB isDirectory:&isDirectory] && !isDirectory) {
301         NSString *newDB = [databaseDirectory stringByAppendingPathComponent:IconDatabase::defaultDatabaseFilename()];
302         if (![defaultManager fileExistsAtPath:newDB])
303             rename([legacyDB fileSystemRepresentation], [newDB fileSystemRepresentation]);
304     }
305     
306     // Set the private browsing pref then open the WebCore icon database
307     iconDatabase().setPrivateBrowsingEnabled([[WebPreferences standardPreferences] privateBrowsingEnabled]);
308     if (!iconDatabase().open(databaseDirectory, IconDatabase::defaultDatabaseFilename()))
309         LOG_ERROR("Unable to open icon database");
310     
311     // Register for important notifications
312     [[NSNotificationCenter defaultCenter] addObserver:self
313                                              selector:@selector(_applicationWillTerminate:)
314                                                  name:NSApplicationWillTerminateNotification
315                                                object:NSApp];
316     [[NSNotificationCenter defaultCenter] addObserver:self
317                                              selector:@selector(_resetCachedWebPreferences:)
318                                                  name:WebPreferencesChangedInternalNotification
319                                                object:nil];
320 }
321
322 - (void)_shutDownIconDatabase
323 {
324     // Unregister for important notifications
325     [[NSNotificationCenter defaultCenter] removeObserver:self
326                                                     name:NSApplicationWillTerminateNotification
327                                                   object:NSApp];
328     [[NSNotificationCenter defaultCenter] removeObserver:self
329                                                     name:WebPreferencesChangedInternalNotification
330                                                   object:nil];
331 }
332
333 - (void)_applicationWillTerminate:(NSNotification *)notification
334 {
335     iconDatabase().close();
336 }
337
338 - (NSImage *)_iconForFileURL:(NSString *)file withSize:(NSSize)size
339 {
340     ASSERT_MAIN_THREAD();
341     ASSERT(size.width);
342     ASSERT(size.height);
343
344     NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
345     NSString *path = [[NSURL _web_URLWithDataAsString:file] path];
346     NSString *suffix = [path pathExtension];
347     NSImage *icon = nil;
348     
349     if ([suffix _webkit_isCaseInsensitiveEqualToString:@"htm"] || [suffix _webkit_isCaseInsensitiveEqualToString:@"html"]) {
350         if (!_private->htmlIcons) {
351             icon = [workspace iconForFileType:@"html"];
352             _private->htmlIcons = [[self _iconsBySplittingRepresentationsOfIcon:icon] retain];
353         }
354         icon = [self _iconFromDictionary:_private->htmlIcons forSize:size cache:YES];
355     } else {
356         if (!path || ![path isAbsolutePath]) {
357             // Return the generic icon when there is no path.
358             icon = [workspace iconForFileType:NSFileTypeForHFSTypeCode(kGenericDocumentIcon)];
359         } else {
360             icon = [workspace iconForFile:path];
361         }
362         [self _scaleIcon:icon toSize:size];
363     }
364
365     return icon;
366 }
367
368 - (void)_resetCachedWebPreferences:(NSNotification *)notification
369 {
370     BOOL privateBrowsingEnabledNow = [[WebPreferences standardPreferences] privateBrowsingEnabled];
371     iconDatabase().setPrivateBrowsingEnabled(privateBrowsingEnabledNow);
372 }
373
374 - (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons
375 {
376     ASSERT(icons);
377     
378     NSEnumerator *enumerator = [icons keyEnumerator];
379     NSValue *currentSize, *largestSize=nil;
380     float largestSizeArea=0;
381
382     while ((currentSize = [enumerator nextObject]) != nil) {
383         NSSize currentSizeSize = [currentSize sizeValue];
384         float currentSizeArea = currentSizeSize.width * currentSizeSize.height;
385         if(!largestSizeArea || (currentSizeArea > largestSizeArea)){
386             largestSize = currentSize;
387             largestSizeArea = currentSizeArea;
388         }
389     }
390
391     return [icons objectForKey:largestSize];
392 }
393
394 - (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon
395 {
396     ASSERT(icon);
397
398     NSMutableDictionary *icons = [NSMutableDictionary dictionary];
399     NSEnumerator *enumerator = [[icon representations] objectEnumerator];
400     NSImageRep *rep;
401
402     while ((rep = [enumerator nextObject]) != nil) {
403         NSSize size = [rep size];
404         NSImage *subIcon = [[NSImage alloc] initWithSize:size];
405         [subIcon addRepresentation:rep];
406         [icons setObject:subIcon forKey:[NSValue valueWithSize:size]];
407         [subIcon release];
408     }
409
410     if([icons count] > 0)
411         return icons;
412
413     LOG_ERROR("icon has no representations");
414     
415     return nil;
416 }
417
418 - (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache
419 {
420     ASSERT(size.width);
421     ASSERT(size.height);
422
423     NSImage *icon = [icons objectForKey:[NSValue valueWithSize:size]];
424
425     if(!icon){
426         icon = [[[self _largestIconFromDictionary:icons] copy] autorelease];
427         [self _scaleIcon:icon toSize:size];
428
429         if(cache){
430             [icons setObject:icon forKey:[NSValue valueWithSize:size]];
431         }
432     }
433
434     return icon;
435 }
436
437 - (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size
438 {
439     ASSERT(size.width);
440     ASSERT(size.height);
441     
442 #if !LOG_DISABLED        
443     double start = CFAbsoluteTimeGetCurrent();
444 #endif
445     
446     [icon setScalesWhenResized:YES];
447     [icon setSize:size];
448     
449 #if !LOG_DISABLED
450     double duration = CFAbsoluteTimeGetCurrent() - start;
451     LOG(Timing, "scaling icon took %f seconds.", duration);
452 #endif
453 }
454
455 // This hashing String->filename algorithm came from WebFileDatabase.m and is what was used in the 
456 // WebKit Icon Database
457 static void legacyIconDatabaseFilePathForKey(id key, char *buffer)
458 {
459     const char *s;
460     UInt32 hash1;
461     UInt32 hash2;
462     CFIndex len;
463     CFIndex cnt;
464     
465     s = [[[[key description] lowercaseString] stringByStandardizingPath] UTF8String];
466     len = strlen(s);
467
468     // compute first hash    
469     hash1 = len;
470     for (cnt = 0; cnt < len; cnt++) {
471         hash1 += (hash1 << 8) + s[cnt];
472     }
473     hash1 += (hash1 << (len & 31));
474
475     // compute second hash    
476     hash2 = len;
477     for (cnt = 0; cnt < len; cnt++) {
478         hash2 = (37 * hash2) ^ s[cnt];
479     }
480
481 #ifdef __LP64__
482     snprintf(buffer, UniqueFilePathSize, "%.2u/%.2u/%.10u-%.10u.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
483 #else
484     snprintf(buffer, UniqueFilePathSize, "%.2lu/%.2lu/%.10lu-%.10lu.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);
485 #endif
486 }
487
488 // This method of getting an object from the filesystem is taken from the old 
489 // WebKit Icon Database
490 static id objectFromPathForKey(NSString *databasePath, id key)
491 {
492     ASSERT(key);
493     id result = nil;
494
495     // Use the key->filename hashing the old WebKit IconDatabase used
496     char uniqueKey[UniqueFilePathSize];    
497     legacyIconDatabaseFilePathForKey(key, uniqueKey);
498     
499     // Get the data from this file and setup for the un-archiving
500     NSString *filePath = [[NSString alloc] initWithFormat:@"%@/%s", databasePath, uniqueKey];
501     NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
502     NSUnarchiver *unarchiver = nil;
503     
504     @try {
505         if (data) {
506             unarchiver = [[NSUnarchiver alloc] initForReadingWithData:data];
507             if (unarchiver) {
508                 id fileKey = [unarchiver decodeObject];
509                 if ([fileKey isEqual:key]) {
510                     id object = [unarchiver decodeObject];
511                     if (object) {
512                         // Decoded objects go away when the unarchiver does, so we need to
513                         // retain this so we can return it to our caller.
514                         result = [[object retain] autorelease];
515                         LOG(IconDatabase, "read disk cache file - %@", key);
516                     }
517                 }
518             }
519         }
520     } @catch (NSException *localException) {
521         LOG(IconDatabase, "cannot unarchive cache file - %@", key);
522         result = nil;
523     }
524
525     [unarchiver release];
526     [data release];
527     [filePath release];
528     
529     return result;
530 }
531
532 static NSData* iconDataFromPathForIconURL(NSString *databasePath, NSString *iconURLString)
533 {
534     ASSERT(iconURLString);
535     ASSERT(databasePath);
536     
537     NSData *iconData = objectFromPathForKey(databasePath, iconURLString);
538     
539     if ((id)iconData == (id)[NSNull null]) 
540         return nil;
541         
542     return iconData;
543 }
544
545 - (NSString *)_databaseDirectory
546 {
547     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
548
549     // Figure out the directory we should be using for the icon.db
550     NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
551     if (!databaseDirectory) {
552         databaseDirectory = WebIconDatabasePath;
553         [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
554     }
555     
556     return [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];
557 }
558
559 @end
560
561 @implementation WebIconDatabasePrivate
562 @end
563
564 @interface ThreadEnabler : NSObject {
565 }
566 + (void)enableThreading;
567
568 - (void)threadEnablingSelector:(id)arg;
569 @end
570
571 @implementation ThreadEnabler
572
573 - (void)threadEnablingSelector:(id)arg
574 {
575     return;
576 }
577
578 + (void)enableThreading
579 {
580     ThreadEnabler *enabler = [[ThreadEnabler alloc] init];
581     [NSThread detachNewThreadSelector:@selector(threadEnablingSelector:) toTarget:enabler withObject:nil];
582     [enabler release];
583 }
584
585 @end
586
587 bool importToWebCoreFormat()
588 {
589     // Since this is running on a secondary POSIX thread and Cocoa cannot be used multithreaded unless an NSThread has been detached,
590     // make sure that happens here for all WebKit clients
591     if (![NSThread isMultiThreaded])
592         [ThreadEnabler enableThreading];
593     ASSERT([NSThread isMultiThreaded]);    
594     
595     // Get the directory the old icon database *should* be in
596     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
597     NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseImportDirectoryDefaultsKey];
598     
599     if (!databaseDirectory)
600         databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
601         
602     if (!databaseDirectory) {
603         databaseDirectory = WebIconDatabasePath;
604         [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey];
605     }
606     databaseDirectory = [databaseDirectory stringByExpandingTildeInPath];
607
608     // With this directory, get the PageURLToIconURL map that was saved to disk
609     NSMutableDictionary *pageURLToIconURL = objectFromPathForKey(databaseDirectory, WebURLToIconURLKey);
610
611     // If the retrieved object was not a valid NSMutableDictionary, then we have no valid
612     // icons to import
613     if (![pageURLToIconURL isKindOfClass:[NSMutableDictionary class]])
614         pageURLToIconURL = nil;
615     
616     if (!pageURLToIconURL) {
617         // We found no Safari-2-style icon database. Bail out immediately and do not delete everything
618         // in whatever directory we ended up looking in! Return true so we won't bother to check again.
619         // FIXME: We can probably delete all of the code to convert Safari-2-style icon databases now.
620         return true;
621     }
622     
623     NSEnumerator *enumerator = [pageURLToIconURL keyEnumerator];
624     NSString *url, *iconURL;
625     
626     // First, we'll iterate through the PageURL->IconURL map
627     while ((url = [enumerator nextObject]) != nil) {
628         iconURL = [pageURLToIconURL objectForKey:url];
629         if (!iconURL)
630             continue;
631         iconDatabase().importIconURLForPageURL(iconURL, url);
632         if (iconDatabase().shouldStopThreadActivity())
633             return false;
634     }    
635
636     // Second, we'll get a list of the unique IconURLs we have
637     NSMutableSet *iconsOnDiskWithURLs = [NSMutableSet setWithArray:[pageURLToIconURL allValues]];
638     enumerator = [iconsOnDiskWithURLs objectEnumerator];
639     NSData *iconData;
640     
641     // And iterate through them, adding the icon data to the new icon database
642     while ((url = [enumerator nextObject]) != nil) {
643         iconData = iconDataFromPathForIconURL(databaseDirectory, url);
644         if (iconData)
645             iconDatabase().importIconDataForIconURL(SharedBuffer::wrapNSData(iconData), url);
646         else {
647             // This really *shouldn't* happen, so it'd be good to track down why it might happen in a debug build
648             // however, we do know how to handle it gracefully in release
649             LOG_ERROR("%@ is marked as having an icon on disk, but we couldn't get the data for it", url);
650             iconDatabase().importIconDataForIconURL(0, url);
651         }
652         if (iconDatabase().shouldStopThreadActivity())
653             return false;
654     }
655     
656     // After we're done importing old style icons over to webcore icons, we delete the entire directory hierarchy 
657     // for the old icon DB (skipping the new iconDB if it is in the same directory)
658     NSFileManager *fileManager = [NSFileManager defaultManager];
659     enumerator = [[fileManager contentsOfDirectoryAtPath:databaseDirectory error:NULL] objectEnumerator];
660
661     NSString *databaseFilename = IconDatabase::defaultDatabaseFilename();
662
663     BOOL foundIconDB = NO;
664     NSString *file;
665     while ((file = [enumerator nextObject]) != nil) {
666         if ([file caseInsensitiveCompare:databaseFilename] == NSOrderedSame) {
667             foundIconDB = YES;
668             continue;
669         }
670         NSString *filePath = [databaseDirectory stringByAppendingPathComponent:file];
671         if (![fileManager removeItemAtPath:filePath error:NULL])
672             LOG_ERROR("Failed to delete %@ from old icon directory", filePath);
673     }
674     
675     // If the new iconDB wasn't in that directory, we can delete the directory itself
676     if (!foundIconDB)
677         rmdir([databaseDirectory fileSystemRepresentation]);
678     
679     return true;
680 }
681
682 NSImage *webGetNSImage(Image* image, NSSize size)
683 {
684     ASSERT_MAIN_THREAD();
685     ASSERT(size.width);
686     ASSERT(size.height);
687
688     // FIXME: We're doing the resize here for now because WebCore::Image doesn't yet support resizing/multiple representations
689     // This makes it so there's effectively only one size of a particular icon in the system at a time. We should move this
690     // to WebCore::Image at some point.
691     if (!image)
692         return nil;
693     NSImage* nsImage = image->getNSImage();
694     if (!nsImage)
695         return nil;
696     if (!NSEqualSizes([nsImage size], size)) {
697         [nsImage setScalesWhenResized:YES];
698         [nsImage setSize:size];
699     }
700     return nsImage;
701 }