1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 6 #include <set> 7 8 #include "base/utf_string_conversions.h" 9 #include "chrome/app/chrome_command_ids.h" 10 #include "chrome/browser/prefs/pref_service.h" 11 #include "chrome/browser/prefs/pref_change_registrar.h" 12 #include "chrome/browser/tab_contents/render_view_context_menu.h" 13 #include "chrome/browser/translate/translate_infobar_delegate.h" 14 #include "chrome/browser/translate/translate_manager.h" 15 #include "chrome/browser/translate/translate_prefs.h" 16 #include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h" 17 #include "chrome/common/pref_names.h" 18 #include "chrome/common/render_messages.h" 19 #include "chrome/common/net/test_url_fetcher_factory.h" 20 #include "chrome/test/testing_browser_process.h" 21 #include "chrome/test/testing_profile.h" 22 #include "content/browser/browser_thread.h" 23 #include "content/browser/renderer_host/mock_render_process_host.h" 24 #include "content/browser/renderer_host/test_render_view_host.h" 25 #include "content/browser/tab_contents/navigation_controller.h" 26 #include "content/browser/tab_contents/test_tab_contents.h" 27 #include "content/common/notification_details.h" 28 #include "content/common/notification_observer_mock.h" 29 #include "content/common/notification_registrar.h" 30 #include "content/common/notification_type.h" 31 #include "content/common/view_messages.h" 32 #include "grit/generated_resources.h" 33 #include "ipc/ipc_test_sink.h" 34 #include "testing/gmock/include/gmock/gmock.h" 35 #include "third_party/cld/languages/public/languages.h" 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" 37 38 using testing::_; 39 using testing::Pointee; 40 using testing::Property; 41 using WebKit::WebContextMenuData; 42 43 class TranslateManagerTest : public TabContentsWrapperTestHarness, 44 public NotificationObserver { 45 public: 46 TranslateManagerTest() 47 : ui_thread_(BrowserThread::UI, &message_loop_) { 48 } 49 50 // Simluates navigating to a page and getting the page contents and language 51 // for that navigation. 52 void SimulateNavigation(const GURL& url, 53 const std::string& lang, 54 bool page_translatable) { 55 NavigateAndCommit(url); 56 SimulateOnTranslateLanguageDetermined(lang, page_translatable); 57 } 58 59 void SimulateOnTranslateLanguageDetermined(const std::string& lang, 60 bool page_translatable) { 61 rvh()->TestOnMessageReceived(ViewHostMsg_TranslateLanguageDetermined( 62 0, lang, page_translatable)); 63 } 64 65 bool GetTranslateMessage(int* page_id, 66 std::string* original_lang, 67 std::string* target_lang) { 68 const IPC::Message* message = 69 process()->sink().GetFirstMessageMatching(ViewMsg_TranslatePage::ID); 70 if (!message) 71 return false; 72 Tuple4<int, std::string, std::string, std::string> translate_param; 73 ViewMsg_TranslatePage::Read(message, &translate_param); 74 if (page_id) 75 *page_id = translate_param.a; 76 // Ignore translate_param.b which is the script injected in the page. 77 if (original_lang) 78 *original_lang = translate_param.c; 79 if (target_lang) 80 *target_lang = translate_param.d; 81 return true; 82 } 83 84 // Returns the translate infobar if there is 1 infobar and it is a translate 85 // infobar. 86 TranslateInfoBarDelegate* GetTranslateInfoBar() { 87 return (contents()->infobar_count() == 1) ? 88 contents()->GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate() : 89 NULL; 90 } 91 92 // If there is 1 infobar and it is a translate infobar, closes it and returns 93 // true. Returns false otherwise. 94 bool CloseTranslateInfoBar() { 95 InfoBarDelegate* infobar = GetTranslateInfoBar(); 96 if (!infobar) 97 return false; 98 infobar->InfoBarDismissed(); // Simulates closing the infobar. 99 contents()->RemoveInfoBar(infobar); 100 return true; 101 } 102 103 // Checks whether |infobar| has been removed and clears the removed infobar 104 // list. 105 bool CheckInfoBarRemovedAndReset(InfoBarDelegate* delegate) { 106 bool found = removed_infobars_.count(delegate) != 0; 107 removed_infobars_.clear(); 108 return found; 109 } 110 111 // Returns true if at least one infobar was closed. 112 bool InfoBarRemoved() { 113 return !removed_infobars_.empty(); 114 } 115 116 // Clears the list of stored removed infobars. 117 void ClearRemovedInfoBars() { 118 removed_infobars_.clear(); 119 } 120 121 void ExpireTranslateScriptImmediately() { 122 TranslateManager::GetInstance()->set_translate_script_expiration_delay(0); 123 } 124 125 // If there is 1 infobar and it is a translate infobar, deny translation and 126 // returns true. Returns false otherwise. 127 bool DenyTranslation() { 128 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 129 if (!infobar) 130 return false; 131 infobar->TranslationDeclined(); 132 contents()->RemoveInfoBar(infobar); 133 return true; 134 } 135 136 virtual void Observe(NotificationType type, 137 const NotificationSource& source, 138 const NotificationDetails& details) { 139 DCHECK_EQ(NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, type.value); 140 removed_infobars_.insert(Details<InfoBarDelegate>(details).ptr()); 141 } 142 143 protected: 144 virtual void SetUp() { 145 URLFetcher::set_factory(&url_fetcher_factory_); 146 147 // Access the TranslateManager singleton so it is created before we call 148 // RenderViewHostTestHarness::SetUp() to match what's done in Chrome, where 149 // the TranslateManager is created before the TabContents. This matters as 150 // they both register for similar events and we want the notifications to 151 // happen in the same sequence (TranslateManager first, TabContents second). 152 // Also clears the translate script so it is fetched everytime and sets the 153 // expiration delay to a large value by default (in case it was zeroed in 154 // a previous test). 155 TranslateManager::GetInstance()->ClearTranslateScript(); 156 TranslateManager::GetInstance()-> 157 set_translate_script_expiration_delay(60 * 60 * 1000); 158 159 TabContentsWrapperTestHarness::SetUp(); 160 161 notification_registrar_.Add(this, 162 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, 163 Source<TabContents>(contents())); 164 } 165 166 virtual void TearDown() { 167 process()->sink().ClearMessages(); 168 169 notification_registrar_.Remove(this, 170 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, 171 Source<TabContents>(contents())); 172 173 TabContentsWrapperTestHarness::TearDown(); 174 175 URLFetcher::set_factory(NULL); 176 } 177 178 void SimulateURLFetch(bool success) { 179 TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 180 ASSERT_TRUE(fetcher); 181 net::URLRequestStatus status; 182 status.set_status(success ? net::URLRequestStatus::SUCCESS : 183 net::URLRequestStatus::FAILED); 184 fetcher->delegate()->OnURLFetchComplete(fetcher, fetcher->original_url(), 185 status, success ? 200 : 500, 186 ResponseCookies(), 187 std::string()); 188 } 189 190 void SetPrefObserverExpectation(const char* path) { 191 EXPECT_CALL( 192 pref_observer_, 193 Observe(NotificationType(NotificationType::PREF_CHANGED), 194 _, 195 Property(&Details<std::string>::ptr, Pointee(path)))); 196 } 197 198 NotificationObserverMock pref_observer_; 199 200 private: 201 NotificationRegistrar notification_registrar_; 202 TestURLFetcherFactory url_fetcher_factory_; 203 BrowserThread ui_thread_; 204 205 // The infobars that have been removed. 206 // WARNING: the pointers point to deleted objects, use only for comparison. 207 std::set<InfoBarDelegate*> removed_infobars_; 208 209 DISALLOW_COPY_AND_ASSIGN(TranslateManagerTest); 210 }; 211 212 // An observer that keeps track of whether a navigation entry was committed. 213 class NavEntryCommittedObserver : public NotificationObserver { 214 public: 215 explicit NavEntryCommittedObserver(TabContents* tab_contents) { 216 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 217 Source<NavigationController>(&tab_contents->controller())); 218 } 219 220 virtual void Observe(NotificationType type, 221 const NotificationSource& source, 222 const NotificationDetails& details) { 223 DCHECK(type == NotificationType::NAV_ENTRY_COMMITTED); 224 details_ = 225 *(Details<NavigationController::LoadCommittedDetails>(details).ptr()); 226 } 227 228 const NavigationController::LoadCommittedDetails& 229 get_load_commited_details() const { 230 return details_; 231 } 232 233 private: 234 NavigationController::LoadCommittedDetails details_; 235 NotificationRegistrar registrar_; 236 237 DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver); 238 }; 239 240 class TestRenderViewContextMenu : public RenderViewContextMenu { 241 public: 242 static TestRenderViewContextMenu* CreateContextMenu( 243 TabContents* tab_contents) { 244 ContextMenuParams params; 245 params.media_type = WebKit::WebContextMenuData::MediaTypeNone; 246 params.x = 0; 247 params.y = 0; 248 params.is_image_blocked = false; 249 params.media_flags = 0; 250 params.spellcheck_enabled = false; 251 params.is_editable = false; 252 params.page_url = tab_contents->controller().GetActiveEntry()->url(); 253 #if defined(OS_MACOSX) 254 params.writing_direction_default = 0; 255 params.writing_direction_left_to_right = 0; 256 params.writing_direction_right_to_left = 0; 257 #endif // OS_MACOSX 258 params.edit_flags = WebContextMenuData::CanTranslate; 259 return new TestRenderViewContextMenu(tab_contents, params); 260 } 261 262 bool IsItemPresent(int id) { 263 return menu_model_.GetIndexOfCommandId(id) != -1; 264 } 265 266 virtual void PlatformInit() { } 267 virtual bool GetAcceleratorForCommandId( 268 int command_id, 269 ui::Accelerator* accelerator) { return false; } 270 271 private: 272 TestRenderViewContextMenu(TabContents* tab_contents, 273 const ContextMenuParams& params) 274 : RenderViewContextMenu(tab_contents, params) { 275 } 276 277 DISALLOW_COPY_AND_ASSIGN(TestRenderViewContextMenu); 278 }; 279 280 TEST_F(TranslateManagerTest, NormalTranslate) { 281 // Simulate navigating to a page. 282 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 283 284 // We should have an infobar. 285 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 286 ASSERT_TRUE(infobar != NULL); 287 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); 288 289 // Simulate clicking translate. 290 process()->sink().ClearMessages(); 291 infobar->Translate(); 292 293 // The "Translating..." infobar should be showing. 294 infobar = GetTranslateInfoBar(); 295 ASSERT_TRUE(infobar != NULL); 296 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->type()); 297 298 // Simulate the translate script being retrieved (it only needs to be done 299 // once in the test as it is cached). 300 SimulateURLFetch(true); 301 302 // Test that we sent the right message to the renderer. 303 int page_id = 0; 304 std::string original_lang, target_lang; 305 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 306 EXPECT_EQ("fr", original_lang); 307 EXPECT_EQ("en", target_lang); 308 309 // Simulate the render notifying the translation has been done. 310 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 311 TranslateErrors::NONE)); 312 313 // The after translate infobar should be showing. 314 infobar = GetTranslateInfoBar(); 315 ASSERT_TRUE(infobar != NULL); 316 EXPECT_EQ(TranslateInfoBarDelegate::AFTER_TRANSLATE, infobar->type()); 317 318 // Simulate changing the original language, this should trigger a translation. 319 process()->sink().ClearMessages(); 320 std::string new_original_lang = infobar->GetLanguageCodeAt(0); 321 infobar->SetOriginalLanguage(0); 322 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 323 EXPECT_EQ(new_original_lang, original_lang); 324 EXPECT_EQ("en", target_lang); 325 // Simulate the render notifying the translation has been done. 326 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, 327 new_original_lang, "en", TranslateErrors::NONE)); 328 // infobar is now invalid. 329 TranslateInfoBarDelegate* new_infobar = GetTranslateInfoBar(); 330 ASSERT_TRUE(new_infobar != NULL); 331 infobar = new_infobar; 332 333 // Simulate changing the target language, this should trigger a translation. 334 process()->sink().ClearMessages(); 335 std::string new_target_lang = infobar->GetLanguageCodeAt(1); 336 infobar->SetTargetLanguage(1); 337 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 338 EXPECT_EQ(new_original_lang, original_lang); 339 EXPECT_EQ(new_target_lang, target_lang); 340 // Simulate the render notifying the translation has been done. 341 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, 342 new_original_lang, new_target_lang, TranslateErrors::NONE)); 343 // infobar is now invalid. 344 new_infobar = GetTranslateInfoBar(); 345 ASSERT_TRUE(new_infobar != NULL); 346 } 347 348 TEST_F(TranslateManagerTest, TranslateScriptNotAvailable) { 349 // Simulate navigating to a page. 350 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 351 352 // We should have an infobar. 353 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 354 ASSERT_TRUE(infobar != NULL); 355 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); 356 357 // Simulate clicking translate. 358 process()->sink().ClearMessages(); 359 infobar->Translate(); 360 // Simulate a failure retrieving the translate script. 361 SimulateURLFetch(false); 362 363 // We should not have sent any message to translate to the renderer. 364 EXPECT_FALSE(GetTranslateMessage(NULL, NULL, NULL)); 365 366 // And we should have an error infobar showing. 367 infobar = GetTranslateInfoBar(); 368 ASSERT_TRUE(infobar != NULL); 369 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, infobar->type()); 370 } 371 372 // Ensures we deal correctly with pages for which the browser does not recognize 373 // the language (the translate server may or not detect the language). 374 TEST_F(TranslateManagerTest, TranslateUnknownLanguage) { 375 // Simulate navigating to a page ("und" is the string returned by the CLD for 376 // languages it does not recognize). 377 SimulateNavigation(GURL("http://www.google.mys"), "und", true); 378 379 // We should not have an infobar as we don't know the language. 380 ASSERT_TRUE(GetTranslateInfoBar() == NULL); 381 382 // Translate the page anyway throught the context menu. 383 scoped_ptr<TestRenderViewContextMenu> menu( 384 TestRenderViewContextMenu::CreateContextMenu(contents())); 385 menu->Init(); 386 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 387 388 // To test that bug #49018 if fixed, make sure we deal correctly with errors. 389 SimulateURLFetch(false); // Simulate a failure to fetch the translate script. 390 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 391 ASSERT_TRUE(infobar != NULL); 392 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, infobar->type()); 393 EXPECT_TRUE(infobar->IsError()); 394 infobar->MessageInfoBarButtonPressed(); 395 SimulateURLFetch(true); // This time succeed. 396 397 // Simulate the render notifying the translation has been done, the server 398 // having detected the page was in a known and supported language. 399 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 400 TranslateErrors::NONE)); 401 402 // The after translate infobar should be showing. 403 infobar = GetTranslateInfoBar(); 404 ASSERT_TRUE(infobar != NULL); 405 EXPECT_EQ(TranslateInfoBarDelegate::AFTER_TRANSLATE, infobar->type()); 406 EXPECT_EQ("fr", infobar->GetOriginalLanguageCode()); 407 EXPECT_EQ("en", infobar->GetTargetLanguageCode()); 408 409 // Let's run the same steps but this time the server detects the page is 410 // already in English. 411 SimulateNavigation(GURL("http://www.google.com"), "und", true); 412 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 413 menu->Init(); 414 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 415 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(1, 0, "en", "en", 416 TranslateErrors::IDENTICAL_LANGUAGES)); 417 infobar = GetTranslateInfoBar(); 418 ASSERT_TRUE(infobar != NULL); 419 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, infobar->type()); 420 EXPECT_EQ(TranslateErrors::IDENTICAL_LANGUAGES, infobar->error()); 421 422 // Let's run the same steps again but this time the server fails to detect the 423 // page's language (it returns an empty string). 424 SimulateNavigation(GURL("http://www.google.com"), "und", true); 425 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 426 menu->Init(); 427 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 428 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(2, 0, "", "en", 429 TranslateErrors::UNKNOWN_LANGUAGE)); 430 infobar = GetTranslateInfoBar(); 431 ASSERT_TRUE(infobar != NULL); 432 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, infobar->type()); 433 EXPECT_EQ(TranslateErrors::UNKNOWN_LANGUAGE, infobar->error()); 434 } 435 436 // Tests that we show/don't show an info-bar for all languages the CLD can 437 // report. 438 TEST_F(TranslateManagerTest, TestAllLanguages) { 439 // The index in kExpectation are the Language enum (see languages.pb.h). 440 // true if we expect a translate infobar for that language. 441 // Note the supported languages are in translation_manager.cc, see 442 // kSupportedLanguages. 443 bool kExpectations[] = { 444 // 0-9 445 false, true, true, true, true, true, true, true, true, true, 446 // 10-19 447 true, true, true, true, true, true, true, true, true, true, 448 // 20-29 449 true, true, true, true, true, false, false, true, true, true, 450 // 30-39 451 true, true, true, true, true, true, true, false, true, false, 452 // 40-49 453 true, false, true, false, false, true, false, true, false, false, 454 // 50-59 455 true, false, false, true, true, true, false, true, false, false, 456 // 60-69 457 false, false, true, true, false, true, true, false, true, true, 458 // 70-79 459 false, false, false, false, true, true, false, true, false, false, 460 // 80-89 461 false, false, false, false, false, false, false, false, false, false, 462 // 90-99 463 false, true, false, false, false, false, false, true, false, false, 464 // 100-109 465 false, true, false, false, false, false, false, false, false, false, 466 // 110-119 467 false, false, false, false, false, false, false, false, false, false, 468 // 120-129 469 false, false, false, false, false, false, false, false, false, false, 470 // 130-139 471 false, false, false, false, false, false, false, false, false, true, 472 // 140-149 473 false, false, false, false, false, false, false, false, false, false, 474 // 150-159 475 false, false, false, false, false, false, false, false, false, false, 476 // 160 477 false 478 }; 479 480 GURL url("http://www.google.com"); 481 for (size_t i = 0; i < arraysize(kExpectations); ++i) { 482 ASSERT_LT(i, static_cast<size_t>(NUM_LANGUAGES)); 483 484 std::string lang = LanguageCodeWithDialects(static_cast<Language>(i)); 485 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 486 " language=" << lang); 487 488 // We should not have a translate infobar. 489 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 490 ASSERT_TRUE(infobar == NULL); 491 492 // Simulate navigating to a page. 493 NavigateAndCommit(url); 494 SimulateOnTranslateLanguageDetermined(lang, true); 495 496 // Verify we have/don't have an info-bar as expected. 497 infobar = GetTranslateInfoBar(); 498 EXPECT_EQ(kExpectations[i], infobar != NULL); 499 500 // Close the info-bar if applicable. 501 if (infobar != NULL) 502 EXPECT_TRUE(CloseTranslateInfoBar()); 503 } 504 } 505 506 // Tests auto-translate on page. 507 TEST_F(TranslateManagerTest, AutoTranslateOnNavigate) { 508 // Simulate navigating to a page and getting its language. 509 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 510 511 // Simulate the user translating. 512 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 513 ASSERT_TRUE(infobar != NULL); 514 infobar->Translate(); 515 SimulateURLFetch(true); // Simulate the translate script being retrieved. 516 517 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 518 TranslateErrors::NONE)); 519 520 // Now navigate to a new page in the same language. 521 process()->sink().ClearMessages(); 522 SimulateNavigation(GURL("http://news.google.fr"), "fr", true); 523 524 // This should have automatically triggered a translation. 525 int page_id = 0; 526 std::string original_lang, target_lang; 527 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 528 EXPECT_EQ(1, page_id); 529 EXPECT_EQ("fr", original_lang); 530 EXPECT_EQ("en", target_lang); 531 532 // Now navigate to a page in a different language. 533 process()->sink().ClearMessages(); 534 SimulateNavigation(GURL("http://news.google.es"), "es", true); 535 536 // This should not have triggered a translate. 537 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 538 } 539 540 // Tests that multiple OnPageContents do not cause multiple infobars. 541 TEST_F(TranslateManagerTest, MultipleOnPageContents) { 542 // Simulate navigating to a page and getting its language. 543 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 544 545 // Simulate clicking 'Nope' (don't translate). 546 EXPECT_TRUE(DenyTranslation()); 547 EXPECT_EQ(0U, contents()->infobar_count()); 548 549 // Send a new PageContents, we should not show an infobar. 550 SimulateOnTranslateLanguageDetermined("fr", true); 551 EXPECT_EQ(0U, contents()->infobar_count()); 552 553 // Do the same steps but simulate closing the infobar this time. 554 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true); 555 EXPECT_TRUE(CloseTranslateInfoBar()); 556 EXPECT_EQ(0U, contents()->infobar_count()); 557 SimulateOnTranslateLanguageDetermined("fr", true); 558 EXPECT_EQ(0U, contents()->infobar_count()); 559 } 560 561 // Test that reloading the page brings back the infobar. 562 TEST_F(TranslateManagerTest, Reload) { 563 // Simulate navigating to a page and getting its language. 564 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 565 566 // Close the infobar. 567 EXPECT_TRUE(CloseTranslateInfoBar()); 568 569 // Reload should bring back the infobar. 570 NavEntryCommittedObserver nav_observer(contents()); 571 Reload(); 572 573 // Ensures it is really handled a reload. 574 const NavigationController::LoadCommittedDetails& nav_details = 575 nav_observer.get_load_commited_details(); 576 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation. 577 EXPECT_EQ(NavigationType::EXISTING_PAGE, nav_details.type); 578 579 // The TranslateManager class processes the navigation entry committed 580 // notification in a posted task; process that task. 581 MessageLoop::current()->RunAllPending(); 582 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 583 } 584 585 // Test that reloading the page by way of typing again the URL in the 586 // location bar brings back the infobar. 587 TEST_F(TranslateManagerTest, ReloadFromLocationBar) { 588 GURL url("http://www.google.fr"); 589 590 // Simulate navigating to a page and getting its language. 591 SimulateNavigation(url, "fr", true); 592 593 // Close the infobar. 594 EXPECT_TRUE(CloseTranslateInfoBar()); 595 596 // Create a pending navigation and simulate a page load. That should be the 597 // equivalent of typing the URL again in the location bar. 598 NavEntryCommittedObserver nav_observer(contents()); 599 contents()->controller().LoadURL(url, GURL(), PageTransition::TYPED); 600 rvh()->SendNavigate(0, url); 601 602 // Test that we are really getting a same page navigation, the test would be 603 // useless if it was not the case. 604 const NavigationController::LoadCommittedDetails& nav_details = 605 nav_observer.get_load_commited_details(); 606 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation. 607 EXPECT_EQ(NavigationType::SAME_PAGE, nav_details.type); 608 609 // The TranslateManager class processes the navigation entry committed 610 // notification in a posted task; process that task. 611 MessageLoop::current()->RunAllPending(); 612 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 613 } 614 615 // Tests that a closed translate infobar does not reappear when navigating 616 // in-page. 617 TEST_F(TranslateManagerTest, CloseInfoBarInPageNavigation) { 618 // Simulate navigating to a page and getting its language. 619 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 620 621 // Close the infobar. 622 EXPECT_TRUE(CloseTranslateInfoBar()); 623 624 // Navigate in page, no infobar should be shown. 625 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", 626 true); 627 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 628 629 // Navigate out of page, a new infobar should show. 630 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 631 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 632 } 633 634 // Tests that a closed translate infobar does not reappear when navigating 635 // in a subframe. (http://crbug.com/48215) 636 TEST_F(TranslateManagerTest, CloseInfoBarInSubframeNavigation) { 637 // Simulate navigating to a page and getting its language. 638 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 639 640 // Close the infobar. 641 EXPECT_TRUE(CloseTranslateInfoBar()); 642 643 // Simulate a sub-frame auto-navigating. 644 rvh()->SendNavigateWithTransition(1, GURL("http://pub.com"), 645 PageTransition::AUTO_SUBFRAME); 646 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 647 648 // Simulate the user navigating in a sub-frame. 649 rvh()->SendNavigateWithTransition(2, GURL("http://pub.com"), 650 PageTransition::MANUAL_SUBFRAME); 651 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 652 653 // Navigate out of page, a new infobar should show. 654 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 655 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 656 } 657 658 659 660 // Tests that denying translation is sticky when navigating in page. 661 TEST_F(TranslateManagerTest, DenyTranslateInPageNavigation) { 662 // Simulate navigating to a page and getting its language. 663 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 664 665 // Simulate clicking 'Nope' (don't translate). 666 EXPECT_TRUE(DenyTranslation()); 667 668 // Navigate in page, no infobar should be shown. 669 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true); 670 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 671 672 // Navigate out of page, a new infobar should show. 673 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 674 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 675 } 676 677 // Tests that after translating and closing the infobar, the infobar does not 678 // return when navigating in page. 679 TEST_F(TranslateManagerTest, TranslateCloseInfoBarInPageNavigation) { 680 // Simulate navigating to a page and getting its language. 681 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 682 683 // Simulate the user translating. 684 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 685 ASSERT_TRUE(infobar != NULL); 686 infobar->Translate(); 687 SimulateURLFetch(true); // Simulate the translate script being retrieved. 688 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 689 TranslateErrors::NONE)); 690 691 // Close the infobar. 692 EXPECT_TRUE(CloseTranslateInfoBar()); 693 694 // Navigate in page, no infobar should be shown. 695 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true); 696 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 697 698 // Navigate out of page, a new infobar should show. 699 // Note that we navigate to a page in a different language so we don't trigger 700 // the auto-translate feature (it would translate the page automatically and 701 // the before translate inforbar would not be shown). 702 SimulateNavigation(GURL("http://www.google.de"), "de", true); 703 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 704 } 705 706 // Tests that the after translate the infobar still shows when navigating 707 // in-page. 708 TEST_F(TranslateManagerTest, TranslateInPageNavigation) { 709 // Simulate navigating to a page and getting its language. 710 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 711 712 // Simulate the user translating. 713 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 714 ASSERT_TRUE(infobar != NULL); 715 infobar->Translate(); 716 SimulateURLFetch(true); // Simulate the translate script being retrieved. 717 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 718 TranslateErrors::NONE)); 719 // The after translate infobar is showing. 720 infobar = GetTranslateInfoBar(); 721 ASSERT_TRUE(infobar != NULL); 722 723 // Navigate in page, the same infobar should still be shown. 724 ClearRemovedInfoBars(); 725 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", 726 true); 727 EXPECT_FALSE(InfoBarRemoved()); 728 EXPECT_EQ(infobar, GetTranslateInfoBar()); 729 730 // Navigate out of page, a new infobar should show. 731 // See note in TranslateCloseInfoBarInPageNavigation test on why it is 732 // important to navigate to a page in a different language for this test. 733 SimulateNavigation(GURL("http://www.google.de"), "de", true); 734 // The old infobar is gone. 735 EXPECT_TRUE(CheckInfoBarRemovedAndReset(infobar)); 736 // And there is a new one. 737 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 738 } 739 740 // Tests that no translate infobar is shown when navigating to a page in an 741 // unsupported language. 742 TEST_F(TranslateManagerTest, CLDReportsUnsupportedPageLanguage) { 743 // Simulate navigating to a page and getting an unsupported language. 744 SimulateNavigation(GURL("http://www.google.com"), "qbz", true); 745 746 // No info-bar should be shown. 747 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 748 } 749 750 // Tests that we deal correctly with unsupported languages returned by the 751 // server. 752 // The translation server might return a language we don't support. 753 TEST_F(TranslateManagerTest, ServerReportsUnsupportedLanguage) { 754 // Simulate navigating to a page and translating it. 755 SimulateNavigation(GURL("http://mail.google.fr"), "fr", true); 756 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 757 ASSERT_TRUE(infobar != NULL); 758 process()->sink().ClearMessages(); 759 infobar->Translate(); 760 SimulateURLFetch(true); 761 // Simulate the render notifying the translation has been done, but it 762 // reports a language we don't support. 763 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "qbz", "en", 764 TranslateErrors::NONE)); 765 766 // An error infobar should be showing to report that we don't support this 767 // language. 768 infobar = GetTranslateInfoBar(); 769 ASSERT_TRUE(infobar != NULL); 770 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, infobar->type()); 771 772 // This infobar should have a button (so the string should not be empty). 773 ASSERT_FALSE(infobar->GetMessageInfoBarButtonText().empty()); 774 775 // Pressing the button on that infobar should revert to the original language. 776 process()->sink().ClearMessages(); 777 infobar->MessageInfoBarButtonPressed(); 778 const IPC::Message* message = 779 process()->sink().GetFirstMessageMatching(ViewMsg_RevertTranslation::ID); 780 EXPECT_TRUE(message != NULL); 781 // And it should have removed the infobar. 782 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 783 } 784 785 // Tests that no translate infobar is shown when Chrome is in a language that 786 // the translate server does not support. 787 TEST_F(TranslateManagerTest, UnsupportedUILanguage) { 788 TestingBrowserProcess* browser_process = 789 static_cast<TestingBrowserProcess*>(g_browser_process); 790 std::string original_lang = browser_process->GetApplicationLocale(); 791 browser_process->SetApplicationLocale("qbz"); 792 793 // Simulate navigating to a page in a language supported by the translate 794 // server. 795 SimulateNavigation(GURL("http://www.google.com"), "en", true); 796 797 // No info-bar should be shown. 798 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 799 800 browser_process->SetApplicationLocale(original_lang); 801 } 802 803 // Tests that the translate enabled preference is honored. 804 TEST_F(TranslateManagerTest, TranslateEnabledPref) { 805 // Make sure the pref allows translate. 806 PrefService* prefs = contents()->profile()->GetPrefs(); 807 prefs->SetBoolean(prefs::kEnableTranslate, true); 808 809 // Simulate navigating to a page and getting its language. 810 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 811 812 // An infobar should be shown. 813 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 814 EXPECT_TRUE(infobar != NULL); 815 816 // Disable translate. 817 prefs->SetBoolean(prefs::kEnableTranslate, false); 818 819 // Navigate to a new page, that should close the previous infobar. 820 GURL url("http://www.youtube.fr"); 821 NavigateAndCommit(url); 822 infobar = GetTranslateInfoBar(); 823 EXPECT_TRUE(infobar == NULL); 824 825 // Simulate getting the page contents and language, that should not trigger 826 // a translate infobar. 827 SimulateOnTranslateLanguageDetermined("fr", true); 828 infobar = GetTranslateInfoBar(); 829 EXPECT_TRUE(infobar == NULL); 830 } 831 832 // Tests the "Never translate <language>" pref. 833 TEST_F(TranslateManagerTest, NeverTranslateLanguagePref) { 834 // Simulate navigating to a page and getting its language. 835 GURL url("http://www.google.fr"); 836 SimulateNavigation(url, "fr", true); 837 838 // An infobar should be shown. 839 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 840 841 // Select never translate this language. 842 PrefService* prefs = contents()->profile()->GetPrefs(); 843 PrefChangeRegistrar registrar; 844 registrar.Init(prefs); 845 registrar.Add(TranslatePrefs::kPrefTranslateLanguageBlacklist, 846 &pref_observer_); 847 TranslatePrefs translate_prefs(prefs); 848 EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr")); 849 EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); 850 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist); 851 translate_prefs.BlacklistLanguage("fr"); 852 EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("fr")); 853 EXPECT_FALSE(translate_prefs.CanTranslate(prefs, "fr", url)); 854 855 // Close the infobar. 856 EXPECT_TRUE(CloseTranslateInfoBar()); 857 858 // Navigate to a new page also in French. 859 SimulateNavigation(GURL("http://wwww.youtube.fr"), "fr", true); 860 861 // There should not be a translate infobar. 862 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 863 864 // Remove the language from the blacklist. 865 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist); 866 translate_prefs.RemoveLanguageFromBlacklist("fr"); 867 EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr")); 868 EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); 869 870 // Navigate to a page in French. 871 SimulateNavigation(url, "fr", true); 872 873 // There should be a translate infobar. 874 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 875 } 876 877 // Tests the "Never translate this site" pref. 878 TEST_F(TranslateManagerTest, NeverTranslateSitePref) { 879 // Simulate navigating to a page and getting its language. 880 GURL url("http://www.google.fr"); 881 std::string host(url.host()); 882 SimulateNavigation(url, "fr", true); 883 884 // An infobar should be shown. 885 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 886 887 // Select never translate this site. 888 PrefService* prefs = contents()->profile()->GetPrefs(); 889 PrefChangeRegistrar registrar; 890 registrar.Init(prefs); 891 registrar.Add(TranslatePrefs::kPrefTranslateSiteBlacklist, 892 &pref_observer_); 893 TranslatePrefs translate_prefs(prefs); 894 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(host)); 895 EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); 896 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist); 897 translate_prefs.BlacklistSite(host); 898 EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(host)); 899 EXPECT_FALSE(translate_prefs.CanTranslate(prefs, "fr", url)); 900 901 // Close the infobar. 902 EXPECT_TRUE(CloseTranslateInfoBar()); 903 904 // Navigate to a new page also on the same site. 905 SimulateNavigation(GURL("http://www.google.fr/hello"), "fr", true); 906 907 // There should not be a translate infobar. 908 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 909 910 // Remove the site from the blacklist. 911 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist); 912 translate_prefs.RemoveSiteFromBlacklist(host); 913 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(host)); 914 EXPECT_TRUE(translate_prefs.CanTranslate(prefs, "fr", url)); 915 916 // Navigate to a page in French. 917 SimulateNavigation(url, "fr", true); 918 919 // There should be a translate infobar. 920 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 921 } 922 923 // Tests the "Always translate this language" pref. 924 TEST_F(TranslateManagerTest, AlwaysTranslateLanguagePref) { 925 // Select always translate French to English. 926 PrefService* prefs = contents()->profile()->GetPrefs(); 927 PrefChangeRegistrar registrar; 928 registrar.Init(prefs); 929 registrar.Add(TranslatePrefs::kPrefTranslateWhitelists, 930 &pref_observer_); 931 TranslatePrefs translate_prefs(prefs); 932 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists); 933 translate_prefs.WhitelistLanguagePair("fr", "en"); 934 935 // Load a page in French. 936 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 937 938 // It should have triggered an automatic translation to English. 939 940 // The translating infobar should be showing. 941 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 942 ASSERT_TRUE(infobar != NULL); 943 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->type()); 944 945 SimulateURLFetch(true); // Simulate the translate script being retrieved. 946 int page_id = 0; 947 std::string original_lang, target_lang; 948 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 949 EXPECT_EQ("fr", original_lang); 950 EXPECT_EQ("en", target_lang); 951 process()->sink().ClearMessages(); 952 953 // Try another language, it should not be autotranslated. 954 SimulateNavigation(GURL("http://www.google.es"), "es", true); 955 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 956 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 957 EXPECT_TRUE(CloseTranslateInfoBar()); 958 959 // Let's switch to incognito mode, it should not be autotranslated in that 960 // case either. 961 TestingProfile* test_profile = 962 static_cast<TestingProfile*>(contents()->profile()); 963 test_profile->set_incognito(true); 964 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true); 965 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 966 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 967 EXPECT_TRUE(CloseTranslateInfoBar()); 968 test_profile->set_incognito(false); // Get back to non incognito. 969 970 // Now revert the always translate pref and make sure we go back to expected 971 // behavior, which is show a "before translate" infobar. 972 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists); 973 translate_prefs.RemoveLanguagePairFromWhitelist("fr", "en"); 974 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 975 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 976 infobar = GetTranslateInfoBar(); 977 ASSERT_TRUE(infobar != NULL); 978 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); 979 } 980 981 // Context menu. 982 TEST_F(TranslateManagerTest, ContextMenu) { 983 // Blacklist www.google.fr and French for translation. 984 GURL url("http://www.google.fr"); 985 TranslatePrefs translate_prefs(contents()->profile()->GetPrefs()); 986 translate_prefs.BlacklistLanguage("fr"); 987 translate_prefs.BlacklistSite(url.host()); 988 EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("fr")); 989 EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(url.host())); 990 991 // Simulate navigating to a page in French. The translate menu should show but 992 // should only be enabled when the page language has been received. 993 NavigateAndCommit(url); 994 scoped_ptr<TestRenderViewContextMenu> menu( 995 TestRenderViewContextMenu::CreateContextMenu(contents())); 996 menu->Init(); 997 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 998 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 999 1000 // Simulate receiving the language. 1001 SimulateOnTranslateLanguageDetermined("fr", true); 1002 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1003 menu->Init(); 1004 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1005 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1006 1007 // Use the menu to translate the page. 1008 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 1009 1010 // That should have triggered a translation. 1011 // The "translating..." infobar should be showing. 1012 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 1013 ASSERT_TRUE(infobar != NULL); 1014 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->type()); 1015 SimulateURLFetch(true); // Simulate the translate script being retrieved. 1016 int page_id = 0; 1017 std::string original_lang, target_lang; 1018 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1019 EXPECT_EQ("fr", original_lang); 1020 EXPECT_EQ("en", target_lang); 1021 process()->sink().ClearMessages(); 1022 1023 // This should also have reverted the blacklisting of this site and language. 1024 EXPECT_FALSE(translate_prefs.IsLanguageBlacklisted("fr")); 1025 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host())); 1026 1027 // Let's simulate the page being translated. 1028 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 1029 TranslateErrors::NONE)); 1030 1031 // The translate menu should now be disabled. 1032 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1033 menu->Init(); 1034 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1035 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1036 1037 // Test that selecting translate in the context menu WHILE the page is being 1038 // translated does nothing (this could happen if autotranslate kicks-in and 1039 // the user selects the menu while the translation is being performed). 1040 SimulateNavigation(GURL("http://www.google.es"), "es", true); 1041 infobar = GetTranslateInfoBar(); 1042 ASSERT_TRUE(infobar != NULL); 1043 infobar->Translate(); 1044 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1045 process()->sink().ClearMessages(); 1046 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1047 menu->Init(); 1048 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1049 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 1050 // No message expected since the translation should have been ignored. 1051 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1052 1053 // Now test that selecting translate in the context menu AFTER the page has 1054 // been translated does nothing. 1055 SimulateNavigation(GURL("http://www.google.de"), "de", true); 1056 infobar = GetTranslateInfoBar(); 1057 ASSERT_TRUE(infobar != NULL); 1058 infobar->Translate(); 1059 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1060 process()->sink().ClearMessages(); 1061 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1062 menu->Init(); 1063 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1064 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "de", "en", 1065 TranslateErrors::NONE)); 1066 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE); 1067 // No message expected since the translation should have been ignored. 1068 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1069 1070 // Test that the translate context menu is enabled when the page is in an 1071 // unknown language. 1072 SimulateNavigation(url, "und", true); 1073 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1074 menu->Init(); 1075 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1076 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1077 1078 // Test that the translate context menu is disabled when the page is in an 1079 // unsupported language. 1080 SimulateNavigation(url, "qbz", true); 1081 menu.reset(TestRenderViewContextMenu::CreateContextMenu(contents())); 1082 menu->Init(); 1083 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1084 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1085 } 1086 1087 // Tests that an extra always/never translate button is shown on the "before 1088 // translate" infobar when the translation is accepted/declined 3 times, 1089 // only when not in incognito mode. 1090 TEST_F(TranslateManagerTest, BeforeTranslateExtraButtons) { 1091 TranslatePrefs translate_prefs(contents()->profile()->GetPrefs()); 1092 translate_prefs.ResetTranslationAcceptedCount("fr"); 1093 translate_prefs.ResetTranslationDeniedCount("fr"); 1094 translate_prefs.ResetTranslationAcceptedCount("de"); 1095 translate_prefs.ResetTranslationDeniedCount("de"); 1096 1097 // We'll do 4 times in incognito mode first to make sure the button is not 1098 // shown in that case, then 4 times in normal mode. 1099 TranslateInfoBarDelegate* infobar; 1100 TestingProfile* test_profile = 1101 static_cast<TestingProfile*>(contents()->profile()); 1102 test_profile->set_incognito(true); 1103 for (int i = 0; i < 8; ++i) { 1104 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 1105 " incognito mode=" << test_profile->IsOffTheRecord()); 1106 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1107 infobar = GetTranslateInfoBar(); 1108 ASSERT_TRUE(infobar != NULL); 1109 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); 1110 if (i < 7) { 1111 EXPECT_FALSE(infobar->ShouldShowAlwaysTranslateButton()); 1112 infobar->Translate(); 1113 process()->sink().ClearMessages(); 1114 } else { 1115 EXPECT_TRUE(infobar->ShouldShowAlwaysTranslateButton()); 1116 } 1117 if (i == 3) 1118 test_profile->set_incognito(false); 1119 } 1120 // Simulate the user pressing "Always translate French". 1121 infobar->AlwaysTranslatePageLanguage(); 1122 EXPECT_TRUE(translate_prefs.IsLanguagePairWhitelisted("fr", "en")); 1123 // Simulate the translate script being retrieved (it only needs to be done 1124 // once in the test as it is cached). 1125 SimulateURLFetch(true); 1126 // That should have triggered a page translate. 1127 int page_id = 0; 1128 std::string original_lang, target_lang; 1129 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1130 process()->sink().ClearMessages(); 1131 1132 // Now test that declining the translation causes a "never translate" button 1133 // to be shown (in non incognito mode only). 1134 test_profile->set_incognito(true); 1135 for (int i = 0; i < 8; ++i) { 1136 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 1137 " incognito mode=" << test_profile->IsOffTheRecord()); 1138 SimulateNavigation(GURL("http://www.google.de"), "de", true); 1139 infobar = GetTranslateInfoBar(); 1140 ASSERT_TRUE(infobar != NULL); 1141 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); 1142 if (i < 7) { 1143 EXPECT_FALSE(infobar->ShouldShowNeverTranslateButton()); 1144 infobar->TranslationDeclined(); 1145 } else { 1146 EXPECT_TRUE(infobar->ShouldShowNeverTranslateButton()); 1147 } 1148 if (i == 3) 1149 test_profile->set_incognito(false); 1150 } 1151 // Simulate the user pressing "Never translate French". 1152 infobar->NeverTranslatePageLanguage(); 1153 EXPECT_TRUE(translate_prefs.IsLanguageBlacklisted("de")); 1154 // No translation should have occured and the infobar should be gone. 1155 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1156 process()->sink().ClearMessages(); 1157 ASSERT_TRUE(GetTranslateInfoBar() == NULL); 1158 } 1159 1160 // Tests that we don't show a translate infobar when a page instructs that it 1161 // should not be translated. 1162 TEST_F(TranslateManagerTest, NonTranslatablePage) { 1163 // Simulate navigating to a page. 1164 SimulateNavigation(GURL("http://mail.google.fr"), "fr", false); 1165 1166 // We should not have an infobar. 1167 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 1168 1169 // The context menu should be disabled. 1170 scoped_ptr<TestRenderViewContextMenu> menu( 1171 TestRenderViewContextMenu::CreateContextMenu(contents())); 1172 menu->Init(); 1173 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1174 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1175 } 1176 1177 // Tests that the script is expired and refetched as expected. 1178 TEST_F(TranslateManagerTest, ScriptExpires) { 1179 ExpireTranslateScriptImmediately(); 1180 1181 // Simulate navigating to a page and translating it. 1182 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1183 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 1184 ASSERT_TRUE(infobar != NULL); 1185 process()->sink().ClearMessages(); 1186 infobar->Translate(); 1187 SimulateURLFetch(true); 1188 rvh()->TestOnMessageReceived(ViewHostMsg_PageTranslated(0, 0, "fr", "en", 1189 TranslateErrors::NONE)); 1190 1191 // A task should have been posted to clear the script, run it. 1192 MessageLoop::current()->RunAllPending(); 1193 1194 // Do another navigation and translation. 1195 SimulateNavigation(GURL("http://www.google.es"), "es", true); 1196 infobar = GetTranslateInfoBar(); 1197 ASSERT_TRUE(infobar != NULL); 1198 process()->sink().ClearMessages(); 1199 infobar->Translate(); 1200 // If we don't simulate the URL fetch, the TranslateManager should be waiting 1201 // for the script and no message should have been sent to the renderer. 1202 EXPECT_TRUE( 1203 process()->sink().GetFirstMessageMatching(ViewMsg_TranslatePage::ID) == 1204 NULL); 1205 // Now simulate the URL fetch. 1206 SimulateURLFetch(true); 1207 // Now the message should have been sent. 1208 int page_id = 0; 1209 std::string original_lang, target_lang; 1210 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1211 EXPECT_EQ("es", original_lang); 1212 EXPECT_EQ("en", target_lang); 1213 } 1214