Bug 1347272 - Move ChromeRegistry::IsLocaleRTL to LocaleService::IsAppLocaleRTL. r?jfkthame draft
authorZibi Braniecki <gandalf@mozilla.com>
Tue, 14 Mar 2017 12:35:06 -0700
changeset 552355 c5ffe57811e75ba2a97aa52244542cd6900f7751
parent 551223 65b0ac174753b22c01156d72fb42d2abd3176dd1
child 621794 58ca9367373b2a57f8aeb7d7566e5bba4a5aa020
push id51328
push userzbraniecki@mozilla.com
push dateTue, 28 Mar 2017 10:29:26 +0000
reviewersjfkthame
bugs1347272
milestone55.0a1
Bug 1347272 - Move ChromeRegistry::IsLocaleRTL to LocaleService::IsAppLocaleRTL. r?jfkthame MozReview-Commit-ID: BDhgIKNSOEL
browser/base/content/utilityOverlay.js
devtools/client/jsonview/converter-child.js
intl/locale/LocaleService.cpp
intl/locale/LocaleService.h
intl/locale/mozILocaleService.idl
intl/locale/tests/gtest/TestLocaleService.cpp
intl/locale/tests/unit/test_localeService.js
netwerk/streamconv/converters/nsIndexedToHTML.cpp
toolkit/components/extensions/ExtensionUtils.jsm
toolkit/components/reader/AboutReader.jsm
xpfe/appshell/nsAppShellService.cpp
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -665,43 +665,23 @@ function getShellService() {
   return ShellService;
 }
 
 function isBidiEnabled() {
   // first check the pref.
   if (getBoolPref("bidi.browser.ui", false))
     return true;
 
-  // then check intl.uidirection.<locale>
-  var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
-                  getService(Components.interfaces.nsIXULChromeRegistry);
-  if (chromeReg.isLocaleRTL("global"))
-    return true;
-
-  // now see if the system locale is an RTL one.
-  var rv = false;
-
-  try {
-    var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
-                                  .getService(Components.interfaces.nsILocaleService);
-    var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0, 3);
+  // now see if the app locale is an RTL one.
+  const isRTL = Services.locale.isAppLocaleRTL;
 
-    switch (systemLocale) {
-      case "ar-":
-      case "he-":
-      case "fa-":
-      case "ug-":
-      case "ur-":
-      case "syr":
-        rv = true;
-        Services.prefs.setBoolPref("bidi.browser.ui", true);
-    }
-  } catch (e) {}
-
-  return rv;
+  if (isRTL) {
+    Services.prefs.setBoolPref("bidi.browser.ui", true);
+  }
+  return isRTL;
 }
 
 function openAboutDialog() {
   var enumerator = Services.wm.getEnumerator("Browser:About");
   while (enumerator.hasMoreElements()) {
     // Only open one about window (Bug 599573)
     let win = enumerator.getNext();
     if (win.closed) {
--- a/devtools/client/jsonview/converter-child.js
+++ b/devtools/client/jsonview/converter-child.js
@@ -225,19 +225,17 @@ Converter.prototype = {
     if (platform.startsWith("WINNT")) {
       os = "win";
     } else if (platform.startsWith("Darwin")) {
       os = "mac";
     } else {
       os = "linux";
     }
 
-    let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
-                        .getService(Ci.nsIXULChromeRegistry);
-    let dir = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr";
+    let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
 
     return "<!DOCTYPE html>\n" +
       "<html platform=\"" + os + "\" class=\"" + themeClassName +
         "\" dir=\"" + dir + "\">" +
       "<head><title>" + this.htmlEncode(title) + "</title>" +
       "<base href=\"" + this.htmlEncode(baseUrl) + "\">" +
       "<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
         themeVarsUrl + "\">" +
@@ -263,19 +261,17 @@ Converter.prototype = {
     let output = "<div id=\"error\">" + "error parsing";
     if (errorInfo.message) {
       output += "<div class=\"errormessage\">" + errorInfo.message + "</div>";
     }
 
     output += "</div><div id=\"json\">" + this.highlightError(data,
       errorInfo.line, errorInfo.column) + "</div>";
 
-    let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
-                        .getService(Ci.nsIXULChromeRegistry);
-    let dir = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr";
+    let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
 
     return "<!DOCTYPE html>\n" +
       "<html><head><title>" + this.htmlEncode(uri + " - Error") + "</title>" +
       "<base href=\"" + this.htmlEncode(this.data.url()) + "\">" +
       "</head><body dir=\"" + dir + "\">" +
       output +
       "</body></html>";
   },
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -37,17 +37,18 @@ mozilla::StaticRefPtr<LocaleService> Loc
  * This function transforms a canonical Mozilla Language Tag, into it's
  * BCP47 compilant form.
  *
  * Example: "ja-JP-mac" -> "ja-JP-x-lvariant-mac"
  *
  * The BCP47 form should be used for all calls to ICU/Intl APIs.
  * The canonical form is used for all internal operations.
  */
-static void SanitizeForBCP47(nsACString& aLocale)
+static void
+SanitizeForBCP47(nsACString& aLocale)
 {
 #ifdef ENABLE_INTL_API
   // Currently, the only locale code we use that's not BCP47-conformant is
   // "ja-JP-mac" on OS X, but let's try to be more general than just
   // hard-coding that here.
   const int32_t LANG_TAG_CAPACITY = 128;
   char langTag[LANG_TAG_CAPACITY];
   nsAutoCString locale(aLocale);
@@ -373,16 +374,46 @@ LocaleService::NegotiateLanguages(const 
   } else if (!aDefaultLocale.IsEmpty() && !aRetVal.Contains(aDefaultLocale)) {
     // If it's not a Lookup strategy, add the default locale only if it's
     // set and it's not in the results already.
     aRetVal.AppendElement(aDefaultLocale);
   }
   return true;
 }
 
+bool
+LocaleService::IsAppLocaleRTL()
+{
+  nsAutoCString locale;
+  GetAppLocaleAsBCP47(locale);
+
+#ifdef ENABLE_INTL_API
+  int pref = Preferences::GetInt("intl.uidirection", -1);
+  if (pref >= 0) {
+    return (pref > 0);
+  }
+  return uloc_isRightToLeft(locale.get());
+#else
+  // first check the intl.uidirection.<locale> preference, and if that is not
+  // set, check the same preference but with just the first two characters of
+  // the locale. If that isn't set, default to left-to-right.
+  nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale;
+  nsAutoCString dir;
+  Preferences::GetCString(prefString.get(), &dir);
+  if (dir.IsEmpty()) {
+    int32_t hyphen = prefString.FindChar('-');
+    if (hyphen >= 1) {
+      prefString.Truncate(hyphen);
+      Preferences::GetCString(prefString.get(), &dir);
+    }
+  }
+  return dir.EqualsLiteral("rtl");
+#endif
+}
+
 NS_IMETHODIMP
 LocaleService::Observe(nsISupports *aSubject, const char *aTopic,
                       const char16_t *aData)
 {
   // At the moment the only thing we're observing are settings indicating
   // user requested locales.
   NS_ConvertUTF16toUTF8 pref(aData);
   if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) || pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
@@ -698,11 +729,17 @@ LocaleService::GetAvailableLocales(uint3
 
   if (!res) {
     NS_ERROR("Couldn't retrieve available locales!");
     return NS_ERROR_FAILURE;
   }
 
   *aCount = availableLocales.Length();
   *aOutArray = CreateOutArray(availableLocales);
-
   return NS_OK;
 }
+
+NS_IMETHODIMP
+LocaleService::GetIsAppLocaleRTL(bool* aRetVal)
+{
+  (*aRetVal) = IsAppLocaleRTL();
+  return NS_OK;
+}
--- a/intl/locale/LocaleService.h
+++ b/intl/locale/LocaleService.h
@@ -162,16 +162,21 @@ public:
    * (See mozILocaleService.idl for a JS-callable version of this.)
    */
   bool NegotiateLanguages(const nsTArray<nsCString>& aRequested,
                           const nsTArray<nsCString>& aAvailable,
                           const nsACString& aDefaultLocale,
                           LangNegStrategy aLangNegStrategy,
                           nsTArray<nsCString>& aRetVal);
 
+  /**
+   * Returns whether the current app locale is RTL.
+   */
+  bool IsAppLocaleRTL();
+
 private:
   /**
    * Locale object, a BCP47-style tag decomposed into subtags for
    * matching purposes.
    *
    * If constructed with aRange = true, any missing subtags will be
    * set to "*".
    */
--- a/intl/locale/mozILocaleService.idl
+++ b/intl/locale/mozILocaleService.idl
@@ -167,9 +167,14 @@ interface mozILocaleService : nsISupport
    *
    * The result is an unordered list of locale IDs which should be
    * used as a availableLocales input list for language negotiation.
    *
    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
    */
   void getAvailableLocales([optional] out unsigned long aCount,
                            [retval, array, size_is(aCount)] out string aLocales);
+
+  /**
+   * Returns whether the current app locale is RTL.
+   */
+  readonly attribute boolean isAppLocaleRTL;
 };
--- a/intl/locale/tests/gtest/TestLocaleService.cpp
+++ b/intl/locale/tests/gtest/TestLocaleService.cpp
@@ -52,8 +52,15 @@ TEST(Intl_Locale_LocaleService, GetAppLo
   nsTArray<nsCString> appLocales;
   LocaleService::GetInstance()->GetAppLocalesAsLangTags(appLocales);
 
   nsAutoCString locale;
   LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale);
 
   ASSERT_TRUE(appLocales[0] == locale);
 }
+
+TEST(Intl_Locale_LocaleService, IsAppLocaleRTL) {
+  // For now we can only test if the method doesn't crash.
+  LocaleService::GetInstance()->IsAppLocaleRTL();
+  ASSERT_TRUE(true);
+
+}
--- a/intl/locale/tests/unit/test_localeService.js
+++ b/intl/locale/tests/unit/test_localeService.js
@@ -126,12 +126,18 @@ add_test(function test_setRequestedLocal
   matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
   do_check_true(matchOS === false);
   let locales = localeService.getRequestedLocales();;
   do_check_true(locales[0] === 'de-AT');
 
   run_next_test();
 });
 
+add_test(function test_isAppLocaleRTL() {
+  do_check_true(typeof localeService.isAppLocaleRTL === 'boolean');
+
+  run_next_test();
+});
+
 do_register_cleanup(() => {
     Services.prefs.clearUserPref(PREF_SELECTED_LOCALE);
     Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE);
 });
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -1,35 +1,37 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "DateTimeFormat.h"
 #include "nsIndexedToHTML.h"
 #include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/intl/LocaleService.h"
 #include "nsNetUtil.h"
 #include "netCore.h"
 #include "nsStringStream.h"
 #include "nsIFile.h"
 #include "nsIFileURL.h"
 #include "nsEscape.h"
 #include "nsIDirIndex.h"
 #include "nsURLHelper.h"
 #include "nsIPlatformCharset.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefLocalizedString.h"
