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