Bug 917480 - Part 4: handle resetting to the system default locale. r=nalexander
authorRichard Newman <rnewman@mozilla.com>
Tue, 29 Apr 2014 13:41:38 -0700
changeset 183069 84cc0fb8d2f9
parent 183068 1c25bbb1fd76
child 183070 7cf6451e1c88
push id26779
push usercbook@mozilla.com
push date2014-05-14 11:02 +0000
treeherdermozilla-central@5754fc307237 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs917480
milestone32.0a1
Bug 917480 - Part 4: handle resetting to the system default locale. r=nalexander
mobile/android/base/BrowserLocaleManager.java
mobile/android/base/LocaleManager.java
mobile/android/base/preferences/GeckoPreferences.java
mobile/android/chrome/content/browser.js
--- a/mobile/android/base/BrowserLocaleManager.java
+++ b/mobile/android/base/BrowserLocaleManager.java
@@ -45,19 +45,20 @@ import org.mozilla.gecko.util.GeckoJarRe
 public class BrowserLocaleManager implements LocaleManager {
     private static final String LOG_TAG = "GeckoLocales";
 
     private static final String EVENT_LOCALE_CHANGED = "Locale:Changed";
     private static final String PREF_LOCALE = "locale";
 
     private static final String FALLBACK_LOCALE_TAG = "en-US";
 
-    // This is volatile because we don't impose restrictions
+    // These are volatile because we don't impose restrictions
     // over which thread calls our methods.
     private volatile Locale currentLocale = null;
+    private volatile Locale systemLocale = Locale.getDefault();
 
     private AtomicBoolean inited = new AtomicBoolean(false);
     private boolean systemLocaleDidChange = false;
     private BroadcastReceiver receiver;
 
     private static AtomicReference<LocaleManager> instance = new AtomicReference<LocaleManager>();
 
     public static LocaleManager getInstance() {
@@ -126,16 +127,22 @@ public class BrowserLocaleManager implem
     public void initialize(final Context context) {
         if (!inited.compareAndSet(false, true)) {
             return;
         }
 
         receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
+                // We don't trust Locale.getDefault() here, because we make a
+                // habit of mutating it! Use the one Android supplies, because
+                // that gets regularly reset.
+                // The default value of systemLocale is fine, because we haven't
+                // yet swizzled Locale during static initialization.
+                systemLocale = context.getResources().getConfiguration().locale;
                 systemLocaleDidChange = true;
             }
         };
         context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
     }
 
     @Override
     public boolean systemLocaleDidChange() {
@@ -215,16 +222,30 @@ public class BrowserLocaleManager implem
 
         // Tell Gecko.
         GeckoEvent ev = GeckoEvent.createBroadcastEvent(EVENT_LOCALE_CHANGED, BrowserLocaleManager.getLanguageTag(getCurrentLocale(context)));
         GeckoAppShell.sendEventToGecko(ev);
 
         return resultant;
     }
 
