webengine/osswebengine/WebKit/WebView/WebPreferences.m
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/WebView/WebPreferences.m	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,957 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebPreferencesPrivate.h"
+#import "WebPreferenceKeysPrivate.h"
+
+#import "WebKitLogging.h"
+#import "WebKitNSStringExtras.h"
+#import "WebKitSystemBits.h"
+#import "WebKitSystemInterface.h"
+#import "WebKitVersionChecks.h"
+#import "WebNSDictionaryExtras.h"
+#import "WebNSURLExtras.h"
+
+NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
+NSString *WebPreferencesRemovedNotification = @"WebPreferencesRemovedNotification";
+
+#define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
+
+enum { WebPreferencesVersion = 1 };
+
+static WebPreferences *_standardPreferences;
+static NSMutableDictionary *webPreferencesInstances;
+
+static bool contains(const char* const array[], int count, const char* item)
+{
+    if (!item)
+        return false;
+
+    for (int i = 0; i < count; i++)
+        if (!strcasecmp(array[i], item))
+            return true;
+    return false;
+}
+
+static WebCacheModel cacheModelForMainBundle(void)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    // Apps that probably need the small setting
+    static const char* const documentViewerIDs[] = {
+        "Microsoft/com.microsoft.Messenger",
+        "com.adiumX.adiumX", 
+        "com.alientechnology.Proteus",
+        "com.apple.Dashcode",
+        "com.apple.iChat", 
+        "com.barebones.bbedit", 
+        "com.barebones.textwrangler",
+        "com.barebones.yojimbo",
+        "com.equinux.iSale4",
+        "com.growl.growlframework",
+        "com.intrarts.PandoraMan",
+        "com.karelia.Sandvox",
+        "com.macromates.textmate",
+        "com.realmacsoftware.rapidweaverpro",
+        "com.red-sweater.marsedit",
+        "com.yahoo.messenger3",
+        "de.codingmonkeys.SubEthaEdit",
+        "fi.karppinen.Pyro",
+        "info.colloquy", 
+        "kungfoo.tv.ecto",
+    };
+
+    // Apps that probably need the medium setting
+    static const char* const documentBrowserIDs[] = {
+        "com.apple.Dictionary",
+        "com.apple.Xcode",
+        "com.apple.dashboard.client", 
+        "com.apple.helpviewer",
+        "com.culturedcode.xyle",
+        "com.macrabbit.CSSEdit",
+        "com.panic.Coda",
+        "com.ranchero.NetNewsWire",
+        "com.thinkmac.NewsLife",
+        "org.xlife.NewsFire",
+        "uk.co.opencommunity.vienna2",
+    };
+
+    // Apps that probably need the large setting
+    static const char* const primaryWebBrowserIDs[] = {
+        "com.app4mac.KidsBrowser"
+        "com.app4mac.wKiosk",
+        "com.freeverse.bumpercar",
+        "com.omnigroup.OmniWeb5",
+        "com.sunrisebrowser.Sunrise",
+        "net.hmdt-web.Shiira",
+    };
+
+    WebCacheModel cacheModel;
+
+    const char* bundleID = [[[NSBundle mainBundle] bundleIdentifier] UTF8String];
+    if (contains(documentViewerIDs, sizeof(documentViewerIDs) / sizeof(documentViewerIDs[0]), bundleID))
+        cacheModel = WebCacheModelDocumentViewer;
+    else if (contains(documentBrowserIDs, sizeof(documentBrowserIDs) / sizeof(documentBrowserIDs[0]), bundleID))
+        cacheModel = WebCacheModelDocumentBrowser;
+    else if (contains(primaryWebBrowserIDs, sizeof(primaryWebBrowserIDs) / sizeof(primaryWebBrowserIDs[0]), bundleID))
+        cacheModel = WebCacheModelPrimaryWebBrowser;
+    else {
+        bool isLegacyApp = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CACHE_MODEL_API);
+        if (isLegacyApp)
+            cacheModel = WebCacheModelDocumentBrowser; // To avoid regressions in apps that depended on old WebKit's large cache.
+        else
+            cacheModel = WebCacheModelDocumentViewer; // To save memory.
+    }
+
+    [pool drain];
+
+    return cacheModel;
+}
+
+@interface WebPreferencesPrivate : NSObject
+{
+@public
+    NSMutableDictionary *values;
+    NSString *identifier;
+    NSString *IBCreatorID;
+    BOOL autosaves;
+    BOOL automaticallyDetectsCacheModel;
+    unsigned numWebViews;
+}
+@end
+
+@implementation WebPreferencesPrivate
+- (void)dealloc
+{
+    [values release];
+    [identifier release];
+    [IBCreatorID release];
+    [super dealloc];
+}
+@end
+
+@interface WebPreferences (WebInternal)
++ (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key;
++ (NSString *)_IBCreatorID;
+@end
+
+@interface WebPreferences (WebForwardDeclarations)
+// This pseudo-category is needed so these methods can be used from within other category implementations
+// without being in the public header file.
+- (BOOL)_boolValueForKey:(NSString *)key;
+- (void)_setBoolValue:(BOOL)value forKey:(NSString *)key;
+- (int)_integerValueForKey:(NSString *)key;
+- (void)_setIntegerValue:(int)value forKey:(NSString *)key;
+- (float)_floatValueForKey:(NSString *)key;
+- (void)_setFloatValue:(float)value forKey:(NSString *)key;
+@end
+
+@implementation WebPreferences
+
+- init
+{
+    // Create fake identifier
+    static int instanceCount = 1;
+    NSString *fakeIdentifier;
+    
+    // At least ensure that identifier hasn't been already used.  
+    fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
+    while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){
+        fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
+    }
+    
+    return [self initWithIdentifier:fakeIdentifier];
+}
+
+- (id)initWithIdentifier:(NSString *)anIdentifier
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _private = [[WebPreferencesPrivate alloc] init];
+    _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
+
+    WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier];
+    if (instance){
+        [self release];
+        return [instance retain];
+    }
+
+    _private->values = [[NSMutableDictionary alloc] init];
+    _private->identifier = [anIdentifier copy];
+    _private->automaticallyDetectsCacheModel = YES;
+
+    [[self class] _setInstance:self forIdentifier:_private->identifier];
+
+    [self _postPreferencesChangesNotification];
+
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)decoder
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _private = [[WebPreferencesPrivate alloc] init];
+    _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
+    _private->automaticallyDetectsCacheModel = YES;
+
+    @try {
+        id identifier = nil;
+        id values = nil;
+        if ([decoder allowsKeyedCoding]) {
+            identifier = [decoder decodeObjectForKey:@"Identifier"];
+            values = [decoder decodeObjectForKey:@"Values"];
+        } else {
+            int version;
+            [decoder decodeValueOfObjCType:@encode(int) at:&version];
+            if (version == 1) {
+                identifier = [decoder decodeObject];
+                values = [decoder decodeObject];
+            }
+        }
+
+        if ([identifier isKindOfClass:[NSString class]])
+            _private->identifier = [identifier copy];
+        if ([values isKindOfClass:[NSDictionary class]])
+            _private->values = [values mutableCopy]; // ensure dictionary is mutable
+
+        LOG(Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
+    } @catch(id) {
+        [self release];
+        return nil;
+    }
+
+    // If we load a nib multiple times, or have instances in multiple
+    // nibs with the same name, the first guy up wins.
+    WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier];
+    if (instance) {
+        [self release];
+        self = [instance retain];
+    } else {
+        [[self class] _setInstance:self forIdentifier:_private->identifier];
+    }
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)encoder
+{
+    if ([encoder allowsKeyedCoding]){
+        [encoder encodeObject:_private->identifier forKey:@"Identifier"];
+        [encoder encodeObject:_private->values forKey:@"Values"];
+        LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
+    }
+    else {
+        int version = WebPreferencesVersion;
+        [encoder encodeValueOfObjCType:@encode(int) at:&version];
+        [encoder encodeObject:_private->identifier];
+        [encoder encodeObject:_private->values];
+    }
+}
+
++ (WebPreferences *)standardPreferences
+{
+    if (_standardPreferences == nil) {
+        _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil];
+        [_standardPreferences setAutosaves:YES];
+    }
+
+    return _standardPreferences;
+}
+
+// if we ever have more than one WebPreferences object, this would move to init
++ (void)initialize
+{
+    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
+        @"Times",                       WebKitStandardFontPreferenceKey,
+        @"Courier",                     WebKitFixedFontPreferenceKey,
+        @"Times",                       WebKitSerifFontPreferenceKey,
+        @"Helvetica",                   WebKitSansSerifFontPreferenceKey,
+        @"Apple Chancery",              WebKitCursiveFontPreferenceKey,
+        @"Papyrus",                     WebKitFantasyFontPreferenceKey,
+        @"1",                           WebKitMinimumFontSizePreferenceKey,
+        @"9",                           WebKitMinimumLogicalFontSizePreferenceKey, 
+        @"16",                          WebKitDefaultFontSizePreferenceKey,
+        @"13",                          WebKitDefaultFixedFontSizePreferenceKey,
+        @"ISO-8859-1",                  WebKitDefaultTextEncodingNamePreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitUserStyleSheetEnabledPreferenceKey,
+        @"",                            WebKitUserStyleSheetLocationPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitShouldPrintBackgroundsPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitTextAreasAreResizablePreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitShrinksStandaloneImagesToFit,
+        [NSNumber numberWithBool:YES],  WebKitJavaEnabledPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitJavaScriptEnabledPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitPluginsEnabledPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImagesPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImageLoopingPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitDisplayImagesKey,
+        @"1800",                        WebKitBackForwardCacheExpirationIntervalKey,
+        [NSNumber numberWithBool:NO],   WebKitTabToLinksPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitPrivateBrowsingEnabledPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitRespectStandardStyleKeyEquivalentsPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitShowsURLsInToolTipsPreferenceKey,
+        @"1",                           WebKitPDFDisplayModePreferenceKey,
+        @"0",                           WebKitPDFScaleFactorPreferenceKey,
+        @"1",                           WebKitUsePDFPreviewViewPreferenceKey,
+        @"0",                           WebKitUseSiteSpecificSpoofingPreferenceKey,
+        [NSNumber numberWithInt:WebKitEditableLinkDefaultBehavior], WebKitEditableLinkBehaviorPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitDOMPasteAllowedPreferenceKey,
+        [NSNumber numberWithBool:YES],  WebKitUsesPageCachePreferenceKey,
+        [NSNumber numberWithInt:cacheModelForMainBundle()], WebKitCacheModelPreferenceKey,
+        nil];
+
+    // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above
+    ASSERT(kPDFDisplaySinglePageContinuous == 1);
+    [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+}
+
+- (void)dealloc
+{
+    [_private release];
+    [super dealloc];
+}
+
+- (NSString *)identifier
+{
+    return _private->identifier;
+}
+
+- (id)_valueForKey:(NSString *)key
+{
+    NSString *_key = KEY(key);
+    id o = [_private->values objectForKey:_key];
+    if (o)
+        return o;
+    o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
+    if (!o && key != _key)
+        o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
+    return o;
+}
+
+- (NSString *)_stringValueForKey:(NSString *)key
+{
+    id s = [self _valueForKey:key];
+    return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
+}
+
+- (void)_setStringValue:(NSString *)value forKey:(NSString *)key
+{
+    if ([[self _stringValueForKey:key] isEqualToString:value])
+        return;
+    NSString *_key = KEY(key);
+    [_private->values setObject:value forKey:_key];
+    if (_private->autosaves)
+        [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
+    [self _postPreferencesChangesNotification];
+}
+
+- (int)_integerValueForKey:(NSString *)key
+{
+    id o = [self _valueForKey:key];
+    return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
+}
+
+- (void)_setIntegerValue:(int)value forKey:(NSString *)key
+{
+    if ([self _integerValueForKey:key] == value)
+        return;
+    NSString *_key = KEY(key);
+    [_private->values _webkit_setInt:value forKey:_key];
+    if (_private->autosaves)
+        [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
+    [self _postPreferencesChangesNotification];
+}
+
+- (float)_floatValueForKey:(NSString *)key
+{
+    id o = [self _valueForKey:key];
+    return [o respondsToSelector:@selector(floatValue)] ? [o floatValue] : 0.0f;
+}
+
+- (void)_setFloatValue:(float)value forKey:(NSString *)key
+{
+    if ([self _floatValueForKey:key] == value)
+        return;
+    NSString *_key = KEY(key);
+    [_private->values _webkit_setFloat:value forKey:_key];
+    if (_private->autosaves)
+        [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key];
+    [self _postPreferencesChangesNotification];
+}
+
+- (BOOL)_boolValueForKey:(NSString *)key
+{
+    return [self _integerValueForKey:key] != 0;
+}
+
+- (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
+{
+    if ([self _boolValueForKey:key] == value)
+        return;
+    NSString *_key = KEY(key);
+    [_private->values _webkit_setBool:value forKey:_key];
+    if (_private->autosaves)
+        [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
+    [self _postPreferencesChangesNotification];
+}
+
+- (NSString *)standardFontFamily
+{
+    return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
+}
+
+- (void)setStandardFontFamily:(NSString *)family
+{
+    [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
+}
+
+- (NSString *)fixedFontFamily
+{
+    return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
+}
+
+- (void)setFixedFontFamily:(NSString *)family
+{
+    [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
+}
+
+- (NSString *)serifFontFamily
+{
+    return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
+}
+
+- (void)setSerifFontFamily:(NSString *)family 
+{
+    [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
+}
+
+- (NSString *)sansSerifFontFamily
+{
+    return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
+}
+
+- (void)setSansSerifFontFamily:(NSString *)family
+{
+    [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
+}
+
+- (NSString *)cursiveFontFamily
+{
+    return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
+}
+
+- (void)setCursiveFontFamily:(NSString *)family
+{
+    [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
+}
+
+- (NSString *)fantasyFontFamily
+{
+    return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
+}
+
+- (void)setFantasyFontFamily:(NSString *)family
+{
+    [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
+}
+
+- (int)defaultFontSize
+{
+    return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
+}
+
+- (void)setDefaultFontSize:(int)size
+{
+    [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
+}
+
+- (int)defaultFixedFontSize
+{
+    return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
+}
+
+- (void)setDefaultFixedFontSize:(int)size
+{
+    [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
+}
+
+- (int)minimumFontSize
+{
+    return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
+}
+
+- (void)setMinimumFontSize:(int)size
+{
+    [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
+}
+
+- (int)minimumLogicalFontSize
+{
+  return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
+}
+
+- (void)setMinimumLogicalFontSize:(int)size
+{
+  [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
+}
+
+- (NSString *)defaultTextEncodingName
+{
+    return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
+}
+
+- (void)setDefaultTextEncodingName:(NSString *)encoding
+{
+    [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
+}
+
+- (BOOL)userStyleSheetEnabled
+{
+    return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
+}
+
+- (void)setUserStyleSheetEnabled:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
+}
+
+- (NSURL *)userStyleSheetLocation
+{
+    NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
+    
+    if ([locationString _webkit_looksLikeAbsoluteURL]) {
+        return [NSURL _web_URLWithDataAsString:locationString];
+    } else {
+        locationString = [locationString stringByExpandingTildeInPath];
+        return [NSURL fileURLWithPath:locationString];
+    }
+}
+
+- (void)setUserStyleSheetLocation:(NSURL *)URL
+{
+    NSString *locationString;
+    
+    if ([URL isFileURL]) {
+        locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
+    } else {
+        locationString = [URL _web_originalDataAsString];
+    }
+    
+    [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
+}
+
+- (BOOL)shouldPrintBackgrounds
+{
+    return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
+}
+
+- (void)setShouldPrintBackgrounds:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
+}
+
+- (BOOL)isJavaEnabled
+{
+    return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
+}
+
+- (void)setJavaEnabled:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
+}
+
+- (BOOL)isJavaScriptEnabled
+{
+    return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
+}
+
+- (void)setJavaScriptEnabled:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
+}
+
+- (BOOL)javaScriptCanOpenWindowsAutomatically
+{
+    return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
+}
+
+- (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
+}
+
+- (BOOL)arePlugInsEnabled
+{
+    return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
+}
+
+- (void)setPlugInsEnabled:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
+}
+
+- (BOOL)allowsAnimatedImages
+{
+    return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
+}
+
+- (void)setAllowsAnimatedImages:(BOOL)flag;
+{
+    [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
+}
+
+- (BOOL)allowsAnimatedImageLooping
+{
+    return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
+}
+
+- (void)setAllowsAnimatedImageLooping: (BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
+}
+
+- (void)setLoadsImagesAutomatically: (BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
+}
+
+- (BOOL)loadsImagesAutomatically
+{
+    return [self _boolValueForKey: WebKitDisplayImagesKey];
+}
+
+- (void)setAutosaves:(BOOL)flag;
+{
+    _private->autosaves = flag;
+}
+
+- (BOOL)autosaves
+{
+    return _private->autosaves;
+}
+
+- (void)setTabsToLinks:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
+}
+
+- (BOOL)tabsToLinks
+{
+    return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
+}
+
+- (void)setPrivateBrowsingEnabled:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
+}
+
+- (BOOL)privateBrowsingEnabled
+{
+    return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
+}
+
+- (void)setUsesPageCache:(BOOL)usesPageCache
+{
+    [self _setBoolValue:usesPageCache forKey:WebKitUsesPageCachePreferenceKey];
+}
+
+- (BOOL)usesPageCache
+{
+    return [self _boolValueForKey:WebKitUsesPageCachePreferenceKey];
+}
+
+- (void)setCacheModel:(WebCacheModel)cacheModel
+{
+    [self _setIntegerValue:cacheModel forKey:WebKitCacheModelPreferenceKey];
+    [self setAutomaticallyDetectsCacheModel:NO];
+}
+
+- (WebCacheModel)cacheModel
+{
+    return [self _integerValueForKey:WebKitCacheModelPreferenceKey];
+}
+
+@end
+
+@implementation WebPreferences (WebPrivate)
+
+- (BOOL)respectStandardStyleKeyEquivalents
+{
+    return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
+}
+
+- (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
+}
+
+- (BOOL)showsURLsInToolTips
+{
+    return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey];
+}
+
+- (void)setShowsURLsInToolTips:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey];
+}
+
+- (BOOL)textAreasAreResizable
+{
+    return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey];
+}
+
+- (void)setTextAreasAreResizable:(BOOL)flag
+{
+    [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey];
+}
+
+- (BOOL)shrinksStandaloneImagesToFit
+{
+    return [self _boolValueForKey:WebKitShrinksStandaloneImagesToFit];
+}
+
+- (void)setShrinksStandaloneImagesToFit:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitShrinksStandaloneImagesToFit];
+}
+
+- (BOOL)automaticallyDetectsCacheModel
+{
+    return _private->automaticallyDetectsCacheModel;
+}
+
+- (void)setAutomaticallyDetectsCacheModel:(BOOL)automaticallyDetectsCacheModel
+{
+    _private->automaticallyDetectsCacheModel = automaticallyDetectsCacheModel;
+}
+
+- (NSTimeInterval)_backForwardCacheExpirationInterval
+{
+    // FIXME: There's probably no good reason to read from the standard user defaults instead of self.
+    return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
+}
+
+- (float)PDFScaleFactor
+{
+    return [self _floatValueForKey:WebKitPDFScaleFactorPreferenceKey];
+}
+
+- (void)setPDFScaleFactor:(float)factor
+{
+    [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey];
+}
+
+- (PDFDisplayMode)PDFDisplayMode;
+{
+    PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey];
+    if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) {
+        // protect against new modes from future versions of OS X stored in defaults
+        value = kPDFDisplaySinglePageContinuous;
+    }
+    return value;
+}
+
+- (void)setPDFDisplayMode:(PDFDisplayMode)mode
+{
+    [self _setIntegerValue:mode forKey:WebKitPDFDisplayModePreferenceKey];
+}
+
+- (BOOL)_usePDFPreviewView
+{
+    return [self _boolValueForKey:WebKitUsePDFPreviewViewPreferenceKey];
+}
+
+- (void)_setUsePDFPreviewView:(BOOL)newValue
+{
+    [self _setBoolValue:newValue forKey:WebKitUsePDFPreviewViewPreferenceKey];
+}
+
+- (WebKitEditableLinkBehavior)editableLinkBehavior
+{
+    WebKitEditableLinkBehavior value = [self _integerValueForKey:WebKitEditableLinkBehaviorPreferenceKey];
+    if (value != WebKitEditableLinkDefaultBehavior &&
+        value != WebKitEditableLinkAlwaysLive &&
+        value != WebKitEditableLinkNeverLive &&
+        value != WebKitEditableLinkOnlyLiveWithShiftKey &&
+        value != WebKitEditableLinkLiveWhenNotFocused) {
+        // ensure that a valid result is returned
+        value = WebKitEditableLinkDefaultBehavior;
+    }
+    
+    return value;
+}
+
+- (void)setEditableLinkBehavior:(WebKitEditableLinkBehavior)behavior
+{
+    [self _setIntegerValue:behavior forKey:WebKitEditableLinkBehaviorPreferenceKey];
+}
+
+- (BOOL)_useSiteSpecificSpoofing
+{
+    return [self _boolValueForKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
+}
+
+- (void)_setUseSiteSpecificSpoofing:(BOOL)newValue
+{
+    [self _setBoolValue:newValue forKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
+}
+
++ (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
+{
+    LOG(Encoding, "requesting for %@\n", ident);
+
+    if (!ident)
+        return _standardPreferences;
+    
+    WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
+
+    return instance;
+}
+
++ (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
+{
+    if (!webPreferencesInstances)
+        webPreferencesInstances = [[NSMutableDictionary alloc] init];
+    if (ident) {
+        [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
+        LOG(Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
+    }
+}
+
++ (void)_checkLastReferenceForIdentifier:(id)identifier
+{
+    // FIXME: This won't work at all under garbage collection because retainCount returns a constant.
+    // We may need to change WebPreferences API so there's an explicit way to end the lifetime of one.
+    WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
+    if ([instance retainCount] == 1)
+        [webPreferencesInstances removeObjectForKey:identifier];
+}
+
++ (void)_removeReferenceForIdentifier:(NSString *)ident
+{
+    if (ident)
+        [self performSelector:@selector(_checkLastReferenceForIdentifier:) withObject:[self _concatenateKeyWithIBCreatorID:ident] afterDelay:0.1];
+}
+
+- (void)_postPreferencesChangesNotification
+{
+    [[NSNotificationCenter defaultCenter]
+        postNotificationName:WebPreferencesChangedNotification object:self
+                    userInfo:nil];
+}
+
++ (CFStringEncoding)_systemCFStringEncoding
+{
+    return WKGetWebDefaultCFStringEncoding();
+}
+
++ (void)_setInitialDefaultTextEncodingToSystemEncoding
+{
+    [[NSUserDefaults standardUserDefaults] registerDefaults:
+        [NSDictionary dictionaryWithObject:(NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding])
+                                    forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
+}
+
+static NSString *classIBCreatorID = nil;
+
++ (void)_setIBCreatorID:(NSString *)string
+{
+    NSString *old = classIBCreatorID;
+    classIBCreatorID = [string copy];
+    [old release];
+}
+
+- (BOOL)isDOMPasteAllowed
+{
+    return [self _boolValueForKey:WebKitDOMPasteAllowedPreferenceKey];
+}
+
+- (void)setDOMPasteAllowed:(BOOL)DOMPasteAllowed
+{
+    [self _setBoolValue:DOMPasteAllowed forKey:WebKitDOMPasteAllowedPreferenceKey];
+}
+
+- (void)_setFTPDirectoryTemplatePath:(NSString *)path
+{
+    [self _setStringValue:path forKey:WebKitFTPDirectoryTemplatePath];
+}
+
+- (NSString *)_ftpDirectoryTemplatePath
+{
+    return [self _stringValueForKey:WebKitFTPDirectoryTemplatePath];
+}
+
+- (void)_setForceFTPDirectoryListings:(BOOL)force
+{
+    [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings];
+}
+
+- (BOOL)_forceFTPDirectoryListings
+{
+    return [self _boolValueForKey:WebKitForceFTPDirectoryListings];
+}
+
+- (void)didRemoveFromWebView
+{
+    ASSERT(_private->numWebViews);
+    if (--_private->numWebViews == 0)
+        [[NSNotificationCenter defaultCenter]
+            postNotificationName:WebPreferencesRemovedNotification
+                          object:self
+                        userInfo:nil];
+}
+
+- (void)willAddToWebView
+{
+    ++_private->numWebViews;
+}
+
+@end
+
+@implementation WebPreferences (WebInternal)
+
++ (NSString *)_IBCreatorID
+{
+    return classIBCreatorID;
+}
+
++ (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
+{
+    NSString *IBCreatorID = [WebPreferences _IBCreatorID];
+    if (!IBCreatorID)
+        return key;
+    return [IBCreatorID stringByAppendingString:key];
+}
+
+@end