Bug 1486552 - geckoview: Add GeckoRuntimeSettings.setLocale method. r=snorp, a=ritu GECKOVIEW_62_RELBRANCH
authorMatt Brubeck <mbrubeck@mozilla.com>
Fri, 31 Aug 2018 11:33:29 -0700
branchGECKOVIEW_62_RELBRANCH
changeset 481187 691b21e74a51
parent 481186 49b9303f687d
child 481188 7f2d67c5d804
push id1801
push userryanvm@gmail.com
push dateFri, 28 Sep 2018 10:06:43 +0000
treeherdermozilla-release@691b21e74a51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, ritu
bugs1486552
milestone62.0.3
Bug 1486552 - geckoview: Add GeckoRuntimeSettings.setLocale method. r=snorp, a=ritu Differential Revision: https://phabricator.services.mozilla.com/D4794
mobile/android/components/geckoview/GeckoViewStartup.js
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
--- a/mobile/android/components/geckoview/GeckoViewStartup.js
+++ b/mobile/android/components/geckoview/GeckoViewStartup.js
@@ -1,15 +1,16 @@
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  EventDispatcher: "resource://gre/modules/Messaging.jsm",
   GeckoViewTelemetryController: "resource://gre/modules/GeckoViewTelemetryController.jsm",
   GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
   Services: "resource://gre/modules/Services.jsm",
 });
 
 function GeckoViewStartup() {
 }
 
@@ -92,15 +93,20 @@ GeckoViewStartup.prototype = {
         }, {
           handler: _ => this.GeckoViewRemoteDebugger,
         });
 
         // This initializes Telemetry for GeckoView only in the parent process.
         // The Telemetry initialization for the content process is performed in
         // ContentProcessSingleton.js for consistency with Desktop Telemetry.
         GeckoViewTelemetryController.setup();
+
+        // Listen for global EventDispatcher messages
+        EventDispatcher.instance.registerListener(
+          (aEvent, aData, aCallback) => Services.locale.setRequestedLocales([aData.languageTag]),
+          "GeckoView:SetLocale");
         break;
       }
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GeckoViewStartup]);
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
@@ -0,0 +1,33 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.geckoview.test
+
+import org.mozilla.geckoview.GeckoSession
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ReuseSession
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
+
+import android.support.test.filters.MediumTest
+import android.support.test.runner.AndroidJUnit4
+import org.hamcrest.Matchers.*
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@WithDevToolsAPI
+class LocaleTest : BaseSessionTest() {
+
+    @Test fun setLocale() {
+        sessionRule.runtime.getSettings().setLocale("en-GB");
+
+        val index = sessionRule.waitForChromeJS(String.format(
+                "(function() {" +
+                "  return ChromeUtils.import('resource://gre/modules/Services.jsm', {})" +
+                "    .Services.locale.getRequestedLocales().indexOf('en-GB');" +
+                "})()")) as Double;
+
+        assertThat("Requested locale is found", index, greaterThanOrEqualTo(0.0));
+    }
+}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -11,16 +11,18 @@ import java.lang.annotation.RetentionPol
 
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate;
 
 public final class GeckoRuntimeSettings implements Parcelable {
     /**
      * Settings builder used to construct the settings object.
      */
     public static final class Builder {
         private final GeckoRuntimeSettings mSettings;
@@ -240,16 +242,27 @@ public final class GeckoRuntimeSettings 
          * @param enabled A flag determining whether or not to block phishing
          *                sites.
          * @return The builder instance.
          */
         public @NonNull Builder blockPhishing(boolean enabled) {
             mSettings.mSafebrowsingPhishing.set(enabled);
             return this;
         }
+
+        /**
+         * Set the locale.
+         *
+         * @param languageTag The locale code in Gecko format ("en" or "en-US").
+         * @return The builder instance.
+         */
+        public @NonNull Builder locale(String languageTag) {
+            mSettings.mLocale = languageTag;
+            return this;
+        }
     }
 
     /* package */ GeckoRuntime runtime;
     /* package */ boolean mUseContentProcess;
     /* package */ String[] mArgs;
     /* package */ Bundle mExtras;
     /* package */ int prefCount;
 
@@ -306,16 +319,17 @@ public final class GeckoRuntimeSettings 
     /* package */ Pref<Boolean> mSafebrowsingMalware = new Pref<Boolean>(
         "browser.safebrowsing.malware.enabled", true);
     /* package */ Pref<Boolean> mSafebrowsingPhishing = new Pref<Boolean>(
         "browser.safebrowsing.phishing.enabled", true);
 
     /* package */ boolean mNativeCrashReporting;
     /* package */ boolean mJavaCrashReporting;
     /* package */ boolean mDebugPause;
+    /* package */ String mLocale;
 
     private final Pref<?>[] mPrefs = new Pref<?>[] {
         mCookieBehavior, mCookieLifetime, mCookieLifetimeDays, mJavaScript,
         mRemoteDebugging, mSafebrowsingMalware, mSafebrowsingPhishing,
         mTrackingProtection, mWebFonts
     };
 
     /* package */ GeckoRuntimeSettings() {
@@ -345,19 +359,21 @@ public final class GeckoRuntimeSettings 
             @SuppressWarnings("unchecked")
             final Pref<Object> uncheckedPref = (Pref<Object>) mPrefs[i];
             uncheckedPref.set(settings.mPrefs[i].get());
         }
 
         mNativeCrashReporting = settings.mNativeCrashReporting;
         mJavaCrashReporting = settings.mJavaCrashReporting;
         mDebugPause = settings.mDebugPause;
+        mLocale = settings.mLocale;
     }
 
     /* package */ void flush() {
+        flushLocale();
         for (final Pref<?> pref: mPrefs) {
             pref.flush();
         }
     }
 
     /**
      * Get the content process hint flag.
      *
@@ -465,16 +481,39 @@ public final class GeckoRuntimeSettings 
 
     /**
      * Gets whether the pause-for-debugger is enabled or not.
      *
      * @return True if the pause is enabled.
      */
     public boolean getPauseForDebuggerEnabled() { return mDebugPause; }
 
