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 "WebKitLogging.h" 34#import "WebKitNSStringExtras.h" 35#import "WebKitSystemBits.h" 36#import "WebKitSystemInterface.h" 37#import "WebKitVersionChecks.h" 38#import "WebNSDictionaryExtras.h" 39#import "WebNSURLExtras.h" 40 41NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification"; 42NSString *WebPreferencesRemovedNotification = @"WebPreferencesRemovedNotification"; 43 44#define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x)) 45 46enum { WebPreferencesVersion = 1 }; 47 48static WebPreferences *_standardPreferences; 49static NSMutableDictionary *webPreferencesInstances; 50 51static bool contains(const char* const array[], int count, const char* item) 52{ 53 if (!item) 54 return false; 55 56 for (int i = 0; i < count; i++) 57 if (!strcasecmp(array[i], item)) 58 return true; 59 return false; 60} 61 62static WebCacheModel cacheModelForMainBundle(void) 63{ 64 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 65 66 // Apps that probably need the small setting 67 static const char* const documentViewerIDs[] = { 68 "Microsoft/com.microsoft.Messenger", 69 "com.adiumX.adiumX", 70 "com.alientechnology.Proteus", 71 "com.apple.Dashcode", 72 "com.apple.iChat", 73 "com.barebones.bbedit", 74 "com.barebones.textwrangler", 75 "com.barebones.yojimbo", 76 "com.equinux.iSale4", 77 "com.growl.growlframework", 78 "com.intrarts.PandoraMan", 79 "com.karelia.Sandvox", 80 "com.macromates.textmate", 81 "com.realmacsoftware.rapidweaverpro", 82 "com.red-sweater.marsedit", 83 "com.yahoo.messenger3", 84 "de.codingmonkeys.SubEthaEdit", 85 "fi.karppinen.Pyro", 86 "info.colloquy", 87 "kungfoo.tv.ecto", 88 }; 89 90 // Apps that probably need the medium setting 91 static const char* const documentBrowserIDs[] = { 92 "com.apple.Dictionary", 93 "com.apple.Xcode", 94 "com.apple.dashboard.client", 95 "com.apple.helpviewer", 96 "com.culturedcode.xyle", 97 "com.macrabbit.CSSEdit", 98 "com.panic.Coda", 99 "com.ranchero.NetNewsWire", 100 "com.thinkmac.NewsLife", 101 "org.xlife.NewsFire", 102 "uk.co.opencommunity.vienna2", 103 }; 104 105 // Apps that probably need the large setting 106 static const char* const primaryWebBrowserIDs[] = { 107 "com.app4mac.KidsBrowser" 108 "com.app4mac.wKiosk", 109 "com.freeverse.bumpercar", 110 "com.omnigroup.OmniWeb5", 111 "com.sunrisebrowser.Sunrise", 112 "net.hmdt-web.Shiira", 113 }; 114 115 WebCacheModel cacheModel; 116 117 const char* bundleID = [[[NSBundle mainBundle] bundleIdentifier] UTF8String]; 118 if (contains(documentViewerIDs, sizeof(documentViewerIDs) / sizeof(documentViewerIDs[0]), bundleID)) 119 cacheModel = WebCacheModelDocumentViewer; 120 else if (contains(documentBrowserIDs, sizeof(documentBrowserIDs) / sizeof(documentBrowserIDs[0]), bundleID)) 121 cacheModel = WebCacheModelDocumentBrowser; 122 else if (contains(primaryWebBrowserIDs, sizeof(primaryWebBrowserIDs) / sizeof(primaryWebBrowserIDs[0]), bundleID)) 123 cacheModel = WebCacheModelPrimaryWebBrowser; 124 else { 125 bool isLegacyApp = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_CACHE_MODEL_API); 126 if (isLegacyApp) 127 cacheModel = WebCacheModelDocumentBrowser; // To avoid regressions in apps that depended on old WebKit's large cache. 128 else 129 cacheModel = WebCacheModelDocumentViewer; // To save memory. 130 } 131 132 [pool drain]; 133 134 return cacheModel; 135} 136 137@interface WebPreferencesPrivate : NSObject 138{ 139@public 140 NSMutableDictionary *values; 141 NSString *identifier; 142 NSString *IBCreatorID; 143 BOOL autosaves; 144 BOOL automaticallyDetectsCacheModel; 145 unsigned numWebViews; 146} 147@end 148 149@implementation WebPreferencesPrivate 150- (void)dealloc 151{ 152 [values release]; 153 [identifier release]; 154 [IBCreatorID release]; 155 [super dealloc]; 156} 157@end 158 159@interface WebPreferences (WebInternal) 160+ (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key; 161+ (NSString *)_IBCreatorID; 162@end 163 164@interface WebPreferences (WebForwardDeclarations) 165// This pseudo-category is needed so these methods can be used from within other category implementations 166// without being in the public header file. 167- (BOOL)_boolValueForKey:(NSString *)key; 168- (void)_setBoolValue:(BOOL)value forKey:(NSString *)key; 169- (int)_integerValueForKey:(NSString *)key; 170- (void)_setIntegerValue:(int)value forKey:(NSString *)key; 171- (float)_floatValueForKey:(NSString *)key; 172- (void)_setFloatValue:(float)value forKey:(NSString *)key; 173- (void)_setUnsignedLongLongValue:(unsigned long long)value forKey:(NSString *)key; 174- (unsigned long long)_unsignedLongLongValueForKey:(NSString *)key; 175@end 176 177@implementation WebPreferences 178 179- init 180{ 181 // Create fake identifier 182 static int instanceCount = 1; 183 NSString *fakeIdentifier; 184 185 // At least ensure that identifier hasn't been already used. 186 fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++]; 187 while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){ 188 fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++]; 189 } 190 191 return [self initWithIdentifier:fakeIdentifier]; 192} 193 194- (id)initWithIdentifier:(NSString *)anIdentifier 195{ 196 self = [super init]; 197 if (!self) 198 return nil; 199 200 _private = [[WebPreferencesPrivate alloc] init]; 201 _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain]; 202 203 WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier]; 204 if (instance){ 205 [self release]; 206 return [instance retain]; 207 } 208 209 _private->values = [[NSMutableDictionary alloc] init]; 210 _private->identifier = [anIdentifier copy]; 211 _private->automaticallyDetectsCacheModel = YES; 212 213 [[self class] _setInstance:self forIdentifier:_private->identifier]; 214 215 [self _postPreferencesChangesNotification]; 216 217 return self; 218} 219 220- (id)initWithCoder:(NSCoder *)decoder 221{ 222 self = [super init]; 223 if (!self) 224 return nil; 225 226 _private = [[WebPreferencesPrivate alloc] init]; 227 _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain]; 228 _private->automaticallyDetectsCacheModel = YES; 229 230 @try { 231 id identifier = nil; 232 id values = nil; 233 if ([decoder allowsKeyedCoding]) { 234 identifier = [decoder decodeObjectForKey:@"Identifier"]; 235 values = [decoder decodeObjectForKey:@"Values"]; 236 } else { 237 int version; 238 [decoder decodeValueOfObjCType:@encode(int) at:&version]; 239 if (version == 1) { 240 identifier = [decoder decodeObject]; 241 values = [decoder decodeObject]; 242 } 243 } 244 245 if ([identifier isKindOfClass:[NSString class]]) 246 _private->identifier = [identifier copy]; 247 if ([values isKindOfClass:[NSDictionary class]]) 248 _private->values = [values mutableCopy]; // ensure dictionary is mutable 249 250 LOG(Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values); 251 } @catch(id) { 252 [self release]; 253 return nil; 254 } 255 256 // If we load a nib multiple times, or have instances in multiple 257 // nibs with the same name, the first guy up wins. 258 WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier]; 259 if (instance) { 260 [self release]; 261 self = [instance retain]; 262 } else { 263 [[self class] _setInstance:self forIdentifier:_private->identifier]; 264 } 265 266 return self; 267} 268 269- (void)encodeWithCoder:(NSCoder *)encoder 270{ 271 if ([encoder allowsKeyedCoding]){ 272 [encoder encodeObject:_private->identifier forKey:@"Identifier"]; 273 [encoder encodeObject:_private->values forKey:@"Values"]; 274 LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values); 275 } 276 else { 277 int version = WebPreferencesVersion; 278 [encoder encodeValueOfObjCType:@encode(int) at:&version]; 279 [encoder encodeObject:_private->identifier]; 280 [encoder encodeObject:_private->values]; 281 } 282} 283 284+ (WebPreferences *)standardPreferences 285{ 286 if (_standardPreferences == nil) { 287 _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil]; 288 [_standardPreferences setAutosaves:YES]; 289 } 290 291 return _standardPreferences; 292} 293 294// if we ever have more than one WebPreferences object, this would move to init 295+ (void)initialize 296{ 297 NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 298 @"Times", WebKitStandardFontPreferenceKey, 299 @"Courier", WebKitFixedFontPreferenceKey, 300 @"Times", WebKitSerifFontPreferenceKey, 301 @"Helvetica", WebKitSansSerifFontPreferenceKey, 302 @"Apple Chancery", WebKitCursiveFontPreferenceKey, 303 @"Papyrus", WebKitFantasyFontPreferenceKey, 304 @"1", WebKitMinimumFontSizePreferenceKey, 305 @"9", WebKitMinimumLogicalFontSizePreferenceKey, 306 @"16", WebKitDefaultFontSizePreferenceKey, 307 @"13", WebKitDefaultFixedFontSizePreferenceKey, 308 @"ISO-8859-1", WebKitDefaultTextEncodingNamePreferenceKey, 309 [NSNumber numberWithBool:NO], WebKitUsesEncodingDetectorPreferenceKey, 310 [NSNumber numberWithBool:NO], WebKitUserStyleSheetEnabledPreferenceKey, 311 @"", WebKitUserStyleSheetLocationPreferenceKey, 312 [NSNumber numberWithBool:NO], WebKitShouldPrintBackgroundsPreferenceKey, 313 [NSNumber numberWithBool:NO], WebKitTextAreasAreResizablePreferenceKey, 314 [NSNumber numberWithBool:NO], WebKitShrinksStandaloneImagesToFitPreferenceKey, 315 [NSNumber numberWithBool:YES], WebKitJavaEnabledPreferenceKey, 316 [NSNumber numberWithBool:YES], WebKitJavaScriptEnabledPreferenceKey, 317 [NSNumber numberWithBool:YES], WebKitWebSecurityEnabledPreferenceKey, 318 [NSNumber numberWithBool:YES], WebKitAllowUniversalAccessFromFileURLsPreferenceKey, 319 [NSNumber numberWithBool:YES], WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey, 320 [NSNumber numberWithBool:YES], WebKitPluginsEnabledPreferenceKey, 321 [NSNumber numberWithBool:YES], WebKitDatabasesEnabledPreferenceKey, 322 [NSNumber numberWithBool:YES], WebKitLocalStorageEnabledPreferenceKey, 323 [NSNumber numberWithBool:YES], WebKitAllowAnimatedImagesPreferenceKey, 324 [NSNumber numberWithBool:YES], WebKitAllowAnimatedImageLoopingPreferenceKey, 325 [NSNumber numberWithBool:YES], WebKitDisplayImagesKey, 326 @"1800", WebKitBackForwardCacheExpirationIntervalKey, 327 [NSNumber numberWithBool:NO], WebKitTabToLinksPreferenceKey, 328 [NSNumber numberWithBool:NO], WebKitPrivateBrowsingEnabledPreferenceKey, 329 [NSNumber numberWithBool:NO], WebKitRespectStandardStyleKeyEquivalentsPreferenceKey, 330 [NSNumber numberWithBool:NO], WebKitShowsURLsInToolTipsPreferenceKey, 331 @"1", WebKitPDFDisplayModePreferenceKey, 332 @"0", WebKitPDFScaleFactorPreferenceKey, 333 @"0", WebKitUseSiteSpecificSpoofingPreferenceKey, 334 [NSNumber numberWithInt:WebKitEditableLinkDefaultBehavior], WebKitEditableLinkBehaviorPreferenceKey, 335#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) 336 [NSNumber numberWithInt:WebTextDirectionSubmenuAutomaticallyIncluded], 337#else 338 [NSNumber numberWithInt:WebTextDirectionSubmenuNeverIncluded], 339#endif 340 WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey, 341 [NSNumber numberWithBool:NO], WebKitDOMPasteAllowedPreferenceKey, 342 [NSNumber numberWithBool:YES], WebKitUsesPageCachePreferenceKey, 343 [NSNumber numberWithInt:cacheModelForMainBundle()], WebKitCacheModelPreferenceKey, 344 [NSNumber numberWithBool:NO], WebKitDeveloperExtrasEnabledPreferenceKey, 345 [NSNumber numberWithBool:YES], WebKitAuthorAndUserStylesEnabledPreferenceKey, 346 [NSNumber numberWithBool:NO], WebKitApplicationChromeModeEnabledPreferenceKey, 347 [NSNumber numberWithBool:NO], WebKitWebArchiveDebugModeEnabledPreferenceKey, 348 [NSNumber numberWithBool:NO], WebKitLocalFileContentSniffingEnabledPreferenceKey, 349 [NSNumber numberWithBool:NO], WebKitOfflineWebApplicationCacheEnabledPreferenceKey, 350 [NSNumber numberWithBool:YES], WebKitZoomsTextOnlyPreferenceKey, 351 [NSNumber numberWithBool:YES], WebKitXSSAuditorEnabledPreferenceKey, 352 [NSNumber numberWithBool:YES], WebKitAcceleratedCompositingEnabledPreferenceKey, 353 nil]; 354 355 // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above 356 ASSERT(kPDFDisplaySinglePageContinuous == 1); 357 [[NSUserDefaults standardUserDefaults] registerDefaults:dict]; 358} 359 360- (void)dealloc 361{ 362 [_private release]; 363 [super dealloc]; 364} 365 366- (NSString *)identifier 367{ 368 return _private->identifier; 369} 370 371- (id)_valueForKey:(NSString *)key 372{ 373 NSString *_key = KEY(key); 374 id o = [_private->values objectForKey:_key]; 375 if (o) 376 return o; 377 o = [[NSUserDefaults standardUserDefaults] objectForKey:_key]; 378 if (!o && key != _key) 379 o = [[NSUserDefaults standardUserDefaults] objectForKey:key]; 380 return o; 381} 382 383- (NSString *)_stringValueForKey:(NSString *)key 384{ 385 id s = [self _valueForKey:key]; 386 return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil; 387} 388 389- (void)_setStringValue:(NSString *)value forKey:(NSString *)key 390{ 391 if ([[self _stringValueForKey:key] isEqualToString:value]) 392 return; 393 NSString *_key = KEY(key); 394 [_private->values setObject:value forKey:_key]; 395 if (_private->autosaves) 396 [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key]; 397 [self _postPreferencesChangesNotification]; 398} 399 400- (int)_integerValueForKey:(NSString *)key 401{ 402 id o = [self _valueForKey:key]; 403 return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0; 404} 405 406- (void)_setIntegerValue:(int)value forKey:(NSString *)key 407{ 408 if ([self _integerValueForKey:key] == value) 409 return; 410 NSString *_key = KEY(key); 411 [_private->values _webkit_setInt:value forKey:_key]; 412 if (_private->autosaves) 413 [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key]; 414 [self _postPreferencesChangesNotification]; 415} 416 417- (float)_floatValueForKey:(NSString *)key 418{ 419 id o = [self _valueForKey:key]; 420 return [o respondsToSelector:@selector(floatValue)] ? [o floatValue] : 0.0f; 421} 422 423- (void)_setFloatValue:(float)value forKey:(NSString *)key 424{ 425 if ([self _floatValueForKey:key] == value) 426 return; 427 NSString *_key = KEY(key); 428 [_private->values _webkit_setFloat:value forKey:_key]; 429 if (_private->autosaves) 430 [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key]; 431 [self _postPreferencesChangesNotification]; 432} 433 434- (BOOL)_boolValueForKey:(NSString *)key 435{ 436 return [self _integerValueForKey:key] != 0; 437} 438 439- (void)_setBoolValue:(BOOL)value forKey:(NSString *)key 440{ 441 if ([self _boolValueForKey:key] == value) 442 return; 443 NSString *_key = KEY(key); 444 [_private->values _webkit_setBool:value forKey:_key]; 445 if (_private->autosaves) 446 [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key]; 447 [self _postPreferencesChangesNotification]; 448} 449 450- (unsigned long long)_unsignedLongLongValueForKey:(NSString *)key 451{ 452 id o = [self _valueForKey:key]; 453 return [o respondsToSelector:@selector(unsignedLongLongValue)] ? [o unsignedLongLongValue] : 0; 454} 455 456- (void)_setUnsignedLongLongValue:(unsigned long long)value forKey:(NSString *)key 457{ 458 if ([self _unsignedLongLongValueForKey:key] == value) 459 return; 460 NSString *_key = KEY(key); 461 [_private->values _webkit_setUnsignedLongLong:value forKey:_key]; 462 if (_private->autosaves) 463 [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedLongLong:value] forKey:_key]; 464 [self _postPreferencesChangesNotification]; 465} 466 467- (NSString *)standardFontFamily 468{ 469 return [self _stringValueForKey: WebKitStandardFontPreferenceKey]; 470} 471 472- (void)setStandardFontFamily:(NSString *)family 473{ 474 [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey]; 475} 476 477- (NSString *)fixedFontFamily 478{ 479 return [self _stringValueForKey: WebKitFixedFontPreferenceKey]; 480} 481 482- (void)setFixedFontFamily:(NSString *)family 483{ 484 [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey]; 485} 486 487- (NSString *)serifFontFamily 488{ 489 return [self _stringValueForKey: WebKitSerifFontPreferenceKey]; 490} 491 492- (void)setSerifFontFamily:(NSString *)family 493{ 494 [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey]; 495} 496 497- (NSString *)sansSerifFontFamily 498{ 499 return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey]; 500} 501 502- (void)setSansSerifFontFamily:(NSString *)family 503{ 504 [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey]; 505} 506 507- (NSString *)cursiveFontFamily 508{ 509 return [self _stringValueForKey: WebKitCursiveFontPreferenceKey]; 510} 511 512- (void)setCursiveFontFamily:(NSString *)family 513{ 514 [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey]; 515} 516 517- (NSString *)fantasyFontFamily 518{ 519 return [self _stringValueForKey: WebKitFantasyFontPreferenceKey]; 520} 521 522- (void)setFantasyFontFamily:(NSString *)family 523{ 524 [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey]; 525} 526 527- (int)defaultFontSize 528{ 529 return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey]; 530} 531 532- (void)setDefaultFontSize:(int)size 533{ 534 [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey]; 535} 536 537- (int)defaultFixedFontSize 538{ 539 return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey]; 540} 541 542- (void)setDefaultFixedFontSize:(int)size 543{ 544 [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey]; 545} 546 547- (int)minimumFontSize 548{ 549 return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey]; 550} 551 552- (void)setMinimumFontSize:(int)size 553{ 554 [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey]; 555} 556 557- (int)minimumLogicalFontSize 558{ 559 return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey]; 560} 561 562- (void)setMinimumLogicalFontSize:(int)size 563{ 564 [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey]; 565} 566 567- (NSString *)defaultTextEncodingName 568{ 569 return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey]; 570} 571 572- (void)setDefaultTextEncodingName:(NSString *)encoding 573{ 574 [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey]; 575} 576 577- (BOOL)userStyleSheetEnabled 578{ 579 return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey]; 580} 581 582- (void)setUserStyleSheetEnabled:(BOOL)flag 583{ 584 [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey]; 585} 586 587- (NSURL *)userStyleSheetLocation 588{ 589 NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey]; 590 591 if ([locationString _webkit_looksLikeAbsoluteURL]) { 592 return [NSURL _web_URLWithDataAsString:locationString]; 593 } else { 594 locationString = [locationString stringByExpandingTildeInPath]; 595 return [NSURL fileURLWithPath:locationString]; 596 } 597} 598 599- (void)setUserStyleSheetLocation:(NSURL *)URL 600{ 601 NSString *locationString; 602 603 if ([URL isFileURL]) { 604 locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath]; 605 } else { 606 locationString = [URL _web_originalDataAsString]; 607 } 608 609 [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey]; 610} 611 612- (BOOL)shouldPrintBackgrounds 613{ 614 return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey]; 615} 616 617- (void)setShouldPrintBackgrounds:(BOOL)flag 618{ 619 [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey]; 620} 621 622- (BOOL)isJavaEnabled 623{ 624 return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey]; 625} 626 627- (void)setJavaEnabled:(BOOL)flag 628{ 629 [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey]; 630} 631 632- (BOOL)isJavaScriptEnabled 633{ 634 return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey]; 635} 636 637- (void)setJavaScriptEnabled:(BOOL)flag 638{ 639 [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey]; 640} 641 642- (BOOL)javaScriptCanOpenWindowsAutomatically 643{ 644 return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey]; 645} 646 647- (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag 648{ 649 [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey]; 650} 651 652- (BOOL)arePlugInsEnabled 653{ 654 return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey]; 655} 656 657- (void)setPlugInsEnabled:(BOOL)flag 658{ 659 [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey]; 660} 661 662- (BOOL)allowsAnimatedImages 663{ 664 return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey]; 665} 666 667- (void)setAllowsAnimatedImages:(BOOL)flag 668{ 669 [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey]; 670} 671 672- (BOOL)allowsAnimatedImageLooping 673{ 674 return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey]; 675} 676 677- (void)setAllowsAnimatedImageLooping: (BOOL)flag 678{ 679 [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey]; 680} 681 682- (void)setLoadsImagesAutomatically: (BOOL)flag 683{ 684 [self _setBoolValue: flag forKey: WebKitDisplayImagesKey]; 685} 686 687- (BOOL)loadsImagesAutomatically 688{ 689 return [self _boolValueForKey: WebKitDisplayImagesKey]; 690} 691 692- (void)setAutosaves:(BOOL)flag 693{ 694 _private->autosaves = flag; 695} 696 697- (BOOL)autosaves 698{ 699 return _private->autosaves; 700} 701 702- (void)setTabsToLinks:(BOOL)flag 703{ 704 [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey]; 705} 706 707- (BOOL)tabsToLinks 708{ 709 return [self _boolValueForKey:WebKitTabToLinksPreferenceKey]; 710} 711 712- (void)setPrivateBrowsingEnabled:(BOOL)flag 713{ 714 [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey]; 715} 716 717- (BOOL)privateBrowsingEnabled 718{ 719 return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey]; 720} 721 722- (void)setUsesPageCache:(BOOL)usesPageCache 723{ 724 [self _setBoolValue:usesPageCache forKey:WebKitUsesPageCachePreferenceKey]; 725} 726 727- (BOOL)usesPageCache 728{ 729 return [self _boolValueForKey:WebKitUsesPageCachePreferenceKey]; 730} 731 732- (void)setCacheModel:(WebCacheModel)cacheModel 733{ 734 [self _setIntegerValue:cacheModel forKey:WebKitCacheModelPreferenceKey]; 735 [self setAutomaticallyDetectsCacheModel:NO]; 736} 737 738- (WebCacheModel)cacheModel 739{ 740 return [self _integerValueForKey:WebKitCacheModelPreferenceKey]; 741} 742 743@end 744 745@implementation WebPreferences (WebPrivate) 746 747- (BOOL)developerExtrasEnabled 748{ 749 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 750 if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"]) 751 return NO; 752#ifdef NDEBUG 753 if ([defaults boolForKey:@"WebKitDeveloperExtras"] || [defaults boolForKey:@"IncludeDebugMenu"]) 754 return YES; 755 return [self _boolValueForKey:WebKitDeveloperExtrasEnabledPreferenceKey]; 756#else 757 return YES; // always enable in debug builds 758#endif 759} 760 761- (void)setDeveloperExtrasEnabled:(BOOL)flag 762{ 763 [self _setBoolValue:flag forKey:WebKitDeveloperExtrasEnabledPreferenceKey]; 764} 765 766- (BOOL)authorAndUserStylesEnabled 767{ 768 return [self _boolValueForKey:WebKitAuthorAndUserStylesEnabledPreferenceKey]; 769} 770 771- (void)setAuthorAndUserStylesEnabled:(BOOL)flag 772{ 773 [self _setBoolValue:flag forKey:WebKitAuthorAndUserStylesEnabledPreferenceKey]; 774} 775 776- (BOOL)applicationChromeModeEnabled 777{ 778 return [self _boolValueForKey:WebKitApplicationChromeModeEnabledPreferenceKey]; 779} 780 781- (void)setApplicationChromeModeEnabled:(BOOL)flag 782{ 783 [self _setBoolValue:flag forKey:WebKitApplicationChromeModeEnabledPreferenceKey]; 784} 785 786- (BOOL)webArchiveDebugModeEnabled 787{ 788 return [self _boolValueForKey:WebKitWebArchiveDebugModeEnabledPreferenceKey]; 789} 790 791- (void)setWebArchiveDebugModeEnabled:(BOOL)flag 792{ 793 [self _setBoolValue:flag forKey:WebKitWebArchiveDebugModeEnabledPreferenceKey]; 794} 795 796- (BOOL)localFileContentSniffingEnabled 797{ 798 return [self _boolValueForKey:WebKitLocalFileContentSniffingEnabledPreferenceKey]; 799} 800 801- (void)setLocalFileContentSniffingEnabled:(BOOL)flag 802{ 803 [self _setBoolValue:flag forKey:WebKitLocalFileContentSniffingEnabledPreferenceKey]; 804} 805 806- (BOOL)offlineWebApplicationCacheEnabled 807{ 808 return [self _boolValueForKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey]; 809} 810 811- (void)setOfflineWebApplicationCacheEnabled:(BOOL)flag 812{ 813 [self _setBoolValue:flag forKey:WebKitOfflineWebApplicationCacheEnabledPreferenceKey]; 814} 815 816- (BOOL)zoomsTextOnly 817{ 818 return [self _boolValueForKey:WebKitZoomsTextOnlyPreferenceKey]; 819} 820 821- (void)setZoomsTextOnly:(BOOL)flag 822{ 823 [self _setBoolValue:flag forKey:WebKitZoomsTextOnlyPreferenceKey]; 824} 825 826- (BOOL)isXSSAuditorEnabled 827{ 828 return [self _boolValueForKey:WebKitXSSAuditorEnabledPreferenceKey]; 829} 830 831- (void)setXSSAuditorEnabled:(BOOL)flag 832{ 833 [self _setBoolValue:flag forKey:WebKitXSSAuditorEnabledPreferenceKey]; 834} 835 836- (BOOL)respectStandardStyleKeyEquivalents 837{ 838 return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey]; 839} 840 841- (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag 842{ 843 [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey]; 844} 845 846- (BOOL)showsURLsInToolTips 847{ 848 return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey]; 849} 850 851- (void)setShowsURLsInToolTips:(BOOL)flag 852{ 853 [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey]; 854} 855 856- (BOOL)textAreasAreResizable 857{ 858 return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey]; 859} 860 861- (void)setTextAreasAreResizable:(BOOL)flag 862{ 863 [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey]; 864} 865 866- (BOOL)shrinksStandaloneImagesToFit 867{ 868 return [self _boolValueForKey:WebKitShrinksStandaloneImagesToFitPreferenceKey]; 869} 870 871- (void)setShrinksStandaloneImagesToFit:(BOOL)flag 872{ 873 [self _setBoolValue:flag forKey:WebKitShrinksStandaloneImagesToFitPreferenceKey]; 874} 875 876- (BOOL)automaticallyDetectsCacheModel 877{ 878 return _private->automaticallyDetectsCacheModel; 879} 880 881- (void)setAutomaticallyDetectsCacheModel:(BOOL)automaticallyDetectsCacheModel 882{ 883 _private->automaticallyDetectsCacheModel = automaticallyDetectsCacheModel; 884} 885 886- (BOOL)usesEncodingDetector 887{ 888 return [self _boolValueForKey: WebKitUsesEncodingDetectorPreferenceKey]; 889} 890 891- (void)setUsesEncodingDetector:(BOOL)flag 892{ 893 [self _setBoolValue: flag forKey: WebKitUsesEncodingDetectorPreferenceKey]; 894} 895 896- (BOOL)isWebSecurityEnabled 897{ 898 return [self _boolValueForKey: WebKitWebSecurityEnabledPreferenceKey]; 899} 900 901- (void)setWebSecurityEnabled:(BOOL)flag 902{ 903 [self _setBoolValue: flag forKey: WebKitWebSecurityEnabledPreferenceKey]; 904} 905 906- (BOOL)allowUniversalAccessFromFileURLs 907{ 908 return [self _boolValueForKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey]; 909} 910 911- (void)setAllowUniversalAccessFromFileURLs:(BOOL)flag 912{ 913 [self _setBoolValue: flag forKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey]; 914} 915 916- (NSTimeInterval)_backForwardCacheExpirationInterval 917{ 918 // FIXME: There's probably no good reason to read from the standard user defaults instead of self. 919 return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey]; 920} 921 922- (float)PDFScaleFactor 923{ 924 return [self _floatValueForKey:WebKitPDFScaleFactorPreferenceKey]; 925} 926 927- (void)setPDFScaleFactor:(float)factor 928{ 929 [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey]; 930} 931 932- (PDFDisplayMode)PDFDisplayMode 933{ 934 PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey]; 935 if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) { 936 // protect against new modes from future versions of OS X stored in defaults 937 value = kPDFDisplaySinglePageContinuous; 938 } 939 return value; 940} 941 942- (void)setPDFDisplayMode:(PDFDisplayMode)mode 943{ 944 [self _setIntegerValue:mode forKey:WebKitPDFDisplayModePreferenceKey]; 945} 946 947- (WebKitEditableLinkBehavior)editableLinkBehavior 948{ 949 WebKitEditableLinkBehavior value = static_cast<WebKitEditableLinkBehavior> ([self _integerValueForKey:WebKitEditableLinkBehaviorPreferenceKey]); 950 if (value != WebKitEditableLinkDefaultBehavior && 951 value != WebKitEditableLinkAlwaysLive && 952 value != WebKitEditableLinkNeverLive && 953 value != WebKitEditableLinkOnlyLiveWithShiftKey && 954 value != WebKitEditableLinkLiveWhenNotFocused) { 955 // ensure that a valid result is returned 956 value = WebKitEditableLinkDefaultBehavior; 957 } 958 959 return value; 960} 961 962- (void)setEditableLinkBehavior:(WebKitEditableLinkBehavior)behavior 963{ 964 [self _setIntegerValue:behavior forKey:WebKitEditableLinkBehaviorPreferenceKey]; 965} 966 967- (WebTextDirectionSubmenuInclusionBehavior)textDirectionSubmenuInclusionBehavior 968{ 969 WebTextDirectionSubmenuInclusionBehavior value = static_cast<WebTextDirectionSubmenuInclusionBehavior>([self _integerValueForKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey]); 970 if (value != WebTextDirectionSubmenuNeverIncluded && 971 value != WebTextDirectionSubmenuAutomaticallyIncluded && 972 value != WebTextDirectionSubmenuAlwaysIncluded) { 973 // Ensure that a valid result is returned. 974 value = WebTextDirectionSubmenuNeverIncluded; 975 } 976 return value; 977} 978 979- (void)setTextDirectionSubmenuInclusionBehavior:(WebTextDirectionSubmenuInclusionBehavior)behavior 980{ 981 [self _setIntegerValue:behavior forKey:WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey]; 982} 983 984- (BOOL)_useSiteSpecificSpoofing 985{ 986 return [self _boolValueForKey:WebKitUseSiteSpecificSpoofingPreferenceKey]; 987} 988 989- (void)_setUseSiteSpecificSpoofing:(BOOL)newValue 990{ 991 [self _setBoolValue:newValue forKey:WebKitUseSiteSpecificSpoofingPreferenceKey]; 992} 993 994- (BOOL)databasesEnabled 995{ 996 return [self _boolValueForKey:WebKitDatabasesEnabledPreferenceKey]; 997} 998 999- (void)setDatabasesEnabled:(BOOL)databasesEnabled 1000{ 1001 [self _setBoolValue:databasesEnabled forKey:WebKitDatabasesEnabledPreferenceKey]; 1002} 1003 1004- (BOOL)localStorageEnabled 1005{ 1006 return [self _boolValueForKey:WebKitLocalStorageEnabledPreferenceKey]; 1007} 1008 1009- (void)setLocalStorageEnabled:(BOOL)localStorageEnabled 1010{ 1011 [self _setBoolValue:localStorageEnabled forKey:WebKitLocalStorageEnabledPreferenceKey]; 1012} 1013 1014+ (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident 1015{ 1016 LOG(Encoding, "requesting for %@\n", ident); 1017 1018 if (!ident) 1019 return _standardPreferences; 1020 1021 WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]]; 1022 1023 return instance; 1024} 1025 1026+ (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident 1027{ 1028 if (!webPreferencesInstances) 1029 webPreferencesInstances = [[NSMutableDictionary alloc] init]; 1030 if (ident) { 1031 [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]]; 1032 LOG(Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]); 1033 } 1034} 1035 1036+ (void)_checkLastReferenceForIdentifier:(id)identifier 1037{ 1038 // FIXME: This won't work at all under garbage collection because retainCount returns a constant. 1039 // We may need to change WebPreferences API so there's an explicit way to end the lifetime of one. 1040 WebPreferences *instance = [webPreferencesInstances objectForKey:identifier]; 1041 if ([instance retainCount] == 1) 1042 [webPreferencesInstances removeObjectForKey:identifier]; 1043} 1044 1045+ (void)_removeReferenceForIdentifier:(NSString *)ident 1046{ 1047 if (ident) 1048 [self performSelector:@selector(_checkLastReferenceForIdentifier:) withObject:[self _concatenateKeyWithIBCreatorID:ident] afterDelay:0.1]; 1049} 1050 1051- (void)_postPreferencesChangesNotification 1052{ 1053 if (!pthread_main_np()) { 1054 [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO]; 1055 return; 1056 } 1057 1058 [[NSNotificationCenter defaultCenter] 1059 postNotificationName:WebPreferencesChangedNotification object:self 1060 userInfo:nil]; 1061} 1062 1063+ (CFStringEncoding)_systemCFStringEncoding 1064{ 1065 return WKGetWebDefaultCFStringEncoding(); 1066} 1067 1068+ (void)_setInitialDefaultTextEncodingToSystemEncoding 1069{ 1070 NSString *systemEncodingName = (NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding]); 1071 1072 // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-939. 1073 // ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-939. 1074 // In addition, this value must match what is used in Safari, see <rdar://problem/5579292>. 1075 // On some OS versions, the result is CP949 (uppercase). 1076 if ([systemEncodingName _webkit_isCaseInsensitiveEqualToString:@"cp949"]) 1077 systemEncodingName = @"ks_c_5601-1987"; 1078 [[NSUserDefaults standardUserDefaults] registerDefaults: 1079 [NSDictionary dictionaryWithObject:systemEncodingName forKey:WebKitDefaultTextEncodingNamePreferenceKey]]; 1080} 1081 1082static NSString *classIBCreatorID = nil; 1083 1084+ (void)_setIBCreatorID:(NSString *)string 1085{ 1086 NSString *old = classIBCreatorID; 1087 classIBCreatorID = [string copy]; 1088 [old release]; 1089} 1090 1091- (BOOL)isDOMPasteAllowed 1092{ 1093 return [self _boolValueForKey:WebKitDOMPasteAllowedPreferenceKey]; 1094} 1095 1096- (void)setDOMPasteAllowed:(BOOL)DOMPasteAllowed 1097{ 1098 [self _setBoolValue:DOMPasteAllowed forKey:WebKitDOMPasteAllowedPreferenceKey]; 1099} 1100 1101- (NSString *)_localStorageDatabasePath 1102{ 1103 return [[self _stringValueForKey:WebKitLocalStorageDatabasePathPreferenceKey] stringByStandardizingPath]; 1104} 1105 1106- (void)_setLocalStorageDatabasePath:(NSString *)path 1107{ 1108 [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitLocalStorageDatabasePathPreferenceKey]; 1109} 1110 1111- (NSString *)_ftpDirectoryTemplatePath 1112{ 1113 return [[self _stringValueForKey:WebKitFTPDirectoryTemplatePath] stringByStandardizingPath]; 1114} 1115 1116- (void)_setFTPDirectoryTemplatePath:(NSString *)path 1117{ 1118 [self _setStringValue:[path stringByStandardizingPath] forKey:WebKitFTPDirectoryTemplatePath]; 1119} 1120 1121- (BOOL)_forceFTPDirectoryListings 1122{ 1123 return [self _boolValueForKey:WebKitForceFTPDirectoryListings]; 1124} 1125 1126- (void)_setForceFTPDirectoryListings:(BOOL)force 1127{ 1128 [self _setBoolValue:force forKey:WebKitForceFTPDirectoryListings]; 1129} 1130 1131- (BOOL)acceleratedCompositingEnabled 1132{ 1133 return [self _boolValueForKey:WebKitAcceleratedCompositingEnabledPreferenceKey]; 1134} 1135 1136- (void)setAcceleratedCompositingEnabled:(BOOL)enabled 1137{ 1138 [self _setBoolValue:enabled forKey:WebKitAcceleratedCompositingEnabledPreferenceKey]; 1139} 1140 1141- (void)didRemoveFromWebView 1142{ 1143 ASSERT(_private->numWebViews); 1144 if (--_private->numWebViews == 0) 1145 [[NSNotificationCenter defaultCenter] 1146 postNotificationName:WebPreferencesRemovedNotification 1147 object:self 1148 userInfo:nil]; 1149} 1150 1151- (void)willAddToWebView 1152{ 1153 ++_private->numWebViews; 1154} 1155@end 1156 1157@implementation WebPreferences (WebInternal) 1158 1159+ (NSString *)_IBCreatorID 1160{ 1161 return classIBCreatorID; 1162} 1163 1164+ (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key 1165{ 1166 NSString *IBCreatorID = [WebPreferences _IBCreatorID]; 1167 if (!IBCreatorID) 1168 return key; 1169 return [IBCreatorID stringByAppendingString:key]; 1170} 1171 1172@end 1173