Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
5 #include "mozilla/dom/FallbackEncoding.h"
7 #include "mozilla/dom/EncodingUtils.h"
8 #include "nsUConvPropertySearch.h"
9 #include "nsIChromeRegistry.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/Services.h"
13 namespace mozilla {
14 namespace dom {
16 static const char* localesFallbacks[][3] = {
17 #include "localesfallbacks.properties.h"
18 };
20 static const char* domainsFallbacks[][3] = {
21 #include "domainsfallbacks.properties.h"
22 };
24 static const char* nonParticipatingDomains[][3] = {
25 #include "nonparticipatingdomains.properties.h"
26 };
28 FallbackEncoding* FallbackEncoding::sInstance = nullptr;
29 bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true;
31 FallbackEncoding::FallbackEncoding()
32 {
33 MOZ_COUNT_CTOR(FallbackEncoding);
34 MOZ_ASSERT(!FallbackEncoding::sInstance,
35 "Singleton already exists.");
36 }
38 FallbackEncoding::~FallbackEncoding()
39 {
40 MOZ_COUNT_DTOR(FallbackEncoding);
41 }
43 void
44 FallbackEncoding::Get(nsACString& aFallback)
45 {
46 if (!mFallback.IsEmpty()) {
47 aFallback = mFallback;
48 return;
49 }
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 }
61 if (!mFallback.IsEmpty()) {
62 aFallback = mFallback;
63 return;
64 }
66 nsAutoCString locale;
67 nsCOMPtr<nsIXULChromeRegistry> registry =
68 mozilla::services::GetXULChromeRegistryService();
69 if (registry) {
70 registry->GetSelectedLocale(NS_LITERAL_CSTRING("global"), locale);
71 }
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!
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 }
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 }
96 if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
97 localesFallbacks, ArrayLength(localesFallbacks), locale, mFallback))) {
98 mFallback.AssignLiteral("windows-1252");
99 }
101 aFallback = mFallback;
102 }
104 void
105 FallbackEncoding::FromLocale(nsACString& aFallback)
106 {
107 MOZ_ASSERT(FallbackEncoding::sInstance,
108 "Using uninitialized fallback cache.");
109 FallbackEncoding::sInstance->Get(aFallback);
110 }
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 }
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 }
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 }
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 }
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 }
167 } // namespace dom
168 } // namespace mozilla