Home | History | Annotate | Download | only in autocomplete
      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 "base/command_line.h"
      6 #include "base/format_macros.h"
      7 #include "base/path_service.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "chrome/browser/autocomplete/autocomplete_input.h"
     11 #include "chrome/browser/autocomplete/autocomplete_match.h"
     12 #include "chrome/browser/autocomplete/autocomplete_provider.h"
     13 #include "chrome/browser/extensions/extension_browsertest.h"
     14 #include "chrome/browser/extensions/extension_service.h"
     15 #include "chrome/browser/extensions/unpacked_installer.h"
     16 #include "chrome/browser/history/history_service.h"
     17 #include "chrome/browser/history/history_service_factory.h"
     18 #include "chrome/browser/profiles/profile.h"
     19 #include "chrome/browser/search_engines/template_url_service_factory.h"
     20 #include "chrome/browser/ui/browser.h"
     21 #include "chrome/browser/ui/browser_commands.h"
     22 #include "chrome/browser/ui/browser_tabstrip.h"
     23 #include "chrome/browser/ui/browser_window.h"
     24 #include "chrome/browser/ui/omnibox/location_bar.h"
     25 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
     26 #include "chrome/browser/ui/omnibox/omnibox_view.h"
     27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     28 #include "chrome/common/chrome_paths.h"
     29 #include "chrome/common/url_constants.h"
     30 #include "chrome/test/base/in_process_browser_test.h"
     31 #include "chrome/test/base/test_switches.h"
     32 #include "chrome/test/base/ui_test_utils.h"
     33 #include "components/metrics/proto/omnibox_event.pb.h"
     34 #include "content/public/browser/notification_service.h"
     35 #include "content/public/browser/notification_types.h"
     36 #include "testing/gtest/include/gtest/gtest.h"
     37 
     38 namespace {
     39 
     40 base::string16 AutocompleteResultAsString(const AutocompleteResult& result) {
     41   std::string output(base::StringPrintf("{%" PRIuS "} ", result.size()));
     42   for (size_t i = 0; i < result.size(); ++i) {
     43     AutocompleteMatch match = result.match_at(i);
     44     output.append(base::StringPrintf("[\"%s\" by \"%s\"] ",
     45                                      base::UTF16ToUTF8(match.contents).c_str(),
     46                                      match.provider->GetName()));
     47   }
     48   return base::UTF8ToUTF16(output);
     49 }
     50 
     51 }  // namespace
     52 
     53 class AutocompleteBrowserTest : public ExtensionBrowserTest {
     54  protected:
     55   void WaitForTemplateURLServiceToLoad() {
     56     ui_test_utils::WaitForTemplateURLServiceToLoad(
     57       TemplateURLServiceFactory::GetForProfile(browser()->profile()));
     58   }
     59 
     60   LocationBar* GetLocationBar() const {
     61     return browser()->window()->GetLocationBar();
     62   }
     63 
     64   AutocompleteController* GetAutocompleteController() const {
     65     return GetLocationBar()->GetOmniboxView()->model()->popup_model()->
     66         autocomplete_controller();
     67   }
     68 };
     69 
     70 IN_PROC_BROWSER_TEST_F(AutocompleteBrowserTest, Basic) {
     71 #if defined(OS_WIN) && defined(USE_ASH)
     72   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
     73   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
     74     return;
     75 #endif
     76 
     77   WaitForTemplateURLServiceToLoad();
     78   LocationBar* location_bar = GetLocationBar();
     79   OmniboxView* omnibox_view = location_bar->GetOmniboxView();
     80 
     81   EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
     82   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
     83   // TODO(phajdan.jr): check state of IsSelectAll when it's consistent across
     84   // platforms.
     85 
     86   location_bar->FocusLocation(true);
     87 
     88   EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
     89   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
     90   EXPECT_TRUE(omnibox_view->IsSelectAll());
     91 
     92   omnibox_view->SetUserText(base::ASCIIToUTF16("chrome"));
     93 
     94   EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
     95   EXPECT_EQ(base::ASCIIToUTF16("chrome"), omnibox_view->GetText());
     96   EXPECT_FALSE(omnibox_view->IsSelectAll());
     97 
     98   omnibox_view->RevertAll();
     99 
    100   EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    101   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    102   EXPECT_FALSE(omnibox_view->IsSelectAll());
    103 
    104   omnibox_view->SetUserText(base::ASCIIToUTF16("chrome"));
    105   location_bar->Revert();
    106 
    107   EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    108   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    109   EXPECT_FALSE(omnibox_view->IsSelectAll());
    110 }
    111 
    112 // Autocomplete test is flaky on ChromeOS.
    113 // http://crbug.com/52928
    114 #if defined(OS_CHROMEOS)
    115 #define MAYBE_Autocomplete DISABLED_Autocomplete
    116 #else
    117 #define MAYBE_Autocomplete Autocomplete
    118 #endif
    119 
    120 IN_PROC_BROWSER_TEST_F(AutocompleteBrowserTest, MAYBE_Autocomplete) {
    121 #if defined(OS_WIN) && defined(USE_ASH)
    122   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    123   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    124     return;
    125 #endif
    126 
    127   WaitForTemplateURLServiceToLoad();
    128   // The results depend on the history backend being loaded. Make sure it is
    129   // loaded so that the autocomplete results are consistent.
    130   ui_test_utils::WaitForHistoryToLoad(
    131       HistoryServiceFactory::GetForProfile(browser()->profile(),
    132                                            Profile::EXPLICIT_ACCESS));
    133 
    134   LocationBar* location_bar = GetLocationBar();
    135   OmniboxView* omnibox_view = location_bar->GetOmniboxView();
    136   AutocompleteController* autocomplete_controller = GetAutocompleteController();
    137 
    138   {
    139     omnibox_view->model()->SetInputInProgress(true);
    140     autocomplete_controller->Start(AutocompleteInput(
    141         base::ASCIIToUTF16("chrome"), base::string16::npos, base::string16(),
    142         GURL(), metrics::OmniboxEventProto::NTP, true, false, true, false));
    143 
    144     EXPECT_TRUE(autocomplete_controller->done());
    145     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    146     EXPECT_TRUE(omnibox_view->GetText().empty());
    147     EXPECT_TRUE(omnibox_view->IsSelectAll());
    148     const AutocompleteResult& result = autocomplete_controller->result();
    149     // We get two matches because we have a provider for extension apps and the
    150     // Chrome Web Store is a built-in Extension app. For this test, we only care
    151     // about the other match existing.
    152     ASSERT_GE(result.size(), 1U) << AutocompleteResultAsString(result);
    153     AutocompleteMatch match = result.match_at(0);
    154     EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, match.type);
    155     EXPECT_FALSE(match.deletable);
    156   }
    157 
    158   {
    159     location_bar->Revert();
    160     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    161     EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    162     EXPECT_FALSE(omnibox_view->IsSelectAll());
    163     const AutocompleteResult& result = autocomplete_controller->result();
    164     EXPECT_TRUE(result.empty()) << AutocompleteResultAsString(result);
    165   }
    166 }
    167 
    168 IN_PROC_BROWSER_TEST_F(AutocompleteBrowserTest, TabAwayRevertSelect) {
    169 #if defined(OS_WIN) && defined(USE_ASH)
    170   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    171   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    172     return;
    173 #endif
    174 
    175   WaitForTemplateURLServiceToLoad();
    176   // http://code.google.com/p/chromium/issues/detail?id=38385
    177   // Make sure that tabbing away from an empty omnibox causes a revert
    178   // and select all.
    179   LocationBar* location_bar = GetLocationBar();
    180   OmniboxView* omnibox_view = location_bar->GetOmniboxView();
    181   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    182   omnibox_view->SetUserText(base::string16());
    183   content::WindowedNotificationObserver observer(
    184       content::NOTIFICATION_LOAD_STOP,
    185       content::NotificationService::AllSources());
    186   chrome::AddSelectedTabWithURL(browser(),
    187                                 GURL(url::kAboutBlankURL),
    188                                 content::PAGE_TRANSITION_AUTO_TOPLEVEL);
    189   observer.Wait();
    190   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    191   chrome::CloseTab(browser());
    192   EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    193   EXPECT_TRUE(omnibox_view->IsSelectAll());
    194 }
    195 
    196 IN_PROC_BROWSER_TEST_F(AutocompleteBrowserTest, FocusSearch) {
    197 #if defined(OS_WIN) && defined(USE_ASH)
    198   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    199   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    200     return;
    201 #endif
    202 
    203   WaitForTemplateURLServiceToLoad();
    204   LocationBar* location_bar = GetLocationBar();
    205   OmniboxView* omnibox_view = location_bar->GetOmniboxView();
    206 
    207   // Focus search when omnibox is blank
    208   {
    209     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    210     EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), omnibox_view->GetText());
    211 
    212     location_bar->FocusSearch();
    213     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    214     EXPECT_EQ(base::ASCIIToUTF16("?"), omnibox_view->GetText());
    215 
    216     size_t selection_start, selection_end;
    217     omnibox_view->GetSelectionBounds(&selection_start, &selection_end);
    218     EXPECT_EQ(1U, selection_start);
    219     EXPECT_EQ(1U, selection_end);
    220   }
    221 
    222   // Focus search when omnibox is _not_ alread in forced query mode.
    223   {
    224     omnibox_view->SetUserText(base::ASCIIToUTF16("foo"));
    225     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    226     EXPECT_EQ(base::ASCIIToUTF16("foo"), omnibox_view->GetText());
    227 
    228     location_bar->FocusSearch();
    229     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    230     EXPECT_EQ(base::ASCIIToUTF16("?"), omnibox_view->GetText());
    231 
    232     size_t selection_start, selection_end;
    233     omnibox_view->GetSelectionBounds(&selection_start, &selection_end);
    234     EXPECT_EQ(1U, selection_start);
    235     EXPECT_EQ(1U, selection_end);
    236   }
    237 
    238   // Focus search when omnibox _is_ already in forced query mode, but no query
    239   // has been typed.
    240   {
    241     omnibox_view->SetUserText(base::ASCIIToUTF16("?"));
    242     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    243     EXPECT_EQ(base::ASCIIToUTF16("?"), omnibox_view->GetText());
    244 
    245     location_bar->FocusSearch();
    246     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    247     EXPECT_EQ(base::ASCIIToUTF16("?"), omnibox_view->GetText());
    248 
    249     size_t selection_start, selection_end;
    250     omnibox_view->GetSelectionBounds(&selection_start, &selection_end);
    251     EXPECT_EQ(1U, selection_start);
    252     EXPECT_EQ(1U, selection_end);
    253   }
    254 
    255   // Focus search when omnibox _is_ already in forced query mode, and some query
    256   // has been typed.
    257   {
    258     omnibox_view->SetUserText(base::ASCIIToUTF16("?foo"));
    259     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    260     EXPECT_EQ(base::ASCIIToUTF16("?foo"), omnibox_view->GetText());
    261 
    262     location_bar->FocusSearch();
    263     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    264     EXPECT_EQ(base::ASCIIToUTF16("?foo"), omnibox_view->GetText());
    265 
    266     size_t selection_start, selection_end;
    267     omnibox_view->GetSelectionBounds(&selection_start, &selection_end);
    268     EXPECT_EQ(1U, std::min(selection_start, selection_end));
    269     EXPECT_EQ(4U, std::max(selection_start, selection_end));
    270   }
    271 
    272   // Focus search when omnibox is in forced query mode with leading whitespace.
    273   {
    274     omnibox_view->SetUserText(base::ASCIIToUTF16("   ?foo"));
    275     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    276     EXPECT_EQ(base::ASCIIToUTF16("   ?foo"), omnibox_view->GetText());
    277 
    278     location_bar->FocusSearch();
    279     EXPECT_FALSE(location_bar->GetDestinationURL().is_valid());
    280     EXPECT_EQ(base::ASCIIToUTF16("   ?foo"), omnibox_view->GetText());
    281 
    282     size_t selection_start, selection_end;
    283     omnibox_view->GetSelectionBounds(&selection_start, &selection_end);
    284     EXPECT_EQ(4U, std::min(selection_start, selection_end));
    285     EXPECT_EQ(7U, std::max(selection_start, selection_end));
    286   }
    287 }
    288