Chromium Code Reviews| 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" | 10 #include "base/json/json_reader.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 // application locale. | 160 // application locale. |
| 161 const char kHostLocaleQueryName[] = "hl"; | 161 const char kHostLocaleQueryName[] = "hl"; |
| 162 | 162 |
| 163 // Used in kReportLanguageDetectionErrorURL to specify the original page | 163 // Used in kReportLanguageDetectionErrorURL to specify the original page |
| 164 // language. | 164 // language. |
| 165 const char kSourceLanguageQueryName[] = "sl"; | 165 const char kSourceLanguageQueryName[] = "sl"; |
| 166 | 166 |
| 167 // Used in kReportLanguageDetectionErrorURL to specify the page URL. | 167 // Used in kReportLanguageDetectionErrorURL to specify the page URL. |
| 168 const char kUrlQueryName[] = "u"; | 168 const char kUrlQueryName[] = "u"; |
| 169 | 169 |
| 170 // The delay in ms that we'll wait to check if a page has finished loading | |
| 171 // before attempting a translation. | |
| 172 const int kTranslateLoadCheckDelayMs = 150; | |
| 173 | |
| 174 // The maximum number of attempts we'll do to see if the page has finshed | |
| 175 // loading before giving up the translation | |
| 176 const int kMaxTranslateLoadCheckAttempts = 20; | |
| 177 | |
| 170 const int kMaxRetryLanguageListFetch = 5; | 178 const int kMaxRetryLanguageListFetch = 5; |
| 171 const int kTranslateScriptExpirationDelayDays = 1; | 179 const int kTranslateScriptExpirationDelayDays = 1; |
| 172 | 180 |
| 173 GURL AddApiKeyToUrl(const GURL& url) { | 181 GURL AddApiKeyToUrl(const GURL& url) { |
| 174 return net::AppendQueryParameter(url, kApiKeyName, google_apis::GetAPIKey()); | 182 return net::AppendQueryParameter(url, kApiKeyName, google_apis::GetAPIKey()); |
| 175 } | 183 } |
| 176 | 184 |
| 177 GURL AddHostLocaleToUrl(const GURL& url) { | 185 GURL AddHostLocaleToUrl(const GURL& url) { |
| 178 return net::AppendQueryParameter( | 186 return net::AppendQueryParameter( |
| 179 url, | 187 url, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 translate_tab_helper->language_state().translation_declined()) { | 344 translate_tab_helper->language_state().translation_declined()) { |
| 337 // Some sites (such as Google map) may trigger sub-frame navigations | 345 // Some sites (such as Google map) may trigger sub-frame navigations |
| 338 // when the user interacts with the page. We don't want to show a new | 346 // when the user interacts with the page. We don't want to show a new |
| 339 // infobar if the user already dismissed one in that case. | 347 // infobar if the user already dismissed one in that case. |
| 340 return; | 348 return; |
| 341 } | 349 } |
| 342 if (entry->GetTransitionType() != content::PAGE_TRANSITION_RELOAD && | 350 if (entry->GetTransitionType() != content::PAGE_TRANSITION_RELOAD && |
| 343 load_details->type != content::NAVIGATION_TYPE_SAME_PAGE) { | 351 load_details->type != content::NAVIGATION_TYPE_SAME_PAGE) { |
| 344 return; | 352 return; |
| 345 } | 353 } |
| 354 | |
| 346 // When doing a page reload, TAB_LANGUAGE_DETERMINED is not sent, | 355 // When doing a page reload, TAB_LANGUAGE_DETERMINED is not sent, |
| 347 // so the translation needs to be explicitly initiated, but only when the | 356 // so the translation needs to be explicitly initiated, but only when the |
| 348 // page is translatable. | 357 // page is translatable. |
| 349 if (!translate_tab_helper->language_state().page_translatable()) | 358 if (!translate_tab_helper->language_state().page_translatable()) |
| 350 return; | 359 return; |
| 351 // Note that we delay it as the TranslateManager gets this notification | 360 // Note that we delay it as the TranslateManager gets this notification |
| 352 // before the WebContents and the WebContents processing might remove the | 361 // before the WebContents and the WebContents processing might remove the |
| 353 // current infobars. Since InitTranslation might add an infobar, it must | 362 // current infobars. Since InitTranslation might add an infobar, it must |
| 354 // be done after that. | 363 // be done after that. |
| 355 MessageLoop::current()->PostTask(FROM_HERE, | 364 MessageLoop::current()->PostTask(FROM_HERE, |
| 356 base::Bind( | 365 base::Bind( |
| 357 &TranslateManager::InitiateTranslationPosted, | 366 &TranslateManager::InitiateTranslationPosted, |
| 358 weak_method_factory_.GetWeakPtr(), | 367 weak_method_factory_.GetWeakPtr(), |
| 359 controller->GetWebContents()->GetRenderProcessHost()->GetID(), | 368 controller->GetWebContents()->GetRenderProcessHost()->GetID(), |
| 360 controller->GetWebContents()->GetRenderViewHost()->GetRoutingID(), | 369 controller->GetWebContents()->GetRenderViewHost()->GetRoutingID(), |
| 361 translate_tab_helper->language_state().original_language())); | 370 translate_tab_helper->language_state().original_language(), 0)); |
| 362 break; | 371 break; |
| 363 } | 372 } |
| 364 case chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED: { | 373 case chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED: { |
| 365 WebContents* tab = content::Source<WebContents>(source).ptr(); | 374 WebContents* tab = content::Source<WebContents>(source).ptr(); |
| 366 // We may get this notifications multiple times. Make sure to translate | 375 // We may get this notifications multiple times. Make sure to translate |
| 367 // only once. | 376 // only once. |
| 368 TranslateTabHelper* translate_tab_helper = | 377 TranslateTabHelper* translate_tab_helper = |
| 369 TranslateTabHelper::FromWebContents(tab); | 378 TranslateTabHelper::FromWebContents(tab); |
| 370 if (!translate_tab_helper) | 379 if (!translate_tab_helper) |
| 371 return; | 380 return; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 GetRawDataResource(IDR_TRANSLATE_JS); | 441 GetRawDataResource(IDR_TRANSLATE_JS); |
| 433 DCHECK(translate_script_.empty()); | 442 DCHECK(translate_script_.empty()); |
| 434 str.CopyToString(&translate_script_); | 443 str.CopyToString(&translate_script_); |
| 435 std::string argument = "('"; | 444 std::string argument = "('"; |
| 436 std::string api_key = google_apis::GetAPIKey(); | 445 std::string api_key = google_apis::GetAPIKey(); |
| 437 argument += net::EscapeQueryParamValue(api_key, true); | 446 argument += net::EscapeQueryParamValue(api_key, true); |
| 438 argument += "');\n"; | 447 argument += "');\n"; |
| 439 std::string data; | 448 std::string data; |
| 440 source->GetResponseAsString(&data); | 449 source->GetResponseAsString(&data); |
| 441 translate_script_ += argument + data; | 450 translate_script_ += argument + data; |
| 451 | |
| 442 // We'll expire the cached script after some time, to make sure long | 452 // We'll expire the cached script after some time, to make sure long |
| 443 // running browsers still get fixes that might get pushed with newer | 453 // running browsers still get fixes that might get pushed with newer |
| 444 // scripts. | 454 // scripts. |
| 445 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 455 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 446 base::Bind(&TranslateManager::ClearTranslateScript, | 456 base::Bind(&TranslateManager::ClearTranslateScript, |
| 447 weak_method_factory_.GetWeakPtr()), | 457 weak_method_factory_.GetWeakPtr()), |
| 448 translate_script_expiration_delay_); | 458 translate_script_expiration_delay_); |
| 449 } | 459 } |
| 450 // Process any pending requests. | 460 // Process any pending requests. |
| 451 std::vector<PendingRequest>::const_iterator iter; | 461 std::vector<PendingRequest>::const_iterator iter; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 std::string data; | 501 std::string data; |
| 492 source->GetResponseAsString(&data); | 502 source->GetResponseAsString(&data); |
| 493 SetSupportedLanguages(data); | 503 SetSupportedLanguages(data); |
| 494 } else { | 504 } else { |
| 495 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; | 505 VLOG(9) << "Failed to Fetch languages from: " << kLanguageListFetchURL; |
| 496 } | 506 } |
| 497 } | 507 } |
| 498 } | 508 } |
| 499 | 509 |
| 500 TranslateManager::TranslateManager() | 510 TranslateManager::TranslateManager() |
| 501 : weak_method_factory_(this), | 511 : weak_method_factory_(this), |
| 502 translate_script_expiration_delay_( | 512 translate_script_expiration_delay_(base::TimeDelta::FromDays( |
| 503 base::TimeDelta::FromDays(kTranslateScriptExpirationDelayDays)) { | 513 kTranslateScriptExpirationDelayDays)), |
| 514 max_reload_check_attempts_(kMaxTranslateLoadCheckAttempts) { | |
| 504 notification_registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 515 notification_registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 505 content::NotificationService::AllSources()); | 516 content::NotificationService::AllSources()); |
| 506 notification_registrar_.Add(this, | 517 notification_registrar_.Add(this, |
| 507 chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, | 518 chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, |
| 508 content::NotificationService::AllSources()); | 519 content::NotificationService::AllSources()); |
| 509 notification_registrar_.Add(this, chrome::NOTIFICATION_PAGE_TRANSLATED, | 520 notification_registrar_.Add(this, chrome::NOTIFICATION_PAGE_TRANSLATED, |
| 510 content::NotificationService::AllSources()); | 521 content::NotificationService::AllSources()); |
| 511 } | 522 } |
| 512 | 523 |
| 513 void TranslateManager::InitiateTranslation(WebContents* web_contents, | 524 void TranslateManager::InitiateTranslation(WebContents* web_contents, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 | 587 |
| 577 // Prompts the user if he/she wants the page translated. | 588 // Prompts the user if he/she wants the page translated. |
| 578 TranslateInfoBarDelegate::Create( | 589 TranslateInfoBarDelegate::Create( |
| 579 InfoBarService::FromWebContents(web_contents), false, | 590 InfoBarService::FromWebContents(web_contents), false, |
| 580 TranslateInfoBarDelegate::BEFORE_TRANSLATE, TranslateErrors::NONE, | 591 TranslateInfoBarDelegate::BEFORE_TRANSLATE, TranslateErrors::NONE, |
| 581 profile->GetPrefs(), ShortcutConfig(), | 592 profile->GetPrefs(), ShortcutConfig(), |
| 582 language_code, target_lang); | 593 language_code, target_lang); |
| 583 } | 594 } |
| 584 | 595 |
| 585 void TranslateManager::InitiateTranslationPosted( | 596 void TranslateManager::InitiateTranslationPosted( |
| 586 int process_id, int render_id, const std::string& page_lang) { | 597 int process_id, int render_id, const std::string& page_lang, int attempt) { |
| 587 // The tab might have been closed. | 598 // The tab might have been closed. |
| 588 WebContents* web_contents = | 599 WebContents* web_contents = |
| 589 tab_util::GetWebContentsByID(process_id, render_id); | 600 tab_util::GetWebContentsByID(process_id, render_id); |
| 590 if (!web_contents) | 601 if (!web_contents) |
| 591 return; | 602 return; |
| 592 | 603 |
| 593 TranslateTabHelper* translate_tab_helper = | 604 TranslateTabHelper* translate_tab_helper = |
| 594 TranslateTabHelper::FromWebContents(web_contents); | 605 TranslateTabHelper::FromWebContents(web_contents); |
| 595 if (translate_tab_helper->language_state().translation_pending()) | 606 if (translate_tab_helper->language_state().translation_pending()) |
| 596 return; | 607 return; |
| 597 | 608 |
| 609 // During a reload we need some content to be already loaded before the | |
|
MAD
2013/05/09 14:05:24
The text seem to imply that as soon as "some" cont
Miguel Garcia
2013/05/10 12:00:02
Done.
| |
| 610 // translate script is executed. Otherwise we will run the translate script on | |
| 611 // an empty DOM which will fail. Therefore we wait a bit to see if the page | |
| 612 // has finished. | |
| 613 if ((web_contents->IsLoading()) && attempt < kMaxTranslateLoadCheckAttempts) { | |
| 614 int backoff = attempt * max_reload_check_attempts_; | |
| 615 MessageLoop::current()->PostDelayedTask( | |
| 616 FROM_HERE, base::Bind(&TranslateManager::InitiateTranslationPosted, | |
| 617 weak_method_factory_.GetWeakPtr(), process_id, | |
| 618 render_id, page_lang, ++attempt), | |
| 619 base::TimeDelta::FromMilliseconds(backoff)); | |
| 620 return; | |
| 621 } | |
| 622 | |
| 598 InitiateTranslation(web_contents, GetLanguageCode(page_lang)); | 623 InitiateTranslation(web_contents, GetLanguageCode(page_lang)); |
| 599 } | 624 } |
| 600 | 625 |
| 601 void TranslateManager::TranslatePage(WebContents* web_contents, | 626 void TranslateManager::TranslatePage(WebContents* web_contents, |
| 602 const std::string& source_lang, | 627 const std::string& source_lang, |
| 603 const std::string& target_lang) { | 628 const std::string& target_lang) { |
| 604 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); | 629 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); |
| 605 if (!entry) { | 630 if (!entry) { |
| 606 NOTREACHED(); | 631 NOTREACHED(); |
| 607 return; | 632 return; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 } | 874 } |
| 850 // Use default URL when command-line argument is not specified, or specified | 875 // Use default URL when command-line argument is not specified, or specified |
| 851 // URL is invalid. | 876 // URL is invalid. |
| 852 if (translate_script_url.is_empty()) | 877 if (translate_script_url.is_empty()) |
| 853 translate_script_url = GURL(kTranslateScriptURL); | 878 translate_script_url = GURL(kTranslateScriptURL); |
| 854 | 879 |
| 855 translate_script_url = net::AppendQueryParameter( | 880 translate_script_url = net::AppendQueryParameter( |
| 856 translate_script_url, | 881 translate_script_url, |
| 857 kCallbackQueryName, | 882 kCallbackQueryName, |
| 858 kCallbackQueryValue); | 883 kCallbackQueryValue); |
| 884 | |
| 859 translate_script_url = AddHostLocaleToUrl(translate_script_url); | 885 translate_script_url = AddHostLocaleToUrl(translate_script_url); |
| 860 translate_script_url = AddApiKeyToUrl(translate_script_url); | 886 translate_script_url = AddApiKeyToUrl(translate_script_url); |
| 861 | 887 |
| 862 translate_script_request_pending_.reset(net::URLFetcher::Create( | 888 translate_script_request_pending_.reset(net::URLFetcher::Create( |
| 863 0, translate_script_url, net::URLFetcher::GET, this)); | 889 0, translate_script_url, net::URLFetcher::GET, this)); |
| 864 translate_script_request_pending_->SetLoadFlags( | 890 translate_script_request_pending_->SetLoadFlags( |
| 865 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | 891 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); |
| 866 translate_script_request_pending_->SetRequestContext( | 892 translate_script_request_pending_->SetRequestContext( |
| 867 g_browser_process->system_request_context()); | 893 g_browser_process->system_request_context()); |
| 868 translate_script_request_pending_->SetExtraRequestHeaders( | 894 translate_script_request_pending_->SetExtraRequestHeaders( |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 // reason so we are more aggressive showing the shortcuts for never translate. | 929 // reason so we are more aggressive showing the shortcuts for never translate. |
| 904 #if defined(OS_ANDROID) | 930 #if defined(OS_ANDROID) |
| 905 config.never_translate_min_count = 1; | 931 config.never_translate_min_count = 1; |
| 906 #else | 932 #else |
| 907 config.never_translate_min_count = 3; | 933 config.never_translate_min_count = 3; |
| 908 #endif // defined(OS_ANDROID) | 934 #endif // defined(OS_ANDROID) |
| 909 | 935 |
| 910 config.always_translate_min_count = 3; | 936 config.always_translate_min_count = 3; |
| 911 return config; | 937 return config; |
| 912 } | 938 } |
| OLD | NEW |