[tor-commits] [tor-browser/tor-browser-52.5.2esr-7.5-2] Bug 23016: "Print to File" does not create the expected file in non-English locales

gk at torproject.org gk at torproject.org
Thu Dec 14 12:53:02 UTC 2017


commit 8ea9839478bfddd4f078f16c9268edf1755e9cb0
Author: Richard Pospesel <richard at torproject.org>
Date:   Wed Nov 15 10:48:38 2017 -0800

    Bug 23016: "Print to File" does not create the expected file in non-English locales
    
    The Problem:
    
    During firefox and Web Content process startup,
    ::OverrideDefaultLocaleIfNeeded() is called which will conditionally
    ::setlocale() to "C.UTF-8" or "C" based off of the
    javascript.use_us_english_locale preference (to prevent fingerprinting
    based on how dates and what-not are formatted).  Sometime after this
    call in the Web Content process the locale is set to the system's locale
    which effectively stomps over the work done by the
    ::OverrideDefaultLocaleIfNeeded() call.  As a result, the firefox
    process and the Web Content process are configured to use different
    locales; firefox uses "C.UTF-8" while Web Content uses "" (system
    default).
    
    On Linux, the "Print to File" printer is a default GTK printer whose
    name is localized based off of the process's locale.  The GTK print dialog
    is hosted in the firefox process and therefore the printer name will be
    'Print to File.'  This process sends this name over to the Web Content
    process, which iterates over the list of printers and finds one whose
    name matches.  However, as the Web Content process's locale is set to
    system, its printer names will be localized and in the language of the
    system, so no printer with the name 'Print to File' will be found, and
    printing fails.
    
    This is why disabling javascript.use_us_english_locale fixes the issue.
    It also explains why disabling multi-process mode via the
    browser.tabs.remote.autostart.2 preference fixes the issue; one
    process means the printer-name is never used as a selector and also
    means no mismatched locale can happen.
    
    The Solution:
    
    The fix for this issue is to first check the
    javascript.use_us_english_locale preference each place in code where
    setlocale occurs, particularly in the nsLocaleService object which is the
    particular code path which overrides setlocale in the Web Content
    process.
---
 intl/locale/nsLocaleService.cpp   | 72 +++++++++++++++++++++++++++------------
 xpcom/build/XPCOMInit.cpp         | 14 ++++++--
 xpcom/io/nsNativeCharsetUtils.cpp | 14 ++++++--
 3 files changed, 73 insertions(+), 27 deletions(-)

diff --git a/intl/locale/nsLocaleService.cpp b/intl/locale/nsLocaleService.cpp
index 6d45ec9afa2a..e89ff32346cd 100644
--- a/intl/locale/nsLocaleService.cpp
+++ b/intl/locale/nsLocaleService.cpp
@@ -12,6 +12,7 @@
 #include "nsTArray.h"
 #include "nsString.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/Preferences.h"
 
 #include <ctype.h>
 
