Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc

Issue 177052: Add autocomplete_edit_view_browsertest.cc (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:mergeinfo
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 <stdio.h>
6
7 #include "base/file_path.h"
8 #include "base/keyboard_codes.h"
9 #include "base/logging.h"
10 #include "base/message_loop.h"
11 #include "base/platform_thread.h"
12 #include "base/ref_counted.h"
13 #include "base/string_util.h"
14 #include "base/time.h"
15 #include "chrome/app/chrome_dll_resource.h"
16 #include "chrome/browser/autocomplete/autocomplete.h"
17 #include "chrome/browser/autocomplete/autocomplete_edit.h"
18 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
19 #include "chrome/browser/autocomplete/autocomplete_edit_view.h"
20 #include "chrome/browser/automation/ui_controls.h"
21 #include "chrome/browser/bookmarks/bookmark_model.h"
22 #include "chrome/browser/browser.h"
23 #include "chrome/browser/browser_window.h"
24 #include "chrome/browser/history/history.h"
25 #include "chrome/browser/location_bar.h"
26 #include "chrome/browser/profile.h"
27 #include "chrome/browser/search_engines/template_url.h"
28 #include "chrome/browser/search_engines/template_url_model.h"
29 #include "chrome/browser/tab_contents/tab_contents.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/notification_service.h"
32 #include "chrome/test/in_process_browser_test.h"
33 #include "chrome/test/ui_test_utils.h"
34 #include "net/base/mock_host_resolver.h"
35 #include "views/event.h"
36
37 using base::Time;
38 using base::TimeDelta;
39
40 namespace {
41
42 const wchar_t kSearchKeyword[] = L"foo";
43 const wchar_t kSearchKeywordKeys[] = {
44 base::VKEY_F, base::VKEY_O, base::VKEY_O, 0
45 };
46 const wchar_t kSearchURL[] = L"http://www.foo.com/search?q={searchTerms}";
47 const wchar_t kSearchShortName[] = L"foo";
48 const wchar_t kSearchText[] = L"abc";
49 const wchar_t kSearchTextKeys[] = {
50 base::VKEY_A, base::VKEY_B, base::VKEY_C, 0
51 };
52 const char kSearchTextURL[] = "http://www.foo.com/search?q=abc";
53 const char kHistoryPageURL[] = "chrome://history/#q=abc";
54
55 const char kDesiredTLDHostname[] = "www.bar.com";
56 const wchar_t kDesiredTLDKeys[] = {
57 base::VKEY_B, base::VKEY_A, base::VKEY_R, 0
58 };
59
60 // Hostnames that shall be blocked by host resolver.
61 const char *kBlockedHostnames[] = {
62 "foo",
63 "*.foo.com",
64 "bar",
65 "*.bar.com",
66 "abc",
67 "*.abc.com"
68 };
69
70 const struct TestHistoryEntry {
71 const char* url;
72 const wchar_t* title;
73 const wchar_t* body;
74 int visit_count;
75 int typed_count;
76 bool starred;
77 } kHistoryEntries[] = {
78 {"http://www.bar.com/1", L"Page 1", kSearchText, 1, 1, false },
79 {"http://www.bar.com/2", L"Page 2", kSearchText, 1, 1, false },
80 {"http://www.bar.com/3", L"Page 3", kSearchText, 1, 1, false },
81 {"http://www.bar.com/4", L"Page 4", kSearchText, 1, 1, false },
82 {"http://www.bar.com/5", L"Page 5", kSearchText, 1, 1, false },
83 {"http://www.bar.com/6", L"Page 6", kSearchText, 1, 1, false },
84 {"http://www.bar.com/7", L"Page 7", kSearchText, 1, 1, false },
85 {"http://www.bar.com/8", L"Page 8", kSearchText, 1, 1, false },
86 {"http://www.bar.com/9", L"Page 9", kSearchText, 1, 1, false },
87
88 // To trigger inline autocomplete.
89 {"http://www.abc.com", L"Page abc", kSearchText, 10000, 10000, true },
90 };
91
92 } // namespace
93
94 class AutocompleteEditViewTest : public InProcessBrowserTest,
95 public NotificationObserver {
96 protected:
97 AutocompleteEditViewTest() {
98 set_show_window(true);
99 }
100
101 void GetNativeWindow(gfx::NativeWindow* native_window) {
102 BrowserWindow* window = browser()->window();
103 ASSERT_TRUE(window);
104 *native_window = window->GetNativeHandle();
105 ASSERT_TRUE(*native_window);
106 }
107
108 void GetAutocompleteEditView(AutocompleteEditView** edit_view) {
109 BrowserWindow* window = browser()->window();
110 ASSERT_TRUE(window);
111 LocationBar* loc_bar = window->GetLocationBar();
112 ASSERT_TRUE(loc_bar);
113 *edit_view = loc_bar->location_entry();
114 ASSERT_TRUE(*edit_view);
115 }
116
117 void SendKey(wchar_t key, bool control, bool shift, bool alt) {
118 gfx::NativeWindow window;
119 ASSERT_NO_FATAL_FAILURE(GetNativeWindow(&window));
120 ui_controls::SendKeyPressNotifyWhenDone(window, key, control, shift, alt,
121 new MessageLoop::QuitTask());
122 ui_test_utils::RunMessageLoop();
123 }
124
125 void SendKeySequence(const wchar_t* keys) {
126 for (; *keys; ++keys)
127 ASSERT_NO_FATAL_FAILURE(SendKey(*keys, false, false, false));
128 }
129
130 void WaitForTabOpenOrClose(int expected_tab_count) {
131 int tab_count = browser()->tab_count();
132 if (tab_count == expected_tab_count)
133 return;
134
135 NotificationRegistrar registrar;
136 registrar.Add(this,
137 (tab_count < expected_tab_count ?
138 NotificationType::TAB_PARENTED :
139 NotificationType::TAB_CLOSED),
140 NotificationService::AllSources());
141
142 while (!HasFailure() && browser()->tab_count() != expected_tab_count)
143 ui_test_utils::RunMessageLoop();
144
145 ASSERT_EQ(expected_tab_count, browser()->tab_count());
146 }
147
148 void WaitForAutocompleteControllerDone() {
149 AutocompleteEditView* edit_view;
150 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
151
152 AutocompleteController* controller =
153 edit_view->model()->popup_model()->autocomplete_controller();
154 ASSERT_TRUE(controller);
155
156 if (controller->done())
157 return;
158
159 NotificationRegistrar registrar;
160 registrar.Add(this,
161 NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
162 Source<AutocompleteController>(controller));
163
164 while (!HasFailure() && !controller->done())
165 ui_test_utils::RunMessageLoop();
166
167 ASSERT_TRUE(controller->done());
168 }
169
170 void SetupSearchEngine() {
171 TemplateURLModel* model = browser()->profile()->GetTemplateURLModel();
172 ASSERT_TRUE(model);
173
174 if (!model->loaded()) {
175 NotificationRegistrar registrar;
176 registrar.Add(this, NotificationType::TEMPLATE_URL_MODEL_LOADED,
177 Source<TemplateURLModel>(model));
178 model->Load();
179 ui_test_utils::RunMessageLoop();
180 }
181
182 ASSERT_TRUE(model->loaded());
183
184 TemplateURL* template_url = new TemplateURL();
185 template_url->SetURL(kSearchURL, 0, 0);
186 template_url->set_keyword(kSearchKeyword);
187 template_url->set_short_name(kSearchShortName);
188
189 model->Add(template_url);
190 model->SetDefaultSearchProvider(template_url);
191 }
192
193 void SetupHistory() {
194 HistoryService* history_service =
195 browser()->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
196 ASSERT_TRUE(history_service);
197
198 // Add enough history pages containing |kSearchText| to trigger open history
199 // page url in autocomplete result.
200 for (size_t i = 0; i < arraysize(kHistoryEntries); i++) {
201 const TestHistoryEntry& cur = kHistoryEntries[i];
202 GURL url(cur.url);
203 // Add everything in order of time. We don't want to have a time that
204 // is "right now" or it will nondeterministically appear in the results.
205 Time t = Time::Now() - TimeDelta::FromHours(i + 1);
206 history_service->AddPageWithDetails(url, cur.title, cur.visit_count,
207 cur.typed_count, t, false);
208 history_service->SetPageContents(url, cur.body);
209 if (cur.starred) {
210 browser()->profile()->GetBookmarkModel()->SetURLStarred(
211 url, std::wstring(), true);
212 }
213 }
214 }
215
216 void SetupHostResolver() {
217 for (size_t i = 0; i < arraysize(kBlockedHostnames); ++i)
218 host_resolver()->AddSimulatedFailure(kBlockedHostnames[i]);
219 }
220
221 virtual void Observe(NotificationType type,
222 const NotificationSource& source,
223 const NotificationDetails& details) {
224 ASSERT_TRUE(MessageLoopForUI::current()->IsNested());
225 switch (type.value) {
226 case NotificationType::TAB_PARENTED:
227 case NotificationType::TAB_CLOSED:
228 case NotificationType::TEMPLATE_URL_MODEL_LOADED:
229 case NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED:
230 break;
231 default:
232 FAIL() << "Unexpected notification type";
233 }
234 MessageLoopForUI::current()->Quit();
235 }
236
237 #if defined(OS_WIN)
238 virtual void CleanUpOnMainThread() {
239 // A hack to avoid hitting issue http://crbug.com/18372 and
240 // http://crbug.com/18373
241 // Weird that it only happens on Windows.
242 // TODO(suzhe): Remove ths hack as soon as these bugs are fixed.
Peter Kasting 2009/09/14 17:54:57 Nit: ths -> this
James Su 2009/09/15 01:13:47 Done.
243 MessageLoop::current()->PostDelayedTask(FROM_HERE,
244 new MessageLoop::QuitTask(),
245 2000);
246 ui_test_utils::RunMessageLoop();
247 }
248 #endif
249 };
250
251 // Test if ctrl-* accelerators are workable in omnibox.
252 // See http://crbug.com/19193: omnibox blocks ctrl-* commands
253 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BrowserAccelerators) {
254 browser()->FocusLocationBar();
255 AutocompleteEditView* edit_view;
256 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
257
258 int tab_count = browser()->tab_count();
259
260 // Create a new Tab.
261 browser()->NewTab();
262 ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
263
264 // Select the first Tab.
265 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_1, true, false, false));
266 ASSERT_EQ(0, browser()->selected_index());
267
268 browser()->FocusLocationBar();
269
270 // Select the second Tab.
271 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_2, true, false, false));
272 ASSERT_EQ(1, browser()->selected_index());
273
274 browser()->FocusLocationBar();
275
276 // Close a Tab.
277 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_W, true, false, false));
278 ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count));
279
280 // Try ctrl-l to focus location bar.
281 edit_view->SetUserText(L"Hello world");
282 EXPECT_FALSE(edit_view->IsSelectAll());
283 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_L, true, false, false));
284 EXPECT_TRUE(edit_view->IsSelectAll());
285 }
286
287 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, BackspaceInKeywordMode) {
288 ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
289 ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
290 browser()->FocusLocationBar();
291
292 AutocompleteEditView* edit_view;
293 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
294
295 // Trigger keyword hint mode.
296 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
297 ASSERT_TRUE(edit_view->model()->is_keyword_hint());
298 ASSERT_EQ(std::wstring(kSearchKeyword), edit_view->model()->keyword());
299
300 // Trigger keyword mode.
301 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_TAB, false, false, false));
302 ASSERT_FALSE(edit_view->model()->is_keyword_hint());
303 ASSERT_EQ(std::wstring(kSearchKeyword), edit_view->model()->keyword());
304
305 // Backspace without search text should bring back keyword hint mode.
306 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_BACK, false, false, false));
307 ASSERT_TRUE(edit_view->model()->is_keyword_hint());
308 ASSERT_EQ(std::wstring(kSearchKeyword), edit_view->model()->keyword());
309
310 // Trigger keyword mode again.
311 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_TAB, false, false, false));
312 ASSERT_FALSE(edit_view->model()->is_keyword_hint());
313 ASSERT_EQ(std::wstring(kSearchKeyword), edit_view->model()->keyword());
314
315 // Input something as search text.
316 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
317
318 // Should stay in keyword mode while deleting search text by pressing
319 // backspace.
320 for (size_t i = 0; i < arraysize(kSearchText) - 1; ++i) {
321 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_BACK, false, false, false));
322 ASSERT_FALSE(edit_view->model()->is_keyword_hint());
323 ASSERT_EQ(std::wstring(kSearchKeyword), edit_view->model()->keyword());
324 }
325
326 // Input something as search text.
327 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
328
329 // Move cursor to the beginning of the search text.
330 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_HOME, false, false, false));
331 // Backspace at the beginning of the search text shall turn off
332 // the keyword mode.
333 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_BACK, false, false, false));
334 ASSERT_FALSE(edit_view->model()->is_keyword_hint());
335 ASSERT_EQ(std::wstring(), edit_view->model()->keyword());
336 ASSERT_EQ(std::wstring(kSearchKeyword) + std::wstring(kSearchText),
337 edit_view->GetText());
338 }
339
340 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, Escape) {
341 ui_test_utils::NavigateToURL(browser(), GURL("chrome://history/"));
342 browser()->FocusLocationBar();
343
344 AutocompleteEditView* edit_view;
345 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
346
347 std::wstring old_text = edit_view->GetText();
348 EXPECT_FALSE(old_text.empty());
349 EXPECT_TRUE(edit_view->IsSelectAll());
350
351 // Delete all text in omnibox.
352 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_BACK, false, false, false));
353 EXPECT_TRUE(edit_view->GetText().empty());
354
355 // Escape shall revert the text in omnibox.
356 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_ESCAPE, false, false, false));
357 EXPECT_EQ(old_text, edit_view->GetText());
358 EXPECT_TRUE(edit_view->IsSelectAll());
359 }
360
361 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, DesiredTLD) {
362 ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
363 ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
364 browser()->FocusLocationBar();
365
366 AutocompleteEditView* edit_view;
367 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
368 AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
369 ASSERT_TRUE(popup_model);
370
371 // Test ctrl-Enter.
372 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kDesiredTLDKeys));
373 ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
374 ASSERT_TRUE(popup_model->IsOpen());
375 // ctrl-Enter triggers desired_tld feature, thus www.bar.com shall be opened.
376 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_RETURN, true, false, false));
377
378 GURL url = browser()->GetSelectedTabContents()->GetURL();
379 EXPECT_STREQ(kDesiredTLDHostname, url.host().c_str());
380 }
381
382 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, AltEnter) {
383 browser()->FocusLocationBar();
384
385 AutocompleteEditView* edit_view;
386 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
387
388 edit_view->SetUserText(L"chrome://history/");
389 int tab_count = browser()->tab_count();
390 // alt-Enter opens a new tab.
391 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_RETURN, false, false, true));
392 ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
393 }
394
395 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EnterToSearch) {
396 ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
397 ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
398 browser()->FocusLocationBar();
399
400 AutocompleteEditView* edit_view;
401 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
402 AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
403 ASSERT_TRUE(popup_model);
404
405 // Test Enter to search.
406 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
407 ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
408 ASSERT_TRUE(popup_model->IsOpen());
409
410 // Check if the default match result is Search Primary Provider.
411 ASSERT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
412 popup_model->result().default_match()->type);
413
414 // Open the default match.
415 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_RETURN, false, false, false));
416 GURL url = browser()->GetSelectedTabContents()->GetURL();
417 EXPECT_STREQ(kSearchTextURL, url.spec().c_str());
418 }
419
420 // See http://crbug.com/20934: Omnibox keyboard behavior wrong for
421 // "See recent pages in history"
422 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EnterToOpenHistoryPage) {
423 ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
424 ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
425 ASSERT_NO_FATAL_FAILURE(SetupHistory());
426
427 browser()->FocusLocationBar();
428
429 AutocompleteEditView* edit_view;
430 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
431 AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
432 ASSERT_TRUE(popup_model);
433
434 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
435 ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
436 ASSERT_TRUE(popup_model->IsOpen());
437 EXPECT_EQ(0U, popup_model->selected_line());
438
439 // Move to the history page item.
440 size_t size = popup_model->result().size();
441 while (true) {
442 if (popup_model->result().match_at(popup_model->selected_line()).type ==
443 AutocompleteMatch::OPEN_HISTORY_PAGE)
444 break;
445 size_t old_selected_line = popup_model->selected_line();
446 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_DOWN, false, false, false));
447 ASSERT_EQ(old_selected_line + 1, popup_model->selected_line());
448 if (popup_model->selected_line() == size - 1)
449 break;
450 }
451
452 // Make sure the history page item is selected.
453 ASSERT_EQ(AutocompleteMatch::OPEN_HISTORY_PAGE,
454 popup_model->result().match_at(popup_model->selected_line()).type);
455
456 // Open the history page item.
457 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_RETURN, false, false, false));
458 GURL url = browser()->GetSelectedTabContents()->GetURL();
459 EXPECT_STREQ(kHistoryPageURL, url.spec().c_str());
460 }
461
462 IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, EscapeToDefaultMatch) {
463 ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
464 ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
465 ASSERT_NO_FATAL_FAILURE(SetupHistory());
466 browser()->FocusLocationBar();
467
468 AutocompleteEditView* edit_view;
469 ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view));
470 AutocompletePopupModel* popup_model = edit_view->model()->popup_model();
471 ASSERT_TRUE(popup_model);
472
473 // Input something to trigger inline autocomplete.
474 ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
475 ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
476 ASSERT_TRUE(popup_model->IsOpen());
477
478 std::wstring old_text = edit_view->GetText();
479
480 // Make sure inline autocomplete is triggerred.
481 EXPECT_GT(old_text.length(), arraysize(kSearchText) - 1);
482
483 size_t old_selected_line = popup_model->selected_line();
484 EXPECT_EQ(0U, old_selected_line);
485
486 // Move to another line with different text.
487 size_t size = popup_model->result().size();
488 while (popup_model->selected_line() < size - 1) {
489 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_DOWN, false, false, false));
490 ASSERT_NE(old_selected_line, popup_model->selected_line());
491 if (old_text != edit_view->GetText())
492 break;
493 }
494
495 EXPECT_NE(old_text, edit_view->GetText());
496
497 // Escape shall revert back to the default match item.
498 ASSERT_NO_FATAL_FAILURE(SendKey(base::VKEY_ESCAPE, false, false, false));
499 EXPECT_EQ(old_text, edit_view->GetText());
500 EXPECT_EQ(old_selected_line, popup_model->selected_line());
501 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698