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 <xsl:sort>.

<xsl:sort order="descending"
          select="@displayname[$sortColumnName='displayname'] |
                  @name[$sortColumnName='name'] |
                  exslt:node-set($FriendlyTypeNames)/types/type[@xmlName=current()/@datatype and $sortColumnName='datatype']"
          lang="$languageName"/>

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
This commit is contained in:
Makoto Kato 2017-08-24 23:13:42 +09:00
Родитель e9f7da41fa
Коммит dd679562b1
3 изменённых файлов: 67 добавлений и 1 удалений

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCollation.h" #include "nsCollation.h"
#include "mozilla/intl/LocaleService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsString.h" #include "nsString.h"
@ -117,7 +118,20 @@ nsCollation::Initialize(const nsACString& locale)
{ {
NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED); 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; mInit = true;
return NS_OK; return NS_OK;

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

@ -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<nsICollationFactory> colFactory =
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
ASSERT_TRUE(colFactory);
// Don't throw error even if locale name is invalid
nsCOMPtr<nsICollation> 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);
}

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

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'TestCollation.cpp',
'TestLocaleService.cpp', 'TestLocaleService.cpp',
'TestLocaleServiceNegotiate.cpp', 'TestLocaleServiceNegotiate.cpp',
] ]