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
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 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;
 
     }
   },