Reviewed by Don.
[WebKit-https.git] / WebKit / WebView.subproj / WebPreferences.m
1 /*
2  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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. 
16  *
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.
27  */
28
29 #import <WebKit/WebPreferencesPrivate.h>
30 #import <WebKit/WebPreferenceKeysPrivate.h>
31
32 #import <WebKit/WebKitLogging.h>
33 #import <WebKit/WebKitNSStringExtras.h>
34 #import <WebKit/WebNSDictionaryExtras.h>
35 #import <WebKit/WebNSURLExtras.h>
36 #import <WebKitSystemInterface.h>
37
38 #import <WebCore/WebCoreSettings.h>
39
40 NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
41
42 #define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
43
44 enum { WebPreferencesVersion = 1 };
45
46 @interface WebPreferencesPrivate : NSObject
47 {
48 @public
49     NSMutableDictionary *values;
50     NSString *identifier;
51     NSString *IBCreatorID;
52     BOOL autosaves;
53 }
54 @end
55
56 @implementation WebPreferencesPrivate
57 - (void)dealloc
58 {
59     [values release];
60     [identifier release];
61     [IBCreatorID release];
62     [super dealloc];
63 }
64 @end
65
66 @interface WebPreferences (WebInternal)
67 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key;
68 + (NSString *)_IBCreatorID;
69 @end
70
71 @interface WebPreferences (WebForwardDeclarations)
72 // This pseudo-category is needed so these methods can be used from within other category implementations
73 // without being in the public header file.
74 - (BOOL)_boolValueForKey:(NSString *)key;
75 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key;
76 @end
77
78 @implementation WebPreferences
79
80 - init
81 {
82     // Create fake identifier
83     static int instanceCount = 1;
84     NSString *fakeIdentifier;
85     
86     // At least ensure that identifier hasn't been already used.  
87     fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
88     while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){
89         fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
90     }
91     
92     return [self initWithIdentifier:fakeIdentifier];
93 }
94
95 static WebPreferences *_standardPreferences = nil;
96
97 - (id)initWithIdentifier:(NSString *)anIdentifier
98 {
99     [super init];
100
101     _private = [[WebPreferencesPrivate alloc] init];
102     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
103
104     WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier];
105     if (instance){
106         [self release];
107         return [instance retain];
108     }
109
110     _private->values = [[NSMutableDictionary alloc] init];
111     _private->identifier = [anIdentifier copy];
112     
113     [[self class] _setInstance:self forIdentifier:_private->identifier];
114
115     [[NSNotificationCenter defaultCenter]
116        postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
117
118     return self;
119 }
120
121 - (id)initWithCoder:(NSCoder *)decoder
122 {
123     volatile id result = nil;
124
125 NS_DURING
126
127     int version;
128
129     _private = [[WebPreferencesPrivate alloc] init];
130     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
131     
132     if ([decoder allowsKeyedCoding]){
133         _private->identifier = [[decoder decodeObjectForKey:@"Identifier"] retain];
134         _private->values = [[decoder decodeObjectForKey:@"Values"] retain];
135         LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
136     }
137     else {
138         [decoder decodeValueOfObjCType:@encode(int) at:&version];
139         if (version == 1){
140             _private->identifier = [[decoder decodeObject] retain];
141             _private->values = [[decoder decodeObject] retain];
142         }
143     }
144     
145     // If we load a nib multiple times, or have instances in multiple
146     // nibs with the same name, the first guy up wins.
147     WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier];
148     if (instance){
149         [self release];
150         result = [instance retain];
151     }
152     else {
153         [[self class] _setInstance:self forIdentifier:_private->identifier];
154         result = self;
155     }
156     
157 NS_HANDLER
158
159     result = nil;
160     [self release];
161     
162 NS_ENDHANDLER
163
164     return result;
165 }
166
167 - (void)encodeWithCoder:(NSCoder *)encoder
168 {
169     if ([encoder allowsKeyedCoding]){
170         [encoder encodeObject:_private->identifier forKey:@"Identifier"];
171         [encoder encodeObject:_private->values forKey:@"Values"];
172         LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
173     }
174     else {
175         int version = WebPreferencesVersion;
176         [encoder encodeValueOfObjCType:@encode(int) at:&version];
177         [encoder encodeObject:_private->identifier];
178         [encoder encodeObject:_private->values];
179     }
180 }
181
182 + (WebPreferences *)standardPreferences
183 {
184     if (_standardPreferences == nil) {
185         _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil];
186         [_standardPreferences setAutosaves:YES];
187         [_standardPreferences _postPreferencesChangesNotification];
188     }
189
190     return _standardPreferences;
191 }
192
193 // if we ever have more than one WebPreferences object, this would move to init
194 + (void)initialize
195 {
196     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
197         @"0x0",                         WebKitLogLevelPreferenceKey,
198         @"Times",                       WebKitStandardFontPreferenceKey,
199         @"Courier",                     WebKitFixedFontPreferenceKey,
200         @"Times",                       WebKitSerifFontPreferenceKey,
201         @"Helvetica",                   WebKitSansSerifFontPreferenceKey,
202         @"Apple Chancery",              WebKitCursiveFontPreferenceKey,
203         @"Papyrus",                     WebKitFantasyFontPreferenceKey,
204         @"1",                           WebKitMinimumFontSizePreferenceKey,
205         @"9",                           WebKitMinimumLogicalFontSizePreferenceKey, 
206         @"16",                          WebKitDefaultFontSizePreferenceKey,
207         @"13",                          WebKitDefaultFixedFontSizePreferenceKey,
208         @"ISO-8859-1",                  WebKitDefaultTextEncodingNamePreferenceKey,
209         @"4",                           WebKitPageCacheSizePreferenceKey,
210         @"8388608",                     WebKitObjectCacheSizePreferenceKey,
211         [NSNumber numberWithBool:NO],   WebKitUserStyleSheetEnabledPreferenceKey,
212         @"",                            WebKitUserStyleSheetLocationPreferenceKey,
213         [NSNumber numberWithBool:NO],   WebKitShouldPrintBackgroundsPreferenceKey,
214         [NSNumber numberWithBool:NO],   WebKitTextAreasAreResizablePreferenceKey,
215         [NSNumber numberWithBool:YES],  WebKitJavaEnabledPreferenceKey,
216         [NSNumber numberWithBool:YES],  WebKitJavaScriptEnabledPreferenceKey,
217         [NSNumber numberWithBool:YES],  WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey,
218         [NSNumber numberWithBool:YES],  WebKitPluginsEnabledPreferenceKey,
219         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImagesPreferenceKey,
220         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImageLoopingPreferenceKey,
221         [NSNumber numberWithBool:YES],  WebKitDisplayImagesKey,
222         @"1800",                        WebKitBackForwardCacheExpirationIntervalKey,
223         [NSNumber numberWithBool:NO],   WebKitTabToLinksPreferenceKey,
224         [NSNumber numberWithBool:NO],   WebKitPrivateBrowsingEnabledPreferenceKey,
225         [NSNumber numberWithBool:NO],   WebKitRespectStandardStyleKeyEquivalentsPreferenceKey,
226         [NSNumber numberWithBool:NO],   WebKitShowsURLsInToolTipsPreferenceKey,
227         nil];
228
229     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
230 }
231
232 - (void)dealloc
233 {
234     [_private release];
235     [super dealloc];
236 }
237
238 - (NSString *)identifier
239 {
240     return _private->identifier;
241 }
242
243 - (id)_valueForKey:(NSString *)key
244 {
245     NSString *_key = KEY(key);
246     id o = [_private->values objectForKey:_key];
247     if (o)
248         return o;
249     o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
250     if (!o && key != _key)
251         o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
252     return o;
253 }
254
255 - (NSString *)_stringValueForKey:(NSString *)key
256 {
257     id s = [self _valueForKey:key];
258     return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
259 }
260
261 - (void)_setStringValue:(NSString *)value forKey:(NSString *)key
262 {
263     if ([[self _stringValueForKey:key] isEqualToString:value])
264         return;
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];
270 }
271
272 - (int)_integerValueForKey:(NSString *)key
273 {
274     id o = [self _valueForKey:key];
275     // 
276     return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
277 }
278
279 - (void)_setIntegerValue:(int)value forKey:(NSString *)key
280 {
281     if ([self _integerValueForKey:key] == value)
282         return;
283     NSString *_key = KEY(key);
284     [_private->values _webkit_setInt:value forKey:_key];
285     if (_private->autosaves)
286         [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
287     [self _postPreferencesChangesNotification];
288 }
289
290 - (BOOL)_boolValueForKey:(NSString *)key
291 {
292     return [self _integerValueForKey:key] != 0;
293 }
294
295 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
296 {
297     if ([self _boolValueForKey:key] == value)
298         return;
299     NSString *_key = KEY(key);
300     [_private->values _webkit_setBool:value forKey:_key];
301     if (_private->autosaves)
302         [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
303     [self _postPreferencesChangesNotification];
304 }
305
306 - (NSString *)standardFontFamily
307 {
308     return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
309 }
310
311 - (void)setStandardFontFamily:(NSString *)family
312 {
313     [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
314 }
315
316 - (NSString *)fixedFontFamily
317 {
318     return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
319 }
320
321 - (void)setFixedFontFamily:(NSString *)family
322 {
323     [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
324 }
325
326 - (NSString *)serifFontFamily
327 {
328     return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
329 }
330
331 - (void)setSerifFontFamily:(NSString *)family 
332 {
333     [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
334 }
335
336 - (NSString *)sansSerifFontFamily
337 {
338     return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
339 }
340
341 - (void)setSansSerifFontFamily:(NSString *)family
342 {
343     [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
344 }
345
346 - (NSString *)cursiveFontFamily
347 {
348     return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
349 }
350
351 - (void)setCursiveFontFamily:(NSString *)family
352 {
353     [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
354 }
355
356 - (NSString *)fantasyFontFamily
357 {
358     return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
359 }
360
361 - (void)setFantasyFontFamily:(NSString *)family
362 {
363     [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
364 }
365
366 - (int)defaultFontSize
367 {
368     return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
369 }
370
371 - (void)setDefaultFontSize:(int)size
372 {
373     [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
374 }
375
376 - (int)defaultFixedFontSize
377 {
378     return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
379 }
380
381 - (void)setDefaultFixedFontSize:(int)size
382 {
383     [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
384 }
385
386 - (int)minimumFontSize
387 {
388     return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
389 }
390
391 - (void)setMinimumFontSize:(int)size
392 {
393     [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
394 }
395
396 - (int)minimumLogicalFontSize
397 {
398   return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
399 }
400
401 - (void)setMinimumLogicalFontSize:(int)size
402 {
403   [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
404 }
405
406 - (NSString *)defaultTextEncodingName
407 {
408     return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
409 }
410
411 - (void)setDefaultTextEncodingName:(NSString *)encoding
412 {
413     [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
414 }
415
416 - (BOOL)userStyleSheetEnabled
417 {
418     return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
419 }
420
421 - (void)setUserStyleSheetEnabled:(BOOL)flag
422 {
423     [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
424 }
425
426 - (NSURL *)userStyleSheetLocation
427 {
428     NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
429     
430     if ([locationString _webkit_looksLikeAbsoluteURL]) {
431         return [NSURL _web_URLWithDataAsString:locationString];
432     } else {
433         locationString = [locationString stringByExpandingTildeInPath];
434         return [NSURL fileURLWithPath:locationString];
435     }
436 }
437
438 - (void)setUserStyleSheetLocation:(NSURL *)URL
439 {
440     NSString *locationString;
441     
442     if ([URL isFileURL]) {
443         locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
444     } else {
445         locationString = [URL _web_originalDataAsString];
446     }
447     
448     [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
449 }
450
451 - (BOOL)shouldPrintBackgrounds
452 {
453     return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
454 }
455
456 - (void)setShouldPrintBackgrounds:(BOOL)flag
457 {
458     [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
459 }
460
461 - (BOOL)isJavaEnabled
462 {
463     return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
464 }
465
466 - (void)setJavaEnabled:(BOOL)flag
467 {
468     [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
469 }
470
471 - (BOOL)isJavaScriptEnabled
472 {
473     return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
474 }
475
476 - (void)setJavaScriptEnabled:(BOOL)flag
477 {
478     [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
479 }
480
481 - (BOOL)javaScriptCanOpenWindowsAutomatically
482 {
483     return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
484 }
485
486 - (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
487 {
488     [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
489 }
490
491 - (BOOL)arePlugInsEnabled
492 {
493     return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
494 }
495
496 - (void)setPlugInsEnabled:(BOOL)flag
497 {
498     [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
499 }
500
501 - (BOOL)allowsAnimatedImages
502 {
503     return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
504 }
505
506 - (void)setAllowsAnimatedImages:(BOOL)flag;
507 {
508     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
509 }
510
511 - (BOOL)allowsAnimatedImageLooping
512 {
513     return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
514 }
515
516 - (void)setAllowsAnimatedImageLooping: (BOOL)flag
517 {
518     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
519 }
520
521 - (void)setLoadsImagesAutomatically: (BOOL)flag
522 {
523     [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
524 }
525
526 - (BOOL)loadsImagesAutomatically
527 {
528     return [self _boolValueForKey: WebKitDisplayImagesKey];
529 }
530
531 - (void)setAutosaves:(BOOL)flag;
532 {
533     _private->autosaves = flag;
534 }
535
536 - (BOOL)autosaves
537 {
538     return _private->autosaves;
539 }
540
541 - (void)setTabsToLinks:(BOOL)flag
542 {
543     [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
544 }
545
546 - (BOOL)tabsToLinks
547 {
548     return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
549 }
550
551 - (void)setPrivateBrowsingEnabled:(BOOL)flag
552 {
553     [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
554 }
555
556 - (BOOL)privateBrowsingEnabled
557 {
558     return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
559 }
560
561 @end
562
563 @implementation WebPreferences (WebPrivate)
564
565 - (BOOL)respectStandardStyleKeyEquivalents
566 {
567     return [self _boolValueForKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
568 }
569
570 - (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag
571 {
572     [self _setBoolValue:flag forKey:WebKitRespectStandardStyleKeyEquivalentsPreferenceKey];
573 }
574
575 - (BOOL)showsURLsInToolTips
576 {
577     return [self _boolValueForKey:WebKitShowsURLsInToolTipsPreferenceKey];
578 }
579
580 - (void)setShowsURLsInToolTips:(BOOL)flag
581 {
582     [self _setBoolValue:flag forKey:WebKitShowsURLsInToolTipsPreferenceKey];
583 }
584
585 - (BOOL)textAreasAreResizable
586 {
587     return [self _boolValueForKey: WebKitTextAreasAreResizablePreferenceKey];
588 }
589
590 - (void)setTextAreasAreResizable:(BOOL)flag
591 {
592     [self _setBoolValue: flag forKey: WebKitTextAreasAreResizablePreferenceKey];
593 }
594
595 - (int)_pageCacheSize
596 {
597     return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitPageCacheSizePreferenceKey];
598 }
599
600 - (int)_objectCacheSize
601 {
602     return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitObjectCacheSizePreferenceKey];
603 }
604
605 - (NSTimeInterval)_backForwardCacheExpirationInterval
606 {
607     return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
608 }
609
610 static NSMutableDictionary *webPreferencesInstances = nil;
611
612 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
613 {
614         LOG (Encoding, "requesting for %@\n", ident);
615
616     if (!ident){
617         if(_standardPreferences)
618             return _standardPreferences;
619         return nil;
620     }    
621     
622     WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
623
624     return instance;
625 }
626
627 + (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
628 {
629     if (!webPreferencesInstances)
630         webPreferencesInstances = [[NSMutableDictionary alloc] init];
631     if (ident) {
632         [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
633         LOG (Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
634     }
635 }
636
637 + (void)_removeReferenceForIdentifier:(NSString *)ident
638 {
639     if (ident != nil) {
640         [webPreferencesInstances performSelector:@selector(_web_checkLastReferenceForIdentifier:) withObject: [self _concatenateKeyWithIBCreatorID:ident] afterDelay:.1];
641     }
642 }
643
644 - (void)_postPreferencesChangesNotification
645 {
646     [[NSNotificationCenter defaultCenter]
647         postNotificationName:WebPreferencesChangedNotification object:self
648                     userInfo:nil];
649 }
650
651 + (CFStringEncoding)_systemCFStringEncoding
652 {
653 #if OMIT_TIGER_FEATURES
654     CFStringEncoding encoding = CFStringGetSystemEncoding();
655
656     // Map from system encodings to the appropriate default web encoding.
657     // Web pages that are not labeled will be decoded assuming this encoding,
658     // so it's important that this be the most likely encoding to encounter
659     // on a web page. MacArabic, MacHebrew, and MacRoman are not common on
660     // the web, so instead we map to the most common similar encoding actually used.
661     switch (encoding) {
662         case kCFStringEncodingMacArabic:
663             encoding = kCFStringEncodingDOSArabic;
664             break;
665         case kCFStringEncodingMacHebrew:
666             encoding = kCFStringEncodingDOSHebrew;
667             break;
668         case kCFStringEncodingMacRoman:
669             encoding = kCFStringEncodingISOLatin1;
670             break;
671     }
672
673     // We must not use any encoding that has no IANA character set name.
674     if (CFStringConvertEncodingToIANACharSetName(encoding) == NULL)
675         encoding = kCFStringEncodingISOLatin1;
676 #else
677         CFStringEncoding encoding = WKGetWebDefaultCFStringEncoding();
678 #endif
679
680     return encoding;
681 }
682
683 + (void)_setInitialDefaultTextEncodingToSystemEncoding
684 {
685     [[NSUserDefaults standardUserDefaults] registerDefaults:
686         [NSDictionary dictionaryWithObject:(NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding])
687                                     forKey:WebKitDefaultTextEncodingNamePreferenceKey]];
688 }
689
690 static NSString *classIBCreatorID = nil;
691
692 + (void)_setIBCreatorID:(NSString *)string
693 {
694     NSString *old = classIBCreatorID;
695     classIBCreatorID = [string copy];
696     [old release];
697 }
698
699 @end
700
701 @implementation WebPreferences (WebInternal)
702
703 + (NSString *)_IBCreatorID
704 {
705     return classIBCreatorID;
706 }
707
708 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
709 {
710     NSString *IBCreatorID = [WebPreferences _IBCreatorID];
711     if (!IBCreatorID)
712         return key;
713     return [IBCreatorID stringByAppendingString:key];
714 }
715
716 @end
717
718 @implementation NSMutableDictionary (WebInternal)
719
720 - (void)_web_checkLastReferenceForIdentifier:(NSString *)identifier
721 {
722     WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
723     if ([instance retainCount] == 1)
724         [webPreferencesInstances removeObjectForKey:identifier];
725 }
726
727 @end