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