+    @Override
+    public void resetToSystemLocale(Context context) {
+        // Wipe the pref.
+        final SharedPreferences settings = getSharedPreferences(context);
+        settings.edit().remove(PREF_LOCALE).commit();
+
+        // Apply the system locale.
+        updateLocale(context, systemLocale);
+
+        // Tell Gecko.
+        GeckoEvent ev = GeckoEvent.createBroadcastEvent(EVENT_LOCALE_CHANGED, "");
+        GeckoAppShell.sendEventToGecko(ev);
+    }
+
     /**
      * This is public to allow for an activity to force the
      * current locale to be applied if necessary (e.g., when
      * a new activity launches).
      */
     @Override
     public void updateConfiguration(Context context, Locale locale) {
         Resources res = context.getResources();
@@ -279,18 +300,22 @@ public class BrowserLocaleManager implem
         // Fast path.
         final Locale defaultLocale = Locale.getDefault();
         if (defaultLocale.toString().equals(localeCode)) {
             return null;
         }
 
         final Locale locale = parseLocaleCode(localeCode);
 
+        return updateLocale(context, locale);
+    }
+
+    private String updateLocale(Context context, final Locale locale) {
         // Fast path.
-        if (defaultLocale.equals(locale)) {
+        if (Locale.getDefault().equals(locale)) {
             return null;
         }
 
         Locale.setDefault(locale);
         currentLocale = locale;
 
         // Update resources.
         updateConfiguration(context, locale);
--- a/mobile/android/base/LocaleManager.java
+++ b/mobile/android/base/LocaleManager.java
@@ -13,9 +13,10 @@ import android.content.res.Resources;
 public interface LocaleManager {
     void initialize(Context context);
     Locale getCurrentLocale(Context context);
     String getAndApplyPersistedLocale(Context context);
     void correctLocale(Context context, Resources resources, Configuration newConfig);
     void updateConfiguration(Context context, Locale locale);
     String setSelectedLocale(Context context, String localeCode);
     boolean systemLocaleDidChange();
+    void resetToSystemLocale(Context context);
 }
--- a/mobile/android/base/preferences/GeckoPreferences.java
+++ b/mobile/android/base/preferences/GeckoPreferences.java
@@ -712,32 +712,32 @@ public class GeckoPreferences
      * * We need to adapt the preferences UI to the locale ourselves.
      * * The user might not hit Back (or Up) -- they might hit Home and never
      *   come back.
      *
      * We handle the case of the user returning to the browser via the
      * onActivityResult mechanism: see {@link BrowserApp#onActivityResult(int, int, Intent)}.
      */
     private boolean onLocaleSelected(final String newValue) {
-        if (newValue.equals("")) {
-            // TODO: reset our locale to match system.
-            return false;
-        }
-
         final Context context = getApplicationContext();
 
         // LocaleManager operations need to occur on the background thread.
         // ... but activity operations need to occur on the UI thread. So we
         // have nested runnables.
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 final LocaleManager localeManager = BrowserLocaleManager.getInstance();
-                if (null == localeManager.setSelectedLocale(context, newValue)) {
-                    localeManager.updateConfiguration(context, Locale.getDefault());
+
+                if (newValue.equals("")) {
+                    BrowserLocaleManager.getInstance().resetToSystemLocale(context);
+                } else {
+                    if (null == localeManager.setSelectedLocale(context, newValue)) {
+                        localeManager.updateConfiguration(context, Locale.getDefault());
+                    }
                 }
 
                 ThreadUtils.postToUiThread(new Runnable() {
                     @Override
                     public void run() {
                         onLocaleChanged(Locale.getDefault());
                     }
                 });
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1607,24 +1607,28 @@ var BrowserApp = {
         break;
 
       case "Webapps:AutoUninstall":
         WebappManager.autoUninstall(JSON.parse(aData));
         break;
 #endif
 
       case "Locale:Changed":
-        // The value provided to Locale:Changed should be a BCP47 language tag
-        // understood by Gecko -- for example, "es-ES" or "de".
-        console.log("Locale:Changed: " + aData);
-
-        // TODO: do we need to be more nuanced here -- e.g., checking for the
-        // OS locale -- or should it always be false on Fennec?
-        Services.prefs.setBoolPref("intl.locale.matchOS", false);
-        Services.prefs.setCharPref("general.useragent.locale", aData);
+        if (aData) {
+          // The value provided to Locale:Changed should be a BCP47 language tag
+          // understood by Gecko -- for example, "es-ES" or "de".
+          console.log("Locale:Changed: " + aData);
+          Services.prefs.setCharPref("general.useragent.locale", aData);
+        } else {
+          // Resetting.
+          console.log("Switching to system locale.");
+          Services.prefs.clearUserPref("general.useragent.locale");
+        }
+
+        Services.prefs.setBoolPref("intl.locale.matchOS", !aData);
         break;
 
       default:
         dump('BrowserApp.observe: unexpected topic "' + aTopic + '"\n');
         break;
 
     }
   },