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