OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_manager.h" | 5 #include "chrome/browser/translate/translate_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/json/json_reader.h" | |
11 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
12 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
13 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
14 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
15 #include "base/string_util.h" | 14 #include "base/string_util.h" |
16 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
17 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
18 #include "base/values.h" | |
19 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
20 #include "chrome/browser/infobars/infobar_service.h" | 18 #include "chrome/browser/infobars/infobar_service.h" |
21 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/browser/tab_contents/language_state.h" | 20 #include "chrome/browser/tab_contents/language_state.h" |
23 #include "chrome/browser/tab_contents/tab_util.h" | 21 #include "chrome/browser/tab_contents/tab_util.h" |
24 #include "chrome/browser/translate/page_translated_details.h" | 22 #include "chrome/browser/translate/page_translated_details.h" |
25 #include "chrome/browser/translate/translate_infobar_delegate.h" | 23 #include "chrome/browser/translate/translate_infobar_delegate.h" |
24 #include "chrome/browser/translate/translate_language_list.h" | |
26 #include "chrome/browser/translate/translate_manager_metrics.h" | 25 #include "chrome/browser/translate/translate_manager_metrics.h" |
27 #include "chrome/browser/translate/translate_prefs.h" | 26 #include "chrome/browser/translate/translate_prefs.h" |
28 #include "chrome/browser/translate/translate_tab_helper.h" | 27 #include "chrome/browser/translate/translate_tab_helper.h" |
28 #include "chrome/browser/translate/translate_url_util.h" | |
29 #include "chrome/browser/ui/browser.h" | 29 #include "chrome/browser/ui/browser.h" |
30 #include "chrome/browser/ui/browser_finder.h" | 30 #include "chrome/browser/ui/browser_finder.h" |
31 #include "chrome/browser/ui/browser_tabstrip.h" | 31 #include "chrome/browser/ui/browser_tabstrip.h" |
32 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 32 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
33 #include "chrome/common/chrome_notification_types.h" | 33 #include "chrome/common/chrome_notification_types.h" |
34 #include "chrome/common/chrome_switches.h" | 34 #include "chrome/common/chrome_switches.h" |
35 #include "chrome/common/pref_names.h" | 35 #include "chrome/common/pref_names.h" |
36 #include "chrome/common/render_messages.h" | 36 #include "chrome/common/render_messages.h" |
37 #include "chrome/common/translate_errors.h" | 37 #include "chrome/common/translate_errors.h" |
38 #include "chrome/common/url_constants.h" | 38 #include "chrome/common/url_constants.h" |
(...skipping 21 matching lines...) Expand all Loading... | |
60 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" | 60 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" |
61 #include "extensions/common/constants.h" | 61 #include "extensions/common/constants.h" |
62 #endif | 62 #endif |
63 | 63 |
64 using content::NavigationController; | 64 using content::NavigationController; |
65 using content::NavigationEntry; | 65 using content::NavigationEntry; |
66 using content::WebContents; | 66 using content::WebContents; |
67 | 67 |
68 namespace { | 68 namespace { |
69 | 69 |
70 // The default list of languages the Google translation server supports. | |
71 // We use this list until we receive the list that the server exposes. | |
72 // For information, here is the list of languages that Chrome can be run in | |
73 // but that the translation server does not support: | |
74 // am Amharic | |
75 // bn Bengali | |
76 // gu Gujarati | |
77 // kn Kannada | |
78 // ml Malayalam | |
79 // mr Marathi | |
80 // ta Tamil | |
81 // te Telugu | |
82 const char* const kDefaultSupportedLanguages[] = { | |
83 "af", // Afrikaans | |
84 "sq", // Albanian | |
85 "ar", // Arabic | |
86 "be", // Belarusian | |
87 "bg", // Bulgarian | |
88 "ca", // Catalan | |
89 "zh-CN", // Chinese (Simplified) | |
90 "zh-TW", // Chinese (Traditional) | |
91 "hr", // Croatian | |
92 "cs", // Czech | |
93 "da", // Danish | |
94 "nl", // Dutch | |
95 "en", // English | |
96 "eo", // Esperanto | |
97 "et", // Estonian | |
98 "tl", // Filipino | |
99 "fi", // Finnish | |
100 "fr", // French | |
101 "gl", // Galician | |
102 "de", // German | |
103 "el", // Greek | |
104 "ht", // Haitian Creole | |
105 "iw", // Hebrew | |
106 "hi", // Hindi | |
107 "hu", // Hungarian | |
108 "is", // Icelandic | |
109 "id", // Indonesian | |
110 "ga", // Irish | |
111 "it", // Italian | |
112 "ja", // Japanese | |
113 "ko", // Korean | |
114 "lv", // Latvian | |
115 "lt", // Lithuanian | |
116 "mk", // Macedonian | |
117 "ms", // Malay | |
118 "mt", // Maltese | |
119 "no", // Norwegian | |
120 "fa", // Persian | |
121 "pl", // Polish | |
122 "pt", // Portuguese | |
123 "ro", // Romanian | |
124 "ru", // Russian | |
125 "sr", // Serbian | |
126 "sk", // Slovak | |
127 "sl", // Slovenian | |
128 "es", // Spanish | |
129 "sw", // Swahili | |
130 "sv", // Swedish | |
131 "th", // Thai | |
132 "tr", // Turkish | |
133 "uk", // Ukrainian | |
134 "vi", // Vietnamese | |
135 "cy", // Welsh | |
136 "yi", // Yiddish | |
137 }; | |
138 | |
139 const char kTranslateScriptURL[] = | 70 const char kTranslateScriptURL[] = |
140 "https://translate.google.com/translate_a/element.js"; | 71 "https://translate.google.com/translate_a/element.js"; |
141 const char kTranslateScriptHeader[] = "Google-Translate-Element-Mode: library"; | 72 const char kTranslateScriptHeader[] = "Google-Translate-Element-Mode: library"; |
142 const char kReportLanguageDetectionErrorURL[] = | 73 const char kReportLanguageDetectionErrorURL[] = |
143 "https://translate.google.com/translate_error?client=cr&action=langidc"; | 74 "https://translate.google.com/translate_error?client=cr&action=langidc"; |
144 const char kLanguageListFetchURL[] = | |
145 "https://translate.googleapis.com/translate_a/l?client=chrome&cb=sl"; | |
146 | |
147 // Used in kTranslateScriptURL to request supporting languages list including | |
148 // "alpha languages". | |
149 const char kAlphaLanguageQueryName[] = "alpha"; | |
150 const char kAlphaLanguageQueryValue[] = "1"; | |
151 | |
152 // Used in all translate URLs to specify API Key. | |
153 const char kApiKeyName[] = "key"; | |
154 | 75 |
155 // Used in kTranslateScriptURL to specify a callback function name. | 76 // Used in kTranslateScriptURL to specify a callback function name. |
156 const char kCallbackQueryName[] = "cb"; | 77 const char kCallbackQueryName[] = "cb"; |
157 const char kCallbackQueryValue[] = | 78 const char kCallbackQueryValue[] = |
158 "cr.googleTranslate.onTranslateElementLoad"; | 79 "cr.googleTranslate.onTranslateElementLoad"; |
159 | 80 |
160 // Used in kTranslateScriptURL and kLanguageListFetchURL to specify the | |
161 // application locale. | |
162 const char kHostLocaleQueryName[] = "hl"; | |
163 | |
164 // Used in kReportLanguageDetectionErrorURL to specify the original page | 81 // Used in kReportLanguageDetectionErrorURL to specify the original page |
165 // language. | 82 // language. |
166 const char kSourceLanguageQueryName[] = "sl"; | 83 const char kSourceLanguageQueryName[] = "sl"; |
167 | 84 |
168 // Used in kReportLanguageDetectionErrorURL to specify the page URL. | 85 // Used in kReportLanguageDetectionErrorURL to specify the page URL. |
169 const char kUrlQueryName[] = "u"; | 86 const char kUrlQueryName[] = "u"; |
170 | 87 |
171 // The delay in ms that we'll wait to check if a page has finished loading | 88 // The delay in ms that we'll wait to check if a page has finished loading |
172 // before attempting a translation. | 89 // before attempting a translation. |
173 const int kTranslateLoadCheckDelayMs = 150; | 90 const int kTranslateLoadCheckDelayMs = 150; |
174 | 91 |
175 // The maximum number of attempts we'll do to see if the page has finshed | 92 // The maximum number of attempts we'll do to see if the page has finshed |
176 // loading before giving up the translation | 93 // loading before giving up the translation |
177 const int kMaxTranslateLoadCheckAttempts = 20; | 94 const int kMaxTranslateLoadCheckAttempts = 20; |
178 | 95 |
179 const int kMaxRetryLanguageListFetch = 5; | |
180 const int kTranslateScriptExpirationDelayDays = 1; | 96 const int kTranslateScriptExpirationDelayDays = 1; |
181 | 97 |
182 GURL AddApiKeyToUrl(const GURL& url) { | |
183 return net::AppendQueryParameter(url, kApiKeyName, google_apis::GetAPIKey()); | |
184 } | |
185 | |
186 GURL AddHostLocaleToUrl(const GURL& url) { | |
187 return net::AppendQueryParameter( | |
188 url, | |
189 kHostLocaleQueryName, | |
190 TranslateManager::GetLanguageCode( | |
191 g_browser_process->GetApplicationLocale())); | |
192 } | |
193 | |
194 } // namespace | 98 } // namespace |
195 | 99 |
196 // This must be kept in sync with the &cb= value in the kLanguageListFetchURL. | |
197 const char TranslateManager::kLanguageListCallbackName[] = "sl("; | |
198 const char TranslateManager::kTargetLanguagesKey[] = "tl"; | |
199 | |
200 // static | |
201 base::LazyInstance<std::set<std::string> > | |
202 TranslateManager::supported_languages_ = LAZY_INSTANCE_INITIALIZER; | |
203 | |
204 TranslateManager::~TranslateManager() { | 100 TranslateManager::~TranslateManager() { |
205 weak_method_factory_.InvalidateWeakPtrs(); | 101 weak_method_factory_.InvalidateWeakPtrs(); |
206 } | 102 } |
207 | 103 |
208 // static | 104 // static |
209 TranslateManager* TranslateManager::GetInstance() { | 105 TranslateManager* TranslateManager::GetInstance() { |
210 return Singleton<TranslateManager>::get(); | 106 return Singleton<TranslateManager>::get(); |
211 } | 107 } |
212 | 108 |
213 // static | 109 // static |
214 bool TranslateManager::IsTranslatableURL(const GURL& url) { | 110 bool TranslateManager::IsTranslatableURL(const GURL& url) { |
215 // A URLs is translatable unless it is one of the following: | 111 // A URLs is translatable unless it is one of the following: |
216 // - empty (can happen for popups created with window.open("")) | 112 // - empty (can happen for popups created with window.open("")) |
217 // - an internal URL (chrome:// and others) | 113 // - an internal URL (chrome:// and others) |
218 // - the devtools (which is considered UI) | 114 // - the devtools (which is considered UI) |
219 // - Chrome OS file manager extension | 115 // - Chrome OS file manager extension |
220 // - an FTP page (as FTP pages tend to have long lists of filenames that may | 116 // - an FTP page (as FTP pages tend to have long lists of filenames that may |
221 // confuse the CLD) | 117 // confuse the CLD) |
222 return !url.is_empty() && | 118 return !url.is_empty() && |
223 !url.SchemeIs(chrome::kChromeUIScheme) && | 119 !url.SchemeIs(chrome::kChromeUIScheme) && |
224 !url.SchemeIs(chrome::kChromeDevToolsScheme) && | 120 !url.SchemeIs(chrome::kChromeDevToolsScheme) && |
225 #ifdef FILE_MANAGER_EXTENSION | 121 #ifdef FILE_MANAGER_EXTENSION |
226 !(url.SchemeIs(extensions::kExtensionScheme) && | 122 !(url.SchemeIs(extensions::kExtensionScheme) && |
227 url.DomainIs(kFileBrowserDomain)) && | 123 url.DomainIs(kFileBrowserDomain)) && |
228 #endif | 124 #endif |
229 !url.SchemeIs(chrome::kFtpScheme); | 125 !url.SchemeIs(chrome::kFtpScheme); |
230 } | 126 } |
231 | 127 |
232 // static | |
233 void TranslateManager::SetSupportedLanguages(const std::string& language_list) { | |
234 // The format is: | |
235 // sl({"sl": {"XX": "LanguageName", ...}, "tl": {"XX": "LanguageName", ...}}) | |
236 // Where "sl(" is set in kLanguageListCallbackName | |
237 // and "tl" is kTargetLanguagesKey | |
238 if (!StartsWithASCII(language_list, kLanguageListCallbackName, false) || | |
239 !EndsWith(language_list, ")", false)) { | |
240 // We don't have a NOTREACHED here since this can happen in ui_tests, even | |
241 // though the the BrowserMain function won't call us with parameters.ui_task | |
242 // is NULL some tests don't set it, so we must bail here. | |
243 return; | |
244 } | |
245 static const size_t kLanguageListCallbackNameLength = | |
246 strlen(kLanguageListCallbackName); | |
247 std::string languages_json = language_list.substr( | |
248 kLanguageListCallbackNameLength, | |
249 language_list.size() - kLanguageListCallbackNameLength - 1); | |
250 scoped_ptr<Value> json_value( | |
251 base::JSONReader::Read(languages_json, base::JSON_ALLOW_TRAILING_COMMAS)); | |
252 if (json_value == NULL || !json_value->IsType(Value::TYPE_DICTIONARY)) { | |
253 NOTREACHED(); | |
254 return; | |
255 } | |
256 // The first level dictionary contains two sub-dict, one for source languages | |
257 // and the other for target languages, we want to use the target languages. | |
258 DictionaryValue* language_dict = | |
259 static_cast<DictionaryValue*>(json_value.get()); | |
260 DictionaryValue* target_languages = NULL; | |
261 if (!language_dict->GetDictionary(kTargetLanguagesKey, &target_languages) || | |
262 target_languages == NULL) { | |
263 NOTREACHED(); | |
264 return; | |
265 } | |
266 // Now we can clear our current state... | |
267 std::set<std::string>* supported_languages = supported_languages_.Pointer(); | |
268 supported_languages->clear(); | |
269 // ... and replace it with the values we just fetched from the server. | |
270 for (DictionaryValue::Iterator iter(*target_languages); !iter.IsAtEnd(); | |
271 iter.Advance()) { | |
272 supported_languages_.Pointer()->insert(iter.key()); | |
273 } | |
274 } | |
275 | |
276 // static | |
277 void TranslateManager::InitSupportedLanguages() { | |
278 // If our list of supported languages have not been set yet, we default | |
279 // to our hard coded list of languages in kDefaultSupportedLanguages. | |
280 if (supported_languages_.Pointer()->empty()) { | |
281 for (size_t i = 0; i < arraysize(kDefaultSupportedLanguages); ++i) | |
282 supported_languages_.Pointer()->insert(kDefaultSupportedLanguages[i]); | |
283 } | |
284 } | |
285 | |
286 // static | |
287 void TranslateManager::GetSupportedLanguages( | |
288 std::vector<std::string>* languages) { | |
289 DCHECK(languages && languages->empty()); | |
290 InitSupportedLanguages(); | |
291 std::set<std::string>* supported_languages = supported_languages_.Pointer(); | |
292 std::set<std::string>::const_iterator iter = supported_languages->begin(); | |
293 for (; iter != supported_languages->end(); ++iter) | |
294 languages->push_back(*iter); | |
295 } | |
296 | |
297 // static | |
298 std::string TranslateManager::GetLanguageCode( | |
299 const std::string& chrome_locale) { | |
300 // Only remove the country code for country specific languages we don't | |
301 // support specifically yet. | |
302 if (IsSupportedLanguage(chrome_locale)) | |
303 return chrome_locale; | |
304 | |
305 size_t hypen_index = chrome_locale.find('-'); | |
306 if (hypen_index == std::string::npos) | |
307 return chrome_locale; | |
308 return chrome_locale.substr(0, hypen_index); | |
309 } | |
310 | |
311 // static | |
312 bool TranslateManager::IsSupportedLanguage(const std::string& page_language) { | |
313 InitSupportedLanguages(); | |
314 return supported_languages_.Pointer()->count(page_language) != 0; | |
315 } | |
316 | |
317 void TranslateManager::Observe(int type, | 128 void TranslateManager::Observe(int type, |
318 const content::NotificationSource& source, | 129 const content::NotificationSource& source, |
319 const content::NotificationDetails& details) { | 130 const content::NotificationDetails& details) { |
320 switch (type) { | 131 switch (type) { |
321 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | 132 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
322 NavigationController* controller = | 133 NavigationController* controller = |
323 content::Source<NavigationController>(source).ptr(); | 134 content::Source<NavigationController>(source).ptr(); |
324 content::LoadCommittedDetails* load_details = | 135 content::LoadCommittedDetails* load_details = |
325 content::Details<content::LoadCommittedDetails>(details).ptr(); | 136 content::Details<content::LoadCommittedDetails>(details).ptr(); |
326 NavigationEntry* entry = controller->GetActiveEntry(); | 137 NavigationEntry* entry = controller->GetActiveEntry(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 DCHECK(count == 1u); | 227 DCHECK(count == 1u); |
417 delete pref_change_registrar; | 228 delete pref_change_registrar; |
418 break; | 229 break; |
419 } | 230 } |
420 default: | 231 default: |
421 NOTREACHED(); | 232 NOTREACHED(); |
422 } | 233 } |
423 } | 234 } |
424 | 235 |
425 void TranslateManager::OnURLFetchComplete(const net::URLFetcher* source) { | 236 void TranslateManager::OnURLFetchComplete(const net::URLFetcher* source) { |
426 if (translate_script_request_pending_.get() != source && | 237 if (translate_script_request_pending_.get() != source) { |
427 language_list_request_pending_.get() != source) { | |
428 // Looks like crash on Mac is possibly caused with callback entering here | 238 // Looks like crash on Mac is possibly caused with callback entering here |
429 // with unknown fetcher when network is refreshed. | 239 // with unknown fetcher when network is refreshed. |
430 scoped_ptr<const net::URLFetcher> delete_ptr(source); | 240 scoped_ptr<const net::URLFetcher> delete_ptr(source); |
431 return; | 241 return; |
432 } | 242 } |
433 | 243 |
434 bool error = | 244 bool error = |
435 (source->GetStatus().status() != net::URLRequestStatus::SUCCESS || | 245 source->GetStatus().status() != net::URLRequestStatus::SUCCESS || |
436 source->GetResponseCode() != net::HTTP_OK); | 246 source->GetResponseCode() != net::HTTP_OK; |
437 if (translate_script_request_pending_.get() == source) { | 247 if (translate_script_request_pending_.get() == source) { |
438 scoped_ptr<const net::URLFetcher> delete_ptr( | 248 scoped_ptr<const net::URLFetcher> delete_ptr( |
439 translate_script_request_pending_.release()); | 249 translate_script_request_pending_.release()); |
440 if (!error) { | 250 if (!error) { |
441 base::StringPiece str = ResourceBundle::GetSharedInstance(). | 251 base::StringPiece str = ResourceBundle::GetSharedInstance(). |
442 GetRawDataResource(IDR_TRANSLATE_JS); | 252 GetRawDataResource(IDR_TRANSLATE_JS); |
443 DCHECK(translate_script_.empty()); | 253 DCHECK(translate_script_.empty()); |
444 str.CopyToString(&translate_script_); | 254 str.CopyToString(&translate_script_); |
445 std::string argument = "('"; | 255 std::string argument = "('"; |
446 std::string api_key = google_apis::GetAPIKey(); | 256 std::string api_key = google_apis::GetAPIKey(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 ShortcutConfig(), | 298 ShortcutConfig(), |
489 request.source_lang, | 299 request.source_lang, |
490 request.target_lang); | 300 request.target_lang); |
491 } else { | 301 } else { |
492 // Translate the page. | 302 // Translate the page. |
493 DoTranslatePage(web_contents, translate_script_, | 303 DoTranslatePage(web_contents, translate_script_, |
494 request.source_lang, request.target_lang); | 304 request.source_lang, request.target_lang); |
495 } | 305 } |
496 } | 306 } |
497 pending_requests_.clear(); | 307 pending_requests_.clear(); |
498 } else { // if (translate_script_request_pending_.get() == source) | |
499 scoped_ptr<const net::URLFetcher> delete_ptr( | |
500 language_list_request_pending_.release()); | |
501 if (!error) { | |
502 std::string data; | |
503 source->GetResponseAsString(&data); | |
504 SetSupportedLanguages(data); | |
505 } else { | |
506 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; | |
507 } | |
508 } | 308 } |
509 } | 309 } |
510 | 310 |
511 TranslateManager::TranslateManager() | 311 TranslateManager::TranslateManager() |
512 : weak_method_factory_(this), | 312 : weak_method_factory_(this), |
513 translate_script_expiration_delay_(base::TimeDelta::FromDays( | 313 translate_script_expiration_delay_(base::TimeDelta::FromDays( |
514 kTranslateScriptExpirationDelayDays)), | 314 kTranslateScriptExpirationDelayDays)), |
515 max_reload_check_attempts_(kMaxTranslateLoadCheckAttempts) { | 315 max_reload_check_attempts_(kMaxTranslateLoadCheckAttempts) { |
516 notification_registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 316 notification_registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
517 content::NotificationService::AllSources()); | 317 content::NotificationService::AllSources()); |
(...skipping 28 matching lines...) Expand all Loading... | |
546 // History, and so on. | 346 // History, and so on. |
547 GURL page_url = web_contents->GetURL(); | 347 GURL page_url = web_contents->GetURL(); |
548 if (!IsTranslatableURL(page_url)) { | 348 if (!IsTranslatableURL(page_url)) { |
549 TranslateManagerMetrics::ReportInitiationStatus( | 349 TranslateManagerMetrics::ReportInitiationStatus( |
550 TranslateManagerMetrics::INITIATION_STATUS_URL_IS_NOT_SUPPORTED); | 350 TranslateManagerMetrics::INITIATION_STATUS_URL_IS_NOT_SUPPORTED); |
551 return; | 351 return; |
552 } | 352 } |
553 | 353 |
554 // Don't translate similar languages (ex: en-US to en). | 354 // Don't translate similar languages (ex: en-US to en). |
555 std::string target_lang = GetTargetLanguage(prefs); | 355 std::string target_lang = GetTargetLanguage(prefs); |
556 std::string language_code = GetLanguageCode(page_lang); | 356 std::string language_code = |
357 TranslateLanguageList::GetLanguageCode(page_lang); | |
557 if (language_code == target_lang) { | 358 if (language_code == target_lang) { |
558 TranslateManagerMetrics::ReportInitiationStatus( | 359 TranslateManagerMetrics::ReportInitiationStatus( |
559 TranslateManagerMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); | 360 TranslateManagerMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES); |
560 return; | 361 return; |
561 } | 362 } |
562 | 363 |
563 // Don't translate any language the user configured as accepted languages. | 364 // Don't translate any language the user configured as accepted languages. |
564 if (IsAcceptLanguage(web_contents, language_code)) { | 365 if (IsAcceptLanguage(web_contents, language_code)) { |
565 TranslateManagerMetrics::ReportInitiationStatus( | 366 TranslateManagerMetrics::ReportInitiationStatus( |
566 TranslateManagerMetrics::INITIATION_STATUS_ACCEPT_LANGUAGES); | 367 TranslateManagerMetrics::INITIATION_STATUS_ACCEPT_LANGUAGES); |
567 return; | 368 return; |
568 } | 369 } |
569 | 370 |
570 // Nothing to do if either the language Chrome is in or the language of the | 371 // Nothing to do if either the language Chrome is in or the language of the |
571 // page is not supported by the translation server. | 372 // page is not supported by the translation server. |
572 if (target_lang.empty() || !IsSupportedLanguage(language_code)) { | 373 if (target_lang.empty() || |
374 !TranslateLanguageList::IsSupportedLanguage(language_code)) { | |
573 TranslateManagerMetrics::ReportInitiationStatus( | 375 TranslateManagerMetrics::ReportInitiationStatus( |
574 TranslateManagerMetrics::INITIATION_STATUS_LANGUAGE_IS_NOT_SUPPORTED); | 376 TranslateManagerMetrics::INITIATION_STATUS_LANGUAGE_IS_NOT_SUPPORTED); |
575 return; | 377 return; |
576 } | 378 } |
577 | 379 |
578 // Don't translate any user black-listed URLs or user selected language | 380 // Don't translate any user black-listed URLs or user selected language |
579 // combination. | 381 // combination. |
580 if (!TranslatePrefs::CanTranslate(prefs, language_code, page_url)) { | 382 if (!TranslatePrefs::CanTranslate(prefs, language_code, page_url)) { |
581 TranslateManagerMetrics::ReportInitiationStatus( | 383 TranslateManagerMetrics::ReportInitiationStatus( |
582 TranslateManagerMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); | 384 TranslateManagerMetrics::INITIATION_STATUS_DISABLED_BY_CONFIG); |
583 return; | 385 return; |
584 } | 386 } |
585 | 387 |
586 // If the user has previously selected "always translate" for this language we | 388 // If the user has previously selected "always translate" for this language we |
587 // automatically translate. Note that in incognito mode we disable that | 389 // automatically translate. Note that in incognito mode we disable that |
588 // feature; the user will get an infobar, so they can control whether the | 390 // feature; the user will get an infobar, so they can control whether the |
589 // page's text is sent to the translate server. | 391 // page's text is sent to the translate server. |
590 std::string auto_target_lang; | 392 std::string auto_target_lang; |
591 if (!web_contents->GetBrowserContext()->IsOffTheRecord() && | 393 if (!web_contents->GetBrowserContext()->IsOffTheRecord() && |
592 TranslatePrefs::ShouldAutoTranslate(prefs, language_code, | 394 TranslatePrefs::ShouldAutoTranslate(prefs, language_code, |
593 &auto_target_lang)) { | 395 &auto_target_lang)) { |
594 // We need to confirm that the saved target language is still supported. | 396 // We need to confirm that the saved target language is still supported. |
595 // Also, GetLanguageCode will take care of removing country code if any. | 397 // Also, GetLanguageCode will take care of removing country code if any. |
596 auto_target_lang = GetLanguageCode(auto_target_lang); | 398 auto_target_lang = TranslateLanguageList::GetLanguageCode(auto_target_lang); |
597 if (IsSupportedLanguage(auto_target_lang)) { | 399 if (TranslateLanguageList::IsSupportedLanguage(auto_target_lang)) { |
598 TranslateManagerMetrics::ReportInitiationStatus( | 400 TranslateManagerMetrics::ReportInitiationStatus( |
599 TranslateManagerMetrics::INITIATION_STATUS_AUTO_BY_CONFIG); | 401 TranslateManagerMetrics::INITIATION_STATUS_AUTO_BY_CONFIG); |
600 TranslatePage(web_contents, language_code, auto_target_lang); | 402 TranslatePage(web_contents, language_code, auto_target_lang); |
601 return; | 403 return; |
602 } | 404 } |
603 } | 405 } |
604 | 406 |
605 TranslateTabHelper* translate_tab_helper = | 407 TranslateTabHelper* translate_tab_helper = |
606 TranslateTabHelper::FromWebContents(web_contents); | 408 TranslateTabHelper::FromWebContents(web_contents); |
607 if (!translate_tab_helper) | 409 if (!translate_tab_helper) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
647 if ((web_contents->IsLoading()) && attempt < kMaxTranslateLoadCheckAttempts) { | 449 if ((web_contents->IsLoading()) && attempt < kMaxTranslateLoadCheckAttempts) { |
648 int backoff = attempt * max_reload_check_attempts_; | 450 int backoff = attempt * max_reload_check_attempts_; |
649 MessageLoop::current()->PostDelayedTask( | 451 MessageLoop::current()->PostDelayedTask( |
650 FROM_HERE, base::Bind(&TranslateManager::InitiateTranslationPosted, | 452 FROM_HERE, base::Bind(&TranslateManager::InitiateTranslationPosted, |
651 weak_method_factory_.GetWeakPtr(), process_id, | 453 weak_method_factory_.GetWeakPtr(), process_id, |
652 render_id, page_lang, ++attempt), | 454 render_id, page_lang, ++attempt), |
653 base::TimeDelta::FromMilliseconds(backoff)); | 455 base::TimeDelta::FromMilliseconds(backoff)); |
654 return; | 456 return; |
655 } | 457 } |
656 | 458 |
657 InitiateTranslation(web_contents, GetLanguageCode(page_lang)); | 459 InitiateTranslation(web_contents, |
460 TranslateLanguageList::GetLanguageCode(page_lang)); | |
658 } | 461 } |
659 | 462 |
660 void TranslateManager::TranslatePage(WebContents* web_contents, | 463 void TranslateManager::TranslatePage(WebContents* web_contents, |
661 const std::string& source_lang, | 464 const std::string& source_lang, |
662 const std::string& target_lang) { | 465 const std::string& target_lang) { |
663 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); | 466 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); |
664 if (!entry) { | 467 if (!entry) { |
665 NOTREACHED(); | 468 NOTREACHED(); |
666 return; | 469 return; |
667 } | 470 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 kUrlQueryName, | 527 kUrlQueryName, |
725 page_url.spec()); | 528 page_url.spec()); |
726 | 529 |
727 TranslateTabHelper* translate_tab_helper = | 530 TranslateTabHelper* translate_tab_helper = |
728 TranslateTabHelper::FromWebContents(web_contents); | 531 TranslateTabHelper::FromWebContents(web_contents); |
729 report_error_url = net::AppendQueryParameter( | 532 report_error_url = net::AppendQueryParameter( |
730 report_error_url, | 533 report_error_url, |
731 kSourceLanguageQueryName, | 534 kSourceLanguageQueryName, |
732 translate_tab_helper->language_state().original_language()); | 535 translate_tab_helper->language_state().original_language()); |
733 | 536 |
734 report_error_url = AddHostLocaleToUrl(report_error_url); | 537 report_error_url = TranslateURLUtil::AddHostLocaleToUrl(report_error_url); |
735 report_error_url = AddApiKeyToUrl(report_error_url); | 538 report_error_url = TranslateURLUtil::AddApiKeyToUrl(report_error_url); |
736 | 539 |
737 chrome::AddSelectedTabWithURL(browser, report_error_url, | 540 chrome::AddSelectedTabWithURL(browser, report_error_url, |
738 content::PAGE_TRANSITION_AUTO_BOOKMARK); | 541 content::PAGE_TRANSITION_AUTO_BOOKMARK); |
739 } | 542 } |
740 | 543 |
741 void TranslateManager::DoTranslatePage(WebContents* web_contents, | 544 void TranslateManager::DoTranslatePage(WebContents* web_contents, |
742 const std::string& translate_script, | 545 const std::string& translate_script, |
743 const std::string& source_lang, | 546 const std::string& source_lang, |
744 const std::string& target_lang) { | 547 const std::string& target_lang) { |
745 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); | 548 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); |
746 if (!entry) { | 549 if (!entry) { |
747 NOTREACHED(); | 550 NOTREACHED(); |
748 return; | 551 return; |
749 } | 552 } |
750 | 553 |
751 TranslateTabHelper* translate_tab_helper = | 554 TranslateTabHelper* translate_tab_helper = |
752 TranslateTabHelper::FromWebContents(web_contents); | 555 TranslateTabHelper::FromWebContents(web_contents); |
753 if (!translate_tab_helper) | 556 if (!translate_tab_helper) |
754 return; | 557 return; |
755 | 558 |
756 translate_tab_helper->language_state().set_translation_pending(true); | 559 translate_tab_helper->language_state().set_translation_pending(true); |
757 web_contents->GetRenderViewHost()->Send(new ChromeViewMsg_TranslatePage( | 560 web_contents->GetRenderViewHost()->Send(new ChromeViewMsg_TranslatePage( |
758 web_contents->GetRenderViewHost()->GetRoutingID(), entry->GetPageID(), | 561 web_contents->GetRenderViewHost()->GetRoutingID(), entry->GetPageID(), |
759 translate_script, source_lang, target_lang)); | 562 translate_script, source_lang, target_lang)); |
760 } | 563 } |
761 | 564 |
762 void TranslateManager::PageTranslated(WebContents* web_contents, | 565 void TranslateManager::PageTranslated(WebContents* web_contents, |
763 PageTranslatedDetails* details) { | 566 PageTranslatedDetails* details) { |
764 if ((details->error_type == TranslateErrors::NONE) && | 567 if ((details->error_type == TranslateErrors::NONE) && |
765 !IsSupportedLanguage(details->source_language)) { | 568 !TranslateLanguageList::IsSupportedLanguage(details->source_language)) { |
766 // TODO(jcivelli): http://crbug.com/9390 We should change the "after | 569 // TODO(jcivelli): http://crbug.com/9390 We should change the "after |
767 // translate" infobar to support unknown as the original | 570 // translate" infobar to support unknown as the original |
768 // language. | 571 // language. |
769 TranslateManagerMetrics::ReportUnsupportedLanguage(); | 572 TranslateManagerMetrics::ReportUnsupportedLanguage(); |
770 details->error_type = TranslateErrors::UNSUPPORTED_LANGUAGE; | 573 details->error_type = TranslateErrors::UNSUPPORTED_LANGUAGE; |
771 } | 574 } |
772 Profile* profile = | 575 Profile* profile = |
773 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 576 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
774 PrefService* prefs = profile->GetPrefs(); | 577 PrefService* prefs = profile->GetPrefs(); |
775 TranslateInfoBarDelegate::Create( | 578 TranslateInfoBarDelegate::Create( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
813 return iter->second.count(language) != 0; | 616 return iter->second.count(language) != 0; |
814 } | 617 } |
815 | 618 |
816 void TranslateManager::InitAcceptLanguages(PrefService* prefs) { | 619 void TranslateManager::InitAcceptLanguages(PrefService* prefs) { |
817 // We have been asked for this profile, build the languages. | 620 // We have been asked for this profile, build the languages. |
818 std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); | 621 std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); |
819 std::vector<std::string> accept_langs_list; | 622 std::vector<std::string> accept_langs_list; |
820 LanguageSet accept_langs_set; | 623 LanguageSet accept_langs_set; |
821 base::SplitString(accept_langs_str, ',', &accept_langs_list); | 624 base::SplitString(accept_langs_str, ',', &accept_langs_list); |
822 std::vector<std::string>::const_iterator iter; | 625 std::vector<std::string>::const_iterator iter; |
823 std::string ui_lang = | 626 std::string ui_lang = TranslateLanguageList::GetLanguageCode( |
824 GetLanguageCode(g_browser_process->GetApplicationLocale()); | 627 g_browser_process->GetApplicationLocale()); |
825 bool is_ui_english = StartsWithASCII(ui_lang, "en-", false); | 628 bool is_ui_english = StartsWithASCII(ui_lang, "en-", false); |
826 for (iter = accept_langs_list.begin(); | 629 for (iter = accept_langs_list.begin(); |
827 iter != accept_langs_list.end(); ++iter) { | 630 iter != accept_langs_list.end(); ++iter) { |
828 // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese | 631 // Get rid of the locale extension if any (ex: en-US -> en), but for Chinese |
829 // for which the CLD reports zh-CN and zh-TW. | 632 // for which the CLD reports zh-CN and zh-TW. |
830 std::string accept_lang(*iter); | 633 std::string accept_lang(*iter); |
831 size_t index = iter->find("-"); | 634 size_t index = iter->find("-"); |
832 if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW") | 635 if (index != std::string::npos && *iter != "zh-CN" && *iter != "zh-TW") |
833 accept_lang = iter->substr(0, index); | 636 accept_lang = iter->substr(0, index); |
834 // Special-case English until we resolve bug 36182 properly. | 637 // Special-case English until we resolve bug 36182 properly. |
835 // Add English only if the UI language is not English. This will annoy | 638 // Add English only if the UI language is not English. This will annoy |
836 // users of non-English Chrome who can comprehend English until English is | 639 // users of non-English Chrome who can comprehend English until English is |
837 // black-listed. | 640 // black-listed. |
838 // TODO(jungshik): Once we determine that it's safe to remove English from | 641 // TODO(jungshik): Once we determine that it's safe to remove English from |
839 // the default Accept-Language values for most locales, remove this | 642 // the default Accept-Language values for most locales, remove this |
840 // special-casing. | 643 // special-casing. |
841 if (accept_lang != "en" || is_ui_english) | 644 if (accept_lang != "en" || is_ui_english) |
842 accept_langs_set.insert(accept_lang); | 645 accept_langs_set.insert(accept_lang); |
843 } | 646 } |
844 accept_languages_[prefs] = accept_langs_set; | 647 accept_languages_[prefs] = accept_langs_set; |
845 } | 648 } |
846 | 649 |
847 void TranslateManager::FetchLanguageListFromTranslateServer( | 650 void TranslateManager::FetchLanguageListFromTranslateServer( |
848 PrefService* prefs) { | 651 PrefService* prefs) { |
849 if (language_list_request_pending_.get() != NULL) | 652 if (TranslateLanguageList::HasPendingRequest()) |
850 return; | 653 return; |
851 | 654 |
852 // We don't want to do this when translate is disabled. | 655 // We don't want to do this when translate is disabled. |
853 DCHECK(prefs != NULL); | 656 DCHECK(prefs != NULL); |
854 if (CommandLine::ForCurrentProcess()->HasSwitch( | 657 if (CommandLine::ForCurrentProcess()->HasSwitch( |
855 switches::kDisableTranslate) || | 658 switches::kDisableTranslate) || |
856 (prefs != NULL && !prefs->GetBoolean(prefs::kEnableTranslate))) { | 659 (prefs != NULL && !prefs->GetBoolean(prefs::kEnableTranslate))) { |
857 return; | 660 return; |
858 } | 661 } |
859 | 662 |
860 GURL language_list_fetch_url = GURL(kLanguageListFetchURL); | 663 TranslateLanguageList::RequestLanguageList(); |
861 language_list_fetch_url = AddHostLocaleToUrl(language_list_fetch_url); | |
862 language_list_fetch_url = AddApiKeyToUrl(language_list_fetch_url); | |
863 | |
864 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
865 if (command_line.HasSwitch(switches::kEnableTranslateAlphaLanguages)) { | |
866 language_list_fetch_url = net::AppendQueryParameter( | |
867 language_list_fetch_url, | |
868 kAlphaLanguageQueryName, | |
869 kAlphaLanguageQueryValue); | |
870 } | |
871 | |
872 VLOG(9) << "Fetch supporting language list from: " | |
873 << language_list_fetch_url.spec().c_str(); | |
874 | |
875 language_list_request_pending_.reset(net::URLFetcher::Create( | |
876 1, language_list_fetch_url, net::URLFetcher::GET, this)); | |
877 language_list_request_pending_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
878 net::LOAD_DO_NOT_SAVE_COOKIES); | |
879 language_list_request_pending_->SetRequestContext( | |
880 g_browser_process->system_request_context()); | |
881 language_list_request_pending_->SetMaxRetriesOn5xx( | |
882 kMaxRetryLanguageListFetch); | |
883 language_list_request_pending_->Start(); | |
884 } | 664 } |
885 | 665 |
886 void TranslateManager::CleanupPendingUlrFetcher() { | 666 void TranslateManager::CleanupPendingUlrFetcher() { |
Takashi Toyoshima
2013/05/22 16:00:45
This function is called from browser main thread b
| |
887 language_list_request_pending_.reset(); | 667 TranslateLanguageList::ResetPendingRequest(); |
888 translate_script_request_pending_.reset(); | 668 translate_script_request_pending_.reset(); |
889 } | 669 } |
890 | 670 |
891 void TranslateManager::RequestTranslateScript() { | 671 void TranslateManager::RequestTranslateScript() { |
892 if (translate_script_request_pending_.get() != NULL) | 672 if (translate_script_request_pending_.get() != NULL) |
893 return; | 673 return; |
894 | 674 |
895 GURL translate_script_url; | 675 GURL translate_script_url; |
896 // Check if command-line contains an alternative URL for translate service. | 676 // Check if command-line contains an alternative URL for translate service. |
897 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 677 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
(...skipping 11 matching lines...) Expand all Loading... | |
909 // Use default URL when command-line argument is not specified, or specified | 689 // Use default URL when command-line argument is not specified, or specified |
910 // URL is invalid. | 690 // URL is invalid. |
911 if (translate_script_url.is_empty()) | 691 if (translate_script_url.is_empty()) |
912 translate_script_url = GURL(kTranslateScriptURL); | 692 translate_script_url = GURL(kTranslateScriptURL); |
913 | 693 |
914 translate_script_url = net::AppendQueryParameter( | 694 translate_script_url = net::AppendQueryParameter( |
915 translate_script_url, | 695 translate_script_url, |
916 kCallbackQueryName, | 696 kCallbackQueryName, |
917 kCallbackQueryValue); | 697 kCallbackQueryValue); |
918 | 698 |
919 translate_script_url = AddHostLocaleToUrl(translate_script_url); | 699 translate_script_url = |
920 translate_script_url = AddApiKeyToUrl(translate_script_url); | 700 TranslateURLUtil::AddHostLocaleToUrl(translate_script_url); |
701 translate_script_url = | |
702 TranslateURLUtil::AddApiKeyToUrl(translate_script_url); | |
921 | 703 |
922 translate_script_request_pending_.reset(net::URLFetcher::Create( | 704 translate_script_request_pending_.reset(net::URLFetcher::Create( |
923 0, translate_script_url, net::URLFetcher::GET, this)); | 705 0, translate_script_url, net::URLFetcher::GET, this)); |
924 translate_script_request_pending_->SetLoadFlags( | 706 translate_script_request_pending_->SetLoadFlags( |
925 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | 707 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); |
926 translate_script_request_pending_->SetRequestContext( | 708 translate_script_request_pending_->SetRequestContext( |
927 g_browser_process->system_request_context()); | 709 g_browser_process->system_request_context()); |
928 translate_script_request_pending_->SetExtraRequestHeaders( | 710 translate_script_request_pending_->SetExtraRequestHeaders( |
929 kTranslateScriptHeader); | 711 kTranslateScriptHeader); |
930 translate_script_request_pending_->Start(); | 712 translate_script_request_pending_->Start(); |
931 } | 713 } |
932 | 714 |
933 // static | 715 // static |
934 std::string TranslateManager::GetTargetLanguage(PrefService* prefs) { | 716 std::string TranslateManager::GetTargetLanguage(PrefService* prefs) { |
935 std::string ui_lang = | 717 std::string ui_lang = TranslateLanguageList::GetLanguageCode( |
936 GetLanguageCode(g_browser_process->GetApplicationLocale()); | 718 g_browser_process->GetApplicationLocale()); |
937 if (IsSupportedLanguage(ui_lang)) | 719 if (TranslateLanguageList::IsSupportedLanguage(ui_lang)) |
938 return ui_lang; | 720 return ui_lang; |
939 | 721 |
940 // Getting the accepted languages list | 722 // Getting the accepted languages list |
941 std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); | 723 std::string accept_langs_str = prefs->GetString(prefs::kAcceptLanguages); |
942 | 724 |
943 std::vector<std::string> accept_langs_list; | 725 std::vector<std::string> accept_langs_list; |
944 base::SplitString(accept_langs_str, ',', &accept_langs_list); | 726 base::SplitString(accept_langs_str, ',', &accept_langs_list); |
945 | 727 |
946 // Will translate to the first supported language on the Accepted Language | 728 // Will translate to the first supported language on the Accepted Language |
947 // list or not at all if no such candidate exists | 729 // list or not at all if no such candidate exists |
948 std::vector<std::string>::iterator iter; | 730 std::vector<std::string>::iterator iter; |
949 for (iter = accept_langs_list.begin(); | 731 for (iter = accept_langs_list.begin(); |
950 iter != accept_langs_list.end(); ++iter) { | 732 iter != accept_langs_list.end(); ++iter) { |
951 std::string lang_code = GetLanguageCode(*iter); | 733 std::string lang_code = TranslateLanguageList::GetLanguageCode(*iter); |
952 if (IsSupportedLanguage(lang_code)) | 734 if (TranslateLanguageList::IsSupportedLanguage(lang_code)) |
953 return lang_code; | 735 return lang_code; |
954 } | 736 } |
955 return std::string(); | 737 return std::string(); |
956 } | 738 } |
957 | 739 |
958 // static | 740 // static |
959 ShortcutConfiguration TranslateManager::ShortcutConfig() { | 741 ShortcutConfiguration TranslateManager::ShortcutConfig() { |
960 ShortcutConfiguration config; | 742 ShortcutConfiguration config; |
961 | 743 |
962 // The android implementation does not offer a drop down for space | 744 // The android implementation does not offer a drop down for space |
963 // reason so we are more aggressive showing the shortcuts for never translate. | 745 // reason so we are more aggressive showing the shortcuts for never translate. |
964 #if defined(OS_ANDROID) | 746 #if defined(OS_ANDROID) |
965 config.never_translate_min_count = 1; | 747 config.never_translate_min_count = 1; |
966 #else | 748 #else |
967 config.never_translate_min_count = 3; | 749 config.never_translate_min_count = 3; |
968 #endif // defined(OS_ANDROID) | 750 #endif // defined(OS_ANDROID) |
969 | 751 |
970 config.always_translate_min_count = 3; | 752 config.always_translate_min_count = 3; |
971 return config; | 753 return config; |
972 } | 754 } |
OLD | NEW |