Home | History | Annotate | Download | only in WebView
      1 /*
      2  * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
      3  *           (C) 2006 Graham Dennis (graham.dennis (at) gmail.com)
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #import "WebPreferencesPrivate.h"
     31 #import "WebPreferenceKeysPrivate.h"
     32 
     33 #import "WebApplicationCache.h"
     34 #import "WebKitLogging.h"
     35 #import "WebKitNSStringExtras.h"
     36 #import "WebKitSystemBits.h"
     37 #import "WebKitSystemInterface.h"
     38 #import "WebKitVersionChecks.h"
     39 #import "WebNSDictionaryExtras.h"
     40 #import "WebNSURLExtras.h"
     41 #import <WebCore/ApplicationCacheStorage.h>
     42 
     43 NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
     44 NSString *WebPreferencesRemovedNotification = @"WebPreferencesRemovedNotification";
     45 NSString *WebPreferencesChangedInternalNotification = @"WebPreferencesChangedInternalNotification";
     46 
     47 #define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
     48 
     49 enum { WebPreferencesVersion = 1 };
     50 
     51 static WebPreferences *_standardPreferences;
     52 static NSMutableDictionary *webPreferencesInstances;
     53 
     54 static bool contains(const char* const array[], int count, const char* item)
     55 {
     56     if (!item)
     57         return false;
     58 
     59     for (int i = 0; i < count; i++)
     60         if (!strcasecmp(array[i], item))
     61             return true;
     62     return false;
     63 }
     64 
     65 static WebCacheModel cacheModelForMainBundle(void)
     66 {
     67     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     68 
     69     // Apps that probably need the small setting
     70     static const char* const documentViewerIDs[] = {
     71         "Microsoft/com.microsoft.Messenger",
     72         "com.adiumX.adiumX",
     73         "com.alientechnology.Proteus",
     74         "com.apple.Dashcode",
     75         "com.apple.iChat",
     76         "com.barebones.bbedit",
     77         "com.barebones.textwrangler",
     78         "com.barebones.yojimbo",
     79         "com.equinux.iSale4",
     80         "com.growl.growlframework",
     81         "com.intrarts.PandoraMan",
     82         "com.karelia.Sandvox",
     83         "com.macromates.textmate",
     84         "com.realmacsoftware.rapidweaverpro",
     85         "com.red-sweater.marsedit",
     86         "com.yahoo.messenger3",
     87         "de.codingmonkeys.SubEthaEdit",
     88         "fi.karppinen.Pyro",
     89         "info.colloquy",
     90         "kungfoo.tv.ecto",
     91     };
     92 
     93     // Apps that probably need the medium setting
     94     static const char* const documentBrowserIDs[] = {
     95         "com.apple.Dictionary",
     96         "com.apple.Xcode",
     97         "com.apple.dashboard.client",
     98         "com.apple.helpviewer",
     99         "com.culturedcode.xyle",
    100         "com.macrabbit.CSSEdit",
    101         "com.panic.Coda",
    102         "com.ranchero.NetNewsWire",
    103         "com.thinkmac.NewsLife",
    104         "org.xlife.NewsFire",
    105         "uk.co.opencommunity.vienna2",
    106     };
    107 
    108     // Apps that probably need the large setting
    109     static const char* const primaryWebBrowserIDs[] = {
    110         "com.app4mac.KidsBrowser"
    111         "com.app4mac.wKiosk",
    112         "com.freeverse.bumpercar",
    113         "com.omnigroup.OmniWeb5",
    114         "com.sunrisebrowser.Sunrise",
    115         "net.hmdt-web.Shiira",
    116     };
    117 
    118     WebCacheModel cacheModel;
    119 
    120     const char* bundleID = [[[NSBundle mainBundle] bundleIdentifier] UTF8String];
    121     if (contains(documentViewerIDs, sizeof(documentViewerIDs) / sizeof(documentViewerIDs[0]), bundleID))
    122         cacheModel = WebCacheModelDocumentViewer;
    123     else if (contains(documentBrowserIDs, sizeof(documentBrowserIDs) / sizeof(documentBrowserIDs[0]), bundleID))
    124         cacheModel = WebCacheModelDocumentBrowser;
    125     else if (contains(primaryWebBrowserIDs, sizeof(primaryWebBrowserIDs) / sizeof(primaryWebBrowserIDs[0]), bundleID))
    126         cacheModel = WebCacheModelPrimaryWebBrowser;
    127     else {
    128         bool isLegacyApp = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CACHE_MODEL_API);
    129         if (isLegacyApp)
    130             cacheModel = WebCacheModelDocumentBrowser; // To avoid regressions in apps that depended on old WebKit's large cache.
    131         else
    132             cacheModel = WebCacheModelDocumentViewer; // To save memory.
    133     }
    134 
    135     [pool drain];
    136 
    137     return cacheModel;
    138 }
    139 
    140 static bool useQuickLookQuirks(void)
    141 {
    142     NSArray* frameworks = [NSBundle allFrameworks];
    143 
    144     if (!frameworks)
    145         return false;
    146 
    147     for (unsigned int i = 0; i < [frameworks count]; i++) {
    148         NSBundle* bundle = [frameworks objectAtIndex: i];
    149         const char* bundleID = [[bundle bundleIdentifier] UTF8String];
    150         if (bundleID && !strcasecmp(bundleID, "com.apple.QuickLookUIFramework"))
    151             return true;
    152     }
    153     return false;
    154 }
    155 
    156 @interface WebPreferencesPrivate : NSObject
    157 {
    158 @public
    159     NSMutableDictionary *values;
    160     NSString *identifier;
    161     NSString *IBCreatorID;
    162     BOOL autosaves;
    163     BOOL automaticallyDetectsCacheModel;
    164     unsigned numWebViews;
    165 }
    166 @end
    167 
    168 @implementation WebPreferencesPrivate
    169 - (void)dealloc
    170 {
    171     [values release];
    172     [identifier release];
    173     [IBCreatorID release];
    174     [super dealloc];
    175 }
    176 @end
    177 
    178 @interface WebPreferences (WebInternal)
    179 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key;
    180 + (NSString *)_IBCreatorID;
    181 @end
    182 
    183 @interface WebPreferences (WebForwardDeclarations)
    184 // This pseudo-category is needed so these methods can be used from within other category implementations
    185 // without being in the public header file.
    186 - (BOOL)_boolValueForKey:(NSString *)key;
    187 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key;
    188 - (int)_integerValueForKey:(NSString *)key;
    189 - (void)_setIntegerValue:(int)value forKey:(NSString *)key;
    190 - (float)_floatValueForKey:(NSString *)key;
    191 - (void)_setFloatValue:(float)value forKey:(NSString *)key;
    192 - (void)_setLongLongValue:(long long)value forKey:(NSString *)key;
    193 - (long long)_longLongValueForKey:(NSString *)key;
    194 - (void)_setUnsignedLongLongValue:(unsigned long long)value forKey:(NSString *)key;
    195 - (unsigned long long)_unsignedLongLongValueForKey:(NSString *)key;
    196 @end
    197 
    198 @implementation WebPreferences
    199 
    200 - (id)init
    201 {
    202     // Create fake identifier
    203     static int instanceCount = 1;
    204     NSString *fakeIdentifier;
    205 
    206     // At least ensure that identifier hasn't been already used.
    207     fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
    208     while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){
    209         fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
    210     }
    211 
    212     return [self initWithIdentifier:fakeIdentifier];
    213 }
    214 
    215 - (id)initWithIdentifier:(NSString *)anIdentifier
    216 {
    217     self = [super init];
    218     if (!self)
    219         return nil;
    220 
    221     _private = [[WebPreferencesPrivate alloc] init];
    222     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
    223 
    224     WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier];
    225     if (instance){
    226         [self release];
    227         return [instance retain];
    228     }
    229 
    230     _private->values = [[NSMutableDictionary alloc] init];
    231     _private->identifier = [anIdentifier copy];
    232     _private->automaticallyDetectsCacheModel = YES;
    233 
    234     [[self class] _setInstance:self forIdentifier:_private->identifier];
    235 
    236     [self _postPreferencesChangedNotification];
    237 
    238     return self;
    239 }
    240 
    241 - (id)initWithCoder:(NSCoder *)decoder
    242 {
    243     self = [super init];
    244     if (!self)
    245         return nil;
    246 
    247     _private = [[WebPreferencesPrivate alloc] init];
    248     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
    249     _private->automaticallyDetectsCacheModel = YES;
    250 
    251     @try {
    252         id identifier = nil;
    253         id values = nil;
    254         if ([decoder allowsKeyedCoding]) {
    255             identifier = [decoder decodeObjectForKey:@"Identifier"];
    256             values = [decoder decodeObjectForKey:@"Values"];
    257         } else {
    258             int version;
    259             [decoder decodeValueOfObjCType:@encode(int) at:&version];
    260             if (version == 1) {
    261                 identifier = [decoder decodeObject];
    262                 values = [decoder decodeObject];
    263             }
    264         }
    265 
    266         if ([identifier isKindOfClass:[NSString class]])
    267             _private->identifier = [identifier copy];
    268         if ([values isKindOfClass:[NSDictionary class]])
    269             _private->values = [values mutableCopy]; // ensure dictionary is mutable
    270 
    271         LOG(Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
    272     } @catch(id) {
    273         [self release];
    274         return nil;
    275     }
    276 
    277     // If we load a nib multiple times, or have instances in multiple
    278     // nibs with the same name, the first guy up wins.
    279     WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier];
    280     if (instance) {
    281         [self release];
    282         self = [instance retain];
    283     } else {
    284         [[self class] _setInstance:self forIdentifier:_private->identifier];
    285     }
    286 
    287     return self;
    288 }
    289 
    290 - (void)encodeWithCoder:(NSCoder *)encoder
    291 {
    292     if ([encoder allowsKeyedCoding]){
    293         [encoder encodeObject:_private->identifier forKey:@"Identifier"];
    294         [encoder encodeObject:_private->values forKey:@"Values"];
    295         LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
    296     }
    297     else {
    298         int version = WebPreferencesVersion;
    299         [encoder encodeValueOfObjCType:@encode(int) at:&version];
    300         [encoder encodeObject:_private->identifier];
    301         [encoder encodeObject:_private->values];
    302     }
    303 }
    304 
    305 + (WebPreferences *)standardPreferences
    306 {
    307     if (_standardPreferences == nil) {
    308         _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil];
    309         [_standardPreferences setAutosaves:YES];
    310     }
    311 
    312     return _standardPreferences;
    313 }
    314 
    315 // if we ever have more than one WebPreferences object, this would move to init
    316 + (void)initialize
    317 {
    318     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
    319         @"Times",                       WebKitStandardFontPreferenceKey,
    320         @"Courier",                     WebKitFixedFontPreferenceKey,
    321         @"Times",                       WebKitSerifFontPreferenceKey,
    322         @"Helvetica",                   WebKitSansSerifFontPreferenceKey,
    323         @"Apple Chancery",              WebKitCursiveFontPreferenceKey,
    324         @"Papyrus",                     WebKitFantasyFontPreferenceKey,
    325         @"0",                           WebKitMinimumFontSizePreferenceKey,
    326         @"9",                           WebKitMinimumLogicalFontSizePreferenceKey,
    327         @"16",                          WebKitDefaultFontSizePreferenceKey,
    328         @"13",                          WebKitDefaultFixedFontSizePreferenceKey,
    329         @"ISO-8859-1",                  WebKitDefaultTextEncodingNamePreferenceKey,
    330         [NSNumber numberWithBool:NO],   WebKitUsesEncodingDetectorPreferenceKey,
    331         [NSNumber numberWithBool:NO],   WebKitUserStyleSheetEnabledPreferenceKey,
    332         @"",                            WebKitUserStyleSheetLocationPreferenceKey,
    333         [NSNumber numberWithBool:NO],   WebKitShouldPrintBackgroundsPreferenceKey,
    334         [NSNumber numberWithBool:NO],   WebKitTextAreasAreResizablePreferenceKey,
    335         [NSNumber numberWithBool:NO],   WebKitShrinksStandaloneImagesToFitPreferenceKey,
    336         [NSNumber numberWithBool:YES],  WebKitJavaEnabledPreferenceKey,
    337         [NSNumber numberWithBool:YES],  WebKitJavaScriptEnabledPreferenceKey,
    338         [NSNumber numberWithBool:YES],  WebKitWebSecurityEnabledPreferenceKey,
    339         [NSNumber numberWithBool:YES],  WebKitAllowUniversalAccessFromFileURLsPreferenceKey,
    340         [NSNumber numberWithBool:YES],  WebKitAllowFileAccessFromFileURLsPreferenceKey,
    341         [NSNumber numberWithBool:YES],  WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey,
    342         [NSNumber numberWithBool:YES],  WebKitPluginsEnabledPreferenceKey,
    343         [NSNumber numberWithBool:YES],  WebKitDatabasesEnabledPreferenceKey,
    344         [NSNumber numberWithBool:YES],  WebKitLocalStorageEnabledPreferenceKey,
    345         [NSNumber numberWithBool:NO],   WebKitExperimentalNotificationsEnabledPreferenceKey,
    346         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImagesPreferenceKey,
    347         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImageLoopingPreferenceKey,
    348         [NSNumber numberWithBool:YES],  WebKitDisplayImagesKey,
    349         [NSNumber numberWithBool:NO],   WebKitLoadSiteIconsKey,
    350         @"1800",                        WebKitBackForwardCacheExpirationIntervalKey,
    351         [NSNumber numberWithBool:NO],   WebKitTabToLinksPreferenceKey,
    352         [NSNumber numberWithBool:NO],   WebKitPrivateBrowsingEnabledPreferenceKey,
    353         [NSNumber numberWithBool:NO],   WebKitRespectStandardStyleKeyEquivalentsPreferenceKey,
    354         [NSNumber numberWithBool:NO],   WebKitShowsURLsInToolTipsPreferenceKey,
    355         @"1",                           WebKitPDFDisplayModePreferenceKey,
    356         @"0",                           WebKitPDFScaleFactorPreferenceKey,
    357         @"0",                           WebKitUseSiteSpecificSpoofingPreferenceKey,
    358         [NSNumber numberWithInt:WebKitEditableLinkDefaultBehavior], WebKitEditableLinkBehaviorPreferenceKey,
    359         [NSNumber numberWithInt:WebKitEditingMacBehavior], WebKitEditingBehaviorPreferenceKey,
    360 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    361         [NSNumber numberWithInt:WebTextDirectionSubmenuAutomaticallyIncluded],
    362 #else
    363         [NSNumber numberWithInt:WebTextDirectionSubmenuNeverIncluded],
    364 #endif
    365                                         WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey,
    366         [NSNumber numberWithBool:NO],   WebKitDOMPasteAllowedPreferenceKey,
    367         [NSNumber numberWithBool:YES],  WebKitUsesPageCachePreferenceKey,
    368         [NSNumber numberWithInt:cacheModelForMainBundle()], WebKitCacheModelPreferenceKey,
    369         [NSNumber numberWithBool:NO],   WebKitDeveloperExtrasEnabledPreferenceKey,
    370         [NSNumber numberWithBool:YES],  WebKitAuthorAndUserStylesEnabledPreferenceKey,
    371         [NSNumber numberWithBool:NO],   WebKitApplicationChromeModeEnabledPreferenceKey,
    372         [NSNumber numberWithBool:NO],   WebKitWebArchiveDebugModeEnabledPreferenceKey,
    373         [NSNumber numberWithBool:NO],   WebKitLocalFileContentSniffingEnabledPreferenceKey,
    374         [NSNumber numberWithBool:NO],   WebKitOfflineWebApplicationCacheEnabledPreferenceKey,
    375         [NSNumber numberWithBool:YES],  WebKitZoomsTextOnlyPreferenceKey,
    376         [NSNumber numberWithBool:NO],   WebKitJavaScriptCanAccessClipboardPreferenceKey,
    377         [NSNumber numberWithBool:YES],  WebKitXSSAuditorEnabledPreferenceKey,
    378         [NSNumber numberWithBool:YES],  WebKitAcceleratedCompositingEnabledPreferenceKey,
    379         [NSNumber numberWithBool:NO],  WebKitAcceleratedDrawingEnabledPreferenceKey,
    380         [NSNumber numberWithBool:NO],  WebKitCanvasUsesAcceleratedDrawingPreferenceKey,
    381         [NSNumber numberWithBool:NO],   WebKitShowDebugBordersPreferenceKey,
    382         [NSNumber numberWithBool:NO],   WebKitShowRepaintCounterPreferenceKey,
    383         [NSNumber numberWithBool:NO],   WebKitWebGLEnabledPreferenceKey,
    384         [NSNumber numberWithBool:NO],   WebKitAccelerated2dCanvasEnabledPreferenceKey,
    385         [NSNumber numberWithUnsignedInt:4], WebKitPluginAllowedRunTimePreferenceKey,
    386         [NSNumber numberWithBool:NO],   WebKitFrameFlatteningEnabledPreferenceKey,
    387         [NSNumber numberWithBool:NO],   WebKitSpatialNavigationEnabledPreferenceKey,
    388         [NSNumber numberWithBool:NO],  WebKitDNSPrefetchingEnabledPreferenceKey,
    389         [NSNumber numberWithBool:YES],  WebKitFullScreenEnabledPreferenceKey,
    390         [NSNumber numberWithBool:NO],   WebKitAsynchronousSpellCheckingEnabledPreferenceKey,
    391         [NSNumber numberWithBool:NO],   WebKitMemoryInfoEnabledPreferenceKey,
    392         [NSNumber numberWithBool:YES],  WebKitHyperlinkAuditingEnabledPreferenceKey,
    393         [NSNumber numberWithBool:NO],   WebKitUsePreHTML5ParserQuirksKey,
    394         [NSNumber numberWithBool:useQuickLookQuirks()], WebKitUseQuickLookResourceCachingQuirksPreferenceKey,
    395         [NSNumber numberWithLongLong:WebCore::ApplicationCacheStorage::noQuota()], WebKitApplicationCacheTotalQuota,
    396         [NSNumber numberWithLongLong:WebCore::ApplicationCacheStorage::noQuota()], WebKitApplicationCacheDefaultOriginQuota,
    397         nil];
    398 
    399     // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above
    400     ASSERT(kPDFDisplaySinglePageContinuous == 1);
    401     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
    402 }
    403 
    404 - (void)dealloc
    405 {
    406     [_private release];
    407     [super dealloc];
    408 }
    409 
    410 - (NSString *)identifier
    411 {
    412     return _private->identifier;
    413 }
    414 
    415 - (id)_valueForKey:(NSString *)key
    416 {
    417     NSString *_key = KEY(key);
    418     id o = [_private->values objectForKey:_key];
    419     if (o)
    420         return o;
    421     o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
    422     if (!o && key != _key)
    423         o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    424     return o;
    425 }
    426 
    427 - (NSString *)_stringValueForKey:(NSString *)key
    428 {
    429     id s = [self _valueForKey:key];
    430     return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
    431 }
    432 
    433 - (void)_setStringValue:(NSString *)value forKey:(NSString *)key
    434 {
    435     if ([[self _stringValueForKey:key] isEqualToString:value])
    436         return;
    437     NSString *_key = KEY(key);
    438     [_private->values setObject:value forKey:_key];
    439     if (_private->autosaves)
    440         [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
    441     [self _postPreferencesChangedNotification];
    442 }
    443 
    444 - (int)_integerValueForKey:(NSString *)key
    445 {
    446     id o = [self _valueForKey:key];
    447     return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
    448 }
    449 
    450 - (void)_setIntegerValue:(int)value forKey:(NSString *)key
    451 {
    452     if ([self _integerValueForKey:key] == value)
    453         return;
    454     NSString *_key = KEY(key);
    455     [_private->values _webkit_setInt:value forKey:_key];
    456     if (_private->autosaves)
    457         [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
    458     [self _postPreferencesChangedNotification];
    459 }
    460 
    461 - (float)_floatValueForKey:(NSString *)key
    462 {
    463     id o = [self _valueForKey:key];
    464     return [o respondsToSelector:@selector(floatValue)] ? [o floatValue] : 0.0f;
    465 }
    466 
    467 - (void)_setFloatValue:(float)value forKey:(NSString *)key
    468 {
    469     if ([self _floatValueForKey:key] == value)
    470         return;
    471     NSString *_key = KEY(key);
    472     [_private->values _webkit_setFloat:value forKey:_key];
    473     if (_private->autosaves)
    474         [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key];
    475     [self _postPreferencesChangedNotification];
    476 }
    477 
    478 - (BOOL)_boolValueForKey:(NSString *)key
    479 {
    480     return [self _integerValueForKey:key] != 0;
    481 }
    482 
    483 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
    484 {
    485     if ([self _boolValueForKey:key] == value)
    486         return;
    487     NSString *_key = KEY(key);
    488     [_private->values _webkit_setBool:value forKey:_key];
    489     if (_private->autosaves)
    490         [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
    491     [self _postPreferencesChangedNotification];
    492 }
    493 
    494 - (long long)_longLongValueForKey:(NSString *)key
    495 {
    496     id o = [self _valueForKey:key];
    497     return [o respondsToSelector:@selector(longLongValue)] ? [o longLongValue] : 0;
    498 }
    499 
    500 - (void)_setLongLongValue:(long long)value forKey:(NSString *)key
    501 {
    502     if ([self _longLongValueForKey:key] == value)
    503         return;
    504     NSString *_key = KEY(key);
    505     [_private->values _webkit_setLongLong:value forKey:_key];
    506     if (_private->autosaves)
    507         [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithLongLong:value] forKey:_key];
    508     [self _postPreferencesChangedNotification];
    509 }
    510 
    511 - (unsigned long long)_unsignedLongLongValueForKey:(NSString *)key
    512 {
    513     id o = [self _valueForKey:key];
    514     return [o respondsToSelector:@selector(unsignedLongLongValue)] ? [o unsignedLongLongValue] : 0;
    515 }
    516 
    517 - (void)_setUnsignedLongLongValue:(unsigned long long)value forKey:(NSString *)key
    518 {
    519     if ([self _unsignedLongLongValueForKey:key] == value)
    520         return;
    521     NSString *_key = KEY(key);
    522     [_private->values _webkit_setUnsignedLongLong:value forKey:_key];
    523     if (_private->autosaves)
    524         [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedLongLong:value] forKey:_key];
    525     [self _postPreferencesChangedNotification];
    526 }
    527 
    528 - (NSString *)standardFontFamily
    529 {
    530     return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
    531 }
    532 
    533 - (void)setStandardFontFamily:(NSString *)family
    534 {
    535     [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
    536 }
    537 
    538 - (NSString *)fixedFontFamily
    539 {
    540     return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
    541 }
    542 
    543 - (void)setFixedFontFamily:(NSString *)family
    544 {
    545     [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
    546 }
    547 
    548 - (NSString *)serifFontFamily
    549 {
    550     return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
    551 }
    552 
    553 - (void)setSerifFontFamily:(NSString *)family
    554 {
    555     [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
    556 }
    557 
    558 - (NSString *)sansSerifFontFamily
    559 {
    560     return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
    561 }
    562 
    563 - (void)setSansSerifFontFamily:(NSString *)family
    564 {
    565     [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
    566 }
    567 
    568 - (NSString *)cursiveFontFamily
    569 {
    570     return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
    571 }
    572 
    573 - (void)setCursiveFontFamily:(NSString *)family
    574 {
    575     [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
    576 }
    577 
    578 - (NSString *)fantasyFontFamily
    579 {
    580     return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
    581 }
    582 
    583 - (void)setFantasyFontFamily:(NSString *)family
    584 {
    585     [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
    586 }
    587 
    588 - (int)defaultFontSize
    589 {
    590     return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
    591 }
    592 
    593 - (void)setDefaultFontSize:(int)size
    594 {
    595     [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
    596 }
    597 
    598 - (int)defaultFixedFontSize
    599 {
    600     return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
    601 }
    602 
    603 - (void)setDefaultFixedFontSize:(int)size
    604 {
    605     [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
    606 }
    607 
    608 - (int)minimumFontSize
    609 {
    610     return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
    611 }
    612 
    613 - (void)setMinimumFontSize:(int)size
    614 {
    615     [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
    616 }
    617 
    618 - (int)minimumLogicalFontSize
    619 {
    620   return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
    621 }
    622 
    623 - (void)setMinimumLogicalFontSize:(int)size
    624 {
    625   [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
    626 }
    627 
    628 - (NSString *)defaultTextEncodingName
    629 {
    630     return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
    631 }
    632 
    633 - (void)setDefaultTextEncodingName:(NSString *)encoding
    634 {
    635     [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
    636 }
    637 
    638 - (BOOL)userStyleSheetEnabled
    639 {
    640     return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
    641 }
    642 
    643 - (void)setUserStyleSheetEnabled:(BOOL)flag
    644 {
    645     [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
    646 }
    647 
    648 - (NSURL *)userStyleSheetLocation
    649 {
    650     NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
    651 
    652     if ([locationString _webkit_looksLikeAbsoluteURL]) {
    653         return [NSURL _web_URLWithDataAsString:locationString];
    654     } else {
    655         locationString = [locationString stringByExpandingTildeInPath];
    656         return [NSURL fileURLWithPath:locationString];
    657     }
    658 }
    659 
    660 - (void)setUserStyleSheetLocation:(NSURL *)URL
    661 {
    662     NSString *locationString;
    663 
    664     if ([URL isFileURL]) {
    665         locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
    666     } else {
    667         locationString = [URL _web_originalDataAsString];
    668     }
    669 
    670     if (!locationString)
    671         locationString = @"";
    672 
    673     [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
    674 }
    675 
    676 - (BOOL)shouldPrintBackgrounds
    677 {
    678     return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
    679 }
    680 
    681 - (void)setShouldPrintBackgrounds:(BOOL)flag
    682 {
    683     [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
    684 }
    685 
    686 - (BOOL)isJavaEnabled
    687 {
    688     return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
    689 }
    690 
    691 - (void)setJavaEnabled:(BOOL)flag
    692 {
    693     [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
    694 }
    695 
    696 - (BOOL)isJavaScriptEnabled
    697 {
    698     return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
    699 }
    700 
    701 - (void)setJavaScriptEnabled:(BOOL)flag
    702 {
    703     [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
    704 }
    705 
    706 - (BOOL)javaScriptCanOpenWindowsAutomatically
    707 {
    708     return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
    709 }
    710 
    711 - (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
    712 {
    713     [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
    714 }
    715 
    716 - (BOOL)arePlugInsEnabled
    717 {
    718     return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
    719 }
    720 
    721 - (void)setPlugInsEnabled:(BOOL)flag
    722 {
    723     [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
    724 }
    725 
    726 - (BOOL)allowsAnimatedImages
    727 {
    728     return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
    729 }
    730 
    731 - (void)setAllowsAnimatedImages:(BOOL)flag
    732 {
    733     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
    734 }
    735 
    736 - (BOOL)allowsAnimatedImageLooping
    737 {
    738     return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
    739 }
    740 
    741 - (void)setAllowsAnimatedImageLooping: (BOOL)flag
    742 {
    743     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
    744 }
    745 
    746 - (void)setLoadsImagesAutomatically: (BOOL)flag
    747 {
    748     [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
    749 }
    750 
    751 - (BOOL)loadsImagesAutomatically
    752 {
    753     return [self _boolValueForKey: WebKitDisplayImagesKey];
    754 }
    755 
    756 - (void)setAutosaves:(BOOL)flag
    757 {
    758     _private->autosaves = flag;
    759 }
    760 
    761 - (BOOL)autosaves
    762 {
    763     return _private->autosaves;
    764 }
    765 
    766 - (void)setTabsToLinks:(BOOL)flag
    767 {
    768     [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
    769 }
    770 
    771 - (BOOL)tabsToLinks
    772 {
    773     return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
    774 }
    775 
    776 - (void)setPrivateBrowsingEnabled:(BOOL)flag
    777 {
    778     [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
    779 }
    780 
    781 - (BOOL)privateBrowsingEnabled
    782 {
    783     return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
    784 }
    785 
    786 - (void)setUsesPageCache:(BOOL)usesPageCache
    787 {
    788     [self _setBoolValue:usesPageCache forKey:WebKitUsesPageCachePreferenceKey];
    789 }
    790 
    791 - (BOOL)usesPageCache
    792 {
    793     return [self _boolValueForKey:WebKitUsesPageCachePreferenceKey];
    794 }
    795 
    796 - (void)setCacheModel:(WebCacheModel)cacheModel
    797 {
    798     [self _setIntegerValue:cacheModel forKey:WebKitCacheModelPreferenceKey];
    799     [self setAutomaticallyDetectsCacheModel:NO];
    800 }
    801 
    802 - (WebCacheModel)cacheModel
    803 {
    804     return [self _integerValueForKey:WebKitCacheModelPreferenceKey];
    805 }
    806 
    807 @end
    808 
    809 @implementation WebPreferences (WebPrivate)
    810 
    811 - (BOOL)isDNSPrefetchingEnabled
    812 {
    813     return [self _boolValueForKey:WebKitDNSPrefetchingEnabledPreferenceKey];
    814 }
    815 
    816 - (void)setDNSPrefetchingEnabled:(BOOL)flag
    817 {
    818     [self _setBoolValue:flag forKey:WebKitDNSPrefetchingEnabledPreferenceKey];
    819 }
    820 
    821 - (BOOL)developerExtrasEnabled
    822 {
    823     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    824     if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"])
    825         return NO;
    826 #ifdef NDEBUG
    827     if ([defaults boolForKey:@"WebKitDeveloperExtras"] || [defaults boolForKey:@"IncludeDebugMenu"])
    828         return YES;
    829     return [self _boolValueForKey:WebKitDeveloperExtrasEnabledPreferenceKey];
    830 #else
    831     return YES; // always enable in debug builds
    832 #endif
    833 }
    834 
    835 - (void)setDeveloperExtrasEnabled:(BOOL)flag
    836 {
    837     [self _setBoolValue:flag forKey:WebKitDeveloperExtrasEnabledPreferenceKey];
    838 }
    839 
    840 - (BOOL)authorAndUserStylesEnabled
    841 {
    842     return [self _boolValueForKey:WebKitAuthorAndUserStylesEnabledPreferenceKey];
    843 }
    844 
    845 - (void)setAuthorAndUserStylesEnabled:(BOOL)flag
    846 {
    847     [self _setBoolValue:flag forKey:WebKitAuthorAndUserStylesEnabledPreferenceKey];
    848 }
    849 
    850 - (BOOL)applicationChromeModeEnabled
    851 {
    852     return [self _boolValueForKey:WebKitApplicationChromeModeEnabledPreferenceKey];
    853 }
    854 
    855 - (void)setApplicationChromeModeEnabled:(BOOL)flag
    856 {
    857     [self _setBoolValue:flag forKey:WebKitApplicationChromeModeEnabledPreferenceKey];
    858 }
    859 
    860 - (BOOL)webArchiveDebugModeEnabled
    861 {
    862     return [self _boolValueForKey:WebKitWebArchiveDebugModeEnabledPreferenceKey];
    863 }
    864 
    865 - (void)setWebArchiveDebugModeEnabled:(BOOL)flag
    866 {
    867     [self _setBoolValue:flag forKey:WebKitWebArchiveDebugModeEnabledPreferenceKey];
    868 }
    869 
    870 - (BOOL)localFileContentSniffingEnabled
    871 {
    872     return [self _boolValueForKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
    873 }
    874 
    875 - (void)setLocalFileContentSniffingEnabled:(BOOL)flag
    876 {
    877     [self _setBoolValue:flag forKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
    878 }
    879 
    880 - (BOOL)offlineWebApplicationCacheEnabled
    881 {
    882     return [self _boolValueForKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey];
    883 }
    884 
    885 - (void)setOfflineWebApplicationCacheEnabled:(BOOL)flag
    886 {
    887     [self _setBoolValue:flag forKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey];
    888 }
    889 
    890 - (BOOL)zoomsTextOnly
    891 {
    892     return [self _boolValueForKey:WebKitZoomsTextOnlyPreferenceKey];
    893 }
    894 
    895 - (void)setZoomsTextOnly:(BOOL)flag
    896 {
    897     [self _setBoolValue:flag forKey:WebKitZoomsTextOnlyPreferenceKey];
    898 }
    899 
    900 - (BOOL)javaScriptCanAccessClipboard
    901 {
    902     return [self _boolValueForKey:WebKitJavaScriptCanAccessClipboardPreferenceKey];
    903 }
    904 
    905 - (void)setJavaScriptCanAccessClipboard:(BOOL)flag
    906 {
    907     [self _setBoolValue:flag forKey:WebKitJavaScriptCanAccessClipboardPreferenceKey];
    908 }
    909 
    910 - (BOOL)isXSSAuditorEnabled
    911 {
    912     return [self _boolValueForKey:WebKitXSSAuditorEnabledPreferenceKey];
    913 }
    914 
    915 - (void)setXSSAuditorEnabled:(BOOL)flag
    916 {
    917     [self _setBoolValue:flag forKey:WebKitXSSAuditorEnabledPreferenceKey];
    918 }
    919 
    920 - (BOOL)respectStandardStyleKeyEquivalents
    921 {
    922     return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
    923 }
    924 
    925 - (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag
    926 {
    927     [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
    928 }
    929 
    930 - (BOOL)showsURLsInToolTips
    931 {
    932     return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey];
    933 }
    934 
    935 - (void)setShowsURLsInToolTips:(BOOL)flag
    936 {
    937     [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey];
    938 }
    939 
    940 - (BOOL)textAreasAreResizable
    941 {
    942     return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey];
    943 }
    944 
    945 - (void)setTextAreasAreResizable:(BOOL)flag
    946 {
    947     [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey];
    948 }
    949 
    950 - (BOOL)shrinksStandaloneImagesToFit
    951 {
    952     return [self _boolValueForKey:WebKitShrinksStandaloneImagesToFitPreferenceKey];
    953 }
    954 
    955 - (void)setShrinksStandaloneImagesToFit:(BOOL)flag
    956 {
    957     [self _setBoolValue:flag forKey:WebKitShrinksStandaloneImagesToFitPreferenceKey];
    958 }
    959 
    960 - (BOOL)automaticallyDetectsCacheModel
    961 {
    962     return _private->automaticallyDetectsCacheModel;
    963 }
    964 
    965 - (void)setAutomaticallyDetectsCacheModel:(BOOL)automaticallyDetectsCacheModel
    966 {
    967     _private->automaticallyDetectsCacheModel = automaticallyDetectsCacheModel;
    968 }
    969 
    970 - (BOOL)usesEncodingDetector
    971 {
    972     return [self _boolValueForKey: WebKitUsesEncodingDetectorPreferenceKey];
    973 }
    974 
    975 - (void)setUsesEncodingDetector:(BOOL)flag
    976 {
    977     [self _setBoolValue: flag forKey: WebKitUsesEncodingDetectorPreferenceKey];
    978 }
    979 
    980 - (BOOL)isWebSecurityEnabled
    981 {
    982     return [self _boolValueForKey: WebKitWebSecurityEnabledPreferenceKey];
    983 }
    984 
    985 - (void)setWebSecurityEnabled:(BOOL)flag
    986 {
    987     [self _setBoolValue: flag forKey: WebKitWebSecurityEnabledPreferenceKey];
    988 }
    989 
    990 - (BOOL)allowUniversalAccessFromFileURLs
    991 {
    992     return [self _boolValueForKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey];
    993 }
    994 
    995 - (void)setAllowUniversalAccessFromFileURLs:(BOOL)flag
    996 {
    997     [self _setBoolValue: flag forKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey];
    998 }
    999 
   1000 - (BOOL)allowFileAccessFromFileURLs
   1001 {
   1002     return [self _boolValueForKey: WebKitAllowFileAccessFromFileURLsPreferenceKey];
   1003 }
   1004 
   1005 - (void)setAllowFileAccessFromFileURLs:(BOOL)flag
   1006 {
   1007     [self _setBoolValue: flag forKey: WebKitAllowFileAccessFromFileURLsPreferenceKey];
   1008 }
   1009 
   1010 - (NSTimeInterval)_backForwardCacheExpirationInterval
   1011 {
   1012     // FIXME: There's probably no good reason to read from the standard user defaults instead of self.
   1013     return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
   1014 }
   1015 
   1016 - (float)PDFScaleFactor
   1017 {
   1018     return [self _floatValueForKey:WebKitPDFScaleFactorPreferenceKey];
   1019 }
   1020 
   1021 - (void)setPDFScaleFactor:(float)factor
   1022 {
   1023     [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey];
   1024 }
   1025 
   1026 - (int64_t)applicationCacheTotalQuota
   1027 {
   1028     return [self _longLongValueForKey:WebKitApplicationCacheTotalQuota];
   1029 }
   1030 
   1031 - (void)setApplicationCacheTotalQuota:(int64_t)quota
   1032 {
   1033     [self _setLongLongValue:quota forKey:WebKitApplicationCacheTotalQuota];
   1034 
   1035     // Application Cache Preferences are stored on the global cache storage manager, not in Settings.
   1036     [WebApplicationCache setMaximumSize:quota];
   1037 }
   1038 
   1039 - (int64_t)applicationCacheDefaultOriginQuota
   1040 {
   1041     return [self _longLongValueForKey:WebKitApplicationCacheDefaultOriginQuota];
   1042 }
   1043 
   1044 - (void)setApplicationCacheDefaultOriginQuota:(int64_t)quota
   1045 {
   1046     [self _setLongLongValue:quota forKey:WebKitApplicationCacheDefaultOriginQuota];
   1047 }
   1048 
   1049 - (PDFDisplayMode)PDFDisplayMode
   1050 {
   1051     PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey];
   1052     if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) {
   1053         // protect against new modes from future versions of OS X stored in defaults
   1054         value = kPDFDisplaySinglePageContinuous;
   1055     }
   1056     return value;
   1057 }
   1058 
   1059 - (void)setPDFDisplayMode:(PDFDisplayMode)mode
   1060 {
   1061     [self _setIntegerValue:mode forKey:WebKitPDFDisplayModePreferenceKey];
   1062 }
   1063 
   1064 - (WebKitEditableLinkBehavior)editableLinkBehavior
   1065 {
   1066     WebKitEditableLinkBehavior value = static_cast<WebKitEditableLinkBehavior> ([self _integerValueForKey:WebKitEditableLinkBehaviorPreferenceKey]);
   1067     if (value != WebKitEditableLinkDefaultBehavior &&
   1068         value != WebKitEditableLinkAlwaysLive &&
   1069         value != WebKitEditableLinkNeverLive &&
   1070         value != WebKitEditableLinkOnlyLiveWithShiftKey &&
   1071         value != WebKitEditableLinkLiveWhenNotFocused) {
   1072         // ensure that a valid result is returned
   1073         value = WebKitEditableLinkDefaultBehavior;
   1074     }
   1075 
   1076     return value;
   1077 }
   1078 
   1079 - (void)setEditableLinkBehavior:(WebKitEditableLinkBehavior)behavior
   1080 {
   1081     [self _setIntegerValue:behavior forKey:WebKitEditableLinkBehaviorPreferenceKey];
   1082 }
   1083 
   1084 - (WebTextDirectionSubmenuInclusionBehavior)textDirectionSubmenuInclusionBehavior
   1085 {
   1086     WebTextDirectionSubmenuInclusionBehavior value = static_cast<WebTextDirectionSubmenuInclusionBehavior>([self _integerValueForKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey]);
   1087     if (value != WebTextDirectionSubmenuNeverIncluded &&
   1088         value != WebTextDirectionSubmenuAutomaticallyIncluded &&
   1089         value != WebTextDirectionSubmenuAlwaysIncluded) {
   1090         // Ensure that a valid result is returned.
   1091         value = WebTextDirectionSubmenuNeverIncluded;
   1092     }
   1093     return value;
   1094 }
   1095 
   1096 - (void)setTextDirectionSubmenuInclusionBehavior:(WebTextDirectionSubmenuInclusionBehavior)behavior
   1097 {
   1098     [self _setIntegerValue:behavior forKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey];
   1099 }
   1100 
   1101 - (BOOL)_useSiteSpecificSpoofing
   1102 {
   1103     return [self _boolValueForKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
   1104 }
   1105 
   1106 - (void)_setUseSiteSpecificSpoofing:(BOOL)newValue
   1107 {
   1108     [self _setBoolValue:newValue forKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
   1109 }
   1110 
   1111 - (BOOL)databasesEnabled
   1112 {
   1113     return [self _boolValueForKey:WebKitDatabasesEnabledPreferenceKey];
   1114 }
   1115 
   1116 - (void)setDatabasesEnabled:(BOOL)databasesEnabled
   1117 {
   1118     [self _setBoolValue:databasesEnabled forKey:WebKitDatabasesEnabledPreferenceKey];
   1119 }
   1120 
   1121 - (BOOL)localStorageEnabled
   1122 {
   1123     return [self _boolValueForKey:WebKitLocalStorageEnabledPreferenceKey];
   1124 }
   1125 
   1126 - (void)setLocalStorageEnabled:(BOOL)localStorageEnabled
   1127 {
   1128     [self _setBoolValue:localStorageEnabled forKey:WebKitLocalStorageEnabledPreferenceKey];
   1129 }
   1130 
   1131 - (BOOL)experimentalNotificationsEnabled
   1132 {
   1133     return [self _boolValueForKey:WebKitExperimentalNotificationsEnabledPreferenceKey];
   1134 }
   1135 
   1136 - (void)setExperimentalNotificationsEnabled:(BOOL)experimentalNotificationsEnabled
   1137 {
   1138     [self _setBoolValue:experimentalNotificationsEnabled forKey:WebKitExperimentalNotificationsEnabledPreferenceKey];
   1139 }
   1140 
   1141 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
   1142 {
   1143     LOG(Encoding, "requesting for %@\n", ident);
   1144 
   1145     if (!ident)
   1146         return _standardPreferences;
   1147 
   1148     WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
   1149 
   1150     return instance;
   1151 }
   1152 
   1153 + (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
   1154 {
   1155     if (!webPreferencesInstances)
   1156         webPreferencesInstances = [[NSMutableDictionary alloc] init];
   1157     if (ident) {
   1158         [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
   1159         LOG(Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
   1160     }
   1161 }
   1162 
   1163 + (void)_checkLastReferenceForIdentifier:(id)identifier
   1164 {
   1165     // FIXME: This won't work at all under garbage collection because retainCount returns a constant.
   1166     // We may need to change WebPreferences API so there's an explicit way to end the lifetime of one.
   1167     WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
   1168     if ([instance retainCount] == 1)
   1169         [webPreferencesInstances removeObjectForKey:identifier];
   1170 }
   1171 
   1172 + (void)_removeReferenceForIdentifier:(NSString *)ident
   1173 {
   1174     if (ident)
   1175         [self performSelector:@selector(_checkLastReferenceForIdentifier:) withObject:[self _concatenateKeyWithIBCreatorID:ident] afterDelay:0.1];
   1176 }
   1177 
   1178 - (void)_postPreferencesChangedNotification
   1179 {
   1180     if (!pthread_main_np()) {
   1181         [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
   1182         return;
   1183     }
   1184 
   1185     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedInternalNotification object:self userInfo:nil];
   1186     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
   1187 }
   1188 
   1189 - (void)_postPreferencesChangedAPINotification
   1190 {
   1191     if (!pthread_main_np()) {
   1192         [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
   1193         return;
   1194     }
   1195 
   1196     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
   1197 }
   1198 
   1199 + (CFStringEncoding)_systemCFStringEncoding
   1200 {
   1201     return WKGetWebDefaultCFStringEncoding();
   1202 }
   1203 
   1204 + (void)_setInitialDefaultTextEncodingToSystemEncoding
   1205 {
   1206     NSString *systemEncodingName = (NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding]);
   1207 
   1208     // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-949.
   1209     // ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-949.
   1210     // In addition, this value must match what is used in Safari, see <rdar://problem/5579292>.
   1211     // On some OS versions, the result is CP949 (uppercase).
   1212     if ([systemEncodingName _webkit_isCaseInsensitiveEqualToString:@"cp949"])
   1213         systemEncodingName = @"ks_c_5601-1987";
   1214     [[NSUserDefaults standardUserDefaults] registerDefaults:
   1215         [NSDictionary dictionaryWithObject:systemEncodingName forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
   1216 }
   1217 
   1218 static NSString *classIBCreatorID = nil;
   1219 
   1220 + (void)_setIBCreatorID:(NSString *)string
   1221 {
   1222     NSString *old = classIBCreatorID;
   1223     classIBCreatorID = [string copy];
   1224     [old release];
   1225 }
   1226 
   1227 - (BOOL)isDOMPasteAllowed
   1228 {
   1229     return [self _boolValueForKey:WebKitDOMPasteAllowedPreferenceKey];
   1230 }
   1231 
   1232 - (void)setDOMPasteAllowed:(BOOL)DOMPasteAllowed
   1233 {
   1234     [self _setBoolValue:DOMPasteAllowed forKey:WebKitDOMPasteAllowedPreferenceKey];
   1235 }
   1236 
   1237 - (NSString *)_localStorageDatabasePath
   1238 {
   1239     return [[self _stringValueForKey:WebKitLocalStorageDatabasePathPreferenceKey] stringByStandardizingPath];
   1240 }
   1241 
   1242 - (void)_setLocalStorageDatabasePath:(NSString *)path
   1243 {
   1244     [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitLocalStorageDatabasePathPreferenceKey];
   1245 }
   1246 
   1247 - (NSString *)_ftpDirectoryTemplatePath
   1248 {
   1249     return [[self _stringValueForKey:WebKitFTPDirectoryTemplatePath] stringByStandardizingPath];
   1250 }
   1251 
   1252 - (void)_setFTPDirectoryTemplatePath:(NSString *)path
   1253 {
   1254     [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitFTPDirectoryTemplatePath];
   1255 }
   1256 
   1257 - (BOOL)_forceFTPDirectoryListings
   1258 {
   1259     return [self _boolValueForKey:WebKitForceFTPDirectoryListings];
   1260 }
   1261 
   1262 - (void)_setForceFTPDirectoryListings:(BOOL)force
   1263 {
   1264     [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings];
   1265 }
   1266 
   1267 - (BOOL)acceleratedDrawingEnabled
   1268 {
   1269     return [self _boolValueForKey:WebKitAcceleratedDrawingEnabledPreferenceKey];
   1270 }
   1271 
   1272 - (void)setAcceleratedDrawingEnabled:(BOOL)enabled
   1273 {
   1274     [self _setBoolValue:enabled forKey:WebKitAcceleratedDrawingEnabledPreferenceKey];
   1275 }
   1276 
   1277 - (BOOL)canvasUsesAcceleratedDrawing
   1278 {
   1279     return [self _boolValueForKey:WebKitCanvasUsesAcceleratedDrawingPreferenceKey];
   1280 }
   1281 
   1282 - (void)setCanvasUsesAcceleratedDrawing:(BOOL)enabled
   1283 {
   1284     [self _setBoolValue:enabled forKey:WebKitCanvasUsesAcceleratedDrawingPreferenceKey];
   1285 }
   1286 
   1287 - (BOOL)acceleratedCompositingEnabled
   1288 {
   1289     return [self _boolValueForKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
   1290 }
   1291 
   1292 - (void)setAcceleratedCompositingEnabled:(BOOL)enabled
   1293 {
   1294     [self _setBoolValue:enabled forKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
   1295 }
   1296 
   1297 - (BOOL)showDebugBorders
   1298 {
   1299     return [self _boolValueForKey:WebKitShowDebugBordersPreferenceKey];
   1300 }
   1301 
   1302 - (void)setShowDebugBorders:(BOOL)enabled
   1303 {
   1304     [self _setBoolValue:enabled forKey:WebKitShowDebugBordersPreferenceKey];
   1305 }
   1306 
   1307 - (BOOL)showRepaintCounter
   1308 {
   1309     return [self _boolValueForKey:WebKitShowRepaintCounterPreferenceKey];
   1310 }
   1311 
   1312 - (void)setShowRepaintCounter:(BOOL)enabled
   1313 {
   1314     [self _setBoolValue:enabled forKey:WebKitShowRepaintCounterPreferenceKey];
   1315 }
   1316 
   1317 - (BOOL)webAudioEnabled
   1318 {
   1319     return [self _boolValueForKey:WebKitWebAudioEnabledPreferenceKey];
   1320 }
   1321 
   1322 - (void)setWebAudioEnabled:(BOOL)enabled
   1323 {
   1324     [self _setBoolValue:enabled forKey:WebKitWebAudioEnabledPreferenceKey];
   1325 }
   1326 
   1327 - (BOOL)webGLEnabled
   1328 {
   1329     return [self _boolValueForKey:WebKitWebGLEnabledPreferenceKey];
   1330 }
   1331 
   1332 - (void)setWebGLEnabled:(BOOL)enabled
   1333 {
   1334     [self _setBoolValue:enabled forKey:WebKitWebGLEnabledPreferenceKey];
   1335 }
   1336 
   1337 - (BOOL)accelerated2dCanvasEnabled
   1338 {
   1339     return [self _boolValueForKey:WebKitAccelerated2dCanvasEnabledPreferenceKey];
   1340 }
   1341 
   1342 - (void)setAccelerated2dCanvasEnabled:(BOOL)enabled
   1343 {
   1344     [self _setBoolValue:enabled forKey:WebKitAccelerated2dCanvasEnabledPreferenceKey];
   1345 }
   1346 
   1347 - (unsigned)pluginAllowedRunTime
   1348 {
   1349     return [self _integerValueForKey:WebKitPluginAllowedRunTimePreferenceKey];
   1350 }
   1351 
   1352 - (void)setPluginAllowedRunTime:(unsigned)allowedRunTime
   1353 {
   1354     return [self _setIntegerValue:allowedRunTime forKey:WebKitPluginAllowedRunTimePreferenceKey];
   1355 }
   1356 
   1357 - (BOOL)isFrameFlatteningEnabled
   1358 {
   1359     return [self _boolValueForKey:WebKitFrameFlatteningEnabledPreferenceKey];
   1360 }
   1361 
   1362 - (void)setFrameFlatteningEnabled:(BOOL)flag
   1363 {
   1364     [self _setBoolValue:flag forKey:WebKitFrameFlatteningEnabledPreferenceKey];
   1365 }
   1366 
   1367 - (BOOL)isSpatialNavigationEnabled
   1368 {
   1369     return [self _boolValueForKey:WebKitSpatialNavigationEnabledPreferenceKey];
   1370 }
   1371 
   1372 - (void)setSpatialNavigationEnabled:(BOOL)flag
   1373 {
   1374     [self _setBoolValue:flag forKey:WebKitSpatialNavigationEnabledPreferenceKey];
   1375 }
   1376 
   1377 - (BOOL)paginateDuringLayoutEnabled
   1378 {
   1379     return [self _boolValueForKey:WebKitPaginateDuringLayoutEnabledPreferenceKey];
   1380 }
   1381 
   1382 - (void)setPaginateDuringLayoutEnabled:(BOOL)flag
   1383 {
   1384     [self _setBoolValue:flag forKey:WebKitPaginateDuringLayoutEnabledPreferenceKey];
   1385 }
   1386 
   1387 - (BOOL)memoryInfoEnabled
   1388 {
   1389     return [self _boolValueForKey:WebKitMemoryInfoEnabledPreferenceKey];
   1390 }
   1391 
   1392 - (void)setMemoryInfoEnabled:(BOOL)flag
   1393 {
   1394     [self _setBoolValue:flag forKey:WebKitMemoryInfoEnabledPreferenceKey];
   1395 }
   1396 
   1397 - (BOOL)hyperlinkAuditingEnabled
   1398 {
   1399     return [self _boolValueForKey:WebKitHyperlinkAuditingEnabledPreferenceKey];
   1400 }
   1401 
   1402 - (void)setHyperlinkAuditingEnabled:(BOOL)flag
   1403 {
   1404     [self _setBoolValue:flag forKey:WebKitHyperlinkAuditingEnabledPreferenceKey];
   1405 }
   1406 
   1407 - (WebKitEditingBehavior)editingBehavior
   1408 {
   1409     return static_cast<WebKitEditingBehavior>([self _integerValueForKey:WebKitEditingBehaviorPreferenceKey]);
   1410 }
   1411 
   1412 - (void)setEditingBehavior:(WebKitEditingBehavior)behavior
   1413 {
   1414     [self _setIntegerValue:behavior forKey:WebKitEditingBehaviorPreferenceKey];
   1415 }
   1416 
   1417 - (BOOL)usePreHTML5ParserQuirks
   1418 {
   1419     return [self _boolValueForKey:WebKitUsePreHTML5ParserQuirksKey];
   1420 }
   1421 
   1422 - (void)setUsePreHTML5ParserQuirks:(BOOL)flag
   1423 {
   1424     [self _setBoolValue:flag forKey:WebKitUsePreHTML5ParserQuirksKey];
   1425 }
   1426 
   1427 - (BOOL)useQuickLookResourceCachingQuirks
   1428 {
   1429     return [self _boolValueForKey:WebKitUseQuickLookResourceCachingQuirksPreferenceKey];
   1430 }
   1431 
   1432 - (void)didRemoveFromWebView
   1433 {
   1434     ASSERT(_private->numWebViews);
   1435     if (--_private->numWebViews == 0)
   1436         [[NSNotificationCenter defaultCenter]
   1437             postNotificationName:WebPreferencesRemovedNotification
   1438                           object:self
   1439                         userInfo:nil];
   1440 }
   1441 
   1442 - (void)willAddToWebView
   1443 {
   1444     ++_private->numWebViews;
   1445 }
   1446 
   1447 - (void)_setPreferenceForTestWithValue:(NSString *)value forKey:(NSString *)key
   1448 {
   1449     [self _setStringValue:value forKey:key];
   1450 }
   1451 
   1452 - (void)setFullScreenEnabled:(BOOL)flag
   1453 {
   1454     [self _setBoolValue:flag forKey:WebKitFullScreenEnabledPreferenceKey];
   1455 }
   1456 
   1457 - (BOOL)fullScreenEnabled
   1458 {
   1459     return [self _boolValueForKey:WebKitFullScreenEnabledPreferenceKey];
   1460 }
   1461 
   1462 - (void)setAsynchronousSpellCheckingEnabled:(BOOL)flag
   1463 {
   1464     [self _setBoolValue:flag forKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
   1465 }
   1466 
   1467 - (BOOL)asynchronousSpellCheckingEnabled
   1468 {
   1469     return [self _boolValueForKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
   1470 }
   1471 
   1472 + (void)setWebKitLinkTimeVersion:(int)version
   1473 {
   1474     setWebKitLinkTimeVersion(version);
   1475 }
   1476 
   1477 - (void)setLoadsSiteIconsIgnoringImageLoadingPreference: (BOOL)flag
   1478 {
   1479     [self _setBoolValue: flag forKey: WebKitLoadSiteIconsKey];
   1480 }
   1481 
   1482 - (BOOL)loadsSiteIconsIgnoringImageLoadingPreference
   1483 {
   1484     return [self _boolValueForKey: WebKitLoadSiteIconsKey];
   1485 }
   1486 
   1487 @end
   1488 
   1489 @implementation WebPreferences (WebInternal)
   1490 
   1491 + (NSString *)_IBCreatorID
   1492 {
   1493     return classIBCreatorID;
   1494 }
   1495 
   1496 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
   1497 {
   1498     NSString *IBCreatorID = [WebPreferences _IBCreatorID];
   1499     if (!IBCreatorID)
   1500         return key;
   1501     return [IBCreatorID stringByAppendingString:key];
   1502 }
   1503 
   1504 @end
   1505