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 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 #include <set> 7 #include <vector> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "base/prefs/pref_change_registrar.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/strings/stringprintf.h" 13 #include "chrome/app/chrome_command_ids.h" 14 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/extensions/test_extension_system.h" 16 #include "chrome/browser/infobars/infobar.h" 17 #include "chrome/browser/infobars/infobar_service.h" 18 #include "chrome/browser/prefs/session_startup_pref.h" 19 #include "chrome/browser/tab_contents/render_view_context_menu.h" 20 #include "chrome/browser/translate/translate_infobar_delegate.h" 21 #include "chrome/browser/translate/translate_language_list.h" 22 #include "chrome/browser/translate/translate_manager.h" 23 #include "chrome/browser/translate/translate_prefs.h" 24 #include "chrome/browser/translate/translate_script.h" 25 #include "chrome/browser/translate/translate_tab_helper.h" 26 #include "chrome/browser/ui/browser.h" 27 #include "chrome/browser/ui/tabs/tab_strip_model.h" 28 #include "chrome/common/pref_names.h" 29 #include "chrome/common/render_messages.h" 30 #include "chrome/common/translate/language_detection_details.h" 31 #include "chrome/common/url_constants.h" 32 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 33 #include "chrome/test/base/in_process_browser_test.h" 34 #include "chrome/test/base/testing_browser_process.h" 35 #include "chrome/test/base/testing_profile.h" 36 #include "chrome/test/base/ui_test_utils.h" 37 #include "content/public/browser/navigation_details.h" 38 #include "content/public/browser/navigation_entry.h" 39 #include "content/public/browser/notification_details.h" 40 #include "content/public/browser/notification_registrar.h" 41 #include "content/public/browser/web_contents.h" 42 #include "content/public/test/mock_render_process_host.h" 43 #include "content/public/test/test_renderer_host.h" 44 #include "net/url_request/test_url_fetcher_factory.h" 45 #include "net/url_request/url_fetcher_delegate.h" 46 #include "testing/gmock/include/gmock/gmock.h" 47 #include "third_party/WebKit/public/web/WebContextMenuData.h" 48 49 using content::RenderViewHostTester; 50 51 // An observer that keeps track of whether a navigation entry was committed. 52 class NavEntryCommittedObserver : public content::NotificationObserver { 53 public: 54 explicit NavEntryCommittedObserver(content::WebContents* web_contents) { 55 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 56 content::Source<content::NavigationController>( 57 &web_contents->GetController())); 58 } 59 60 virtual void Observe(int type, 61 const content::NotificationSource& source, 62 const content::NotificationDetails& details) OVERRIDE { 63 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED); 64 details_ = 65 *(content::Details<content::LoadCommittedDetails>(details).ptr()); 66 } 67 68 const content::LoadCommittedDetails& load_committed_details() const { 69 return details_; 70 } 71 72 private: 73 content::LoadCommittedDetails details_; 74 content::NotificationRegistrar registrar_; 75 76 DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver); 77 }; 78 79 class TranslateManagerBrowserTest : public ChromeRenderViewHostTestHarness, 80 public content::NotificationObserver { 81 public: 82 TranslateManagerBrowserTest() 83 : pref_callback_( 84 base::Bind(&TranslateManagerBrowserTest::OnPreferenceChanged, 85 base::Unretained(this))) { 86 } 87 88 // Simulates navigating to a page and getting the page contents and language 89 // for that navigation. 90 void SimulateNavigation(const GURL& url, 91 const std::string& lang, 92 bool page_translatable) { 93 NavigateAndCommit(url); 94 SimulateOnTranslateLanguageDetermined(lang, page_translatable); 95 } 96 97 void SimulateOnTranslateLanguageDetermined(const std::string& lang, 98 bool page_translatable) { 99 LanguageDetectionDetails details; 100 details.adopted_language = lang; 101 RenderViewHostTester::TestOnMessageReceived( 102 rvh(), 103 ChromeViewHostMsg_TranslateLanguageDetermined( 104 0, details, page_translatable)); 105 } 106 107 void SimulateOnPageTranslated(int routing_id, 108 const std::string& source_lang, 109 const std::string& target_lang, 110 TranslateErrors::Type error) { 111 RenderViewHostTester::TestOnMessageReceived( 112 rvh(), 113 ChromeViewHostMsg_PageTranslated( 114 routing_id, 0, source_lang, target_lang, error)); 115 } 116 117 void SimulateOnPageTranslated(const std::string& source_lang, 118 const std::string& target_lang) { 119 SimulateOnPageTranslated(0, source_lang, target_lang, 120 TranslateErrors::NONE); 121 } 122 123 bool GetTranslateMessage(int* page_id, 124 std::string* original_lang, 125 std::string* target_lang) { 126 const IPC::Message* message = 127 process()->sink().GetFirstMessageMatching( 128 ChromeViewMsg_TranslatePage::ID); 129 if (!message) 130 return false; 131 Tuple4<int, std::string, std::string, std::string> translate_param; 132 ChromeViewMsg_TranslatePage::Read(message, &translate_param); 133 if (page_id) 134 *page_id = translate_param.a; 135 // Ignore translate_param.b which is the script injected in the page. 136 if (original_lang) 137 *original_lang = translate_param.c; 138 if (target_lang) 139 *target_lang = translate_param.d; 140 return true; 141 } 142 143 InfoBarService* infobar_service() { 144 return InfoBarService::FromWebContents(web_contents()); 145 } 146 147 // Returns the translate infobar if there is 1 infobar and it is a translate 148 // infobar. 149 TranslateInfoBarDelegate* GetTranslateInfoBar() { 150 return (infobar_service()->infobar_count() == 1) ? 151 infobar_service()->infobar_at(0)->AsTranslateInfoBarDelegate() : NULL; 152 } 153 154 // If there is 1 infobar and it is a translate infobar, closes it and returns 155 // true. Returns false otherwise. 156 bool CloseTranslateInfoBar() { 157 InfoBarDelegate* infobar = GetTranslateInfoBar(); 158 if (!infobar) 159 return false; 160 infobar->InfoBarDismissed(); // Simulates closing the infobar. 161 infobar_service()->RemoveInfoBar(infobar); 162 return true; 163 } 164 165 // Checks whether |infobar| has been removed and clears the removed infobar 166 // list. 167 bool CheckInfoBarRemovedAndReset(InfoBarDelegate* delegate) { 168 bool found = removed_infobars_.count(delegate) != 0; 169 removed_infobars_.clear(); 170 return found; 171 } 172 173 void ExpireTranslateScriptImmediately() { 174 TranslateManager::GetInstance()->SetTranslateScriptExpirationDelay(0); 175 } 176 177 // If there is 1 infobar and it is a translate infobar, deny translation and 178 // returns true. Returns false otherwise. 179 bool DenyTranslation() { 180 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 181 if (!infobar) 182 return false; 183 infobar->TranslationDeclined(); 184 infobar_service()->RemoveInfoBar(infobar); 185 return true; 186 } 187 188 void ReloadAndWait(bool successful_reload) { 189 NavEntryCommittedObserver nav_observer(web_contents()); 190 if (successful_reload) 191 Reload(); 192 else 193 FailedReload(); 194 195 // Ensures it is really handled a reload. 196 const content::LoadCommittedDetails& nav_details = 197 nav_observer.load_committed_details(); 198 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation. 199 EXPECT_EQ(content::NAVIGATION_TYPE_EXISTING_PAGE, nav_details.type); 200 201 // The TranslateManager class processes the navigation entry committed 202 // notification in a posted task; process that task. 203 base::MessageLoop::current()->RunUntilIdle(); 204 } 205 206 virtual void Observe(int type, 207 const content::NotificationSource& source, 208 const content::NotificationDetails& details) { 209 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type); 210 removed_infobars_.insert( 211 content::Details<InfoBarRemovedDetails>(details)->first); 212 } 213 214 MOCK_METHOD1(OnPreferenceChanged, void(const std::string&)); 215 216 protected: 217 virtual void SetUp() { 218 // Access the TranslateManager singleton so it is created before we call 219 // ChromeRenderViewHostTestHarness::SetUp() to match what's done in Chrome, 220 // where the TranslateManager is created before the WebContents. This 221 // matters as they both register for similar events and we want the 222 // notifications to happen in the same sequence (TranslateManager first, 223 // WebContents second). Also clears the translate script so it is fetched 224 // everytime and sets the expiration delay to a large value by default (in 225 // case it was zeroed in a previous test). 226 TranslateManager::GetInstance()->ClearTranslateScript(); 227 TranslateManager::GetInstance()-> 228 SetTranslateScriptExpirationDelay(60 * 60 * 1000); 229 TranslateManager::GetInstance()->set_translate_max_reload_attemps(0); 230 231 ChromeRenderViewHostTestHarness::SetUp(); 232 InfoBarService::CreateForWebContents(web_contents()); 233 TranslateTabHelper::CreateForWebContents(web_contents()); 234 235 notification_registrar_.Add(this, 236 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, 237 content::Source<InfoBarService>(infobar_service())); 238 } 239 240 virtual void TearDown() { 241 process()->sink().ClearMessages(); 242 243 notification_registrar_.Remove(this, 244 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, 245 content::Source<InfoBarService>(infobar_service())); 246 247 ChromeRenderViewHostTestHarness::TearDown(); 248 } 249 250 void SimulateTranslateScriptURLFetch(bool success) { 251 net::TestURLFetcher* fetcher = 252 url_fetcher_factory_.GetFetcherByID(TranslateScript::kFetcherId); 253 ASSERT_TRUE(fetcher); 254 net::URLRequestStatus status; 255 status.set_status(success ? net::URLRequestStatus::SUCCESS : 256 net::URLRequestStatus::FAILED); 257 fetcher->set_url(fetcher->GetOriginalURL()); 258 fetcher->set_status(status); 259 fetcher->set_response_code(success ? 200 : 500); 260 fetcher->delegate()->OnURLFetchComplete(fetcher); 261 } 262 263 void SimulateSupportedLanguagesURLFetch( 264 bool success, 265 const std::vector<std::string>& languages, 266 bool use_alpha_languages, 267 const std::vector<std::string>& alpha_languages) { 268 net::URLRequestStatus status; 269 status.set_status(success ? net::URLRequestStatus::SUCCESS : 270 net::URLRequestStatus::FAILED); 271 272 std::string data; 273 if (success) { 274 data = base::StringPrintf( 275 "%s{\"sl\": {\"bla\": \"bla\"}, \"%s\": {", 276 TranslateLanguageList::kLanguageListCallbackName, 277 TranslateLanguageList::kTargetLanguagesKey); 278 const char* comma = ""; 279 for (size_t i = 0; i < languages.size(); ++i) { 280 data += base::StringPrintf( 281 "%s\"%s\": \"UnusedFullName\"", comma, languages[i].c_str()); 282 if (i == 0) 283 comma = ","; 284 } 285 286 if (use_alpha_languages) { 287 data += base::StringPrintf("},\"%s\": {", 288 TranslateLanguageList::kAlphaLanguagesKey); 289 comma = ""; 290 for (size_t i = 0; i < alpha_languages.size(); ++i) { 291 data += base::StringPrintf("%s\"%s\": 1", comma, 292 alpha_languages[i].c_str()); 293 if (i == 0) 294 comma = ","; 295 } 296 } 297 298 data += "}})"; 299 } 300 net::TestURLFetcher* fetcher = 301 url_fetcher_factory_.GetFetcherByID(TranslateLanguageList::kFetcherId); 302 ASSERT_TRUE(fetcher != NULL); 303 fetcher->set_url(fetcher->GetOriginalURL()); 304 fetcher->set_status(status); 305 fetcher->set_response_code(success ? 200 : 500); 306 fetcher->SetResponseString(data); 307 fetcher->delegate()->OnURLFetchComplete(fetcher); 308 } 309 310 void SetPrefObserverExpectation(const char* path) { 311 EXPECT_CALL(*this, OnPreferenceChanged(std::string(path))); 312 } 313 314 PrefChangeRegistrar::NamedChangeCallback pref_callback_; 315 316 private: 317 content::NotificationRegistrar notification_registrar_; 318 net::TestURLFetcherFactory url_fetcher_factory_; 319 320 // The infobars that have been removed. 321 // WARNING: the pointers point to deleted objects, use only for comparison. 322 std::set<InfoBarDelegate*> removed_infobars_; 323 324 DISALLOW_COPY_AND_ASSIGN(TranslateManagerBrowserTest); 325 }; 326 327 namespace { 328 329 class TestRenderViewContextMenu : public RenderViewContextMenu { 330 public: 331 static TestRenderViewContextMenu* CreateContextMenu( 332 content::WebContents* web_contents) { 333 content::ContextMenuParams params; 334 params.media_type = WebKit::WebContextMenuData::MediaTypeNone; 335 params.x = 0; 336 params.y = 0; 337 params.is_image_blocked = false; 338 params.media_flags = 0; 339 params.spellcheck_enabled = false; 340 params.is_editable = false; 341 params.page_url = web_contents->GetController().GetActiveEntry()->GetURL(); 342 #if defined(OS_MACOSX) 343 params.writing_direction_default = 0; 344 params.writing_direction_left_to_right = 0; 345 params.writing_direction_right_to_left = 0; 346 #endif // OS_MACOSX 347 params.edit_flags = WebKit::WebContextMenuData::CanTranslate; 348 return new TestRenderViewContextMenu(web_contents, params); 349 } 350 351 bool IsItemPresent(int id) { 352 return menu_model_.GetIndexOfCommandId(id) != -1; 353 } 354 355 virtual void PlatformInit() OVERRIDE { } 356 virtual void PlatformCancel() OVERRIDE { } 357 virtual bool GetAcceleratorForCommandId( 358 int command_id, 359 ui::Accelerator* accelerator) OVERRIDE { return false; } 360 361 private: 362 TestRenderViewContextMenu(content::WebContents* web_contents, 363 const content::ContextMenuParams& params) 364 : RenderViewContextMenu(web_contents, params) { 365 } 366 367 DISALLOW_COPY_AND_ASSIGN(TestRenderViewContextMenu); 368 }; 369 370 } // namespace 371 372 TEST_F(TranslateManagerBrowserTest, NormalTranslate) { 373 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 374 375 // We should have an infobar. 376 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 377 ASSERT_TRUE(infobar != NULL); 378 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 379 infobar->infobar_type()); 380 381 // Simulate clicking translate. 382 process()->sink().ClearMessages(); 383 infobar->Translate(); 384 385 // The "Translating..." infobar should be showing. 386 infobar = GetTranslateInfoBar(); 387 ASSERT_TRUE(infobar != NULL); 388 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->infobar_type()); 389 390 // Simulate the translate script being retrieved (it only needs to be done 391 // once in the test as it is cached). 392 SimulateTranslateScriptURLFetch(true); 393 394 // Test that we sent the right message to the renderer. 395 int page_id = 0; 396 std::string original_lang, target_lang; 397 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 398 EXPECT_EQ("fr", original_lang); 399 EXPECT_EQ("en", target_lang); 400 401 // Simulate the render notifying the translation has been done. 402 SimulateOnPageTranslated("fr", "en"); 403 404 // The after translate infobar should be showing. 405 infobar = GetTranslateInfoBar(); 406 ASSERT_TRUE(infobar != NULL); 407 EXPECT_EQ(TranslateInfoBarDelegate::AFTER_TRANSLATE, infobar->infobar_type()); 408 409 // Simulate changing the original language and translating. 410 process()->sink().ClearMessages(); 411 std::string new_original_lang = infobar->language_code_at(0); 412 infobar->set_original_language_index(0); 413 infobar->Translate(); 414 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 415 EXPECT_EQ(new_original_lang, original_lang); 416 EXPECT_EQ("en", target_lang); 417 // Simulate the render notifying the translation has been done. 418 SimulateOnPageTranslated(new_original_lang, "en"); 419 // infobar is now invalid. 420 TranslateInfoBarDelegate* new_infobar = GetTranslateInfoBar(); 421 ASSERT_TRUE(new_infobar != NULL); 422 infobar = new_infobar; 423 424 // Simulate changing the target language and translating. 425 process()->sink().ClearMessages(); 426 std::string new_target_lang = infobar->language_code_at(1); 427 infobar->set_target_language_index(1); 428 infobar->Translate(); 429 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 430 EXPECT_EQ(new_original_lang, original_lang); 431 EXPECT_EQ(new_target_lang, target_lang); 432 // Simulate the render notifying the translation has been done. 433 SimulateOnPageTranslated(new_original_lang, new_target_lang); 434 // infobar is now invalid. 435 new_infobar = GetTranslateInfoBar(); 436 ASSERT_TRUE(new_infobar != NULL); 437 438 // Verify reload keeps the same settings. 439 ReloadAndWait(true); 440 new_infobar = GetTranslateInfoBar(); 441 ASSERT_TRUE(new_infobar != NULL); 442 ASSERT_EQ(new_target_lang, infobar->target_language_code()); 443 } 444 445 TEST_F(TranslateManagerBrowserTest, TranslateScriptNotAvailable) { 446 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 447 448 // We should have an infobar. 449 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 450 ASSERT_TRUE(infobar != NULL); 451 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 452 infobar->infobar_type()); 453 454 // Simulate clicking translate. 455 process()->sink().ClearMessages(); 456 infobar->Translate(); 457 SimulateTranslateScriptURLFetch(false); 458 459 // We should not have sent any message to translate to the renderer. 460 EXPECT_FALSE(GetTranslateMessage(NULL, NULL, NULL)); 461 462 // And we should have an error infobar showing. 463 infobar = GetTranslateInfoBar(); 464 ASSERT_TRUE(infobar != NULL); 465 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, 466 infobar->infobar_type()); 467 } 468 469 // Ensures we deal correctly with pages for which the browser does not recognize 470 // the language (the translate server may or not detect the language). 471 TEST_F(TranslateManagerBrowserTest, TranslateUnknownLanguage) { 472 // Simulate navigating to a page ("und" is the string returned by the CLD for 473 // languages it does not recognize). 474 SimulateNavigation(GURL("http://www.google.mys"), "und", true); 475 476 // We should not have an infobar as we don't know the language. 477 ASSERT_TRUE(GetTranslateInfoBar() == NULL); 478 479 // Translate the page anyway throught the context menu. 480 scoped_ptr<TestRenderViewContextMenu> menu( 481 TestRenderViewContextMenu::CreateContextMenu(web_contents())); 482 menu->Init(); 483 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 484 485 // To test that bug #49018 if fixed, make sure we deal correctly with errors. 486 // Simulate a failure to fetch the translate script. 487 SimulateTranslateScriptURLFetch(false); 488 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 489 ASSERT_TRUE(infobar != NULL); 490 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, 491 infobar->infobar_type()); 492 EXPECT_TRUE(infobar->is_error()); 493 infobar->MessageInfoBarButtonPressed(); 494 SimulateTranslateScriptURLFetch(true); // This time succeed. 495 496 // Simulate the render notifying the translation has been done, the server 497 // having detected the page was in a known and supported language. 498 SimulateOnPageTranslated("fr", "en"); 499 500 // The after translate infobar should be showing. 501 infobar = GetTranslateInfoBar(); 502 ASSERT_TRUE(infobar != NULL); 503 EXPECT_EQ(TranslateInfoBarDelegate::AFTER_TRANSLATE, infobar->infobar_type()); 504 EXPECT_EQ("fr", infobar->original_language_code()); 505 EXPECT_EQ("en", infobar->target_language_code()); 506 507 // Let's run the same steps but this time the server detects the page is 508 // already in English. 509 SimulateNavigation(GURL("http://www.google.com"), "und", true); 510 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 511 menu->Init(); 512 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 513 SimulateOnPageTranslated(1, "en", "en", TranslateErrors::IDENTICAL_LANGUAGES); 514 infobar = GetTranslateInfoBar(); 515 ASSERT_TRUE(infobar != NULL); 516 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, 517 infobar->infobar_type()); 518 EXPECT_EQ(TranslateErrors::IDENTICAL_LANGUAGES, infobar->error_type()); 519 520 // Let's run the same steps again but this time the server fails to detect the 521 // page's language (it returns an empty string). 522 SimulateNavigation(GURL("http://www.google.com"), "und", true); 523 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 524 menu->Init(); 525 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 526 SimulateOnPageTranslated(2, std::string(), "en", 527 TranslateErrors::UNKNOWN_LANGUAGE); 528 infobar = GetTranslateInfoBar(); 529 ASSERT_TRUE(infobar != NULL); 530 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, 531 infobar->infobar_type()); 532 EXPECT_EQ(TranslateErrors::UNKNOWN_LANGUAGE, infobar->error_type()); 533 } 534 535 // Tests that we show/don't show an info-bar for the languages. 536 TEST_F(TranslateManagerBrowserTest, TestLanguages) { 537 std::vector<std::string> languages; 538 languages.push_back("en"); 539 languages.push_back("ja"); 540 languages.push_back("fr"); 541 languages.push_back("ht"); 542 languages.push_back("xx"); 543 languages.push_back("zh"); 544 languages.push_back("zh-CN"); 545 languages.push_back("und"); 546 547 GURL url("http://www.google.com"); 548 for (size_t i = 0; i < languages.size(); ++i) { 549 std::string lang = languages[i]; 550 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 551 " language=" << lang); 552 553 // We should not have a translate infobar. 554 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 555 ASSERT_TRUE(infobar == NULL); 556 557 SimulateNavigation(url, lang, true); 558 559 // Verify we have/don't have an info-bar as expected. 560 infobar = GetTranslateInfoBar(); 561 bool expected = TranslateManager::IsSupportedLanguage(lang) && 562 lang != "en"; 563 EXPECT_EQ(expected, infobar != NULL); 564 565 if (infobar != NULL) 566 EXPECT_TRUE(CloseTranslateInfoBar()); 567 } 568 } 569 570 // Test the fetching of languages from the translate server 571 TEST_F(TranslateManagerBrowserTest, FetchLanguagesFromTranslateServer) { 572 std::vector<std::string> server_languages; 573 // A list of languages to fake being returned by the translate server. 574 server_languages.push_back("aa"); 575 server_languages.push_back("ak"); 576 server_languages.push_back("ab"); 577 server_languages.push_back("en-CA"); 578 server_languages.push_back("zh"); 579 server_languages.push_back("yi"); 580 server_languages.push_back("fr-FR"); 581 server_languages.push_back("xx"); 582 583 std::vector<std::string> alpha_languages; 584 alpha_languages.push_back("aa"); 585 alpha_languages.push_back("yi"); 586 587 // First, get the default languages list. Note that calling 588 // GetSupportedLanguages() invokes RequestLanguageList() internally. 589 std::vector<std::string> default_supported_languages; 590 TranslateManager::GetSupportedLanguages(&default_supported_languages); 591 // To make sure we got the defaults and don't confuse them with the mocks. 592 ASSERT_NE(default_supported_languages.size(), server_languages.size()); 593 594 // Check that we still get the defaults until the URLFetch has completed. 595 std::vector<std::string> current_supported_languages; 596 TranslateManager::GetSupportedLanguages(¤t_supported_languages); 597 EXPECT_EQ(default_supported_languages, current_supported_languages); 598 599 // Also check that it didn't change if we failed the URL fetch. 600 SimulateSupportedLanguagesURLFetch(false, std::vector<std::string>(), 601 true, std::vector<std::string>()); 602 current_supported_languages.clear(); 603 TranslateManager::GetSupportedLanguages(¤t_supported_languages); 604 EXPECT_EQ(default_supported_languages, current_supported_languages); 605 606 // Now check that we got the appropriate set of languages from the server. 607 SimulateSupportedLanguagesURLFetch(true, server_languages, 608 true, alpha_languages); 609 current_supported_languages.clear(); 610 TranslateManager::GetSupportedLanguages(¤t_supported_languages); 611 // "xx" can't be displayed in the Translate inforbar, so this is eliminated. 612 EXPECT_EQ(server_languages.size() - 1, current_supported_languages.size()); 613 // Not sure we need to guarantee the order of languages, so we find them. 614 for (size_t i = 0; i < server_languages.size(); ++i) { 615 const std::string& lang = server_languages[i]; 616 if (lang == "xx") 617 continue; 618 EXPECT_NE(current_supported_languages.end(), 619 std::find(current_supported_languages.begin(), 620 current_supported_languages.end(), 621 lang)); 622 bool is_alpha = std::find(alpha_languages.begin(), 623 alpha_languages.end(), 624 lang) != alpha_languages.end(); 625 EXPECT_EQ(TranslateManager::IsAlphaLanguage(lang), is_alpha); 626 } 627 } 628 629 // Test the fetching of languages from the translate server without 'al' 630 // parameter. 631 TEST_F(TranslateManagerBrowserTest, 632 FetchLanguagesFromTranslateServerWithoutAlpha) { 633 std::vector<std::string> server_languages; 634 server_languages.push_back("aa"); 635 server_languages.push_back("ak"); 636 server_languages.push_back("ab"); 637 server_languages.push_back("en-CA"); 638 server_languages.push_back("zh"); 639 server_languages.push_back("yi"); 640 server_languages.push_back("fr-FR"); 641 server_languages.push_back("xx"); 642 643 std::vector<std::string> alpha_languages; 644 alpha_languages.push_back("aa"); 645 alpha_languages.push_back("yi"); 646 647 // call GetSupportedLanguages to call RequestLanguageList internally. 648 std::vector<std::string> default_supported_languages; 649 TranslateManager::GetSupportedLanguages(&default_supported_languages); 650 651 SimulateSupportedLanguagesURLFetch(true, server_languages, 652 false, alpha_languages); 653 654 std::vector<std::string> current_supported_languages; 655 TranslateManager::GetSupportedLanguages(¤t_supported_languages); 656 657 // "xx" can't be displayed in the Translate inforbar, so this is eliminated. 658 EXPECT_EQ(server_languages.size() - 1, current_supported_languages.size()); 659 660 for (size_t i = 0; i < server_languages.size(); ++i) { 661 const std::string& lang = server_languages[i]; 662 if (lang == "xx") 663 continue; 664 EXPECT_NE(current_supported_languages.end(), 665 std::find(current_supported_languages.begin(), 666 current_supported_languages.end(), 667 lang)); 668 EXPECT_FALSE(TranslateManager::IsAlphaLanguage(lang)); 669 } 670 } 671 672 // Tests auto-translate on page. 673 TEST_F(TranslateManagerBrowserTest, AutoTranslateOnNavigate) { 674 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 675 676 // Simulate the user translating. 677 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 678 ASSERT_TRUE(infobar != NULL); 679 infobar->Translate(); 680 // Simulate the translate script being retrieved. 681 SimulateTranslateScriptURLFetch(true); 682 SimulateOnPageTranslated("fr", "en"); 683 684 // Now navigate to a new page in the same language. 685 process()->sink().ClearMessages(); 686 SimulateNavigation(GURL("http://news.google.fr"), "fr", true); 687 688 // This should have automatically triggered a translation. 689 int page_id = 0; 690 std::string original_lang, target_lang; 691 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 692 EXPECT_EQ(1, page_id); 693 EXPECT_EQ("fr", original_lang); 694 EXPECT_EQ("en", target_lang); 695 696 // Now navigate to a page in a different language. 697 process()->sink().ClearMessages(); 698 SimulateNavigation(GURL("http://news.google.es"), "es", true); 699 700 // This should not have triggered a translate. 701 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 702 } 703 704 // Tests that multiple OnPageContents do not cause multiple infobars. 705 TEST_F(TranslateManagerBrowserTest, MultipleOnPageContents) { 706 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 707 708 // Simulate clicking 'Nope' (don't translate). 709 EXPECT_TRUE(DenyTranslation()); 710 EXPECT_EQ(0U, infobar_service()->infobar_count()); 711 712 // Send a new PageContents, we should not show an infobar. 713 SimulateOnTranslateLanguageDetermined("fr", true); 714 EXPECT_EQ(0U, infobar_service()->infobar_count()); 715 716 // Do the same steps but simulate closing the infobar this time. 717 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true); 718 EXPECT_TRUE(CloseTranslateInfoBar()); 719 EXPECT_EQ(0U, infobar_service()->infobar_count()); 720 SimulateOnTranslateLanguageDetermined("fr", true); 721 EXPECT_EQ(0U, infobar_service()->infobar_count()); 722 } 723 724 // Test that reloading the page brings back the infobar if the 725 // reload succeeded and does not bring it back the reload fails. 726 TEST_F(TranslateManagerBrowserTest, Reload) { 727 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 728 729 EXPECT_TRUE(CloseTranslateInfoBar()); 730 731 // Reload should bring back the infobar if the page succeds 732 ReloadAndWait(true); 733 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 734 735 EXPECT_TRUE(CloseTranslateInfoBar()); 736 737 // And not show it if the reload fails 738 ReloadAndWait(false); 739 EXPECT_EQ(NULL, GetTranslateInfoBar()); 740 741 // Set reload attempts to a high value, we will not see the infobar 742 // immediatly. 743 TranslateManager::GetInstance()->set_translate_max_reload_attemps(100); 744 ReloadAndWait(true); 745 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 746 } 747 748 // Test that reloading the page by way of typing again the URL in the 749 // location bar brings back the infobar. 750 TEST_F(TranslateManagerBrowserTest, ReloadFromLocationBar) { 751 GURL url("http://www.google.fr"); 752 SimulateNavigation(url, "fr", true); 753 754 EXPECT_TRUE(CloseTranslateInfoBar()); 755 756 // Create a pending navigation and simulate a page load. That should be the 757 // equivalent of typing the URL again in the location bar. 758 NavEntryCommittedObserver nav_observer(web_contents()); 759 web_contents()->GetController().LoadURL(url, content::Referrer(), 760 content::PAGE_TRANSITION_TYPED, 761 std::string()); 762 rvh_tester()->SendNavigate(0, url); 763 764 // Test that we are really getting a same page navigation, the test would be 765 // useless if it was not the case. 766 const content::LoadCommittedDetails& nav_details = 767 nav_observer.load_committed_details(); 768 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation. 769 EXPECT_EQ(content::NAVIGATION_TYPE_SAME_PAGE, nav_details.type); 770 771 // The TranslateManager class processes the navigation entry committed 772 // notification in a posted task; process that task. 773 base::MessageLoop::current()->RunUntilIdle(); 774 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 775 } 776 777 // Tests that a closed translate infobar does not reappear when navigating 778 // in-page. 779 TEST_F(TranslateManagerBrowserTest, CloseInfoBarInPageNavigation) { 780 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 781 782 EXPECT_TRUE(CloseTranslateInfoBar()); 783 784 // Navigate in page, no infobar should be shown. 785 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true); 786 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 787 788 // Navigate out of page, a new infobar should show. 789 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 790 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 791 } 792 793 // Tests that a closed translate infobar does not reappear when navigating 794 // in a subframe. (http://crbug.com/48215) 795 TEST_F(TranslateManagerBrowserTest, CloseInfoBarInSubframeNavigation) { 796 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 797 798 EXPECT_TRUE(CloseTranslateInfoBar()); 799 800 // Simulate a sub-frame auto-navigating. 801 rvh_tester()->SendNavigateWithTransition( 802 1, GURL("http://pub.com"), content::PAGE_TRANSITION_AUTO_SUBFRAME); 803 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 804 805 // Simulate the user navigating in a sub-frame. 806 rvh_tester()->SendNavigateWithTransition( 807 2, GURL("http://pub.com"), content::PAGE_TRANSITION_MANUAL_SUBFRAME); 808 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 809 810 // Navigate out of page, a new infobar should show. 811 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 812 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 813 } 814 815 // Tests that denying translation is sticky when navigating in page. 816 TEST_F(TranslateManagerBrowserTest, DenyTranslateInPageNavigation) { 817 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 818 819 // Simulate clicking 'Nope' (don't translate). 820 EXPECT_TRUE(DenyTranslation()); 821 822 // Navigate in page, no infobar should be shown. 823 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true); 824 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 825 826 // Navigate out of page, a new infobar should show. 827 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true); 828 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 829 } 830 831 // Tests that after translating and closing the infobar, the infobar does not 832 // return when navigating in page. 833 TEST_F(TranslateManagerBrowserTest, TranslateCloseInfoBarInPageNavigation) { 834 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 835 836 // Simulate the user translating. 837 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 838 ASSERT_TRUE(infobar != NULL); 839 infobar->Translate(); 840 // Simulate the translate script being retrieved. 841 SimulateTranslateScriptURLFetch(true); 842 SimulateOnPageTranslated("fr", "en"); 843 844 EXPECT_TRUE(CloseTranslateInfoBar()); 845 846 // Navigate in page, no infobar should be shown. 847 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true); 848 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 849 850 // Navigate out of page, a new infobar should show. 851 // Note that we navigate to a page in a different language so we don't trigger 852 // the auto-translate feature (it would translate the page automatically and 853 // the before translate inforbar would not be shown). 854 SimulateNavigation(GURL("http://www.google.de"), "de", true); 855 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 856 } 857 858 // Tests that the after translate the infobar still shows when navigating 859 // in-page. 860 TEST_F(TranslateManagerBrowserTest, TranslateInPageNavigation) { 861 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 862 863 // Simulate the user translating. 864 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 865 ASSERT_TRUE(infobar != NULL); 866 infobar->Translate(); 867 SimulateTranslateScriptURLFetch(true); 868 SimulateOnPageTranslated("fr", "en"); 869 // The after translate infobar is showing. 870 infobar = GetTranslateInfoBar(); 871 ASSERT_TRUE(infobar != NULL); 872 873 // Navigate out of page, a new infobar should show. 874 // See note in TranslateCloseInfoBarInPageNavigation test on why it is 875 // important to navigate to a page in a different language for this test. 876 SimulateNavigation(GURL("http://www.google.de"), "de", true); 877 // The old infobar is gone. 878 EXPECT_TRUE(CheckInfoBarRemovedAndReset(infobar)); 879 // And there is a new one. 880 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 881 } 882 883 // Tests that no translate infobar is shown when navigating to a page in an 884 // unsupported language. 885 TEST_F(TranslateManagerBrowserTest, CLDReportsUnsupportedPageLanguage) { 886 // Simulate navigating to a page and getting an unsupported language. 887 SimulateNavigation(GURL("http://www.google.com"), "qbz", true); 888 889 // No info-bar should be shown. 890 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 891 } 892 893 // Tests that we deal correctly with unsupported languages returned by the 894 // server. 895 // The translation server might return a language we don't support. 896 TEST_F(TranslateManagerBrowserTest, ServerReportsUnsupportedLanguage) { 897 SimulateNavigation(GURL("http://mail.google.fr"), "fr", true); 898 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 899 ASSERT_TRUE(infobar != NULL); 900 process()->sink().ClearMessages(); 901 infobar->Translate(); 902 SimulateTranslateScriptURLFetch(true); 903 // Simulate the render notifying the translation has been done, but it 904 // reports a language we don't support. 905 SimulateOnPageTranslated("qbz", "en"); 906 907 // An error infobar should be showing to report that we don't support this 908 // language. 909 infobar = GetTranslateInfoBar(); 910 ASSERT_TRUE(infobar != NULL); 911 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATION_ERROR, 912 infobar->infobar_type()); 913 914 // This infobar should have a button (so the string should not be empty). 915 ASSERT_FALSE(infobar->GetMessageInfoBarButtonText().empty()); 916 917 // Pressing the button on that infobar should revert to the original language. 918 process()->sink().ClearMessages(); 919 infobar->MessageInfoBarButtonPressed(); 920 const IPC::Message* message = 921 process()->sink().GetFirstMessageMatching( 922 ChromeViewMsg_RevertTranslation::ID); 923 EXPECT_TRUE(message != NULL); 924 // And it should have removed the infobar. 925 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 926 } 927 928 // Tests that no translate infobar is shown and context menu is disabled, when 929 // Chrome is in a language that the translate server does not support. 930 TEST_F(TranslateManagerBrowserTest, UnsupportedUILanguage) { 931 std::string original_lang = g_browser_process->GetApplicationLocale(); 932 g_browser_process->SetApplicationLocale("qbz"); 933 934 // Make sure that the accept language list only contains unsupported languages 935 Profile* profile = 936 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 937 PrefService* prefs = profile->GetPrefs(); 938 prefs->SetString(prefs::kAcceptLanguages, "qbz"); 939 940 // Simulate navigating to a page in a language supported by the translate 941 // server. 942 SimulateNavigation(GURL("http://www.google.com"), "en", true); 943 944 // No info-bar should be shown. 945 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 946 947 // And the context menu option should be disabled too. 948 scoped_ptr<TestRenderViewContextMenu> menu( 949 TestRenderViewContextMenu::CreateContextMenu(web_contents())); 950 menu->Init(); 951 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 952 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 953 954 g_browser_process->SetApplicationLocale(original_lang); 955 } 956 957 // Tests that the first supported accept language is selected 958 TEST_F(TranslateManagerBrowserTest, TranslateAcceptLanguage) { 959 // Set locate to non-existant language 960 std::string original_lang = g_browser_process->GetApplicationLocale(); 961 g_browser_process->SetApplicationLocale("qbz"); 962 963 // Set Qbz and French as the only accepted languages 964 Profile* profile = 965 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 966 PrefService* prefs = profile->GetPrefs(); 967 prefs->SetString(prefs::kAcceptLanguages, "qbz,fr"); 968 969 // Go to a German page 970 SimulateNavigation(GURL("http://google.de"), "de", true); 971 972 // Expect the infobar to pop up 973 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 974 975 // Set Qbz and English-US as the only accepted languages to test the country 976 // code removal code which was causing a crash as filed in Issue 90106, 977 // a crash caused by a language with a country code that wasn't recognized. 978 prefs->SetString(prefs::kAcceptLanguages, "qbz,en-us"); 979 980 // Go to a German page 981 SimulateNavigation(GURL("http://google.de"), "de", true); 982 983 // Expect the infobar to pop up 984 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 985 } 986 987 // Tests that the translate enabled preference is honored. 988 TEST_F(TranslateManagerBrowserTest, TranslateEnabledPref) { 989 // Make sure the pref allows translate. 990 Profile* profile = 991 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 992 PrefService* prefs = profile->GetPrefs(); 993 prefs->SetBoolean(prefs::kEnableTranslate, true); 994 995 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 996 997 // An infobar should be shown. 998 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 999 EXPECT_TRUE(infobar != NULL); 1000 1001 // Disable translate. 1002 prefs->SetBoolean(prefs::kEnableTranslate, false); 1003 1004 // Navigate to a new page, that should close the previous infobar. 1005 GURL url("http://www.youtube.fr"); 1006 NavigateAndCommit(url); 1007 infobar = GetTranslateInfoBar(); 1008 EXPECT_TRUE(infobar == NULL); 1009 1010 // Simulate getting the page contents and language, that should not trigger 1011 // a translate infobar. 1012 SimulateOnTranslateLanguageDetermined("fr", true); 1013 infobar = GetTranslateInfoBar(); 1014 EXPECT_TRUE(infobar == NULL); 1015 } 1016 1017 // Tests the "Never translate <language>" pref. 1018 TEST_F(TranslateManagerBrowserTest, NeverTranslateLanguagePref) { 1019 GURL url("http://www.google.fr"); 1020 SimulateNavigation(url, "fr", true); 1021 1022 // An infobar should be shown. 1023 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1024 1025 // Select never translate this language. 1026 Profile* profile = 1027 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 1028 PrefService* prefs = profile->GetPrefs(); 1029 PrefChangeRegistrar registrar; 1030 registrar.Init(prefs); 1031 registrar.Add(TranslatePrefs::kPrefTranslateLanguageBlacklist, 1032 pref_callback_); 1033 TranslatePrefs translate_prefs(prefs); 1034 EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr")); 1035 EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1036 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist); 1037 translate_prefs.BlockLanguage("fr"); 1038 EXPECT_TRUE(translate_prefs.IsBlockedLanguage("fr")); 1039 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host())); 1040 EXPECT_FALSE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1041 1042 EXPECT_TRUE(CloseTranslateInfoBar()); 1043 1044 // Navigate to a new page also in French. 1045 SimulateNavigation(GURL("http://wwww.youtube.fr"), "fr", true); 1046 1047 // There should not be a translate infobar. 1048 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 1049 1050 // Remove the language from the blacklist. 1051 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateLanguageBlacklist); 1052 translate_prefs.UnblockLanguage("fr"); 1053 EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr")); 1054 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host())); 1055 EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1056 1057 // Navigate to a page in French. 1058 SimulateNavigation(url, "fr", true); 1059 1060 // There should be a translate infobar. 1061 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1062 } 1063 1064 // Tests the "Never translate this site" pref. 1065 TEST_F(TranslateManagerBrowserTest, NeverTranslateSitePref) { 1066 GURL url("http://www.google.fr"); 1067 std::string host(url.host()); 1068 SimulateNavigation(url, "fr", true); 1069 1070 // An infobar should be shown. 1071 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1072 1073 // Select never translate this site. 1074 Profile* profile = 1075 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 1076 PrefService* prefs = profile->GetPrefs(); 1077 PrefChangeRegistrar registrar; 1078 registrar.Init(prefs); 1079 registrar.Add(TranslatePrefs::kPrefTranslateSiteBlacklist, pref_callback_); 1080 TranslatePrefs translate_prefs(prefs); 1081 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(host)); 1082 EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1083 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist); 1084 translate_prefs.BlacklistSite(host); 1085 EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(host)); 1086 EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1087 1088 EXPECT_TRUE(CloseTranslateInfoBar()); 1089 1090 // Navigate to a new page also on the same site. 1091 SimulateNavigation(GURL("http://www.google.fr/hello"), "fr", true); 1092 1093 // There should not be a translate infobar. 1094 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 1095 1096 // Remove the site from the blacklist. 1097 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist); 1098 translate_prefs.RemoveSiteFromBlacklist(host); 1099 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(host)); 1100 EXPECT_TRUE(translate_prefs.CanTranslateLanguage(profile, "fr")); 1101 1102 // Navigate to a page in French. 1103 SimulateNavigation(url, "fr", true); 1104 1105 // There should be a translate infobar. 1106 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1107 } 1108 1109 // Tests the "Always translate this language" pref. 1110 TEST_F(TranslateManagerBrowserTest, AlwaysTranslateLanguagePref) { 1111 // Select always translate French to English. 1112 Profile* profile = 1113 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 1114 PrefService* prefs = profile->GetPrefs(); 1115 PrefChangeRegistrar registrar; 1116 registrar.Init(prefs); 1117 registrar.Add(TranslatePrefs::kPrefTranslateWhitelists, pref_callback_); 1118 TranslatePrefs translate_prefs(prefs); 1119 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists); 1120 translate_prefs.WhitelistLanguagePair("fr", "en"); 1121 1122 // Load a page in French. 1123 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1124 1125 // It should have triggered an automatic translation to English. 1126 1127 // The translating infobar should be showing. 1128 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 1129 ASSERT_TRUE(infobar != NULL); 1130 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->infobar_type()); 1131 SimulateTranslateScriptURLFetch(true); 1132 int page_id = 0; 1133 std::string original_lang, target_lang; 1134 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1135 EXPECT_EQ("fr", original_lang); 1136 EXPECT_EQ("en", target_lang); 1137 process()->sink().ClearMessages(); 1138 1139 // Try another language, it should not be autotranslated. 1140 SimulateNavigation(GURL("http://www.google.es"), "es", true); 1141 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1142 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1143 EXPECT_TRUE(CloseTranslateInfoBar()); 1144 1145 // Let's switch to incognito mode, it should not be autotranslated in that 1146 // case either. 1147 TestingProfile* test_profile = 1148 static_cast<TestingProfile*>(web_contents()->GetBrowserContext()); 1149 test_profile->set_incognito(true); 1150 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true); 1151 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1152 EXPECT_TRUE(GetTranslateInfoBar() != NULL); 1153 EXPECT_TRUE(CloseTranslateInfoBar()); 1154 test_profile->set_incognito(false); // Get back to non incognito. 1155 1156 // Now revert the always translate pref and make sure we go back to expected 1157 // behavior, which is show a "before translate" infobar. 1158 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists); 1159 translate_prefs.RemoveLanguagePairFromWhitelist("fr", "en"); 1160 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1161 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1162 infobar = GetTranslateInfoBar(); 1163 ASSERT_TRUE(infobar != NULL); 1164 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 1165 infobar->infobar_type()); 1166 } 1167 1168 // Context menu. 1169 TEST_F(TranslateManagerBrowserTest, ContextMenu) { 1170 // Blacklist www.google.fr and French for translation. 1171 GURL url("http://www.google.fr"); 1172 Profile* profile = 1173 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 1174 TranslatePrefs translate_prefs(profile->GetPrefs()); 1175 translate_prefs.BlockLanguage("fr"); 1176 translate_prefs.BlacklistSite(url.host()); 1177 EXPECT_TRUE(translate_prefs.IsBlockedLanguage("fr")); 1178 EXPECT_TRUE(translate_prefs.IsSiteBlacklisted(url.host())); 1179 1180 // Simulate navigating to a page in French. The translate menu should show but 1181 // should only be enabled when the page language has been received. 1182 NavigateAndCommit(url); 1183 scoped_ptr<TestRenderViewContextMenu> menu( 1184 TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1185 menu->Init(); 1186 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1187 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1188 1189 // Simulate receiving the language. 1190 SimulateOnTranslateLanguageDetermined("fr", true); 1191 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1192 menu->Init(); 1193 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1194 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1195 1196 // Use the menu to translate the page. 1197 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 1198 1199 // That should have triggered a translation. 1200 // The "translating..." infobar should be showing. 1201 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 1202 ASSERT_TRUE(infobar != NULL); 1203 EXPECT_EQ(TranslateInfoBarDelegate::TRANSLATING, infobar->infobar_type()); 1204 SimulateTranslateScriptURLFetch(true); 1205 int page_id = 0; 1206 std::string original_lang, target_lang; 1207 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1208 EXPECT_EQ("fr", original_lang); 1209 EXPECT_EQ("en", target_lang); 1210 process()->sink().ClearMessages(); 1211 1212 // This should also have reverted the blacklisting of this site and language. 1213 EXPECT_FALSE(translate_prefs.IsBlockedLanguage("fr")); 1214 EXPECT_FALSE(translate_prefs.IsSiteBlacklisted(url.host())); 1215 1216 // Let's simulate the page being translated. 1217 SimulateOnPageTranslated("fr", "en"); 1218 1219 // The translate menu should now be disabled. 1220 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1221 menu->Init(); 1222 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1223 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1224 1225 // Test that selecting translate in the context menu WHILE the page is being 1226 // translated does nothing (this could happen if autotranslate kicks-in and 1227 // the user selects the menu while the translation is being performed). 1228 SimulateNavigation(GURL("http://www.google.es"), "es", true); 1229 infobar = GetTranslateInfoBar(); 1230 ASSERT_TRUE(infobar != NULL); 1231 infobar->Translate(); 1232 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1233 process()->sink().ClearMessages(); 1234 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1235 menu->Init(); 1236 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1237 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 1238 // No message expected since the translation should have been ignored. 1239 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1240 1241 // Now test that selecting translate in the context menu AFTER the page has 1242 // been translated does nothing. 1243 SimulateNavigation(GURL("http://www.google.de"), "de", true); 1244 infobar = GetTranslateInfoBar(); 1245 ASSERT_TRUE(infobar != NULL); 1246 infobar->Translate(); 1247 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1248 process()->sink().ClearMessages(); 1249 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1250 menu->Init(); 1251 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1252 SimulateOnPageTranslated("de", "en"); 1253 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0); 1254 // No message expected since the translation should have been ignored. 1255 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1256 1257 // Test that the translate context menu is enabled when the page is in an 1258 // unknown language. 1259 SimulateNavigation(url, "und", true); 1260 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1261 menu->Init(); 1262 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1263 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1264 1265 // Test that the translate context menu is enabled even if the page is in an 1266 // unsupported language. 1267 SimulateNavigation(url, "qbz", true); 1268 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1269 menu->Init(); 1270 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1271 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1272 } 1273 1274 // Tests that an extra always/never translate button is shown on the "before 1275 // translate" infobar when the translation is accepted/declined 3 times, 1276 // only when not in incognito mode. 1277 TEST_F(TranslateManagerBrowserTest, BeforeTranslateExtraButtons) { 1278 Profile* profile = 1279 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 1280 TranslatePrefs translate_prefs(profile->GetPrefs()); 1281 translate_prefs.ResetTranslationAcceptedCount("fr"); 1282 translate_prefs.ResetTranslationDeniedCount("fr"); 1283 translate_prefs.ResetTranslationAcceptedCount("de"); 1284 translate_prefs.ResetTranslationDeniedCount("de"); 1285 1286 // We'll do 4 times in incognito mode first to make sure the button is not 1287 // shown in that case, then 4 times in normal mode. 1288 TranslateInfoBarDelegate* infobar; 1289 TestingProfile* test_profile = 1290 static_cast<TestingProfile*>(web_contents()->GetBrowserContext()); 1291 static_cast<extensions::TestExtensionSystem*>( 1292 extensions::ExtensionSystem::Get(test_profile))-> 1293 CreateExtensionProcessManager(); 1294 test_profile->set_incognito(true); 1295 for (int i = 0; i < 8; ++i) { 1296 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 1297 " incognito mode=" << test_profile->IsOffTheRecord()); 1298 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1299 infobar = GetTranslateInfoBar(); 1300 ASSERT_TRUE(infobar != NULL); 1301 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 1302 infobar->infobar_type()); 1303 if (i < 7) { 1304 EXPECT_FALSE(infobar->ShouldShowAlwaysTranslateShortcut()); 1305 infobar->Translate(); 1306 process()->sink().ClearMessages(); 1307 } else { 1308 EXPECT_TRUE(infobar->ShouldShowAlwaysTranslateShortcut()); 1309 } 1310 if (i == 3) 1311 test_profile->set_incognito(false); 1312 } 1313 // Simulate the user pressing "Always translate French". 1314 infobar->AlwaysTranslatePageLanguage(); 1315 EXPECT_TRUE(translate_prefs.IsLanguagePairWhitelisted("fr", "en")); 1316 // Simulate the translate script being retrieved (it only needs to be done 1317 // once in the test as it is cached). 1318 SimulateTranslateScriptURLFetch(true); 1319 // That should have triggered a page translate. 1320 int page_id = 0; 1321 std::string original_lang, target_lang; 1322 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1323 process()->sink().ClearMessages(); 1324 1325 // Now test that declining the translation causes a "never translate" button 1326 // to be shown (in non incognito mode only). 1327 test_profile->set_incognito(true); 1328 for (int i = 0; i < 8; ++i) { 1329 SCOPED_TRACE(::testing::Message() << "Iteration " << i << 1330 " incognito mode=" << test_profile->IsOffTheRecord()); 1331 SimulateNavigation(GURL("http://www.google.de"), "de", true); 1332 infobar = GetTranslateInfoBar(); 1333 ASSERT_TRUE(infobar != NULL); 1334 EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, 1335 infobar->infobar_type()); 1336 if (i < 7) { 1337 EXPECT_FALSE(infobar->ShouldShowNeverTranslateShortcut()); 1338 infobar->TranslationDeclined(); 1339 } else { 1340 EXPECT_TRUE(infobar->ShouldShowNeverTranslateShortcut()); 1341 } 1342 if (i == 3) 1343 test_profile->set_incognito(false); 1344 } 1345 // Simulate the user pressing "Never translate French". 1346 infobar->NeverTranslatePageLanguage(); 1347 EXPECT_TRUE(translate_prefs.IsBlockedLanguage("de")); 1348 // No translation should have occured and the infobar should be gone. 1349 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1350 process()->sink().ClearMessages(); 1351 ASSERT_TRUE(GetTranslateInfoBar() == NULL); 1352 } 1353 1354 // Tests that we don't show a translate infobar when a page instructs that it 1355 // should not be translated. 1356 TEST_F(TranslateManagerBrowserTest, NonTranslatablePage) { 1357 SimulateNavigation(GURL("http://mail.google.fr"), "fr", false); 1358 1359 // We should not have an infobar. 1360 EXPECT_TRUE(GetTranslateInfoBar() == NULL); 1361 1362 // The context menu is enabled to allow users to force translation. 1363 scoped_ptr<TestRenderViewContextMenu> menu( 1364 TestRenderViewContextMenu::CreateContextMenu(web_contents())); 1365 menu->Init(); 1366 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE)); 1367 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE)); 1368 } 1369 1370 // Tests that the script is expired and refetched as expected. 1371 TEST_F(TranslateManagerBrowserTest, ScriptExpires) { 1372 ExpireTranslateScriptImmediately(); 1373 1374 SimulateNavigation(GURL("http://www.google.fr"), "fr", true); 1375 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar(); 1376 ASSERT_TRUE(infobar != NULL); 1377 process()->sink().ClearMessages(); 1378 infobar->Translate(); 1379 SimulateTranslateScriptURLFetch(true); 1380 SimulateOnPageTranslated("fr", "en"); 1381 1382 // A task should have been posted to clear the script, run it. 1383 base::MessageLoop::current()->RunUntilIdle(); 1384 1385 // Do another navigation and translation. 1386 SimulateNavigation(GURL("http://www.google.es"), "es", true); 1387 infobar = GetTranslateInfoBar(); 1388 ASSERT_TRUE(infobar != NULL); 1389 process()->sink().ClearMessages(); 1390 infobar->Translate(); 1391 // If we don't simulate the URL fetch, the TranslateManager should be waiting 1392 // for the script and no message should have been sent to the renderer. 1393 EXPECT_TRUE( 1394 process()->sink().GetFirstMessageMatching( 1395 ChromeViewMsg_TranslatePage::ID) == NULL); 1396 // Now simulate the URL fetch. 1397 SimulateTranslateScriptURLFetch(true); 1398 // Now the message should have been sent. 1399 int page_id = 0; 1400 std::string original_lang, target_lang; 1401 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang)); 1402 EXPECT_EQ("es", original_lang); 1403 EXPECT_EQ("en", target_lang); 1404 } 1405 1406 TEST_F(TranslateManagerBrowserTest, DownloadsAndHistoryNotTranslated) { 1407 ASSERT_FALSE(TranslateManager::IsTranslatableURL( 1408 GURL(chrome::kChromeUIDownloadsURL))); 1409 ASSERT_FALSE(TranslateManager::IsTranslatableURL( 1410 GURL(chrome::kChromeUIHistoryURL))); 1411 } 1412 1413 // Test is flaky on Win http://crbug.com/166334 1414 #if defined(OS_WIN) 1415 #define MAYBE_PRE_TranslateSessionRestore DISABLED_PRE_TranslateSessionRestore 1416 #else 1417 #define MAYBE_PRE_TranslateSessionRestore PRE_TranslateSessionRestore 1418 #endif 1419 // Test that session restore restores the translate infobar and other translate 1420 // settings. 1421 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, 1422 MAYBE_PRE_TranslateSessionRestore) { 1423 SessionStartupPref pref(SessionStartupPref::LAST); 1424 SessionStartupPref::SetStartupPref(browser()->profile(), pref); 1425 1426 content::WebContents* current_web_contents = 1427 browser()->tab_strip_model()->GetActiveWebContents(); 1428 TranslateTabHelper* translate_tab_helper = 1429 TranslateTabHelper::FromWebContents(current_web_contents); 1430 content::Source<content::WebContents> source(current_web_contents); 1431 1432 ui_test_utils::WindowedNotificationObserverWithDetails< 1433 LanguageDetectionDetails> 1434 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, 1435 source); 1436 1437 GURL french_url = ui_test_utils::GetTestUrl( 1438 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("french_page.html"))); 1439 ui_test_utils::NavigateToURL(browser(), french_url); 1440 fr_language_detected_signal.Wait(); 1441 LanguageDetectionDetails details; 1442 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor( 1443 source.map_key(), &details)); 1444 EXPECT_EQ("fr", details.adopted_language); 1445 EXPECT_EQ("fr", translate_tab_helper->language_state().original_language()); 1446 } 1447 1448 #if defined (OS_WIN) 1449 #define MAYBE_TranslateSessionRestore DISABLED_TranslateSessionRestore 1450 #else 1451 #define MAYBE_TranslateSessionRestore TranslateSessionRestore 1452 #endif 1453 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, MAYBE_TranslateSessionRestore) { 1454 content::WebContents* current_web_contents = 1455 browser()->tab_strip_model()->GetActiveWebContents(); 1456 content::Source<content::WebContents> source(current_web_contents); 1457 1458 ui_test_utils::WindowedNotificationObserverWithDetails< 1459 LanguageDetectionDetails> 1460 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, 1461 source); 1462 fr_language_detected_signal.Wait(); 1463 } 1464