-#include "nsIChromeRegistry.h"
 #include "nsIStringBundle.h"
 #include "nsITextToSubURI.h"
 #include "nsXPIDLString.h"
 #include <algorithm>
 #include "nsIChannel.h"
 
+using mozilla::intl::LocaleService;
+
 NS_IMPL_ISUPPORTS(nsIndexedToHTML,
                   nsIDirIndexListener,
                   nsIStreamConverter,
                   nsIRequestObserver,
                   nsIStreamListener)
 
 static void AppendNonAsciiToNCR(const nsAString& in, nsCString& out)
 {
@@ -557,24 +559,18 @@ nsIndexedToHTML::DoOnStartRequest(nsIReq
         }
     }
     else
     {
         NS_ERROR("broken protocol handler didn't escape double-quote.");
     }
 
     nsCString direction(NS_LITERAL_CSTRING("ltr"));
-    nsCOMPtr<nsIXULChromeRegistry> reg =
-      mozilla::services::GetXULChromeRegistryService();
-    if (reg) {
-      bool isRTL = false;
-      reg->IsLocaleRTL(NS_LITERAL_CSTRING("global"), &isRTL);
-      if (isRTL) {
-        direction.AssignLiteral("rtl");
-      }
+    if (LocaleService::GetInstance()->IsAppLocaleRTL()) {
+      direction.AssignLiteral("rtl");
     }
 
     buffer.AppendLiteral("</head>\n<body dir=\"");
     buffer.Append(direction);
     buffer.AppendLiteral("\">\n<h1>");
     
     const char16_t* formatHeading[] = {
         htmlEscSpec.get()
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -625,18 +625,17 @@ LocaleData.prototype = {
         return str.replace(/\$(?:([1-9]\d*)|(\$+))/g, replacer);
       }
     }
 
     // Check for certain pre-defined messages.
     if (message == "@@ui_locale") {
       return this.uiLocale;
     } else if (message.startsWith("@@bidi_")) {
-      let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
-      let rtl = registry.isLocaleRTL("global");
+      let rtl = Services.locale.isAppLocaleRTL;
 
       if (message == "@@bidi_dir") {
         return rtl ? "rtl" : "ltr";
       } else if (message == "@@bidi_reversed_dir") {
         return rtl ? "ltr" : "rtl";
       } else if (message == "@@bidi_start_edge") {
         return rtl ? "right" : "left";
       } else if (message == "@@bidi_end_edge") {
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -12,18 +12,16 @@ Cu.import("resource://gre/modules/Reader
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncPrefs", "resource://gre/modules/AsyncPrefs.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NarrateControls", "resource://gre/modules/narrate/NarrateControls.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Rect", "resource://gre/modules/Geometry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "gChromeRegistry",
-                                   "@mozilla.org/chrome/chrome-registry;1", Ci.nsIXULChromeRegistry);
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
 
 var gStrings = Services.strings.createBundle("chrome://global/locale/aboutReader.properties");
 
 const gIsFirefoxDesktop = Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 
 var AboutReader = function(mm, win, articlePromise) {
   let url = this._getOriginalUrl(win);
@@ -728,17 +726,17 @@ AboutReader.prototype = {
 
   _maybeSetTextDirection: function Read_maybeSetTextDirection(article) {
     if (article.dir) {
       // Set "dir" attribute on content
       this._contentElement.setAttribute("dir", article.dir);
       this._headerElement.setAttribute("dir", article.dir);
 
       // The native locale could be set differently than the article's text direction.
-      var localeDirection = gChromeRegistry.isLocaleRTL("global") ? "rtl" : "ltr";
+      var localeDirection = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
       this._readTimeElement.setAttribute("dir", localeDirection);
       this._readTimeElement.style.textAlign = article.dir == "rtl" ? "right" : "left";
     }
   },
 
   _formatReadTime(slowEstimate, fastEstimate) {
     let displayStringKey = "aboutReader.estimatedReadTimeRange1";
 
--- a/xpfe/appshell/nsAppShellService.cpp
+++ b/xpfe/appshell/nsAppShellService.cpp
@@ -26,35 +26,36 @@
 #include "nsIWidget.h"
 #include "nsIRequestObserver.h"
 #include "nsIEmbeddingSiteWindow.h"
 
 #include "nsAppShellService.h"
 #include "nsContentUtils.h"
 #include "nsThreadUtils.h"
 #include "nsISupportsPrimitives.h"
-#include "nsIChromeRegistry.h"
 #include "nsILoadContext.h"
 #include "nsIWebNavigation.h"
 #include "nsIWindowlessBrowser.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StartupTimeline.h"
+#include "mozilla/intl/LocaleService.h"
 
 #include "nsEmbedCID.h"
 #include "nsIWebBrowser.h"
 #include "nsIDocShell.h"
 
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
 #include "EventTracer.h"
 #endif
 
 using namespace mozilla;
+using mozilla::intl::LocaleService;
 
 // Default URL for the hidden window, can be overridden by a pref on Mac
 #define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html"
 
 class nsIAppShell;
 
 nsAppShellService::nsAppShellService() :
   mXPCOMWillShutDown(false),
@@ -715,25 +716,17 @@ nsAppShellService::JustCreateTopWindow(n
       aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) {
     aInitialWidth = 1;
     aInitialHeight = 1;
     window->SetIntrinsicallySized(true);
   }
 
   bool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
 
-  nsCOMPtr<nsIXULChromeRegistry> reg =
-    mozilla::services::GetXULChromeRegistryService();
-  if (reg) {
-    nsAutoCString package;
-    package.AssignLiteral("global");
-    bool isRTL = false;
-    reg->IsLocaleRTL(package, &isRTL);
-    widgetInitData.mRTL = isRTL;
-  }
+  widgetInitData.mRTL = LocaleService::GetInstance()->IsAppLocaleRTL();
 
 #ifdef MOZ_WIDGET_GONK
   // B2G multi-screen support. Screen ID is for differentiating screens of
   // windows, and due to the hardware limitation, it is platform-specific for
   // now, which align with the value of display type defined in HWC.
   widgetInitData.mScreenId = mScreenId;
 #endif