From dd679562b19555b0535e8f952a3789046b023bc3 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Thu, 24 Aug 2017 23:13:42 +0900 Subject: [PATCH] Bug 1391628 - Use fallback locale on nsICollation if locale is invalid. r=emk Original issue is that Microsoft Dynamics CRM uses invalid lang attribute in . Our XSLT implementation detects "$languageName" as locale name, then use it to nsICollation. Until Gecko 54 for Windows, even if using invalid locale name for nsICollation, it uses platform locale as fallback. But from 55, we use same implementation as macOS's to use ICU. So this issue occurs. ICU implementation doesn't use fallback locale if it is invalid. We should use fallback locale if locale is invalid. Most code for fallback locale such as FallbackEncoding uses application locale, so use it. MozReview-Commit-ID: EKYkZG7Hnz0 --HG-- extra : rebase_source : fec89c67317d7df041f3b237122fb7e20e32fe1b --- intl/locale/nsCollation.cpp | 16 ++++++- intl/locale/tests/gtest/TestCollation.cpp | 51 +++++++++++++++++++++++ intl/locale/tests/gtest/moz.build | 1 + 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 intl/locale/tests/gtest/TestCollation.cpp diff --git a/intl/locale/nsCollation.cpp b/intl/locale/nsCollation.cpp index 44409cd6ba18..5bc98807457b 100644 --- a/intl/locale/nsCollation.cpp +++ b/intl/locale/nsCollation.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCollation.h" +#include "mozilla/intl/LocaleService.h" #include "nsIServiceManager.h" #include "nsString.h" @@ -117,7 +118,20 @@ nsCollation::Initialize(const nsACString& locale) { NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED); - mLocale = locale; + // Check whether locale parameter is valid. If no, use application locale + UErrorCode status = U_ZERO_ERROR; + UCollator* collator = ucol_open(PromiseFlatCString(locale).get(), &status); + if (U_SUCCESS(status)) { + mLocale = locale; + } else { + status = U_ZERO_ERROR; + mozilla::LocaleService::GetInstance()->GetAppLocaleAsLangTag(mLocale); + collator = ucol_open(mLocale.get(), &status); + if (NS_WARN_IF(U_FAILURE(status))) { + return NS_ERROR_UNEXPECTED; + } + } + ucol_close(collator); mInit = true; return NS_OK; diff --git a/intl/locale/tests/gtest/TestCollation.cpp b/intl/locale/tests/gtest/TestCollation.cpp new file mode 100644 index 000000000000..4b1fa21e44cc --- /dev/null +++ b/intl/locale/tests/gtest/TestCollation.cpp @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "gtest/gtest.h" +#include "mozilla/Services.h" +#include "nsCollationCID.h" +#include "nsComponentManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsICollation.h" +#include "nsString.h" + +TEST(Collation, AllocateRowSortKey) { + nsCOMPtr colFactory = + do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID); + ASSERT_TRUE(colFactory); + + // Don't throw error even if locale name is invalid + nsCOMPtr collator; + nsresult rv = + colFactory->CreateCollationForLocale(NS_LITERAL_CSTRING("$languageName"), + getter_AddRefs(collator)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + uint8_t* sortKey1 = nullptr; + uint32_t sortKeyLen1 = 0; + // Don't throw error even if locale name is invalid + rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault, + NS_LITERAL_STRING("ABC"), + &sortKey1, &sortKeyLen1); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + uint8_t* sortKey2 = nullptr; + uint32_t sortKeyLen2 = 0; + // Don't throw error even if locale name is invalid + rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault, + NS_LITERAL_STRING("DEF"), + &sortKey2, &sortKeyLen2); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + int32_t result; + rv = collator->CompareRawSortKey(sortKey1, sortKeyLen1, + sortKey2, sortKeyLen2, &result); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + ASSERT_TRUE(result < 0); + + free(sortKey1); + free(sortKey2); +} diff --git a/intl/locale/tests/gtest/moz.build b/intl/locale/tests/gtest/moz.build index 9943ec9ba1d0..13399751dba2 100644 --- a/intl/locale/tests/gtest/moz.build +++ b/intl/locale/tests/gtest/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ + 'TestCollation.cpp', 'TestLocaleService.cpp', 'TestLocaleServiceNegotiate.cpp', ]