Reviewed by Hyatt.
[WebKit-https.git] / WebKit / Misc.subproj / WebNSUserDefaultsExtras.m
1 /*
2     WebNSUserDefaultsExtras.m
3     Private (SPI) header
4     Copyright 2005, Apple, Inc. All rights reserved.
5  */
6
7 #import <WebKit/WebNSUserDefaultsExtras.h>
8
9 #import <WebKit/WebAssertions.h>
10 #import <WebKitSystemInterface.h>
11
12 @implementation NSString (WebNSUserDefaultsPrivate)
13
14 - (NSString *)_webkit_HTTPStyleLanguageCode
15 {
16     // Look up the language code using CFBundle.
17     NSString *languageCode = self;
18     NSString *preferredLanguageCode = [(id)WKCopyCFLocalizationPreferredName((CFStringRef)self) autorelease];
19
20     if (preferredLanguageCode)
21         languageCode = preferredLanguageCode;
22     
23     // Make the string lowercase.
24     NSString *lowercaseLanguageCode = [languageCode lowercaseString];
25     
26     // Turn a '_' into a '-' if it appears after a 2-letter language code.
27     if ([lowercaseLanguageCode length] < 3 || [lowercaseLanguageCode characterAtIndex:2] != '_') {
28         return lowercaseLanguageCode;
29     }
30     NSMutableString *result = [lowercaseLanguageCode mutableCopy];
31     [result replaceCharactersInRange:NSMakeRange(2, 1) withString:@"-"];
32     return [result autorelease];
33 }
34
35 @end
36
37 @implementation NSUserDefaults (WebNSUserDefaultsExtras)
38
39 static NSString *preferredLanguageCode = nil;
40 static NSLock *preferredLanguageLock = nil;
41 static pthread_once_t preferredLanguageLockOnce = PTHREAD_ONCE_INIT;
42 static pthread_once_t addDefaultsChangeObserverOnce = PTHREAD_ONCE_INIT;
43
44 static void makeLock(void)
45 {
46     preferredLanguageLock = [[NSLock alloc] init]; 
47 }
48
49 + (void)_ensureAndLockPreferredLanguageLock
50 {
51     pthread_once(&preferredLanguageLockOnce, makeLock);
52     [preferredLanguageLock lock];
53 }
54
55 + (void)_webkit_defaultsDidChange
56 {
57     [self _ensureAndLockPreferredLanguageLock];
58
59     [preferredLanguageCode release];
60     preferredLanguageCode = nil;
61
62     [preferredLanguageLock unlock];
63 }
64
65 static void addDefaultsChangeObserver(void)
66 {
67     [[NSNotificationCenter defaultCenter] addObserver:[NSUserDefaults class]
68                                              selector:@selector(_webkit_defaultsDidChange)
69                                                  name:NSUserDefaultsDidChangeNotification
70                                                object:[NSUserDefaults standardUserDefaults]];
71 }
72
73 + (void)_webkit_addDefaultsChangeObserver
74 {
75     pthread_once(&addDefaultsChangeObserverOnce, addDefaultsChangeObserver);
76 }
77
78 + (NSString *)_webkit_preferredLanguageCode
79 {
80     // Get this outside the lock since it might block on the defaults lock, while we are inside registerDefaults:.
81     NSUserDefaults *standardDefaults = [self standardUserDefaults];
82
83     BOOL addObserver = NO;
84
85     [self _ensureAndLockPreferredLanguageLock];
86
87     if (!preferredLanguageCode) {
88         NSArray *languages = [standardDefaults stringArrayForKey:@"AppleLanguages"];
89         if ([languages count] == 0) {
90             preferredLanguageCode = [@"en" retain];
91         } else {
92             preferredLanguageCode = [[[languages objectAtIndex:0] _webkit_HTTPStyleLanguageCode] copy];
93         }
94         addObserver = YES;
95     }
96
97     NSString *code = [[preferredLanguageCode retain] autorelease];
98     
99     [preferredLanguageLock unlock];
100
101     if (addObserver) {
102         [self _webkit_addDefaultsChangeObserver];
103     }
104
105     return code;
106 }
107
108 @end