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