omnibox_view_views_browsertest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright (c) 2013 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 "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
6
7#include "base/command_line.h"
8#include "chrome/browser/search_engines/template_url_service_factory.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/browser/ui/browser_commands.h"
11#include "chrome/browser/ui/browser_window.h"
12#include "chrome/browser/ui/browser_window_testing_views.h"
13#include "chrome/browser/ui/location_bar/location_bar.h"
14#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
15#include "chrome/browser/ui/view_ids.h"
16#include "chrome/browser/ui/views/frame/browser_view.h"
17#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
18#include "chrome/test/base/in_process_browser_test.h"
19#include "chrome/test/base/interactive_test_utils.h"
20#include "grit/generated_resources.h"
21#include "ui/base/clipboard/clipboard.h"
22#include "ui/base/clipboard/scoped_clipboard_writer.h"
23#include "ui/base/ime/text_input_focus_manager.h"
24#include "ui/base/test/ui_controls.h"
25#include "ui/base/ui_base_switches.h"
26#include "ui/events/event_processor.h"
27#include "ui/events/event_utils.h"
28#include "ui/events/test/event_generator.h"
29#include "ui/views/controls/textfield/textfield_test_api.h"
30
31class OmniboxViewViewsTest : public InProcessBrowserTest {
32 protected:
33  OmniboxViewViewsTest() {}
34
35  static void GetOmniboxViewForBrowser(const Browser* browser,
36                                       OmniboxView** omnibox_view) {
37    BrowserWindow* window = browser->window();
38    ASSERT_TRUE(window);
39    LocationBar* location_bar = window->GetLocationBar();
40    ASSERT_TRUE(location_bar);
41    *omnibox_view = location_bar->GetOmniboxView();
42    ASSERT_TRUE(*omnibox_view);
43  }
44
45  // Move the mouse to the center of the browser window and left-click.
46  void ClickBrowserWindowCenter() {
47    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
48        BrowserView::GetBrowserViewForBrowser(
49            browser())->GetBoundsInScreen().CenterPoint()));
50    ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(ui_controls::LEFT,
51                                                   ui_controls::DOWN));
52    ASSERT_TRUE(
53        ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::UP));
54  }
55
56  // Press and release the mouse at the specified locations.  If
57  // |release_offset| differs from |press_offset|, the mouse will be moved
58  // between the press and release.
59  void Click(ui_controls::MouseButton button,
60             const gfx::Point& press_location,
61             const gfx::Point& release_location) {
62    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(press_location));
63    ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button, ui_controls::DOWN));
64
65    if (press_location != release_location)
66      ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(release_location));
67    ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button, ui_controls::UP));
68  }
69
70  // Tap the center of the browser window.
71  void TapBrowserWindowCenter() {
72    gfx::Point center = BrowserView::GetBrowserViewForBrowser(
73        browser())->GetBoundsInScreen().CenterPoint();
74    ui::test::EventGenerator generator(browser()->window()->GetNativeWindow());
75    generator.GestureTapAt(center);
76  }
77
78  // Touch down and release at the specified locations.
79  void Tap(const gfx::Point& press_location,
80           const gfx::Point& release_location) {
81    ui::test::EventGenerator generator(browser()->window()->GetNativeWindow());
82    if (press_location == release_location) {
83      generator.GestureTapAt(press_location);
84    } else {
85      generator.GestureScrollSequence(press_location,
86                                      release_location,
87                                      base::TimeDelta::FromMilliseconds(10),
88                                      1);
89    }
90  }
91
92 private:
93  // InProcessBrowserTest:
94  virtual void SetUpOnMainThread() OVERRIDE {
95    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
96    chrome::FocusLocationBar(browser());
97    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
98  }
99
100  DISALLOW_COPY_AND_ASSIGN(OmniboxViewViewsTest);
101};
102
103IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, PasteAndGoDoesNotLeavePopupOpen) {
104  OmniboxView* view = NULL;
105  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view));
106  OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
107
108  // Put an URL on the clipboard.
109  {
110    ui::ScopedClipboardWriter clipboard_writer(
111        ui::Clipboard::GetForCurrentThread(), ui::CLIPBOARD_TYPE_COPY_PASTE);
112    clipboard_writer.WriteURL(base::ASCIIToUTF16("http://www.example.com/"));
113  }
114
115  // Paste and go.
116  omnibox_view_views->ExecuteCommand(IDS_PASTE_AND_GO, ui::EF_NONE);
117
118  // The popup should not be open.
119  EXPECT_FALSE(view->model()->popup_model()->IsOpen());
120}
121
122IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, SelectAllOnClick) {
123  OmniboxView* omnibox_view = NULL;
124  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
125  omnibox_view->SetUserText(base::ASCIIToUTF16("http://www.google.com/"));
126
127  // Take the focus away from the omnibox.
128  ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
129  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
130  EXPECT_FALSE(omnibox_view->IsSelectAll());
131
132  // Clicking in the omnibox should take focus and select all text.
133  const gfx::Rect omnibox_bounds = BrowserView::GetBrowserViewForBrowser(
134        browser())->GetViewByID(VIEW_ID_OMNIBOX)->GetBoundsInScreen();
135  const gfx::Point click_location = omnibox_bounds.CenterPoint();
136  ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT,
137                                click_location, click_location));
138  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
139  EXPECT_TRUE(omnibox_view->IsSelectAll());
140
141  // Clicking in another view should clear focus and the selection.
142  ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
143  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
144  EXPECT_FALSE(omnibox_view->IsSelectAll());
145
146  // Clicking in the omnibox again should take focus and select all text again.
147  ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT,
148                                click_location, click_location));
149  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
150  EXPECT_TRUE(omnibox_view->IsSelectAll());
151
152  // Clicking another omnibox spot should keep focus but clear the selection.
153  omnibox_view->SelectAll(false);
154  const gfx::Point click2_location = omnibox_bounds.origin() +
155      gfx::Vector2d(omnibox_bounds.width() / 4, omnibox_bounds.height() / 4);
156  ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT,
157                                click2_location, click2_location));
158  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
159  EXPECT_FALSE(omnibox_view->IsSelectAll());
160
161  // Take the focus away and click in the omnibox again, but drag a bit before
162  // releasing.  We should focus the omnibox but not select all of its text.
163  ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
164  ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT,
165                                click_location, click2_location));
166  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
167  EXPECT_FALSE(omnibox_view->IsSelectAll());
168
169  // Middle-clicking should not be handled by the omnibox.
170  ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
171  ASSERT_NO_FATAL_FAILURE(Click(ui_controls::MIDDLE,
172                                click_location, click_location));
173  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
174  EXPECT_FALSE(omnibox_view->IsSelectAll());
175}
176
177IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, SelectAllOnTap) {
178  OmniboxView* omnibox_view = NULL;
179  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
180  omnibox_view->SetUserText(base::ASCIIToUTF16("http://www.google.com/"));
181
182  // Take the focus away from the omnibox.
183  ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
184  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
185  EXPECT_FALSE(omnibox_view->IsSelectAll());
186
187  // Tapping in the omnibox should take focus and select all text.
188  const gfx::Rect omnibox_bounds = BrowserView::GetBrowserViewForBrowser(
189      browser())->GetViewByID(VIEW_ID_OMNIBOX)->GetBoundsInScreen();
190  const gfx::Point tap_location = omnibox_bounds.CenterPoint();
191  ASSERT_NO_FATAL_FAILURE(Tap(tap_location, tap_location));
192  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
193  EXPECT_TRUE(omnibox_view->IsSelectAll());
194
195  // Tapping in another view should clear focus and the selection.
196  ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
197  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
198  EXPECT_FALSE(omnibox_view->IsSelectAll());
199
200  // Tapping in the omnibox again should take focus and select all text again.
201  ASSERT_NO_FATAL_FAILURE(Tap(tap_location, tap_location));
202  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
203  EXPECT_TRUE(omnibox_view->IsSelectAll());
204
205  // Tapping another omnibox spot should keep focus and selection.
206  omnibox_view->SelectAll(false);
207  const gfx::Point tap2_location = omnibox_bounds.origin() +
208      gfx::Vector2d(omnibox_bounds.width() / 4, omnibox_bounds.height() / 4);
209  ASSERT_NO_FATAL_FAILURE(Tap(tap2_location, tap2_location));
210  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
211  // We don't test if the all text is selected because it depends on whether or
212  // not there was text under the tap, which appears to be flaky.
213
214  // Take the focus away and tap in the omnibox again, but drag a bit before
215  // releasing.  We should focus the omnibox but not select all of its text.
216  ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
217  ASSERT_NO_FATAL_FAILURE(Tap(tap_location, tap2_location));
218  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
219  EXPECT_FALSE(omnibox_view->IsSelectAll());
220}
221
222IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, SelectAllOnTabToFocus) {
223  OmniboxView* omnibox_view = NULL;
224  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
225  ui_test_utils::NavigateToURL(browser(), GURL("http://www.google.com/"));
226  // RevertAll after navigation to invalidate the selection range saved on blur.
227  omnibox_view->RevertAll();
228  EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
229  EXPECT_FALSE(omnibox_view->IsSelectAll());
230
231  // Pressing tab to focus the omnibox should select all text.
232  while (!ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)) {
233    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB,
234                                                false, false, false, false));
235  }
236  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
237  EXPECT_TRUE(omnibox_view->IsSelectAll());
238}
239
240IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, CloseOmniboxPopupOnTextDrag) {
241  OmniboxView* omnibox_view = NULL;
242  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
243  OmniboxViewViews* omnibox_view_views =
244      static_cast<OmniboxViewViews*>(omnibox_view);
245
246  // Populate suggestions for the omnibox popup.
247  AutocompleteController* autocomplete_controller =
248      omnibox_view->model()->popup_model()->autocomplete_controller();
249  AutocompleteResult& results = autocomplete_controller->result_;
250  ACMatches matches;
251  AutocompleteMatch match;
252  match.destination_url = GURL("http://autocomplete-result/");
253  match.allowed_to_be_default_match = true;
254  match.type = AutocompleteMatchType::HISTORY_TITLE;
255  match.relevance = 500;
256  matches.push_back(match);
257  match.destination_url = GURL("http://autocomplete-result2/");
258  matches.push_back(match);
259  results.AppendMatches(matches);
260  results.SortAndCull(
261      AutocompleteInput(),
262      TemplateURLServiceFactory::GetForProfile(browser()->profile()));
263
264  // The omnibox popup should open with suggestions displayed.
265  omnibox_view->model()->popup_model()->OnResultChanged();
266  EXPECT_TRUE(omnibox_view->model()->popup_model()->IsOpen());
267
268  // The omnibox text should be selected.
269  EXPECT_TRUE(omnibox_view->IsSelectAll());
270
271  // Simulate a mouse click before dragging the mouse.
272  gfx::Point point(omnibox_view_views->x(), omnibox_view_views->y());
273  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point,
274                         ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
275  omnibox_view_views->OnMousePressed(pressed);
276  EXPECT_TRUE(omnibox_view->model()->popup_model()->IsOpen());
277
278  // Simulate a mouse drag of the omnibox text, and the omnibox should close.
279  ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, point, point,
280                         ui::EF_LEFT_MOUSE_BUTTON, 0);
281  omnibox_view_views->OnMouseDragged(dragged);
282
283  EXPECT_FALSE(omnibox_view->model()->popup_model()->IsOpen());
284}
285
286IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, BackgroundIsOpaque) {
287  // The omnibox text should be rendered on an opaque background. Otherwise, we
288  // can't use subpixel rendering.
289  BrowserWindowTesting* window = browser()->window()->GetBrowserWindowTesting();
290  ASSERT_TRUE(window);
291  OmniboxViewViews* view = window->GetLocationBarView()->omnibox_view();
292  ASSERT_TRUE(view);
293  EXPECT_FALSE(view->GetRenderText()->background_is_transparent());
294}
295
296// Tests if executing a command hides touch editing handles.
297IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest,
298                       DeactivateTouchEditingOnExecuteCommand) {
299  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
300
301  OmniboxView* view = NULL;
302  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view));
303  OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
304  views::TextfieldTestApi textfield_test_api(omnibox_view_views);
305
306  // Put a URL on the clipboard. It is written to the clipboard upon destruction
307  // of the writer.
308  {
309    ui::ScopedClipboardWriter clipboard_writer(
310        ui::Clipboard::GetForCurrentThread(),
311        ui::CLIPBOARD_TYPE_COPY_PASTE);
312    clipboard_writer.WriteURL(base::ASCIIToUTF16("http://www.example.com/"));
313  }
314
315  // Tap to activate touch editing.
316  gfx::Point omnibox_center =
317      omnibox_view_views->GetBoundsInScreen().CenterPoint();
318  Tap(omnibox_center, omnibox_center);
319  EXPECT_TRUE(textfield_test_api.touch_selection_controller());
320
321  // Execute a command and check if it deactivate touch editing. Paste & Go is
322  // chosen since it is specific to Omnibox and its execution wouldn't be
323  // delgated to the base Textfield class.
324  omnibox_view_views->ExecuteCommand(IDS_PASTE_AND_GO, ui::EF_NONE);
325  EXPECT_FALSE(textfield_test_api.touch_selection_controller());
326}
327
328IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FocusedTextInputClient) {
329  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
330  cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager);
331
332  // TODO(yukishiino): The following call to FocusLocationBar is not necessary
333  // if the flag is enabled by default.  Remove the call once the transition to
334  // TextInputFocusManager completes.
335  chrome::FocusLocationBar(browser());
336  OmniboxView* view = NULL;
337  ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view));
338  OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
339  ui::TextInputFocusManager* text_input_focus_manager =
340      ui::TextInputFocusManager::GetInstance();
341  EXPECT_EQ(omnibox_view_views->GetTextInputClient(),
342            text_input_focus_manager->GetFocusedTextInputClient());
343}
344