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.
9 #include "base/command_line.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/prefs/pref_change_registrar.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/extensions/test_extension_system.h"
17 #include "chrome/browser/infobars/infobar.h"
18 #include "chrome/browser/infobars/infobar_service.h"
19 #include "chrome/browser/prefs/session_startup_pref.h"
20 #include "chrome/browser/tab_contents/render_view_context_menu.h"
21 #include "chrome/browser/translate/translate_infobar_delegate.h"
22 #include "chrome/browser/translate/translate_manager.h"
23 #include "chrome/browser/translate/translate_service.h"
24 #include "chrome/browser/translate/translate_tab_helper.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/browser/ui/translate/translate_bubble_factory.h"
28 #include "chrome/browser/ui/translate/translate_bubble_model.h"
29 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/render_messages.h"
33 #include "chrome/common/url_constants.h"
34 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
35 #include "chrome/test/base/in_process_browser_test.h"
36 #include "chrome/test/base/testing_browser_process.h"
37 #include "chrome/test/base/testing_profile.h"
38 #include "chrome/test/base/ui_test_utils.h"
39 #include "components/translate/core/browser/translate_accept_languages.h"
40 #include "components/translate/core/browser/translate_download_manager.h"
41 #include "components/translate/core/browser/translate_language_list.h"
42 #include "components/translate/core/browser/translate_prefs.h"
43 #include "components/translate/core/browser/translate_script.h"
44 #include "components/translate/core/common/language_detection_details.h"
45 #include "components/translate/core/common/translate_pref_names.h"
46 #include "content/public/browser/navigation_details.h"
47 #include "content/public/browser/navigation_entry.h"
48 #include "content/public/browser/notification_details.h"
49 #include "content/public/browser/notification_registrar.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/test/mock_render_process_host.h"
52 #include "content/public/test/test_renderer_host.h"
53 #include "net/url_request/test_url_fetcher_factory.h"
54 #include "net/url_request/url_fetcher_delegate.h"
55 #include "testing/gmock/include/gmock/gmock.h"
56 #include "third_party/WebKit/public/web/WebContextMenuData.h"
59 // An observer that keeps track of whether a navigation entry was committed.
60 class NavEntryCommittedObserver : public content::NotificationObserver {
62 explicit NavEntryCommittedObserver(content::WebContents* web_contents) {
63 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
64 content::Source<content::NavigationController>(
65 &web_contents->GetController()));
68 virtual void Observe(int type,
69 const content::NotificationSource& source,
70 const content::NotificationDetails& details) OVERRIDE {
71 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
73 *(content::Details<content::LoadCommittedDetails>(details).ptr());
76 const content::LoadCommittedDetails& load_committed_details() const {
81 content::LoadCommittedDetails details_;
82 content::NotificationRegistrar registrar_;
84 DISALLOW_COPY_AND_ASSIGN(NavEntryCommittedObserver);
87 class TranslateManagerBrowserTest : public ChromeRenderViewHostTestHarness,
88 public content::NotificationObserver {
90 TranslateManagerBrowserTest()
92 base::Bind(&TranslateManagerBrowserTest::OnPreferenceChanged,
93 base::Unretained(this))) {
96 // Simulates navigating to a page and getting the page contents and language
97 // for that navigation.
98 void SimulateNavigation(const GURL& url,
99 const std::string& lang,
100 bool page_translatable) {
101 NavigateAndCommit(url);
102 SimulateOnTranslateLanguageDetermined(lang, page_translatable);
105 void SimulateOnTranslateLanguageDetermined(const std::string& lang,
106 bool page_translatable) {
107 LanguageDetectionDetails details;
108 details.adopted_language = lang;
109 content::RenderViewHostTester::TestOnMessageReceived(
111 ChromeViewHostMsg_TranslateLanguageDetermined(
112 0, details, page_translatable));
115 void SimulateOnPageTranslated(int routing_id,
116 const std::string& source_lang,
117 const std::string& target_lang,
118 TranslateErrors::Type error) {
119 content::RenderViewHostTester::TestOnMessageReceived(
121 ChromeViewHostMsg_PageTranslated(
122 routing_id, 0, source_lang, target_lang, error));
125 void SimulateOnPageTranslated(const std::string& source_lang,
126 const std::string& target_lang) {
127 SimulateOnPageTranslated(0, source_lang, target_lang,
128 TranslateErrors::NONE);
131 bool GetTranslateMessage(int* page_id,
132 std::string* original_lang,
133 std::string* target_lang) {
134 const IPC::Message* message =
135 process()->sink().GetFirstMessageMatching(
136 ChromeViewMsg_TranslatePage::ID);
139 Tuple4<int, std::string, std::string, std::string> translate_param;
140 ChromeViewMsg_TranslatePage::Read(message, &translate_param);
142 *page_id = translate_param.a;
143 // Ignore translate_param.b which is the script injected in the page.
145 *original_lang = translate_param.c;
147 *target_lang = translate_param.d;
151 InfoBarService* infobar_service() {
152 return InfoBarService::FromWebContents(web_contents());
155 // Returns the translate infobar if there is 1 infobar and it is a translate
157 TranslateInfoBarDelegate* GetTranslateInfoBar() {
158 return (infobar_service()->infobar_count() == 1) ?
159 infobar_service()->infobar_at(0)->delegate()->
160 AsTranslateInfoBarDelegate() : NULL;
163 // If there is 1 infobar and it is a translate infobar, closes it and returns
164 // true. Returns false otherwise.
165 bool CloseTranslateInfoBar() {
166 InfoBarDelegate* infobar = GetTranslateInfoBar();
169 infobar->InfoBarDismissed(); // Simulates closing the infobar.
170 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
174 // Checks whether |infobar| has been removed and clears the removed infobar
176 bool CheckInfoBarRemovedAndReset(InfoBarDelegate* delegate) {
177 bool found = removed_infobars_.count(delegate) != 0;
178 removed_infobars_.clear();
182 void ExpireTranslateScriptImmediately() {
183 TranslateDownloadManager::GetInstance()->SetTranslateScriptExpirationDelay(
187 // If there is 1 infobar and it is a translate infobar, deny translation and
188 // returns true. Returns false otherwise.
189 bool DenyTranslation() {
190 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
193 infobar->TranslationDeclined();
194 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
198 void ReloadAndWait(bool successful_reload) {
199 NavEntryCommittedObserver nav_observer(web_contents());
200 if (successful_reload)
205 // Ensures it is really handled a reload.
206 const content::LoadCommittedDetails& nav_details =
207 nav_observer.load_committed_details();
208 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation.
209 EXPECT_EQ(content::NAVIGATION_TYPE_EXISTING_PAGE, nav_details.type);
211 // The TranslateManager class processes the navigation entry committed
212 // notification in a posted task; process that task.
213 base::MessageLoop::current()->RunUntilIdle();
216 virtual void Observe(int type,
217 const content::NotificationSource& source,
218 const content::NotificationDetails& details) {
219 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
220 removed_infobars_.insert(
221 content::Details<InfoBar::RemovedDetails>(details)->first->delegate());
224 MOCK_METHOD1(OnPreferenceChanged, void(const std::string&));
227 virtual void SetUp() {
228 // This test is a unit test but runs in the browser_tests suite. Therefore
229 // it needs to manage its own TestingBrowserProcess.
230 // TODO(jamescook): Figure out how to move this suite back to unit_tests.
231 // Right now it fails to get the translate infobar if you run it there.
232 TestingBrowserProcess::CreateInstance();
233 // Access the TranslateManager singleton so it is created before we call
234 // ChromeRenderViewHostTestHarness::SetUp() to match what's done in Chrome,
235 // where the TranslateManager is created before the WebContents. This
236 // matters as they both register for similar events and we want the
237 // notifications to happen in the same sequence (TranslateManager first,
238 // WebContents second). Also clears the translate script so it is fetched
239 // everytime and sets the expiration delay to a large value by default (in
240 // case it was zeroed in a previous test).
241 TranslateService::Initialize();
242 TranslateDownloadManager* download_manager =
243 TranslateDownloadManager::GetInstance();
244 download_manager->ClearTranslateScriptForTesting();
245 download_manager->SetTranslateScriptExpirationDelay(60 * 60 * 1000);
246 TranslateManager::GetInstance()->set_translate_max_reload_attemps(0);
247 TranslateService::SetUseInfobar(true);
249 ChromeRenderViewHostTestHarness::SetUp();
250 InfoBarService::CreateForWebContents(web_contents());
251 TranslateTabHelper::CreateForWebContents(web_contents());
253 notification_registrar_.Add(this,
254 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
255 content::Source<InfoBarService>(infobar_service()));
258 virtual void TearDown() {
259 process()->sink().ClearMessages();
261 notification_registrar_.Remove(this,
262 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
263 content::Source<InfoBarService>(infobar_service()));
265 ChromeRenderViewHostTestHarness::TearDown();
266 TestingBrowserProcess::DeleteInstance();
269 void SetApplicationLocale(const std::string& locale) {
270 g_browser_process->SetApplicationLocale(locale);
271 TranslateDownloadManager::GetInstance()->set_application_locale(
272 g_browser_process->GetApplicationLocale());
275 void SimulateTranslateScriptURLFetch(bool success) {
276 net::TestURLFetcher* fetcher =
277 url_fetcher_factory_.GetFetcherByID(TranslateScript::kFetcherId);
278 ASSERT_TRUE(fetcher);
279 net::URLRequestStatus status;
280 status.set_status(success ? net::URLRequestStatus::SUCCESS :
281 net::URLRequestStatus::FAILED);
282 fetcher->set_url(fetcher->GetOriginalURL());
283 fetcher->set_status(status);
284 fetcher->set_response_code(success ? 200 : 500);
285 fetcher->delegate()->OnURLFetchComplete(fetcher);
288 void SimulateSupportedLanguagesURLFetch(
290 const std::vector<std::string>& languages,
291 bool use_alpha_languages,
292 const std::vector<std::string>& alpha_languages) {
293 net::URLRequestStatus status;
294 status.set_status(success ? net::URLRequestStatus::SUCCESS :
295 net::URLRequestStatus::FAILED);
299 data = base::StringPrintf(
300 "%s{\"sl\": {\"bla\": \"bla\"}, \"%s\": {",
301 TranslateLanguageList::kLanguageListCallbackName,
302 TranslateLanguageList::kTargetLanguagesKey);
303 const char* comma = "";
304 for (size_t i = 0; i < languages.size(); ++i) {
305 data += base::StringPrintf(
306 "%s\"%s\": \"UnusedFullName\"", comma, languages[i].c_str());
311 if (use_alpha_languages) {
312 data += base::StringPrintf("},\"%s\": {",
313 TranslateLanguageList::kAlphaLanguagesKey);
315 for (size_t i = 0; i < alpha_languages.size(); ++i) {
316 data += base::StringPrintf("%s\"%s\": 1", comma,
317 alpha_languages[i].c_str());
325 net::TestURLFetcher* fetcher =
326 url_fetcher_factory_.GetFetcherByID(TranslateLanguageList::kFetcherId);
327 ASSERT_TRUE(fetcher != NULL);
328 fetcher->set_url(fetcher->GetOriginalURL());
329 fetcher->set_status(status);
330 fetcher->set_response_code(success ? 200 : 500);
331 fetcher->SetResponseString(data);
332 fetcher->delegate()->OnURLFetchComplete(fetcher);
335 void SetPrefObserverExpectation(const char* path) {
336 EXPECT_CALL(*this, OnPreferenceChanged(std::string(path)));
339 PrefChangeRegistrar::NamedChangeCallback pref_callback_;
342 content::NotificationRegistrar notification_registrar_;
343 net::TestURLFetcherFactory url_fetcher_factory_;
345 // The infobars that have been removed.
346 // WARNING: the pointers point to deleted objects, use only for comparison.
347 std::set<InfoBarDelegate*> removed_infobars_;
349 DISALLOW_COPY_AND_ASSIGN(TranslateManagerBrowserTest);
352 class MockTranslateBubbleFactory : public TranslateBubbleFactory {
354 MockTranslateBubbleFactory() {
357 virtual void ShowImplementation(BrowserWindow* window,
358 content::WebContents* web_contents,
359 TranslateTabHelper::TranslateStep step,
360 TranslateErrors::Type error_type) OVERRIDE {
362 model_->SetViewState(
363 TranslateBubbleModelImpl::TranslateStepToViewState(step));
367 TranslateTabHelper* translate_tab_helper =
368 TranslateTabHelper::FromWebContents(web_contents);
369 std::string source_language =
370 translate_tab_helper->GetLanguageState().original_language();
371 std::string target_language = TranslateDownloadManager::GetLanguageCode(
372 g_browser_process->GetApplicationLocale());
373 scoped_ptr<TranslateUIDelegate> ui_delegate(
374 new TranslateUIDelegate(web_contents,
377 model_.reset(new TranslateBubbleModelImpl(step, ui_delegate.Pass()));
380 TranslateBubbleModel* model() { return model_.get(); }
383 scoped_ptr<TranslateBubbleModel> model_;
385 DISALLOW_COPY_AND_ASSIGN(MockTranslateBubbleFactory);
390 class TestRenderViewContextMenu : public RenderViewContextMenu {
392 static TestRenderViewContextMenu* CreateContextMenu(
393 content::WebContents* web_contents) {
394 content::ContextMenuParams params;
395 params.media_type = blink::WebContextMenuData::MediaTypeNone;
398 params.has_image_contents = true;
399 params.media_flags = 0;
400 params.spellcheck_enabled = false;
401 params.is_editable = false;
402 params.page_url = web_contents->GetController().GetActiveEntry()->GetURL();
403 #if defined(OS_MACOSX)
404 params.writing_direction_default = 0;
405 params.writing_direction_left_to_right = 0;
406 params.writing_direction_right_to_left = 0;
408 params.edit_flags = blink::WebContextMenuData::CanTranslate;
409 return new TestRenderViewContextMenu(web_contents->GetMainFrame(), params);
412 bool IsItemPresent(int id) {
413 return menu_model_.GetIndexOfCommandId(id) != -1;
416 virtual void PlatformInit() OVERRIDE { }
417 virtual void PlatformCancel() OVERRIDE { }
418 virtual bool GetAcceleratorForCommandId(
420 ui::Accelerator* accelerator) OVERRIDE { return false; }
423 TestRenderViewContextMenu(content::RenderFrameHost* render_frame_host,
424 const content::ContextMenuParams& params)
425 : RenderViewContextMenu(render_frame_host, params) {
428 DISALLOW_COPY_AND_ASSIGN(TestRenderViewContextMenu);
433 TEST_F(TranslateManagerBrowserTest, NormalTranslate) {
434 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
436 // We should have an infobar.
437 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
438 ASSERT_TRUE(infobar != NULL);
439 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
441 // Simulate clicking translate.
442 process()->sink().ClearMessages();
443 infobar->Translate();
445 // The "Translating..." infobar should be showing.
446 infobar = GetTranslateInfoBar();
447 ASSERT_TRUE(infobar != NULL);
448 EXPECT_EQ(TranslateTabHelper::TRANSLATING, infobar->translate_step());
450 // Simulate the translate script being retrieved (it only needs to be done
451 // once in the test as it is cached).
452 SimulateTranslateScriptURLFetch(true);
454 // Test that we sent the right message to the renderer.
456 std::string original_lang, target_lang;
457 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
458 EXPECT_EQ("fr", original_lang);
459 EXPECT_EQ("en", target_lang);
461 // Simulate the render notifying the translation has been done.
462 SimulateOnPageTranslated("fr", "en");
464 // The after translate infobar should be showing.
465 infobar = GetTranslateInfoBar();
466 ASSERT_TRUE(infobar != NULL);
467 EXPECT_EQ(TranslateTabHelper::AFTER_TRANSLATE, infobar->translate_step());
469 // Simulate changing the original language and translating.
470 process()->sink().ClearMessages();
471 std::string new_original_lang = infobar->language_code_at(0);
472 infobar->UpdateOriginalLanguageIndex(0);
473 infobar->Translate();
474 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
475 EXPECT_EQ(new_original_lang, original_lang);
476 EXPECT_EQ("en", target_lang);
477 // Simulate the render notifying the translation has been done.
478 SimulateOnPageTranslated(new_original_lang, "en");
479 infobar = GetTranslateInfoBar();
480 ASSERT_TRUE(infobar != NULL);
482 // Simulate changing the target language and translating.
483 process()->sink().ClearMessages();
484 std::string new_target_lang = infobar->language_code_at(1);
485 infobar->UpdateTargetLanguageIndex(1);
486 infobar->Translate();
487 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
488 EXPECT_EQ(new_original_lang, original_lang);
489 EXPECT_EQ(new_target_lang, target_lang);
490 // Simulate the render notifying the translation has been done.
491 SimulateOnPageTranslated(new_original_lang, new_target_lang);
492 infobar = GetTranslateInfoBar();
493 ASSERT_TRUE(infobar != NULL);
494 EXPECT_EQ(new_target_lang, infobar->target_language_code());
496 // Reloading should trigger translation iff Always Translate is on.
498 infobar = GetTranslateInfoBar();
499 ASSERT_TRUE(infobar != NULL);
500 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
501 infobar->UpdateTargetLanguageIndex(1);
502 infobar->ToggleAlwaysTranslate();
504 infobar = GetTranslateInfoBar();
505 ASSERT_TRUE(infobar != NULL);
506 EXPECT_EQ(TranslateTabHelper::TRANSLATING, infobar->translate_step());
507 EXPECT_EQ(new_target_lang, infobar->target_language_code());
510 TEST_F(TranslateManagerBrowserTest, TranslateScriptNotAvailable) {
511 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
513 // We should have an infobar.
514 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
515 ASSERT_TRUE(infobar != NULL);
516 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
518 // Simulate clicking translate.
519 process()->sink().ClearMessages();
520 infobar->Translate();
521 SimulateTranslateScriptURLFetch(false);
523 // We should not have sent any message to translate to the renderer.
524 EXPECT_FALSE(GetTranslateMessage(NULL, NULL, NULL));
526 // And we should have an error infobar showing.
527 infobar = GetTranslateInfoBar();
528 ASSERT_TRUE(infobar != NULL);
529 EXPECT_EQ(TranslateTabHelper::TRANSLATE_ERROR, infobar->translate_step());
532 // Ensures we deal correctly with pages for which the browser does not recognize
533 // the language (the translate server may or not detect the language).
534 TEST_F(TranslateManagerBrowserTest, TranslateUnknownLanguage) {
535 // Simulate navigating to a page ("und" is the string returned by the CLD for
536 // languages it does not recognize).
537 SimulateNavigation(GURL("http://www.google.mys"), "und", true);
539 // We should not have an infobar as we don't know the language.
540 ASSERT_TRUE(GetTranslateInfoBar() == NULL);
542 // Translate the page anyway throught the context menu.
543 scoped_ptr<TestRenderViewContextMenu> menu(
544 TestRenderViewContextMenu::CreateContextMenu(web_contents()));
546 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
548 // To test that bug #49018 if fixed, make sure we deal correctly with errors.
549 // Simulate a failure to fetch the translate script.
550 SimulateTranslateScriptURLFetch(false);
551 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
552 ASSERT_TRUE(infobar != NULL);
553 EXPECT_EQ(TranslateTabHelper::TRANSLATE_ERROR, infobar->translate_step());
554 EXPECT_TRUE(infobar->is_error());
555 infobar->MessageInfoBarButtonPressed();
556 SimulateTranslateScriptURLFetch(true); // This time succeed.
558 // Simulate the render notifying the translation has been done, the server
559 // having detected the page was in a known and supported language.
560 SimulateOnPageTranslated("fr", "en");
562 // The after translate infobar should be showing.
563 infobar = GetTranslateInfoBar();
564 ASSERT_TRUE(infobar != NULL);
565 EXPECT_EQ(TranslateTabHelper::AFTER_TRANSLATE, infobar->translate_step());
566 EXPECT_EQ("fr", infobar->original_language_code());
567 EXPECT_EQ("en", infobar->target_language_code());
569 // Let's run the same steps but this time the server detects the page is
570 // already in English.
571 SimulateNavigation(GURL("http://www.google.com"), "und", true);
572 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
574 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
575 SimulateOnPageTranslated(1, "en", "en", TranslateErrors::IDENTICAL_LANGUAGES);
576 infobar = GetTranslateInfoBar();
577 ASSERT_TRUE(infobar != NULL);
578 EXPECT_EQ(TranslateTabHelper::TRANSLATE_ERROR, infobar->translate_step());
579 EXPECT_EQ(TranslateErrors::IDENTICAL_LANGUAGES, infobar->error_type());
581 // Let's run the same steps again but this time the server fails to detect the
582 // page's language (it returns an empty string).
583 SimulateNavigation(GURL("http://www.google.com"), "und", true);
584 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
586 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
587 SimulateOnPageTranslated(2, std::string(), "en",
588 TranslateErrors::UNKNOWN_LANGUAGE);
589 infobar = GetTranslateInfoBar();
590 ASSERT_TRUE(infobar != NULL);
591 EXPECT_EQ(TranslateTabHelper::TRANSLATE_ERROR, infobar->translate_step());
592 EXPECT_EQ(TranslateErrors::UNKNOWN_LANGUAGE, infobar->error_type());
595 // Tests that we show/don't show an info-bar for the languages.
596 TEST_F(TranslateManagerBrowserTest, TestLanguages) {
597 std::vector<std::string> languages;
598 languages.push_back("en");
599 languages.push_back("ja");
600 languages.push_back("fr");
601 languages.push_back("ht");
602 languages.push_back("xx");
603 languages.push_back("zh");
604 languages.push_back("zh-CN");
605 languages.push_back("und");
607 GURL url("http://www.google.com");
608 for (size_t i = 0; i < languages.size(); ++i) {
609 std::string lang = languages[i];
610 SCOPED_TRACE(::testing::Message() << "Iteration " << i <<
611 " language=" << lang);
613 // We should not have a translate infobar.
614 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
615 ASSERT_TRUE(infobar == NULL);
617 SimulateNavigation(url, lang, true);
619 // Verify we have/don't have an info-bar as expected.
620 infobar = GetTranslateInfoBar();
622 TranslateDownloadManager::IsSupportedLanguage(lang) && lang != "en";
623 EXPECT_EQ(expected, infobar != NULL);
626 EXPECT_TRUE(CloseTranslateInfoBar());
630 // Test the fetching of languages from the translate server
631 TEST_F(TranslateManagerBrowserTest, FetchLanguagesFromTranslateServer) {
632 std::vector<std::string> server_languages;
633 // A list of languages to fake being returned by the translate server.
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");
643 std::vector<std::string> alpha_languages;
644 alpha_languages.push_back("aa");
645 alpha_languages.push_back("yi");
647 // First, get the default languages list. Note that calling
648 // GetSupportedLanguages() invokes RequestLanguageList() internally.
649 std::vector<std::string> default_supported_languages;
650 TranslateDownloadManager::GetSupportedLanguages(&default_supported_languages);
651 // To make sure we got the defaults and don't confuse them with the mocks.
652 ASSERT_NE(default_supported_languages.size(), server_languages.size());
654 // Check that we still get the defaults until the URLFetch has completed.
655 std::vector<std::string> current_supported_languages;
656 TranslateDownloadManager::GetSupportedLanguages(¤t_supported_languages);
657 EXPECT_EQ(default_supported_languages, current_supported_languages);
659 // Also check that it didn't change if we failed the URL fetch.
660 SimulateSupportedLanguagesURLFetch(false, std::vector<std::string>(),
661 true, std::vector<std::string>());
662 current_supported_languages.clear();
663 TranslateDownloadManager::GetSupportedLanguages(¤t_supported_languages);
664 EXPECT_EQ(default_supported_languages, current_supported_languages);
666 // Now check that we got the appropriate set of languages from the server.
667 SimulateSupportedLanguagesURLFetch(true, server_languages,
668 true, alpha_languages);
669 current_supported_languages.clear();
670 TranslateDownloadManager::GetSupportedLanguages(¤t_supported_languages);
671 // "xx" can't be displayed in the Translate inforbar, so this is eliminated.
672 EXPECT_EQ(server_languages.size() - 1, current_supported_languages.size());
673 // Not sure we need to guarantee the order of languages, so we find them.
674 for (size_t i = 0; i < server_languages.size(); ++i) {
675 const std::string& lang = server_languages[i];
678 EXPECT_NE(current_supported_languages.end(),
679 std::find(current_supported_languages.begin(),
680 current_supported_languages.end(),
682 bool is_alpha = std::find(alpha_languages.begin(),
683 alpha_languages.end(),
684 lang) != alpha_languages.end();
685 EXPECT_EQ(TranslateDownloadManager::IsAlphaLanguage(lang), is_alpha);
689 // Test the fetching of languages from the translate server without 'al'
691 TEST_F(TranslateManagerBrowserTest,
692 FetchLanguagesFromTranslateServerWithoutAlpha) {
693 std::vector<std::string> server_languages;
694 server_languages.push_back("aa");
695 server_languages.push_back("ak");
696 server_languages.push_back("ab");
697 server_languages.push_back("en-CA");
698 server_languages.push_back("zh");
699 server_languages.push_back("yi");
700 server_languages.push_back("fr-FR");
701 server_languages.push_back("xx");
703 std::vector<std::string> alpha_languages;
704 alpha_languages.push_back("aa");
705 alpha_languages.push_back("yi");
707 // call GetSupportedLanguages to call RequestLanguageList internally.
708 std::vector<std::string> default_supported_languages;
709 TranslateDownloadManager::GetSupportedLanguages(&default_supported_languages);
711 SimulateSupportedLanguagesURLFetch(true, server_languages,
712 false, alpha_languages);
714 std::vector<std::string> current_supported_languages;
715 TranslateDownloadManager::GetSupportedLanguages(¤t_supported_languages);
717 // "xx" can't be displayed in the Translate inforbar, so this is eliminated.
718 EXPECT_EQ(server_languages.size() - 1, current_supported_languages.size());
720 for (size_t i = 0; i < server_languages.size(); ++i) {
721 const std::string& lang = server_languages[i];
724 EXPECT_NE(current_supported_languages.end(),
725 std::find(current_supported_languages.begin(),
726 current_supported_languages.end(),
728 EXPECT_FALSE(TranslateDownloadManager::IsAlphaLanguage(lang));
732 // Tests auto-translate on page.
733 TEST_F(TranslateManagerBrowserTest, AutoTranslateOnNavigate) {
734 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
736 // Simulate the user translating.
737 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
738 ASSERT_TRUE(infobar != NULL);
739 infobar->Translate();
740 // Simulate the translate script being retrieved.
741 SimulateTranslateScriptURLFetch(true);
742 SimulateOnPageTranslated("fr", "en");
744 // Now navigate to a new page in the same language.
745 process()->sink().ClearMessages();
746 SimulateNavigation(GURL("http://news.google.fr"), "fr", true);
748 // This should have automatically triggered a translation.
750 std::string original_lang, target_lang;
751 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
752 EXPECT_EQ(1, page_id);
753 EXPECT_EQ("fr", original_lang);
754 EXPECT_EQ("en", target_lang);
756 // Now navigate to a page in a different language.
757 process()->sink().ClearMessages();
758 SimulateNavigation(GURL("http://news.google.es"), "es", true);
760 // This should not have triggered a translate.
761 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
764 // Tests that multiple OnPageContents do not cause multiple infobars.
765 TEST_F(TranslateManagerBrowserTest, MultipleOnPageContents) {
766 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
768 // Simulate clicking 'Nope' (don't translate).
769 EXPECT_TRUE(DenyTranslation());
770 EXPECT_EQ(0U, infobar_service()->infobar_count());
772 // Send a new PageContents, we should not show an infobar.
773 SimulateOnTranslateLanguageDetermined("fr", true);
774 EXPECT_EQ(0U, infobar_service()->infobar_count());
776 // Do the same steps but simulate closing the infobar this time.
777 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true);
778 EXPECT_TRUE(CloseTranslateInfoBar());
779 EXPECT_EQ(0U, infobar_service()->infobar_count());
780 SimulateOnTranslateLanguageDetermined("fr", true);
781 EXPECT_EQ(0U, infobar_service()->infobar_count());
784 // Test that reloading the page brings back the infobar if the
785 // reload succeeded and does not bring it back the reload fails.
786 TEST_F(TranslateManagerBrowserTest, Reload) {
787 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
789 EXPECT_TRUE(CloseTranslateInfoBar());
791 // Reload should bring back the infobar if the reload succeeds.
793 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
794 EXPECT_TRUE(CloseTranslateInfoBar());
796 // ...But not show it if the reload fails.
797 ReloadAndWait(false);
798 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
800 // If we set reload attempts to a high value, we will not see the infobar
802 TranslateManager::GetInstance()->set_translate_max_reload_attemps(100);
804 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
807 // Test that reloading the page by way of typing again the URL in the
808 // location bar brings back the infobar.
809 TEST_F(TranslateManagerBrowserTest, ReloadFromLocationBar) {
810 GURL url("http://www.google.fr");
811 SimulateNavigation(url, "fr", true);
813 EXPECT_TRUE(CloseTranslateInfoBar());
815 // Create a pending navigation and simulate a page load. That should be the
816 // equivalent of typing the URL again in the location bar.
817 NavEntryCommittedObserver nav_observer(web_contents());
818 web_contents()->GetController().LoadURL(url, content::Referrer(),
819 content::PAGE_TRANSITION_TYPED,
821 rvh_tester()->SendNavigate(0, url);
823 // Test that we are really getting a same page navigation, the test would be
824 // useless if it was not the case.
825 const content::LoadCommittedDetails& nav_details =
826 nav_observer.load_committed_details();
827 EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation.
828 EXPECT_EQ(content::NAVIGATION_TYPE_SAME_PAGE, nav_details.type);
830 // The TranslateManager class processes the navigation entry committed
831 // notification in a posted task; process that task.
832 base::MessageLoop::current()->RunUntilIdle();
833 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
836 // Tests that a closed translate infobar does not reappear when navigating
838 TEST_F(TranslateManagerBrowserTest, CloseInfoBarInPageNavigation) {
839 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
841 EXPECT_TRUE(CloseTranslateInfoBar());
843 // Navigate in page, no infobar should be shown.
844 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true);
845 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
847 // Navigate out of page, a new infobar should show.
848 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true);
849 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
852 // Tests that a closed translate infobar does not reappear when navigating
853 // in a subframe. (http://crbug.com/48215)
854 TEST_F(TranslateManagerBrowserTest, CloseInfoBarInSubframeNavigation) {
855 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
857 EXPECT_TRUE(CloseTranslateInfoBar());
859 // Simulate a sub-frame auto-navigating.
860 rvh_tester()->SendNavigateWithTransition(
861 1, GURL("http://pub.com"), content::PAGE_TRANSITION_AUTO_SUBFRAME);
862 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
864 // Simulate the user navigating in a sub-frame.
865 rvh_tester()->SendNavigateWithTransition(
866 2, GURL("http://pub.com"), content::PAGE_TRANSITION_MANUAL_SUBFRAME);
867 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
869 // Navigate out of page, a new infobar should show.
870 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true);
871 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
874 // Tests that denying translation is sticky when navigating in page.
875 TEST_F(TranslateManagerBrowserTest, DenyTranslateInPageNavigation) {
876 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
878 // Simulate clicking 'Nope' (don't translate).
879 EXPECT_TRUE(DenyTranslation());
881 // Navigate in page, no infobar should be shown.
882 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true);
883 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
885 // Navigate out of page, a new infobar should show.
886 SimulateNavigation(GURL("http://www.google.fr/foot"), "fr", true);
887 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
890 // Tests that after translating and closing the infobar, the infobar does not
891 // return when navigating in page.
892 TEST_F(TranslateManagerBrowserTest, TranslateCloseInfoBarInPageNavigation) {
893 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
895 // Simulate the user translating.
896 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
897 ASSERT_TRUE(infobar != NULL);
898 infobar->Translate();
899 // Simulate the translate script being retrieved.
900 SimulateTranslateScriptURLFetch(true);
901 SimulateOnPageTranslated("fr", "en");
903 EXPECT_TRUE(CloseTranslateInfoBar());
905 // Navigate in page, no infobar should be shown.
906 SimulateNavigation(GURL("http://www.google.fr/#ref1"), "fr", true);
907 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
909 // Navigate out of page, a new infobar should show.
910 // Note that we navigate to a page in a different language so we don't trigger
911 // the auto-translate feature (it would translate the page automatically and
912 // the before translate inforbar would not be shown).
913 SimulateNavigation(GURL("http://www.google.de"), "de", true);
914 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
917 // Tests that the after translate the infobar still shows when navigating
919 TEST_F(TranslateManagerBrowserTest, TranslateInPageNavigation) {
920 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
922 // Simulate the user translating.
923 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
924 ASSERT_TRUE(infobar != NULL);
925 infobar->Translate();
926 SimulateTranslateScriptURLFetch(true);
927 SimulateOnPageTranslated("fr", "en");
928 // The after translate infobar is showing.
929 infobar = GetTranslateInfoBar();
930 ASSERT_TRUE(infobar != NULL);
932 // Navigate out of page, a new infobar should show.
933 // See note in TranslateCloseInfoBarInPageNavigation test on why it is
934 // important to navigate to a page in a different language for this test.
935 SimulateNavigation(GURL("http://www.google.de"), "de", true);
936 // The old infobar is gone.
937 EXPECT_TRUE(CheckInfoBarRemovedAndReset(infobar));
938 // And there is a new one.
939 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
942 // Tests that no translate infobar is shown when navigating to a page in an
943 // unsupported language.
944 TEST_F(TranslateManagerBrowserTest, CLDReportsUnsupportedPageLanguage) {
945 // Simulate navigating to a page and getting an unsupported language.
946 SimulateNavigation(GURL("http://www.google.com"), "qbz", true);
948 // No info-bar should be shown.
949 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
952 // Tests that we deal correctly with unsupported languages returned by the
954 // The translation server might return a language we don't support.
955 TEST_F(TranslateManagerBrowserTest, ServerReportsUnsupportedLanguage) {
956 SimulateNavigation(GURL("http://mail.google.fr"), "fr", true);
957 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
958 ASSERT_TRUE(infobar != NULL);
959 process()->sink().ClearMessages();
960 infobar->Translate();
961 SimulateTranslateScriptURLFetch(true);
962 // Simulate the render notifying the translation has been done, but it
963 // reports a language we don't support.
964 SimulateOnPageTranslated("qbz", "en");
966 // An error infobar should be showing to report that we don't support this
968 infobar = GetTranslateInfoBar();
969 ASSERT_TRUE(infobar != NULL);
970 EXPECT_EQ(TranslateTabHelper::TRANSLATE_ERROR, infobar->translate_step());
972 // This infobar should have a button (so the string should not be empty).
973 ASSERT_FALSE(infobar->GetMessageInfoBarButtonText().empty());
975 // Pressing the button on that infobar should revert to the original language.
976 process()->sink().ClearMessages();
977 infobar->MessageInfoBarButtonPressed();
978 const IPC::Message* message =
979 process()->sink().GetFirstMessageMatching(
980 ChromeViewMsg_RevertTranslation::ID);
981 EXPECT_TRUE(message != NULL);
982 // And it should have removed the infobar.
983 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
986 // Tests that no translate infobar is shown and context menu is disabled, when
987 // Chrome is in a language that the translate server does not support.
988 TEST_F(TranslateManagerBrowserTest, UnsupportedUILanguage) {
989 std::string original_lang = g_browser_process->GetApplicationLocale();
990 SetApplicationLocale("qbz");
992 // Make sure that the accept language list only contains unsupported languages
994 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
995 PrefService* prefs = profile->GetPrefs();
996 prefs->SetString(prefs::kAcceptLanguages, "qbz");
998 // Simulate navigating to a page in a language supported by the translate
1000 SimulateNavigation(GURL("http://www.google.com"), "en", true);
1002 // No info-bar should be shown.
1003 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
1005 // And the context menu option should be disabled too.
1006 scoped_ptr<TestRenderViewContextMenu> menu(
1007 TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1009 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1010 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1012 SetApplicationLocale(original_lang);
1015 // Tests that the first supported accept language is selected
1016 TEST_F(TranslateManagerBrowserTest, TranslateAcceptLanguage) {
1017 // Set locate to non-existant language
1018 std::string original_lang = g_browser_process->GetApplicationLocale();
1019 SetApplicationLocale("qbz");
1021 // Set Qbz and French as the only accepted languages
1023 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1024 PrefService* prefs = profile->GetPrefs();
1025 prefs->SetString(prefs::kAcceptLanguages, "qbz,fr");
1027 // Go to a German page
1028 SimulateNavigation(GURL("http://google.de"), "de", true);
1030 // Expect the infobar to pop up
1031 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1033 // Set Qbz and English-US as the only accepted languages to test the country
1034 // code removal code which was causing a crash as filed in Issue 90106,
1035 // a crash caused by a language with a country code that wasn't recognized.
1036 prefs->SetString(prefs::kAcceptLanguages, "qbz,en-us");
1038 // Go to a German page
1039 SimulateNavigation(GURL("http://google.de"), "de", true);
1041 // Expect the infobar to pop up
1042 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1045 // Tests that the translate enabled preference is honored.
1046 TEST_F(TranslateManagerBrowserTest, TranslateEnabledPref) {
1047 // Make sure the pref allows translate.
1049 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1050 PrefService* prefs = profile->GetPrefs();
1051 prefs->SetBoolean(prefs::kEnableTranslate, true);
1053 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1055 // An infobar should be shown.
1056 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1057 EXPECT_TRUE(infobar != NULL);
1059 // Disable translate.
1060 prefs->SetBoolean(prefs::kEnableTranslate, false);
1062 // Navigate to a new page, that should close the previous infobar.
1063 GURL url("http://www.youtube.fr");
1064 NavigateAndCommit(url);
1065 infobar = GetTranslateInfoBar();
1066 EXPECT_TRUE(infobar == NULL);
1068 // Simulate getting the page contents and language, that should not trigger
1069 // a translate infobar.
1070 SimulateOnTranslateLanguageDetermined("fr", true);
1071 infobar = GetTranslateInfoBar();
1072 EXPECT_TRUE(infobar == NULL);
1075 // Tests the "Never translate <language>" pref.
1076 TEST_F(TranslateManagerBrowserTest, NeverTranslateLanguagePref) {
1077 GURL url("http://www.google.fr");
1078 SimulateNavigation(url, "fr", true);
1080 // An infobar should be shown.
1081 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1083 // Select never translate this language.
1085 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1086 PrefService* prefs = profile->GetPrefs();
1087 PrefChangeRegistrar registrar;
1088 registrar.Init(prefs);
1089 registrar.Add(TranslatePrefs::kPrefTranslateBlockedLanguages,
1091 scoped_ptr<TranslatePrefs> translate_prefs(
1092 TranslateTabHelper::CreateTranslatePrefs(prefs));
1093 EXPECT_FALSE(translate_prefs->IsBlockedLanguage("fr"));
1094 TranslateAcceptLanguages* accept_languages =
1095 TranslateTabHelper::GetTranslateAcceptLanguages(profile);
1096 EXPECT_TRUE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1097 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateBlockedLanguages);
1098 translate_prefs->BlockLanguage("fr");
1099 EXPECT_TRUE(translate_prefs->IsBlockedLanguage("fr"));
1100 EXPECT_FALSE(translate_prefs->IsSiteBlacklisted(url.host()));
1101 EXPECT_FALSE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1103 EXPECT_TRUE(CloseTranslateInfoBar());
1105 // Navigate to a new page also in French.
1106 SimulateNavigation(GURL("http://wwww.youtube.fr"), "fr", true);
1108 // There should not be a translate infobar.
1109 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
1111 // Remove the language from the blacklist.
1112 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateBlockedLanguages);
1113 translate_prefs->UnblockLanguage("fr");
1114 EXPECT_FALSE(translate_prefs->IsBlockedLanguage("fr"));
1115 EXPECT_FALSE(translate_prefs->IsSiteBlacklisted(url.host()));
1116 EXPECT_TRUE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1118 // Navigate to a page in French.
1119 SimulateNavigation(url, "fr", true);
1121 // There should be a translate infobar.
1122 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1125 // Tests the "Never translate this site" pref.
1126 TEST_F(TranslateManagerBrowserTest, NeverTranslateSitePref) {
1127 GURL url("http://www.google.fr");
1128 std::string host(url.host());
1129 SimulateNavigation(url, "fr", true);
1131 // An infobar should be shown.
1132 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1134 // Select never translate this site.
1136 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1137 PrefService* prefs = profile->GetPrefs();
1138 PrefChangeRegistrar registrar;
1139 registrar.Init(prefs);
1140 registrar.Add(TranslatePrefs::kPrefTranslateSiteBlacklist, pref_callback_);
1141 scoped_ptr<TranslatePrefs> translate_prefs(
1142 TranslateTabHelper::CreateTranslatePrefs(prefs));
1143 EXPECT_FALSE(translate_prefs->IsSiteBlacklisted(host));
1144 TranslateAcceptLanguages* accept_languages =
1145 TranslateTabHelper::GetTranslateAcceptLanguages(profile);
1146 EXPECT_TRUE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1147 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist);
1148 translate_prefs->BlacklistSite(host);
1149 EXPECT_TRUE(translate_prefs->IsSiteBlacklisted(host));
1150 EXPECT_TRUE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1152 EXPECT_TRUE(CloseTranslateInfoBar());
1154 // Navigate to a new page also on the same site.
1155 SimulateNavigation(GURL("http://www.google.fr/hello"), "fr", true);
1157 // There should not be a translate infobar.
1158 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
1160 // Remove the site from the blacklist.
1161 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateSiteBlacklist);
1162 translate_prefs->RemoveSiteFromBlacklist(host);
1163 EXPECT_FALSE(translate_prefs->IsSiteBlacklisted(host));
1164 EXPECT_TRUE(translate_prefs->CanTranslateLanguage(accept_languages, "fr"));
1166 // Navigate to a page in French.
1167 SimulateNavigation(url, "fr", true);
1169 // There should be a translate infobar.
1170 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1173 // Tests the "Always translate this language" pref.
1174 TEST_F(TranslateManagerBrowserTest, AlwaysTranslateLanguagePref) {
1175 // Select always translate French to English.
1177 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1178 PrefService* prefs = profile->GetPrefs();
1179 PrefChangeRegistrar registrar;
1180 registrar.Init(prefs);
1181 registrar.Add(TranslatePrefs::kPrefTranslateWhitelists, pref_callback_);
1182 scoped_ptr<TranslatePrefs> translate_prefs(
1183 TranslateTabHelper::CreateTranslatePrefs(prefs));
1184 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists);
1185 translate_prefs->WhitelistLanguagePair("fr", "en");
1187 // Load a page in French.
1188 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1190 // It should have triggered an automatic translation to English.
1192 // The translating infobar should be showing.
1193 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1194 ASSERT_TRUE(infobar != NULL);
1195 EXPECT_EQ(TranslateTabHelper::TRANSLATING, infobar->translate_step());
1196 SimulateTranslateScriptURLFetch(true);
1198 std::string original_lang, target_lang;
1199 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1200 EXPECT_EQ("fr", original_lang);
1201 EXPECT_EQ("en", target_lang);
1202 process()->sink().ClearMessages();
1204 // Try another language, it should not be autotranslated.
1205 SimulateNavigation(GURL("http://www.google.es"), "es", true);
1206 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1207 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1208 EXPECT_TRUE(CloseTranslateInfoBar());
1210 // Let's switch to incognito mode, it should not be autotranslated in that
1212 TestingProfile* test_profile =
1213 static_cast<TestingProfile*>(web_contents()->GetBrowserContext());
1214 test_profile->ForceIncognito(true);
1215 SimulateNavigation(GURL("http://www.youtube.fr"), "fr", true);
1216 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1217 EXPECT_TRUE(GetTranslateInfoBar() != NULL);
1218 EXPECT_TRUE(CloseTranslateInfoBar());
1219 test_profile->ForceIncognito(false); // Get back to non incognito.
1221 // Now revert the always translate pref and make sure we go back to expected
1222 // behavior, which is show a "before translate" infobar.
1223 SetPrefObserverExpectation(TranslatePrefs::kPrefTranslateWhitelists);
1224 translate_prefs->RemoveLanguagePairFromWhitelist("fr", "en");
1225 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1226 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1227 infobar = GetTranslateInfoBar();
1228 ASSERT_TRUE(infobar != NULL);
1229 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
1233 TEST_F(TranslateManagerBrowserTest, ContextMenu) {
1234 // Blacklist www.google.fr and French for translation.
1235 GURL url("http://www.google.fr");
1237 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1238 scoped_ptr<TranslatePrefs> translate_prefs(
1239 TranslateTabHelper::CreateTranslatePrefs(profile->GetPrefs()));
1240 translate_prefs->BlockLanguage("fr");
1241 translate_prefs->BlacklistSite(url.host());
1242 EXPECT_TRUE(translate_prefs->IsBlockedLanguage("fr"));
1243 EXPECT_TRUE(translate_prefs->IsSiteBlacklisted(url.host()));
1245 // Simulate navigating to a page in French. The translate menu should show but
1246 // should only be enabled when the page language has been received.
1247 NavigateAndCommit(url);
1248 scoped_ptr<TestRenderViewContextMenu> menu(
1249 TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1251 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1252 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1254 // Simulate receiving the language.
1255 SimulateOnTranslateLanguageDetermined("fr", true);
1256 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1258 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1259 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1261 // Use the menu to translate the page.
1262 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
1264 // That should have triggered a translation.
1265 // The "translating..." infobar should be showing.
1266 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1267 ASSERT_TRUE(infobar != NULL);
1268 EXPECT_EQ(TranslateTabHelper::TRANSLATING, infobar->translate_step());
1269 SimulateTranslateScriptURLFetch(true);
1271 std::string original_lang, target_lang;
1272 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1273 EXPECT_EQ("fr", original_lang);
1274 EXPECT_EQ("en", target_lang);
1275 process()->sink().ClearMessages();
1277 // This should also have reverted the blacklisting of this site and language.
1278 EXPECT_FALSE(translate_prefs->IsBlockedLanguage("fr"));
1279 EXPECT_FALSE(translate_prefs->IsSiteBlacklisted(url.host()));
1281 // Let's simulate the page being translated.
1282 SimulateOnPageTranslated("fr", "en");
1284 // The translate menu should now be disabled.
1285 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1287 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1288 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1290 // Test that selecting translate in the context menu WHILE the page is being
1291 // translated does nothing (this could happen if autotranslate kicks-in and
1292 // the user selects the menu while the translation is being performed).
1293 SimulateNavigation(GURL("http://www.google.es"), "es", true);
1294 infobar = GetTranslateInfoBar();
1295 ASSERT_TRUE(infobar != NULL);
1296 infobar->Translate();
1297 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1298 process()->sink().ClearMessages();
1299 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1301 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1302 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
1303 // No message expected since the translation should have been ignored.
1304 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1306 // Now test that selecting translate in the context menu AFTER the page has
1307 // been translated does nothing.
1308 SimulateNavigation(GURL("http://www.google.de"), "de", true);
1309 infobar = GetTranslateInfoBar();
1310 ASSERT_TRUE(infobar != NULL);
1311 infobar->Translate();
1312 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1313 process()->sink().ClearMessages();
1314 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1316 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1317 SimulateOnPageTranslated("de", "en");
1318 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
1319 // No message expected since the translation should have been ignored.
1320 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1322 // Test that the translate context menu is enabled when the page is in an
1323 // unknown language.
1324 SimulateNavigation(url, "und", true);
1325 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1327 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1328 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1330 // Test that the translate context menu is enabled even if the page is in an
1331 // unsupported language.
1332 SimulateNavigation(url, "qbz", true);
1333 menu.reset(TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1335 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1336 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1339 // Tests that an extra always/never translate button is shown on the "before
1340 // translate" infobar when the translation is accepted/declined 3 times,
1341 // only when not in incognito mode.
1342 TEST_F(TranslateManagerBrowserTest, BeforeTranslateExtraButtons) {
1344 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1345 scoped_ptr<TranslatePrefs> translate_prefs(
1346 TranslateTabHelper::CreateTranslatePrefs(profile->GetPrefs()));
1347 translate_prefs->ResetTranslationAcceptedCount("fr");
1348 translate_prefs->ResetTranslationDeniedCount("fr");
1349 translate_prefs->ResetTranslationAcceptedCount("de");
1350 translate_prefs->ResetTranslationDeniedCount("de");
1352 // We'll do 4 times in incognito mode first to make sure the button is not
1353 // shown in that case, then 4 times in normal mode.
1354 TranslateInfoBarDelegate* infobar;
1355 TestingProfile* test_profile =
1356 static_cast<TestingProfile*>(web_contents()->GetBrowserContext());
1357 static_cast<extensions::TestExtensionSystem*>(
1358 extensions::ExtensionSystem::Get(test_profile))->
1359 CreateProcessManager();
1360 test_profile->ForceIncognito(true);
1361 for (int i = 0; i < 8; ++i) {
1362 SCOPED_TRACE(::testing::Message() << "Iteration " << i <<
1363 " incognito mode=" << test_profile->IsOffTheRecord());
1364 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1365 infobar = GetTranslateInfoBar();
1366 ASSERT_TRUE(infobar != NULL);
1367 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
1369 EXPECT_FALSE(infobar->ShouldShowAlwaysTranslateShortcut());
1370 infobar->Translate();
1371 process()->sink().ClearMessages();
1373 EXPECT_TRUE(infobar->ShouldShowAlwaysTranslateShortcut());
1376 test_profile->ForceIncognito(false);
1378 // Simulate the user pressing "Always translate French".
1379 infobar->AlwaysTranslatePageLanguage();
1380 EXPECT_TRUE(translate_prefs->IsLanguagePairWhitelisted("fr", "en"));
1381 // Simulate the translate script being retrieved (it only needs to be done
1382 // once in the test as it is cached).
1383 SimulateTranslateScriptURLFetch(true);
1384 // That should have triggered a page translate.
1386 std::string original_lang, target_lang;
1387 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1388 process()->sink().ClearMessages();
1390 // Now test that declining the translation causes a "never translate" button
1391 // to be shown (in non incognito mode only).
1392 test_profile->ForceIncognito(true);
1393 for (int i = 0; i < 8; ++i) {
1394 SCOPED_TRACE(::testing::Message() << "Iteration " << i <<
1395 " incognito mode=" << test_profile->IsOffTheRecord());
1396 SimulateNavigation(GURL("http://www.google.de"), "de", true);
1397 infobar = GetTranslateInfoBar();
1398 ASSERT_TRUE(infobar != NULL);
1399 EXPECT_EQ(TranslateTabHelper::BEFORE_TRANSLATE, infobar->translate_step());
1401 EXPECT_FALSE(infobar->ShouldShowNeverTranslateShortcut());
1402 infobar->TranslationDeclined();
1404 EXPECT_TRUE(infobar->ShouldShowNeverTranslateShortcut());
1407 test_profile->ForceIncognito(false);
1409 // Simulate the user pressing "Never translate French".
1410 infobar->NeverTranslatePageLanguage();
1411 EXPECT_TRUE(translate_prefs->IsBlockedLanguage("de"));
1412 // No translation should have occured and the infobar should be gone.
1413 EXPECT_FALSE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1414 process()->sink().ClearMessages();
1415 ASSERT_TRUE(GetTranslateInfoBar() == NULL);
1418 // Tests that we don't show a translate infobar when a page instructs that it
1419 // should not be translated.
1420 TEST_F(TranslateManagerBrowserTest, NonTranslatablePage) {
1421 SimulateNavigation(GURL("http://mail.google.fr"), "fr", false);
1423 // We should not have an infobar.
1424 EXPECT_TRUE(GetTranslateInfoBar() == NULL);
1426 // The context menu is enabled to allow users to force translation.
1427 scoped_ptr<TestRenderViewContextMenu> menu(
1428 TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1430 EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1431 EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1434 // Tests that the script is expired and refetched as expected.
1435 TEST_F(TranslateManagerBrowserTest, ScriptExpires) {
1436 ExpireTranslateScriptImmediately();
1438 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1439 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1440 ASSERT_TRUE(infobar != NULL);
1441 process()->sink().ClearMessages();
1442 infobar->Translate();
1443 SimulateTranslateScriptURLFetch(true);
1444 SimulateOnPageTranslated("fr", "en");
1446 // A task should have been posted to clear the script, run it.
1447 base::MessageLoop::current()->RunUntilIdle();
1449 // Do another navigation and translation.
1450 SimulateNavigation(GURL("http://www.google.es"), "es", true);
1451 infobar = GetTranslateInfoBar();
1452 ASSERT_TRUE(infobar != NULL);
1453 process()->sink().ClearMessages();
1454 infobar->Translate();
1455 // If we don't simulate the URL fetch, the TranslateManager should be waiting
1456 // for the script and no message should have been sent to the renderer.
1458 process()->sink().GetFirstMessageMatching(
1459 ChromeViewMsg_TranslatePage::ID) == NULL);
1460 // Now simulate the URL fetch.
1461 SimulateTranslateScriptURLFetch(true);
1462 // Now the message should have been sent.
1464 std::string original_lang, target_lang;
1465 EXPECT_TRUE(GetTranslateMessage(&page_id, &original_lang, &target_lang));
1466 EXPECT_EQ("es", original_lang);
1467 EXPECT_EQ("en", target_lang);
1470 TEST_F(TranslateManagerBrowserTest, DownloadsAndHistoryNotTranslated) {
1471 ASSERT_FALSE(TranslateManager::IsTranslatableURL(
1472 GURL(chrome::kChromeUIDownloadsURL)));
1473 ASSERT_FALSE(TranslateManager::IsTranslatableURL(
1474 GURL(chrome::kChromeUIHistoryURL)));
1477 #if defined(USE_AURA)
1479 TEST_F(TranslateManagerBrowserTest, BubbleNormalTranslate) {
1480 // Prepare for the bubble
1481 TranslateService::SetUseInfobar(false);
1482 MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1483 scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1484 TranslateBubbleFactory::SetFactory(factory);
1486 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1488 // Check the bubble exists instead of the infobar.
1489 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1490 ASSERT_TRUE(infobar == NULL);
1491 TranslateBubbleModel* bubble = factory->model();
1492 ASSERT_TRUE(bubble != NULL);
1493 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
1494 bubble->GetViewState());
1496 // Simulate clicking translate.
1497 process()->sink().ClearMessages();
1498 bubble->Translate();
1500 // Check the bubble shows "Translating...".
1501 bubble = factory->model();
1502 ASSERT_TRUE(bubble != NULL);
1503 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_TRANSLATING,
1504 bubble->GetViewState());
1506 // Simulate the translate script being retrieved (it only needs to be done
1507 // once in the test as it is cached).
1508 SimulateTranslateScriptURLFetch(true);
1510 // Simulate the render notifying the translation has been done.
1511 SimulateOnPageTranslated("fr", "en");
1513 // Check the bubble shows "Translated."
1514 bubble = factory->model();
1515 ASSERT_TRUE(bubble != NULL);
1516 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE,
1517 bubble->GetViewState());
1520 TEST_F(TranslateManagerBrowserTest, BubbleTranslateScriptNotAvailable) {
1521 // Prepare for the bubble
1522 TranslateService::SetUseInfobar(false);
1523 MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1524 scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1525 TranslateBubbleFactory::SetFactory(factory);
1527 SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1529 // Check the bubble exists instead of the infobar.
1530 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1531 ASSERT_TRUE(infobar == NULL);
1532 TranslateBubbleModel* bubble = factory->model();
1533 ASSERT_TRUE(bubble != NULL);
1534 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
1535 bubble->GetViewState());
1537 // Simulate clicking translate.
1538 process()->sink().ClearMessages();
1539 bubble->Translate();
1540 SimulateTranslateScriptURLFetch(false);
1542 // We should not have sent any message to translate to the renderer.
1543 EXPECT_FALSE(GetTranslateMessage(NULL, NULL, NULL));
1545 // And we should have an error infobar showing.
1546 bubble = factory->model();
1547 ASSERT_TRUE(bubble != NULL);
1548 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ERROR,
1549 bubble->GetViewState());
1552 TEST_F(TranslateManagerBrowserTest, BubbleUnknownLanguage) {
1553 // Prepare for the bubble
1554 TranslateService::SetUseInfobar(false);
1555 MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1556 scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1557 TranslateBubbleFactory::SetFactory(factory);
1559 // Simulate navigating to a page ("und" is the string returned by the CLD for
1560 // languages it does not recognize).
1561 SimulateNavigation(GURL("http://www.google.mys"), "und", true);
1563 // We should not have a bubble as we don't know the language.
1564 ASSERT_TRUE(factory->model() == NULL);
1566 // Translate the page anyway throught the context menu.
1567 scoped_ptr<TestRenderViewContextMenu> menu(
1568 TestRenderViewContextMenu::CreateContextMenu(web_contents()));
1570 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
1572 // Check the bubble exists instead of the infobar.
1573 TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1574 ASSERT_TRUE(infobar == NULL);
1575 TranslateBubbleModel* bubble = factory->model();
1576 ASSERT_TRUE(bubble != NULL);
1577 EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_TRANSLATING,
1578 bubble->GetViewState());
1581 #endif // defined(USE_AURA)
1583 // Test is flaky on Win http://crbug.com/166334
1585 #define MAYBE_PRE_TranslateSessionRestore DISABLED_PRE_TranslateSessionRestore
1587 #define MAYBE_PRE_TranslateSessionRestore PRE_TranslateSessionRestore
1589 // Test that session restore restores the translate infobar and other translate
1591 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,
1592 MAYBE_PRE_TranslateSessionRestore) {
1593 SessionStartupPref pref(SessionStartupPref::LAST);
1594 SessionStartupPref::SetStartupPref(browser()->profile(), pref);
1596 content::WebContents* current_web_contents =
1597 browser()->tab_strip_model()->GetActiveWebContents();
1598 TranslateTabHelper* translate_tab_helper =
1599 TranslateTabHelper::FromWebContents(current_web_contents);
1600 content::Source<content::WebContents> source(current_web_contents);
1602 ui_test_utils::WindowedNotificationObserverWithDetails<
1603 LanguageDetectionDetails>
1604 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1607 GURL french_url = ui_test_utils::GetTestUrl(
1608 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("french_page.html")));
1609 ui_test_utils::NavigateToURL(browser(), french_url);
1610 fr_language_detected_signal.Wait();
1611 LanguageDetectionDetails details;
1612 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor(
1613 source.map_key(), &details));
1614 EXPECT_EQ("fr", details.adopted_language);
1615 EXPECT_EQ("fr", translate_tab_helper->GetLanguageState().original_language());
1618 #if defined (OS_WIN)
1619 #define MAYBE_TranslateSessionRestore DISABLED_TranslateSessionRestore
1621 #define MAYBE_TranslateSessionRestore TranslateSessionRestore
1623 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, MAYBE_TranslateSessionRestore) {
1624 content::WebContents* current_web_contents =
1625 browser()->tab_strip_model()->GetActiveWebContents();
1626 content::Source<content::WebContents> source(current_web_contents);
1628 ui_test_utils::WindowedNotificationObserverWithDetails<
1629 LanguageDetectionDetails>
1630 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
1632 fr_language_detected_signal.Wait();