Bug 943287 - Part 2. Use ICU version of nsICollation on all platform. r=hsivonen
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Thu, 23 Mar 2017 13:42:49 +0900
changeset 384675 3ccff122964891dcffa75d6f957b9353aa60932e
parent 384674 5148d608e50fddb6ac27cbaa57482def17a1d40c
child 384676 bc2abb9359fc5124c3ec6b0dae2f89cc1133a310
push idunknown
push userunknown
push dateunknown
reviewershsivonen
bugs943287
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 943287 - Part 2. Use ICU version of nsICollation on all platform. r=hsivonen nsICollation for macOS version uses ICU, so we should use it on all platform since nightly and aurora can use ICU on all platform. MozReview-Commit-ID: 4nTzDCjOQXJ
intl/build/nsI18nModule.cpp
intl/locale/mac/moz.build
intl/locale/mac/nsCollationMacUC.cpp
intl/locale/mac/nsCollationMacUC.h
intl/locale/moz.build
intl/locale/nsCollation.cpp
intl/locale/nsCollation.h
intl/locale/nsCollationFactory.cpp
intl/locale/nsCollationFactory.h
intl/locale/nsLocaleConstructors.h
intl/locale/tests/unit/test_collation.js
intl/locale/tests/unit/test_collation_mac_icu.js
intl/locale/tests/unit/xpcshell.ini
intl/locale/unix/moz.build
intl/locale/unix/nsCollationUnix.h
intl/locale/windows/moz.build
intl/locale/windows/nsCollationWin.cpp
intl/locale/windows/nsCollationWin.h
--- a/intl/build/nsI18nModule.cpp
+++ b/intl/build/nsI18nModule.cpp
@@ -56,25 +56,17 @@ NS_DEFINE_NAMED_CID(NS_SAVEASCHARSET_CID
 NS_DEFINE_NAMED_CID(NS_UNICODE_NORMALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID);
 NS_DEFINE_NAMED_CID(NS_LOCALESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTABLEDATEFORMAT_CID);
 NS_DEFINE_NAMED_CID(NS_LANGUAGEATOMSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_PLATFORMCHARSET_CID);
-#ifdef XP_WIN
 NS_DEFINE_NAMED_CID(NS_COLLATION_CID);
-#endif
-#ifdef USE_UNIX_LOCALE
-NS_DEFINE_NAMED_CID(NS_COLLATION_CID);
-#endif
-#ifdef USE_MAC_LOCALE
-NS_DEFINE_NAMED_CID(NS_COLLATION_CID);
-#endif
 
 static const mozilla::Module::CIDEntry kIntlCIDs[] = {
     { &kMOZ_LOCALESERVICE_CID, false, nullptr, mozilla::intl::LocaleServiceConstructor },
     { &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor },
     { &kNS_LBRK_CID, false, nullptr, nsJISx4051LineBreakerConstructor },
     { &kNS_WBRK_CID, false, nullptr, nsSampleWordBreakerConstructor },
     { &kNS_SEMANTICUNITSCANNER_CID, false, nullptr, nsSemanticUnitScannerConstructor },
     { &kNS_UNICHARUTIL_CID, false, nullptr, nsCaseConversionImp2Constructor },
@@ -84,25 +76,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_UNICODE_NORMALIZER_CID, false, nullptr, nsUnicodeNormalizerConstructor },
     { &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor },
     { &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor },
     { &kNS_LOCALESERVICE_CID, false, nullptr, CreateLocaleService },
     { &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor },
     { &kNS_SCRIPTABLEDATEFORMAT_CID, false, nullptr, NS_NewScriptableDateFormat },
     { &kNS_LANGUAGEATOMSERVICE_CID, false, nullptr, nsLanguageAtomServiceConstructor },
     { &kNS_PLATFORMCHARSET_CID, false, nullptr, nsPlatformCharsetConstructor },
-#ifdef XP_WIN
-    { &kNS_COLLATION_CID, false, nullptr, nsCollationWinConstructor },
-#endif
-#ifdef USE_UNIX_LOCALE
-    { &kNS_COLLATION_CID, false, nullptr, nsCollationUnixConstructor },
-#endif
-#ifdef USE_MAC_LOCALE
-    { &kNS_COLLATION_CID, false, nullptr, nsCollationMacUCConstructor },
-#endif
+    { &kNS_COLLATION_CID, false, nullptr, nsCollationConstructor },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
     { MOZ_LOCALESERVICE_CONTRACTID, &kMOZ_LOCALESERVICE_CID },
     { MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID },
     { NS_LBRK_CONTRACTID, &kNS_LBRK_CID },
     { NS_WBRK_CONTRACTID, &kNS_WBRK_CID },
@@ -114,25 +98,17 @@ static const mozilla::Module::ContractID
     { NS_UNICODE_NORMALIZER_CONTRACTID, &kNS_UNICODE_NORMALIZER_CID },
     { NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID },
     { NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID },
     { NS_LOCALESERVICE_CONTRACTID, &kNS_LOCALESERVICE_CID },
     { NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID },
     { NS_SCRIPTABLEDATEFORMAT_CONTRACTID, &kNS_SCRIPTABLEDATEFORMAT_CID },
     { NS_LANGUAGEATOMSERVICE_CONTRACTID, &kNS_LANGUAGEATOMSERVICE_CID },
     { NS_PLATFORMCHARSET_CONTRACTID, &kNS_PLATFORMCHARSET_CID },
-#ifdef XP_WIN
     { NS_COLLATION_CONTRACTID, &kNS_COLLATION_CID },
-#endif
-#ifdef USE_UNIX_LOCALE
-    { NS_COLLATION_CONTRACTID, &kNS_COLLATION_CID },
-#endif
-#ifdef USE_MAC_LOCALE
-    { NS_COLLATION_CONTRACTID, &kNS_COLLATION_CID },
-#endif
     { nullptr }
 };
 
 static const mozilla::Module kIntlModule = {
     mozilla::Module::kVersion,
     kIntlCIDs,
     kIntlContracts,
     nullptr,
--- a/intl/locale/mac/moz.build
+++ b/intl/locale/mac/moz.build
@@ -1,16 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 UNIFIED_SOURCES += [
-    'nsCollationMacUC.cpp',
     'nsMacCharset.cpp',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     UNIFIED_SOURCES += ['OSPreferences_mac.cpp']
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
deleted file mode 100644
--- a/intl/locale/mac/nsCollationMacUC.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* -*- 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 "nsCollationMacUC.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
-#include "nsIServiceManager.h"
-#include "prmem.h"
-#include "nsString.h"
-
-NS_IMPL_ISUPPORTS(nsCollationMacUC, nsICollation)
-
-nsCollationMacUC::nsCollationMacUC()
-  : mInit(false)
-  , mHasCollator(false)
-  , mLastStrength(-1)
-  , mCollatorICU(nullptr)
-{ }
-
-nsCollationMacUC::~nsCollationMacUC()
-{
-#ifdef DEBUG
-  nsresult res =
-#endif
-    CleanUpCollator();
-  NS_ASSERTION(NS_SUCCEEDED(res), "CleanUpCollator failed");
-}
-
-nsresult nsCollationMacUC::ConvertStrength(const int32_t aNSStrength,
-                                           UCollationStrength* aICUStrength,
-                                           UColAttributeValue* aCaseLevelOut)
-{
-  NS_ENSURE_ARG_POINTER(aICUStrength);
-  NS_ENSURE_TRUE((aNSStrength < 4), NS_ERROR_FAILURE);
-
-  UCollationStrength strength = UCOL_DEFAULT;
-  UColAttributeValue caseLevel = UCOL_OFF;
-  switch (aNSStrength) {
-    case kCollationCaseInSensitive:
-      strength = UCOL_PRIMARY;
-      break;
-    case kCollationCaseInsensitiveAscii:
-      strength = UCOL_SECONDARY;
-      break;
-    case kCollationAccentInsenstive:
-      caseLevel = UCOL_ON;
-      strength = UCOL_PRIMARY;
-      break;
-    case kCollationCaseSensitive:
-      strength = UCOL_TERTIARY;
-      break;
-    default:
-      NS_WARNING("Bad aNSStrength passed to ConvertStrength.");
-      return NS_ERROR_FAILURE;
-  }
-
-  *aICUStrength = strength;
-  *aCaseLevelOut = caseLevel;
-
-  return NS_OK;
-}
-
-nsresult nsCollationMacUC::EnsureCollator(const int32_t newStrength)
-{
-  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
-  if (mHasCollator && (mLastStrength == newStrength))
-    return NS_OK;
-
-  nsresult res;
-  res = CleanUpCollator();
-  NS_ENSURE_SUCCESS(res, res);
-
-  UErrorCode status;
-  status = U_ZERO_ERROR;
-  mCollatorICU = ucol_open(mLocale.get(), &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-
-  UCollationStrength strength;
-  UColAttributeValue caseLevel;
-  res = ConvertStrength(newStrength, &strength, &caseLevel);
-  NS_ENSURE_SUCCESS(res, res);
-
-  status = U_ZERO_ERROR;
-  ucol_setAttribute(mCollatorICU, UCOL_STRENGTH, strength, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-  ucol_setAttribute(mCollatorICU, UCOL_CASE_LEVEL, caseLevel, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-  ucol_setAttribute(mCollatorICU, UCOL_ALTERNATE_HANDLING, UCOL_DEFAULT, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-  ucol_setAttribute(mCollatorICU, UCOL_NUMERIC_COLLATION, UCOL_OFF, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-  ucol_setAttribute(mCollatorICU, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-  ucol_setAttribute(mCollatorICU, UCOL_CASE_FIRST, UCOL_DEFAULT, &status);
-  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
-
-  mHasCollator = true;
-
-  mLastStrength = newStrength;
-  return NS_OK;
-}
-
-nsresult nsCollationMacUC::CleanUpCollator(void)
-{
-  if (mHasCollator) {
-    ucol_close(mCollatorICU);
-    mHasCollator = false;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsCollationMacUC::Initialize(const nsACString& locale)
-{
-  NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
-  nsCOMPtr<nsILocale> appLocale;
-
-  mLocale = locale;
-
-  mInit = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
-                                                   uint8_t** key, uint32_t* outLen)
-{
-  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
-  NS_ENSURE_ARG_POINTER(key);
-  NS_ENSURE_ARG_POINTER(outLen);
-
-  nsresult res = EnsureCollator(strength);
-  NS_ENSURE_SUCCESS(res, res);
-
-  uint32_t stringInLen = stringIn.Length();
-
-  const UChar* str = (const UChar*)stringIn.BeginReading();
-
-  int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
-  NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
-
-  // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
-  uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1);
-  if (!newKey) {
-      return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1);
-  NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
-
-  *key = newKey;
-  *outLen = keyLength;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1,
-                                              const nsAString& string2, int32_t* result)
-{
-  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
-  NS_ENSURE_ARG_POINTER(result);
-  *result = 0;
-
-  nsresult rv = EnsureCollator(strength);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  UCollationResult uresult;
-  uresult = ucol_strcoll(mCollatorICU,
-                         (const UChar*)string1.BeginReading(),
-                         string1.Length(),
-                         (const UChar*)string2.BeginReading(),
-                         string2.Length());
-  int32_t res;
-  switch (uresult) {
-    case UCOL_LESS:
-      res = -1;
-      break;
-    case UCOL_EQUAL:
-      res = 0;
-      break;
-    case UCOL_GREATER:
-      res = 1;
-      break;
-    default:
-      MOZ_CRASH("ucol_strcoll returned bad UCollationResult");
-  }
-  *result = res;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsCollationMacUC::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
-                                                  const uint8_t* key2, uint32_t len2,
-                                                  int32_t* result)
-{
-  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
-  NS_ENSURE_ARG_POINTER(key1);
-  NS_ENSURE_ARG_POINTER(key2);
-  NS_ENSURE_ARG_POINTER(result);
-  *result = 0;
-
-  int32_t tmpResult = strcmp((const char*)key1, (const char*)key2);
-  int32_t res;
-  if (tmpResult < 0) {
-      res = -1;
-  } else if (tmpResult > 0) {
-      res = 1;
-  } else {
-      res = 0;
-  }
-  *result = res;
-  return NS_OK;
-}
deleted file mode 100644
--- a/intl/locale/mac/nsCollationMacUC.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- 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/. */
-
-#ifndef nsCollationMacUC_h_
-#define nsCollationMacUC_h_
-
-#include "mozilla/Attributes.h"
-#include "nsICollation.h"
-#include "nsCollationFactory.h"
-#include "nsString.h"
-
-#include "unicode/ucol.h"
-
-class nsCollationMacUC final : public nsICollation {
-
-public:
-  nsCollationMacUC();
-
-  // nsISupports interface
-  NS_DECL_ISUPPORTS
-
-  // nsICollation interface
-  NS_DECL_NSICOLLATION
-
-protected:
-  ~nsCollationMacUC();
-
-  nsresult ConvertStrength(const int32_t aStrength,
-                           UCollationStrength* aStrengthOut,
-                           UColAttributeValue* aCaseLevelOut);
-  nsresult EnsureCollator(const int32_t newStrength);
-  nsresult CleanUpCollator(void);
-
-private:
-  bool mInit;
-  bool mHasCollator;
-  nsCString mLocale;
-  int32_t mLastStrength;
-  UCollator* mCollatorICU;
-};
-
-#endif  /* nsCollationMacUC_h_ */
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -28,31 +28,31 @@ XPIDL_SOURCES += [
     'nsIScriptableDateFormat.idl',
 ]
 
 XPIDL_MODULE = 'locale'
 
 EXPORTS += [
     'DateTimeFormat.h',
     'nsCollationCID.h',
-    'nsCollationFactory.h',
     'nsILanguageAtomService.h',
     'nsIPlatformCharset.h',
     'nsPosixLocale.h',
     'nsUConvPropertySearch.h',
     'nsWin32Locale.h',
 ]
 
 EXPORTS.mozilla.intl += [
     'LocaleService.h',
     'OSPreferences.h',
 ]
 
 UNIFIED_SOURCES += [
     'LocaleService.cpp',
+    'nsCollation.cpp',
     'nsCollationFactory.cpp',
     'nsLanguageAtomService.cpp',
     'nsLocale.cpp',
     'nsLocaleService.cpp',
     'nsScriptableDateFormat.cpp',
     'nsUConvPropertySearch.cpp',
     'OSPreferences.cpp',
 ]
new file mode 100644
--- /dev/null
+++ b/intl/locale/nsCollation.cpp
@@ -0,0 +1,217 @@
+/* -*- 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 "nsCollation.h"
+#include "nsIServiceManager.h"
+#include "prmem.h"
+#include "nsString.h"
+
+NS_IMPL_ISUPPORTS(nsCollation, nsICollation)
+
+nsCollation::nsCollation()
+  : mInit(false)
+  , mHasCollator(false)
+  , mLastStrength(-1)
+  , mCollatorICU(nullptr)
+{ }
+
+nsCollation::~nsCollation()
+{
+#ifdef DEBUG
+  nsresult res =
+#endif
+    CleanUpCollator();
+  NS_ASSERTION(NS_SUCCEEDED(res), "CleanUpCollator failed");
+}
+
+nsresult
+nsCollation::ConvertStrength(const int32_t aNSStrength,
+                             UCollationStrength* aICUStrength,
+                             UColAttributeValue* aCaseLevelOut)
+{
+  NS_ENSURE_ARG_POINTER(aICUStrength);
+  NS_ENSURE_TRUE((aNSStrength < 4), NS_ERROR_FAILURE);
+
+  UCollationStrength strength = UCOL_DEFAULT;
+  UColAttributeValue caseLevel = UCOL_OFF;
+  switch (aNSStrength) {
+    case kCollationCaseInSensitive:
+      strength = UCOL_PRIMARY;
+      break;
+    case kCollationCaseInsensitiveAscii:
+      strength = UCOL_SECONDARY;
+      break;
+    case kCollationAccentInsenstive:
+      caseLevel = UCOL_ON;
+      strength = UCOL_PRIMARY;
+      break;
+    case kCollationCaseSensitive:
+      strength = UCOL_TERTIARY;
+      break;
+    default:
+      NS_WARNING("Bad aNSStrength passed to ConvertStrength.");
+      return NS_ERROR_FAILURE;
+  }
+
+  *aICUStrength = strength;
+  *aCaseLevelOut = caseLevel;
+
+  return NS_OK;
+}
+
+nsresult
+nsCollation::EnsureCollator(const int32_t newStrength)
+{
+  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
+  if (mHasCollator && (mLastStrength == newStrength))
+    return NS_OK;
+
+  nsresult res;
+  res = CleanUpCollator();
+  NS_ENSURE_SUCCESS(res, res);
+
+  UErrorCode status;
+  status = U_ZERO_ERROR;
+  mCollatorICU = ucol_open(mLocale.get(), &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+
+  UCollationStrength strength;
+  UColAttributeValue caseLevel;
+  res = ConvertStrength(newStrength, &strength, &caseLevel);
+  NS_ENSURE_SUCCESS(res, res);
+
+  status = U_ZERO_ERROR;
+  ucol_setAttribute(mCollatorICU, UCOL_STRENGTH, strength, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+  ucol_setAttribute(mCollatorICU, UCOL_CASE_LEVEL, caseLevel, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+  ucol_setAttribute(mCollatorICU, UCOL_ALTERNATE_HANDLING, UCOL_DEFAULT, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+  ucol_setAttribute(mCollatorICU, UCOL_NUMERIC_COLLATION, UCOL_OFF, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+  ucol_setAttribute(mCollatorICU, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+  ucol_setAttribute(mCollatorICU, UCOL_CASE_FIRST, UCOL_DEFAULT, &status);
+  NS_ENSURE_TRUE(U_SUCCESS(status), NS_ERROR_FAILURE);
+
+  mHasCollator = true;
+
+  mLastStrength = newStrength;
+  return NS_OK;
+}
+
+nsresult
+nsCollation::CleanUpCollator(void)
+{
+  if (mHasCollator) {
+    ucol_close(mCollatorICU);
+    mHasCollator = false;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCollation::Initialize(const nsACString& locale)
+{
+  NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
+
+  mLocale = locale;
+
+  mInit = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCollation::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
+                                uint8_t** key, uint32_t* outLen)
+{
+  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_ARG_POINTER(key);
+  NS_ENSURE_ARG_POINTER(outLen);
+
+  nsresult res = EnsureCollator(strength);
+  NS_ENSURE_SUCCESS(res, res);
+
+  uint32_t stringInLen = stringIn.Length();
+
+  const UChar* str = (const UChar*)stringIn.BeginReading();
+
+  int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
+  NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
+
+  // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
+  uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1);
+  if (!newKey) {
+      return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1);
+  NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);
+
+  *key = newKey;
+  *outLen = keyLength;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCollation::CompareString(int32_t strength, const nsAString& string1,
+                           const nsAString& string2, int32_t* result)
+{
+  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_ARG_POINTER(result);
+  *result = 0;
+
+  nsresult rv = EnsureCollator(strength);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  UCollationResult uresult;
+  uresult = ucol_strcoll(mCollatorICU,
+                         (const UChar*)string1.BeginReading(),
+                         string1.Length(),
+                         (const UChar*)string2.BeginReading(),
+                         string2.Length());
+  int32_t res;
+  switch (uresult) {
+    case UCOL_LESS:
+      res = -1;
+      break;
+    case UCOL_EQUAL:
+      res = 0;
+      break;
+    case UCOL_GREATER:
+      res = 1;
+      break;
+    default:
+      MOZ_CRASH("ucol_strcoll returned bad UCollationResult");
+  }
+  *result = res;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCollation::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
+                               const uint8_t* key2, uint32_t len2,
+                               int32_t* result)
+{
+  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_ARG_POINTER(key1);
+  NS_ENSURE_ARG_POINTER(key2);
+  NS_ENSURE_ARG_POINTER(result);
+  *result = 0;
+
+  int32_t tmpResult = strcmp((const char*)key1, (const char*)key2);
+  int32_t res;
+  if (tmpResult < 0) {
+      res = -1;
+  } else if (tmpResult > 0) {
+      res = 1;
+  } else {
+      res = 0;
+  }
+  *result = res;
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/intl/locale/nsCollation.h
@@ -0,0 +1,44 @@
+/* -*- 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/. */
+
+#ifndef nsCollation_h_
+#define nsCollation_h_
+
+#include "mozilla/Attributes.h"
+#include "nsICollation.h"
+#include "nsCollationFactory.h"
+#include "nsString.h"
+
+#include "unicode/ucol.h"
+
+class nsCollation final : public nsICollation {
+
+public:
+  nsCollation();
+
+  // nsISupports interface
+  NS_DECL_ISUPPORTS
+
+  // nsICollation interface
+  NS_DECL_NSICOLLATION
+
+protected:
+  ~nsCollation();
+
+  nsresult ConvertStrength(const int32_t aStrength,
+                           UCollationStrength* aStrengthOut,
+                           UColAttributeValue* aCaseLevelOut);
+  nsresult EnsureCollator(const int32_t newStrength);
+  nsresult CleanUpCollator(void);
+
+private:
+  bool mInit;
+  bool mHasCollator;
+  nsCString mLocale;
+  int32_t mLastStrength;
+  UCollator* mCollatorICU;
+};
+
+#endif  /* nsCollation_h_ */
--- a/intl/locale/nsCollationFactory.cpp
+++ b/intl/locale/nsCollationFactory.cpp
@@ -1,24 +1,18 @@
 /* -*- 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 "nsCollationFactory.h"
 #include "nsCollationCID.h"
-#include "nsUnicharUtils.h"
-#include "prmem.h"
-#include "nsIUnicodeEncoder.h"
 #include "nsServiceManagerUtils.h"
-#include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/intl/LocaleService.h"
 
-using mozilla::dom::EncodingUtils;
-
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_DEFINE_CID(kCollationCID, NS_COLLATION_CID);
 
 NS_IMPL_ISUPPORTS(nsCollationFactory, nsICollationFactory)
 
 nsresult nsCollationFactory::CreateCollation(nsICollation** instancePtr)
 {
@@ -42,104 +36,8 @@ nsCollationFactory::CreateCollationForLo
   }
 
   inst->Initialize(locale);
 
   *instancePtr = inst;
 
   return res;
 }
-
-////////////////////////////////////////////////////////////////////////////////
-
-nsCollation::nsCollation()
-{
-  MOZ_COUNT_CTOR(nsCollation);
-}
-
-nsCollation::~nsCollation()
-{
-  MOZ_COUNT_DTOR(nsCollation);
-}
-
-nsresult nsCollation::NormalizeString(const nsAString& stringIn, nsAString& stringOut)
-{
-  int32_t aLength = stringIn.Length();
-
-  if (aLength <= 64) {
-    char16_t conversionBuffer[64];
-    ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
-    stringOut.Assign(conversionBuffer, aLength);
-  }
-  else {
-    char16_t* conversionBuffer;
-    conversionBuffer = new char16_t[aLength];
-    if (!conversionBuffer) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    ToLowerCase(PromiseFlatString(stringIn).get(), conversionBuffer, aLength);
-    stringOut.Assign(conversionBuffer, aLength);
-    delete [] conversionBuffer;
-  }
-  return NS_OK;
-}
-
-nsresult nsCollation::SetCharset(const char* aCharset)
-{
-  NS_ENSURE_ARG_POINTER(aCharset);
-
-  nsDependentCString label(aCharset);
-  nsAutoCString encoding;
-  if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
-      return NS_ERROR_UCONV_NOCONV;
-  }
-  mEncoder = EncodingUtils::EncoderForEncoding(encoding);
-  return NS_OK;
-}
-
-nsresult nsCollation::UnicodeToChar(const nsAString& aSrc, char** dst)
-{
-  NS_ENSURE_ARG_POINTER(dst);
-
-  nsresult res = NS_OK;
-  if (!mEncoder)
-    res = SetCharset("ISO-8859-1");
-
-  if (NS_SUCCEEDED(res)) {
-    const nsPromiseFlatString& src = PromiseFlatString(aSrc);
-    const char16_t *unichars = src.get();
-    int32_t unicharLength = src.Length();
-    int32_t dstLength;
-    res = mEncoder->GetMaxLength(unichars, unicharLength, &dstLength);
-    if (NS_SUCCEEDED(res)) {
-      int32_t bufLength = dstLength + 1 + 32; // extra 32 bytes for Finish() call
-      *dst = (char *) PR_Malloc(bufLength);
-      if (*dst) {
-        **dst = '\0';
-        res = mEncoder->Convert(unichars, &unicharLength, *dst, &dstLength);
-
-        if (NS_SUCCEEDED(res) || (NS_ERROR_UENC_NOMAPPING == res)) {
-          // Finishes the conversion. The converter has the possibility to write some 
-          // extra data and flush its final state.
-          int32_t finishLength = bufLength - dstLength; // remaining unused buffer length
-          if (finishLength > 0) {
-            res = mEncoder->Finish((*dst + dstLength), &finishLength);
-            if (NS_SUCCEEDED(res)) {
-              (*dst)[dstLength + finishLength] = '\0';
-            }
-          }
-        }
-        if (NS_FAILED(res)) {
-          PR_Free(*dst);
-          *dst = nullptr;
-        }
-      }
-      else {
-        res = NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-  }
-
-  return res;
-}
-
-
-
--- a/intl/locale/nsCollationFactory.h
+++ b/intl/locale/nsCollationFactory.h
@@ -7,44 +7,22 @@
 #ifndef nsCollationFactory_h__
 #define nsCollationFactory_h__
 
 
 #include "nsICollation.h"
 #include "nsCOMPtr.h"
 #include "mozilla/Attributes.h"
 
-class nsIUnicodeEncoder;
-
 // Create a collation interface for the current app's locale.
 // 
 class nsCollationFactory final : public nsICollationFactory {
 
   ~nsCollationFactory() {}
 
 public: 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOLLATIONFACTORY
 
   nsCollationFactory() {}
 };
 
-
-struct nsCollation {
-
-public: 
-
-  nsCollation();
-  
-  ~nsCollation();
-
-  // normalize string before collation key generation
-  nsresult NormalizeString(const nsAString& stringIn, nsAString& stringOut);
-
-  // charset conversion util, C string buffer is allocate by PR_Malloc, caller should call PR_Free
-  nsresult SetCharset(const char* aCharset);
-  nsresult UnicodeToChar(const nsAString& aSrc, char** dst);
-
-protected:
-  nsCOMPtr <nsIUnicodeEncoder>            mEncoder;
-};
-
 #endif  /* nsCollationFactory_h__ */
--- a/intl/locale/nsLocaleConstructors.h
+++ b/intl/locale/nsLocaleConstructors.h
@@ -1,46 +1,27 @@
 /* -*- 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/. */
 
 #ifndef nsLocaleConstructors_h__
 #define nsLocaleConstructors_h__
 
+#include "nsCollation.h"
 #include "nsCollationCID.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsILocaleService.h"
 #include "nsIScriptableDateFormat.h"
 #include "nsIServiceManager.h"
 #include "nsLanguageAtomService.h"
 #include "nsPlatformCharset.h"
 #include "LocaleService.h"
 #include "OSPreferences.h"
 
-#if defined(XP_MACOSX)
-#define USE_MAC_LOCALE
-#endif
-
-#if defined(XP_UNIX) && !defined(XP_MACOSX)
-#define USE_UNIX_LOCALE
-#endif
-
-#ifdef XP_WIN
-#include "windows/nsCollationWin.h"
-#endif
-
-#ifdef USE_MAC_LOCALE
-#include "mac/nsCollationMacUC.h"
-#endif
-
-#ifdef USE_UNIX_LOCALE
-#include "unix/nsCollationUnix.h"
-#endif
-
 #define NSLOCALE_MAKE_CTOR(ctor_, iface_, func_)          \
 static nsresult                                           \
 ctor_(nsISupports* aOuter, REFNSIID aIID, void** aResult) \
 {                                                         \
   *aResult = nullptr;                                      \
   if (aOuter)                                             \
     return NS_ERROR_NO_AGGREGATION;                       \
   iface_* inst;                                           \
@@ -49,35 +30,24 @@ ctor_(nsISupports* aOuter, REFNSIID aIID
     rv = inst->QueryInterface(aIID, aResult);             \
     NS_RELEASE(inst);                                     \
   }                                                       \
   return rv;                                              \
 }
 
 
 NSLOCALE_MAKE_CTOR(CreateLocaleService, nsILocaleService, NS_NewLocaleService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollation)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationFactory)
 //NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableDateTimeFormat)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLanguageAtomService)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPlatformCharset, Init)
 
 namespace mozilla {
 namespace intl {
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(LocaleService,
                                          LocaleService::GetInstanceAddRefed)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(OSPreferences,
                                          OSPreferences::GetInstanceAddRefed)
 }
 }
 
-#ifdef XP_WIN
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationWin)
 #endif
-
-#ifdef USE_UNIX_LOCALE
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationUnix)
-#endif  
-
-#ifdef USE_MAC_LOCALE
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationMacUC)
-#endif  
-
-#endif
rename from intl/locale/tests/unit/test_collation_mac_icu.js
rename to intl/locale/tests/unit/test_collation.js
--- a/intl/locale/tests/unit/xpcshell.ini
+++ b/intl/locale/tests/unit/xpcshell.ini
@@ -6,19 +6,17 @@ support-files =
 
 [test_bug22310.js]
 skip-if = toolkit != "windows" && toolkit != "cocoa"
 
 [test_bug371611.js]
 [test_bug374040.js]
 skip-if = toolkit == "windows" || toolkit == "cocoa"
 
-[test_collation_mac_icu.js]
-skip-if = toolkit != "cocoa"
-
+[test_collation.js]
 [test_bug1086527.js]
 [test_intl_on_workers.js]
 skip-if = toolkit == "android" # bug 1309447
 
 [test_pluralForm.js]
 [test_pluralForm_english.js]
 [test_pluralForm_makeGetter.js]
 
--- a/intl/locale/unix/moz.build
+++ b/intl/locale/unix/moz.build
@@ -1,16 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 SOURCES += [
-    'nsCollationUnix.cpp',
     'nsPosixLocale.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
     SOURCES += [
         'nsUNIXCharset.cpp',
     ]
     GENERATED_FILES = [
deleted file mode 100644
--- a/intl/locale/unix/nsCollationUnix.h
+++ /dev/null
@@ -1,43 +0,0 @@
-
-/* -*- 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/. */
-#ifndef nsCollationUnix_h__
-#define nsCollationUnix_h__
-
-
-#include "nsICollation.h"
-#include "nsCollationFactory.h"  // static library
-#include "plstr.h"
-#include "mozilla/Attributes.h"
-#include "nsString.h"
-
-
-
-class nsCollationUnix final : public nsICollation {
-
-protected:
-  nsCollation   *mCollation;
-  nsCString     mLocale;
-  nsCString     mSavedLocale;
-  bool          mUseCodePointOrder;
-
-  void DoSetLocale();
-  void DoRestoreLocale();
-
-  ~nsCollationUnix(); 
-
-public:
-  nsCollationUnix();
-
-  // nsISupports interface
-  NS_DECL_ISUPPORTS
-
-  // nsICollation interface
-  NS_DECL_NSICOLLATION
-
-};
-
-#endif  /* nsCollationUnix_h__ */
--- a/intl/locale/windows/moz.build
+++ b/intl/locale/windows/moz.build
@@ -1,16 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 SOURCES += [
-    'nsCollationWin.cpp',
     'nsWin32Locale.cpp',
     'nsWinCharset.cpp',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     SOURCES += ['OSPreferences_win.cpp']
 
 FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/intl/locale/windows/nsCollationWin.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- 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 "nsCollationWin.h"
-#include "nsIServiceManager.h"
-#include "nsIComponentManager.h"
-#include "nsIPlatformCharset.h"
-#include "nsWin32Locale.h"
-#include "nsCOMPtr.h"
-#include "prmem.h"
-#include "plstr.h"
-#include <windows.h>
-
-#undef CompareString
-
-NS_IMPL_ISUPPORTS(nsCollationWin, nsICollation)
-
-
-nsCollationWin::nsCollationWin() : mCollation(nullptr)
-{
-}
-
-nsCollationWin::~nsCollationWin() 
-{
-  if (mCollation)
-    delete mCollation;
-}
-
-nsresult nsCollationWin::Initialize(const nsACString& locale)
-{
-  NS_ASSERTION(!mCollation, "Should only be initialized once.");
-
-  nsresult res;
-
-  mCollation = new nsCollation;
-
-  NS_ConvertASCIItoUTF16 wideLocale(locale);
-
-  // default LCID (en-US)
-  mLCID = 1033;
-
-  // Get LCID and charset name from locale, if available
-  LCID lcid;
-  res = nsWin32Locale::GetPlatformLocale(wideLocale, &lcid);
-  if (NS_SUCCEEDED(res)) {
-    mLCID = lcid;
-  }
-
-  nsCOMPtr <nsIPlatformCharset> platformCharset = 
-      do_GetService(NS_PLATFORMCHARSET_CONTRACTID);
-  if (platformCharset) {
-    nsAutoCString mappedCharset;
-    res = platformCharset->GetDefaultCharsetForLocale(wideLocale, mappedCharset);
-    if (NS_SUCCEEDED(res)) {
-      mCollation->SetCharset(mappedCharset.get());
-    }
-  }
-
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP nsCollationWin::CompareString(int32_t strength, 
-                                            const nsAString & string1, 
-                                            const nsAString & string2, 
-                                            int32_t *result)
-{
-  int retval;
-  nsresult res;
-  DWORD dwMapFlags = 0;
-
-  if (strength == kCollationCaseInSensitive)
-    dwMapFlags |= NORM_IGNORECASE;
-
-  retval = ::CompareStringW(mLCID, 
-                            dwMapFlags,
-                            (LPCWSTR) PromiseFlatString(string1).get(), 
-                            -1,
-                            (LPCWSTR) PromiseFlatString(string2).get(), 
-                            -1);
-  if (retval) {
-    res = NS_OK;
-    *result = retval - 2;
-  } else {
-    res = NS_ERROR_FAILURE;
-  }
-
-  return res;
-}
- 
-
-nsresult nsCollationWin::AllocateRawSortKey(int32_t strength, 
-                                            const nsAString& stringIn, uint8_t** key, uint32_t* outLen)
-{
-  int byteLen;
-  void *buffer;
-  nsresult res = NS_OK;
-  DWORD dwMapFlags = LCMAP_SORTKEY;
-
-  if (strength == kCollationCaseInSensitive)
-    dwMapFlags |= NORM_IGNORECASE;
-
-  byteLen = LCMapStringW(mLCID, dwMapFlags, 
-                         (LPCWSTR) PromiseFlatString(stringIn).get(),
-                         -1, nullptr, 0);
-  buffer = PR_Malloc(byteLen);
-  if (!buffer) {
-    res = NS_ERROR_OUT_OF_MEMORY;
-  } else {
-    *key = (uint8_t *)buffer;
-    *outLen = LCMapStringW(mLCID, dwMapFlags, 
-                           (LPCWSTR) PromiseFlatString(stringIn).get(),
-                           -1, (LPWSTR) buffer, byteLen);
-  }
-  return res;
-}
-
-nsresult nsCollationWin::CompareRawSortKey(const uint8_t* key1, uint32_t len1, 
-                                           const uint8_t* key2, uint32_t len2, 
-                                           int32_t* result)
-{
-  *result = PL_strcmp((const char *)key1, (const char *)key2);
-  return NS_OK;
-}
deleted file mode 100644
--- a/intl/locale/windows/nsCollationWin.h
+++ /dev/null
@@ -1,35 +0,0 @@
-
-/* -*- 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/. */
-#ifndef nsCollationWin_h__
-#define nsCollationWin_h__
-
-
-#include "nsICollation.h"
-#include "nsCollationFactory.h"  // static library
-#include "plstr.h"
-
-
-
-class nsCollationWin final : public nsICollation {
-  ~nsCollationWin();
-
-protected:
-  nsCollation   *mCollation;  // XP collation class
-  uint32_t      mLCID;        // Windows platform locale ID
-
-public: 
-  nsCollationWin();
-
-  // nsISupports interface
-  NS_DECL_ISUPPORTS
-
-  // nsICollation interface
-  NS_DECL_NSICOLLATION
-
-};
-
-#endif  /* nsCollationWin_h__ */