+    /**
+     * Gets the locale code in Gecko format ("en" or "en-US").
+     */
+    public String getLocale() {
+        return mLocale;
+    }
+
+    /**
+     * Set the locale.
+     *
+     * @param languageTag The locale code in Gecko format ("en-US").
+     */
+    public void setLocale(String languageTag) {
+        mLocale = languageTag;
+        flushLocale();
+    }
+
+    private void flushLocale() {
+        final GeckoBundle data = new GeckoBundle(1);
+        data.putString("languageTag", mLocale);
+        EventDispatcher.getInstance().dispatch("GeckoView:SetLocale", data);
+    }
+
     // Sync values with nsICookieService.idl.
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({ COOKIE_ACCEPT_ALL, COOKIE_ACCEPT_FIRST_PARTY,
               COOKIE_ACCEPT_NONE, COOKIE_ACCEPT_VISITED })
     /* package */ @interface CookieBehavior {}
 
     /**
      * Accept first-party and third-party cookies and site data.
@@ -673,16 +712,17 @@ public final class GeckoRuntimeSettings 
 
         for (final Pref<?> pref : mPrefs) {
             out.writeValue(pref.get());
         }
 
         ParcelableUtils.writeBoolean(out, mNativeCrashReporting);
         ParcelableUtils.writeBoolean(out, mJavaCrashReporting);
         ParcelableUtils.writeBoolean(out, mDebugPause);
+        out.writeString(mLocale);
     }
 
     // AIDL code may call readFromParcel even though it's not part of Parcelable.
     public void readFromParcel(final Parcel source) {
         mUseContentProcess = ParcelableUtils.readBoolean(source);
         mArgs = source.createStringArray();
         mExtras.readFromParcel(source);
 
@@ -691,16 +731,17 @@ public final class GeckoRuntimeSettings 
             @SuppressWarnings("unchecked")
             final Pref<Object> uncheckedPref = (Pref<Object>) pref;
             uncheckedPref.set(source.readValue(getClass().getClassLoader()));
         }
 
         mNativeCrashReporting = ParcelableUtils.readBoolean(source);
         mJavaCrashReporting = ParcelableUtils.readBoolean(source);
         mDebugPause = ParcelableUtils.readBoolean(source);
+        mLocale = source.readString();
     }
 
     public static final Parcelable.Creator<GeckoRuntimeSettings> CREATOR
         = new Parcelable.Creator<GeckoRuntimeSettings>() {
         @Override
         public GeckoRuntimeSettings createFromParcel(final Parcel in) {
             final GeckoRuntimeSettings settings = new GeckoRuntimeSettings();
             settings.readFromParcel(in);