• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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