diff options
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 5 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host_delegate.h | 3 | ||||
-rw-r--r-- | chrome/browser/tab_contents/language_state.cc | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/language_state.h | 12 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_context_menu.cc | 1 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 3 | ||||
-rw-r--r-- | chrome/browser/translate/translate_manager.cc | 3 | ||||
-rw-r--r-- | chrome/browser/translate/translate_manager_unittest.cc | 141 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 21 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 6 | ||||
-rw-r--r-- | webkit/glue/dom_operations.cc | 25 | ||||
-rw-r--r-- | webkit/glue/dom_operations.h | 6 |
15 files changed, 178 insertions, 66 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index e7ba21f..cf890e4 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1893,13 +1893,14 @@ void RenderViewHost::OnCSSInserted() { void RenderViewHost::OnPageContents(const GURL& url, int32 page_id, const string16& contents, - const std::string& language) { + const std::string& language, + bool page_translatable) { RenderViewHostDelegate::BrowserIntegration* integration_delegate = delegate_->GetBrowserIntegrationDelegate(); if (!integration_delegate) return; integration_delegate->OnPageContents(url, process()->id(), page_id, contents, - language); + language, page_translatable); } void RenderViewHost::OnPageTranslated(int32 page_id, diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index e1073ec..aa66275 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -631,7 +631,8 @@ class RenderViewHost : public RenderWidgetHost { void OnPageContents(const GURL& url, int32 page_id, const string16& contents, - const std::string& language); + const std::string& language, + bool page_translatable); void OnPageTranslated(int32 page_id, const std::string& original_lang, const std::string& translated_lang, diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index a5fca32..eb2a555 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -243,7 +243,8 @@ class RenderViewHostDelegate { int renderer_process_id, int32 page_id, const string16& contents, - const std::string& language) = 0; + const std::string& language, + bool page_translatable) = 0; // Notification that the page has been translated. virtual void OnPageTranslated(int32 page_id, diff --git a/chrome/browser/tab_contents/language_state.cc b/chrome/browser/tab_contents/language_state.cc index d294eec..2808b2a 100644 --- a/chrome/browser/tab_contents/language_state.cc +++ b/chrome/browser/tab_contents/language_state.cc @@ -9,6 +9,7 @@ LanguageState::LanguageState(NavigationController* nav_controller) : navigation_controller_(nav_controller), + page_translatable_(false), translation_pending_(false), translation_declined_(false), in_page_navigation_(false) { @@ -38,13 +39,15 @@ void LanguageState::DidNavigate(bool reload, bool in_page) { translation_declined_ = false; } -void LanguageState::LanguageDetermined(const std::string& page_language) { +void LanguageState::LanguageDetermined(const std::string& page_language, + bool page_translatable) { if (in_page_navigation_ && !original_lang_.empty()) { // In-page navigation, we don't expect our states to change. // Note that we'll set the languages if original_lang_ is empty. This might // happen if the we did not get called on the top-page. return; } + page_translatable_ = page_translatable; original_lang_ = page_language; current_lang_ = page_language; } diff --git a/chrome/browser/tab_contents/language_state.h b/chrome/browser/tab_contents/language_state.h index f428229..8cbdfd7 100644 --- a/chrome/browser/tab_contents/language_state.h +++ b/chrome/browser/tab_contents/language_state.h @@ -30,7 +30,10 @@ class LanguageState { void DidNavigate(bool reload, bool in_page_navigation); // Should be called when the language of the page has been determined. - void LanguageDetermined(const std::string& page_language); + // |page_translatable| when false indicates that the browser should not offer + // to translate the page. + void LanguageDetermined(const std::string& page_language, + bool page_translatable); // Returns the language the current page should be translated to, based on the // previous page languages and the transition. This should be called after @@ -48,6 +51,8 @@ class LanguageState { } const std::string& current_language() const { return current_lang_; } + bool page_translatable() const { return page_translatable_; } + // Whether the page is currently in the process of being translated. bool translation_pending() const { return translation_pending_; } void set_translation_pending(bool value) { translation_pending_ = value; } @@ -75,6 +80,11 @@ class LanguageState { // The navigation controller of the tab we are associated with. NavigationController* navigation_controller_; + // Whether it is OK to offer to translate the page. Some pages explictly + // specify that they should not be translated by the browser (this is the case + // for GMail for example, which provides its own translation features). + bool page_translatable_; + // Whether a translation is currently pending (TabContents waiting for the // PAGE_TRANSLATED notification). This is needed to avoid sending duplicate // translate requests to a page. TranslateManager initiates translations diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index c912965..f513891 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -730,6 +730,7 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { std::string target_lang = g_browser_process->GetApplicationLocale(); target_lang = TranslateManager::GetLanguageCode(target_lang); return !!(params_.edit_flags & WebContextMenuData::CanTranslate) && + source_tab_contents_->language_state().page_translatable() && original_lang != target_lang && !source_tab_contents_->language_state().IsPageTranslated() && !source_tab_contents_->interstitial_page() && diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 8a29653..5457a0d 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -1959,7 +1959,8 @@ void TabContents::OnPageContents(const GURL& url, int renderer_process_id, int32 page_id, const string16& contents, - const std::string& language) { + const std::string& language, + bool page_translatable) { // Don't index any https pages. People generally don't want their bank // accounts, etc. indexed on their computer, especially since some of these // things are not marked cachable. @@ -1979,7 +1980,7 @@ void TabContents::OnPageContents(const GURL& url, } #endif - language_state_.LanguageDetermined(language); + language_state_.LanguageDetermined(language, page_translatable); std::string lang = language; NotificationService::current()->Notify( diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index a96a790..304a6d2 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -843,7 +843,8 @@ class TabContents : public PageNavigator, int renderer_process_id, int32 page_id, const string16& contents, - const std::string& language); + const std::string& language, + bool page_translatable); virtual void OnPageTranslated(int32 page_id, const std::string& original_lang, const std::string& translated_lang, diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc index 2a02546..073f0c0 100644 --- a/chrome/browser/translate/translate_manager.cc +++ b/chrome/browser/translate/translate_manager.cc @@ -197,7 +197,8 @@ void TranslateManager::Observe(NotificationType type, // We may get this notifications multiple times. Make sure to translate // only once. LanguageState& language_state = tab->language_state(); - if (!language_state.translation_pending() && + if (language_state.page_translatable() && + !language_state.translation_pending() && !language_state.translation_declined() && !language_state.IsPageTranslated()) { std::string language = *(Details<std::string>(details).ptr()); diff --git a/chrome/browser/translate/translate_manager_unittest.cc b/chrome/browser/translate/translate_manager_unittest.cc index 79e3962a..88710a9 100644 --- a/chrome/browser/translate/translate_manager_unittest.cc +++ b/chrome/browser/translate/translate_manager_unittest.cc @@ -45,17 +45,20 @@ class TranslateManagerTest : public RenderViewHostTestHarness, // for that navigation. void SimulateNavigation(const GURL& url, int page_id, const std::string& contents, - const std::string& lang) { + const std::string& lang, + bool page_translatable) { NavigateAndCommit(url); - SimulateOnPageContents(url, page_id, contents, lang); + SimulateOnPageContents(url, page_id, contents, lang, page_translatable); } void SimulateOnPageContents(const GURL& url, int page_id, const std::string& contents, - const std::string& lang) { + const std::string& lang, + bool page_translatable) { rvh()->TestOnMessageReceived(ViewHostMsg_PageContents(0, url, page_id, UTF8ToUTF16(contents), - lang)); + lang, + page_translatable)); } bool GetTranslateMessage(int* page_id, @@ -270,7 +273,7 @@ class TestRenderViewContextMenu : public RenderViewContextMenu { TEST_F(TranslateManagerTest, NormalTranslate) { // Simulate navigating to a page. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // We should have an infobar. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -341,7 +344,7 @@ TEST_F(TranslateManagerTest, NormalTranslate) { TEST_F(TranslateManagerTest, TranslateScriptNotAvailable) { // Simulate navigating to a page. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // We should have an infobar. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -368,7 +371,7 @@ TEST_F(TranslateManagerTest, TranslateScriptNotAvailable) { TEST_F(TranslateManagerTest, TranslateUnknownLanguage) { // Simulate navigating to a page ("und" is the string returned by the CLD for // languages it does not recognize). - SimulateNavigation(GURL("http://www.google.mys"), 0, "G00g1e", "und"); + SimulateNavigation(GURL("http://www.google.mys"), 0, "G00g1e", "und", true); // We should not have an infobar as we don't know the language. ASSERT_TRUE(GetTranslateInfoBar() == NULL); @@ -394,7 +397,8 @@ TEST_F(TranslateManagerTest, TranslateUnknownLanguage) { // Let's run the same steps but this time the server detects the page is // already in English. - SimulateNavigation(GURL("http://www.google.com"), 1, "The Google", "und"); + SimulateNavigation(GURL("http://www.google.com"), 1, "The Google", "und", + true); menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); menu->Init(); menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); @@ -407,7 +411,8 @@ TEST_F(TranslateManagerTest, TranslateUnknownLanguage) { // Let's run the same steps again but this time the server fails to detect the // page's language (it returns an empty string). - SimulateNavigation(GURL("http://www.google.com"), 2, "The Google", "und"); + SimulateNavigation(GURL("http://www.google.com"), 2, "The Google", "und", + true); menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); menu->Init(); menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); @@ -477,7 +482,7 @@ TEST_F(TranslateManagerTest, TestAllLanguages) { // Simulate navigating to a page. NavigateAndCommit(url); - SimulateOnPageContents(url, i, "", lang); + SimulateOnPageContents(url, i, "", lang, true); // Verify we have/don't have an info-bar as expected. infobar = GetTranslateInfoBar(); @@ -492,7 +497,7 @@ TEST_F(TranslateManagerTest, TestAllLanguages) { // Tests auto-translate on page. TEST_F(TranslateManagerTest, AutoTranslateOnNavigate) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Simulate the user translating. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -505,7 +510,7 @@ TEST_F(TranslateManagerTest, AutoTranslateOnNavigate) { // Now navigate to a new page in the same language. process()->sink().ClearMessages(); - SimulateNavigation(GURL("http://news.google.fr"), 1, "Les news", "fr"); + SimulateNavigation(GURL("http://news.google.fr"), 1, "Les news", "fr", true); // This should have automatically triggered a translation. int page_id = 0; @@ -517,7 +522,7 @@ TEST_F(TranslateManagerTest, AutoTranslateOnNavigate) { // Now navigate to a page in a different language. process()->sink().ClearMessages(); - SimulateNavigation(GURL("http://news.google.es"), 1, "Las news", "es"); + SimulateNavigation(GURL("http://news.google.es"), 1, "Las news", "es", true); // This should not have triggered a translate. EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); @@ -526,28 +531,31 @@ TEST_F(TranslateManagerTest, AutoTranslateOnNavigate) { // Tests that multiple OnPageContents do not cause multiple infobars. TEST_F(TranslateManagerTest, MultipleOnPageContents) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Simulate clicking 'Nope' (don't translate). EXPECT_TRUE(DenyTranslation()); EXPECT_EQ(0, contents()->infobar_delegate_count()); // Send a new PageContents, we should not show an infobar. - SimulateOnPageContents(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateOnPageContents(GURL("http://www.google.fr"), 0, "Le Google", "fr", + true); EXPECT_EQ(0, contents()->infobar_delegate_count()); // Do the same steps but simulate closing the infobar this time. - SimulateNavigation(GURL("http://www.youtube.fr"), 1, "Le YouTube", "fr"); + SimulateNavigation(GURL("http://www.youtube.fr"), 1, "Le YouTube", "fr", + true); EXPECT_TRUE(CloseTranslateInfoBar()); EXPECT_EQ(0, contents()->infobar_delegate_count()); - SimulateOnPageContents(GURL("http://www.youtube.fr"), 1, "Le YouTube", "fr"); + SimulateOnPageContents(GURL("http://www.youtube.fr"), 1, "Le YouTube", "fr", + true); EXPECT_EQ(0, contents()->infobar_delegate_count()); } // Test that reloading the page brings back the infobar. TEST_F(TranslateManagerTest, Reload) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Close the infobar. EXPECT_TRUE(CloseTranslateInfoBar()); @@ -574,7 +582,7 @@ TEST_F(TranslateManagerTest, ReloadFromLocationBar) { GURL url("http://www.google.fr"); // Simulate navigating to a page and getting its language. - SimulateNavigation(url, 0, "Le Google", "fr"); + SimulateNavigation(url, 0, "Le Google", "fr", true); // Close the infobar. EXPECT_TRUE(CloseTranslateInfoBar()); @@ -602,34 +610,38 @@ TEST_F(TranslateManagerTest, ReloadFromLocationBar) { // in-page. TEST_F(TranslateManagerTest, CloseInfoBarInPageNavigation) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Close the infobar. EXPECT_TRUE(CloseTranslateInfoBar()); // Navigate in page, no infobar should be shown. - SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr", + true); EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Navigate out of page, a new infobar should show. - SimulateNavigation(GURL("http://www.google.fr/foot"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/foot"), 0, "Le Google", "fr", + true); EXPECT_TRUE(GetTranslateInfoBar() != NULL); } // Tests that denying translation is sticky when navigating in page. TEST_F(TranslateManagerTest, DenyTranslateInPageNavigation) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Simulate clicking 'Nope' (don't translate). EXPECT_TRUE(DenyTranslation()); // Navigate in page, no infobar should be shown. - SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr", + true); EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Navigate out of page, a new infobar should show. - SimulateNavigation(GURL("http://www.google.fr/foot"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/foot"), 0, "Le Google", "fr", + true); EXPECT_TRUE(GetTranslateInfoBar() != NULL); } @@ -637,7 +649,7 @@ TEST_F(TranslateManagerTest, DenyTranslateInPageNavigation) { // return when navigating in page. TEST_F(TranslateManagerTest, TranslateCloseInfoBarInPageNavigation) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Simulate the user translating. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -651,14 +663,15 @@ TEST_F(TranslateManagerTest, TranslateCloseInfoBarInPageNavigation) { EXPECT_TRUE(CloseTranslateInfoBar()); // Navigate in page, no infobar should be shown. - SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr", + true); EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Navigate out of page, a new infobar should show. // Note that we navigate to a page in a different language so we don't trigger // the auto-translate feature (it would translate the page automatically and // the before translate inforbar would not be shown). - SimulateNavigation(GURL("http://www.google.de"), 0, "Das Google", "de"); + SimulateNavigation(GURL("http://www.google.de"), 0, "Das Google", "de", true); EXPECT_TRUE(GetTranslateInfoBar() != NULL); } @@ -666,7 +679,7 @@ TEST_F(TranslateManagerTest, TranslateCloseInfoBarInPageNavigation) { // in-page. TEST_F(TranslateManagerTest, TranslateInPageNavigation) { // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // Simulate the user translating. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -681,14 +694,15 @@ TEST_F(TranslateManagerTest, TranslateInPageNavigation) { // Navigate in page, the same infobar should still be shown. ClearRemovedInfoBars(); - SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr/#ref1"), 0, "Le Google", "fr", + true); EXPECT_FALSE(InfoBarRemoved()); EXPECT_EQ(infobar, GetTranslateInfoBar()); // Navigate out of page, a new infobar should show. // See note in TranslateCloseInfoBarInPageNavigation test on why it is // important to navigate to a page in a different language for this test. - SimulateNavigation(GURL("http://www.google.de"), 0, "Das Google", "de"); + SimulateNavigation(GURL("http://www.google.de"), 0, "Das Google", "de", true); // The old infobar is gone. EXPECT_TRUE(CheckInfoBarRemovedAndReset(infobar)); // And there is a new one. @@ -699,7 +713,7 @@ TEST_F(TranslateManagerTest, TranslateInPageNavigation) { // unsupported language. TEST_F(TranslateManagerTest, UnsupportedPageLanguage) { // Simulate navigating to a page and getting an unsupported language. - SimulateNavigation(GURL("http://www.google.com"), 0, "Google", "qbz"); + SimulateNavigation(GURL("http://www.google.com"), 0, "Google", "qbz", true); // No info-bar should be shown. EXPECT_TRUE(GetTranslateInfoBar() == NULL); @@ -715,7 +729,7 @@ TEST_F(TranslateManagerTest, UnsupportedUILanguage) { // Simulate navigating to a page in a language supported by the translate // server. - SimulateNavigation(GURL("http://www.google.com"), 0, "Google", "en"); + SimulateNavigation(GURL("http://www.google.com"), 0, "Google", "en", true); // No info-bar should be shown. EXPECT_TRUE(GetTranslateInfoBar() == NULL); @@ -730,7 +744,7 @@ TEST_F(TranslateManagerTest, TranslateEnabledPref) { prefs->SetBoolean(prefs::kEnableTranslate, true); // Simulate navigating to a page and getting its language. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // An infobar should be shown. TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); @@ -747,7 +761,7 @@ TEST_F(TranslateManagerTest, TranslateEnabledPref) { // Simulate getting the page contents and language, that should not trigger // a translate infobar. - SimulateOnPageContents(url, 1, "Le YouTube", "fr"); + SimulateOnPageContents(url, 1, "Le YouTube", "fr", true); infobar = GetTranslateInfoBar(); EXPECT_TRUE(infobar == NULL); } @@ -756,7 +770,7 @@ TEST_F(TranslateManagerTest, TranslateEnabledPref) { TEST_F(TranslateManagerTest, NeverTranslateLanguagePref) { // Simulate navigating to a page and getting its language. GURL url("http://www.google.fr"); - SimulateNavigation(url, 0, "Le Google", "fr"); + SimulateNavigation(url, 0, "Le Google", "fr", true); // An infobar should be shown. EXPECT_TRUE(GetTranslateInfoBar() != NULL); @@ -777,7 +791,8 @@ TEST_F(TranslateManagerTest, NeverTranslateLanguagePref) { EXPECT_TRUE(CloseTranslateInfoBar()); // Navigate to a new page also in French. - SimulateNavigation(GURL("http://wwww.youtube.fr"), 1, "Le YouTube", "fr"); + SimulateNavigation(GURL("http://wwww.youtube.fr"), 1, "Le YouTube", "fr", + true); // There should not be a translate infobar. EXPECT_TRUE(GetTranslateInfoBar() == NULL); @@ -789,7 +804,7 @@ TEST_F(TranslateManagerTest, NeverTranslateLanguagePref) { EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); // Navigate to a page in French. - SimulateNavigation(url, 2, "Le Google", "fr"); + SimulateNavigation(url, 2, "Le Google", "fr", true); // There should be a translate infobar. EXPECT_TRUE(GetTranslateInfoBar() != NULL); @@ -802,7 +817,7 @@ TEST_F(TranslateManagerTest, NeverTranslateSitePref) { // Simulate navigating to a page and getting its language. GURL url("http://www.google.fr"); std::string host(url.host()); - SimulateNavigation(url, 0, "Le Google", "fr"); + SimulateNavigation(url, 0, "Le Google", "fr", true); // An infobar should be shown. EXPECT_TRUE(GetTranslateInfoBar() != NULL); @@ -823,7 +838,8 @@ TEST_F(TranslateManagerTest, NeverTranslateSitePref) { EXPECT_TRUE(CloseTranslateInfoBar()); // Navigate to a new page also on the same site. - SimulateNavigation(GURL("http://www.google.fr/hello"), 1, "Bonjour", "fr"); + SimulateNavigation(GURL("http://www.google.fr/hello"), 1, "Bonjour", "fr", + true); // There should not be a translate infobar. EXPECT_TRUE(GetTranslateInfoBar() == NULL); @@ -835,7 +851,7 @@ TEST_F(TranslateManagerTest, NeverTranslateSitePref) { EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); // Navigate to a page in French. - SimulateNavigation(url, 0, "Le Google", "fr"); + SimulateNavigation(url, 0, "Le Google", "fr", true); // There should be a translate infobar. EXPECT_TRUE(GetTranslateInfoBar() != NULL); @@ -854,7 +870,7 @@ TEST_F(TranslateManagerTest, AlwaysTranslateLanguagePref) { translate_prefs.WhitelistLanguagePair("fr", "en"); // Load a page in French. - SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 0, "Le Google", "fr", true); // It should have triggered an automatic translation to English. SimulateURLFetch(true); // Simulate the translate script being retrieved. @@ -870,7 +886,7 @@ TEST_F(TranslateManagerTest, AlwaysTranslateLanguagePref) { EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Try another language, it should not be autotranslated. - SimulateNavigation(GURL("http://www.google.es"), 1, "El Google", "es"); + SimulateNavigation(GURL("http://www.google.es"), 1, "El Google", "es", true); EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); EXPECT_TRUE(GetTranslateInfoBar() != NULL); EXPECT_TRUE(CloseTranslateInfoBar()); @@ -880,7 +896,8 @@ TEST_F(TranslateManagerTest, AlwaysTranslateLanguagePref) { TestingProfile* test_profile = static_cast<TestingProfile*>(contents()->profile()); test_profile->set_off_the_record(true); - SimulateNavigation(GURL("http://www.youtube.fr"), 2, "Le YouTube", "fr"); + SimulateNavigation(GURL("http://www.youtube.fr"), 2, "Le YouTube", "fr", + true); EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); EXPECT_TRUE(GetTranslateInfoBar() != NULL); EXPECT_TRUE(CloseTranslateInfoBar()); @@ -890,7 +907,7 @@ TEST_F(TranslateManagerTest, AlwaysTranslateLanguagePref) { // behavior, which is show an infobar. SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists); translate_prefs.RemoveLanguagePairFromWhitelist("fr", "en"); - SimulateNavigation(GURL("http://www.google.fr"), 3, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 3, "Le Google", "fr", true); EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); EXPECT_TRUE(GetTranslateInfoBar() != NULL); prefs->RemovePrefObserver(TranslatePrefs::kPrefTranslateWhitelists, @@ -908,7 +925,7 @@ TEST_F(TranslateManagerTest, ContextMenu) { EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(url.host())); // Simulate navigating to a page in French. The translate menu should show. - SimulateNavigation(url, 0, "Le Google", "fr"); + SimulateNavigation(url, 0, "Le Google", "fr", true); scoped_ptr<TestRenderViewContextMenu> menu( TestRenderViewContextMenu::CreateContextMenu(contents())); menu->Init(); @@ -945,7 +962,7 @@ TEST_F(TranslateManagerTest, ContextMenu) { // Test that selecting translate in the context menu WHILE the page is being // translated does nothing (this could happen if autotranslate kicks-in and // the user selects the menu while the translation is being performed). - SimulateNavigation(GURL("http://www.google.es"), 1, "El Google", "es"); + SimulateNavigation(GURL("http://www.google.es"), 1, "El Google", "es", true); TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); ASSERT_TRUE(infobar != NULL); infobar->Translate(); @@ -961,7 +978,7 @@ TEST_F(TranslateManagerTest, ContextMenu) { // Now test that selecting translate in the context menu AFTER the page has // been translated does nothing. - SimulateNavigation(GURL("http://www.google.de"), 2, "Das Google", "de"); + SimulateNavigation(GURL("http://www.google.de"), 2, "Das Google", "de", true); infobar = GetTranslateInfoBar(); ASSERT_TRUE(infobar != NULL); infobar->Translate(); @@ -979,7 +996,7 @@ TEST_F(TranslateManagerTest, ContextMenu) { // Test that the translate context menu is disabled when the page is in the // same language as the UI. - SimulateNavigation(url, 0, "Google", "en"); + SimulateNavigation(url, 0, "Google", "en", true); menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); menu->Init(); EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); @@ -987,7 +1004,7 @@ TEST_F(TranslateManagerTest, ContextMenu) { // Test that the translate context menu is enabled when the page is in an // unknown language as the UI. - SimulateNavigation(url, 0, "G00g1e", "und"); + SimulateNavigation(url, 0, "G00g1e", "und", true); menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); menu->Init(); EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); @@ -1005,7 +1022,8 @@ TEST_F(TranslateManagerTest, BeforeTranslateExtraButtons) { TranslateInfoBarDelegate* infobar; for (int i = 0; i < 4; ++i) { - SimulateNavigation(GURL("http://www.google.fr"), 1, "Le Google", "fr"); + SimulateNavigation(GURL("http://www.google.fr"), 1, "Le Google", "fr", + true); infobar = GetTranslateInfoBar(); ASSERT_TRUE(infobar != NULL); EXPECT_EQ(TranslateInfoBarDelegate::kBeforeTranslate, infobar->type()); @@ -1032,7 +1050,8 @@ TEST_F(TranslateManagerTest, BeforeTranslateExtraButtons) { // Now test that declining the translation causes a "never translate" button // to be shown. for (int i = 0; i < 4; ++i) { - SimulateNavigation(GURL("http://www.google.de"), 1, "Das Google", "de"); + SimulateNavigation(GURL("http://www.google.de"), 1, "Das Google", "de", + true); infobar = GetTranslateInfoBar(); ASSERT_TRUE(infobar != NULL); EXPECT_EQ(TranslateInfoBarDelegate::kBeforeTranslate, infobar->type()); @@ -1051,3 +1070,21 @@ TEST_F(TranslateManagerTest, BeforeTranslateExtraButtons) { process()->sink().ClearMessages(); ASSERT_TRUE(GetTranslateInfoBar() == NULL); } + +// Tests that we don't show a translate infobar when a page instructs that it +// should not be translated. +TEST_F(TranslateManagerTest, NonTranslatablePage) { + // Simulate navigating to a page. + SimulateNavigation(GURL("http://mail.google.fr"), 0, "Le Google", "fr", + false); + + // We should not have an infobar. + EXPECT_TRUE(GetTranslateInfoBar() == NULL); + + // The context menu should be disabled. + scoped_ptr<TestRenderViewContextMenu> menu( + TestRenderViewContextMenu::CreateContextMenu(contents())); + menu->Init(); + EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); + EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); +} diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 0b8e903..5fc758f 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1299,11 +1299,12 @@ IPC_BEGIN_MESSAGES(ViewHost) std::wstring /* out - prompt field */) // Provides the contents for the given page that was loaded recently. - IPC_MESSAGE_ROUTED4(ViewHostMsg_PageContents, + IPC_MESSAGE_ROUTED5(ViewHostMsg_PageContents, GURL /* URL of the page */, int32 /* page id */, string16 /* page contents */, - std::string /* page ISO639_1 language code */) + std::string /* page ISO639_1 language code */, + bool /* whether the page can be translated */) // Used to get the extension message bundle. IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetExtensionMessageBundle, diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 1386917..7030f80 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -838,11 +838,11 @@ void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) { std::string language = DetermineTextLanguage(contents); UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.LanguageDetection", base::TimeTicks::Now() - begin_time); - + WebKit::WebDocument document = main_frame->document(); // Send the text to the browser for indexing (the browser might decide not // to index, if the URL is HTTPS for instance) and language discovery. Send(new ViewHostMsg_PageContents(routing_id_, url, load_id, contents, - language)); + language, IsPageTranslatable(&document))); } OnCaptureThumbnail(); @@ -1978,6 +1978,23 @@ void RenderView::UpdateTargetURL(const GURL& url, const GURL& fallback_url) { } } +bool RenderView::IsPageTranslatable(WebKit::WebDocument* document) { + std::vector<WebKit::WebElement> meta_elements; + webkit_glue::GetMetaElementsWithName(document, ASCIIToUTF16("google"), + &meta_elements); + std::vector<WebKit::WebElement>::const_iterator iter; + for (iter = meta_elements.begin(); iter != meta_elements.end(); ++iter) { + WebString attribute = iter->getAttribute("value"); + if (attribute.isNull()) // We support both 'value' and 'content'. + attribute = iter->getAttribute("content"); + if (attribute.isNull()) + continue; + if (LowerCaseEqualsASCII(attribute, "notranslate")) + return false; + } + return true; +} + void RenderView::StartNavStateSyncTimerIfNecessary() { int delay; if (send_content_state_immediately_) diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index ea515b4..71b8693 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -103,6 +103,7 @@ class WebAccessibilityCache; class WebApplicationCacheHost; class WebApplicationCacheHostClient; class WebDataSource; +class WebDocument; class WebDragData; class WebGeolocationServiceInterface; class WebImage; @@ -933,6 +934,11 @@ class RenderView : public RenderWidget, // If |only_visible| is true, only forms visible in the layout are sent void SendPasswordForms(WebKit::WebFrame* frame, bool only_visible); + // Returns whether the page associated with |document| is a candidate for + // translation. Some pages can explictly specify (via a meta-tag) that they + // should not be translated. + bool IsPageTranslatable(WebKit::WebDocument* document); + // Starts nav_state_sync_timer_ if it isn't already running. void StartNavStateSyncTimerIfNecessary(); diff --git a/webkit/glue/dom_operations.cc b/webkit/glue/dom_operations.cc index d0b371d..017c3c6 100644 --- a/webkit/glue/dom_operations.cc +++ b/webkit/glue/dom_operations.cc @@ -590,4 +590,29 @@ int NumberOfActiveAnimations(WebView* view) { return controller->numberOfActiveAnimations(); } +void GetMetaElementsWithName(WebDocument* document, + const string16& name, + std::vector<WebElement>* meta_elements) { + DCHECK(document); + DCHECK(meta_elements); + meta_elements->clear(); + WebElement head = document->head(); + if (head.isNull() || !head.hasChildNodes()) + return; + + WebNodeList children = head.childNodes(); + for (size_t i = 0; i < children.length(); ++i) { + WebNode node = children.item(i); + if (!node.isElementNode()) + continue; + WebElement element = node.to<WebElement>(); + if (!element.hasTagName("meta")) + continue; + WebString meta_name = element.getAttribute("name"); + if (meta_name.isNull() || meta_name != name) + continue; + meta_elements->push_back(element); + } +} + } // webkit_glue diff --git a/webkit/glue/dom_operations.h b/webkit/glue/dom_operations.h index 4741bce..b8915be 100644 --- a/webkit/glue/dom_operations.h +++ b/webkit/glue/dom_operations.h @@ -129,6 +129,12 @@ int NumberOfActiveAnimations(WebKit::WebView* view); WebKit::WebString GetSubResourceLinkFromElement( const WebKit::WebElement& element); +// Puts the meta-elements of |document| that have the specified |name| in +// |meta_elements|. +void GetMetaElementsWithName(WebKit::WebDocument* document, + const string16& name, + std::vector<WebKit::WebElement>* meta_elements); + } // namespace webkit_glue #endif // WEBKIT_GLUE_DOM_OPERATIONS_H__ |