summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/Language.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/Language.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/Language.cpp')
-rw-r--r--Source/WebCore/platform/Language.cpp70
1 files changed, 51 insertions, 19 deletions
diff --git a/Source/WebCore/platform/Language.cpp b/Source/WebCore/platform/Language.cpp
index fcd31259f..ec4b34924 100644
--- a/Source/WebCore/platform/Language.cpp
+++ b/Source/WebCore/platform/Language.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,24 +27,39 @@
#include "Language.h"
#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/PlatformUserPreferredLanguages.h>
#include <wtf/RetainPtr.h>
#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC)
+#if USE(CF) && !PLATFORM(WIN)
#include <CoreFoundation/CoreFoundation.h>
#endif
namespace WebCore {
+static StaticLock userPreferredLanguagesMutex;
+
+static void registerLanguageDidChangeCallbackIfNecessary()
+{
+ static std::once_flag once;
+ std::call_once(
+ once,
+ [] {
+ setPlatformUserPreferredLanguagesChangedCallback(languageDidChange);
+ });
+}
+
typedef HashMap<void*, LanguageChangeObserverFunction> ObserverMap;
static ObserverMap& observerMap()
{
- DEFINE_STATIC_LOCAL(ObserverMap, map, ());
- return map;
+ static NeverDestroyed<ObserverMap> map;
+ return map.get();
}
void addLanguageChangeObserver(void* context, LanguageChangeObserverFunction customObserver)
{
+ registerLanguageDidChangeCallbackIfNecessary();
observerMap().set(context, customObserver);
}
@@ -72,7 +87,7 @@ String defaultLanguage()
static Vector<String>& preferredLanguagesOverride()
{
- DEFINE_STATIC_LOCAL(Vector<String>, override, ());
+ static NeverDestroyed<Vector<String>> override;
return override;
}
@@ -84,20 +99,34 @@ Vector<String> userPreferredLanguagesOverride()
void overrideUserPreferredLanguages(const Vector<String>& override)
{
preferredLanguagesOverride() = override;
+ languageDidChange();
}
-
+
+static Vector<String> isolatedCopy(const Vector<String>& strings)
+{
+ Vector<String> copy;
+ copy.reserveInitialCapacity(strings.size());
+ for (auto& language : strings)
+ copy.uncheckedAppend(language.isolatedCopy());
+ return copy;
+}
+
Vector<String> userPreferredLanguages()
{
- Vector<String>& override = preferredLanguagesOverride();
- if (!override.isEmpty())
- return override;
+ {
+ std::lock_guard<StaticLock> lock(userPreferredLanguagesMutex);
+ Vector<String>& override = preferredLanguagesOverride();
+ if (!override.isEmpty())
+ return isolatedCopy(override);
+ }
+ registerLanguageDidChangeCallbackIfNecessary();
return platformUserPreferredLanguages();
}
static String canonicalLanguageIdentifier(const String& languageCode)
{
- String lowercaseLanguageCode = languageCode.lower();
+ String lowercaseLanguageCode = languageCode.convertToASCIILowercase();
if (lowercaseLanguageCode.length() >= 3 && lowercaseLanguageCode[2] == '_')
lowercaseLanguageCode.replace(2, 1, "-");
@@ -105,22 +134,25 @@ static String canonicalLanguageIdentifier(const String& languageCode)
return lowercaseLanguageCode;
}
-size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<String>& languageList)
+size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<String>& languageList, bool& exactMatch)
{
+ String lowercaseLanguage = language.convertToASCIILowercase();
String languageWithoutLocaleMatch;
String languageMatchButNotLocale;
size_t languageWithoutLocaleMatchIndex = 0;
size_t languageMatchButNotLocaleMatchIndex = 0;
- bool canMatchLanguageOnly = (language.length() == 2 || (language.length() >= 3 && language[2] == '-'));
+ bool canMatchLanguageOnly = (lowercaseLanguage.length() == 2 || (lowercaseLanguage.length() >= 3 && lowercaseLanguage[2] == '-'));
for (size_t i = 0; i < languageList.size(); ++i) {
String canonicalizedLanguageFromList = canonicalLanguageIdentifier(languageList[i]);
- if (language == canonicalizedLanguageFromList)
+ if (lowercaseLanguage == canonicalizedLanguageFromList) {
+ exactMatch = true;
return i;
+ }
if (canMatchLanguageOnly && canonicalizedLanguageFromList.length() >= 2) {
- if (language[0] == canonicalizedLanguageFromList[0] && language[1] == canonicalizedLanguageFromList[1]) {
+ if (lowercaseLanguage[0] == canonicalizedLanguageFromList[0] && lowercaseLanguage[1] == canonicalizedLanguageFromList[1]) {
if (!languageWithoutLocaleMatch.length() && canonicalizedLanguageFromList.length() == 2) {
languageWithoutLocaleMatch = languageList[i];
languageWithoutLocaleMatchIndex = i;
@@ -133,6 +165,8 @@ size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<St
}
}
+ exactMatch = false;
+
// If we have both a language-only match and a languge-but-not-locale match, return the
// languge-only match as is considered a "better" match. For example, if the list
// provided has both "en-GB" and "en" and the user prefers "en-US" we will return "en".
@@ -147,11 +181,9 @@ size_t indexOfBestMatchingLanguageInList(const String& language, const Vector<St
String displayNameForLanguageLocale(const String& localeName)
{
-#if PLATFORM(MAC)
- if (!localeName.isNull() && !localeName.isEmpty()) {
- RetainPtr<CFLocaleRef> currentLocale = adoptCF(CFLocaleCopyCurrent());
- return CFLocaleCopyDisplayNameForPropertyValue(currentLocale.get(), kCFLocaleIdentifier, localeName.createCFString().get());
- }
+#if USE(CF) && !PLATFORM(WIN)
+ if (!localeName.isEmpty())
+ return adoptCF(CFLocaleCopyDisplayNameForPropertyValue(adoptCF(CFLocaleCopyCurrent()).get(), kCFLocaleIdentifier, localeName.createCFString().get())).get();
#endif
return localeName;
}