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