Bug 943287 - Part 3. nsICollation fallback version for Android. r?hsivonen draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Thu, 23 Mar 2017 13:43:38 +0900
changeset 503371 b9ab09d6f137c3ac38979d81ad1ac59e037fb62a
parent 503370 e1b49606417c3d41d86bfc7c9ebb65531f21ebc1
child 550408 0d13755749a6edd7fe03c419c92a7f8592bf2cfd
push id50557
push userm_kato@ga2.so-net.ne.jp
push dateThu, 23 Mar 2017 04:56:59 +0000
reviewershsivonen
bugs943287
milestone55.0a1
Bug 943287 - Part 3. nsICollation fallback version for Android. r?hsivonen Beta and release channel of Android still turn off ICU. So we should add UTF-8 version of nsICollation for fallback. Some people want to keep --enale-intl-api=no for faster build on developer environment, so even if non-Android, it will be required. MozReview-Commit-ID: 3RcjqoVip1W
intl/locale/moz.build
intl/locale/nsCollation.h
intl/locale/nsCollationAndroid.cpp
intl/locale/tests/unit/xpcshell.ini
intl/locale/unix/nsCollationUnix.cpp
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -42,33 +42,34 @@ EXPORTS += [
 
 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',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     UNIFIED_SOURCES += [
         'DateTimeFormat.cpp',
+        'nsCollation.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'DateTimeFormatAndroid.cpp',
+        'nsCollationAndroid.cpp',
     ]
 
 EXTRA_JS_MODULES += [
     'PluralForm.jsm',
 ]
 
 FINAL_LIBRARY = 'xul'
 
--- a/intl/locale/nsCollation.h
+++ b/intl/locale/nsCollation.h
@@ -6,39 +6,43 @@
 #ifndef nsCollation_h_
 #define nsCollation_h_
 
 #include "mozilla/Attributes.h"
 #include "nsICollation.h"
 #include "nsCollationFactory.h"
 #include "nsString.h"
 
+#ifdef ENABLE_INTL_API
 #include "unicode/ucol.h"
+#endif
 
 class nsCollation final : public nsICollation {
 
 public:
   nsCollation();
 
   // nsISupports interface
   NS_DECL_ISUPPORTS
 
   // nsICollation interface
   NS_DECL_NSICOLLATION
 
 protected:
   ~nsCollation();
 
+#ifdef ENABLE_INTL_API
   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
 };
 
 #endif  /* nsCollation_h_ */
