2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #import <WebKit/WebPreferencesPrivate.h>
30 #import <WebKit/WebPreferenceKeysPrivate.h>
32 #import <WebKit/WebKitLogging.h>
33 #import <WebKit/WebKitNSStringExtras.h>
34 #import <WebKit/WebNSDictionaryExtras.h>
35 #import <WebKit/WebNSURLExtras.h>
37 #import <WebCore/WebCoreSettings.h>
39 #import <Carbon/Carbon.h> // For TEC
40 #import <CoreFoundation/CFStringDefaultEncoding.h> // For __CFStringGetUserDefaultEncoding
42 NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
44 #define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
46 enum { WebPreferencesVersion = 1 };
48 @interface WebPreferencesPrivate : NSObject
51 NSMutableDictionary *values;
53 NSString *IBCreatorID;
58 @implementation WebPreferencesPrivate
63 [IBCreatorID release];
68 @interface WebPreferences (WebInternal)
69 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key;
70 + (NSString *)_IBCreatorID;
73 @interface WebPreferences (WebForwardDeclarations)
74 // This pseudo-category is needed so these methods can be used from within other category implementations
75 // without being in the public header file.
76 - (BOOL)_boolValueForKey:(NSString *)key;
77 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key;
80 @implementation WebPreferences
84 // Create fake identifier
85 static int instanceCount = 1;
86 NSString *fakeIdentifier;
88 // At least ensure that identifier hasn't been already used.
89 fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
90 while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){
91 fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
94 return [self initWithIdentifier:fakeIdentifier];
97 static WebPreferences *_standardPreferences = nil;
99 - (id)initWithIdentifier:(NSString *)anIdentifier
103 _private = [[WebPreferencesPrivate alloc] init];
104 _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
106 WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier];
109 return [instance retain];
112 _private->values = [[NSMutableDictionary alloc] init];
113 _private->identifier = [anIdentifier copy];
115 [[self class] _setInstance:self forIdentifier:_private->identifier];
117 [[NSNotificationCenter defaultCenter]
118 postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
123 - (id)initWithCoder:(NSCoder *)decoder
125 volatile id result = nil;
131 _private = [[WebPreferencesPrivate alloc] init];
132 _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
134 if ([decoder allowsKeyedCoding]){
135 _private->identifier = [[decoder decodeObjectForKey:@"Identifier"] retain];
136 _private->values = [[decoder decodeObjectForKey:@"Values"] retain];
137 LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
140 [decoder decodeValueOfObjCType:@encode(int) at:&version];
142 _private->identifier = [[decoder decodeObject] retain];
143 _private->values = [[decoder decodeObject] retain];
147 // If we load a nib multiple times, or have instances in multiple
148 // nibs with the same name, the first guy up wins.
149 WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier];
152 result = [instance retain];
155 [[self class] _setInstance:self forIdentifier:_private->identifier];
169 - (void)encodeWithCoder:(NSCoder *)encoder
171 if ([encoder allowsKeyedCoding]){
172 [encoder encodeObject:_private->identifier forKey:@"Identifier"];
173 [encoder encodeObject:_private->values forKey:@"Values"];
174 LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
177 int version = WebPreferencesVersion;
178 [encoder encodeValueOfObjCType:@encode(int) at:&version];
179 [encoder encodeObject:_private->identifier];
180 [encoder encodeObject:_private->values];
184 + (WebPreferences *)standardPreferences
186 if (_standardPreferences == nil) {
187 _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil];
188 [_standardPreferences setAutosaves:YES];
189 [_standardPreferences _postPreferencesChangesNotification];
192 return _standardPreferences;
195 // if we ever have more than one WebPreferences object, this would move to init
198 NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
199 @"0x0", WebKitLogLevelPreferenceKey,
200 @"Times", WebKitStandardFontPreferenceKey,
201 @"Courier", WebKitFixedFontPreferenceKey,
202 @"Times", WebKitSerifFontPreferenceKey,
203 @"Helvetica", WebKitSansSerifFontPreferenceKey,
204 @"Apple Chancery", WebKitCursiveFontPreferenceKey,
205 @"Papyrus", WebKitFantasyFontPreferenceKey,
206 @"1", WebKitMinimumFontSizePreferenceKey,
207 @"9", WebKitMinimumLogicalFontSizePreferenceKey,
208 @"16", WebKitDefaultFontSizePreferenceKey,
209 @"13", WebKitDefaultFixedFontSizePreferenceKey,
210 @"ISO-8859-1", WebKitDefaultTextEncodingNamePreferenceKey,
211 @"4", WebKitPageCacheSizePreferenceKey,
212 @"8388608", WebKitObjectCacheSizePreferenceKey,
213 [NSNumber numberWithBool:NO], WebKitUserStyleSheetEnabledPreferenceKey,
214 @"", WebKitUserStyleSheetLocationPreferenceKey,
215 [NSNumber numberWithBool:NO], WebKitShouldPrintBackgroundsPreferenceKey,
216 [NSNumber numberWithBool:NO], WebKitTextAreasAreResizablePreferenceKey,
217 [NSNumber numberWithBool:YES], WebKitJavaEnabledPreferenceKey,
218 [NSNumber numberWithBool:YES], WebKitJavaScriptEnabledPreferenceKey,
219 [NSNumber numberWithBool:YES], WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey,
220 [NSNumber numberWithBool:YES], WebKitPluginsEnabledPreferenceKey,
221 [NSNumber numberWithBool:YES], WebKitAllowAnimatedImagesPreferenceKey,
222 [NSNumber numberWithBool:YES], WebKitAllowAnimatedImageLoopingPreferenceKey,
223 [NSNumber numberWithBool:YES], WebKitDisplayImagesKey,
224 @"1800", WebKitBackForwardCacheExpirationIntervalKey,
225 [NSNumber numberWithBool:NO], WebKitTabToLinksPreferenceKey,
226 [NSNumber numberWithBool:NO], WebKitPrivateBrowsingEnabledPreferenceKey,
227 [NSNumber numberWithBool:NO], WebKitRespectStandardStyleKeyEquivalentsPreferenceKey,
228 [NSNumber numberWithBool:NO], WebKitShowsURLsInToolTipsPreferenceKey,
231 [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
240 - (NSString *)identifier
242 return _private->identifier;
245 - (id)_valueForKey:(NSString *)key
247 NSString *_key = KEY(key);
248 id o = [_private->values objectForKey:_key];
251 o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
252 if (!o && key != _key)
253 o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
257 - (NSString *)_stringValueForKey:(NSString *)key
259 id s = [self _valueForKey:key];
260 return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
263 - (void)_setStringValue:(NSString *)value forKey:(NSString *)key
265 NSString *_key = KEY(key);
266 [_private->values setObject:value forKey:_key];
267 if (_private->autosaves)
268 [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
269 [self _postPreferencesChangesNotification];
272 - (int)_integerValueForKey:(NSString *)key
274 id o = [self _valueForKey:key];
276 return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
279 - (void)_setIntegerValue:(int)value forKey:(NSString *)key
281 NSString *_key = KEY(key);
282 [_private->values _webkit_setInt:value forKey:_key];
283 if (_private->autosaves)
284 [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
285 [self _postPreferencesChangesNotification];
288 - (BOOL)_boolValueForKey:(NSString *)key
290 return [self _integerValueForKey:key] != 0;
293 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
295 NSString *_key = KEY(key);
296 [_private->values _webkit_setBool:value forKey:_key];
297 if (_private->autosaves)
298 [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
299 [self _postPreferencesChangesNotification];
302 - (NSString *)standardFontFamily
304 return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
307 - (void)setStandardFontFamily:(NSString *)family
309 [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
312 - (NSString *)fixedFontFamily
314 return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
317 - (void)setFixedFontFamily:(NSString *)family
319 [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
322 - (NSString *)serifFontFamily
324 return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
327 - (void)setSerifFontFamily:(NSString *)family
329 [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
332 - (NSString *)sansSerifFontFamily
334 return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
337 - (void)setSansSerifFontFamily:(NSString *)family
339 [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
342 - (NSString *)cursiveFontFamily
344 return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
347 - (void)setCursiveFontFamily:(NSString *)family
349 [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
352 - (NSString *)fantasyFontFamily
354 return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
357 - (void)setFantasyFontFamily:(NSString *)family
359 [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
362 - (int)defaultFontSize
364 return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
367 - (void)setDefaultFontSize:(int)size
369 [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
372 - (int)defaultFixedFontSize
374 return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
377 - (void)setDefaultFixedFontSize:(int)size
379 [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
382 - (int)minimumFontSize
384 return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
387 - (void)setMinimumFontSize:(int)size
389 [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
392 - (int)minimumLogicalFontSize
394 return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
397 - (void)setMinimumLogicalFontSize:(int)size
399 [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
402 - (NSString *)defaultTextEncodingName
404 return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
407 - (void)setDefaultTextEncodingName:(NSString *)encoding
409 [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
412 - (BOOL)userStyleSheetEnabled
414 return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
417 - (void)setUserStyleSheetEnabled:(BOOL)flag
419 [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
422 - (NSURL *)userStyleSheetLocation
424 NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
426 if ([locationString _webkit_looksLikeAbsoluteURL]) {
427 return [NSURL _web_URLWithDataAsString:locationString];
429 locationString = [locationString stringByExpandingTildeInPath];
430 return [NSURL fileURLWithPath:locationString];
434 - (void)setUserStyleSheetLocation:(NSURL *)URL
436 NSString *locationString;
438 if ([URL isFileURL]) {
439 locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
441 locationString = [URL _web_originalDataAsString];
444 [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
447 - (BOOL)shouldPrintBackgrounds
449 return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
452 - (void)setShouldPrintBackgrounds:(BOOL)flag
454 [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
457 - (BOOL)isJavaEnabled
459 return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
462 - (void)setJavaEnabled:(BOOL)flag
464 [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
467 - (BOOL)isJavaScriptEnabled
469 return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
472 - (void)setJavaScriptEnabled:(BOOL)flag
474 [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
477 - (BOOL)javaScriptCanOpenWindowsAutomatically
479 return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
482 - (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
484 [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
487 - (BOOL)arePlugInsEnabled
489 return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
492 - (void)setPlugInsEnabled:(BOOL)flag
494 [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
497 - (BOOL)allowsAnimatedImages
499 return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
502 - (void)setAllowsAnimatedImages:(BOOL)flag;
504 [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
507 - (BOOL)allowsAnimatedImageLooping
509 return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
512 - (void)setAllowsAnimatedImageLooping: (BOOL)flag
514 [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
517 - (void)setLoadsImagesAutomatically: (BOOL)flag
519 [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
522 - (BOOL)loadsImagesAutomatically
524 return [self _boolValueForKey: WebKitDisplayImagesKey];
527 - (void)setAutosaves:(BOOL)flag;
529 _private->autosaves = flag;
534 return _private->autosaves;
537 - (void)setTabsToLinks:(BOOL)flag
539 [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
544 return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
547 - (void)setPrivateBrowsingEnabled:(BOOL)flag
549 [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
552 - (BOOL)privateBrowsingEnabled
554 return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
559 @implementation WebPreferences (WebPrivate)
561 - (BOOL)respectStandardStyleKeyEquivalents
563 return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
566 - (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag
568 [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
571 - (BOOL)showsURLsInToolTips
573 return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey];
576 - (void)setShowsURLsInToolTips:(BOOL)flag
578 [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey];
581 - (BOOL)textAreasAreResizable
583 return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey];
586 - (void)setTextAreasAreResizable:(BOOL)flag
588 [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey];
591 - (int)_pageCacheSize
593 return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitPageCacheSizePreferenceKey];
596 - (int)_objectCacheSize
598 return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitObjectCacheSizePreferenceKey];
601 - (NSTimeInterval)_backForwardCacheExpirationInterval
603 return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
606 static NSMutableDictionary *webPreferencesInstances = nil;
608 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
610 LOG (Encoding, "requesting for %@\n", ident);
613 if(_standardPreferences)
614 return _standardPreferences;
618 WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
623 + (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
625 if (!webPreferencesInstances)
626 webPreferencesInstances = [[NSMutableDictionary alloc] init];
628 [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
629 LOG (Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
633 + (void)_removeReferenceForIdentifier:(NSString *)ident
636 [webPreferencesInstances performSelector:@selector(_web_checkLastReferenceForIdentifier:) withObject: [self _concatenateKeyWithIBCreatorID:ident] afterDelay:.1];
640 - (void)_postPreferencesChangesNotification
642 [[NSNotificationCenter defaultCenter]
643 postNotificationName:WebPreferencesChangedNotification object:self
647 + (CFStringEncoding)_systemCFStringEncoding
649 #if OMIT_TIGER_FEATURES
650 CFStringEncoding encoding = CFStringGetSystemEncoding();
652 // Map from system encodings to the appropriate default web encoding.
653 // Web pages that are not labeled will be decoded assuming this encoding,
654 // so it's important that this be the most likely encoding to encounter
655 // on a web page. MacArabic, MacHebrew, and MacRoman are not common on
656 // the web, so instead we map to the most common similar encoding actually used.
658 case kCFStringEncodingMacArabic:
659 encoding = kCFStringEncodingDOSArabic;
661 case kCFStringEncodingMacHebrew:
662 encoding = kCFStringEncodingDOSHebrew;
664 case kCFStringEncodingMacRoman:
665 encoding = kCFStringEncodingISOLatin1;
669 // We must not use any encoding that has no IANA character set name.
670 if (CFStringConvertEncodingToIANACharSetName(encoding) == NULL)
671 return kCFStringEncodingISOLatin1;
675 TextEncoding encoding;
679 // We can't use the Script Manager as it will not return things that use
680 // a script that is not supported on Mac OS X.
681 __CFStringGetUserDefaultEncoding(&script, ®ion);
682 err = TECGetWebTextEncodings(region, &encoding, 1, &dontcare);
684 encoding = kCFStringEncodingISOLatin1;
690 + (void)_setInitialDefaultTextEncodingToSystemEncoding
692 [[NSUserDefaults standardUserDefaults] registerDefaults:
693 [NSDictionary dictionaryWithObject:(NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding])
694 forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
697 static NSString *classIBCreatorID = nil;
699 + (void)_setIBCreatorID:(NSString *)string
701 NSString *old = classIBCreatorID;
702 classIBCreatorID = [string copy];
708 @implementation WebPreferences (WebInternal)
710 + (NSString *)_IBCreatorID
712 return classIBCreatorID;
715 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
717 NSString *IBCreatorID = [WebPreferences _IBCreatorID];
720 return [IBCreatorID stringByAppendingString:key];
725 @implementation NSMutableDictionary (WebInternal)
727 - (void)_web_checkLastReferenceForIdentifier:(NSString *)identifier
729 WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
730 if ([instance retainCount] == 1)
731 [webPreferencesInstances removeObjectForKey:identifier];