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