OLD | NEW |
---|---|
(Empty) | |
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_language_list.h" | |
6 | |
7 #include <set> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/json/json_reader.h" | |
11 #include "base/lazy_instance.h" | |
12 #include "base/logging.h" | |
13 #include "base/string_util.h" | |
14 #include "base/values.h" | |
15 #include "chrome/browser/browser_process.h" | |
16 #include "chrome/browser/translate/translate_url_util.h" | |
17 #include "chrome/common/chrome_switches.h" | |
18 #include "googleurl/src/gurl.h" | |
19 #include "net/base/load_flags.h" | |
20 #include "net/base/url_util.h" | |
21 #include "net/http/http_status_code.h" | |
22 #include "net/url_request/url_fetcher.h" | |
23 #include "net/url_request/url_request_status.h" | |
24 | |
25 namespace { | |
26 | |
27 // The default list of languages the Google translation server supports. | |
28 // We use this list until we receive the list that the server exposes. | |
29 // For information, here is the list of languages that Chrome can be run in | |
30 // but that the translation server does not support: | |
31 // am Amharic | |
32 // bn Bengali | |
33 // gu Gujarati | |
34 // kn Kannada | |
35 // ml Malayalam | |
36 // mr Marathi | |
37 // ta Tamil | |
38 // te Telugu | |
39 const char* const kDefaultSupportedLanguages[] = { | |
40 "af", // Afrikaans | |
41 "sq", // Albanian | |
42 "ar", // Arabic | |
43 "be", // Belarusian | |
44 "bg", // Bulgarian | |
45 "ca", // Catalan | |
46 "zh-CN", // Chinese (Simplified) | |
47 "zh-TW", // Chinese (Traditional) | |
48 "hr", // Croatian | |
49 "cs", // Czech | |
50 "da", // Danish | |
51 "nl", // Dutch | |
52 "en", // English | |
53 "eo", // Esperanto | |
54 "et", // Estonian | |
55 "tl", // Filipino | |
56 "fi", // Finnish | |
57 "fr", // French | |
58 "gl", // Galician | |
59 "de", // German | |
60 "el", // Greek | |
61 "ht", // Haitian Creole | |
62 "iw", // Hebrew | |
63 "hi", // Hindi | |
64 "hu", // Hungarian | |
65 "is", // Icelandic | |
66 "id", // Indonesian | |
67 "ga", // Irish | |
68 "it", // Italian | |
69 "ja", // Japanese | |
70 "ko", // Korean | |
71 "lv", // Latvian | |
72 "lt", // Lithuanian | |
73 "mk", // Macedonian | |
74 "ms", // Malay | |
75 "mt", // Maltese | |
76 "no", // Norwegian | |
77 "fa", // Persian | |
78 "pl", // Polish | |
79 "pt", // Portuguese | |
80 "ro", // Romanian | |
81 "ru", // Russian | |
82 "sr", // Serbian | |
83 "sk", // Slovak | |
84 "sl", // Slovenian | |
85 "es", // Spanish | |
86 "sw", // Swahili | |
87 "sv", // Swedish | |
88 "th", // Thai | |
89 "tr", // Turkish | |
90 "uk", // Ukrainian | |
91 "vi", // Vietnamese | |
92 "cy", // Welsh | |
93 "yi", // Yiddish | |
94 }; | |
95 | |
96 // Constant URL string to fetch server supporting language list. | |
97 const char kLanguageListFetchURL[] = | |
98 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; | |
99 | |
100 // Used in kTranslateScriptURL to request supporting languages list including | |
101 // "alpha languages". | |
102 const char kAlphaLanguageQueryName[] = "alpha"; | |
103 const char kAlphaLanguageQueryValue[] = "1"; | |
104 | |
105 // Retry parameter for fetching supporting language list. | |
106 const int kMaxRetryLanguageListFetch = 5; | |
107 | |
108 | |
MAD
2013/05/27 21:34:35
One empty line is enough.
Takashi Toyoshima
2013/05/28 07:35:28
Done.
| |
109 } // namespace | |
110 | |
111 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. | |
112 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl("; | |
113 const char TranslateLanguageList::kTargetLanguagesKey[] = "tl"; | |
114 | |
115 TranslateLanguageList::TranslateLanguageList() { | |
116 // We default to our hard coded list of languages in | |
117 // |kDefaultSupportedLanguages|. This list will be override by a server | |
MAD
2013/05/27 21:34:35
override -> overriden
Takashi Toyoshima
2013/05/28 07:35:28
Done.
| |
118 // providing support langauges list. | |
MAD
2013/05/27 21:34:35
support -> supported
Takashi Toyoshima
2013/05/28 07:35:28
Done.
| |
119 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) | |
120 supported_languages_.insert(kDefaultSupportedLanguages[i]); | |
121 } | |
122 | |
123 TranslateLanguageList::~TranslateLanguageList() { | |
124 url_fetcher_.reset(); | |
MAD
2013/05/27 21:34:35
This is not needed since the destructor of the sco
Takashi Toyoshima
2013/05/28 07:35:28
Done.
| |
125 } | |
126 | |
127 void TranslateLanguageList::OnURLFetchComplete(const net::URLFetcher* source) { | |
128 DCHECK(url_fetcher_.get() == source); | |
129 | |
MAD
2013/05/27 21:34:35
Nit: Maybe remove this empty line.
Takashi Toyoshima
2013/05/28 07:35:28
Done.
| |
130 scoped_ptr<const net::URLFetcher> delete_ptr(url_fetcher_.release()); | |
131 | |
132 if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && | |
133 source->GetResponseCode() == net::HTTP_OK) { | |
134 std::string data; | |
135 source->GetResponseAsString(&data); | |
136 SetSupportedLanguages(data); | |
137 } else { | |
138 // TODO(toyoshim): Try again. http://crbug.com/244202 . | |
139 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; | |
140 } | |
141 } | |
142 | |
143 void TranslateLanguageList::GetSupportedLanguages( | |
144 std::vector<std::string>* languages) { | |
145 DCHECK(languages && languages->empty()); | |
146 std::set<std::string>::const_iterator iter = supported_languages_.begin(); | |
147 for (; iter != supported_languages_.end(); ++iter) | |
148 languages->push_back(*iter); | |
149 } | |
150 | |
151 std::string TranslateLanguageList::GetLanguageCode( | |
152 const std::string& chrome_locale) { | |
153 // Only remove the country code for country specific languages we don't | |
154 // support specifically yet. | |
155 if (IsSupportedLanguage(chrome_locale)) | |
156 return chrome_locale; | |
157 | |
158 size_t hypen_index = chrome_locale.find('-'); | |
159 if (hypen_index == std::string::npos) | |
160 return chrome_locale; | |
161 return chrome_locale.substr(0, hypen_index); | |
162 } | |
163 | |
164 bool TranslateLanguageList::IsSupportedLanguage( | |
165 const std::string& page_language) { | |
166 return supported_languages_.count(page_language) != 0; | |
167 } | |
168 | |
169 void TranslateLanguageList::RequestLanguageList() { | |
170 if (url_fetcher_.get()) | |
171 return; | |
172 | |
173 GURL language_list_fetch_url = GURL(kLanguageListFetchURL); | |
174 language_list_fetch_url = | |
175 TranslateURLUtil::AddHostLocaleToUrl(language_list_fetch_url); | |
176 language_list_fetch_url = | |
177 TranslateURLUtil::AddApiKeyToUrl(language_list_fetch_url); | |
178 | |
179 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
180 if (command_line.HasSwitch(switches::kEnableTranslateAlphaLanguages)) { | |
181 language_list_fetch_url = net::AppendQueryParameter( | |
182 language_list_fetch_url, | |
183 kAlphaLanguageQueryName, | |
184 kAlphaLanguageQueryValue); | |
185 } | |
186 | |
187 VLOG(9) << "Fetch supporting language list from: " | |
188 << language_list_fetch_url.spec().c_str(); | |
189 | |
190 url_fetcher_.reset(net::URLFetcher::Create(1, | |
191 language_list_fetch_url, | |
192 net::URLFetcher::GET, | |
193 this)); | |
194 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
195 net::LOAD_DO_NOT_SAVE_COOKIES); | |
196 url_fetcher_->SetRequestContext(g_browser_process->system_request_context()); | |
197 url_fetcher_->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetch); | |
198 url_fetcher_->Start(); | |
199 } | |
200 | |
201 void TranslateLanguageList::SetSupportedLanguages( | |
202 const std::string& language_list) { | |
203 // The format is: | |
204 // sl({"sl": {"XX": "LanguageName", ...}, "tl": {"XX": "LanguageName", ...}}) | |
205 // Where "sl(" is set in kLanguageListCallbackName | |
206 // and "tl" is kTargetLanguagesKey | |
207 if (!StartsWithASCII(language_list, | |
208 TranslateLanguageList::kLanguageListCallbackName, | |
209 false) || | |
210 !EndsWith(language_list, ")", false)) { | |
211 // We don't have a NOTREACHED here since this can happen in ui_tests, even | |
212 // though the the BrowserMain function won't call us with parameters.ui_task | |
213 // is NULL some tests don't set it, so we must bail here. | |
214 return; | |
215 } | |
216 static const size_t kLanguageListCallbackNameLength = | |
217 strlen(TranslateLanguageList::kLanguageListCallbackName); | |
218 std::string languages_json = language_list.substr( | |
219 kLanguageListCallbackNameLength, | |
220 language_list.size() - kLanguageListCallbackNameLength - 1); | |
221 scoped_ptr<Value> json_value( | |
222 base::JSONReader::Read(languages_json, base::JSON_ALLOW_TRAILING_COMMAS)); | |
223 if (json_value == NULL || !json_value->IsType(Value::TYPE_DICTIONARY)) { | |
224 NOTREACHED(); | |
225 return; | |
226 } | |
227 // The first level dictionary contains two sub-dict, one for source languages | |
228 // and the other for target languages, we want to use the target languages. | |
229 DictionaryValue* language_dict = | |
230 static_cast<DictionaryValue*>(json_value.get()); | |
231 DictionaryValue* target_languages = NULL; | |
232 if (!language_dict->GetDictionary(TranslateLanguageList::kTargetLanguagesKey, | |
233 &target_languages) || | |
234 target_languages == NULL) { | |
235 NOTREACHED(); | |
236 return; | |
237 } | |
238 // Now we can clear our current state... | |
239 supported_languages_.clear(); | |
240 // ... and replace it with the values we just fetched from the server. | |
241 for (DictionaryValue::Iterator iter(*target_languages); | |
242 !iter.IsAtEnd(); | |
243 iter.Advance()) { | |
244 supported_languages_.insert(iter.key()); | |
245 } | |
246 } | |
OLD | NEW |