fa2542b31b30bbb4bc97ce744db90ac7d8ddba1f
[WebKit-https.git] / Source / WebCore / platform / mac / Language.mm
1 /*
2  * Copyright (C) 2003, 2005, 2006, 2010, 2011 Apple 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "Language.h"
28
29 #import "BlockExceptions.h"
30 #import "WebCoreNSStringExtras.h"
31 #import <mutex>
32 #import <wtf/Assertions.h>
33 #import <wtf/NeverDestroyed.h>
34 #import <wtf/RetainPtr.h>
35 #import <wtf/text/WTFString.h>
36
37 namespace WebCore {
38
39 static std::mutex& preferredLanguagesMutex()
40 {
41     static dispatch_once_t onceToken;
42     static std::mutex* mutex;
43
44     dispatch_once(&onceToken, ^{
45         mutex = std::make_unique<std::mutex>().release();
46     });
47
48     return *mutex;
49 }
50
51 static Vector<String>& preferredLanguages()
52 {
53     static NeverDestroyed<Vector<String>> languages;
54     return languages;
55 }
56
57 }
58
59 @interface WebLanguageChangeObserver : NSObject
60 @end
61
62 @implementation WebLanguageChangeObserver
63
64 + (void)languagePreferencesDidChange:(NSNotification *)notification
65 {
66     UNUSED_PARAM(notification);
67
68     {
69         std::lock_guard<std::mutex> lock(WebCore::preferredLanguagesMutex());
70         WebCore::preferredLanguages().clear();
71     }
72
73     WebCore::languageDidChange();
74 }
75
76 @end
77
78 namespace WebCore {
79
80 static String httpStyleLanguageCode(NSString *language)
81 {
82     return [[NSLocale canonicalLanguageIdentifierFromString:canonicalLocaleName(language)] lowercaseString];
83 }
84
85 Vector<String> platformUserPreferredLanguages()
86 {
87 #if PLATFORM(MAC)
88     static dispatch_once_t onceToken;
89     dispatch_once(&onceToken, ^{
90         [[NSDistributedNotificationCenter defaultCenter] addObserver:[WebLanguageChangeObserver self] selector:@selector(languagePreferencesDidChange:) name:@"AppleLanguagePreferencesChangedNotification" object:nil];
91     });
92 #endif
93
94     BEGIN_BLOCK_OBJC_EXCEPTIONS;
95
96     std::lock_guard<std::mutex> lock(preferredLanguagesMutex());
97     Vector<String>& userPreferredLanguages = preferredLanguages();
98
99     if (userPreferredLanguages.isEmpty()) {
100         RetainPtr<CFArrayRef> languages = adoptCF(CFLocaleCopyPreferredLanguages());
101         CFIndex languageCount = CFArrayGetCount(languages.get());
102         if (!languageCount)
103             userPreferredLanguages.append("en");
104         else {
105             for (CFIndex i = 0; i < languageCount; i++)
106                 userPreferredLanguages.append(httpStyleLanguageCode((NSString *)CFArrayGetValueAtIndex(languages.get(), i)));
107         }
108     }
109
110     Vector<String> userPreferredLanguagesCopy;
111     userPreferredLanguagesCopy.reserveInitialCapacity(userPreferredLanguages.size());
112
113     for (auto& language : userPreferredLanguages)
114         userPreferredLanguagesCopy.uncheckedAppend(language.isolatedCopy());
115
116     return userPreferredLanguagesCopy;
117
118     END_BLOCK_OBJC_EXCEPTIONS;
119
120     return Vector<String>();
121 }
122
123 }