// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/translate/translate_accept_languages.h" #include "base/bind.h" #include "base/command_line.h" #include "base/prefs/pref_change_registrar.h" #include "base/prefs/pref_service.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/translate/translate_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/translate/translate_util.h" #include "content/public/browser/notification_source.h" #include "net/url_request/url_fetcher.h" #include "ui/base/l10n/l10n_util.h" TranslateAcceptLanguages::TranslateAcceptLanguages() { } TranslateAcceptLanguages::~TranslateAcceptLanguages() { } // static bool TranslateAcceptLanguages::CanBeAcceptLanguage( const std::string& language) { std::string accept_language = language; TranslateUtil::ToChromeLanguageSynonym(&accept_language); const std::string locale = g_browser_process->GetApplicationLocale(); std::vector accept_language_codes; l10n_util::GetAcceptLanguagesForLocale(locale, &accept_language_codes); if (std::find(accept_language_codes.begin(), accept_language_codes.end(), accept_language) != accept_language_codes.end()) { return true; } return false; } bool TranslateAcceptLanguages::IsAcceptLanguage(Profile* profile, const std::string& language) { DCHECK(profile); PrefService* pref_service = profile->GetPrefs(); PrefServiceLanguagesMap::const_iterator iter = accept_languages_.find(pref_service); if (iter == accept_languages_.end()) { InitAcceptLanguages(pref_service); // Listen for this profile going away, in which case we would need to clear // the accepted languages for the profile. notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::Source(profile)); // Also start listening for changes in the accept languages. DCHECK(pref_change_registrars_.find(pref_service) == pref_change_registrars_.end()); PrefChangeRegistrar* pref_change_registrar = new PrefChangeRegistrar; pref_change_registrar->Init(pref_service); pref_change_registrar->Add( prefs::kAcceptLanguages, base::Bind(&TranslateAcceptLanguages::InitAcceptLanguages, base::Unretained(this), pref_service)); pref_change_registrars_[pref_service] = pref_change_registrar; iter = accept_languages_.find(pref_service); } std::string accept_language = language; TranslateUtil::ToChromeLanguageSynonym(&accept_language); return iter->second.count(accept_language) != 0; } void TranslateAcceptLanguages::InitAcceptLanguages(PrefService* prefs) { DCHECK(prefs); // We have been asked for this profile, build the languages. std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); std::vector accept_langs_list; LanguageSet accept_langs_set; base::SplitString(accept_langs_str, ',', &accept_langs_list); std::vector::const_iterator iter; std::string app_locale = g_browser_process->GetApplicationLocale(); std::string ui_lang = TranslateManager::GetLanguageCode(app_locale); bool is_ui_english = StartsWithASCII(ui_lang, "en-", false); CommandLine* command_line = CommandLine::ForCurrentProcess(); bool enable_translate_settings = command_line->HasSwitch(switches::kEnableTranslateSettings); for (iter = accept_langs_list.begin(); iter != accept_langs_list.end(); ++iter) { // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese // for which the CLD reports zh-CN and zh-TW. std::string accept_lang(*iter); size_t index = iter->find("-"); if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW") accept_lang = iter->substr(0, index); // Special-case English until we resolve bug 36182 properly. // Add English only if the UI language is not English. This will annoy // users of non-English Chrome who can comprehend English until English is // black-listed. // TODO(jungshik): Once we determine that it's safe to remove English from // the default Accept-Language values for most locales, remove this // special-casing. // TODO(hajimehoshi): We can remove this special-casing if the Translate // settings UI is enabled by default. if (!enable_translate_settings && accept_lang == "en" && !is_ui_english) continue; accept_langs_set.insert(accept_lang); } accept_languages_[prefs] = accept_langs_set; } void TranslateAcceptLanguages::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); PrefService* pref_service = content::Source(source).ptr()->GetPrefs(); notification_registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, source); size_t count = accept_languages_.erase(pref_service); // We should know about this profile since we are listening for // notifications on it. DCHECK_EQ(1u, count); PrefChangeRegistrar* pref_change_registrar = pref_change_registrars_[pref_service]; count = pref_change_registrars_.erase(pref_service); DCHECK_EQ(1u, count); delete pref_change_registrar; }