Coverage Report

Created: 2018-09-25 14:53

/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