📄 webicondatabase.mm
字号:
return icon;}- (void)_resetCachedWebPreferences:(NSNotification *)notification{ BOOL privateBrowsingEnabledNow = [[WebPreferences standardPreferences] privateBrowsingEnabled]; iconDatabase()->setPrivateBrowsingEnabled(privateBrowsingEnabledNow);}- (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons{ ASSERT(icons); NSEnumerator *enumerator = [icons keyEnumerator]; NSValue *currentSize, *largestSize=nil; float largestSizeArea=0; while ((currentSize = [enumerator nextObject]) != nil) { NSSize currentSizeSize = [currentSize sizeValue]; float currentSizeArea = currentSizeSize.width * currentSizeSize.height; if(!largestSizeArea || (currentSizeArea > largestSizeArea)){ largestSize = currentSize; largestSizeArea = currentSizeArea; } } return [icons objectForKey:largestSize];}- (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon{ ASSERT(icon); NSMutableDictionary *icons = [NSMutableDictionary dictionary]; NSEnumerator *enumerator = [[icon representations] objectEnumerator]; NSImageRep *rep; while ((rep = [enumerator nextObject]) != nil) { NSSize size = [rep size]; NSImage *subIcon = [[NSImage alloc] initWithSize:size]; [subIcon addRepresentation:rep]; [icons setObject:subIcon forKey:[NSValue valueWithSize:size]]; [subIcon release]; } if([icons count] > 0) return icons; LOG_ERROR("icon has no representations"); return nil;}- (NSImage *)_iconFromDictionary:(NSMutableDictionary *)icons forSize:(NSSize)size cache:(BOOL)cache{ ASSERT(size.width); ASSERT(size.height); NSImage *icon = [icons objectForKey:[NSValue valueWithSize:size]]; if(!icon){ icon = [[[self _largestIconFromDictionary:icons] copy] autorelease]; [self _scaleIcon:icon toSize:size]; if(cache){ [icons setObject:icon forKey:[NSValue valueWithSize:size]]; } } return icon;}- (void)_scaleIcon:(NSImage *)icon toSize:(NSSize)size{ ASSERT(size.width); ASSERT(size.height); #if !LOG_DISABLED double start = CFAbsoluteTimeGetCurrent();#endif [icon setScalesWhenResized:YES]; [icon setSize:size]; #if !LOG_DISABLED double duration = CFAbsoluteTimeGetCurrent() - start; LOG(Timing, "scaling icon took %f seconds.", duration);#endif}// This hashing String->filename algorithm came from WebFileDatabase.m and is what was used in the // WebKit Icon Databasestatic void legacyIconDatabaseFilePathForKey(id key, char *buffer){ const char *s; UInt32 hash1; UInt32 hash2; CFIndex len; CFIndex cnt; s = [[[[key description] lowercaseString] stringByStandardizingPath] UTF8String]; len = strlen(s); // compute first hash hash1 = len; for (cnt = 0; cnt < len; cnt++) { hash1 += (hash1 << 8) + s[cnt]; } hash1 += (hash1 << (len & 31)); // compute second hash hash2 = len; for (cnt = 0; cnt < len; cnt++) { hash2 = (37 * hash2) ^ s[cnt]; }#ifdef __LP64__ snprintf(buffer, UniqueFilePathSize, "%.2u/%.2u/%.10u-%.10u.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);#else snprintf(buffer, UniqueFilePathSize, "%.2lu/%.2lu/%.10lu-%.10lu.cache", ((hash1 & 0xff) >> 4), ((hash2 & 0xff) >> 4), hash1, hash2);#endif}// This method of getting an object from the filesystem is taken from the old // WebKit Icon Databasestatic id objectFromPathForKey(NSString *databasePath, id key){ ASSERT(key); id result = nil; // Use the key->filename hashing the old WebKit IconDatabase used char uniqueKey[UniqueFilePathSize]; legacyIconDatabaseFilePathForKey(key, uniqueKey); // Get the data from this file and setup for the un-archiving NSString *filePath = [[NSString alloc] initWithFormat:@"%@/%s", databasePath, uniqueKey]; NSData *data = [[NSData alloc] initWithContentsOfFile:filePath]; NSUnarchiver *unarchiver = nil; @try { if (data) { unarchiver = [[NSUnarchiver alloc] initForReadingWithData:data]; if (unarchiver) { id fileKey = [unarchiver decodeObject]; if ([fileKey isEqual:key]) { id object = [unarchiver decodeObject]; if (object) { // Decoded objects go away when the unarchiver does, so we need to // retain this so we can return it to our caller. result = [[object retain] autorelease]; LOG(IconDatabase, "read disk cache file - %@", key); } } } } } @catch (NSException *localException) { LOG(IconDatabase, "cannot unarchive cache file - %@", key); result = nil; } [unarchiver release]; [data release]; [filePath release]; return result;}static NSData* iconDataFromPathForIconURL(NSString *databasePath, NSString *iconURLString){ ASSERT(iconURLString); ASSERT(databasePath); NSData *iconData = objectFromPathForKey(databasePath, iconURLString); if ((id)iconData == (id)[NSNull null]) return nil; return iconData;}- (NSString *)_databaseDirectory{ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // Figure out the directory we should be using for the icon.db NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey]; if (!databaseDirectory) { databaseDirectory = WebIconDatabasePath; [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey]; } return [[databaseDirectory stringByExpandingTildeInPath] stringByStandardizingPath];}@end@implementation WebIconDatabasePrivate@end@interface ThreadEnabler : NSObject {}+ (void)enableThreading;- (void)threadEnablingSelector:(id)arg;@end@implementation ThreadEnabler- (void)threadEnablingSelector:(id)arg{ return;}+ (void)enableThreading{ ThreadEnabler *enabler = [[ThreadEnabler alloc] init]; [NSThread detachNewThreadSelector:@selector(threadEnablingSelector:) toTarget:enabler withObject:nil]; [enabler release];}@endbool importToWebCoreFormat(){ // Since this is running on a secondary POSIX thread and Cocoa cannot be used multithreaded unless an NSThread has been detached, // make sure that happens here for all WebKit clients if (![NSThread isMultiThreaded]) [ThreadEnabler enableThreading]; ASSERT([NSThread isMultiThreaded]); #ifndef BUILDING_ON_TIGER // Tell backup software (i.e., Time Machine) to never back up the icon database, because // it's a large file that changes frequently, thus using a lot of backup disk space, and // it's unlikely that many users would be upset about it not being backed up. We do this // here because this code is only executed once for each icon database instance. We could // make this configurable on a per-client basis someday if that seemed useful. // See <rdar://problem/5320208>. CFStringRef databasePath = iconDatabase()->databasePath().createCFString(); if (databasePath) { CFURLRef databasePathURL = CFURLCreateWithFileSystemPath(0, databasePath, kCFURLPOSIXPathStyle, FALSE); CFRelease(databasePath); CSBackupSetItemExcluded(databasePathURL, true, true); CFRelease(databasePathURL); }#endif // Get the directory the old icon database *should* be in NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseImportDirectoryDefaultsKey]; if (!databaseDirectory) databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey]; if (!databaseDirectory) { databaseDirectory = WebIconDatabasePath; [defaults setObject:databaseDirectory forKey:WebIconDatabaseDirectoryDefaultsKey]; } databaseDirectory = [databaseDirectory stringByExpandingTildeInPath]; // With this directory, get the PageURLToIconURL map that was saved to disk NSMutableDictionary *pageURLToIconURL = objectFromPathForKey(databaseDirectory, WebURLToIconURLKey); // If the retrieved object was not a valid NSMutableDictionary, then we have no valid // icons to import if (![pageURLToIconURL isKindOfClass:[NSMutableDictionary class]]) pageURLToIconURL = nil; NSEnumerator *enumerator = [pageURLToIconURL keyEnumerator]; NSString *url, *iconURL; // First, we'll iterate through the PageURL->IconURL map while ((url = [enumerator nextObject]) != nil) { iconURL = [pageURLToIconURL objectForKey:url]; if (!iconURL) continue; iconDatabase()->importIconURLForPageURL(iconURL, url); if (iconDatabase()->shouldStopThreadActivity()) return false; } // Second, we'll get a list of the unique IconURLs we have NSMutableSet *iconsOnDiskWithURLs = [NSMutableSet setWithArray:[pageURLToIconURL allValues]]; enumerator = [iconsOnDiskWithURLs objectEnumerator]; NSData *iconData; // And iterate through them, adding the icon data to the new icon database while ((url = [enumerator nextObject]) != nil) { iconData = iconDataFromPathForIconURL(databaseDirectory, url); if (iconData) iconDatabase()->importIconDataForIconURL(SharedBuffer::wrapNSData(iconData), url); else { // This really *shouldn't* happen, so it'd be good to track down why it might happen in a debug build // however, we do know how to handle it gracefully in release LOG_ERROR("%@ is marked as having an icon on disk, but we couldn't get the data for it", url); iconDatabase()->importIconDataForIconURL(0, url); } if (iconDatabase()->shouldStopThreadActivity()) return false; } // After we're done importing old style icons over to webcore icons, we delete the entire directory hierarchy // for the old icon DB (skipping the new iconDB if it is in the same directory) NSFileManager *fileManager = [NSFileManager defaultManager]; enumerator = [[fileManager contentsOfDirectoryAtPath:databaseDirectory error:NULL] objectEnumerator]; NSString *databaseFilename = iconDatabase()->defaultDatabaseFilename(); BOOL foundIconDB = NO; NSString *file; while ((file = [enumerator nextObject]) != nil) { if ([file caseInsensitiveCompare:databaseFilename] == NSOrderedSame) { foundIconDB = YES; continue; } NSString *filePath = [databaseDirectory stringByAppendingPathComponent:file]; if (![fileManager removeItemAtPath:filePath error:NULL]) LOG_ERROR("Failed to delete %@ from old icon directory", filePath); } // If the new iconDB wasn't in that directory, we can delete the directory itself if (!foundIconDB) rmdir([databaseDirectory fileSystemRepresentation]); return true;}NSImage *webGetNSImage(Image* image, NSSize size){ ASSERT_MAIN_THREAD(); ASSERT(size.width); ASSERT(size.height); // FIXME: We're doing the resize here for now because WebCore::Image doesn't yet support resizing/multiple representations // This makes it so there's effectively only one size of a particular icon in the system at a time. We should move this // to WebCore::Image at some point. if (!image) return nil; NSImage* nsImage = image->getNSImage(); if (!nsImage) return nil; if (!NSEqualSizes([nsImage size], size)) { [nsImage setScalesWhenResized:YES]; [nsImage setSize:size]; } return nsImage;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -