<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[200089] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/200089">200089</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-04-26 09:22:32 -0700 (Tue, 26 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebCore on Mac ignores the user's preferred region (country) while getting the language
https://bugs.webkit.org/show_bug.cgi?id=156993

Reviewed by Geoffrey Garen.

I don't know how to test this since this depends on user settings.
        
WebCore was previously getting the list of preferred languages, and for each one, deducing
the default region. That's wrong, since for example it doesn't respect the user's choice (in
System Preferences) to display dates/calenders/etc according to a different region (like how
I have my machine set to en-pl right now).
        
It might be possible for the country code we get via kCFLocaleCountryCode to be something
that our ICU doesn't handle. To defend against this, we search for the resulting country
code in ICU's ISO countries list. If it doesn't appear in that list, we fall back on old
behavior.

* platform/mac/Language.mm:
(WebCore::httpStyleLanguageCode):
(WebCore::platformUserPreferredLanguages):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformmacLanguagemm">trunk/Source/WebCore/platform/mac/Language.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200088 => 200089)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-04-26 16:12:19 UTC (rev 200088)
+++ trunk/Source/WebCore/ChangeLog        2016-04-26 16:22:32 UTC (rev 200089)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2016-04-25  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        WebCore on Mac ignores the user's preferred region (country) while getting the language
+        https://bugs.webkit.org/show_bug.cgi?id=156993
+
+        Reviewed by Geoffrey Garen.
+
+        I don't know how to test this since this depends on user settings.
+        
+        WebCore was previously getting the list of preferred languages, and for each one, deducing
+        the default region. That's wrong, since for example it doesn't respect the user's choice (in
+        System Preferences) to display dates/calenders/etc according to a different region (like how
+        I have my machine set to en-pl right now).
+        
+        It might be possible for the country code we get via kCFLocaleCountryCode to be something
+        that our ICU doesn't handle. To defend against this, we search for the resulting country
+        code in ICU's ISO countries list. If it doesn't appear in that list, we fall back on old
+        behavior.
+
+        * platform/mac/Language.mm:
+        (WebCore::httpStyleLanguageCode):
+        (WebCore::platformUserPreferredLanguages):
+
</ins><span class="cx"> 2016-04-26  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Web IDL] Specify default values for optional parameters of TypedArray types
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmacLanguagemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mac/Language.mm (200088 => 200089)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mac/Language.mm        2016-04-26 16:12:19 UTC (rev 200088)
+++ trunk/Source/WebCore/platform/mac/Language.mm        2016-04-26 16:22:32 UTC (rev 200089)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2003, 2005, 2006, 2010, 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2003, 2005, 2006, 2010, 2011, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #import &quot;CFBundleSPI.h&quot;
</span><span class="cx"> #import &quot;WebCoreNSStringExtras.h&quot;
</span><span class="cx"> #import &lt;mutex&gt;
</span><ins>+#import &lt;unicode/uloc.h&gt;
</ins><span class="cx"> #import &lt;wtf/Assertions.h&gt;
</span><span class="cx"> #import &lt;wtf/Lock.h&gt;
</span><span class="cx"> #import &lt;wtf/NeverDestroyed.h&gt;
</span><span class="lines">@@ -69,7 +70,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static String httpStyleLanguageCode(NSString *language)
</del><ins>+static String httpStyleLanguageCode(NSString *language, NSString *country)
</ins><span class="cx"> {
</span><span class="cx">     SInt32 languageCode;
</span><span class="cx">     SInt32 regionCode; 
</span><span class="lines">@@ -87,9 +88,19 @@
</span><span class="cx"> 
</span><span class="cx">     // Make the string lowercase.
</span><span class="cx">     NSString *lowercaseLanguageCode = [language lowercaseString];
</span><del>-
-    // Turn a '_' into a '-' if it appears after a 2-letter language code.
</del><ins>+    NSString *lowercaseCountryCode = [country lowercaseString];
+    
+    // If we see a &quot;_&quot; after a 2-letter language code:
+    // If the country is valid, replace the &quot;_&quot; and whatever comes after it with &quot;-&quot; followed by the
+    // country code.
+    // Otherwise, replace the &quot;_&quot; with a &quot;-&quot; and use whatever country
+    // CFBundleCopyLocalizationForLocalizationInfo() returned.
</ins><span class="cx">     if ([lowercaseLanguageCode length] &gt;= 3 &amp;&amp; [lowercaseLanguageCode characterAtIndex:2] == '_') {
</span><ins>+        if (country)
+            return [NSString stringWithFormat:@&quot;%@-%@&quot;, [lowercaseLanguageCode substringWithRange:NSMakeRange(0, 2)], lowercaseCountryCode];
+        
+        // Fall back to older behavior, which used the original language-based code but just changed
+        // the &quot;_&quot; to a &quot;-&quot;.
</ins><span class="cx">         RetainPtr&lt;NSMutableString&gt; mutableLanguageCode = adoptNS([lowercaseLanguageCode mutableCopy]);
</span><span class="cx">         [mutableLanguageCode.get() replaceCharactersInRange:NSMakeRange(2, 1) withString:@&quot;-&quot;];
</span><span class="cx">         return mutableLanguageCode.get();
</span><span class="lines">@@ -98,6 +109,18 @@
</span><span class="cx">     return lowercaseLanguageCode;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool isValidICUCountryCode(NSString* countryCode)
+{
+    const char* const* countries = uloc_getISOCountries();
+    const char* countryUTF8 = [countryCode UTF8String];
+    for (unsigned i = 0; countries[i]; ++i) {
+        const char* possibleCountry = countries[i];
+        if (!strcmp(countryUTF8, possibleCountry))
+            return true;
+    }
+    return false;
+}
+
</ins><span class="cx"> Vector&lt;String&gt; platformUserPreferredLanguages()
</span><span class="cx"> {
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="lines">@@ -113,13 +136,19 @@
</span><span class="cx">     Vector&lt;String&gt;&amp; userPreferredLanguages = preferredLanguages();
</span><span class="cx"> 
</span><span class="cx">     if (userPreferredLanguages.isEmpty()) {
</span><ins>+        RetainPtr&lt;CFLocaleRef&gt; locale = adoptCF(CFLocaleCopyCurrent());
+        NSString *countryCode = (NSString *)CFLocaleGetValue(locale.get(), kCFLocaleCountryCode);
+        
+        if (!isValidICUCountryCode(countryCode))
+            countryCode = nil;
+        
</ins><span class="cx">         RetainPtr&lt;CFArrayRef&gt; languages = adoptCF(CFLocaleCopyPreferredLanguages());
</span><span class="cx">         CFIndex languageCount = CFArrayGetCount(languages.get());
</span><span class="cx">         if (!languageCount)
</span><span class="cx">             userPreferredLanguages.append(&quot;en&quot;);
</span><span class="cx">         else {
</span><span class="cx">             for (CFIndex i = 0; i &lt; languageCount; i++)
</span><del>-                userPreferredLanguages.append(httpStyleLanguageCode((NSString *)CFArrayGetValueAtIndex(languages.get(), i)));
</del><ins>+                userPreferredLanguages.append(httpStyleLanguageCode((NSString *)CFArrayGetValueAtIndex(languages.get(), i), countryCode));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>