bug 642203 - Must treat locale pref as localized in multi-locale builds r=blassey,dougt,gavin,mossop a=blocking-fennec GECKO_2_1_BASE
authorMark Finkle <mfinkle@mozilla.com>
Wed, 16 Mar 2011 19:17:59 -0400
changeset 63430 e273946b74c8d631ed86bd74ba9afe0e67b12378
parent 63429 bb59490890025376aadb83090ee55f9731c20dc2
child 63431 40d2d7bcc30af5bacdc885c2edf70825a0089fde
push idunknown
push userunknown
push dateunknown
reviewersblassey, dougt, gavin, mossop, blocking-fennec
bugs642203
milestone2.0b13pre
bug 642203 - Must treat locale pref as localized in multi-locale builds r=blassey,dougt,gavin,mossop a=blocking-fennec
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/nsBlocklistService.js
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
widget/src/android/nsAppShell.cpp
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -339,16 +339,19 @@ SafeInstallOperation.prototype = {
 
 /**
  * Gets the currently selected locale for display.
  * @return  the selected locale or "en-US" if none is selected
  */
 function getLocale() {
   if (Prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false))
     return Services.locale.getLocaleComponentForUserAgent();
+  let locale = Prefs.getComplexPref(PREF_SELECTED_LOCALE, Ci.nsIPrefLocalizedString);
+  if (locale)
+    return locale;
   return Prefs.getCharPref(PREF_SELECTED_LOCALE, "en-US");
 }
 
 /**
  * Selects the closest matching locale from a list of locales.
  *
  * @param  aLocales
  *         An array of locales
@@ -1211,16 +1214,36 @@ var Prefs = {
       return Services.prefs.getCharPref(aName);
     }
     catch (e) {
     }
     return aDefaultValue;
   },
 
   /**
+   * Gets a complex preference.
+   *
+   * @param  aName
+   *         The name of the preference
+   * @param  aType
+   *         The interface type of the preference
+   * @param  aDefaultValue
+   *         A value to return if the preference does not exist
+   * @return the value of the preference or aDefaultValue if there is none
+   */
+  getComplexPref: function(aName, aType, aDefaultValue) {
+    try {
+      return Services.prefs.getComplexPref(aName, aType).data;
+    }
+    catch (e) {
+    }
+    return aDefaultValue;
+  },
+
+  /**
    * Gets a boolean preference.
    *
    * @param  aName
    *         The name of the preference
    * @param  aDefaultValue
    *         A value to return if the preference does not exist
    * @return the value of the preference or aDefaultValue if there is none
    */
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -241,17 +241,18 @@ function matchesOSABI(blocklistElement) 
  * Gets the current value of the locale.  It's possible for this preference to
  * be localized, so we have to do a little extra work here.  Similar code
  * exists in nsHttpHandler.cpp when building the UA string.
  */
 function getLocale() {
   try {
       // Get the default branch
       var defaultPrefs = gPref.getDefaultBranch(null);
-      return defaultPrefs.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
+      return defaultPrefs.getComplexPref(PREF_GENERAL_USERAGENT_LOCALE,
+                                         Ci.nsIPrefLocalizedString).data;
   } catch (e) {}
 
   return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
 }
 
 /**
  * Read the update channel from defaults only.  We do this to ensure that
  * the channel is tightly coupled with the application and does not apply
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -640,21 +640,20 @@ AndroidBridge::IsNetworkLinkUp()
 bool
 AndroidBridge::IsNetworkLinkKnown()
 {
     ALOG_BRIDGE("AndroidBridge::IsNetworkLinkKnown");
     return !!mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass, jIsNetworkLinkKnown);
 }
 
 void
-AndroidBridge::SetSelectedLocale(const nsACString& aLocale)
+AndroidBridge::SetSelectedLocale(const nsAString& aLocale)
 {
     ALOG_BRIDGE("AndroidBridge::SetSelectedLocale");
-    NS_ConvertUTF8toUTF16 wLocale(aLocale);
-    jstring jLocale = GetJNIForThread()->NewString(wLocale.get(), wLocale.Length());
+    jstring jLocale = GetJNIForThread()->NewString(PromiseFlatString(aLocale).get(), aLocale.Length());
     GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSetSelectedLocale, jLocale);
 }
 
 void
 AndroidBridge::SetSurfaceView(jobject obj)
 {
     mSurfaceView.Init(obj);
 }
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -182,17 +182,17 @@ public:
     void ShowInputMethodPicker();
 
     void HideProgressDialogOnce();
 
     bool IsNetworkLinkUp();
 
     bool IsNetworkLinkKnown();
 
-    void SetSelectedLocale(const nsACString&);
+    void SetSelectedLocale(const nsAString&);
 
     struct AutoLocalJNIFrame {
         AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
             // Make sure there is enough space to store a local ref to the
             // exception.  I am not completely sure this is needed, but does
             // not hurt.
             AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries + 1);
         }
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -39,16 +39,17 @@
 #include "nsAppShell.h"
 #include "nsWindow.h"
 #include "nsThreadUtils.h"
 #include "nsICommandLineRunner.h"
 #include "nsIObserverService.h"
 #include "nsIAppStartup.h"
 #include "nsIGeolocationProvider.h"
 #include "nsIPrefService.h"
+#include "nsIPrefLocalizedString.h"
 
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "prenv.h"
 
 #include "AndroidBridge.h"
 #include "nsAccelerometerSystem.h"
 #include <android/log.h>
@@ -129,52 +130,97 @@ nsAppShell::Init()
 
     if (!bridge)
         return rv;
 
     nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     branch->AddObserver("intl.locale.matchOS", this, PR_FALSE);
     branch->AddObserver("general.useragent.locale", this, PR_FALSE);
+
+    nsString locale;
     PRBool match = PR_FALSE;
-    nsCString locale;
-    branch->GetBoolPref("intl.locale.matchOS", &match);
-    if (!match ||
-        NS_FAILED(branch->GetCharPref("general.useragent.locale", getter_Copies(locale))))
-        bridge->SetSelectedLocale(EmptyCString());
-    else
-        bridge->SetSelectedLocale(locale);
+    rv = branch->GetBoolPref("intl.locale.matchOS", &match);
+
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (match) {
+        bridge->SetSelectedLocale(EmptyString());
+        return NS_OK;
+    }
+    nsCOMPtr<nsIPrefLocalizedString> pls;
+    rv = branch->GetComplexValue("general.useragent.locale",
+                                 NS_GET_IID(nsIPrefLocalizedString),
+                                 getter_AddRefs(pls));
+    if (NS_SUCCEEDED(rv) && pls) {
+        nsXPIDLString uval;
+        pls->ToString(getter_Copies(uval));
+        if (uval)
+            locale.Assign(uval);
+    } else {
+        nsXPIDLCString cval;
+        rv = branch->GetCharPref("general.useragent.locale",
+                                 getter_Copies(cval));
+        if (NS_SUCCEEDED(rv) && cval)
+            locale.AssignWithConversion(cval);
+    }
+
+    bridge->SetSelectedLocale(locale);
     return rv;
 }
 
 NS_IMETHODIMP
 nsAppShell::Observe(nsISupports* aSubject,
                     const char* aTopic,
                     const PRUnichar* aData)
 {
     if (!strcmp(aTopic, "xpcom-shutdown")) {
         // We need to ensure no observers stick around after XPCOM shuts down
         // or we'll see crashes, as the app shell outlives XPConnect.
         mObserversHash.Clear();
         return nsBaseAppShell::Observe(aSubject, aTopic, aData);
-    } else if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) && (
-                   !wcscmp((const wchar_t*)aData, L"intl.locale.matchOS") ||
-                   !wcscmp((const wchar_t*)aData, L"general.useragent.locale"))) {
+    } else if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) && aData && (
+                   nsDependentString(aData).Equals(
+                       NS_LITERAL_STRING("general.useragent.locale")) ||
+                   nsDependentString(aData).Equals(
+                       NS_LITERAL_STRING("intl.locale.matchOS"))))
+    {
         AndroidBridge* bridge = AndroidBridge::Bridge();
         nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject);
         if (!prefs || !bridge)
             return NS_OK;
+
+        nsString locale;
         PRBool match = PR_FALSE;
-        nsXPIDLCString locale;
+        nsresult rv = prefs->GetBoolPref("intl.locale.matchOS", &match);
+        NS_ENSURE_SUCCESS(rv, rv);
 
-        if (!match && NS_SUCCEEDED(prefs->GetCharPref("general.useragent.locale",
-                                                      getter_Copies(locale))))
-            bridge->SetSelectedLocale(locale);
-        else
-            bridge->SetSelectedLocale(EmptyCString());
+        if (match) {
+            bridge->SetSelectedLocale(EmptyString());
+            return NS_OK;
+        }
+        nsCOMPtr<nsIPrefLocalizedString> pls;
+        rv = prefs->GetComplexValue("general.useragent.locale",
+                                    NS_GET_IID(nsIPrefLocalizedString),
+                                    getter_AddRefs(pls));
+        if (NS_SUCCEEDED(rv) && pls) {
+            nsXPIDLString uval;
+            pls->ToString(getter_Copies(uval));
+            if (uval)
+                locale.Assign(uval);
+        }
+        else {
+            nsXPIDLCString cval;
+            rv = prefs->GetCharPref("general.useragent.locale",
+                                    getter_Copies(cval));
+            if (NS_SUCCEEDED(rv) && cval)
+                locale.AssignWithConversion(cval);
+        }
+
+        bridge->SetSelectedLocale(locale);
         return NS_OK;
     }
     return NS_OK;
 }
 
 void
 nsAppShell::ScheduleNativeEventCallback()
 {