diff --git a/intl/locale/OSPreferences.cpp b/intl/locale/OSPreferences.cpp index d3dd30fd47ba..f4311ca3a8fc 100644 --- a/intl/locale/OSPreferences.cpp +++ b/intl/locale/OSPreferences.cpp @@ -38,12 +38,21 @@ OSPreferences::GetInstance() bool OSPreferences::GetSystemLocales(nsTArray& aRetVal) { - bool status = true; - if (mSystemLocales.IsEmpty()) { - status = ReadSystemLocales(mSystemLocales); + if (!mSystemLocales.IsEmpty()) { + aRetVal = mSystemLocales; + return true; } - aRetVal = mSystemLocales; - return status; + + if (ReadSystemLocales(aRetVal)) { + mSystemLocales = aRetVal; + return true; + } + + // If we failed to get the system locale, we still need + // to return something because there are tests out there that + // depend on system locale to be set. + aRetVal.AppendElement(NS_LITERAL_CSTRING("en-US")); + return false; } void @@ -294,15 +303,22 @@ OSPreferences::GetDateTimeConnectorPattern(const nsACString& aLocale, NS_IMETHODIMP OSPreferences::GetSystemLocales(uint32_t* aCount, char*** aOutArray) { - if (mSystemLocales.IsEmpty()) { - ReadSystemLocales(mSystemLocales); - } + AutoTArray tempLocales; + nsTArray* systemLocalesPtr; - *aCount = mSystemLocales.Length(); + if (!mSystemLocales.IsEmpty()) { + // use cached value + systemLocalesPtr = &mSystemLocales; + } else { + // get a (perhaps temporary/fallback/hack) value + GetSystemLocales(tempLocales); + systemLocalesPtr = &tempLocales; + } + *aCount = systemLocalesPtr->Length(); *aOutArray = static_cast(moz_xmalloc(*aCount * sizeof(char*))); for (uint32_t i = 0; i < *aCount; i++) { - (*aOutArray)[i] = moz_xstrdup(mSystemLocales[i].get()); + (*aOutArray)[i] = moz_xstrdup((*systemLocalesPtr)[i].get()); } return NS_OK; @@ -311,12 +327,14 @@ OSPreferences::GetSystemLocales(uint32_t* aCount, char*** aOutArray) NS_IMETHODIMP OSPreferences::GetSystemLocale(nsACString& aRetVal) { - if (mSystemLocales.IsEmpty()) { - ReadSystemLocales(mSystemLocales); - } - if (!mSystemLocales.IsEmpty()) { aRetVal = mSystemLocales[0]; + } else { + AutoTArray locales; + GetSystemLocales(locales); + if (!locales.IsEmpty()) { + aRetVal = locales[0]; + } } return NS_OK; } diff --git a/intl/locale/android/OSPreferences_android.cpp b/intl/locale/android/OSPreferences_android.cpp index 86e3d06648e3..3221646f09f4 100644 --- a/intl/locale/android/OSPreferences_android.cpp +++ b/intl/locale/android/OSPreferences_android.cpp @@ -15,13 +15,16 @@ OSPreferences::ReadSystemLocales(nsTArray& aLocaleList) //XXX: This is a quite sizable hack to work around the fact that we cannot // retrieve OS locale in C++ without reaching out to JNI. // Once we fix this (bug 1337078), this hack should not be necessary. - nsAutoCString locale; - if (!NS_SUCCEEDED(Preferences::GetCString("intl.locale.os", &locale)) || - locale.IsEmpty()) { - locale.AssignLiteral("en-US"); + // + //XXX: Notice, this value may be empty on an early read. In that case + // we won't add anything to the return list so that it doesn't get + // cached in mSystemLocales. + nsAdoptingCString locale = Preferences::GetCString("intl.locale.os"); + if (!locale.IsEmpty()) { aLocaleList.AppendElement(locale); + return true; } - return true; + return false; } bool diff --git a/intl/locale/tests/unit/test_localeService.js b/intl/locale/tests/unit/test_localeService.js index 6f69140d1537..9431ba14963b 100644 --- a/intl/locale/tests/unit/test_localeService.js +++ b/intl/locale/tests/unit/test_localeService.js @@ -45,6 +45,7 @@ add_test(function test_getAppLocalesAsLangTags() { const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; const PREF_SELECTED_LOCALE = "general.useragent.locale"; +const PREF_OS_LOCALE = "intl.locale.os"; const REQ_LOC_CHANGE_EVENT = "intl:requested-locales-changed"; add_test(function test_getRequestedLocales() { @@ -67,6 +68,7 @@ add_test(function test_getRequestedLocales_matchOS() { Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "ar-IR"); + Services.prefs.setCharPref(PREF_OS_LOCALE, "en-US"); const observer = { observe: function (aSubject, aTopic, aData) { @@ -138,6 +140,7 @@ add_test(function test_isAppLocaleRTL() { }); do_register_cleanup(() => { - Services.prefs.clearUserPref(PREF_SELECTED_LOCALE); - Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE); + Services.prefs.clearUserPref(PREF_SELECTED_LOCALE); + Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE); + Services.prefs.clearUserPref(PREF_OS_LOCALE, "en-US"); });