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