8adae4ea0a81140f5d8893837cbf895ff51512d9
[WebKit-https.git] / Source / WebKit / mac / WebView / WebPreferences.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
3  *           (C) 2006 Graham Dennis (graham.dennis@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:NO],   WebKitFullScreenEnabledPreferenceKey,
390         [NSNumber numberWithBool:NO],   WebKitAsynchronousSpellCheckingEnabledPreferenceKey,
391         [NSNumber numberWithBool:NO],   WebKitMemoryInfoEnabledPreferenceKey,
392         [NSNumber numberWithBool:YES],  WebKitHyperlinkAuditingEnabledPreferenceKey,
393         [NSNumber numberWithBool:NO],   WebKitUsePreHTML5ParserQuirksKey,
394         [NSNumber numberWithBool:YES],  WebKitAVFoundationEnabledKey,
395         [NSNumber numberWithBool:useQuickLookQuirks()], WebKitUseQuickLookResourceCachingQuirksPreferenceKey,
396         [NSNumber numberWithLongLong:WebCore::ApplicationCacheStorage::noQuota()], WebKitApplicationCacheTotalQuota,
397         [NSNumber numberWithLongLong:WebCore::ApplicationCacheStorage::noQuota()], WebKitApplicationCacheDefaultOriginQuota,
398         nil];
399
400     // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above
401     ASSERT(kPDFDisplaySinglePageContinuous == 1);
402     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
403 }
404
405 - (void)dealloc
406 {
407     [_private release];
408     [super dealloc];
409 }
410
411 - (NSString *)identifier
412 {
413     return _private->identifier;
414 }
415
416 - (id)_valueForKey:(NSString *)key
417 {
418     NSString *_key = KEY(key);
419     id o = [_private->values objectForKey:_key];
420     if (o)
421         return o;
422     o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
423     if (!o && key != _key)
424         o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
425     return o;
426 }
427
428 - (NSString *)_stringValueForKey:(NSString *)key
429 {
430     id s = [self _valueForKey:key];
431     return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
432 }
433
434 - (void)_setStringValue:(NSString *)value forKey:(NSString *)key
435 {
436     if ([[self _stringValueForKey:key] isEqualToString:value])
437         return;
438     NSString *_key = KEY(key);
439     [_private->values setObject:value forKey:_key];
440     if (_private->autosaves)
441         [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
442     [self _postPreferencesChangedNotification];
443 }
444
445 - (int)_integerValueForKey:(NSString *)key
446 {
447     id o = [self _valueForKey:key];
448     return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
449 }
450
451 - (void)_setIntegerValue:(int)value forKey:(NSString *)key
452 {
453     if ([self _integerValueForKey:key] == value)
454         return;
455     NSString *_key = KEY(key);
456     [_private->values _webkit_setInt:value forKey:_key];
457     if (_private->autosaves)
458         [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
459     [self _postPreferencesChangedNotification];
460 }
461
462 - (float)_floatValueForKey:(NSString *)key
463 {
464     id o = [self _valueForKey:key];
465     return [o respondsToSelector:@selector(floatValue)] ? [o floatValue] : 0.0f;
466 }
467
468 - (void)_setFloatValue:(float)value forKey:(NSString *)key
469 {
470     if ([self _floatValueForKey:key] == value)
471         return;
472     NSString *_key = KEY(key);
473     [_private->values _webkit_setFloat:value forKey:_key];
474     if (_private->autosaves)
475         [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key];
476     [self _postPreferencesChangedNotification];
477 }
478
479 - (BOOL)_boolValueForKey:(NSString *)key
480 {
481     return [self _integerValueForKey:key] != 0;
482 }
483
484 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
485 {
486     if ([self _boolValueForKey:key] == value)
487         return;
488     NSString *_key = KEY(key);
489     [_private->values _webkit_setBool:value forKey:_key];
490     if (_private->autosaves)
491         [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
492     [self _postPreferencesChangedNotification];
493 }
494
495 - (long long)_longLongValueForKey:(NSString *)key
496 {
497     id o = [self _valueForKey:key];
498     return [o respondsToSelector:@selector(longLongValue)] ? [o longLongValue] : 0;
499 }
500
501 - (void)_setLongLongValue:(long long)value forKey:(NSString *)key
502 {
503     if ([self _longLongValueForKey:key] == value)
504         return;
505     NSString *_key = KEY(key);
506     [_private->values _webkit_setLongLong:value forKey:_key];
507     if (_private->autosaves)
508         [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithLongLong:value] forKey:_key];
509     [self _postPreferencesChangedNotification];
510 }
511
512 - (unsigned long long)_unsignedLongLongValueForKey:(NSString *)key
513 {
514     id o = [self _valueForKey:key];
515     return [o respondsToSelector:@selector(unsignedLongLongValue)] ? [o unsignedLongLongValue] : 0;
516 }
517
518 - (void)_setUnsignedLongLongValue:(unsigned long long)value forKey:(NSString *)key
519 {
520     if ([self _unsignedLongLongValueForKey:key] == value)
521         return;
522     NSString *_key = KEY(key);
523     [_private->values _webkit_setUnsignedLongLong:value forKey:_key];
524     if (_private->autosaves)
525         [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedLongLong:value] forKey:_key];
526     [self _postPreferencesChangedNotification];
527 }
528
529 - (NSString *)standardFontFamily
530 {
531     return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
532 }
533
534 - (void)setStandardFontFamily:(NSString *)family
535 {
536     [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
537 }
538
539 - (NSString *)fixedFontFamily
540 {
541     return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
542 }
543
544 - (void)setFixedFontFamily:(NSString *)family
545 {
546     [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
547 }
548
549 - (NSString *)serifFontFamily
550 {
551     return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
552 }
553
554 - (void)setSerifFontFamily:(NSString *)family 
555 {
556     [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
557 }
558
559 - (NSString *)sansSerifFontFamily
560 {
561     return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
562 }
563
564 - (void)setSansSerifFontFamily:(NSString *)family
565 {
566     [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
567 }
568
569 - (NSString *)cursiveFontFamily
570 {
571     return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
572 }
573
574 - (void)setCursiveFontFamily:(NSString *)family
575 {
576     [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
577 }
578
579 - (NSString *)fantasyFontFamily
580 {
581     return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
582 }
583
584 - (void)setFantasyFontFamily:(NSString *)family
585 {
586     [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
587 }
588
589 - (int)defaultFontSize
590 {
591     return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
592 }
593
594 - (void)setDefaultFontSize:(int)size
595 {
596     [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
597 }
598
599 - (int)defaultFixedFontSize
600 {
601     return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
602 }
603
604 - (void)setDefaultFixedFontSize:(int)size
605 {
606     [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
607 }
608
609 - (int)minimumFontSize
610 {
611     return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
612 }
613
614 - (void)setMinimumFontSize:(int)size
615 {
616     [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
617 }
618
619 - (int)minimumLogicalFontSize
620 {
621   return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
622 }
623
624 - (void)setMinimumLogicalFontSize:(int)size
625 {
626   [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
627 }
628
629 - (NSString *)defaultTextEncodingName
630 {
631     return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
632 }
633
634 - (void)setDefaultTextEncodingName:(NSString *)encoding
635 {
636     [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
637 }
638
639 - (BOOL)userStyleSheetEnabled
640 {
641     return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
642 }
643
644 - (void)setUserStyleSheetEnabled:(BOOL)flag
645 {
646     [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
647 }
648
649 - (NSURL *)userStyleSheetLocation
650 {
651     NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
652     
653     if ([locationString _webkit_looksLikeAbsoluteURL]) {
654         return [NSURL _web_URLWithDataAsString:locationString];
655     } else {
656         locationString = [locationString stringByExpandingTildeInPath];
657         return [NSURL fileURLWithPath:locationString];
658     }
659 }
660
661 - (void)setUserStyleSheetLocation:(NSURL *)URL
662 {
663     NSString *locationString;
664     
665     if ([URL isFileURL]) {
666         locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
667     } else {
668         locationString = [URL _web_originalDataAsString];
669     }
670
671     if (!locationString)
672         locationString = @"";
673
674     [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
675 }
676
677 - (BOOL)shouldPrintBackgrounds
678 {
679     return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
680 }
681
682 - (void)setShouldPrintBackgrounds:(BOOL)flag
683 {
684     [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
685 }
686
687 - (BOOL)isJavaEnabled
688 {
689     return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
690 }
691
692 - (void)setJavaEnabled:(BOOL)flag
693 {
694     [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
695 }
696
697 - (BOOL)isJavaScriptEnabled
698 {
699     return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
700 }
701
702 - (void)setJavaScriptEnabled:(BOOL)flag
703 {
704     [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
705 }
706
707 - (BOOL)javaScriptCanOpenWindowsAutomatically
708 {
709     return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
710 }
711
712 - (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
713 {
714     [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
715 }
716
717 - (BOOL)arePlugInsEnabled
718 {
719     return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
720 }
721
722 - (void)setPlugInsEnabled:(BOOL)flag
723 {
724     [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
725 }
726
727 - (BOOL)allowsAnimatedImages
728 {
729     return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
730 }
731
732 - (void)setAllowsAnimatedImages:(BOOL)flag
733 {
734     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
735 }
736
737 - (BOOL)allowsAnimatedImageLooping
738 {
739     return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
740 }
741
742 - (void)setAllowsAnimatedImageLooping: (BOOL)flag
743 {
744     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
745 }
746
747 - (void)setLoadsImagesAutomatically: (BOOL)flag
748 {
749     [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
750 }
751
752 - (BOOL)loadsImagesAutomatically
753 {
754     return [self _boolValueForKey: WebKitDisplayImagesKey];
755 }
756
757 - (void)setAutosaves:(BOOL)flag
758 {
759     _private->autosaves = flag;
760 }
761
762 - (BOOL)autosaves
763 {
764     return _private->autosaves;
765 }
766
767 - (void)setTabsToLinks:(BOOL)flag
768 {
769     [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
770 }
771
772 - (BOOL)tabsToLinks
773 {
774     return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
775 }
776
777 - (void)setPrivateBrowsingEnabled:(BOOL)flag
778 {
779     [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
780 }
781
782 - (BOOL)privateBrowsingEnabled
783 {
784     return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
785 }
786
787 - (void)setUsesPageCache:(BOOL)usesPageCache
788 {
789     [self _setBoolValue:usesPageCache forKey:WebKitUsesPageCachePreferenceKey];
790 }
791
792 - (BOOL)usesPageCache
793 {
794     return [self _boolValueForKey:WebKitUsesPageCachePreferenceKey];
795 }
796
797 - (void)setCacheModel:(WebCacheModel)cacheModel
798 {
799     [self _setIntegerValue:cacheModel forKey:WebKitCacheModelPreferenceKey];
800     [self setAutomaticallyDetectsCacheModel:NO];
801 }
802
803 - (WebCacheModel)cacheModel
804 {
805     return [self _integerValueForKey:WebKitCacheModelPreferenceKey];
806 }
807
808 @end
809
810 @implementation WebPreferences (WebPrivate)
811
812 - (BOOL)isDNSPrefetchingEnabled
813 {
814     return [self _boolValueForKey:WebKitDNSPrefetchingEnabledPreferenceKey];
815 }
816
817 - (void)setDNSPrefetchingEnabled:(BOOL)flag
818 {
819     [self _setBoolValue:flag forKey:WebKitDNSPrefetchingEnabledPreferenceKey];
820 }
821
822 - (BOOL)developerExtrasEnabled
823 {
824     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
825     if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"])
826         return NO;
827 #ifdef NDEBUG
828     if ([defaults boolForKey:@"WebKitDeveloperExtras"] || [defaults boolForKey:@"IncludeDebugMenu"])
829         return YES;
830     return [self _boolValueForKey:WebKitDeveloperExtrasEnabledPreferenceKey];
831 #else
832     return YES; // always enable in debug builds
833 #endif
834 }
835
836 - (void)setDeveloperExtrasEnabled:(BOOL)flag
837 {
838     [self _setBoolValue:flag forKey:WebKitDeveloperExtrasEnabledPreferenceKey];
839 }
840
841 - (BOOL)authorAndUserStylesEnabled
842 {
843     return [self _boolValueForKey:WebKitAuthorAndUserStylesEnabledPreferenceKey];
844 }
845
846 - (void)setAuthorAndUserStylesEnabled:(BOOL)flag
847 {
848     [self _setBoolValue:flag forKey:WebKitAuthorAndUserStylesEnabledPreferenceKey];
849 }
850
851 - (BOOL)applicationChromeModeEnabled
852 {
853     return [self _boolValueForKey:WebKitApplicationChromeModeEnabledPreferenceKey];
854 }
855
856 - (void)setApplicationChromeModeEnabled:(BOOL)flag
857 {
858     [self _setBoolValue:flag forKey:WebKitApplicationChromeModeEnabledPreferenceKey];
859 }
860
861 - (BOOL)webArchiveDebugModeEnabled
862 {
863     return [self _boolValueForKey:WebKitWebArchiveDebugModeEnabledPreferenceKey];
864 }
865
866 - (void)setWebArchiveDebugModeEnabled:(BOOL)flag
867 {
868     [self _setBoolValue:flag forKey:WebKitWebArchiveDebugModeEnabledPreferenceKey];
869 }
870
871 - (BOOL)localFileContentSniffingEnabled
872 {
873     return [self _boolValueForKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
874 }
875
876 - (void)setLocalFileContentSniffingEnabled:(BOOL)flag
877 {
878     [self _setBoolValue:flag forKey:WebKitLocalFileContentSniffingEnabledPreferenceKey];
879 }
880
881 - (BOOL)offlineWebApplicationCacheEnabled
882 {
883     return [self _boolValueForKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey];
884 }
885
886 - (void)setOfflineWebApplicationCacheEnabled:(BOOL)flag
887 {
888     [self _setBoolValue:flag forKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey];
889 }
890
891 - (BOOL)zoomsTextOnly
892 {
893     return [self _boolValueForKey:WebKitZoomsTextOnlyPreferenceKey];
894 }
895
896 - (void)setZoomsTextOnly:(BOOL)flag
897 {
898     [self _setBoolValue:flag forKey:WebKitZoomsTextOnlyPreferenceKey];
899 }
900
901 - (BOOL)javaScriptCanAccessClipboard
902 {
903     return [self _boolValueForKey:WebKitJavaScriptCanAccessClipboardPreferenceKey];
904 }
905
906 - (void)setJavaScriptCanAccessClipboard:(BOOL)flag
907 {
908     [self _setBoolValue:flag forKey:WebKitJavaScriptCanAccessClipboardPreferenceKey];
909 }
910
911 - (BOOL)isXSSAuditorEnabled
912 {
913     return [self _boolValueForKey:WebKitXSSAuditorEnabledPreferenceKey];
914 }
915
916 - (void)setXSSAuditorEnabled:(BOOL)flag
917 {
918     [self _setBoolValue:flag forKey:WebKitXSSAuditorEnabledPreferenceKey];
919 }
920
921 - (BOOL)respectStandardStyleKeyEquivalents
922 {
923     return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
924 }
925
926 - (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag
927 {
928     [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
929 }
930
931 - (BOOL)showsURLsInToolTips
932 {
933     return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey];
934 }
935
936 - (void)setShowsURLsInToolTips:(BOOL)flag
937 {
938     [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey];
939 }
940
941 - (BOOL)textAreasAreResizable
942 {
943     return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey];
944 }
945
946 - (void)setTextAreasAreResizable:(BOOL)flag
947 {
948     [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey];
949 }
950
951 - (BOOL)shrinksStandaloneImagesToFit
952 {
953     return [self _boolValueForKey:WebKitShrinksStandaloneImagesToFitPreferenceKey];
954 }
955
956 - (void)setShrinksStandaloneImagesToFit:(BOOL)flag
957 {
958     [self _setBoolValue:flag forKey:WebKitShrinksStandaloneImagesToFitPreferenceKey];
959 }
960
961 - (BOOL)automaticallyDetectsCacheModel
962 {
963     return _private->automaticallyDetectsCacheModel;
964 }
965
966 - (void)setAutomaticallyDetectsCacheModel:(BOOL)automaticallyDetectsCacheModel
967 {
968     _private->automaticallyDetectsCacheModel = automaticallyDetectsCacheModel;
969 }
970
971 - (BOOL)usesEncodingDetector
972 {
973     return [self _boolValueForKey: WebKitUsesEncodingDetectorPreferenceKey];
974 }
975
976 - (void)setUsesEncodingDetector:(BOOL)flag
977 {
978     [self _setBoolValue: flag forKey: WebKitUsesEncodingDetectorPreferenceKey];
979 }
980
981 - (BOOL)isWebSecurityEnabled
982 {
983     return [self _boolValueForKey: WebKitWebSecurityEnabledPreferenceKey];
984 }
985
986 - (void)setWebSecurityEnabled:(BOOL)flag
987 {
988     [self _setBoolValue: flag forKey: WebKitWebSecurityEnabledPreferenceKey];
989 }
990
991 - (BOOL)allowUniversalAccessFromFileURLs
992 {
993     return [self _boolValueForKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey];
994 }
995
996 - (void)setAllowUniversalAccessFromFileURLs:(BOOL)flag
997 {
998     [self _setBoolValue: flag forKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey];
999 }
1000
1001 - (BOOL)allowFileAccessFromFileURLs
1002 {
1003     return [self _boolValueForKey: WebKitAllowFileAccessFromFileURLsPreferenceKey];
1004 }
1005
1006 - (void)setAllowFileAccessFromFileURLs:(BOOL)flag
1007 {
1008     [self _setBoolValue: flag forKey: WebKitAllowFileAccessFromFileURLsPreferenceKey];
1009 }
1010
1011 - (NSTimeInterval)_backForwardCacheExpirationInterval
1012 {
1013     // FIXME: There's probably no good reason to read from the standard user defaults instead of self.
1014     return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
1015 }
1016
1017 - (float)PDFScaleFactor
1018 {
1019     return [self _floatValueForKey:WebKitPDFScaleFactorPreferenceKey];
1020 }
1021
1022 - (void)setPDFScaleFactor:(float)factor
1023 {
1024     [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey];
1025 }
1026
1027 - (int64_t)applicationCacheTotalQuota
1028 {
1029     return [self _longLongValueForKey:WebKitApplicationCacheTotalQuota];
1030 }
1031
1032 - (void)setApplicationCacheTotalQuota:(int64_t)quota
1033 {
1034     [self _setLongLongValue:quota forKey:WebKitApplicationCacheTotalQuota];
1035
1036     // Application Cache Preferences are stored on the global cache storage manager, not in Settings.
1037     [WebApplicationCache setMaximumSize:quota];
1038 }
1039
1040 - (int64_t)applicationCacheDefaultOriginQuota
1041 {
1042     return [self _longLongValueForKey:WebKitApplicationCacheDefaultOriginQuota];
1043 }
1044
1045 - (void)setApplicationCacheDefaultOriginQuota:(int64_t)quota
1046 {
1047     [self _setLongLongValue:quota forKey:WebKitApplicationCacheDefaultOriginQuota];
1048 }
1049
1050 - (PDFDisplayMode)PDFDisplayMode
1051 {
1052     PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey];
1053     if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) {
1054         // protect against new modes from future versions of OS X stored in defaults
1055         value = kPDFDisplaySinglePageContinuous;
1056     }
1057     return value;
1058 }
1059
1060 - (void)setPDFDisplayMode:(PDFDisplayMode)mode
1061 {
1062     [self _setIntegerValue:mode forKey:WebKitPDFDisplayModePreferenceKey];
1063 }
1064
1065 - (WebKitEditableLinkBehavior)editableLinkBehavior
1066 {
1067     WebKitEditableLinkBehavior value = static_cast<WebKitEditableLinkBehavior> ([self _integerValueForKey:WebKitEditableLinkBehaviorPreferenceKey]);
1068     if (value != WebKitEditableLinkDefaultBehavior &&
1069         value != WebKitEditableLinkAlwaysLive &&
1070         value != WebKitEditableLinkNeverLive &&
1071         value != WebKitEditableLinkOnlyLiveWithShiftKey &&
1072         value != WebKitEditableLinkLiveWhenNotFocused) {
1073         // ensure that a valid result is returned
1074         value = WebKitEditableLinkDefaultBehavior;
1075     }
1076     
1077     return value;
1078 }
1079
1080 - (void)setEditableLinkBehavior:(WebKitEditableLinkBehavior)behavior
1081 {
1082     [self _setIntegerValue:behavior forKey:WebKitEditableLinkBehaviorPreferenceKey];
1083 }
1084
1085 - (WebTextDirectionSubmenuInclusionBehavior)textDirectionSubmenuInclusionBehavior
1086 {
1087     WebTextDirectionSubmenuInclusionBehavior value = static_cast<WebTextDirectionSubmenuInclusionBehavior>([self _integerValueForKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey]);
1088     if (value != WebTextDirectionSubmenuNeverIncluded &&
1089         value != WebTextDirectionSubmenuAutomaticallyIncluded &&
1090         value != WebTextDirectionSubmenuAlwaysIncluded) {
1091         // Ensure that a valid result is returned.
1092         value = WebTextDirectionSubmenuNeverIncluded;
1093     }
1094     return value;
1095 }
1096
1097 - (void)setTextDirectionSubmenuInclusionBehavior:(WebTextDirectionSubmenuInclusionBehavior)behavior
1098 {
1099     [self _setIntegerValue:behavior forKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey];
1100 }
1101
1102 - (BOOL)_useSiteSpecificSpoofing
1103 {
1104     return [self _boolValueForKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
1105 }
1106
1107 - (void)_setUseSiteSpecificSpoofing:(BOOL)newValue
1108 {
1109     [self _setBoolValue:newValue forKey:WebKitUseSiteSpecificSpoofingPreferenceKey];
1110 }
1111
1112 - (BOOL)databasesEnabled
1113 {
1114     return [self _boolValueForKey:WebKitDatabasesEnabledPreferenceKey];
1115 }
1116
1117 - (void)setDatabasesEnabled:(BOOL)databasesEnabled
1118 {
1119     [self _setBoolValue:databasesEnabled forKey:WebKitDatabasesEnabledPreferenceKey];
1120 }
1121
1122 - (BOOL)localStorageEnabled
1123 {
1124     return [self _boolValueForKey:WebKitLocalStorageEnabledPreferenceKey];
1125 }
1126
1127 - (void)setLocalStorageEnabled:(BOOL)localStorageEnabled
1128 {
1129     [self _setBoolValue:localStorageEnabled forKey:WebKitLocalStorageEnabledPreferenceKey];
1130 }
1131
1132 - (BOOL)experimentalNotificationsEnabled
1133 {
1134     return [self _boolValueForKey:WebKitExperimentalNotificationsEnabledPreferenceKey];
1135 }
1136
1137 - (void)setExperimentalNotificationsEnabled:(BOOL)experimentalNotificationsEnabled
1138 {
1139     [self _setBoolValue:experimentalNotificationsEnabled forKey:WebKitExperimentalNotificationsEnabledPreferenceKey];
1140 }
1141
1142 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
1143 {
1144     LOG(Encoding, "requesting for %@\n", ident);
1145
1146     if (!ident)
1147         return _standardPreferences;
1148     
1149     WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
1150
1151     return instance;
1152 }
1153
1154 + (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
1155 {
1156     if (!webPreferencesInstances)
1157         webPreferencesInstances = [[NSMutableDictionary alloc] init];
1158     if (ident) {
1159         [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
1160         LOG(Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
1161     }
1162 }
1163
1164 + (void)_checkLastReferenceForIdentifier:(id)identifier
1165 {
1166     // FIXME: This won't work at all under garbage collection because retainCount returns a constant.
1167     // We may need to change WebPreferences API so there's an explicit way to end the lifetime of one.
1168     WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
1169     if ([instance retainCount] == 1)
1170         [webPreferencesInstances removeObjectForKey:identifier];
1171 }
1172
1173 + (void)_removeReferenceForIdentifier:(NSString *)ident
1174 {
1175     if (ident)
1176         [self performSelector:@selector(_checkLastReferenceForIdentifier:) withObject:[self _concatenateKeyWithIBCreatorID:ident] afterDelay:0.1];
1177 }
1178
1179 - (void)_postPreferencesChangedNotification
1180 {
1181     if (!pthread_main_np()) {
1182         [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
1183         return;
1184     }
1185
1186     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedInternalNotification object:self userInfo:nil];
1187     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
1188 }
1189
1190 - (void)_postPreferencesChangedAPINotification
1191 {
1192     if (!pthread_main_np()) {
1193         [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
1194         return;
1195     }
1196
1197     [[NSNotificationCenter defaultCenter] postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
1198 }
1199
1200 + (CFStringEncoding)_systemCFStringEncoding
1201 {
1202     return WKGetWebDefaultCFStringEncoding();
1203 }
1204
1205 + (void)_setInitialDefaultTextEncodingToSystemEncoding
1206 {
1207     NSString *systemEncodingName = (NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding]);
1208
1209     // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-949.
1210     // ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-949.
1211     // In addition, this value must match what is used in Safari, see <rdar://problem/5579292>.
1212     // On some OS versions, the result is CP949 (uppercase).
1213     if ([systemEncodingName _webkit_isCaseInsensitiveEqualToString:@"cp949"])
1214         systemEncodingName = @"ks_c_5601-1987";
1215     [[NSUserDefaults standardUserDefaults] registerDefaults:
1216         [NSDictionary dictionaryWithObject:systemEncodingName forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
1217 }
1218
1219 static NSString *classIBCreatorID = nil;
1220
1221 + (void)_setIBCreatorID:(NSString *)string
1222 {
1223     NSString *old = classIBCreatorID;
1224     classIBCreatorID = [string copy];
1225     [old release];
1226 }
1227
1228 - (BOOL)isDOMPasteAllowed
1229 {
1230     return [self _boolValueForKey:WebKitDOMPasteAllowedPreferenceKey];
1231 }
1232
1233 - (void)setDOMPasteAllowed:(BOOL)DOMPasteAllowed
1234 {
1235     [self _setBoolValue:DOMPasteAllowed forKey:WebKitDOMPasteAllowedPreferenceKey];
1236 }
1237
1238 - (NSString *)_localStorageDatabasePath
1239 {
1240     return [[self _stringValueForKey:WebKitLocalStorageDatabasePathPreferenceKey] stringByStandardizingPath];
1241 }
1242
1243 - (void)_setLocalStorageDatabasePath:(NSString *)path
1244 {
1245     [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitLocalStorageDatabasePathPreferenceKey];
1246 }
1247
1248 - (NSString *)_ftpDirectoryTemplatePath
1249 {
1250     return [[self _stringValueForKey:WebKitFTPDirectoryTemplatePath] stringByStandardizingPath];
1251 }
1252
1253 - (void)_setFTPDirectoryTemplatePath:(NSString *)path
1254 {
1255     [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitFTPDirectoryTemplatePath];
1256 }
1257
1258 - (BOOL)_forceFTPDirectoryListings
1259 {
1260     return [self _boolValueForKey:WebKitForceFTPDirectoryListings];
1261 }
1262
1263 - (void)_setForceFTPDirectoryListings:(BOOL)force
1264 {
1265     [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings];
1266 }
1267
1268 - (BOOL)acceleratedDrawingEnabled
1269 {
1270     return [self _boolValueForKey:WebKitAcceleratedDrawingEnabledPreferenceKey];
1271 }
1272
1273 - (void)setAcceleratedDrawingEnabled:(BOOL)enabled
1274 {
1275     [self _setBoolValue:enabled forKey:WebKitAcceleratedDrawingEnabledPreferenceKey];
1276 }
1277
1278 - (BOOL)canvasUsesAcceleratedDrawing
1279 {
1280     return [self _boolValueForKey:WebKitCanvasUsesAcceleratedDrawingPreferenceKey];
1281 }
1282
1283 - (void)setCanvasUsesAcceleratedDrawing:(BOOL)enabled
1284 {
1285     [self _setBoolValue:enabled forKey:WebKitCanvasUsesAcceleratedDrawingPreferenceKey];
1286 }
1287
1288 - (BOOL)acceleratedCompositingEnabled
1289 {
1290     return [self _boolValueForKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
1291 }
1292
1293 - (void)setAcceleratedCompositingEnabled:(BOOL)enabled
1294 {
1295     [self _setBoolValue:enabled forKey:WebKitAcceleratedCompositingEnabledPreferenceKey];
1296 }
1297
1298 - (BOOL)showDebugBorders
1299 {
1300     return [self _boolValueForKey:WebKitShowDebugBordersPreferenceKey];
1301 }
1302
1303 - (void)setShowDebugBorders:(BOOL)enabled
1304 {
1305     [self _setBoolValue:enabled forKey:WebKitShowDebugBordersPreferenceKey];
1306 }
1307
1308 - (BOOL)showRepaintCounter
1309 {
1310     return [self _boolValueForKey:WebKitShowRepaintCounterPreferenceKey];
1311 }
1312
1313 - (void)setShowRepaintCounter:(BOOL)enabled
1314 {
1315     [self _setBoolValue:enabled forKey:WebKitShowRepaintCounterPreferenceKey];
1316 }
1317
1318 - (BOOL)webAudioEnabled
1319 {
1320     return [self _boolValueForKey:WebKitWebAudioEnabledPreferenceKey];
1321 }
1322
1323 - (void)setWebAudioEnabled:(BOOL)enabled
1324 {
1325     [self _setBoolValue:enabled forKey:WebKitWebAudioEnabledPreferenceKey];
1326 }
1327
1328 - (BOOL)webGLEnabled
1329 {
1330     return [self _boolValueForKey:WebKitWebGLEnabledPreferenceKey];
1331 }
1332
1333 - (void)setWebGLEnabled:(BOOL)enabled
1334 {
1335     [self _setBoolValue:enabled forKey:WebKitWebGLEnabledPreferenceKey];
1336 }
1337
1338 - (BOOL)accelerated2dCanvasEnabled
1339 {
1340     return [self _boolValueForKey:WebKitAccelerated2dCanvasEnabledPreferenceKey];
1341 }
1342
1343 - (void)setAccelerated2dCanvasEnabled:(BOOL)enabled
1344 {
1345     [self _setBoolValue:enabled forKey:WebKitAccelerated2dCanvasEnabledPreferenceKey];
1346 }
1347
1348 - (unsigned)pluginAllowedRunTime
1349 {
1350     return [self _integerValueForKey:WebKitPluginAllowedRunTimePreferenceKey];
1351 }
1352
1353 - (void)setPluginAllowedRunTime:(unsigned)allowedRunTime
1354 {
1355     return [self _setIntegerValue:allowedRunTime forKey:WebKitPluginAllowedRunTimePreferenceKey];
1356 }
1357
1358 - (BOOL)isFrameFlatteningEnabled
1359 {
1360     return [self _boolValueForKey:WebKitFrameFlatteningEnabledPreferenceKey];
1361 }
1362
1363 - (void)setFrameFlatteningEnabled:(BOOL)flag
1364 {
1365     [self _setBoolValue:flag forKey:WebKitFrameFlatteningEnabledPreferenceKey];
1366 }
1367
1368 - (BOOL)isSpatialNavigationEnabled
1369 {
1370     return [self _boolValueForKey:WebKitSpatialNavigationEnabledPreferenceKey];
1371 }
1372
1373 - (void)setSpatialNavigationEnabled:(BOOL)flag
1374 {
1375     [self _setBoolValue:flag forKey:WebKitSpatialNavigationEnabledPreferenceKey];
1376 }
1377
1378 - (BOOL)paginateDuringLayoutEnabled
1379 {
1380     return [self _boolValueForKey:WebKitPaginateDuringLayoutEnabledPreferenceKey];
1381 }
1382
1383 - (void)setPaginateDuringLayoutEnabled:(BOOL)flag
1384 {
1385     [self _setBoolValue:flag forKey:WebKitPaginateDuringLayoutEnabledPreferenceKey];
1386 }
1387
1388 - (BOOL)memoryInfoEnabled
1389 {
1390     return [self _boolValueForKey:WebKitMemoryInfoEnabledPreferenceKey];
1391 }
1392
1393 - (void)setMemoryInfoEnabled:(BOOL)flag
1394 {
1395     [self _setBoolValue:flag forKey:WebKitMemoryInfoEnabledPreferenceKey];
1396 }
1397
1398 - (BOOL)hyperlinkAuditingEnabled
1399 {
1400     return [self _boolValueForKey:WebKitHyperlinkAuditingEnabledPreferenceKey];
1401 }
1402
1403 - (void)setHyperlinkAuditingEnabled:(BOOL)flag
1404 {
1405     [self _setBoolValue:flag forKey:WebKitHyperlinkAuditingEnabledPreferenceKey];
1406 }
1407
1408 - (WebKitEditingBehavior)editingBehavior
1409 {
1410     return static_cast<WebKitEditingBehavior>([self _integerValueForKey:WebKitEditingBehaviorPreferenceKey]);
1411 }
1412
1413 - (void)setEditingBehavior:(WebKitEditingBehavior)behavior
1414 {
1415     [self _setIntegerValue:behavior forKey:WebKitEditingBehaviorPreferenceKey];
1416 }
1417
1418 - (BOOL)usePreHTML5ParserQuirks
1419 {
1420     return [self _boolValueForKey:WebKitUsePreHTML5ParserQuirksKey];
1421 }
1422
1423 - (void)setUsePreHTML5ParserQuirks:(BOOL)flag
1424 {
1425     [self _setBoolValue:flag forKey:WebKitUsePreHTML5ParserQuirksKey];
1426 }
1427
1428 - (BOOL)useQuickLookResourceCachingQuirks
1429 {
1430     return [self _boolValueForKey:WebKitUseQuickLookResourceCachingQuirksPreferenceKey];
1431 }
1432
1433 - (void)didRemoveFromWebView
1434 {
1435     ASSERT(_private->numWebViews);
1436     if (--_private->numWebViews == 0)
1437         [[NSNotificationCenter defaultCenter]
1438             postNotificationName:WebPreferencesRemovedNotification
1439                           object:self
1440                         userInfo:nil];
1441 }
1442
1443 - (void)willAddToWebView
1444 {
1445     ++_private->numWebViews;
1446 }
1447
1448 - (void)_setPreferenceForTestWithValue:(NSString *)value forKey:(NSString *)key
1449 {
1450     [self _setStringValue:value forKey:key];
1451 }
1452
1453 - (void)setFullScreenEnabled:(BOOL)flag
1454 {
1455     [self _setBoolValue:flag forKey:WebKitFullScreenEnabledPreferenceKey];
1456 }
1457
1458 - (BOOL)fullScreenEnabled
1459 {
1460     return [self _boolValueForKey:WebKitFullScreenEnabledPreferenceKey];
1461 }
1462
1463 - (void)setAsynchronousSpellCheckingEnabled:(BOOL)flag
1464 {
1465     [self _setBoolValue:flag forKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
1466 }
1467
1468 - (BOOL)asynchronousSpellCheckingEnabled
1469 {
1470     return [self _boolValueForKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
1471 }
1472
1473 + (void)setWebKitLinkTimeVersion:(int)version
1474 {
1475     setWebKitLinkTimeVersion(version);
1476 }
1477
1478 - (void)setLoadsSiteIconsIgnoringImageLoadingPreference: (BOOL)flag
1479 {
1480     [self _setBoolValue: flag forKey: WebKitLoadSiteIconsKey];
1481 }
1482
1483 - (BOOL)loadsSiteIconsIgnoringImageLoadingPreference
1484 {
1485     return [self _boolValueForKey: WebKitLoadSiteIconsKey];
1486 }
1487
1488 - (void)setAVFoundationEnabled:(BOOL)flag
1489 {
1490     [self _setBoolValue:flag forKey:WebKitAVFoundationEnabledKey];
1491 }
1492
1493 - (BOOL)isAVFoundationEnabled
1494 {
1495     return [self _boolValueForKey:WebKitAVFoundationEnabledKey];
1496 }
1497 @end
1498
1499 @implementation WebPreferences (WebInternal)
1500
1501 + (NSString *)_IBCreatorID
1502 {
1503     return classIBCreatorID;
1504 }
1505
1506 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
1507 {
1508     NSString *IBCreatorID = [WebPreferences _IBCreatorID];
1509     if (!IBCreatorID)
1510         return key;
1511     return [IBCreatorID stringByAppendingString:key];
1512 }
1513
1514 @end