rename from intl/locale/unix/nsCollationUnix.cpp
rename to intl/locale/nsCollationAndroid.cpp
--- a/intl/locale/unix/nsCollationUnix.cpp
+++ b/intl/locale/nsCollationAndroid.cpp
@@ -1,154 +1,90 @@
 /* -*- 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  <locale.h>
-#include "prmem.h"
-#include "nsCollationUnix.h"
-#include "nsIServiceManager.h"
-#include "nsIComponentManager.h"
-#include "nsIPlatformCharset.h"
-#include "nsPosixLocale.h"
+#include "nsCollation.h"
 #include "nsCOMPtr.h"
 #include "nsUnicharUtils.h"
-#include "nsCRT.h"
-//#define DEBUG_UNIX_COLLATION
+#include "prmem.h"
 
-inline void nsCollationUnix::DoSetLocale()
+#include  <string.h>
+
+nsCollation::nsCollation()
 {
-  char *locale = setlocale(LC_COLLATE, nullptr);
-  mSavedLocale.Assign(locale ? locale : "");
-  if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) {
-    (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mLocale,0,MAX_LOCALE_LEN)).get());
-  }
 }
 
-inline void nsCollationUnix::DoRestoreLocale()
-{
-  if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) { 
-    (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mSavedLocale,0,MAX_LOCALE_LEN)).get());
-  }
-}
-
-nsCollationUnix::nsCollationUnix() : mCollation(nullptr)
+nsCollation::~nsCollation()
 {
 }
 
-nsCollationUnix::~nsCollationUnix() 
+NS_IMPL_ISUPPORTS(nsCollation, nsICollation)
+
+NS_IMETHODIMP
+nsCollation::Initialize(const nsACString& locale)
 {
-  if (mCollation)
-    delete mCollation;
+  // Android doesn't have locale support
+  return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS(nsCollationUnix, nsICollation)
-
-nsresult nsCollationUnix::Initialize(const nsACString& locale) 
+NS_IMETHODIMP
+nsCollation::CompareString(int32_t strength,
+                           const nsAString& string1,
+                           const nsAString& string2,
+                           int32_t* result)
 {
-#define kPlatformLocaleLength 64
-  NS_ASSERTION(!mCollation, "Should only be initialized once");
-
-  nsresult res;
+  NS_ENSURE_ARG_POINTER(result);
 
-  mCollation = new nsCollation;
+  nsAutoString stringNormalized1(string1);
+  nsAutoString stringNormalized2(string2);
+  if (strength != kCollationCaseSensitive) {
+    ToLowerCase(stringNormalized1);
+    ToLowerCase(stringNormalized2);
+  }
 
-  nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &res);
-  if (NS_SUCCEEDED(res)) {
-    nsAutoCString mappedCharset;
-    res = platformCharset->GetDefaultCharsetForLocale(NS_ConvertUTF8toUTF16(locale), mappedCharset);
-    if (NS_SUCCEEDED(res)) {
-      mCollation->SetCharset(mappedCharset.get());
-    }
-  }
+  *result = strcoll(NS_ConvertUTF16toUTF8(stringNormalized1).get(),
+                    NS_ConvertUTF16toUTF8(stringNormalized2).get());
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsCollation::AllocateRawSortKey(int32_t strength,
+                                const nsAString& stringIn,
+                                uint8_t** key, uint32_t* outLen)
+{
+  NS_ENSURE_ARG_POINTER(key);
+  NS_ENSURE_ARG_POINTER(outLen);
 
-nsresult nsCollationUnix::CompareString(int32_t strength,
-                                        const nsAString& string1,
-                                        const nsAString& string2,
-                                        int32_t* result) 
-{
-  nsresult res = NS_OK;
-
-  nsAutoString stringNormalized1, stringNormalized2;
+  nsAutoString stringNormalized(stringIn);
   if (strength != kCollationCaseSensitive) {
-    res = mCollation->NormalizeString(string1, stringNormalized1);
-    if (NS_FAILED(res)) {
-      return res;
-    }
-    res = mCollation->NormalizeString(string2, stringNormalized2);
-    if (NS_FAILED(res)) {
-      return res;
-    }
-  } else {
-    stringNormalized1 = string1;
-    stringNormalized2 = string2;
+    ToLowerCase(stringNormalized);
   }
 
-  // convert unicode to charset
-  char *str1, *str2;
-
-  res = mCollation->UnicodeToChar(stringNormalized1, &str1);
-  if (NS_SUCCEEDED(res) && str1) {
-    res = mCollation->UnicodeToChar(stringNormalized2, &str2);
-    if (NS_SUCCEEDED(res) && str2) {
-      DoSetLocale();
-      *result = strcoll(str1, str2);
-      DoRestoreLocale();
-      PR_Free(str2);
-    }
-    PR_Free(str1);
+  // call strxfrm to generate a key
+  NS_ConvertUTF16toUTF8 str(stringNormalized);
+  size_t len = strxfrm(nullptr, str.get(), 0) + 1;
+  void *buffer = PR_Malloc(len);
+  if (strxfrm((char *)buffer, str.get(), len) >= len) {
+    PR_Free(buffer);
+    return NS_ERROR_FAILURE;
   }
 
-  return res;
+  *key = (uint8_t *)buffer;
+  *outLen = len;
+
+  return NS_OK;
 }
 
-
-nsresult nsCollationUnix::AllocateRawSortKey(int32_t strength, 
-                                             const nsAString& stringIn,
-                                             uint8_t** key, uint32_t* outLen)
+NS_IMETHODIMP
+nsCollation::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
+                               const uint8_t* key2, uint32_t len2,
+                               int32_t* result)
 {
-  nsresult res = NS_OK;
-
-  nsAutoString stringNormalized;
-  if (strength != kCollationCaseSensitive) {
-    res = mCollation->NormalizeString(stringIn, stringNormalized);
-    if (NS_FAILED(res))
-      return res;
-  } else {
-    stringNormalized = stringIn;
-  }
-  // convert unicode to charset
-  char *str;
+  NS_ENSURE_ARG_POINTER(key1);
+  NS_ENSURE_ARG_POINTER(key2);
+  NS_ENSURE_ARG_POINTER(result);
 
-  res = mCollation->UnicodeToChar(stringNormalized, &str);
-  if (NS_SUCCEEDED(res) && str) {
-    DoSetLocale();
-    // call strxfrm to generate a key 
-    size_t len = strxfrm(nullptr, str, 0) + 1;
-    void *buffer = PR_Malloc(len);
-    if (!buffer) {
-      res = NS_ERROR_OUT_OF_MEMORY;
-    } else if (strxfrm((char *)buffer, str, len) >= len) {
-      PR_Free(buffer);
-      res = NS_ERROR_FAILURE;
-    } else {
-      *key = (uint8_t *)buffer;
-      *outLen = len;
-    }
-    DoRestoreLocale();
-    PR_Free(str);
-  }
-
-  return res;
-}
-
-nsresult nsCollationUnix::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);
+  *result = strcmp((const char *)key1, (const char *)key2);
   return NS_OK;
 }
--- a/intl/locale/tests/unit/xpcshell.ini
+++ b/intl/locale/tests/unit/xpcshell.ini
@@ -7,16 +7,18 @@ 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.js]
+skip-if = toolkit == "android" # ICU might be turned off
+
 [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]