|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "mozilla/dom/FallbackEncoding.h" |
|
6 |
|
7 #include "mozilla/dom/EncodingUtils.h" |
|
8 #include "nsUConvPropertySearch.h" |
|
9 #include "nsIChromeRegistry.h" |
|
10 #include "mozilla/Preferences.h" |
|
11 #include "mozilla/Services.h" |
|
12 |
|
13 namespace mozilla { |
|
14 namespace dom { |
|
15 |
|
16 static const char* localesFallbacks[][3] = { |
|
17 #include "localesfallbacks.properties.h" |
|
18 }; |
|
19 |
|
20 static const char* domainsFallbacks[][3] = { |
|
21 #include "domainsfallbacks.properties.h" |
|
22 }; |
|
23 |
|
24 static const char* nonParticipatingDomains[][3] = { |
|
25 #include "nonparticipatingdomains.properties.h" |
|
26 }; |
|
27 |
|
28 FallbackEncoding* FallbackEncoding::sInstance = nullptr; |
|
29 bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true; |
|
30 |
|
31 FallbackEncoding::FallbackEncoding() |
|
32 { |
|
33 MOZ_COUNT_CTOR(FallbackEncoding); |
|
34 MOZ_ASSERT(!FallbackEncoding::sInstance, |
|
35 "Singleton already exists."); |
|
36 } |
|
37 |
|
38 FallbackEncoding::~FallbackEncoding() |
|
39 { |
|
40 MOZ_COUNT_DTOR(FallbackEncoding); |
|
41 } |
|
42 |
|
43 void |
|
44 FallbackEncoding::Get(nsACString& aFallback) |
|
45 { |
|
46 if (!mFallback.IsEmpty()) { |
|
47 aFallback = mFallback; |
|
48 return; |
|
49 } |
|
50 |
|
51 const nsAdoptingCString& override = |
|
52 Preferences::GetCString("intl.charset.fallback.override"); |
|
53 // Don't let the user break things by setting the override to unreasonable |
|
54 // values via about:config |
|
55 if (!EncodingUtils::FindEncodingForLabel(override, mFallback) || |
|
56 !EncodingUtils::IsAsciiCompatible(mFallback) || |
|
57 mFallback.EqualsLiteral("UTF-8")) { |
|
58 mFallback.Truncate(); |
|
59 } |
|
60 |
|
61 if (!mFallback.IsEmpty()) { |
|
62 aFallback = mFallback; |
|
63 return; |
|
64 } |
|
65 |
|
66 nsAutoCString locale; |
|
67 nsCOMPtr<nsIXULChromeRegistry> registry = |
|
68 mozilla::services::GetXULChromeRegistryService(); |
|
69 if (registry) { |
|
70 registry->GetSelectedLocale(NS_LITERAL_CSTRING("global"), locale); |
|
71 } |
|
72 |
|
73 // Let's lower case the string just in case unofficial language packs |
|
74 // don't stick to conventions. |
|
75 ToLowerCase(locale); // ASCII lowercasing with CString input! |
|
76 |
|
77 // Special case Traditional Chinese before throwing away stuff after the |
|
78 // language itself. Today we only ship zh-TW, but be defensive about |
|
79 // possible future values. |
|
80 if (locale.EqualsLiteral("zh-tw") || |
|
81 locale.EqualsLiteral("zh-hk") || |
|
82 locale.EqualsLiteral("zh-mo") || |
|
83 locale.EqualsLiteral("zh-hant")) { |
|
84 mFallback.AssignLiteral("Big5"); |
|
85 aFallback = mFallback; |
|
86 return; |
|
87 } |
|
88 |
|
89 // Throw away regions and other variants to accommodate weird stuff seen |
|
90 // in telemetry--apparently unofficial language packs. |
|
91 int32_t index = locale.FindChar('-'); |
|
92 if (index >= 0) { |
|
93 locale.Truncate(index); |
|
94 } |
|
95 |
|
96 if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue( |
|
97 localesFallbacks, ArrayLength(localesFallbacks), locale, mFallback))) { |
|
98 mFallback.AssignLiteral("windows-1252"); |
|
99 } |
|
100 |
|
101 aFallback = mFallback; |
|
102 } |
|
103 |
|
104 void |
|
105 FallbackEncoding::FromLocale(nsACString& aFallback) |
|
106 { |
|
107 MOZ_ASSERT(FallbackEncoding::sInstance, |
|
108 "Using uninitialized fallback cache."); |
|
109 FallbackEncoding::sInstance->Get(aFallback); |
|
110 } |
|
111 |
|
112 // PrefChangedFunc |
|
113 void |
|
114 FallbackEncoding::PrefChanged(const char*, void*) |
|
115 { |
|
116 MOZ_ASSERT(FallbackEncoding::sInstance, |
|
117 "Pref callback called with null fallback cache."); |
|
118 FallbackEncoding::sInstance->Invalidate(); |
|
119 } |
|
120 |
|
121 void |
|
122 FallbackEncoding::Initialize() |
|
123 { |
|
124 MOZ_ASSERT(!FallbackEncoding::sInstance, |
|
125 "Initializing pre-existing fallback cache."); |
|
126 FallbackEncoding::sInstance = new FallbackEncoding; |
|
127 Preferences::RegisterCallback(FallbackEncoding::PrefChanged, |
|
128 "intl.charset.fallback.override", |
|
129 nullptr); |
|
130 Preferences::RegisterCallback(FallbackEncoding::PrefChanged, |
|
131 "general.useragent.locale", |
|
132 nullptr); |
|
133 Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain, |
|
134 "intl.charset.fallback.tld"); |
|
135 } |
|
136 |
|
137 void |
|
138 FallbackEncoding::Shutdown() |
|
139 { |
|
140 MOZ_ASSERT(FallbackEncoding::sInstance, |
|
141 "Releasing non-existent fallback cache."); |
|
142 delete FallbackEncoding::sInstance; |
|
143 FallbackEncoding::sInstance = nullptr; |
|
144 } |
|
145 |
|
146 bool |
|
147 FallbackEncoding::IsParticipatingTopLevelDomain(const nsACString& aTLD) |
|
148 { |
|
149 nsAutoCString dummy; |
|
150 return NS_FAILED(nsUConvPropertySearch::SearchPropertyValue( |
|
151 nonParticipatingDomains, |
|
152 ArrayLength(nonParticipatingDomains), |
|
153 aTLD, |
|
154 dummy)); |
|
155 } |
|
156 |
|
157 void |
|
158 FallbackEncoding::FromTopLevelDomain(const nsACString& aTLD, |
|
159 nsACString& aFallback) |
|
160 { |
|
161 if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue( |
|
162 domainsFallbacks, ArrayLength(domainsFallbacks), aTLD, aFallback))) { |
|
163 aFallback.AssignLiteral("windows-1252"); |
|
164 } |
|
165 } |
|
166 |
|
167 } // namespace dom |
|
168 } // namespace mozilla |