WebKit:
[WebKit-https.git] / WebKit / WebView.subproj / WebPreferences.m
1 /*        
2         WebPreferences.m
3         Copyright 2001, 2002, Apple Computer, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebPreferencesPrivate.h>
7 #import <WebKit/WebPreferenceKeysPrivate.h>
8
9 #import <WebKit/WebKitLogging.h>
10 #import <WebKit/WebKitNSStringExtras.h>
11 #import <WebKit/WebNSURLExtras.h>
12
13 #import <Foundation/NSDictionary_NSURLExtras.h>
14 #import <Foundation/NSString_NSURLExtras.h>
15
16 #import <WebCore/WebCoreSettings.h>
17
18 NSString *WebPreferencesChangedNotification = @"WebPreferencesChangedNotification";
19
20 #define KEY(x) (_private->identifier ? [_private->identifier stringByAppendingString:(x)] : (x))
21
22 enum { WebPreferencesVersion = 1 };
23
24 @interface WebPreferencesPrivate : NSObject
25 {
26 @public
27     NSMutableDictionary *values;
28     NSString *identifier;
29     NSString *IBCreatorID;
30     BOOL autosaves;
31 }
32 @end
33
34 @implementation WebPreferencesPrivate
35 - (void)dealloc
36 {
37     [values release];
38     [identifier release];
39     [IBCreatorID release];
40     [super dealloc];
41 }
42 @end
43
44 @interface WebPreferences (WebInternal)
45 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key;
46 + (NSString *)_IBCreatorID;
47 @end
48
49 @implementation WebPreferences
50
51 - init
52 {
53     // Create fake identifier
54     static int instanceCount = 1;
55     NSString *fakeIdentifier;
56     
57     // At least ensure that identifier hasn't been already used.  
58     fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
59     while ([[self class] _getInstanceForIdentifier:fakeIdentifier]){
60         fakeIdentifier = [NSString stringWithFormat:@"WebPreferences%d", instanceCount++];
61     }
62     
63     return [self initWithIdentifier:fakeIdentifier];
64 }
65
66 static WebPreferences *_standardPreferences = nil;
67
68 - (id)initWithIdentifier:(NSString *)anIdentifier
69 {
70     [super init];
71
72     _private = [[WebPreferencesPrivate alloc] init];
73     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
74
75     WebPreferences *instance = [[self class] _getInstanceForIdentifier:anIdentifier];
76     if (instance){
77         [self release];
78         return [instance retain];
79     }
80
81     _private->values = [[NSMutableDictionary alloc] init];
82     _private->identifier = [anIdentifier copy];
83     
84     [[self class] _setInstance:self forIdentifier:_private->identifier];
85
86     [[NSNotificationCenter defaultCenter]
87        postNotificationName:WebPreferencesChangedNotification object:self userInfo:nil];
88
89     return self;
90 }
91
92 - (id)initWithCoder:(NSCoder *)decoder
93 {
94     volatile id result = nil;
95
96 NS_DURING
97
98     int version;
99
100     _private = [[WebPreferencesPrivate alloc] init];
101     _private->IBCreatorID = [[WebPreferences _IBCreatorID] retain];
102     
103     if ([decoder allowsKeyedCoding]){
104         _private->identifier = [[decoder decodeObjectForKey:@"Identifier"] retain];
105         _private->values = [[decoder decodeObjectForKey:@"Values"] retain];
106         LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
107     }
108     else {
109         [decoder decodeValueOfObjCType:@encode(int) at:&version];
110         if (version == 1){
111             _private->identifier = [[decoder decodeObject] retain];
112             _private->values = [[decoder decodeObject] retain];
113         }
114     }
115     
116     // If we load a nib multiple times, or have instances in multiple
117     // nibs with the same name, the first guy up wins.
118     WebPreferences *instance = [[self class] _getInstanceForIdentifier:_private->identifier];
119     if (instance){
120         [self release];
121         result = [instance retain];
122     }
123     else {
124         [[self class] _setInstance:self forIdentifier:_private->identifier];
125         result = self;
126     }
127     
128 NS_HANDLER
129
130     result = nil;
131     [self release];
132     
133 NS_ENDHANDLER
134
135     return result;
136 }
137
138 - (void)encodeWithCoder:(NSCoder *)encoder
139 {
140     if ([encoder allowsKeyedCoding]){
141         [encoder encodeObject:_private->identifier forKey:@"Identifier"];
142         [encoder encodeObject:_private->values forKey:@"Values"];
143         LOG (Encoding, "Identifier = %@, Values = %@\n", _private->identifier, _private->values);
144     }
145     else {
146         int version = WebPreferencesVersion;
147         [encoder encodeValueOfObjCType:@encode(int) at:&version];
148         [encoder encodeObject:_private->identifier];
149         [encoder encodeObject:_private->values];
150     }
151 }
152
153 + (WebPreferences *)standardPreferences
154 {
155     if (_standardPreferences == nil) {
156         _standardPreferences = [[WebPreferences alloc] initWithIdentifier:nil];
157         [_standardPreferences setAutosaves:YES];
158         [_standardPreferences _postPreferencesChangesNotification];
159     }
160
161     return _standardPreferences;
162 }
163
164 // if we ever have more than one WebPreferences object, this would move to init
165 + (void)initialize
166 {
167     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
168         @"0x0",                         WebKitLogLevelPreferenceKey,
169         @"Times",                       WebKitStandardFontPreferenceKey,
170         @"Courier",                     WebKitFixedFontPreferenceKey,
171         @"Times",                       WebKitSerifFontPreferenceKey,
172         @"Helvetica",                   WebKitSansSerifFontPreferenceKey,
173         @"Apple Chancery",              WebKitCursiveFontPreferenceKey,
174         @"Papyrus",                     WebKitFantasyFontPreferenceKey,
175         @"1",                           WebKitMinimumFontSizePreferenceKey,
176         @"9",                           WebKitMinimumLogicalFontSizePreferenceKey, 
177         @"16",                          WebKitDefaultFontSizePreferenceKey,
178         @"13",                          WebKitDefaultFixedFontSizePreferenceKey,
179         @"ISO-8859-1",                  WebKitDefaultTextEncodingNamePreferenceKey,
180         @"4",                           WebKitPageCacheSizePreferenceKey,
181         @"4194304",                     WebKitObjectCacheSizePreferenceKey,
182         [NSNumber numberWithBool:NO],   WebKitUserStyleSheetEnabledPreferenceKey,
183         @"",                            WebKitUserStyleSheetLocationPreferenceKey,
184         [NSNumber numberWithBool:NO],   WebKitShouldPrintBackgroundsPreferenceKey,
185         [NSNumber numberWithBool:YES],  WebKitJavaEnabledPreferenceKey,
186         [NSNumber numberWithBool:YES],  WebKitJavaScriptEnabledPreferenceKey,
187         [NSNumber numberWithBool:YES],  WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey,
188         [NSNumber numberWithBool:YES],  WebKitPluginsEnabledPreferenceKey,
189         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImagesPreferenceKey,
190         [NSNumber numberWithBool:YES],  WebKitAllowAnimatedImageLoopingPreferenceKey,
191         [NSNumber numberWithBool:YES],  WebKitDisplayImagesKey,
192         @"1800",                        WebKitBackForwardCacheExpirationIntervalKey,
193         [NSNumber numberWithBool:NO],   WebKitTabToLinksPreferenceKey,
194         [NSNumber numberWithBool:NO],   WebKitPrivateBrowsingEnabledPreferenceKey,
195         nil];
196
197     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
198 }
199
200 - (void)dealloc
201 {
202     [_private release];
203     [super dealloc];
204 }
205
206 - (NSString *)identifier
207 {
208     return _private->identifier;
209 }
210
211 - (id)_valueForKey:(NSString *)key
212 {
213     NSString *_key = KEY(key);
214     id o = [_private->values objectForKey:_key];
215     if (o)
216         return o;
217     o = [[NSUserDefaults standardUserDefaults] objectForKey:_key];
218     if (!o && key != _key)
219         o = [[NSUserDefaults standardUserDefaults] objectForKey:key];
220     return o;
221 }
222
223 - (NSString *)_stringValueForKey:(NSString *)key
224 {
225     id s = [self _valueForKey:key];
226     return [s isKindOfClass:[NSString class]] ? (NSString *)s : nil;
227 }
228
229 - (void)_setStringValue:(NSString *)value forKey:(NSString *)key
230 {
231     NSString *_key = KEY(key);
232     if (_private->autosaves)
233         [[NSUserDefaults standardUserDefaults] setObject:value forKey:_key];
234     [_private->values setObject:value forKey:_key];
235     [self _postPreferencesChangesNotification];
236 }
237
238 - (int)_integerValueForKey:(NSString *)key
239 {
240     id o = [self _valueForKey:key];
241     // 
242     return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
243 }
244
245 - (void)_setIntegerValue:(int)value forKey:(NSString *)key
246 {
247     NSString *_key = KEY(key);
248     if (_private->autosaves)
249         [[NSUserDefaults standardUserDefaults] setInteger:value forKey:_key];
250     [_private->values _web_setInt:value forKey:_key];
251     [self _postPreferencesChangesNotification];
252 }
253
254 - (BOOL)_boolValueForKey:(NSString *)key
255 {
256     return [self _integerValueForKey:key] != 0;
257 }
258
259 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key
260 {
261     NSString *_key = KEY(key);
262     if (_private->autosaves)
263         [[NSUserDefaults standardUserDefaults] setBool:value forKey:_key];
264     [_private->values _web_setBool:value forKey:_key];
265     [self _postPreferencesChangesNotification];
266 }
267
268 - (NSString *)standardFontFamily
269 {
270     return [self _stringValueForKey: WebKitStandardFontPreferenceKey];
271 }
272
273 - (void)setStandardFontFamily:(NSString *)family
274 {
275     [self _setStringValue: family forKey: WebKitStandardFontPreferenceKey];
276 }
277
278 - (NSString *)fixedFontFamily
279 {
280     return [self _stringValueForKey: WebKitFixedFontPreferenceKey];
281 }
282
283 - (void)setFixedFontFamily:(NSString *)family
284 {
285     [self _setStringValue: family forKey: WebKitFixedFontPreferenceKey];
286 }
287
288 - (NSString *)serifFontFamily
289 {
290     return [self _stringValueForKey: WebKitSerifFontPreferenceKey];
291 }
292
293 - (void)setSerifFontFamily:(NSString *)family 
294 {
295     [self _setStringValue: family forKey: WebKitSerifFontPreferenceKey];
296 }
297
298 - (NSString *)sansSerifFontFamily
299 {
300     return [self _stringValueForKey: WebKitSansSerifFontPreferenceKey];
301 }
302
303 - (void)setSansSerifFontFamily:(NSString *)family
304 {
305     [self _setStringValue: family forKey: WebKitSansSerifFontPreferenceKey];
306 }
307
308 - (NSString *)cursiveFontFamily
309 {
310     return [self _stringValueForKey: WebKitCursiveFontPreferenceKey];
311 }
312
313 - (void)setCursiveFontFamily:(NSString *)family
314 {
315     [self _setStringValue: family forKey: WebKitCursiveFontPreferenceKey];
316 }
317
318 - (NSString *)fantasyFontFamily
319 {
320     return [self _stringValueForKey: WebKitFantasyFontPreferenceKey];
321 }
322
323 - (void)setFantasyFontFamily:(NSString *)family
324 {
325     [self _setStringValue: family forKey: WebKitFantasyFontPreferenceKey];
326 }
327
328 - (int)defaultFontSize
329 {
330     return [self _integerValueForKey: WebKitDefaultFontSizePreferenceKey];
331 }
332
333 - (void)setDefaultFontSize:(int)size
334 {
335     [self _setIntegerValue: size forKey: WebKitDefaultFontSizePreferenceKey];
336 }
337
338 - (int)defaultFixedFontSize
339 {
340     return [self _integerValueForKey: WebKitDefaultFixedFontSizePreferenceKey];
341 }
342
343 - (void)setDefaultFixedFontSize:(int)size
344 {
345     [self _setIntegerValue: size forKey: WebKitDefaultFixedFontSizePreferenceKey];
346 }
347
348 - (int)minimumFontSize
349 {
350     return [self _integerValueForKey: WebKitMinimumFontSizePreferenceKey];
351 }
352
353 - (void)setMinimumFontSize:(int)size
354 {
355     [self _setIntegerValue: size forKey: WebKitMinimumFontSizePreferenceKey];
356 }
357
358 - (int)minimumLogicalFontSize
359 {
360   return [self _integerValueForKey: WebKitMinimumLogicalFontSizePreferenceKey];
361 }
362
363 - (void)setMinimumLogicalFontSize:(int)size
364 {
365   [self _setIntegerValue: size forKey: WebKitMinimumLogicalFontSizePreferenceKey];
366 }
367
368 - (NSString *)defaultTextEncodingName
369 {
370     return [self _stringValueForKey: WebKitDefaultTextEncodingNamePreferenceKey];
371 }
372
373 - (void)setDefaultTextEncodingName:(NSString *)encoding
374 {
375     [self _setStringValue: encoding forKey: WebKitDefaultTextEncodingNamePreferenceKey];
376 }
377
378 - (BOOL)userStyleSheetEnabled
379 {
380     return [self _boolValueForKey: WebKitUserStyleSheetEnabledPreferenceKey];
381 }
382
383 - (void)setUserStyleSheetEnabled:(BOOL)flag
384 {
385     [self _setBoolValue: flag forKey: WebKitUserStyleSheetEnabledPreferenceKey];
386 }
387
388 - (NSURL *)userStyleSheetLocation
389 {
390     NSString *locationString = [self _stringValueForKey: WebKitUserStyleSheetLocationPreferenceKey];
391     
392     if ([locationString _web_looksLikeAbsoluteURL]) {
393         return [NSURL _web_URLWithDataAsString:locationString];
394     } else {
395         locationString = [locationString stringByExpandingTildeInPath];
396         return [NSURL fileURLWithPath:locationString];
397     }
398 }
399
400 - (void)setUserStyleSheetLocation:(NSURL *)URL
401 {
402     NSString *locationString;
403     
404     if ([URL isFileURL]) {
405         locationString = [[URL path] _web_stringByAbbreviatingWithTildeInPath];
406     } else {
407         locationString = [URL _web_originalDataAsString];
408     }
409     
410     [self _setStringValue:locationString forKey: WebKitUserStyleSheetLocationPreferenceKey];
411 }
412
413 - (BOOL)shouldPrintBackgrounds
414 {
415     return [self _boolValueForKey: WebKitShouldPrintBackgroundsPreferenceKey];
416 }
417
418 - (void)setShouldPrintBackgrounds:(BOOL)flag
419 {
420     [self _setBoolValue: flag forKey: WebKitShouldPrintBackgroundsPreferenceKey];
421 }
422
423 - (BOOL)isJavaEnabled
424 {
425     return [self _boolValueForKey: WebKitJavaEnabledPreferenceKey];
426 }
427
428 - (void)setJavaEnabled:(BOOL)flag
429 {
430     [self _setBoolValue: flag forKey: WebKitJavaEnabledPreferenceKey];
431 }
432
433 - (BOOL)isJavaScriptEnabled
434 {
435     return [self _boolValueForKey: WebKitJavaScriptEnabledPreferenceKey];
436 }
437
438 - (void)setJavaScriptEnabled:(BOOL)flag
439 {
440     [self _setBoolValue: flag forKey: WebKitJavaScriptEnabledPreferenceKey];
441 }
442
443 - (BOOL)javaScriptCanOpenWindowsAutomatically
444 {
445     return [self _boolValueForKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
446 }
447
448 - (void)setJavaScriptCanOpenWindowsAutomatically:(BOOL)flag
449 {
450     [self _setBoolValue: flag forKey: WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey];
451 }
452
453 - (BOOL)arePlugInsEnabled
454 {
455     return [self _boolValueForKey: WebKitPluginsEnabledPreferenceKey];
456 }
457
458 - (void)setPlugInsEnabled:(BOOL)flag
459 {
460     [self _setBoolValue: flag forKey: WebKitPluginsEnabledPreferenceKey];
461 }
462
463 - (BOOL)allowsAnimatedImages
464 {
465     return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey];
466 }
467
468 - (void)setAllowsAnimatedImages:(BOOL)flag;
469 {
470     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey];
471 }
472
473 - (BOOL)allowsAnimatedImageLooping
474 {
475     return [self _boolValueForKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
476 }
477
478 - (void)setAllowsAnimatedImageLooping: (BOOL)flag
479 {
480     [self _setBoolValue: flag forKey: WebKitAllowAnimatedImageLoopingPreferenceKey];
481 }
482
483 - (void)setLoadsImagesAutomatically: (BOOL)flag
484 {
485     [self _setBoolValue: flag forKey: WebKitDisplayImagesKey];
486 }
487
488 - (BOOL)loadsImagesAutomatically
489 {
490     return [self _boolValueForKey: WebKitDisplayImagesKey];
491 }
492
493 - (void)setAutosaves:(BOOL)flag;
494 {
495     _private->autosaves = flag;
496 }
497
498 - (BOOL)autosaves
499 {
500     return _private->autosaves;
501 }
502
503 - (void)setTabsToLinks:(BOOL)flag
504 {
505     [self _setBoolValue: flag forKey: WebKitTabToLinksPreferenceKey];
506 }
507
508 - (BOOL)tabsToLinks
509 {
510     return [self _boolValueForKey:WebKitTabToLinksPreferenceKey];
511 }
512
513 - (void)setPrivateBrowsingEnabled:(BOOL)flag
514 {
515     [self _setBoolValue:flag forKey:WebKitPrivateBrowsingEnabledPreferenceKey];
516 }
517
518 - (BOOL)privateBrowsingEnabled
519 {
520     return [self _boolValueForKey:WebKitPrivateBrowsingEnabledPreferenceKey];
521 }
522
523 @end
524
525 @implementation WebPreferences (WebPrivate)
526
527 - (int)_pageCacheSize
528 {
529     return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitPageCacheSizePreferenceKey];
530 }
531
532 - (int)_objectCacheSize
533 {
534     return [[NSUserDefaults standardUserDefaults] integerForKey:WebKitObjectCacheSizePreferenceKey];
535 }
536
537 - (NSTimeInterval)_backForwardCacheExpirationInterval
538 {
539     return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
540 }
541
542 static NSMutableDictionary *webPreferencesInstances = nil;
543
544 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
545 {
546         LOG (Encoding, "requesting for %@\n", ident);
547
548     if (!ident){
549         if(_standardPreferences)
550             return _standardPreferences;
551         return nil;
552     }    
553     
554     WebPreferences *instance = [webPreferencesInstances objectForKey:[self _concatenateKeyWithIBCreatorID:ident]];
555
556     return instance;
557 }
558
559 + (void)_setInstance:(WebPreferences *)instance forIdentifier:(NSString *)ident
560 {
561     if (!webPreferencesInstances)
562         webPreferencesInstances = [[NSMutableDictionary alloc] init];
563     if (ident) {
564         [webPreferencesInstances setObject:instance forKey:[self _concatenateKeyWithIBCreatorID:ident]];
565         LOG (Encoding, "recording %p for %@\n", instance, [self _concatenateKeyWithIBCreatorID:ident]);
566     }
567 }
568
569 + (void)_removeReferenceForIdentifier:(NSString *)ident
570 {
571     if (ident != nil) {
572         [webPreferencesInstances performSelector:@selector(_web_checkLastReferenceForIdentifier:) withObject: [self _concatenateKeyWithIBCreatorID:ident] afterDelay:.1];
573     }
574 }
575
576 - (void)_postPreferencesChangesNotification
577 {
578     [[NSNotificationCenter defaultCenter]
579         postNotificationName:WebPreferencesChangedNotification object:self
580                     userInfo:nil];
581 }
582
583 static NSString *classIBCreatorID = nil;
584
585 + (void)_setIBCreatorID:(NSString *)string
586 {
587     NSString *old = classIBCreatorID;
588     classIBCreatorID = [string copy];
589     [old release];
590 }
591
592 @end
593
594 @implementation WebPreferences (WebInternal)
595
596 + (NSString *)_IBCreatorID
597 {
598     return classIBCreatorID;
599 }
600
601 + (NSString *)_concatenateKeyWithIBCreatorID:(NSString *)key
602 {
603     NSString *IBCreatorID = [WebPreferences _IBCreatorID];
604     if (!IBCreatorID)
605         return key;
606     return [IBCreatorID stringByAppendingString:key];
607 }
608
609 @end
610
611 @implementation NSMutableDictionary (WebInternal)
612
613 - (void)_web_checkLastReferenceForIdentifier:(NSString *)identifier
614 {
615     WebPreferences *instance = [webPreferencesInstances objectForKey:identifier];
616     if ([instance retainCount] == 1)
617         [webPreferencesInstances removeObjectForKey:identifier];
618 }
619
620 @end