Backed out changeset c3e43b7b1376 (bug 1607052) for causing leaks CLOSED TREE

This commit is contained in:
Noemi Erli 2020-02-20 20:17:46 +02:00
Родитель 3d7d919746
Коммит 27e963773a
5 изменённых файлов: 53 добавлений и 58 удалений

Просмотреть файл

@ -45,15 +45,43 @@ mozilla::StaticRefPtr<LocaleService> LocaleService::sInstance;
*
* Example: "ja-JP-mac" -> "ja-JP-macos"
*
* The canonical Unicode Language Identifier form should be used for
* all calls to Intl APIs.
* The BCP47 form should be used for all calls to ICU/Intl APIs.
* The canonical form is used for all internal operations.
*/
bool LocaleService::CanonicalizeLanguageId(nsACString& aLocale) {
bool result;
auto loc = unic_langid_new(&aLocale, &result);
unic_langid_as_string(loc, &aLocale);
return result;
static bool SanitizeForBCP47(nsACString& aLocale, bool strict) {
// Currently, the only locale code we use that's not BCP47-conformant is
// "ja-JP-mac" on OS X, and ICU canonicalizes it into a mouthfull
// "ja-JP-x-lvariant-mac", so instead we're hardcoding a conversion
// of it to "ja-JP-macos".
if (aLocale.LowerCaseEqualsASCII("ja-jp-mac")) {
aLocale.AssignLiteral("ja-JP-macos");
return true;
}
nsAutoCString locale(aLocale);
locale.Trim(" ");
// POSIX may bring us locales such as "en-US.UTF8", which
// ICU converts to `en-US-u-va-posix`. Let's cut out
// the `.UTF8`, since it doesn't matter for us.
int32_t pos = locale.FindChar('.');
if (pos != -1) {
locale.Cut(pos, locale.Length() - pos);
}
// The rest of this function will use ICU canonicalization for any other
// tag that may come this way.
const int32_t LANG_TAG_CAPACITY = 128;
char langTag[LANG_TAG_CAPACITY];
UErrorCode err = U_ZERO_ERROR;
// This is a fail-safe method that will set langTag to "und" if it cannot
// match any part of the input locale code.
int32_t len = uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY,
strict, &err);
if (U_SUCCESS(err) && len > 0) {
aLocale.Assign(langTag, len);
}
return U_SUCCESS(err);
}
/**
@ -65,7 +93,7 @@ static void SplitLocaleListStringIntoArray(nsACString& str,
if (str.Length() > 0) {
for (const nsACString& part : str.Split(',')) {
nsAutoCString locale(part);
if (LocaleService::CanonicalizeLanguageId(locale)) {
if (SanitizeForBCP47(locale, true)) {
if (!aRetVal.Contains(locale)) {
aRetVal.AppendElement(locale);
}
@ -393,7 +421,7 @@ LocaleService::GetDefaultLocale(nsACString& aRetVal) {
locale.Trim(" \t\n\r");
// This should never be empty.
MOZ_ASSERT(!locale.IsEmpty());
if (CanonicalizeLanguageId(locale)) {
if (SanitizeForBCP47(locale, true)) {
mDefaultLocale.Assign(locale);
}
@ -589,7 +617,7 @@ LocaleService::SetRequestedLocales(const nsTArray<nsCString>& aRequested) {
for (auto& req : aRequested) {
nsAutoCString locale(req);
if (!CanonicalizeLanguageId(locale)) {
if (!SanitizeForBCP47(locale, true)) {
NS_ERROR("Invalid language tag provided to SetRequestedLocales!");
return NS_ERROR_INVALID_ARG;
}
@ -639,7 +667,7 @@ LocaleService::SetAvailableLocales(const nsTArray<nsCString>& aAvailable) {
for (auto& avail : aAvailable) {
nsAutoCString locale(avail);
if (!CanonicalizeLanguageId(locale)) {
if (!SanitizeForBCP47(locale, true)) {
NS_ERROR("Invalid language tag provided to SetAvailableLocales!");
return NS_ERROR_INVALID_ARG;
}

Просмотреть файл

@ -104,21 +104,6 @@ class LocaleService final : public mozILocaleService,
return RefPtr<LocaleService>(GetInstance()).forget();
}
/**
* Canonicalize a Unicode Language Identifier string.
*
* The operation is:
* * Normalizing casing (`eN-Us-Windows` -> `en-US-windows`)
* * Switching `_` to `-` (`en_US` -> `en-US`)
* * Rejecting invalid identifiers (`e21-X` sets aLocale to `und` and
* returns false)
* * Normalizing Mozilla's `ja-JP-mac` to `ja-JP-macos`
* * Cutting off POSIX dot postfix (`en-US.utf8` -> `en-US`)
*
* This operation should be used on any external input before
* it gets used in internal operations.
*/
static bool CanonicalizeLanguageId(nsACString& aLocale);
/**
* This method should only be called in the client mode.
*

Просмотреть файл

@ -54,7 +54,19 @@ void OSPreferences::Refresh() {
* It returns true if the canonicalization was successful.
*/
bool OSPreferences::CanonicalizeLanguageTag(nsCString& aLoc) {
return LocaleService::CanonicalizeLanguageId(aLoc);
char langTag[512];
UErrorCode status = U_ZERO_ERROR;
int32_t langTagLen = uloc_toLanguageTag(aLoc.get(), langTag,
sizeof(langTag) - 1, false, &status);
if (U_FAILURE(status)) {
return false;
}
aLoc.Assign(langTag, langTagLen);
return true;
}
/**
@ -279,9 +291,7 @@ OSPreferences::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal) {
return NS_OK;
}
// If we failed to read regional prefs locales,
// use system locales as last fallback.
return GetSystemLocales(aRetVal);
return NS_ERROR_FAILURE;
}
static OSPreferences::DateTimeFormatStyle ToDateTimeFormatStyle(

Просмотреть файл

@ -15,11 +15,6 @@ pub unsafe extern "C" fn unic_langid_new(
let langid = if name.eq_ignore_ascii_case(b"ja-jp-mac") {
"ja-JP-macos".parse()
} else {
// Cut out any `.FOO` like `en-US.POSIX`.
let mut name: &[u8] = name.as_ref();
if let Some(ptr) = name.iter().position(|b| b == &b'.') {
name = &name[..ptr];
}
LanguageIdentifier::from_bytes(name)
};

Просмотреть файл

@ -10,29 +10,6 @@
using namespace mozilla::intl;
TEST(Intl_Locale_LocaleService, CanonicalizeLanguageId)
{
nsCString locale("en-US.POSIX");
ASSERT_TRUE(LocaleService::CanonicalizeLanguageId(locale));
ASSERT_TRUE(locale.EqualsLiteral("en-US"));
locale.AssignLiteral("en-US_POSIX");
ASSERT_TRUE(LocaleService::CanonicalizeLanguageId(locale));
ASSERT_TRUE(locale.EqualsLiteral("en-US-posix"));
locale.AssignLiteral("en-US-POSIX");
ASSERT_TRUE(LocaleService::CanonicalizeLanguageId(locale));
ASSERT_TRUE(locale.EqualsLiteral("en-US-posix"));
locale.AssignLiteral("C");
ASSERT_FALSE(LocaleService::CanonicalizeLanguageId(locale));
ASSERT_TRUE(locale.EqualsLiteral("und"));
locale.AssignLiteral("");
ASSERT_FALSE(LocaleService::CanonicalizeLanguageId(locale));
ASSERT_TRUE(locale.EqualsLiteral("und"));
}
TEST(Intl_Locale_LocaleService, GetAppLocalesAsBCP47)
{
nsTArray<nsCString> appLocales;