• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/format_macros.h"
6 #include "base/string_util.h"
7 #include "base/stringprintf.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/autocomplete/autocomplete.h"
10 #include "chrome/browser/autocomplete/autocomplete_edit.h"
11 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
12 #include "chrome/browser/autocomplete/autocomplete_match.h"
13 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
14 #include "chrome/browser/extensions/extension_apitest.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search_engines/template_url.h"
17 #include "chrome/browser/search_engines/template_url_model.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/browser/ui/omnibox/location_bar.h"
21 #include "chrome/common/url_constants.h"
22 #include "chrome/test/ui_test_utils.h"
23 #include "content/common/notification_type.h"
24 
25 #if defined(TOOLKIT_GTK)
26 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
27 #endif
28 
29 // Basic test is flaky on ChromeOS.
30 // http://crbug.com/52929
31 #if defined(OS_CHROMEOS)
32 #define MAYBE_Basic FLAKY_Basic
33 #else
34 #define MAYBE_Basic Basic
35 #endif
36 
37 namespace {
38 
AutocompleteResultAsString(const AutocompleteResult & result)39 string16 AutocompleteResultAsString(const AutocompleteResult& result) {
40   std::string output(base::StringPrintf("{%" PRIuS "} ", result.size()));
41   for (size_t i = 0; i < result.size(); ++i) {
42     AutocompleteMatch match = result.match_at(i);
43     std::string provider_name = match.provider->name();
44     output.append(base::StringPrintf("[\"%s\" by \"%s\"] ",
45                                      UTF16ToUTF8(match.contents).c_str(),
46                                      provider_name.c_str()));
47   }
48   return UTF8ToUTF16(output);
49 }
50 
51 }  // namespace
52 
53 class OmniboxApiTest : public ExtensionApiTest {
54  protected:
GetLocationBar() const55   LocationBar* GetLocationBar() const {
56     return browser()->window()->GetLocationBar();
57   }
58 
GetAutocompleteController() const59   AutocompleteController* GetAutocompleteController() const {
60     return GetLocationBar()->location_entry()->model()->popup_model()->
61         autocomplete_controller();
62   }
63 
WaitForTemplateURLModelToLoad()64   void WaitForTemplateURLModelToLoad() {
65     TemplateURLModel* model =
66         browser()->profile()->GetTemplateURLModel();
67     model->Load();
68     if (!model->loaded()) {
69       ui_test_utils::WaitForNotification(
70           NotificationType::TEMPLATE_URL_MODEL_LOADED);
71     }
72   }
73 
WaitForAutocompleteDone(AutocompleteController * controller)74   void WaitForAutocompleteDone(AutocompleteController* controller) {
75     while (!controller->done()) {
76       ui_test_utils::WaitForNotification(
77           NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_READY);
78     }
79   }
80 };
81 
IN_PROC_BROWSER_TEST_F(OmniboxApiTest,MAYBE_Basic)82 IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_Basic) {
83 #if defined(TOOLKIT_GTK)
84   // Disable the timer because, on Lucid at least, it triggers resize/move
85   // behavior in the browser window, which dismisses the autocomplete popup
86   // before the results can be read.
87   static_cast<BrowserWindowGtk*>(
88       browser()->window())->DisableDebounceTimerForTests(true);
89 #endif
90 
91   ASSERT_TRUE(test_server()->Start());
92   ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
93 
94   // The results depend on the TemplateURLModel being loaded. Make sure it is
95   // loaded so that the autocomplete results are consistent.
96   WaitForTemplateURLModelToLoad();
97 
98   LocationBar* location_bar = GetLocationBar();
99   AutocompleteController* autocomplete_controller = GetAutocompleteController();
100 
101   // Test that our extension's keyword is suggested to us when we partially type
102   // it.
103   {
104     autocomplete_controller->Start(
105         ASCIIToUTF16("keywor"), string16(), true, false, true,
106         AutocompleteInput::ALL_MATCHES);
107 
108     WaitForAutocompleteDone(autocomplete_controller);
109     EXPECT_TRUE(autocomplete_controller->done());
110     EXPECT_EQ(std::wstring(), location_bar->GetInputString());
111     EXPECT_EQ(string16(), location_bar->location_entry()->GetText());
112     EXPECT_TRUE(location_bar->location_entry()->IsSelectAll());
113 
114     // First result should be to search for what was typed, second should be to
115     // enter "extension keyword" mode.
116     const AutocompleteResult& result = autocomplete_controller->result();
117     ASSERT_EQ(2U, result.size()) << AutocompleteResultAsString(result);
118     AutocompleteMatch match = result.match_at(0);
119     EXPECT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, match.type);
120     EXPECT_FALSE(match.deletable);
121 
122     match = result.match_at(1);
123     ASSERT_TRUE(match.template_url);
124     EXPECT_TRUE(match.template_url->IsExtensionKeyword());
125     EXPECT_EQ(ASCIIToUTF16("keyword"), match.template_url->keyword());
126   }
127 
128   // Test that our extension can send suggestions back to us.
129   {
130     autocomplete_controller->Start(
131         ASCIIToUTF16("keyword suggestio"), string16(), true, false, true,
132         AutocompleteInput::ALL_MATCHES);
133 
134     WaitForAutocompleteDone(autocomplete_controller);
135     EXPECT_TRUE(autocomplete_controller->done());
136 
137     // First result should be to invoke the keyword with what we typed, 2-4
138     // should be to invoke with suggestions from the extension, and the last
139     // should be to search for what we typed.
140     const AutocompleteResult& result = autocomplete_controller->result();
141     ASSERT_EQ(5U, result.size()) << AutocompleteResultAsString(result);
142 
143     ASSERT_TRUE(result.match_at(0).template_url);
144     EXPECT_EQ(ASCIIToUTF16("keyword suggestio"),
145               result.match_at(0).fill_into_edit);
146     EXPECT_EQ(ASCIIToUTF16("keyword suggestion1"),
147               result.match_at(1).fill_into_edit);
148     EXPECT_EQ(ASCIIToUTF16("keyword suggestion2"),
149               result.match_at(2).fill_into_edit);
150     EXPECT_EQ(ASCIIToUTF16("keyword suggestion3"),
151               result.match_at(3).fill_into_edit);
152 
153     string16 description =
154         ASCIIToUTF16("Description with style: <match>, [dim], (url till end)");
155     EXPECT_EQ(description, result.match_at(1).contents);
156     ASSERT_EQ(6u, result.match_at(1).contents_class.size());
157 
158     EXPECT_EQ(0u,
159               result.match_at(1).contents_class[0].offset);
160     EXPECT_EQ(ACMatchClassification::NONE,
161               result.match_at(1).contents_class[0].style);
162 
163     EXPECT_EQ(description.find('<'),
164               result.match_at(1).contents_class[1].offset);
165     EXPECT_EQ(ACMatchClassification::MATCH,
166               result.match_at(1).contents_class[1].style);
167 
168     EXPECT_EQ(description.find('>') + 1u,
169               result.match_at(1).contents_class[2].offset);
170     EXPECT_EQ(ACMatchClassification::NONE,
171               result.match_at(1).contents_class[2].style);
172 
173     EXPECT_EQ(description.find('['),
174               result.match_at(1).contents_class[3].offset);
175     EXPECT_EQ(ACMatchClassification::DIM,
176               result.match_at(1).contents_class[3].style);
177 
178     EXPECT_EQ(description.find(']') + 1u,
179               result.match_at(1).contents_class[4].offset);
180     EXPECT_EQ(ACMatchClassification::NONE,
181               result.match_at(1).contents_class[4].style);
182 
183     EXPECT_EQ(description.find('('),
184               result.match_at(1).contents_class[5].offset);
185     EXPECT_EQ(ACMatchClassification::URL,
186               result.match_at(1).contents_class[5].style);
187 
188     AutocompleteMatch match = result.match_at(4);
189     EXPECT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, match.type);
190     EXPECT_FALSE(match.deletable);
191   }
192 
193   {
194     ResultCatcher catcher;
195     autocomplete_controller->Start(
196         ASCIIToUTF16("keyword command"), string16(), true, false, true,
197         AutocompleteInput::ALL_MATCHES);
198     location_bar->AcceptInput();
199     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
200   }
201 }
202