1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/translate/translate_accept_languages.h" 6 7 #include "base/bind.h" 8 #include "base/prefs/pref_change_registrar.h" 9 #include "base/prefs/pref_service.h" 10 #include "base/strings/string_split.h" 11 #include "base/strings/string_util.h" 12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/translate/translate_manager.h" 16 #include "chrome/common/pref_names.h" 17 #include "components/translate/common/translate_util.h" 18 #include "content/public/browser/notification_source.h" 19 #include "net/url_request/url_fetcher.h" 20 #include "ui/base/l10n/l10n_util.h" 21 22 TranslateAcceptLanguages::TranslateAcceptLanguages() { 23 } 24 25 TranslateAcceptLanguages::~TranslateAcceptLanguages() { 26 } 27 28 // static 29 bool TranslateAcceptLanguages::CanBeAcceptLanguage( 30 const std::string& language) { 31 std::string accept_language = language; 32 translate::ToChromeLanguageSynonym(&accept_language); 33 34 const std::string locale = g_browser_process->GetApplicationLocale(); 35 std::vector<std::string> accept_language_codes; 36 l10n_util::GetAcceptLanguagesForLocale(locale, &accept_language_codes); 37 38 if (std::find(accept_language_codes.begin(), 39 accept_language_codes.end(), 40 accept_language) != accept_language_codes.end()) { 41 return true; 42 } 43 44 return false; 45 } 46 47 bool TranslateAcceptLanguages::IsAcceptLanguage(Profile* profile, 48 const std::string& language) { 49 DCHECK(profile); 50 51 PrefService* pref_service = profile->GetPrefs(); 52 PrefServiceLanguagesMap::const_iterator iter = 53 accept_languages_.find(pref_service); 54 if (iter == accept_languages_.end()) { 55 InitAcceptLanguages(pref_service); 56 // Listen for this profile going away, in which case we would need to clear 57 // the accepted languages for the profile. 58 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 59 content::Source<Profile>(profile)); 60 // Also start listening for changes in the accept languages. 61 DCHECK(pref_change_registrars_.find(pref_service) == 62 pref_change_registrars_.end()); 63 PrefChangeRegistrar* pref_change_registrar = new PrefChangeRegistrar; 64 pref_change_registrar->Init(pref_service); 65 pref_change_registrar->Add( 66 prefs::kAcceptLanguages, 67 base::Bind(&TranslateAcceptLanguages::InitAcceptLanguages, 68 base::Unretained(this), 69 pref_service)); 70 pref_change_registrars_[pref_service] = pref_change_registrar; 71 72 iter = accept_languages_.find(pref_service); 73 } 74 75 std::string accept_language = language; 76 translate::ToChromeLanguageSynonym(&accept_language); 77 return iter->second.count(accept_language) != 0; 78 } 79 80 void TranslateAcceptLanguages::InitAcceptLanguages(PrefService* prefs) { 81 DCHECK(prefs); 82 83 // We have been asked for this profile, build the languages. 84 std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); 85 std::vector<std::string> accept_langs_list; 86 LanguageSet accept_langs_set; 87 base::SplitString(accept_langs_str, ',', &accept_langs_list); 88 std::vector<std::string>::const_iterator iter; 89 90 for (iter = accept_langs_list.begin(); 91 iter != accept_langs_list.end(); ++iter) { 92 // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese 93 // for which the CLD reports zh-CN and zh-TW. 94 std::string accept_lang(*iter); 95 size_t index = iter->find("-"); 96 if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW") 97 accept_lang = iter->substr(0, index); 98 99 accept_langs_set.insert(accept_lang); 100 } 101 accept_languages_[prefs] = accept_langs_set; 102 } 103 104 void TranslateAcceptLanguages::Observe(int type, 105 const content::NotificationSource& source, 106 const content::NotificationDetails& details) { 107 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); 108 109 PrefService* pref_service = 110 content::Source<Profile>(source).ptr()->GetPrefs(); 111 notification_registrar_.Remove(this, 112 chrome::NOTIFICATION_PROFILE_DESTROYED, 113 source); 114 size_t count = accept_languages_.erase(pref_service); 115 // We should know about this profile since we are listening for 116 // notifications on it. 117 DCHECK_EQ(1u, count); 118 PrefChangeRegistrar* pref_change_registrar = 119 pref_change_registrars_[pref_service]; 120 count = pref_change_registrars_.erase(pref_service); 121 DCHECK_EQ(1u, count); 122 delete pref_change_registrar; 123 } 124