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/strings/string16.h"
6#include "base/strings/utf_string_conversions.h"
7#include "chrome/browser/autocomplete/autocomplete_controller.h"
8#include "chrome/browser/autocomplete/autocomplete_input.h"
9#include "chrome/browser/autocomplete/autocomplete_match.h"
10#include "chrome/browser/autocomplete/autocomplete_result.h"
11#include "chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/search_engines/template_url_service_factory.h"
14#include "chrome/browser/ui/browser.h"
15#include "chrome/browser/ui/omnibox/location_bar.h"
16#include "chrome/browser/ui/omnibox/omnibox_view.h"
17#include "chrome/test/base/ui_test_utils.h"
18#include "ui/base/window_open_disposition.h"
19
20IN_PROC_BROWSER_TEST_F(OmniboxApiTest, Basic) {
21  ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
22
23  // The results depend on the TemplateURLService being loaded. Make sure it is
24  // loaded so that the autocomplete results are consistent.
25  ui_test_utils::WaitForTemplateURLServiceToLoad(
26      TemplateURLServiceFactory::GetForProfile(browser()->profile()));
27
28  AutocompleteController* autocomplete_controller =
29      GetAutocompleteController(browser());
30
31  // Test that our extension's keyword is suggested to us when we partially type
32  // it.
33  {
34    autocomplete_controller->Start(
35        AutocompleteInput(ASCIIToUTF16("keywor"), base::string16::npos,
36                          base::string16(), GURL(), AutocompleteInput::NTP,
37                          true, false, true, AutocompleteInput::ALL_MATCHES));
38    WaitForAutocompleteDone(autocomplete_controller);
39    EXPECT_TRUE(autocomplete_controller->done());
40
41    // Now, peek into the controller to see if it has the results we expect.
42    // First result should be to search for what was typed, second should be to
43    // enter "extension keyword" mode.
44    const AutocompleteResult& result = autocomplete_controller->result();
45    ASSERT_EQ(2U, result.size()) << AutocompleteResultAsString(result);
46    AutocompleteMatch match = result.match_at(0);
47    EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, match.type);
48    EXPECT_FALSE(match.deletable);
49
50    match = result.match_at(1);
51    EXPECT_EQ(ASCIIToUTF16("keyword"), match.keyword);
52  }
53
54  // Test that our extension can send suggestions back to us.
55  {
56    autocomplete_controller->Start(
57        AutocompleteInput(ASCIIToUTF16("keyword suggestio"),
58                          base::string16::npos, base::string16(), GURL(),
59                          AutocompleteInput::NTP, true, false, true,
60                          AutocompleteInput::ALL_MATCHES));
61    WaitForAutocompleteDone(autocomplete_controller);
62    EXPECT_TRUE(autocomplete_controller->done());
63
64    // Now, peek into the controller to see if it has the results we expect.
65    // First result should be to invoke the keyword with what we typed, 2-4
66    // should be to invoke with suggestions from the extension, and the last
67    // should be to search for what we typed.
68    const AutocompleteResult& result = autocomplete_controller->result();
69    ASSERT_EQ(5U, result.size()) << AutocompleteResultAsString(result);
70
71    EXPECT_EQ(ASCIIToUTF16("keyword"), result.match_at(0).keyword);
72    EXPECT_EQ(ASCIIToUTF16("keyword suggestio"),
73              result.match_at(0).fill_into_edit);
74    EXPECT_EQ(AutocompleteMatchType::SEARCH_OTHER_ENGINE,
75              result.match_at(0).type);
76    EXPECT_EQ(AutocompleteProvider::TYPE_KEYWORD,
77              result.match_at(0).provider->type());
78    EXPECT_EQ(ASCIIToUTF16("keyword"), result.match_at(1).keyword);
79    EXPECT_EQ(ASCIIToUTF16("keyword suggestion1"),
80              result.match_at(1).fill_into_edit);
81    EXPECT_EQ(AutocompleteProvider::TYPE_KEYWORD,
82              result.match_at(1).provider->type());
83    EXPECT_EQ(ASCIIToUTF16("keyword"), result.match_at(2).keyword);
84    EXPECT_EQ(ASCIIToUTF16("keyword suggestion2"),
85              result.match_at(2).fill_into_edit);
86    EXPECT_EQ(AutocompleteProvider::TYPE_KEYWORD,
87              result.match_at(2).provider->type());
88    EXPECT_EQ(ASCIIToUTF16("keyword"), result.match_at(3).keyword);
89    EXPECT_EQ(ASCIIToUTF16("keyword suggestion3"),
90              result.match_at(3).fill_into_edit);
91    EXPECT_EQ(AutocompleteProvider::TYPE_KEYWORD,
92              result.match_at(3).provider->type());
93
94    base::string16 description =
95        ASCIIToUTF16("Description with style: <match>, [dim], (url till end)");
96    EXPECT_EQ(description, result.match_at(1).contents);
97    ASSERT_EQ(6u, result.match_at(1).contents_class.size());
98
99    EXPECT_EQ(0u,
100              result.match_at(1).contents_class[0].offset);
101    EXPECT_EQ(ACMatchClassification::NONE,
102              result.match_at(1).contents_class[0].style);
103
104    EXPECT_EQ(description.find('<'),
105              result.match_at(1).contents_class[1].offset);
106    EXPECT_EQ(ACMatchClassification::MATCH,
107              result.match_at(1).contents_class[1].style);
108
109    EXPECT_EQ(description.find('>') + 1u,
110              result.match_at(1).contents_class[2].offset);
111    EXPECT_EQ(ACMatchClassification::NONE,
112              result.match_at(1).contents_class[2].style);
113
114    EXPECT_EQ(description.find('['),
115              result.match_at(1).contents_class[3].offset);
116    EXPECT_EQ(ACMatchClassification::DIM,
117              result.match_at(1).contents_class[3].style);
118
119    EXPECT_EQ(description.find(']') + 1u,
120              result.match_at(1).contents_class[4].offset);
121    EXPECT_EQ(ACMatchClassification::NONE,
122              result.match_at(1).contents_class[4].style);
123
124    EXPECT_EQ(description.find('('),
125              result.match_at(1).contents_class[5].offset);
126    EXPECT_EQ(ACMatchClassification::URL,
127              result.match_at(1).contents_class[5].style);
128
129    AutocompleteMatch match = result.match_at(4);
130    EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, match.type);
131    EXPECT_EQ(AutocompleteProvider::TYPE_SEARCH,
132              result.match_at(4).provider->type());
133    EXPECT_FALSE(match.deletable);
134  }
135
136  // Flaky, see http://crbug.com/167158
137  /*
138  {
139    LocationBar* location_bar = GetLocationBar(browser());
140    ResultCatcher catcher;
141    OmniboxView* omnibox_view = location_bar->GetOmniboxView();
142    omnibox_view->OnBeforePossibleChange();
143    omnibox_view->SetUserText(ASCIIToUTF16("keyword command"));
144    omnibox_view->OnAfterPossibleChange();
145    location_bar->AcceptInput();
146    // This checks that the keyword provider (via javascript)
147    // gets told to navigate to the string "command".
148    EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
149  }
150  */
151}
152
153IN_PROC_BROWSER_TEST_F(OmniboxApiTest, OnInputEntered) {
154  ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
155  ui_test_utils::WaitForTemplateURLServiceToLoad(
156      TemplateURLServiceFactory::GetForProfile(browser()->profile()));
157
158  LocationBar* location_bar = GetLocationBar(browser());
159  OmniboxView* omnibox_view = location_bar->GetOmniboxView();
160  ResultCatcher catcher;
161  AutocompleteController* autocomplete_controller =
162      GetAutocompleteController(browser());
163  omnibox_view->OnBeforePossibleChange();
164  omnibox_view->SetUserText(ASCIIToUTF16("keyword command"));
165  omnibox_view->OnAfterPossibleChange();
166
167  autocomplete_controller->Start(
168      AutocompleteInput(ASCIIToUTF16("keyword command"), base::string16::npos,
169                        base::string16(), GURL(), AutocompleteInput::NTP,
170                        true, false, true, AutocompleteInput::ALL_MATCHES));
171  omnibox_view->model()->AcceptInput(CURRENT_TAB, false);
172  WaitForAutocompleteDone(autocomplete_controller);
173  EXPECT_TRUE(autocomplete_controller->done());
174  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
175
176  omnibox_view->OnBeforePossibleChange();
177  omnibox_view->SetUserText(ASCIIToUTF16("keyword newtab"));
178  omnibox_view->OnAfterPossibleChange();
179  WaitForAutocompleteDone(autocomplete_controller);
180  EXPECT_TRUE(autocomplete_controller->done());
181
182  autocomplete_controller->Start(
183      AutocompleteInput(ASCIIToUTF16("keyword newtab"), base::string16::npos,
184                        base::string16(), GURL(), AutocompleteInput::NTP,
185                        true, false, true, AutocompleteInput::ALL_MATCHES));
186  omnibox_view->model()->AcceptInput(NEW_FOREGROUND_TAB, false);
187  WaitForAutocompleteDone(autocomplete_controller);
188  EXPECT_TRUE(autocomplete_controller->done());
189  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
190}
191
192// Tests that we get suggestions from and send input to the incognito context
193// of an incognito split mode extension.
194// http://crbug.com/100927
195// Test is flaky: http://crbug.com/101219
196IN_PROC_BROWSER_TEST_F(OmniboxApiTest, DISABLED_IncognitoSplitMode) {
197  ResultCatcher catcher_incognito;
198  catcher_incognito.RestrictToProfile(
199      browser()->profile()->GetOffTheRecordProfile());
200
201  ASSERT_TRUE(RunExtensionTestIncognito("omnibox")) << message_;
202
203  // Open an incognito window and wait for the incognito extension process to
204  // respond.
205  Browser* incognito_browser = CreateIncognitoBrowser();
206  ASSERT_TRUE(catcher_incognito.GetNextResult()) << catcher_incognito.message();
207
208  // The results depend on the TemplateURLService being loaded. Make sure it is
209  // loaded so that the autocomplete results are consistent.
210  ui_test_utils::WaitForTemplateURLServiceToLoad(
211      TemplateURLServiceFactory::GetForProfile(browser()->profile()));
212
213  LocationBar* location_bar = GetLocationBar(incognito_browser);
214  AutocompleteController* autocomplete_controller =
215      GetAutocompleteController(incognito_browser);
216
217  // Test that we get the incognito-specific suggestions.
218  {
219    autocomplete_controller->Start(
220        AutocompleteInput(ASCIIToUTF16("keyword suggestio"),
221                          base::string16::npos, base::string16(), GURL(),
222                          AutocompleteInput::NTP, true, false, true,
223                          AutocompleteInput::ALL_MATCHES));
224    WaitForAutocompleteDone(autocomplete_controller);
225    EXPECT_TRUE(autocomplete_controller->done());
226
227    // First result should be to invoke the keyword with what we typed, 2-4
228    // should be to invoke with suggestions from the extension, and the last
229    // should be to search for what we typed.
230    const AutocompleteResult& result = autocomplete_controller->result();
231    ASSERT_EQ(5U, result.size()) << AutocompleteResultAsString(result);
232    ASSERT_FALSE(result.match_at(0).keyword.empty());
233    EXPECT_EQ(ASCIIToUTF16("keyword suggestion3 incognito"),
234              result.match_at(3).fill_into_edit);
235  }
236
237  // Test that our input is sent to the incognito context. The test will do a
238  // text comparison and succeed only if "command incognito" is sent to the
239  // incognito context.
240  {
241    ResultCatcher catcher;
242    autocomplete_controller->Start(
243        AutocompleteInput(ASCIIToUTF16("keyword command incognito"),
244                          base::string16::npos, base::string16(), GURL(),
245                          AutocompleteInput::NTP, true, false, true,
246                          AutocompleteInput::ALL_MATCHES));
247    location_bar->AcceptInput();
248    EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
249  }
250}
251