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.
57class 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  virtual 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
85class 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
368class MockTranslateBubbleFactory : public TranslateBubbleFactory {
369 public:
370  MockTranslateBubbleFactory() {}
371
372  virtual 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
408TEST_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
491TEST_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).
521TEST_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.
593TEST_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.
637static const char* server_language_list[] =
638    {"ach", "ak", "af", "en-CA", "zh", "yi", "fr-FR", "tl", "iw", "in", "xx"};
639static const char* alpha_language_list[] = {"ach", "yi"};
640
641// Test the fetching of languages from the translate server
642TEST_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.
701TEST_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.
740TEST_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.
774TEST_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.
799TEST_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.
828TEST_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  rvh_tester()->SendNavigateWithTransition(
844      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.
861TEST_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)
881TEST_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.
911TEST_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.
932TEST_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.
964TEST_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.
993TEST_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.
1008TEST_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.
1045TEST_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
1076TEST_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.
1110TEST_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.
1144TEST_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.
1200TEST_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.
1255TEST_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.
1321TEST_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.
1432TEST_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  static_cast<extensions::TestExtensionSystem*>(
1452      extensions::ExtensionSystem::Get(test_profile))->CreateProcessManager();
1453  test_profile->ForceIncognito(true);
1454  for (int i = 0; i < 8; ++i) {
1455    SCOPED_TRACE(::testing::Message() << "Iteration " << i << " incognito mode="
1456                                      << test_profile->IsOffTheRecord());
1457    SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1458    infobar = GetTranslateInfoBar();
1459    ASSERT_TRUE(infobar != NULL);
1460    EXPECT_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE,
1461              infobar->translate_step());
1462    if (i < 7) {
1463      EXPECT_FALSE(infobar->ShouldShowAlwaysTranslateShortcut());
1464      infobar->Translate();
1465      process()->sink().ClearMessages();
1466    } else {
1467      EXPECT_TRUE(infobar->ShouldShowAlwaysTranslateShortcut());
1468    }
1469    if (i == 3)
1470      test_profile->ForceIncognito(false);
1471  }
1472  // Simulate the user pressing "Always translate French".
1473  infobar->AlwaysTranslatePageLanguage();
1474  EXPECT_TRUE(translate_prefs->IsLanguagePairWhitelisted("fr", "en"));
1475  // Simulate the translate script being retrieved (it only needs to be done
1476  // once in the test as it is cached).
1477  SimulateTranslateScriptURLFetch(true);
1478  // That should have triggered a page translate.
1479  std::string original_lang, target_lang;
1480  EXPECT_TRUE(GetTranslateMessage(&original_lang, &target_lang));
1481  process()->sink().ClearMessages();
1482
1483  // Now test that declining the translation causes a "never translate" button
1484  // to be shown (in non incognito mode only).
1485  test_profile->ForceIncognito(true);
1486  for (int i = 0; i < 8; ++i) {
1487    SCOPED_TRACE(::testing::Message() << "Iteration " << i << " incognito mode="
1488                                      << test_profile->IsOffTheRecord());
1489    SimulateNavigation(GURL("http://www.google.de"), "de", true);
1490    infobar = GetTranslateInfoBar();
1491    ASSERT_TRUE(infobar != NULL);
1492    EXPECT_EQ(translate::TRANSLATE_STEP_BEFORE_TRANSLATE,
1493              infobar->translate_step());
1494    if (i < 7) {
1495      EXPECT_FALSE(infobar->ShouldShowNeverTranslateShortcut());
1496      infobar->TranslationDeclined();
1497    } else {
1498      EXPECT_TRUE(infobar->ShouldShowNeverTranslateShortcut());
1499    }
1500    if (i == 3)
1501      test_profile->ForceIncognito(false);
1502  }
1503  // Simulate the user pressing "Never translate French".
1504  infobar->NeverTranslatePageLanguage();
1505  EXPECT_TRUE(translate_prefs->IsBlockedLanguage("de"));
1506  // No translation should have occured and the infobar should be gone.
1507  EXPECT_FALSE(GetTranslateMessage(&original_lang, &target_lang));
1508  process()->sink().ClearMessages();
1509  ASSERT_TRUE(GetTranslateInfoBar() == NULL);
1510}
1511
1512// Tests that we don't show a translate infobar when a page instructs that it
1513// should not be translated.
1514TEST_F(TranslateManagerRenderViewHostTest, NonTranslatablePage) {
1515  // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235
1516  if (TranslateService::IsTranslateBubbleEnabled())
1517    return;
1518
1519  SimulateNavigation(GURL("http://mail.google.fr"), "fr", false);
1520
1521  // We should not have an infobar.
1522  EXPECT_TRUE(GetTranslateInfoBar() == NULL);
1523
1524  // The context menu is enabled to allow users to force translation.
1525  scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu());
1526  menu->Init();
1527  EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATE));
1528  EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_TRANSLATE));
1529}
1530
1531// Tests that the script is expired and refetched as expected.
1532TEST_F(TranslateManagerRenderViewHostTest, ScriptExpires) {
1533  // TODO(port): Test corresponding bubble translate UX: http://crbug.com/383235
1534  if (TranslateService::IsTranslateBubbleEnabled())
1535    return;
1536
1537  ExpireTranslateScriptImmediately();
1538
1539  SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1540  translate::TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1541  ASSERT_TRUE(infobar != NULL);
1542  process()->sink().ClearMessages();
1543  infobar->Translate();
1544  SimulateTranslateScriptURLFetch(true);
1545  SimulateOnPageTranslated("fr", "en");
1546
1547  // A task should have been posted to clear the script, run it.
1548  base::MessageLoop::current()->RunUntilIdle();
1549
1550  // Do another navigation and translation.
1551  SimulateNavigation(GURL("http://www.google.es"), "es", true);
1552  infobar = GetTranslateInfoBar();
1553  ASSERT_TRUE(infobar != NULL);
1554  process()->sink().ClearMessages();
1555  infobar->Translate();
1556  // If we don't simulate the URL fetch, the TranslateManager should be waiting
1557  // for the script and no message should have been sent to the renderer.
1558  EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
1559                  ChromeViewMsg_TranslatePage::ID) == NULL);
1560  // Now simulate the URL fetch.
1561  SimulateTranslateScriptURLFetch(true);
1562  // Now the message should have been sent.
1563  std::string original_lang, target_lang;
1564  EXPECT_TRUE(GetTranslateMessage(&original_lang, &target_lang));
1565  EXPECT_EQ("es", original_lang);
1566  EXPECT_EQ("en", target_lang);
1567}
1568
1569TEST_F(TranslateManagerRenderViewHostTest, DownloadsAndHistoryNotTranslated) {
1570  ASSERT_FALSE(
1571      TranslateService::IsTranslatableURL(GURL(chrome::kChromeUIDownloadsURL)));
1572  ASSERT_FALSE(
1573      TranslateService::IsTranslatableURL(GURL(chrome::kChromeUIHistoryURL)));
1574}
1575
1576TEST_F(TranslateManagerRenderViewHostTest, BubbleNormalTranslate) {
1577  // See NormalTranslate for corresponding infobar UX testing.
1578  if (!TranslateService::IsTranslateBubbleEnabled())
1579    return;
1580
1581  MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1582  scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1583  TranslateBubbleFactory::SetFactory(factory);
1584
1585  SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1586
1587  // Check the bubble exists instead of the infobar.
1588  translate::TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1589  ASSERT_TRUE(infobar == NULL);
1590  TranslateBubbleModel* bubble = factory->model();
1591  ASSERT_TRUE(bubble != NULL);
1592  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
1593            bubble->GetViewState());
1594
1595  // Simulate clicking translate.
1596  process()->sink().ClearMessages();
1597  bubble->Translate();
1598
1599  // Check the bubble shows "Translating...".
1600  bubble = factory->model();
1601  ASSERT_TRUE(bubble != NULL);
1602  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_TRANSLATING,
1603            bubble->GetViewState());
1604
1605  // Simulate the translate script being retrieved (it only needs to be done
1606  // once in the test as it is cached).
1607  SimulateTranslateScriptURLFetch(true);
1608
1609  // Simulate the render notifying the translation has been done.
1610  SimulateOnPageTranslated("fr", "en");
1611
1612  // Check the bubble shows "Translated."
1613  bubble = factory->model();
1614  ASSERT_TRUE(bubble != NULL);
1615  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE,
1616            bubble->GetViewState());
1617}
1618
1619TEST_F(TranslateManagerRenderViewHostTest, BubbleTranslateScriptNotAvailable) {
1620  // See TranslateScriptNotAvailable for corresponding infobar UX testing.
1621  if (!TranslateService::IsTranslateBubbleEnabled())
1622    return;
1623
1624  MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1625  scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1626  TranslateBubbleFactory::SetFactory(factory);
1627
1628  SimulateNavigation(GURL("http://www.google.fr"), "fr", true);
1629
1630  // Check the bubble exists instead of the infobar.
1631  translate::TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1632  ASSERT_TRUE(infobar == NULL);
1633  TranslateBubbleModel* bubble = factory->model();
1634  ASSERT_TRUE(bubble != NULL);
1635  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
1636            bubble->GetViewState());
1637
1638  // Simulate clicking translate.
1639  process()->sink().ClearMessages();
1640  bubble->Translate();
1641  SimulateTranslateScriptURLFetch(false);
1642
1643  // We should not have sent any message to translate to the renderer.
1644  EXPECT_FALSE(GetTranslateMessage(NULL, NULL));
1645
1646  // And we should have an error infobar showing.
1647  bubble = factory->model();
1648  ASSERT_TRUE(bubble != NULL);
1649  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ERROR, bubble->GetViewState());
1650}
1651
1652TEST_F(TranslateManagerRenderViewHostTest, BubbleUnknownLanguage) {
1653  // See TranslateUnknownLanguage for corresponding infobar UX testing.
1654  if (!TranslateService::IsTranslateBubbleEnabled())
1655    return;
1656
1657  MockTranslateBubbleFactory* factory = new MockTranslateBubbleFactory;
1658  scoped_ptr<TranslateBubbleFactory> factory_ptr(factory);
1659  TranslateBubbleFactory::SetFactory(factory);
1660
1661  // Simulate navigating to a page ("und" is the string returned by the CLD for
1662  // languages it does not recognize).
1663  SimulateNavigation(GURL("http://www.google.mys"), "und", true);
1664
1665  // We should not have a bubble as we don't know the language.
1666  ASSERT_TRUE(factory->model() == NULL);
1667
1668  // Translate the page anyway throught the context menu.
1669  scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu());
1670  menu->Init();
1671  menu->ExecuteCommand(IDC_CONTENT_CONTEXT_TRANSLATE, 0);
1672
1673  // Check the bubble exists instead of the infobar.
1674  translate::TranslateInfoBarDelegate* infobar = GetTranslateInfoBar();
1675  ASSERT_TRUE(infobar == NULL);
1676  TranslateBubbleModel* bubble = factory->model();
1677  ASSERT_TRUE(bubble != NULL);
1678  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_TRANSLATING,
1679            bubble->GetViewState());
1680}
1681