Home | History | Annotate | Download | only in Misc
      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 "WebNSUserDefaultsExtras.h"
     30 
     31 #import "WebNSObjectExtras.h"
     32 #import <WebKitSystemInterface.h>
     33 #import <wtf/Assertions.h>
     34 
     35 @implementation NSString (WebNSUserDefaultsPrivate)
     36 
     37 - (NSString *)_webkit_HTTPStyleLanguageCode
     38 {
     39     // Look up the language code using CFBundle.
     40     NSString *languageCode = self;
     41     NSString *preferredLanguageCode = WebCFAutorelease(WKCopyCFLocalizationPreferredName((CFStringRef)self));
     42 
     43     if (preferredLanguageCode)
     44         languageCode = preferredLanguageCode;
     45 
     46     // Make the string lowercase.
     47     NSString *lowercaseLanguageCode = [languageCode lowercaseString];
     48 
     49     // Turn a '_' into a '-' if it appears after a 2-letter language code.
     50     if ([lowercaseLanguageCode length] < 3 || [lowercaseLanguageCode characterAtIndex:2] != '_') {
     51         return lowercaseLanguageCode;
     52     }
     53     NSMutableString *result = [lowercaseLanguageCode mutableCopy];
     54     [result replaceCharactersInRange:NSMakeRange(2, 1) withString:@"-"];
     55     return [result autorelease];
     56 }
     57 
     58 @end
     59 
     60 @implementation NSUserDefaults (WebNSUserDefaultsExtras)
     61 
     62 static NSString *preferredLanguageCode = nil;
     63 static NSLock *preferredLanguageLock = nil;
     64 static pthread_once_t preferredLanguageLockOnce = PTHREAD_ONCE_INIT;
     65 static pthread_once_t addDefaultsChangeObserverOnce = PTHREAD_ONCE_INIT;
     66 
     67 static void makeLock(void)
     68 {
     69     preferredLanguageLock = [[NSLock alloc] init];
     70 }
     71 
     72 + (void)_webkit_ensureAndLockPreferredLanguageLock
     73 {
     74     pthread_once(&preferredLanguageLockOnce, makeLock);
     75     [preferredLanguageLock lock];
     76 }
     77 
     78 + (void)_webkit_defaultsDidChange
     79 {
     80     [self _webkit_ensureAndLockPreferredLanguageLock];
     81 
     82     [preferredLanguageCode release];
     83     preferredLanguageCode = nil;
     84 
     85     [preferredLanguageLock unlock];
     86 }
     87 
     88 static void addDefaultsChangeObserver(void)
     89 {
     90     [[NSNotificationCenter defaultCenter] addObserver:[NSUserDefaults class]
     91                                              selector:@selector(_webkit_defaultsDidChange)
     92                                                  name:NSUserDefaultsDidChangeNotification
     93                                                object:[NSUserDefaults standardUserDefaults]];
     94 }
     95 
     96 + (void)_webkit_addDefaultsChangeObserver
     97 {
     98     pthread_once(&addDefaultsChangeObserverOnce, addDefaultsChangeObserver);
     99 }
    100 
    101 + (NSString *)_webkit_preferredLanguageCode
    102 {
    103     // Get this outside the lock since it might block on the defaults lock, while we are inside registerDefaults:.
    104     NSUserDefaults *standardDefaults = [self standardUserDefaults];
    105 
    106     BOOL addObserver = NO;
    107 
    108     [self _webkit_ensureAndLockPreferredLanguageLock];
    109 
    110     if (!preferredLanguageCode) {
    111         NSArray *languages = [standardDefaults stringArrayForKey:@"AppleLanguages"];
    112         if ([languages count] == 0) {
    113             preferredLanguageCode = [@"en" retain];
    114         } else {
    115             preferredLanguageCode = [[[languages objectAtIndex:0] _webkit_HTTPStyleLanguageCode] copy];
    116         }
    117         addObserver = YES;
    118     }
    119 
    120     NSString *code = [[preferredLanguageCode retain] autorelease];
    121 
    122     [preferredLanguageLock unlock];
    123 
    124     if (addObserver) {
    125         [self _webkit_addDefaultsChangeObserver];
    126     }
    127 
    128     return code;
    129 }
    130 
    131 @end
    132