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