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 <stdio.h>
6
7#include "base/command_line.h"
8#include "base/strings/string16.h"
9#include "base/strings/string_util.h"
10#include "base/strings/utf_string_conversions.h"
11#include "base/time/time.h"
12#include "chrome/app/chrome_command_ids.h"
13#include "chrome/browser/autocomplete/autocomplete_input.h"
14#include "chrome/browser/autocomplete/autocomplete_match.h"
15#include "chrome/browser/autocomplete/history_quick_provider.h"
16#include "chrome/browser/bookmarks/bookmark_model_factory.h"
17#include "chrome/browser/chrome_notification_types.h"
18#include "chrome/browser/history/history_service.h"
19#include "chrome/browser/history/history_service_factory.h"
20#include "chrome/browser/profiles/profile.h"
21#include "chrome/browser/search_engines/template_url.h"
22#include "chrome/browser/search_engines/template_url_service.h"
23#include "chrome/browser/search_engines/template_url_service_factory.h"
24#include "chrome/browser/ui/browser.h"
25#include "chrome/browser/ui/browser_commands.h"
26#include "chrome/browser/ui/browser_window.h"
27#include "chrome/browser/ui/omnibox/location_bar.h"
28#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
29#include "chrome/browser/ui/omnibox/omnibox_view.h"
30#include "chrome/browser/ui/tabs/tab_strip_model.h"
31#include "chrome/browser/ui/toolbar/test_toolbar_model.h"
32#include "chrome/common/chrome_paths.h"
33#include "chrome/common/chrome_switches.h"
34#include "chrome/common/url_constants.h"
35#include "chrome/test/base/in_process_browser_test.h"
36#include "chrome/test/base/interactive_test_utils.h"
37#include "chrome/test/base/ui_test_utils.h"
38#include "components/bookmarks/browser/bookmark_model.h"
39#include "components/bookmarks/browser/bookmark_utils.h"
40#include "components/bookmarks/test/bookmark_test_helpers.h"
41#include "content/public/browser/notification_service.h"
42#include "content/public/browser/web_contents.h"
43#include "net/dns/mock_host_resolver.h"
44#include "ui/base/clipboard/clipboard.h"
45#include "ui/base/clipboard/scoped_clipboard_writer.h"
46#include "ui/events/event_constants.h"
47#include "ui/events/keycodes/keyboard_codes.h"
48#include "ui/gfx/point.h"
49
50using base::ASCIIToUTF16;
51using base::UTF16ToUTF8;
52using base::Time;
53using base::TimeDelta;
54
55namespace {
56
57const char kSearchKeyword[] = "foo";
58const char kSearchKeyword2[] = "footest.com";
59const wchar_t kSearchKeywordKeys[] = { ui::VKEY_F, ui::VKEY_O, ui::VKEY_O, 0 };
60const char kSearchURL[] = "http://www.foo.com/search?q={searchTerms}";
61const char kSearchShortName[] = "foo";
62const char kSearchText[] = "abc";
63const wchar_t kSearchTextKeys[] = { ui::VKEY_A, ui::VKEY_B, ui::VKEY_C, 0 };
64const char kSearchTextURL[] = "http://www.foo.com/search?q=abc";
65
66const char kInlineAutocompleteText[] = "def";
67const wchar_t kInlineAutocompleteTextKeys[] = {
68  ui::VKEY_D, ui::VKEY_E, ui::VKEY_F, 0
69};
70
71// Hostnames that shall be blocked by host resolver.
72const char *kBlockedHostnames[] = {
73  "foo",
74  "*.foo.com",
75  "bar",
76  "*.bar.com",
77  "abc",
78  "*.abc.com",
79  "def",
80  "*.def.com",
81  "*.site.com",
82  "history",
83  "z"
84};
85
86const struct TestHistoryEntry {
87  const char* url;
88  const char* title;
89  int visit_count;
90  int typed_count;
91  bool starred;
92} kHistoryEntries[] = {
93  {"http://www.bar.com/1", "Page 1", 10, 10, false },
94  {"http://www.bar.com/2", "Page 2", 9, 9, false },
95  {"http://www.bar.com/3", "Page 3", 8, 8, false },
96  {"http://www.bar.com/4", "Page 4", 7, 7, false },
97  {"http://www.bar.com/5", "Page 5", 6, 6, false },
98  {"http://www.bar.com/6", "Page 6", 5, 5, false },
99  {"http://www.bar.com/7", "Page 7", 4, 4, false },
100  {"http://www.bar.com/8", "Page 8", 3, 3, false },
101  {"http://www.bar.com/9", "Page 9", 2, 2, false },
102  {"http://www.site.com/path/1", "Site 1", 4, 4, false },
103  {"http://www.site.com/path/2", "Site 2", 3, 3, false },
104  {"http://www.site.com/path/3", "Site 3", 2, 2, false },
105
106  // To trigger inline autocomplete.
107  {"http://www.def.com", "Page def", 10000, 10000, true },
108
109  // Used in particular for the desired TLD test.  This makes it test
110  // the interesting case when there's an intranet host with the same
111  // name as the .com.
112  {"http://bar/", "Bar", 1, 0, false },
113};
114
115// Stores the given text to clipboard.
116void SetClipboardText(const base::string16& text) {
117  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
118  ui::ScopedClipboardWriter writer(clipboard, ui::CLIPBOARD_TYPE_COPY_PASTE);
119  writer.WriteText(text);
120}
121
122#if defined(OS_MACOSX)
123const int kCtrlOrCmdMask = ui::EF_COMMAND_DOWN;
124#else
125const int kCtrlOrCmdMask = ui::EF_CONTROL_DOWN;
126#endif
127
128}  // namespace
129
130class OmniboxViewTest : public InProcessBrowserTest,
131                        public content::NotificationObserver {
132 protected:
133  virtual void SetUpOnMainThread() OVERRIDE {
134    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
135    ASSERT_NO_FATAL_FAILURE(SetupComponents());
136    chrome::FocusLocationBar(browser());
137    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
138  }
139
140  static void GetOmniboxViewForBrowser(
141      const Browser* browser,
142      OmniboxView** omnibox_view) {
143    BrowserWindow* window = browser->window();
144    ASSERT_TRUE(window);
145    LocationBar* location_bar = window->GetLocationBar();
146    ASSERT_TRUE(location_bar);
147    *omnibox_view = location_bar->GetOmniboxView();
148    ASSERT_TRUE(*omnibox_view);
149  }
150
151  void GetOmniboxView(OmniboxView** omnibox_view) {
152    GetOmniboxViewForBrowser(browser(), omnibox_view);
153  }
154
155  static void SendKeyForBrowser(const Browser* browser,
156                                ui::KeyboardCode key,
157                                int modifiers) {
158    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
159        browser, key,
160        (modifiers & ui::EF_CONTROL_DOWN) != 0,
161        (modifiers & ui::EF_SHIFT_DOWN) != 0,
162        (modifiers & ui::EF_ALT_DOWN) != 0,
163        (modifiers & ui::EF_COMMAND_DOWN) != 0));
164  }
165
166  void SendKey(ui::KeyboardCode key, int modifiers) {
167    SendKeyForBrowser(browser(), key, modifiers);
168  }
169
170  void SendKeySequence(const wchar_t* keys) {
171    for (; *keys; ++keys)
172      ASSERT_NO_FATAL_FAILURE(SendKey(static_cast<ui::KeyboardCode>(*keys), 0));
173  }
174
175  bool SendKeyAndWait(const Browser* browser,
176                      ui::KeyboardCode key,
177                      int modifiers,
178                      int type,
179                      const content::NotificationSource& source)
180                          WARN_UNUSED_RESULT {
181    return ui_test_utils::SendKeyPressAndWait(
182        browser, key,
183        (modifiers & ui::EF_CONTROL_DOWN) != 0,
184        (modifiers & ui::EF_SHIFT_DOWN) != 0,
185        (modifiers & ui::EF_ALT_DOWN) != 0,
186        (modifiers & ui::EF_COMMAND_DOWN) != 0,
187        type, source);
188  }
189
190  void WaitForTabOpenOrCloseForBrowser(const Browser* browser,
191                                       int expected_tab_count) {
192    int tab_count = browser->tab_strip_model()->count();
193    if (tab_count == expected_tab_count)
194      return;
195
196    content::NotificationRegistrar registrar;
197    registrar.Add(this,
198        (tab_count < expected_tab_count) ?
199            static_cast<int>(chrome::NOTIFICATION_TAB_PARENTED) :
200            static_cast<int>(content::NOTIFICATION_WEB_CONTENTS_DESTROYED),
201        content::NotificationService::AllSources());
202
203    while (!HasFailure() &&
204           browser->tab_strip_model()->count() != expected_tab_count) {
205      content::RunMessageLoop();
206    }
207
208    ASSERT_EQ(expected_tab_count, browser->tab_strip_model()->count());
209  }
210
211  void WaitForTabOpenOrClose(int expected_tab_count) {
212    WaitForTabOpenOrCloseForBrowser(browser(), expected_tab_count);
213  }
214
215  void WaitForAutocompleteControllerDone() {
216    OmniboxView* omnibox_view = NULL;
217    ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
218
219    AutocompleteController* controller =
220        omnibox_view->model()->autocomplete_controller();
221    ASSERT_TRUE(controller);
222
223    if (controller->done())
224      return;
225
226    content::NotificationRegistrar registrar;
227    registrar.Add(this,
228                  chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
229                  content::Source<AutocompleteController>(controller));
230
231    while (!HasFailure() && !controller->done())
232      content::RunMessageLoop();
233
234    ASSERT_TRUE(controller->done());
235  }
236
237  void SetupSearchEngine() {
238    Profile* profile = browser()->profile();
239    TemplateURLService* model =
240        TemplateURLServiceFactory::GetForProfile(profile);
241    ASSERT_TRUE(model);
242
243    ui_test_utils::WaitForTemplateURLServiceToLoad(model);
244
245    ASSERT_TRUE(model->loaded());
246
247    TemplateURLData data;
248    data.short_name = ASCIIToUTF16(kSearchShortName);
249    data.SetKeyword(ASCIIToUTF16(kSearchKeyword));
250    data.SetURL(kSearchURL);
251    TemplateURL* template_url = new TemplateURL(data);
252    model->Add(template_url);
253    model->SetUserSelectedDefaultSearchProvider(template_url);
254
255    data.SetKeyword(ASCIIToUTF16(kSearchKeyword2));
256    model->Add(new TemplateURL(data));
257
258    // Remove built-in template urls, like google.com, bing.com etc., as they
259    // may appear as autocomplete suggests and interfere with our tests.
260    TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs();
261    for (TemplateURLService::TemplateURLVector::const_iterator i = urls.begin();
262         i != urls.end();
263         ++i) {
264      if ((*i)->prepopulate_id() != 0)
265        model->Remove(*i);
266    }
267  }
268
269  void AddHistoryEntry(const TestHistoryEntry& entry, const Time& time) {
270    Profile* profile = browser()->profile();
271    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
272        profile, Profile::EXPLICIT_ACCESS);
273    ASSERT_TRUE(history_service);
274
275    if (!history_service->BackendLoaded()) {
276      content::NotificationRegistrar registrar;
277      registrar.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
278                    content::Source<Profile>(profile));
279      content::RunMessageLoop();
280    }
281
282    BookmarkModel* bookmark_model =
283        BookmarkModelFactory::GetForProfile(profile);
284    ASSERT_TRUE(bookmark_model);
285    test::WaitForBookmarkModelToLoad(bookmark_model);
286
287    GURL url(entry.url);
288    // Add everything in order of time. We don't want to have a time that
289    // is "right now" or it will nondeterministically appear in the results.
290    history_service->AddPageWithDetails(url, base::UTF8ToUTF16(entry.title),
291                                        entry.visit_count,
292                                        entry.typed_count, time, false,
293                                        history::SOURCE_BROWSED);
294    if (entry.starred)
295      bookmark_utils::AddIfNotBookmarked(bookmark_model, url, base::string16());
296    // Wait at least for the AddPageWithDetails() call to finish.
297    {
298      content::NotificationRegistrar registrar;
299      registrar.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
300                    content::Source<Profile>(profile));
301      content::RunMessageLoop();
302      // We don't want to return until all observers have processed this
303      // notification, because some (e.g. the in-memory history database) may do
304      // something important.  Since we don't know where in the observer list we
305      // stand, just spin the message loop once more to allow the current
306      // callstack to complete.
307      content::RunAllPendingInMessageLoop();
308    }
309  }
310
311  void SetupHistory() {
312    // Add enough history pages containing |kSearchText| to trigger
313    // open history page url in autocomplete result.
314    for (size_t i = 0; i < arraysize(kHistoryEntries); i++) {
315      // Add everything in order of time. We don't want to have a time that
316      // is "right now" or it will nondeterministically appear in the results.
317      Time t = Time::Now() - TimeDelta::FromHours(i + 1);
318      ASSERT_NO_FATAL_FAILURE(AddHistoryEntry(kHistoryEntries[i], t));
319    }
320  }
321
322  void SetupHostResolver() {
323    for (size_t i = 0; i < arraysize(kBlockedHostnames); ++i)
324      host_resolver()->AddSimulatedFailure(kBlockedHostnames[i]);
325  }
326
327  void SetupComponents() {
328    ASSERT_NO_FATAL_FAILURE(SetupHostResolver());
329    ASSERT_NO_FATAL_FAILURE(SetupSearchEngine());
330    ASSERT_NO_FATAL_FAILURE(SetupHistory());
331  }
332
333  virtual void Observe(int type,
334                       const content::NotificationSource& source,
335                       const content::NotificationDetails& details) OVERRIDE {
336    switch (type) {
337      case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
338      case chrome::NOTIFICATION_TAB_PARENTED:
339      case chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY:
340      case chrome::NOTIFICATION_HISTORY_LOADED:
341      case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
342        break;
343      default:
344        FAIL() << "Unexpected notification type";
345    }
346    base::MessageLoop::current()->Quit();
347  }
348};
349
350// Test if ctrl-* accelerators are workable in omnibox.
351// See http://crbug.com/19193: omnibox blocks ctrl-* commands
352//
353// Flaky on interactive tests (dbg), http://crbug.com/69433
354IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_BrowserAccelerators) {
355  OmniboxView* omnibox_view = NULL;
356  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
357
358  int tab_count = browser()->tab_strip_model()->count();
359
360  // Create a new Tab.
361  chrome::NewTab(browser());
362  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
363
364  // Select the first Tab.
365  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_1, kCtrlOrCmdMask));
366  ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
367
368  chrome::FocusLocationBar(browser());
369
370  // Select the second Tab.
371  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, kCtrlOrCmdMask));
372  ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
373
374  chrome::FocusLocationBar(browser());
375
376  // Try ctrl-w to close a Tab.
377  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_W, kCtrlOrCmdMask));
378  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count));
379
380  // Try ctrl-l to focus location bar.
381  omnibox_view->SetUserText(ASCIIToUTF16("Hello world"));
382  EXPECT_FALSE(omnibox_view->IsSelectAll());
383  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_L, kCtrlOrCmdMask));
384  EXPECT_TRUE(omnibox_view->IsSelectAll());
385
386  // Try editing the location bar text.
387  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RIGHT, 0));
388  EXPECT_FALSE(omnibox_view->IsSelectAll());
389  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_S, 0));
390  EXPECT_EQ(ASCIIToUTF16("Hello worlds"), omnibox_view->GetText());
391
392  // Try ctrl-x to cut text.
393#if defined(OS_MACOSX)
394  // Mac uses alt-left/right to select a word.
395  ASSERT_NO_FATAL_FAILURE(
396      SendKey(ui::VKEY_LEFT, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN));
397#else
398  ASSERT_NO_FATAL_FAILURE(
399      SendKey(ui::VKEY_LEFT, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN));
400#endif
401  EXPECT_FALSE(omnibox_view->IsSelectAll());
402  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_X, kCtrlOrCmdMask));
403  EXPECT_EQ(ASCIIToUTF16("Hello "), omnibox_view->GetText());
404
405#if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
406  // Try alt-f4 to close the browser.
407  ASSERT_TRUE(SendKeyAndWait(
408      browser(), ui::VKEY_F4, ui::EF_ALT_DOWN,
409      chrome::NOTIFICATION_BROWSER_CLOSED,
410      content::Source<Browser>(browser())));
411#endif
412}
413
414// Flakily fails and times out on Win only.  http://crbug.com/69941
415#if defined(OS_WIN)
416#define MAYBE_PopupAccelerators DISABLED_PopupAccelerators
417#else
418#define MAYBE_PopupAccelerators PopupAccelerators
419#endif
420
421IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_PopupAccelerators) {
422  // Create a popup.
423  Browser* popup = CreateBrowserForPopup(browser()->profile());
424  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(popup));
425  OmniboxView* omnibox_view = NULL;
426  ASSERT_NO_FATAL_FAILURE(
427      GetOmniboxViewForBrowser(popup, &omnibox_view));
428  chrome::FocusLocationBar(popup);
429  EXPECT_TRUE(omnibox_view->IsSelectAll());
430
431#if !defined(OS_MACOSX)
432  // Try ctrl-w to close the popup.
433  // This piece of code doesn't work on Mac, because the Browser object won't
434  // be destroyed before finishing the current message loop iteration, thus
435  // No BROWSER_CLOSED notification will be sent.
436  ASSERT_TRUE(SendKeyAndWait(
437      popup, ui::VKEY_W, ui::EF_CONTROL_DOWN,
438      chrome::NOTIFICATION_BROWSER_CLOSED, content::Source<Browser>(popup)));
439
440  // Create another popup.
441  popup = CreateBrowserForPopup(browser()->profile());
442  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(popup));
443  ASSERT_NO_FATAL_FAILURE(
444      GetOmniboxViewForBrowser(popup, &omnibox_view));
445#endif
446
447  // Set the edit text to "Hello world".
448  omnibox_view->SetUserText(ASCIIToUTF16("Hello world"));
449  chrome::FocusLocationBar(popup);
450  EXPECT_TRUE(omnibox_view->IsSelectAll());
451
452  // Try editing the location bar text -- should be disallowed.
453  ASSERT_NO_FATAL_FAILURE(SendKeyForBrowser(popup, ui::VKEY_S, 0));
454  EXPECT_EQ(ASCIIToUTF16("Hello world"), omnibox_view->GetText());
455  EXPECT_TRUE(omnibox_view->IsSelectAll());
456
457  ASSERT_NO_FATAL_FAILURE(
458      SendKeyForBrowser(popup, ui::VKEY_X, kCtrlOrCmdMask));
459  EXPECT_EQ(ASCIIToUTF16("Hello world"), omnibox_view->GetText());
460  EXPECT_TRUE(omnibox_view->IsSelectAll());
461
462#if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
463  // Try alt-f4 to close the popup.
464  ASSERT_TRUE(SendKeyAndWait(
465      popup, ui::VKEY_F4, ui::EF_ALT_DOWN,
466      chrome::NOTIFICATION_BROWSER_CLOSED, content::Source<Browser>(popup)));
467#endif
468}
469
470// http://crbug.com/133341
471#if defined(OS_LINUX)
472#define MAYBE_BackspaceInKeywordMode DISABLED_BackspaceInKeywordMode
473#else
474#define MAYBE_BackspaceInKeywordMode BackspaceInKeywordMode
475#endif
476
477IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_BackspaceInKeywordMode) {
478  OmniboxView* omnibox_view = NULL;
479  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
480
481  // Trigger keyword hint mode.
482  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
483  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
484  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
485
486  // Trigger keyword mode.
487  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
488  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
489  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
490
491  // Backspace without search text should bring back keyword hint mode.
492  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
493  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
494  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
495
496  // Trigger keyword mode again.
497  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
498  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
499  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
500
501  // Input something as search text.
502  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
503
504  // Should stay in keyword mode while deleting search text by pressing
505  // backspace.
506  for (size_t i = 0; i < arraysize(kSearchText) - 1; ++i) {
507    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
508    ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
509    ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
510  }
511
512  // Input something as search text.
513  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
514
515  // Move cursor to the beginning of the search text.
516#if defined(OS_MACOSX)
517  // Home doesn't work on Mac trybot.
518  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, ui::EF_CONTROL_DOWN));
519#else
520  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_HOME, 0));
521#endif
522  // Backspace at the beginning of the search text shall turn off
523  // the keyword mode.
524  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
525  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
526  ASSERT_EQ(base::string16(), omnibox_view->model()->keyword());
527  ASSERT_EQ(std::string(kSearchKeyword) + kSearchText,
528            UTF16ToUTF8(omnibox_view->GetText()));
529}
530
531// http://crbug.com/158913
532#if defined(OS_CHROMEOS) || defined(OS_WIN)
533#define MAYBE_Escape DISABLED_Escape
534#else
535#define MAYBE_Escape Escape
536#endif
537IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_Escape) {
538  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIHistoryURL));
539  chrome::FocusLocationBar(browser());
540
541  OmniboxView* omnibox_view = NULL;
542  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
543
544  base::string16 old_text = omnibox_view->GetText();
545  EXPECT_FALSE(old_text.empty());
546  EXPECT_TRUE(omnibox_view->IsSelectAll());
547
548  // Delete all text in omnibox.
549  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
550  EXPECT_TRUE(omnibox_view->GetText().empty());
551
552  // Escape shall revert the text in omnibox.
553  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, 0));
554  EXPECT_EQ(old_text, omnibox_view->GetText());
555  EXPECT_TRUE(omnibox_view->IsSelectAll());
556}
557#undef MAYBE_ESCAPE
558
559IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DesiredTLD) {
560  OmniboxView* omnibox_view = NULL;
561  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
562  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
563  ASSERT_TRUE(popup_model);
564
565  // Test ctrl-Enter.
566  const wchar_t kKeys[] = { ui::VKEY_B, ui::VKEY_A, ui::VKEY_R, 0 };
567  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kKeys));
568  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
569  ASSERT_TRUE(popup_model->IsOpen());
570  // ctrl-Enter triggers desired_tld feature, thus www.bar.com shall be
571  // opened.
572  ASSERT_TRUE(SendKeyAndWait(browser(), ui::VKEY_RETURN, ui::EF_CONTROL_DOWN,
573      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
574      content::Source<content::NavigationController>(
575          &browser()->tab_strip_model()->GetActiveWebContents()->
576              GetController())));
577
578  GURL url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
579  EXPECT_EQ("www.bar.com", url.host());
580  EXPECT_EQ("/", url.path());
581}
582
583IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DesiredTLDWithTemporaryText) {
584  OmniboxView* omnibox_view = NULL;
585  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
586  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
587  ASSERT_TRUE(popup_model);
588
589  Profile* profile = browser()->profile();
590  TemplateURLService* template_url_service =
591      TemplateURLServiceFactory::GetForProfile(profile);
592
593  // Add a non-substituting keyword. This ensures the popup will have a
594  // non-verbatim entry with "ab" as a prefix. This way, by arrowing down, we
595  // can set "abc" as temporary text in the omnibox.
596  TemplateURLData data;
597  data.short_name = ASCIIToUTF16("abc");
598  data.SetKeyword(ASCIIToUTF16(kSearchText));
599  data.SetURL("http://abc.com/");
600  template_url_service->Add(new TemplateURL(data));
601
602  // Send "ab", so that an "abc" entry appears in the popup.
603  const wchar_t kSearchTextPrefixKeys[] = { ui::VKEY_A, ui::VKEY_B, 0 };
604  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextPrefixKeys));
605  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
606  ASSERT_TRUE(popup_model->IsOpen());
607
608  // Arrow down to the "abc" entry in the popup.
609  size_t size = popup_model->result().size();
610  while (popup_model->selected_line() < size - 1) {
611    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DOWN, 0));
612    if (omnibox_view->GetText() == ASCIIToUTF16("abc"))
613      break;
614  }
615  ASSERT_EQ(ASCIIToUTF16("abc"), omnibox_view->GetText());
616
617  // Hitting ctrl-enter should navigate based on the current text rather than
618  // the original input, i.e. to www.abc.com instead of www.ab.com.
619  ASSERT_TRUE(SendKeyAndWait(
620      browser(), ui::VKEY_RETURN, ui::EF_CONTROL_DOWN,
621      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
622      content::Source<content::NavigationController>(
623          &browser()->tab_strip_model()->GetActiveWebContents()->
624              GetController())));
625
626  GURL url(browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
627  EXPECT_EQ("www.abc.com", url.host());
628  EXPECT_EQ("/", url.path());
629}
630
631IN_PROC_BROWSER_TEST_F(OmniboxViewTest, AltEnter) {
632  OmniboxView* omnibox_view = NULL;
633  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
634
635  omnibox_view->SetUserText(ASCIIToUTF16(chrome::kChromeUIHistoryURL));
636  int tab_count = browser()->tab_strip_model()->count();
637  // alt-Enter opens a new tab.
638  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_RETURN, ui::EF_ALT_DOWN));
639  ASSERT_NO_FATAL_FAILURE(WaitForTabOpenOrClose(tab_count + 1));
640}
641
642// http://crbug.com/133354, http://crbug.com/146953
643IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_EnterToSearch) {
644  OmniboxView* omnibox_view = NULL;
645  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
646  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
647  ASSERT_TRUE(popup_model);
648
649  // Test Enter to search.
650  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
651  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
652  ASSERT_TRUE(popup_model->IsOpen());
653
654  // Check if the default match result is Search Primary Provider.
655  ASSERT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
656            popup_model->result().default_match()->type);
657
658  // Open the default match.
659  ASSERT_TRUE(SendKeyAndWait(browser(), ui::VKEY_RETURN, 0,
660      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
661      content::Source<content::NavigationController>(
662          &browser()->tab_strip_model()->GetActiveWebContents()->
663              GetController())));
664  GURL url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
665  EXPECT_EQ(kSearchTextURL, url.spec());
666
667  // Test that entering a single character then Enter performs a search.
668  const wchar_t kSearchSingleCharKeys[] = { ui::VKEY_Z, 0 };
669  chrome::FocusLocationBar(browser());
670  EXPECT_TRUE(omnibox_view->IsSelectAll());
671  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchSingleCharKeys));
672  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
673  ASSERT_TRUE(popup_model->IsOpen());
674  EXPECT_EQ("z", UTF16ToUTF8(omnibox_view->GetText()));
675
676  // Check if the default match result is Search Primary Provider.
677  ASSERT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
678            popup_model->result().default_match()->type);
679
680  // Open the default match.
681  ASSERT_TRUE(SendKeyAndWait(browser(), ui::VKEY_RETURN, 0,
682      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
683      content::Source<content::NavigationController>(
684          &browser()->tab_strip_model()->GetActiveWebContents()->
685              GetController())));
686  url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
687  EXPECT_EQ("http://www.foo.com/search?q=z", url.spec());
688}
689
690// http://crbug.com/131179
691#if defined(OS_LINUX)
692#define MAYBE_EscapeToDefaultMatch DISABLED_EscapeToDefaultMatch
693#else
694#define MAYBE_EscapeToDefaultMatch EscapeToDefaultMatch
695#endif
696IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_EscapeToDefaultMatch) {
697  OmniboxView* omnibox_view = NULL;
698  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
699  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
700  ASSERT_TRUE(popup_model);
701
702  // Input something to trigger inline autocomplete.
703  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kInlineAutocompleteTextKeys));
704  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
705  ASSERT_TRUE(popup_model->IsOpen());
706
707  base::string16 old_text = omnibox_view->GetText();
708
709  // Make sure inline autocomplete is triggerred.
710  EXPECT_GT(old_text.length(), arraysize(kInlineAutocompleteText) - 1);
711
712  size_t old_selected_line = popup_model->selected_line();
713  EXPECT_EQ(0U, old_selected_line);
714
715  // Move to another line with different text.
716  size_t size = popup_model->result().size();
717  while (popup_model->selected_line() < size - 1) {
718    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DOWN, 0));
719    ASSERT_NE(old_selected_line, popup_model->selected_line());
720    if (old_text != omnibox_view->GetText())
721      break;
722  }
723
724  EXPECT_NE(old_text, omnibox_view->GetText());
725
726  // Escape shall revert back to the default match item.
727  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, 0));
728  EXPECT_EQ(old_text, omnibox_view->GetText());
729  EXPECT_EQ(old_selected_line, popup_model->selected_line());
730}
731
732// http://crbug.com/131179, http://crbug.com/146619
733#if defined(OS_LINUX) || defined(OS_WIN)
734#define MAYBE_BasicTextOperations DISABLED_BasicTextOperations
735#else
736#define MAYBE_BasicTextOperations BasicTextOperations
737#endif
738IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_BasicTextOperations) {
739  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
740  chrome::FocusLocationBar(browser());
741
742  OmniboxView* omnibox_view = NULL;
743  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
744
745  base::string16 old_text = omnibox_view->GetText();
746  EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), old_text);
747  EXPECT_TRUE(omnibox_view->IsSelectAll());
748
749  size_t start, end;
750  omnibox_view->GetSelectionBounds(&start, &end);
751  EXPECT_EQ(0U, start);
752  EXPECT_EQ(old_text.size(), end);
753
754  // Move the cursor to the end.
755#if defined(OS_MACOSX)
756  // End doesn't work on Mac trybot.
757  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_E, ui::EF_CONTROL_DOWN));
758#else
759  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, 0));
760#endif
761  EXPECT_FALSE(omnibox_view->IsSelectAll());
762
763  // Make sure the cursor is placed correctly.
764  omnibox_view->GetSelectionBounds(&start, &end);
765  EXPECT_EQ(old_text.size(), start);
766  EXPECT_EQ(old_text.size(), end);
767
768  // Insert one character at the end. Make sure we won't insert
769  // anything after the special ZWS mark used in gtk implementation.
770  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, 0));
771  EXPECT_EQ(old_text + base::char16('a'), omnibox_view->GetText());
772
773  // Delete one character from the end. Make sure we won't delete the special
774  // ZWS mark used in gtk implementation.
775  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
776  EXPECT_EQ(old_text, omnibox_view->GetText());
777
778  omnibox_view->SelectAll(true);
779  EXPECT_TRUE(omnibox_view->IsSelectAll());
780  omnibox_view->GetSelectionBounds(&start, &end);
781  EXPECT_EQ(0U, start);
782  EXPECT_EQ(old_text.size(), end);
783
784  // Delete the content
785  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DELETE, 0));
786  EXPECT_TRUE(omnibox_view->IsSelectAll());
787  omnibox_view->GetSelectionBounds(&start, &end);
788  EXPECT_EQ(0U, start);
789  EXPECT_EQ(0U, end);
790  EXPECT_TRUE(omnibox_view->GetText().empty());
791
792  // Check if RevertAll() can set text and cursor correctly.
793  omnibox_view->RevertAll();
794  EXPECT_FALSE(omnibox_view->IsSelectAll());
795  EXPECT_EQ(old_text, omnibox_view->GetText());
796  omnibox_view->GetSelectionBounds(&start, &end);
797  EXPECT_EQ(old_text.size(), start);
798  EXPECT_EQ(old_text.size(), end);
799}
800
801// http://crbug.com/131179
802#if defined(OS_LINUX)
803#define MAYBE_AcceptKeywordBySpace DISABLED_AcceptKeywordBySpace
804#else
805#define MAYBE_AcceptKeywordBySpace AcceptKeywordBySpace
806#endif
807
808IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_AcceptKeywordBySpace) {
809  OmniboxView* omnibox_view = NULL;
810  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
811
812  base::string16 search_keyword(ASCIIToUTF16(kSearchKeyword));
813
814  // Trigger keyword hint mode.
815  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
816  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
817  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
818  ASSERT_EQ(search_keyword, omnibox_view->GetText());
819
820  // Trigger keyword mode by space.
821  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
822  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
823  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
824  ASSERT_TRUE(omnibox_view->GetText().empty());
825
826  // Revert to keyword hint mode.
827  omnibox_view->model()->ClearKeyword(base::string16());
828  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
829  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
830  ASSERT_EQ(search_keyword, omnibox_view->GetText());
831
832  // Keyword should also be accepted by typing an ideographic space.
833  omnibox_view->OnBeforePossibleChange();
834  omnibox_view->SetWindowTextAndCaretPos(search_keyword +
835      base::WideToUTF16(L"\x3000"), search_keyword.length() + 1, false, false);
836  omnibox_view->OnAfterPossibleChange();
837  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
838  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
839  ASSERT_TRUE(omnibox_view->GetText().empty());
840
841  // Revert to keyword hint mode.
842  omnibox_view->model()->ClearKeyword(base::string16());
843  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
844  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
845  ASSERT_EQ(search_keyword, omnibox_view->GetText());
846
847  // Keyword shouldn't be accepted by pressing space with a trailing
848  // whitespace.
849  omnibox_view->SetWindowTextAndCaretPos(search_keyword + base::char16(' '),
850      search_keyword.length() + 1, false, false);
851  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
852  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
853  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
854  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
855
856  // Keyword shouldn't be accepted by deleting the trailing space.
857  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
858  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
859  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
860  ASSERT_EQ(search_keyword + base::char16(' '), omnibox_view->GetText());
861
862  // Keyword shouldn't be accepted by pressing space before a trailing space.
863  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
864  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
865  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
866  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
867  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
868
869  // Keyword should be accepted by pressing space in the middle of context and
870  // just after the keyword.
871  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
872  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, 0));
873  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
874  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
875  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
876  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
877  ASSERT_EQ(ASCIIToUTF16("a "), omnibox_view->GetText());
878  size_t start, end;
879  omnibox_view->GetSelectionBounds(&start, &end);
880  EXPECT_EQ(0U, start);
881  EXPECT_EQ(0U, end);
882
883  // Keyword shouldn't be accepted by pasting "foo bar".
884  omnibox_view->SetUserText(base::string16());
885  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
886  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
887
888  omnibox_view->OnBeforePossibleChange();
889  omnibox_view->model()->OnPaste();
890  omnibox_view->SetWindowTextAndCaretPos(search_keyword +
891      ASCIIToUTF16(" bar"), search_keyword.length() + 4, false, false);
892  omnibox_view->OnAfterPossibleChange();
893  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
894  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
895  ASSERT_EQ(search_keyword + ASCIIToUTF16(" bar"), omnibox_view->GetText());
896
897  // Keyword shouldn't be accepted for case like: "foo b|ar" -> "foo b |ar".
898  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
899  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
900  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
901  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
902  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
903  ASSERT_EQ(search_keyword + ASCIIToUTF16(" b ar"), omnibox_view->GetText());
904
905  // Keyword could be accepted by pressing space with a selected range at the
906  // end of text.
907  omnibox_view->OnBeforePossibleChange();
908  omnibox_view->OnInlineAutocompleteTextMaybeChanged(
909      search_keyword + ASCIIToUTF16("  "), search_keyword.length());
910  omnibox_view->OnAfterPossibleChange();
911  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
912  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
913  ASSERT_EQ(search_keyword + ASCIIToUTF16("  "), omnibox_view->GetText());
914
915  omnibox_view->GetSelectionBounds(&start, &end);
916  ASSERT_NE(start, end);
917  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
918  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
919  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
920  ASSERT_EQ(base::string16(), omnibox_view->GetText());
921
922  // Space should accept keyword even when inline autocomplete is available.
923  omnibox_view->SetUserText(base::string16());
924  const TestHistoryEntry kHistoryFoobar = {
925    "http://www.foobar.com", "Page foobar", 100, 100, true
926  };
927
928  // Add a history entry to trigger inline autocomplete when typing "foo".
929  ASSERT_NO_FATAL_FAILURE(
930      AddHistoryEntry(kHistoryFoobar, Time::Now() - TimeDelta::FromHours(1)));
931
932  // Type "foo" to trigger inline autocomplete.
933  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
934  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
935  ASSERT_TRUE(omnibox_view->model()->popup_model()->IsOpen());
936  ASSERT_NE(search_keyword, omnibox_view->GetText());
937
938  // Keyword hint shouldn't be visible.
939  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
940  ASSERT_TRUE(omnibox_view->model()->keyword().empty());
941
942  // Trigger keyword mode by space.
943  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
944  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
945  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
946  ASSERT_TRUE(omnibox_view->GetText().empty());
947
948  // Space in the middle of a temporary text, which separates the text into
949  // keyword and replacement portions, should trigger keyword mode.
950  omnibox_view->SetUserText(base::string16());
951  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
952  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
953  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
954  ASSERT_TRUE(popup_model->IsOpen());
955  ASSERT_EQ(ASCIIToUTF16("foobar.com"), omnibox_view->GetText());
956  omnibox_view->model()->OnUpOrDownKeyPressed(1);
957  omnibox_view->model()->OnUpOrDownKeyPressed(-1);
958  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
959  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
960  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
961  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
962  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
963  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
964  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, 0));
965  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
966  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
967  ASSERT_EQ(search_keyword, omnibox_view->model()->keyword());
968  ASSERT_EQ(ASCIIToUTF16("bar.com"), omnibox_view->GetText());
969
970  // Space after temporary text that looks like a keyword, when the original
971  // input does not look like a keyword, should trigger keyword mode.
972  omnibox_view->SetUserText(base::string16());
973  const TestHistoryEntry kHistoryFoo = {
974    "http://footest.com", "Page footest", 1000, 1000, true
975  };
976
977  // Add a history entry to trigger HQP matching with text == keyword when
978  // typing "fo te".
979  ASSERT_NO_FATAL_FAILURE(
980      AddHistoryEntry(kHistoryFoo, Time::Now() - TimeDelta::FromMinutes(10)));
981
982  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_F, 0));
983  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_O, 0));
984  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
985  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_T, 0));
986  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_E, 0));
987  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
988  ASSERT_TRUE(popup_model->IsOpen());
989  base::string16 search_keyword2(ASCIIToUTF16(kSearchKeyword2));
990  while ((omnibox_view->GetText() != search_keyword2) &&
991         (popup_model->selected_line() < popup_model->result().size() - 1))
992    omnibox_view->model()->OnUpOrDownKeyPressed(1);
993  ASSERT_EQ(search_keyword2, omnibox_view->GetText());
994  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, 0));
995  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
996  ASSERT_EQ(search_keyword2, omnibox_view->model()->keyword());
997  ASSERT_TRUE(omnibox_view->GetText().empty());
998}
999
1000// http://crbug.com/131179
1001#if defined(OS_LINUX)
1002#define MAYBE_NonSubstitutingKeywordTest DISABLED_NonSubstitutingKeywordTest
1003#else
1004#define MAYBE_NonSubstitutingKeywordTest NonSubstitutingKeywordTest
1005#endif
1006
1007IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_NonSubstitutingKeywordTest) {
1008  OmniboxView* omnibox_view = NULL;
1009  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1010  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1011  ASSERT_TRUE(popup_model);
1012
1013  Profile* profile = browser()->profile();
1014  TemplateURLService* template_url_service =
1015      TemplateURLServiceFactory::GetForProfile(profile);
1016
1017  // Add a non-default substituting keyword.
1018  TemplateURLData data;
1019  data.short_name = ASCIIToUTF16("Search abc");
1020  data.SetKeyword(ASCIIToUTF16(kSearchText));
1021  data.SetURL("http://abc.com/{searchTerms}");
1022  TemplateURL* template_url = new TemplateURL(data);
1023  template_url_service->Add(template_url);
1024
1025  omnibox_view->SetUserText(base::string16());
1026
1027  // Non-default substituting keyword shouldn't be matched by default.
1028  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
1029  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1030  ASSERT_TRUE(popup_model->IsOpen());
1031
1032  // Check if the default match result is Search Primary Provider.
1033  ASSERT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
1034            popup_model->result().default_match()->type);
1035  ASSERT_EQ(kSearchTextURL,
1036            popup_model->result().default_match()->destination_url.spec());
1037
1038  omnibox_view->SetUserText(base::string16());
1039  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1040  ASSERT_FALSE(popup_model->IsOpen());
1041
1042  // Try a non-substituting keyword.
1043  template_url_service->Remove(template_url);
1044  data.short_name = ASCIIToUTF16("abc");
1045  data.SetURL("http://abc.com/");
1046  template_url_service->Add(new TemplateURL(data));
1047
1048  // We always allow exact matches for non-substituting keywords.
1049  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
1050  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1051  ASSERT_TRUE(popup_model->IsOpen());
1052  ASSERT_EQ(AutocompleteMatchType::HISTORY_KEYWORD,
1053            popup_model->result().default_match()->type);
1054  ASSERT_EQ("http://abc.com/",
1055            popup_model->result().default_match()->destination_url.spec());
1056}
1057
1058// http://crbug.com/131179 http://crbug.com/165765
1059#if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX)
1060#define MAYBE_DeleteItem DISABLED_DeleteItem
1061#else
1062#define MAYBE_DeleteItem DeleteItem
1063#endif
1064IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DeleteItem) {
1065  // Disable the search provider, to make sure the popup contains only history
1066  // items.
1067  TemplateURLService* model =
1068      TemplateURLServiceFactory::GetForProfile(browser()->profile());
1069  model->SetUserSelectedDefaultSearchProvider(NULL);
1070
1071  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
1072  chrome::FocusLocationBar(browser());
1073
1074  OmniboxView* omnibox_view = NULL;
1075  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1076
1077  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1078  ASSERT_TRUE(popup_model);
1079
1080  base::string16 old_text = omnibox_view->GetText();
1081
1082  // Input something that can match history items.
1083  omnibox_view->SetUserText(ASCIIToUTF16("site.com/p"));
1084  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1085  ASSERT_TRUE(popup_model->IsOpen());
1086
1087  // Delete the inline autocomplete part.
1088  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DELETE, 0));
1089  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1090  ASSERT_TRUE(popup_model->IsOpen());
1091  ASSERT_GE(popup_model->result().size(), 3U);
1092
1093  base::string16 user_text = omnibox_view->GetText();
1094  ASSERT_EQ(ASCIIToUTF16("site.com/p"), user_text);
1095  omnibox_view->SelectAll(true);
1096  ASSERT_TRUE(omnibox_view->IsSelectAll());
1097
1098  // Move down.
1099  size_t default_line = popup_model->selected_line();
1100  omnibox_view->model()->OnUpOrDownKeyPressed(1);
1101  ASSERT_EQ(default_line + 1, popup_model->selected_line());
1102  base::string16 selected_text =
1103      popup_model->result().match_at(default_line + 1).fill_into_edit;
1104  // Temporary text is shown.
1105  ASSERT_EQ(selected_text, omnibox_view->GetText());
1106  ASSERT_FALSE(omnibox_view->IsSelectAll());
1107
1108  // Delete the item.
1109  popup_model->TryDeletingCurrentItem();
1110  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1111  // The selected line shouldn't be changed, because we have more than two
1112  // items.
1113  ASSERT_EQ(default_line + 1, popup_model->selected_line());
1114  // Make sure the item is really deleted.
1115  ASSERT_NE(selected_text,
1116            popup_model->result().match_at(default_line + 1).fill_into_edit);
1117  selected_text =
1118      popup_model->result().match_at(default_line + 1).fill_into_edit;
1119  // New temporary text is shown.
1120  ASSERT_EQ(selected_text, omnibox_view->GetText());
1121
1122  // Revert to the default match.
1123  ASSERT_TRUE(omnibox_view->model()->OnEscapeKeyPressed());
1124  ASSERT_EQ(default_line, popup_model->selected_line());
1125  ASSERT_EQ(user_text, omnibox_view->GetText());
1126  ASSERT_TRUE(omnibox_view->IsSelectAll());
1127
1128  // Move down and up to select the default match as temporary text.
1129  omnibox_view->model()->OnUpOrDownKeyPressed(1);
1130  ASSERT_EQ(default_line + 1, popup_model->selected_line());
1131  omnibox_view->model()->OnUpOrDownKeyPressed(-1);
1132  ASSERT_EQ(default_line, popup_model->selected_line());
1133
1134  selected_text = popup_model->result().match_at(default_line).fill_into_edit;
1135  // New temporary text is shown.
1136  ASSERT_EQ(selected_text, omnibox_view->GetText());
1137  ASSERT_FALSE(omnibox_view->IsSelectAll());
1138
1139#if 0
1140  // TODO(mrossetti): http://crbug.com/82335
1141  // Delete the default item.
1142  popup_model->TryDeletingCurrentItem();
1143  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1144  // The selected line shouldn't be changed, but the default item should have
1145  // been changed.
1146  ASSERT_EQ(default_line, popup_model->selected_line());
1147  // Make sure the item is really deleted.
1148  EXPECT_NE(selected_text,
1149            popup_model->result().match_at(default_line).fill_into_edit);
1150  selected_text =
1151      popup_model->result().match_at(default_line).fill_into_edit;
1152  // New temporary text is shown.
1153  ASSERT_EQ(selected_text, omnibox_view->GetText());
1154#endif
1155
1156  // As the current selected item is the new default item, pressing Escape key
1157  // should revert all directly.
1158  ASSERT_TRUE(omnibox_view->model()->OnEscapeKeyPressed());
1159  ASSERT_EQ(old_text, omnibox_view->GetText());
1160  ASSERT_TRUE(omnibox_view->IsSelectAll());
1161}
1162
1163// http://crbug.com/133344
1164#if defined(OS_LINUX)
1165#define MAYBE_TabAcceptKeyword DISABLED_TabAcceptKeyword
1166#else
1167#define MAYBE_TabAcceptKeyword TabAcceptKeyword
1168#endif
1169
1170IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_TabAcceptKeyword) {
1171  OmniboxView* omnibox_view = NULL;
1172  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1173
1174  base::string16 text = ASCIIToUTF16(kSearchKeyword);
1175
1176  // Trigger keyword hint mode.
1177  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
1178  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
1179  ASSERT_EQ(text, omnibox_view->model()->keyword());
1180  ASSERT_EQ(text, omnibox_view->GetText());
1181
1182  // Trigger keyword mode by tab.
1183  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1184  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
1185  ASSERT_EQ(text, omnibox_view->model()->keyword());
1186  ASSERT_TRUE(omnibox_view->GetText().empty());
1187
1188  // Revert to keyword hint mode.
1189  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1190  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
1191  ASSERT_EQ(text, omnibox_view->model()->keyword());
1192  ASSERT_EQ(text, omnibox_view->GetText());
1193
1194  // The location bar should still have focus.
1195  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1196
1197  // Trigger keyword mode by tab.
1198  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1199  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
1200  ASSERT_EQ(text, omnibox_view->model()->keyword());
1201  ASSERT_TRUE(omnibox_view->GetText().empty());
1202
1203  // Revert to keyword hint mode with SHIFT+TAB.
1204#if defined(OS_MACOSX)
1205  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACKTAB, 0));
1206#else
1207  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN));
1208#endif
1209  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
1210  ASSERT_EQ(text, omnibox_view->model()->keyword());
1211  ASSERT_EQ(text, omnibox_view->GetText());
1212  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1213}
1214
1215#if !defined(OS_MACOSX)
1216// Mac intentionally does not support this behavior.
1217
1218// http://crbug.com/133360
1219#if defined(OS_LINUX)
1220#define MAYBE_TabTraverseResultsTest DISABLED_TabTraverseResultsTest
1221#else
1222#define MAYBE_TabTraverseResultsTest TabTraverseResultsTest
1223#endif
1224
1225IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_TabTraverseResultsTest) {
1226  OmniboxView* omnibox_view = NULL;
1227  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1228  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1229  ASSERT_TRUE(popup_model);
1230
1231  // Input something to trigger results.
1232  const wchar_t kKeys[] = { ui::VKEY_B, ui::VKEY_A, ui::VKEY_R, 0 };
1233  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kKeys));
1234  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1235  ASSERT_TRUE(popup_model->IsOpen());
1236
1237  size_t old_selected_line = popup_model->selected_line();
1238  EXPECT_EQ(0U, old_selected_line);
1239
1240  // Move down the results.
1241  for (size_t size = popup_model->result().size();
1242       popup_model->selected_line() < size - 1;
1243       old_selected_line = popup_model->selected_line()) {
1244    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1245    ASSERT_LT(old_selected_line, popup_model->selected_line());
1246  }
1247
1248  // Don't move past the end.
1249  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1250  ASSERT_EQ(old_selected_line, popup_model->selected_line());
1251  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1252
1253  // Move back up the results.
1254  for (; popup_model->selected_line() > 0U;
1255       old_selected_line = popup_model->selected_line()) {
1256    ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN));
1257    ASSERT_GT(old_selected_line, popup_model->selected_line());
1258  }
1259
1260  // Don't move past the beginning.
1261  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN));
1262  ASSERT_EQ(0U, popup_model->selected_line());
1263  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1264
1265  const TestHistoryEntry kHistoryFoo = {
1266    "http://foo/", "Page foo", 1, 1, false
1267  };
1268
1269  // Add a history entry so "foo" gets multiple matches.
1270  ASSERT_NO_FATAL_FAILURE(
1271      AddHistoryEntry(kHistoryFoo, Time::Now() - TimeDelta::FromHours(1)));
1272
1273  // Load results.
1274  ASSERT_NO_FATAL_FAILURE(omnibox_view->SelectAll(false));
1275  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
1276  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1277
1278  // Trigger keyword mode by tab.
1279  base::string16 text = ASCIIToUTF16(kSearchKeyword);
1280  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1281  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
1282  ASSERT_EQ(text, omnibox_view->model()->keyword());
1283  ASSERT_TRUE(omnibox_view->GetText().empty());
1284
1285  // The location bar should still have focus.
1286  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1287
1288  // Pressing tab again should move to the next result and clear keyword
1289  // mode.
1290  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1291  ASSERT_EQ(1U, omnibox_view->model()->popup_model()->selected_line());
1292  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
1293  ASSERT_NE(text, omnibox_view->model()->keyword());
1294
1295  // The location bar should still have focus.
1296  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1297
1298  // Moving back up should not show keyword mode.
1299  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN));
1300  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
1301  ASSERT_EQ(text, omnibox_view->model()->keyword());
1302
1303  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1304}
1305#endif
1306
1307
1308// http://crbug.com/133347
1309#if defined(OS_LINUX)
1310#define MAYBE_PersistKeywordModeOnTabSwitch DISABLED_PersistKeywordModeOnTabSwitch
1311#else
1312#define MAYBE_PersistKeywordModeOnTabSwitch PersistKeywordModeOnTabSwitch
1313#endif
1314
1315IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
1316                       MAYBE_PersistKeywordModeOnTabSwitch) {
1317  OmniboxView* omnibox_view = NULL;
1318  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1319
1320  // Trigger keyword hint mode.
1321  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
1322  ASSERT_TRUE(omnibox_view->model()->is_keyword_hint());
1323  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
1324
1325  // Trigger keyword mode.
1326  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0));
1327  ASSERT_FALSE(omnibox_view->model()->is_keyword_hint());
1328  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
1329
1330  // Input something as search text.
1331  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys));
1332
1333  // Create a new tab.
1334  chrome::NewTab(browser());
1335
1336  // Switch back to the first tab.
1337  browser()->tab_strip_model()->ActivateTabAt(0, true);
1338
1339  // Make sure we're still in keyword mode.
1340  ASSERT_EQ(kSearchKeyword, UTF16ToUTF8(omnibox_view->model()->keyword()));
1341}
1342
1343// http://crbug.com/133355
1344#if defined(OS_LINUX)
1345#define MAYBE_CtrlKeyPressedWithInlineAutocompleteTest DISABLED_CtrlKeyPressedWithInlineAutocompleteTest
1346#else
1347#define MAYBE_CtrlKeyPressedWithInlineAutocompleteTest CtrlKeyPressedWithInlineAutocompleteTest
1348#endif
1349
1350IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
1351                       MAYBE_CtrlKeyPressedWithInlineAutocompleteTest) {
1352  OmniboxView* omnibox_view = NULL;
1353  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1354  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1355  ASSERT_TRUE(popup_model);
1356
1357  // Input something to trigger inline autocomplete.
1358  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kInlineAutocompleteTextKeys));
1359  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1360  ASSERT_TRUE(popup_model->IsOpen());
1361
1362  base::string16 old_text = omnibox_view->GetText();
1363
1364  // Make sure inline autocomplete is triggerred.
1365  EXPECT_GT(old_text.length(), arraysize(kInlineAutocompleteText) - 1);
1366
1367  // Press ctrl key.
1368  omnibox_view->model()->OnControlKeyChanged(true);
1369
1370  // Inline autocomplete should still be there.
1371  EXPECT_EQ(old_text, omnibox_view->GetText());
1372}
1373
1374#if defined(TOOLKIT_VIEWS)
1375IN_PROC_BROWSER_TEST_F(OmniboxViewTest, UndoRedo) {
1376  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
1377  chrome::FocusLocationBar(browser());
1378
1379  OmniboxView* omnibox_view = NULL;
1380  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1381
1382  base::string16 old_text = omnibox_view->GetText();
1383  EXPECT_EQ(base::UTF8ToUTF16(url::kAboutBlankURL), old_text);
1384  EXPECT_TRUE(omnibox_view->IsSelectAll());
1385
1386  // Delete the text, then undo.
1387  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1388  EXPECT_TRUE(omnibox_view->GetText().empty());
1389  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN));
1390  EXPECT_EQ(old_text, omnibox_view->GetText());
1391
1392  // Redo should delete the text again.
1393  ASSERT_NO_FATAL_FAILURE(
1394      SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN));
1395  EXPECT_TRUE(omnibox_view->GetText().empty());
1396
1397  // Looks like the undo manager doesn't support restoring selection.
1398  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN));
1399  EXPECT_FALSE(omnibox_view->IsSelectAll());
1400
1401  // The cursor should be at the end.
1402  size_t start, end;
1403  omnibox_view->GetSelectionBounds(&start, &end);
1404  EXPECT_EQ(old_text.size(), start);
1405  EXPECT_EQ(old_text.size(), end);
1406
1407  // Delete three characters; "about:bl" should not trigger inline autocomplete.
1408  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1409  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1410  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1411  EXPECT_EQ(old_text.substr(0, old_text.size() - 3), omnibox_view->GetText());
1412
1413  // Undo delete.
1414  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN));
1415  EXPECT_EQ(old_text, omnibox_view->GetText());
1416
1417  // Redo delete.
1418  ASSERT_NO_FATAL_FAILURE(
1419      SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN));
1420  EXPECT_EQ(old_text.substr(0, old_text.size() - 3), omnibox_view->GetText());
1421
1422  // Delete everything.
1423  omnibox_view->SelectAll(true);
1424  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1425  EXPECT_TRUE(omnibox_view->GetText().empty());
1426
1427  // Undo delete everything.
1428  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN));
1429  EXPECT_EQ(old_text.substr(0, old_text.size() - 3), omnibox_view->GetText());
1430
1431  // Undo delete two characters.
1432  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN));
1433  EXPECT_EQ(old_text, omnibox_view->GetText());
1434}
1435
1436IN_PROC_BROWSER_TEST_F(OmniboxViewTest, BackspaceDeleteHalfWidthKatakana) {
1437  OmniboxView* omnibox_view = NULL;
1438  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1439  // Insert text: ダ
1440  omnibox_view->SetUserText(base::UTF8ToUTF16("\357\276\200\357\276\236"));
1441
1442  // Move the cursor to the end.
1443  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_END, 0));
1444
1445  // Backspace should delete one character.
1446  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_BACK, 0));
1447  EXPECT_EQ(base::UTF8ToUTF16("\357\276\200"), omnibox_view->GetText());
1448}
1449#endif  // defined(TOOLKIT_VIEWS)
1450
1451// Flaky test. crbug.com/356850
1452IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
1453                       DISABLED_DoesNotUpdateAutocompleteOnBlur) {
1454  OmniboxView* omnibox_view = NULL;
1455  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1456  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1457  ASSERT_TRUE(popup_model);
1458
1459  // Input something to trigger inline autocomplete.
1460  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kInlineAutocompleteTextKeys));
1461  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1462  ASSERT_TRUE(popup_model->IsOpen());
1463  size_t start, end;
1464  omnibox_view->GetSelectionBounds(&start, &end);
1465  EXPECT_TRUE(start != end);
1466  base::string16 old_autocomplete_text =
1467      omnibox_view->model()->autocomplete_controller()->input_.text();
1468
1469  // Unfocus the omnibox. This should clear the text field selection and
1470  // close the popup, but should not run autocomplete.
1471  // Note: GTK preserves the selection when the omnibox is unfocused.
1472  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
1473  ASSERT_FALSE(popup_model->IsOpen());
1474  omnibox_view->GetSelectionBounds(&start, &end);
1475  EXPECT_TRUE(start == end);
1476
1477  EXPECT_EQ(old_autocomplete_text,
1478      omnibox_view->model()->autocomplete_controller()->input_.text());
1479}
1480
1481IN_PROC_BROWSER_TEST_F(OmniboxViewTest, Paste) {
1482  OmniboxView* omnibox_view = NULL;
1483  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1484  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1485  ASSERT_TRUE(popup_model);
1486  EXPECT_FALSE(popup_model->IsOpen());
1487
1488  // Paste should yield the expected text and open the popup.
1489  SetClipboardText(ASCIIToUTF16(kSearchText));
1490  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_V, kCtrlOrCmdMask));
1491  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1492  EXPECT_EQ(ASCIIToUTF16(kSearchText), omnibox_view->GetText());
1493  EXPECT_TRUE(popup_model->IsOpen());
1494
1495  // Close the popup and select all.
1496  omnibox_view->CloseOmniboxPopup();
1497  omnibox_view->SelectAll(false);
1498  EXPECT_FALSE(popup_model->IsOpen());
1499
1500  // Pasting the same text again over itself should re-open the popup.
1501  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_V, kCtrlOrCmdMask));
1502  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1503  EXPECT_EQ(ASCIIToUTF16(kSearchText), omnibox_view->GetText());
1504  EXPECT_TRUE(popup_model->IsOpen());
1505  omnibox_view->CloseOmniboxPopup();
1506  EXPECT_FALSE(popup_model->IsOpen());
1507
1508  // Pasting amid text should yield the expected text and re-open the popup.
1509  omnibox_view->SetWindowTextAndCaretPos(ASCIIToUTF16("abcd"), 2, false, false);
1510  SetClipboardText(ASCIIToUTF16("123"));
1511  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_V, kCtrlOrCmdMask));
1512  EXPECT_EQ(ASCIIToUTF16("ab123cd"), omnibox_view->GetText());
1513  EXPECT_TRUE(popup_model->IsOpen());
1514
1515  // Ctrl/Cmd+Alt+V should not paste.
1516  ASSERT_NO_FATAL_FAILURE(
1517      SendKey(ui::VKEY_V, kCtrlOrCmdMask | ui::EF_ALT_DOWN));
1518  EXPECT_EQ(ASCIIToUTF16("ab123cd"), omnibox_view->GetText());
1519  // TODO(msw): Test that AltGr+V does not paste.
1520}
1521
1522IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CopyURLToClipboard) {
1523  // Set permanent text thus making sure that omnibox treats 'google.com'
1524  // as URL (not as ordinary user input).
1525  TestToolbarModel* test_toolbar_model = new TestToolbarModel;
1526  scoped_ptr<ToolbarModel> toolbar_model(test_toolbar_model);
1527  test_toolbar_model->set_text(ASCIIToUTF16("http://www.google.com/"));
1528  browser()->swap_toolbar_models(&toolbar_model);
1529  OmniboxView* omnibox_view = NULL;
1530  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1531  OmniboxEditModel* edit_model = omnibox_view->model();
1532  ASSERT_NE(static_cast<OmniboxEditModel*>(NULL), edit_model);
1533  edit_model->UpdatePermanentText();
1534
1535  const char* target_url = "http://www.google.com/calendar";
1536  omnibox_view->SetUserText(ASCIIToUTF16(target_url));
1537
1538  // Location bar must have focus.
1539  chrome::FocusLocationBar(browser());
1540  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1541
1542  // Select full URL and copy it to clipboard. General text and html should
1543  // be available.
1544  omnibox_view->SelectAll(true);
1545  EXPECT_TRUE(omnibox_view->IsSelectAll());
1546  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1547  clipboard->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1548  EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_COPY));
1549  EXPECT_EQ(ASCIIToUTF16(target_url), omnibox_view->GetText());
1550  EXPECT_TRUE(clipboard->IsFormatAvailable(
1551      ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1552
1553  // Make sure HTML format isn't written. See
1554  // BookmarkNodeData::WriteToClipboard() for details.
1555  EXPECT_FALSE(clipboard->IsFormatAvailable(
1556      ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1557
1558  // These platforms should read bookmark format.
1559#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
1560  base::string16 title;
1561  std::string url;
1562  clipboard->ReadBookmark(&title, &url);
1563  EXPECT_EQ(target_url, url);
1564  EXPECT_EQ(ASCIIToUTF16(target_url), title);
1565#endif
1566}
1567
1568IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CutURLToClipboard) {
1569  // Set permanent text thus making sure that omnibox treats 'google.com'
1570  // as URL (not as ordinary user input).
1571  TestToolbarModel* test_toolbar_model = new TestToolbarModel;
1572  scoped_ptr<ToolbarModel> toolbar_model(test_toolbar_model);
1573  test_toolbar_model->set_text(ASCIIToUTF16("http://www.google.com/"));
1574  browser()->swap_toolbar_models(&toolbar_model);
1575  OmniboxView* omnibox_view = NULL;
1576  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1577  OmniboxEditModel* edit_model = omnibox_view->model();
1578  ASSERT_NE(static_cast<OmniboxEditModel*>(NULL), edit_model);
1579  edit_model->UpdatePermanentText();
1580
1581  const char* target_url = "http://www.google.com/calendar";
1582  omnibox_view->SetUserText(ASCIIToUTF16(target_url));
1583
1584  // Location bar must have focus.
1585  chrome::FocusLocationBar(browser());
1586  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1587
1588  // Select full URL and cut it. General text and html should be available
1589  // in the clipboard.
1590  omnibox_view->SelectAll(true);
1591  EXPECT_TRUE(omnibox_view->IsSelectAll());
1592  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1593  clipboard->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1594  EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_CUT));
1595  EXPECT_EQ(base::string16(), omnibox_view->GetText());
1596  EXPECT_TRUE(clipboard->IsFormatAvailable(
1597      ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1598
1599  // Make sure HTML format isn't written. See
1600  // BookmarkNodeData::WriteToClipboard() for details.
1601  EXPECT_FALSE(clipboard->IsFormatAvailable(
1602      ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1603
1604  // These platforms should read bookmark format.
1605#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
1606  base::string16 title;
1607  std::string url;
1608  clipboard->ReadBookmark(&title, &url);
1609  EXPECT_EQ(target_url, url);
1610  EXPECT_EQ(ASCIIToUTF16(target_url), title);
1611#endif
1612}
1613
1614IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CopyTextToClipboard) {
1615  OmniboxView* omnibox_view = NULL;
1616  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1617  const char* target_text = "foo";
1618  omnibox_view->SetUserText(ASCIIToUTF16(target_text));
1619
1620  // Location bar must have focus.
1621  chrome::FocusLocationBar(browser());
1622  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1623
1624  // Select full text and copy it to the clipboard.
1625  omnibox_view->SelectAll(true);
1626  EXPECT_TRUE(omnibox_view->IsSelectAll());
1627  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1628  clipboard->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1629  EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_COPY));
1630  EXPECT_TRUE(clipboard->IsFormatAvailable(
1631      ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1632  EXPECT_FALSE(clipboard->IsFormatAvailable(
1633      ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1634  EXPECT_EQ(ASCIIToUTF16(target_text), omnibox_view->GetText());
1635}
1636
1637IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CutTextToClipboard) {
1638  OmniboxView* omnibox_view = NULL;
1639  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1640  const char* target_text = "foo";
1641  omnibox_view->SetUserText(ASCIIToUTF16(target_text));
1642
1643  // Location bar must have focus.
1644  chrome::FocusLocationBar(browser());
1645  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1646
1647  // Select full text and cut it to the clipboard.
1648  omnibox_view->SelectAll(true);
1649  EXPECT_TRUE(omnibox_view->IsSelectAll());
1650  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1651  clipboard->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1652  EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_CUT));
1653  EXPECT_TRUE(clipboard->IsFormatAvailable(
1654      ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1655  EXPECT_FALSE(clipboard->IsFormatAvailable(
1656      ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
1657  EXPECT_EQ(base::string16(), omnibox_view->GetText());
1658}
1659
1660IN_PROC_BROWSER_TEST_F(OmniboxViewTest, EditSearchEngines) {
1661  // Disable settings-in-a-window to simplify test.
1662  base::CommandLine::ForCurrentProcess()->AppendSwitch(
1663      ::switches::kDisableSettingsWindow);
1664  OmniboxView* omnibox_view = NULL;
1665  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1666  EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_EDIT_SEARCH_ENGINES));
1667  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1668  const std::string target_url =
1669      std::string(chrome::kChromeUISettingsURL) + chrome::kSearchEnginesSubPage;
1670  EXPECT_EQ(ASCIIToUTF16(target_url), omnibox_view->GetText());
1671  EXPECT_FALSE(omnibox_view->model()->popup_model()->IsOpen());
1672}
1673
1674IN_PROC_BROWSER_TEST_F(OmniboxViewTest, BeginningShownAfterBlur) {
1675  OmniboxView* omnibox_view = NULL;
1676  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1677
1678  omnibox_view->OnBeforePossibleChange();
1679  omnibox_view->SetWindowTextAndCaretPos(ASCIIToUTF16("data:text/plain,test"),
1680      5U, false, false);
1681  omnibox_view->OnAfterPossibleChange();
1682  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1683  size_t start, end;
1684  omnibox_view->GetSelectionBounds(&start, &end);
1685  ASSERT_EQ(5U, start);
1686  ASSERT_EQ(5U, end);
1687
1688  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
1689  ASSERT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
1690
1691  omnibox_view->GetSelectionBounds(&start, &end);
1692  ASSERT_EQ(0U, start);
1693  ASSERT_EQ(0U, end);
1694}
1695
1696IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CtrlArrowAfterArrowSuggestions) {
1697  OmniboxView* omnibox_view = NULL;
1698  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1699  OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
1700  ASSERT_TRUE(popup_model);
1701
1702  // Input something to trigger results.
1703  const wchar_t kKeys[] = { ui::VKEY_B, ui::VKEY_A, ui::VKEY_R, 0 };
1704  ASSERT_NO_FATAL_FAILURE(SendKeySequence(kKeys));
1705  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1706  ASSERT_TRUE(popup_model->IsOpen());
1707
1708  ASSERT_EQ(ASCIIToUTF16("bar.com/1"), omnibox_view->GetText());
1709
1710  // Arrow down on a suggestion, and omnibox text should be the suggestion.
1711  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DOWN, 0));
1712  ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
1713  ASSERT_EQ(ASCIIToUTF16("www.bar.com/2"), omnibox_view->GetText());
1714
1715  // Highlight the last 2 words and the omnibox text should not change.
1716  // Simulating Ctrl-shift-left only once does not seem to highlight anything
1717  // on Linux.
1718#if defined(OS_MACOSX)
1719  // Mac uses alt-left/right to select a word.
1720  const int modifiers = ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN;
1721#else
1722  const int modifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN;
1723#endif
1724  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, modifiers));
1725  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_LEFT, modifiers));
1726  ASSERT_EQ(ASCIIToUTF16("www.bar.com/2"), omnibox_view->GetText());
1727}
1728
1729IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
1730                       PersistSearchReplacementAcrossTabSwitch) {
1731  EXPECT_TRUE(browser()->toolbar_model()->url_replacement_enabled());
1732  browser()->toolbar_model()->set_url_replacement_enabled(false);
1733
1734  // Create a new tab.
1735  chrome::NewTab(browser());
1736  EXPECT_TRUE(browser()->toolbar_model()->url_replacement_enabled());
1737
1738  // Switch back to the first tab.
1739  browser()->tab_strip_model()->ActivateTabAt(0, true);
1740  EXPECT_FALSE(browser()->toolbar_model()->url_replacement_enabled());
1741}
1742
1743IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
1744                       DontUpdateURLWhileSearchTermReplacementIsDisabled) {
1745  OmniboxView* omnibox_view = NULL;
1746  ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
1747  TestToolbarModel* test_toolbar_model = new TestToolbarModel;
1748  scoped_ptr<ToolbarModel> toolbar_model(test_toolbar_model);
1749  browser()->swap_toolbar_models(&toolbar_model);
1750
1751  base::string16 url_a(ASCIIToUTF16("http://www.a.com/"));
1752  base::string16 url_b(ASCIIToUTF16("http://www.b.com/"));
1753  base::string16 url_c(ASCIIToUTF16("http://www.c.com/"));
1754  chrome::FocusLocationBar(browser());
1755  test_toolbar_model->set_text(url_a);
1756  omnibox_view->Update();
1757  EXPECT_EQ(url_a, omnibox_view->GetText());
1758
1759  // Disable URL replacement and update.  Because the omnibox has focus, the
1760  // visible text shouldn't change; see comments in
1761  // OmniboxEditModel::UpdatePermanentText().
1762  browser()->toolbar_model()->set_url_replacement_enabled(false);
1763  test_toolbar_model->set_text(url_b);
1764  omnibox_view->Update();
1765  EXPECT_EQ(url_a, omnibox_view->GetText());
1766
1767  // Re-enable URL replacement and ensure updating changes the text.
1768  browser()->toolbar_model()->set_url_replacement_enabled(true);
1769  // We have to change the toolbar model text here, or Update() will do nothing.
1770  // This is because the previous update already updated the permanent text.
1771  test_toolbar_model->set_text(url_c);
1772  omnibox_view->Update();
1773  EXPECT_EQ(url_c, omnibox_view->GetText());
1774
1775  // The same test, but using RevertAll() to reset search term replacement.
1776  test_toolbar_model->set_text(url_a);
1777  omnibox_view->Update();
1778  EXPECT_EQ(url_a, omnibox_view->GetText());
1779  browser()->toolbar_model()->set_url_replacement_enabled(false);
1780  test_toolbar_model->set_text(url_b);
1781  omnibox_view->Update();
1782  EXPECT_EQ(url_a, omnibox_view->GetText());
1783  omnibox_view->RevertAll();
1784  EXPECT_EQ(url_b, omnibox_view->GetText());
1785  test_toolbar_model->set_text(url_c);
1786  omnibox_view->Update();
1787  EXPECT_EQ(url_c, omnibox_view->GetText());
1788}
1789
1790IN_PROC_BROWSER_TEST_F(OmniboxViewTest, EscDisablesSearchTermReplacement) {
1791  browser()->toolbar_model()->set_url_replacement_enabled(true);
1792  chrome::FocusLocationBar(browser());
1793  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, 0));
1794  EXPECT_FALSE(browser()->toolbar_model()->url_replacement_enabled());
1795}
1796