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.
5 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
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/grit/generated_resources.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "chrome/test/base/interactive_test_utils.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"
31 class OmniboxViewViewsTest : public InProcessBrowserTest {
33 OmniboxViewViewsTest() {}
35 static void GetOmniboxViewForBrowser(const Browser* browser,
36 OmniboxView** omnibox_view) {
37 BrowserWindow* window = browser->window();
39 LocationBar* location_bar = window->GetLocationBar();
40 ASSERT_TRUE(location_bar);
41 *omnibox_view = location_bar->GetOmniboxView();
42 ASSERT_TRUE(*omnibox_view);
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,
53 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::UP));
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));
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));
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);
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);
85 generator.GestureScrollSequence(press_location,
87 base::TimeDelta::FromMilliseconds(10),
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));
100 DISALLOW_COPY_AND_ASSIGN(OmniboxViewViewsTest);
103 IN_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);
108 // Put an URL on the clipboard.
110 ui::ScopedClipboardWriter clipboard_writer(
111 ui::Clipboard::GetForCurrentThread(), ui::CLIPBOARD_TYPE_COPY_PASTE);
112 clipboard_writer.WriteURL(base::ASCIIToUTF16("http://www.example.com/"));
116 omnibox_view_views->ExecuteCommand(IDS_PASTE_AND_GO, ui::EF_NONE);
118 // The popup should not be open.
119 EXPECT_FALSE(view->model()->popup_model()->IsOpen());
122 IN_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/"));
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());
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());
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());
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());
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());
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());
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());
177 IN_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/"));
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());
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());
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());
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());
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.
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());
222 IN_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());
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));
236 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
237 EXPECT_TRUE(omnibox_view->IsSelectAll());
240 IN_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);
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_;
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);
262 TemplateURLServiceFactory::GetForProfile(browser()->profile()));
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());
268 // The omnibox text should be selected.
269 EXPECT_TRUE(omnibox_view->IsSelectAll());
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());
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);
283 EXPECT_FALSE(omnibox_view->model()->popup_model()->IsOpen());
286 IN_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();
291 OmniboxViewViews* view = window->GetLocationBarView()->omnibox_view();
293 EXPECT_FALSE(view->GetRenderText()->background_is_transparent());
296 // Tests if executing a command hides touch editing handles.
297 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest,
298 DeactivateTouchEditingOnExecuteCommand) {
299 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
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);
306 // Put a URL on the clipboard. It is written to the clipboard upon destruction
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/"));
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());
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());
328 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FocusedTextInputClient) {
329 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
330 cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager);
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());