OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/translate/translate_language_list.h" | 5 #include "chrome/browser/translate/translate_language_list.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 // Constant URL string to fetch server supporting language list. | 98 // Constant URL string to fetch server supporting language list. |
99 const char kLanguageListFetchURL[] = | 99 const char kLanguageListFetchURL[] = |
100 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; | 100 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; |
101 | 101 |
102 // Used in kTranslateScriptURL to request supporting languages list including | 102 // Used in kTranslateScriptURL to request supporting languages list including |
103 // "alpha languages". | 103 // "alpha languages". |
104 const char kAlphaLanguageQueryName[] = "alpha"; | 104 const char kAlphaLanguageQueryName[] = "alpha"; |
105 const char kAlphaLanguageQueryValue[] = "1"; | 105 const char kAlphaLanguageQueryValue[] = "1"; |
106 | 106 |
107 // Retry parameter for fetching supporting language list. | 107 // Retry parameter for fetching supporting language list. |
108 const int kMaxRetryLanguageListFetch = 5; | 108 const int kMaxRetryLanguageListFetchOn5xx = 5; |
109 | |
110 // Retry parameter for LanguageListFetcher. | |
111 const int kMaxRetryLanguageListFetcher = 16; | |
109 | 112 |
110 // Assign following IDs to URLFetchers so that tests can distinguish each | 113 // Assign following IDs to URLFetchers so that tests can distinguish each |
111 // request in order to simiulate respectively. | 114 // request in order to simiulate respectively. |
112 const int kFetcherIdForLanguageList = 1; | 115 const int kFetcherIdForLanguageList = 1; |
113 const int kFetcherIdForAlphaLanguageList = 2; | 116 const int kFetcherIdForAlphaLanguageList = 2; |
114 | 117 |
115 // Show a message in chrome:://translate-internals Event Logs. | 118 // Show a message in chrome:://translate-internals Event Logs. |
116 void NotifyEvent(int line, const std::string& message) { | 119 void NotifyEvent(int line, const std::string& message) { |
117 TranslateManager* manager = TranslateManager::GetInstance(); | 120 TranslateManager* manager = TranslateManager::GetInstance(); |
118 DCHECK(manager); | 121 DCHECK(manager); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 message += ", " + iter.key(); | 180 message += ", " + iter.key(); |
178 } | 181 } |
179 NotifyEvent(__LINE__, message); | 182 NotifyEvent(__LINE__, message); |
180 } | 183 } |
181 | 184 |
182 } // namespace | 185 } // namespace |
183 | 186 |
184 TranslateLanguageList::LanguageListFetcher::LanguageListFetcher( | 187 TranslateLanguageList::LanguageListFetcher::LanguageListFetcher( |
185 bool include_alpha_languages) | 188 bool include_alpha_languages) |
186 : include_alpha_languages_(include_alpha_languages), | 189 : include_alpha_languages_(include_alpha_languages), |
187 state_(IDLE) { | 190 state_(IDLE), |
191 retry_count_(0) { | |
188 } | 192 } |
189 | 193 |
190 TranslateLanguageList::LanguageListFetcher::~LanguageListFetcher() { | 194 TranslateLanguageList::LanguageListFetcher::~LanguageListFetcher() { |
191 } | 195 } |
192 | 196 |
193 bool TranslateLanguageList::LanguageListFetcher::Request( | 197 bool TranslateLanguageList::LanguageListFetcher::Request( |
194 const TranslateLanguageList::LanguageListFetcher::Callback& callback) { | 198 const TranslateLanguageList::LanguageListFetcher::Callback& callback) { |
195 // This function is not supporsed to be called before previous operaion is not | 199 // This function is not supposed to be called before previous operaion is not |
196 // finished. | 200 // finished. |
197 if (state_ == REQUESTING) { | 201 if (state_ == REQUESTING) { |
198 NOTREACHED(); | 202 NOTREACHED(); |
199 return false; | 203 return false; |
200 } | 204 } |
201 | 205 |
206 if (retry_count_ >= kMaxRetryLanguageListFetcher) { | |
207 NotifyEvent(__LINE__, "Request is omitted due to retry limit"); | |
208 return false; | |
209 } | |
210 retry_count_++; | |
211 | |
202 state_ = REQUESTING; | 212 state_ = REQUESTING; |
203 callback_ = callback; | 213 callback_ = callback; |
204 | 214 |
205 GURL url = GURL(kLanguageListFetchURL); | 215 GURL url = GURL(kLanguageListFetchURL); |
206 url = TranslateURLUtil::AddHostLocaleToUrl(url); | 216 url = TranslateURLUtil::AddHostLocaleToUrl(url); |
207 url = TranslateURLUtil::AddApiKeyToUrl(url); | 217 url = TranslateURLUtil::AddApiKeyToUrl(url); |
208 if (include_alpha_languages_) { | 218 if (include_alpha_languages_) { |
209 url = net::AppendQueryParameter(url, | 219 url = net::AppendQueryParameter(url, |
210 kAlphaLanguageQueryName, | 220 kAlphaLanguageQueryName, |
211 kAlphaLanguageQueryValue); | 221 kAlphaLanguageQueryValue); |
212 } | 222 } |
213 | 223 |
214 std::string message = base::StringPrintf( | 224 std::string message = base::StringPrintf( |
215 "%s list fetch starts (URL: %s)", | 225 "%s list fetch starts (URL: %s)", |
216 include_alpha_languages_ ? "Language" : "Alpha language", | 226 include_alpha_languages_ ? "Language" : "Alpha language", |
217 url.spec().c_str()); | 227 url.spec().c_str()); |
218 NotifyEvent(__LINE__, message); | 228 NotifyEvent(__LINE__, message); |
219 | 229 |
220 fetcher_.reset(net::URLFetcher::Create( | 230 fetcher_.reset(net::URLFetcher::Create( |
221 include_alpha_languages_ ? kFetcherIdForAlphaLanguageList : | 231 include_alpha_languages_ ? kFetcherIdForAlphaLanguageList : |
222 kFetcherIdForLanguageList, | 232 kFetcherIdForLanguageList, |
223 url, | 233 url, |
224 net::URLFetcher::GET, | 234 net::URLFetcher::GET, |
225 this)); | 235 this)); |
226 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 236 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
227 net::LOAD_DO_NOT_SAVE_COOKIES); | 237 net::LOAD_DO_NOT_SAVE_COOKIES); |
228 fetcher_->SetRequestContext(g_browser_process->system_request_context()); | 238 fetcher_->SetRequestContext(g_browser_process->system_request_context()); |
229 fetcher_->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetch); | 239 // Set retry parameter for HTTP status code 5xx. This doesn't work against |
240 // 106 (net::ERR_INTERNET_DISCONNECTED) and so on. | |
241 // TranslateLanguageList handles network status, and implements retry. | |
242 fetcher_->SetMaxRetriesOn5xx(kMaxRetryLanguageListFetchOn5xx); | |
230 fetcher_->Start(); | 243 fetcher_->Start(); |
231 | 244 |
232 return true; | 245 return true; |
233 } | 246 } |
234 | 247 |
235 void TranslateLanguageList::LanguageListFetcher::OnURLFetchComplete( | 248 void TranslateLanguageList::LanguageListFetcher::OnURLFetchComplete( |
236 const net::URLFetcher* source) { | 249 const net::URLFetcher* source) { |
237 DCHECK(fetcher_.get() == source); | 250 DCHECK(fetcher_.get() == source); |
238 | 251 |
239 std::string data; | 252 std::string data; |
240 if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && | 253 if (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && |
241 source->GetResponseCode() == net::HTTP_OK) { | 254 source->GetResponseCode() == net::HTTP_OK) { |
242 state_ = COMPLETED; | 255 state_ = COMPLETED; |
243 source->GetResponseAsString(&data); | 256 source->GetResponseAsString(&data); |
244 std::string message = base::StringPrintf( | 257 std::string message = base::StringPrintf( |
245 "%s list is updated", | 258 "%s list is updated", |
246 include_alpha_languages_ ? "Alpha language" : "Language"); | 259 include_alpha_languages_ ? "Alpha language" : "Language"); |
247 NotifyEvent(__LINE__, message); | 260 NotifyEvent(__LINE__, message); |
248 } else { | 261 } else { |
249 state_ = FAILED; | 262 state_ = FAILED; |
250 std::string message = base::StringPrintf( | 263 std::string message = base::StringPrintf( |
251 "Failed to Fetch languages from: %s", | 264 "Failed to Fetch languages from: %s", |
252 source->GetURL().spec().c_str()); | 265 source->GetURL().spec().c_str()); |
253 NotifyEvent(__LINE__, message); | 266 NotifyEvent(__LINE__, message); |
254 } | 267 } |
255 | 268 |
269 // Transfer URLFetcher's ownership before invoking a callback. | |
256 scoped_ptr<const net::URLFetcher> delete_ptr(fetcher_.release()); | 270 scoped_ptr<const net::URLFetcher> delete_ptr(fetcher_.release()); |
257 callback_.Run(include_alpha_languages_, state_ == COMPLETED, data); | 271 callback_.Run(include_alpha_languages_, state_ == COMPLETED, data); |
258 } | 272 } |
259 | 273 |
260 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. | 274 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. |
261 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl("; | 275 const char TranslateLanguageList::kLanguageListCallbackName[] = "sl("; |
262 const char TranslateLanguageList::kTargetLanguagesKey[] = "tl"; | 276 const char TranslateLanguageList::kTargetLanguagesKey[] = "tl"; |
263 | 277 |
264 TranslateLanguageList::TranslateLanguageList() { | 278 TranslateLanguageList::TranslateLanguageList() { |
265 // We default to our hard coded list of languages in | 279 // We default to our hard coded list of languages in |
266 // |kDefaultSupportedLanguages|. This list will be overriden by a server | 280 // |kDefaultSupportedLanguages|. This list will be overriden by a server |
267 // providing supported langauges list. | 281 // providing supported langauges list. |
268 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) | 282 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) |
269 supported_languages_.insert(kDefaultSupportedLanguages[i]); | 283 supported_languages_.insert(kDefaultSupportedLanguages[i]); |
270 UpdateSupportedLanguages(); | 284 UpdateSupportedLanguages(); |
271 | 285 |
272 language_list_fetcher_.reset(new LanguageListFetcher(false)); | 286 language_list_fetcher_.reset(new LanguageListFetcher(false)); |
273 alpha_language_list_fetcher_.reset(new LanguageListFetcher(true)); | 287 alpha_language_list_fetcher_.reset(new LanguageListFetcher(true)); |
288 | |
289 resource_request_allowed_notifier_.Init(this); | |
274 } | 290 } |
275 | 291 |
276 TranslateLanguageList::~TranslateLanguageList() { | 292 TranslateLanguageList::~TranslateLanguageList() { |
277 } | 293 } |
278 | 294 |
279 void TranslateLanguageList::GetSupportedLanguages( | 295 void TranslateLanguageList::GetSupportedLanguages( |
280 std::vector<std::string>* languages) { | 296 std::vector<std::string>* languages) { |
281 DCHECK(languages && languages->empty()); | 297 DCHECK(languages && languages->empty()); |
282 std::set<std::string>::const_iterator iter = all_supported_languages_.begin(); | 298 std::set<std::string>::const_iterator iter = all_supported_languages_.begin(); |
283 for (; iter != all_supported_languages_.end(); ++iter) | 299 for (; iter != all_supported_languages_.end(); ++iter) |
284 languages->push_back(*iter); | 300 languages->push_back(*iter); |
301 | |
302 // Update language lists if they are not updated after Chrome was launched | |
303 // for later requests. | |
304 if (language_list_fetcher_.get() || alpha_language_list_fetcher_.get()) | |
305 RequestLanguageList(); | |
285 } | 306 } |
286 | 307 |
287 std::string TranslateLanguageList::GetLanguageCode( | 308 std::string TranslateLanguageList::GetLanguageCode( |
288 const std::string& chrome_locale) { | 309 const std::string& chrome_locale) { |
289 // Only remove the country code for country specific languages we don't | 310 // Only remove the country code for country specific languages we don't |
290 // support specifically yet. | 311 // support specifically yet. |
291 if (IsSupportedLanguage(chrome_locale)) | 312 if (IsSupportedLanguage(chrome_locale)) |
292 return chrome_locale; | 313 return chrome_locale; |
293 | 314 |
294 size_t hypen_index = chrome_locale.find('-'); | 315 size_t hypen_index = chrome_locale.find('-'); |
295 if (hypen_index == std::string::npos) | 316 if (hypen_index == std::string::npos) |
296 return chrome_locale; | 317 return chrome_locale; |
297 return chrome_locale.substr(0, hypen_index); | 318 return chrome_locale.substr(0, hypen_index); |
298 } | 319 } |
299 | 320 |
300 bool TranslateLanguageList::IsSupportedLanguage(const std::string& language) { | 321 bool TranslateLanguageList::IsSupportedLanguage(const std::string& language) { |
301 return all_supported_languages_.count(language) != 0; | 322 return all_supported_languages_.count(language) != 0; |
302 } | 323 } |
303 | 324 |
304 bool TranslateLanguageList::IsAlphaLanguage(const std::string& language) { | 325 bool TranslateLanguageList::IsAlphaLanguage(const std::string& language) { |
305 // |language| should exist only in the alpha language list. | 326 // |language| should exist only in the alpha language list. |
306 return supported_alpha_languages_.count(language) != 0 && | 327 return supported_alpha_languages_.count(language) != 0 && |
307 supported_languages_.count(language) == 0; | 328 supported_languages_.count(language) == 0; |
308 } | 329 } |
309 | 330 |
310 void TranslateLanguageList::RequestLanguageList() { | 331 void TranslateLanguageList::RequestLanguageList() { |
332 // If resource requests are not allowed, we'll get a callback when they are. | |
333 if (resource_request_allowed_notifier_.ResourceRequestsAllowed()) | |
334 OnResourceRequestsAllowed(); | |
335 } | |
336 | |
337 void TranslateLanguageList::OnResourceRequestsAllowed() { | |
311 if (language_list_fetcher_.get() && | 338 if (language_list_fetcher_.get() && |
312 (language_list_fetcher_->state() == LanguageListFetcher::IDLE || | 339 (language_list_fetcher_->state() == LanguageListFetcher::IDLE || |
313 language_list_fetcher_->state() == LanguageListFetcher::FAILED)) { | 340 language_list_fetcher_->state() == LanguageListFetcher::FAILED)) { |
314 language_list_fetcher_->Request( | 341 language_list_fetcher_->Request( |
315 base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete, | 342 base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete, |
316 base::Unretained(this))); | 343 base::Unretained(this))); |
317 } | 344 } |
318 | 345 |
319 if (alpha_language_list_fetcher_.get() && | 346 if (alpha_language_list_fetcher_.get() && |
320 (alpha_language_list_fetcher_->state() == LanguageListFetcher::IDLE || | 347 (alpha_language_list_fetcher_->state() == LanguageListFetcher::IDLE || |
321 alpha_language_list_fetcher_->state() == LanguageListFetcher::FAILED)) { | 348 alpha_language_list_fetcher_->state() == LanguageListFetcher::FAILED)) { |
322 alpha_language_list_fetcher_->Request( | 349 alpha_language_list_fetcher_->Request( |
323 base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete, | 350 base::Bind(&TranslateLanguageList::OnLanguageListFetchComplete, |
324 base::Unretained(this))); | 351 base::Unretained(this))); |
325 } | 352 } |
326 } | 353 } |
327 | 354 |
328 void TranslateLanguageList::OnLanguageListFetchComplete( | 355 void TranslateLanguageList::OnLanguageListFetchComplete( |
329 bool include_alpha_languages, | 356 bool include_alpha_languages, |
330 bool success, | 357 bool success, |
331 const std::string& data) { | 358 const std::string& data) { |
332 if (!success) | 359 if (!success) { |
360 resource_request_allowed_notifier_.ResourceRequestsAllowed(); | |
361 // Since it fails just now, omit to schedule resource requests if | |
362 // ResourceRequestAllowedNotifier think it's ready. Otherwise, a callback | |
363 // will be invoked later to reuest resources again. | |
364 // The LanguageListFetcher has a limit |kMaxRetryLanguageListFetcher| and | |
365 // aborts re-try not to invoke OnLanguageListFetchComplete anymore if it's | |
366 // asked to re-try too many times. | |
367 to invoke OnLanguageListFetchComplete. | |
Alexei Svitkine (slow)
2013/06/14 22:06:05
Nit: remove this line?
Takashi Toyoshima
2013/06/17 07:20:04
Sorry for poor nit...
Removed.
| |
333 return; | 368 return; |
369 } | |
334 | 370 |
335 if (!include_alpha_languages) { | 371 if (!include_alpha_languages) { |
336 SetSupportedLanguages(data, &supported_languages_); | 372 SetSupportedLanguages(data, &supported_languages_); |
337 language_list_fetcher_.reset(); | 373 language_list_fetcher_.reset(); |
338 } else { | 374 } else { |
339 SetSupportedLanguages(data, &supported_alpha_languages_); | 375 SetSupportedLanguages(data, &supported_alpha_languages_); |
340 alpha_language_list_fetcher_.reset(); | 376 alpha_language_list_fetcher_.reset(); |
341 } | 377 } |
342 UpdateSupportedLanguages(); | 378 UpdateSupportedLanguages(); |
343 } | 379 } |
344 | 380 |
345 void TranslateLanguageList::UpdateSupportedLanguages() { | 381 void TranslateLanguageList::UpdateSupportedLanguages() { |
346 all_supported_languages_.clear(); | 382 all_supported_languages_.clear(); |
347 std::set<std::string>::const_iterator iter; | 383 std::set<std::string>::const_iterator iter; |
348 for (iter = supported_languages_.begin(); | 384 for (iter = supported_languages_.begin(); |
349 iter != supported_languages_.end(); | 385 iter != supported_languages_.end(); |
350 ++iter) | 386 ++iter) |
351 all_supported_languages_.insert(*iter); | 387 all_supported_languages_.insert(*iter); |
352 for (iter = supported_alpha_languages_.begin(); | 388 for (iter = supported_alpha_languages_.begin(); |
353 iter != supported_alpha_languages_.end(); | 389 iter != supported_alpha_languages_.end(); |
354 ++iter) | 390 ++iter) |
355 all_supported_languages_.insert(*iter); | 391 all_supported_languages_.insert(*iter); |
356 } | 392 } |
OLD | NEW |