@@ -93,12 +94,20 @@ protected:
 //
 nsLocaleService::nsLocaleService(void) 
 {
+    // conditionally use us english locale when initialization locale objects
+    const auto use_us_english_locale =
+        mozilla::Preferences::GetBool("javascript.use_us_english_locale", false);
+
 #ifdef XP_WIN
     nsAutoString        xpLocale;
+    // 1033 is default english us locale LCID
+    // https://msdn.microsoft.com/en-us/library/ms912047(v=winembedded.10).aspx
+    const LCID          en_US_lcid = 1033;
+
     //
     // get the system LCID
     //
-    LCID win_lcid = GetSystemDefaultLCID();
+    LCID win_lcid = use_us_english_locale ? en_US_lcid : GetSystemDefaultLCID();
     NS_ENSURE_TRUE_VOID(win_lcid);
     nsWin32Locale::GetXPLocale(win_lcid, xpLocale);
     nsresult rv = NewLocale(xpLocale, getter_AddRefs(mSystemLocale));
@@ -107,7 +116,7 @@ nsLocaleService::nsLocaleService(void)
     //
     // get the application LCID
     //
-    win_lcid = GetUserDefaultLCID();
+    win_lcid = use_us_english_locale ? en_US_lcid : GetUserDefaultLCID();
     NS_ENSURE_TRUE_VOID(win_lcid);
     nsWin32Locale::GetXPLocale(win_lcid, xpLocale);
     rv = NewLocale(xpLocale, getter_AddRefs(mApplicationLocale));
@@ -118,7 +127,7 @@ nsLocaleService::nsLocaleService(void)
     NS_ENSURE_TRUE_VOID(resultLocale);
 
     // Get system configuration
-    const char* lang = getenv("LANG");
+    const char* lang = use_us_english_locale ? "en-US" : getenv("LANG");
 
     nsAutoString xpLocale, platformLocale;
     nsAutoString category, category_platform;
@@ -127,7 +136,19 @@ nsLocaleService::nsLocaleService(void)
     for( i = 0; i < LocaleListLength; i++ ) {
         nsresult result;
         // setlocale( , "") evaluates LC_* and LANG
-        char* lc_temp = setlocale(posix_locale_category[i], "");
+        const auto current_posix_locale_category = posix_locale_category[i];
+        const char* lc_temp = nullptr;
+
+        if (use_us_english_locale) {
+            lc_temp = setlocale(current_posix_locale_category, "C.UTF-8");
+            if (lc_temp == nullptr) {
+                lc_temp = setlocale(current_posix_locale_category, "C");
+            }
+        }
+        else {
+            lc_temp = setlocale(current_posix_locale_category, "");
+        }
+
         CopyASCIItoUTF16(LocaleList[i], category);
         category_platform = category;
         category_platform.AppendLiteral("##PLATFORM");
@@ -163,30 +184,37 @@ nsLocaleService::nsLocaleService(void)
 #endif // XP_UNIX
 
 #ifdef XP_MACOSX
-    // Get string representation of user's current locale
-    CFLocaleRef userLocaleRef = ::CFLocaleCopyCurrent();
-    CFStringRef userLocaleStr = ::CFLocaleGetIdentifier(userLocaleRef);
-    ::CFRetain(userLocaleStr);
-
-    AutoTArray<UniChar, 32> buffer;
-    int size = ::CFStringGetLength(userLocaleStr);
-    buffer.SetLength(size + 1);
-    CFRange range = ::CFRangeMake(0, size);
-    ::CFStringGetCharacters(userLocaleStr, range, buffer.Elements());
-    buffer[size] = 0;
-
-    // Convert the locale string to the format that Mozilla expects
-    nsAutoString xpLocale(reinterpret_cast<char16_t*>(buffer.Elements()));
-    xpLocale.ReplaceChar('_', '-');
+    nsAutoString xpLocale;
+
+    if (use_us_english_locale) {
+        xpLocale = NS_LITERAL_STRING("en-US").get();
+    }
+    else {
+        // Get string representation of user's current locale
+        CFLocaleRef userLocaleRef = ::CFLocaleCopyCurrent();
+        CFStringRef userLocaleStr = ::CFLocaleGetIdentifier(userLocaleRef);
+        ::CFRetain(userLocaleStr);
+
+        AutoTArray<UniChar, 32> buffer;
+        int size = ::CFStringGetLength(userLocaleStr);
+        buffer.SetLength(size + 1);
+        CFRange range = ::CFRangeMake(0, size);
+        ::CFStringGetCharacters(userLocaleStr, range, buffer.Elements());
+        buffer[size] = 0;
+
+        // Convert the locale string to the format that Mozilla expects
+        xpLocale = reinterpret_cast<char16_t*>(buffer.Elements());
+        xpLocale.ReplaceChar('_', '-');
+
+        ::CFRelease(userLocaleStr);
+        ::CFRelease(userLocaleRef);
+    }
 
     nsresult rv = NewLocale(xpLocale, getter_AddRefs(mSystemLocale));
     if (NS_SUCCEEDED(rv)) {
         mApplicationLocale = mSystemLocale;
     }
 
-    ::CFRelease(userLocaleStr);
-    ::CFRelease(userLocaleRef);
-
     NS_ASSERTION(mApplicationLocale, "Failed to create locale objects");
 #endif // XP_MACOSX
 }
diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp
index c72ea48d77c8..4fe9c93de2ec 100644
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -11,6 +11,7 @@
 #include "mozilla/Poison.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/XPCOM.h"
+#include "mozilla/Preferences.h"
 #include "nsXULAppAPI.h"
 
 #include "nsXPCOMPrivate.h"
@@ -571,11 +572,18 @@ NS_InitXPCOM2(nsIServiceManager** aResult,
   }
 
 #ifndef ANDROID
+
   // If the locale hasn't already been setup by our embedder,
-  // get us out of the "C" locale and into the system
-  if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
-    setlocale(LC_ALL, "");
+  // get us out of the "C" locale and into the system,
+  // but only do so if we aren't force using english locale
+  if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
+    setlocale(LC_ALL, "C.UTF-8") || setlocale(LC_ALL, "C");
+  } else {
+    if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
+      setlocale(LC_ALL, "");
+    }
   }
+
 #endif
 
 #if defined(XP_UNIX)
diff --git a/xpcom/io/nsNativeCharsetUtils.cpp b/xpcom/io/nsNativeCharsetUtils.cpp
index e53307af5628..f81c1179256b 100644
--- a/xpcom/io/nsNativeCharsetUtils.cpp
+++ b/xpcom/io/nsNativeCharsetUtils.cpp
@@ -48,6 +48,7 @@ NS_ShutdownNativeCharsetUtils()
 #include <stdlib.h>   // mbtowc, wctomb
 #include <locale.h>   // setlocale
 #include "mozilla/Mutex.h"
+#include "mozilla/Preferences.h"
 #include "nscore.h"
 #include "nsAString.h"
 #include "nsReadableUtils.h"
@@ -316,7 +317,12 @@ nsNativeCharsetConverter::LazyInit()
   // NS_StartupNativeCharsetUtils, assume we are called early enough that
   // we are the first to care about the locale's charset.
   if (!gLock) {
-    setlocale(LC_CTYPE, "");
+
+    if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
+      setlocale(LC_CTYPE, "C.UTF-8") || setlocale(LC_CTYPE, "C");
+    } else {
+      setlocale(LC_CTYPE, "");
+    }
   }
   const char* blank_list[] = { "", nullptr };
   const char** native_charset_list = blank_list;
@@ -884,7 +890,11 @@ NS_StartupNativeCharsetUtils()
   // XXX we assume that we are called early enough that we should
   // always be the first to care about the locale's charset.
   //
-  setlocale(LC_CTYPE, "");
+  if (mozilla::Preferences::GetBool("javascript.use_us_english_locale", false)) {
+    setlocale(LC_CTYPE, "C.UTF-8") || setlocale(LC_CTYPE, "C");
+  } else {
+    setlocale(LC_CTYPE, "");
+  }
 
   nsNativeCharsetConverter::GlobalInit();
 }



More information about the tor-commits mailing list