/src/mozilla-central/dom/encoding/FallbackEncoding.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "mozilla/dom/FallbackEncoding.h" |
8 | | |
9 | | #include "mozilla/ArrayUtils.h" |
10 | | #include "mozilla/Encoding.h" |
11 | | #include "mozilla/intl/LocaleService.h" |
12 | | #include "mozilla/Preferences.h" |
13 | | #include "mozilla/Services.h" |
14 | | #include "nsIObserverService.h" |
15 | | #include "nsUConvPropertySearch.h" |
16 | | |
17 | | using mozilla::intl::LocaleService; |
18 | | |
19 | | namespace mozilla { |
20 | | namespace dom { |
21 | | |
22 | | struct EncodingProp |
23 | | { |
24 | | const char* const mKey; |
25 | | NotNull<const Encoding*> mValue; |
26 | | }; |
27 | | |
28 | | template <int32_t N> |
29 | | static NotNull<const Encoding*> |
30 | | SearchEncodingProp(const EncodingProp (&aProperties)[N], |
31 | | const nsACString& aKey) |
32 | 0 | { |
33 | 0 | const nsCString& flat = PromiseFlatCString(aKey); |
34 | 0 | size_t index; |
35 | 0 | if (!BinarySearchIf(aProperties, 0, ArrayLength(aProperties), |
36 | 0 | [&flat](const EncodingProp& aProperty) |
37 | 0 | { return flat.Compare(aProperty.mKey); }, &index)) { Unexecuted instantiation: Unified_cpp_dom_encoding0.cpp:mozilla::NotNull<mozilla::Encoding const*> mozilla::dom::SearchEncodingProp<32>(mozilla::dom::EncodingProp const (&) [32], nsTSubstring<char> const&)::{lambda(mozilla::dom::EncodingProp const&)#1}::operator()(mozilla::dom::EncodingProp const&) const Unexecuted instantiation: Unified_cpp_dom_encoding0.cpp:mozilla::NotNull<mozilla::Encoding const*> mozilla::dom::SearchEncodingProp<81>(mozilla::dom::EncodingProp const (&) [81], nsTSubstring<char> const&)::{lambda(mozilla::dom::EncodingProp const&)#1}::operator()(mozilla::dom::EncodingProp const&) const |
38 | 0 | return WINDOWS_1252_ENCODING; |
39 | 0 | } |
40 | 0 | return aProperties[index].mValue; |
41 | 0 | } Unexecuted instantiation: Unified_cpp_dom_encoding0.cpp:mozilla::NotNull<mozilla::Encoding const*> mozilla::dom::SearchEncodingProp<32>(mozilla::dom::EncodingProp const (&) [32], nsTSubstring<char> const&) Unexecuted instantiation: Unified_cpp_dom_encoding0.cpp:mozilla::NotNull<mozilla::Encoding const*> mozilla::dom::SearchEncodingProp<81>(mozilla::dom::EncodingProp const (&) [81], nsTSubstring<char> const&) |
42 | | |
43 | | static const EncodingProp localesFallbacks[] = { |
44 | | #include "localesfallbacks.properties.h" |
45 | | }; |
46 | | |
47 | | static const EncodingProp domainsFallbacks[] = { |
48 | | #include "domainsfallbacks.properties.h" |
49 | | }; |
50 | | |
51 | | static constexpr nsUConvProp nonParticipatingDomains[] = { |
52 | | #include "nonparticipatingdomains.properties.h" |
53 | | }; |
54 | | |
55 | | NS_IMPL_ISUPPORTS(FallbackEncoding, nsIObserver) |
56 | | |
57 | | FallbackEncoding* FallbackEncoding::sInstance = nullptr; |
58 | | bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true; |
59 | | bool FallbackEncoding::sFallbackToUTF8ForFile = false; |
60 | | |
61 | | FallbackEncoding::FallbackEncoding() |
62 | | : mFallback(nullptr) |
63 | 3 | { |
64 | 3 | MOZ_ASSERT(!FallbackEncoding::sInstance, |
65 | 3 | "Singleton already exists."); |
66 | 3 | } |
67 | | |
68 | | NotNull<const Encoding*> |
69 | | FallbackEncoding::Get() |
70 | 0 | { |
71 | 0 | if (mFallback) { |
72 | 0 | return WrapNotNull(mFallback); |
73 | 0 | } |
74 | 0 | |
75 | 0 | nsAutoCString override; |
76 | 0 | Preferences::GetCString("intl.charset.fallback.override", override); |
77 | 0 | // Don't let the user break things by setting the override to unreasonable |
78 | 0 | // values via about:config |
79 | 0 | auto encoding = Encoding::ForLabel(override); |
80 | 0 | if (!encoding || !encoding->IsAsciiCompatible() || |
81 | 0 | encoding == UTF_8_ENCODING) { |
82 | 0 | mFallback = nullptr; |
83 | 0 | } else { |
84 | 0 | mFallback = encoding; |
85 | 0 | } |
86 | 0 |
|
87 | 0 | if (mFallback) { |
88 | 0 | return WrapNotNull(mFallback); |
89 | 0 | } |
90 | 0 | |
91 | 0 | nsAutoCString locale; |
92 | 0 | LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale); |
93 | 0 |
|
94 | 0 | // Let's lower case the string just in case unofficial language packs |
95 | 0 | // don't stick to conventions. |
96 | 0 | ToLowerCase(locale); // ASCII lowercasing with CString input! |
97 | 0 |
|
98 | 0 | // Special case Traditional Chinese before throwing away stuff after the |
99 | 0 | // language itself. Today we only ship zh-TW, but be defensive about |
100 | 0 | // possible future values. |
101 | 0 | if (locale.EqualsLiteral("zh-tw") || |
102 | 0 | locale.EqualsLiteral("zh-hk") || |
103 | 0 | locale.EqualsLiteral("zh-mo") || |
104 | 0 | locale.EqualsLiteral("zh-hant")) { |
105 | 0 | mFallback = BIG5_ENCODING; |
106 | 0 | return WrapNotNull(mFallback); |
107 | 0 | } |
108 | 0 | |
109 | 0 | // Throw away regions and other variants to accommodate weird stuff seen |
110 | 0 | // in telemetry--apparently unofficial language packs. |
111 | 0 | int32_t index = locale.FindChar('-'); |
112 | 0 | if (index >= 0) { |
113 | 0 | locale.Truncate(index); |
114 | 0 | } |
115 | 0 |
|
116 | 0 | auto fallback = SearchEncodingProp(localesFallbacks, locale); |
117 | 0 | mFallback = fallback; |
118 | 0 |
|
119 | 0 | return fallback; |
120 | 0 | } |
121 | | |
122 | | NotNull<const Encoding*> |
123 | | FallbackEncoding::FromLocale() |
124 | 0 | { |
125 | 0 | MOZ_ASSERT(FallbackEncoding::sInstance, |
126 | 0 | "Using uninitialized fallback cache."); |
127 | 0 | return FallbackEncoding::sInstance->Get(); |
128 | 0 | } |
129 | | |
130 | | // PrefChangedFunc |
131 | | void |
132 | | FallbackEncoding::PrefChanged(const char*, void*) |
133 | 0 | { |
134 | 0 | MOZ_ASSERT(FallbackEncoding::sInstance, |
135 | 0 | "Pref callback called with null fallback cache."); |
136 | 0 | FallbackEncoding::sInstance->Invalidate(); |
137 | 0 | } |
138 | | |
139 | | NS_IMETHODIMP |
140 | | FallbackEncoding::Observe(nsISupports *aSubject, const char *aTopic, |
141 | | const char16_t *aData) |
142 | 0 | { |
143 | 0 | MOZ_ASSERT(FallbackEncoding::sInstance, |
144 | 0 | "Observe callback called with null fallback cache."); |
145 | 0 | FallbackEncoding::sInstance->Invalidate(); |
146 | 0 | return NS_OK; |
147 | 0 | } |
148 | | |
149 | | void |
150 | | FallbackEncoding::Initialize() |
151 | 3 | { |
152 | 3 | MOZ_ASSERT(!FallbackEncoding::sInstance, |
153 | 3 | "Initializing pre-existing fallback cache."); |
154 | 3 | FallbackEncoding::sInstance = new FallbackEncoding; |
155 | 3 | Preferences::RegisterCallback(FallbackEncoding::PrefChanged, |
156 | 3 | "intl.charset.fallback.override"); |
157 | 3 | Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain, |
158 | 3 | "intl.charset.fallback.tld"); |
159 | 3 | Preferences::AddBoolVarCache(&sFallbackToUTF8ForFile, |
160 | 3 | "intl.charset.fallback.utf8_for_file"); |
161 | 3 | |
162 | 3 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
163 | 3 | if (obs) { |
164 | 3 | obs->AddObserver(sInstance, "intl:requested-locales-changed", true); |
165 | 3 | } |
166 | 3 | } |
167 | | |
168 | | void |
169 | | FallbackEncoding::Shutdown() |
170 | 0 | { |
171 | 0 | MOZ_ASSERT(FallbackEncoding::sInstance, |
172 | 0 | "Releasing non-existent fallback cache."); |
173 | 0 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
174 | 0 | if (obs) { |
175 | 0 | obs->RemoveObserver(sInstance, "intl:requested-locales-changed"); |
176 | 0 | } |
177 | 0 | delete FallbackEncoding::sInstance; |
178 | 0 | FallbackEncoding::sInstance = nullptr; |
179 | 0 | } |
180 | | |
181 | | bool |
182 | | FallbackEncoding::IsParticipatingTopLevelDomain(const nsACString& aTLD) |
183 | 0 | { |
184 | 0 | nsAutoCString dummy; |
185 | 0 | return NS_FAILED(nsUConvPropertySearch::SearchPropertyValue( |
186 | 0 | nonParticipatingDomains, |
187 | 0 | ArrayLength(nonParticipatingDomains), |
188 | 0 | aTLD, |
189 | 0 | dummy)); |
190 | 0 | } |
191 | | |
192 | | NotNull<const Encoding*> |
193 | | FallbackEncoding::FromTopLevelDomain(const nsACString& aTLD) |
194 | 0 | { |
195 | 0 | return SearchEncodingProp(domainsFallbacks, aTLD); |
196 | 0 | } |
197 | | |
198 | | } // namespace dom |
199 | | } // namespace mozilla |