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 "chrome/browser/ui/browser.h"
8 #include "chrome/browser/ui/browser_commands.h"
9 #include "chrome/browser/ui/browser_window.h"
10 #include "chrome/browser/ui/omnibox/location_bar.h"
11 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
12 #include "chrome/browser/ui/view_ids.h"
13 #include "chrome/browser/ui/views/frame/browser_view.h"
14 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/interactive_test_utils.h"
17 #include "grit/generated_resources.h"
18 #include "ui/aura/test/event_generator.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_tree_host.h"
21 #include "ui/base/clipboard/clipboard.h"
22 #include "ui/base/clipboard/scoped_clipboard_writer.h"
23 #include "ui/base/test/ui_controls.h"
24 #include "ui/events/event_processor.h"
26 class OmniboxViewViewsTest
: public InProcessBrowserTest
{
28 OmniboxViewViewsTest() {}
30 static void GetOmniboxViewForBrowser(const Browser
* browser
,
31 OmniboxView
** omnibox_view
) {
32 BrowserWindow
* window
= browser
->window();
34 LocationBar
* location_bar
= window
->GetLocationBar();
35 ASSERT_TRUE(location_bar
);
36 *omnibox_view
= location_bar
->GetOmniboxView();
37 ASSERT_TRUE(*omnibox_view
);
40 // Move the mouse to the center of the browser window and left-click.
41 void ClickBrowserWindowCenter() {
42 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
43 BrowserView::GetBrowserViewForBrowser(
44 browser())->GetBoundsInScreen().CenterPoint()));
45 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(ui_controls::LEFT
,
48 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT
, ui_controls::UP
));
51 // Press and release the mouse at the specified locations. If
52 // |release_offset| differs from |press_offset|, the mouse will be moved
53 // between the press and release.
54 void Click(ui_controls::MouseButton button
,
55 const gfx::Point
& press_location
,
56 const gfx::Point
& release_location
) {
57 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(press_location
));
58 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button
, ui_controls::DOWN
));
60 if (press_location
!= release_location
)
61 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(release_location
));
62 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(button
, ui_controls::UP
));
65 // Tap the center of the browser window.
66 void TapBrowserWindowCenter() {
67 gfx::Point center
= BrowserView::GetBrowserViewForBrowser(
68 browser())->GetBoundsInScreen().CenterPoint();
69 aura::test::EventGenerator
generator(browser()->window()->
70 GetNativeWindow()->GetRootWindow());
71 generator
.GestureTapAt(center
);
74 // Touch down and release at the specified locations.
75 void Tap(const gfx::Point
& press_location
,
76 const gfx::Point
& release_location
) {
77 ui::EventProcessor
* dispatcher
=
78 browser()->window()->GetNativeWindow()->GetHost()->event_processor();
80 ui::TouchEvent
press(ui::ET_TOUCH_PRESSED
, press_location
,
81 5, base::TimeDelta::FromMilliseconds(0));
82 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&press
);
83 ASSERT_FALSE(details
.dispatcher_destroyed
);
85 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
, release_location
,
86 5, base::TimeDelta::FromMilliseconds(50));
87 details
= dispatcher
->OnEventFromSource(&release
);
88 ASSERT_FALSE(details
.dispatcher_destroyed
);
92 // InProcessBrowserTest:
93 virtual void SetUpOnMainThread() OVERRIDE
{
94 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
95 chrome::FocusLocationBar(browser());
96 ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
99 DISALLOW_COPY_AND_ASSIGN(OmniboxViewViewsTest
);
102 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, PasteAndGoDoesNotLeavePopupOpen
) {
103 OmniboxView
* view
= NULL
;
104 ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view
));
105 OmniboxViewViews
* omnibox_view_views
= static_cast<OmniboxViewViews
*>(view
);
107 // Put an URL on the clipboard.
109 ui::ScopedClipboardWriter
clipboard_writer(
110 ui::Clipboard::GetForCurrentThread(), ui::CLIPBOARD_TYPE_COPY_PASTE
);
111 clipboard_writer
.WriteURL(base::ASCIIToUTF16("http://www.example.com/"));
115 omnibox_view_views
->ExecuteCommand(IDS_PASTE_AND_GO
, ui::EF_NONE
);
117 // The popup should not be open.
118 EXPECT_FALSE(view
->model()->popup_model()->IsOpen());
121 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, SelectAllOnClick
) {
122 OmniboxView
* omnibox_view
= NULL
;
123 ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view
));
124 omnibox_view
->SetUserText(base::ASCIIToUTF16("http://www.google.com/"));
126 // Take the focus away from the omnibox.
127 ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
128 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
129 EXPECT_FALSE(omnibox_view
->IsSelectAll());
131 // Clicking in the omnibox should take focus and select all text.
132 const gfx::Rect omnibox_bounds
= BrowserView::GetBrowserViewForBrowser(
133 browser())->GetViewByID(VIEW_ID_OMNIBOX
)->GetBoundsInScreen();
134 const gfx::Point click_location
= omnibox_bounds
.CenterPoint();
135 ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT
,
136 click_location
, click_location
));
137 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
138 EXPECT_TRUE(omnibox_view
->IsSelectAll());
140 // Clicking in another view should clear focus and the selection.
141 ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
142 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
143 EXPECT_FALSE(omnibox_view
->IsSelectAll());
145 // Clicking in the omnibox again should take focus and select all text again.
146 ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT
,
147 click_location
, click_location
));
148 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
149 EXPECT_TRUE(omnibox_view
->IsSelectAll());
151 // Clicking another omnibox spot should keep focus but clear the selection.
152 omnibox_view
->SelectAll(false);
153 const gfx::Point click2_location
= omnibox_bounds
.origin() +
154 gfx::Vector2d(omnibox_bounds
.width() / 4, omnibox_bounds
.height() / 4);
155 ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT
,
156 click2_location
, click2_location
));
157 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
158 EXPECT_FALSE(omnibox_view
->IsSelectAll());
160 // Take the focus away and click in the omnibox again, but drag a bit before
161 // releasing. We should focus the omnibox but not select all of its text.
162 ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
163 ASSERT_NO_FATAL_FAILURE(Click(ui_controls::LEFT
,
164 click_location
, click2_location
));
165 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
166 EXPECT_FALSE(omnibox_view
->IsSelectAll());
168 // Middle-clicking should not be handled by the omnibox.
169 ASSERT_NO_FATAL_FAILURE(ClickBrowserWindowCenter());
170 ASSERT_NO_FATAL_FAILURE(Click(ui_controls::MIDDLE
,
171 click_location
, click_location
));
172 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
173 EXPECT_FALSE(omnibox_view
->IsSelectAll());
176 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, SelectAllOnTap
) {
177 OmniboxView
* omnibox_view
= NULL
;
178 ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view
));
179 omnibox_view
->SetUserText(base::ASCIIToUTF16("http://www.google.com/"));
181 // Take the focus away from the omnibox.
182 ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
183 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
184 EXPECT_FALSE(omnibox_view
->IsSelectAll());
186 // Tapping in the omnibox should take focus and select all text.
187 const gfx::Rect omnibox_bounds
= BrowserView::GetBrowserViewForBrowser(
188 browser())->GetViewByID(VIEW_ID_OMNIBOX
)->GetBoundsInScreen();
189 const gfx::Point tap_location
= omnibox_bounds
.CenterPoint();
190 ASSERT_NO_FATAL_FAILURE(Tap(tap_location
, tap_location
));
191 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
192 EXPECT_TRUE(omnibox_view
->IsSelectAll());
194 // Tapping in another view should clear focus and the selection.
195 ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
196 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
197 EXPECT_FALSE(omnibox_view
->IsSelectAll());
199 // Tapping in the omnibox again should take focus and select all text again.
200 ASSERT_NO_FATAL_FAILURE(Tap(tap_location
, tap_location
));
201 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
202 EXPECT_TRUE(omnibox_view
->IsSelectAll());
204 // Tapping another omnibox spot should keep focus and selection.
205 omnibox_view
->SelectAll(false);
206 const gfx::Point tap2_location
= omnibox_bounds
.origin() +
207 gfx::Vector2d(omnibox_bounds
.width() / 4, omnibox_bounds
.height() / 4);
208 ASSERT_NO_FATAL_FAILURE(Tap(tap2_location
, tap2_location
));
209 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
210 // We don't test if the all text is selected because it depends on whether or
211 // not there was text under the tap, which appears to be flaky.
213 // Take the focus away and tap in the omnibox again, but drag a bit before
214 // releasing. We should focus the omnibox but not select all of its text.
215 ASSERT_NO_FATAL_FAILURE(TapBrowserWindowCenter());
216 ASSERT_NO_FATAL_FAILURE(Tap(tap_location
, tap2_location
));
217 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
218 EXPECT_FALSE(omnibox_view
->IsSelectAll());
221 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, SelectAllOnTabToFocus
) {
222 OmniboxView
* omnibox_view
= NULL
;
223 ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view
));
224 ui_test_utils::NavigateToURL(browser(), GURL("http://www.google.com/"));
225 // RevertAll after navigation to invalidate the selection range saved on blur.
226 omnibox_view
->RevertAll();
227 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
228 EXPECT_FALSE(omnibox_view
->IsSelectAll());
230 // Pressing tab to focus the omnibox should select all text.
231 while (!ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
)) {
232 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB
,
233 false, false, false, false));
235 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX
));
236 EXPECT_TRUE(omnibox_view
->IsSelectAll());
239 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, CloseOmniboxPopupOnTextDrag
) {
240 OmniboxView
* omnibox_view
= NULL
;
241 ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view
));
242 OmniboxViewViews
* omnibox_view_views
=
243 static_cast<OmniboxViewViews
*>(omnibox_view
);
245 // Populate suggestions for the omnibox popup.
246 AutocompleteController
* autocomplete_controller
=
247 omnibox_view
->model()->popup_model()->autocomplete_controller();
248 AutocompleteResult
& results
= autocomplete_controller
->result_
;
250 AutocompleteMatch match
;
251 match
.destination_url
= GURL("http://autocomplete-result/");
252 match
.allowed_to_be_default_match
= true;
253 match
.type
= AutocompleteMatchType::HISTORY_TITLE
;
254 match
.relevance
= 500;
255 matches
.push_back(match
);
256 match
.destination_url
= GURL("http://autocomplete-result2/");
257 matches
.push_back(match
);
258 results
.AppendMatches(matches
);
259 results
.SortAndCull(AutocompleteInput(), browser()->profile());
261 // The omnibox popup should open with suggestions displayed.
262 omnibox_view
->model()->popup_model()->OnResultChanged();
263 EXPECT_TRUE(omnibox_view
->model()->popup_model()->IsOpen());
265 // The omnibox text should be selected.
266 EXPECT_TRUE(omnibox_view
->IsSelectAll());
268 // Simulate a mouse click before dragging the mouse.
269 gfx::Point
point(omnibox_view_views
->x(), omnibox_view_views
->y());
270 ui::MouseEvent
pressed(ui::ET_MOUSE_PRESSED
, point
, point
,
271 ui::EF_LEFT_MOUSE_BUTTON
, ui::EF_LEFT_MOUSE_BUTTON
);
272 omnibox_view_views
->OnMousePressed(pressed
);
273 EXPECT_TRUE(omnibox_view
->model()->popup_model()->IsOpen());
275 // Simulate a mouse drag of the omnibox text, and the omnibox should close.
276 ui::MouseEvent
dragged(ui::ET_MOUSE_DRAGGED
, point
, point
,
277 ui::EF_LEFT_MOUSE_BUTTON
, 0);
278 omnibox_view_views
->OnMouseDragged(dragged
);
280 EXPECT_FALSE(omnibox_view
->model()->popup_model()->IsOpen());
283 IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest
, BackgroundIsOpaque
) {
284 // The omnibox text should be rendered on an opaque background. Otherwise, we
285 // can't use subpixel rendering.
286 BrowserWindowTesting
* window
= browser()->window()->GetBrowserWindowTesting();
288 OmniboxViewViews
* view
= window
->GetLocationBarView()->omnibox_view();
290 EXPECT_FALSE(view
->GetRenderText()->background_is_transparent());