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