summaryrefslogtreecommitdiffstats
path: root/dom/encoding/FallbackEncoding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/encoding/FallbackEncoding.cpp')
-rw-r--r--dom/encoding/FallbackEncoding.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/dom/encoding/FallbackEncoding.cpp b/dom/encoding/FallbackEncoding.cpp
new file mode 100644
index 000000000..93fe0f8cb
--- /dev/null
+++ b/dom/encoding/FallbackEncoding.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/FallbackEncoding.h"
+
+#include "mozilla/dom/EncodingUtils.h"
+#include "nsUConvPropertySearch.h"
+#include "nsIChromeRegistry.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+
+namespace mozilla {
+namespace dom {
+
+static const nsUConvProp localesFallbacks[] = {
+#include "localesfallbacks.properties.h"
+};
+
+static const nsUConvProp domainsFallbacks[] = {
+#include "domainsfallbacks.properties.h"
+};
+
+static const nsUConvProp nonParticipatingDomains[] = {
+#include "nonparticipatingdomains.properties.h"
+};
+
+FallbackEncoding* FallbackEncoding::sInstance = nullptr;
+bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true;
+
+FallbackEncoding::FallbackEncoding()
+{
+ MOZ_COUNT_CTOR(FallbackEncoding);
+ MOZ_ASSERT(!FallbackEncoding::sInstance,
+ "Singleton already exists.");
+}
+
+FallbackEncoding::~FallbackEncoding()
+{
+ MOZ_COUNT_DTOR(FallbackEncoding);
+}
+
+void
+FallbackEncoding::Get(nsACString& aFallback)
+{
+ if (!mFallback.IsEmpty()) {
+ aFallback = mFallback;
+ return;
+ }
+
+ const nsAdoptingCString& override =
+ Preferences::GetCString("intl.charset.fallback.override");
+ // Don't let the user break things by setting the override to unreasonable
+ // values via about:config
+ if (!EncodingUtils::FindEncodingForLabel(override, mFallback) ||
+ !EncodingUtils::IsAsciiCompatible(mFallback) ||
+ mFallback.EqualsLiteral("UTF-8")) {
+ mFallback.Truncate();
+ }
+
+ if (!mFallback.IsEmpty()) {
+ aFallback = mFallback;
+ return;
+ }
+
+ nsAutoCString locale;
+ nsCOMPtr<nsIXULChromeRegistry> registry =
+ mozilla::services::GetXULChromeRegistryService();
+ if (registry) {
+ registry->GetSelectedLocale(NS_LITERAL_CSTRING("global"), false, locale);
+ }
+
+ // Let's lower case the string just in case unofficial language packs
+ // don't stick to conventions.
+ ToLowerCase(locale); // ASCII lowercasing with CString input!
+
+ // Special case Traditional Chinese before throwing away stuff after the
+ // language itself. Today we only ship zh-TW, but be defensive about
+ // possible future values.
+ if (locale.EqualsLiteral("zh-tw") ||
+ locale.EqualsLiteral("zh-hk") ||
+ locale.EqualsLiteral("zh-mo") ||
+ locale.EqualsLiteral("zh-hant")) {
+ mFallback.AssignLiteral("Big5");
+ aFallback = mFallback;
+ return;
+ }
+
+ // Throw away regions and other variants to accommodate weird stuff seen
+ // in telemetry--apparently unofficial language packs.
+ int32_t index = locale.FindChar('-');
+ if (index >= 0) {
+ locale.Truncate(index);
+ }
+
+ if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
+ localesFallbacks, ArrayLength(localesFallbacks), locale, mFallback))) {
+ mFallback.AssignLiteral("windows-1252");
+ }
+
+ aFallback = mFallback;
+}
+
+void
+FallbackEncoding::FromLocale(nsACString& aFallback)
+{
+ MOZ_ASSERT(FallbackEncoding::sInstance,
+ "Using uninitialized fallback cache.");
+ FallbackEncoding::sInstance->Get(aFallback);
+}
+
+// PrefChangedFunc
+void
+FallbackEncoding::PrefChanged(const char*, void*)
+{
+ MOZ_ASSERT(FallbackEncoding::sInstance,
+ "Pref callback called with null fallback cache.");
+ FallbackEncoding::sInstance->Invalidate();
+}
+
+void
+FallbackEncoding::Initialize()
+{
+ MOZ_ASSERT(!FallbackEncoding::sInstance,
+ "Initializing pre-existing fallback cache.");
+ FallbackEncoding::sInstance = new FallbackEncoding;
+ Preferences::RegisterCallback(FallbackEncoding::PrefChanged,
+ "intl.charset.fallback.override",
+ nullptr);
+ Preferences::RegisterCallback(FallbackEncoding::PrefChanged,
+ "general.useragent.locale",
+ nullptr);
+ Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain,
+ "intl.charset.fallback.tld");
+}
+
+void
+FallbackEncoding::Shutdown()
+{
+ MOZ_ASSERT(FallbackEncoding::sInstance,
+ "Releasing non-existent fallback cache.");
+ delete FallbackEncoding::sInstance;
+ FallbackEncoding::sInstance = nullptr;
+}
+
+bool
+FallbackEncoding::IsParticipatingTopLevelDomain(const nsACString& aTLD)
+{
+ nsAutoCString dummy;
+ return NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
+ nonParticipatingDomains,
+ ArrayLength(nonParticipatingDomains),
+ aTLD,
+ dummy));
+}
+
+void
+FallbackEncoding::FromTopLevelDomain(const nsACString& aTLD,
+ nsACString& aFallback)
+{
+ if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
+ domainsFallbacks, ArrayLength(domainsFallbacks), aTLD, aFallback))) {
+ aFallback.AssignLiteral("windows-1252");
+ }
+}
+
+} // namespace dom
+} // namespace mozilla