browser_focus_uitest.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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 "build/build_config.h" 6 7#include "base/file_util.h" 8#include "base/format_macros.h" 9#include "base/message_loop.h" 10#include "base/path_service.h" 11#include "base/string_util.h" 12#include "base/utf_string_conversions.h" 13#include "chrome/browser/browser.h" 14#include "chrome/browser/browser_window.h" 15#include "chrome/browser/renderer_host/render_view_host.h" 16#include "chrome/browser/renderer_host/render_widget_host_view.h" 17#include "chrome/browser/tab_contents/interstitial_page.h" 18#include "chrome/browser/tab_contents/tab_contents.h" 19#include "chrome/browser/tab_contents/tab_contents_view.h" 20#include "chrome/browser/tabs/tab_strip_model.h" 21#include "chrome/browser/view_ids.h" 22#include "chrome/common/chrome_paths.h" 23#include "chrome/common/url_constants.h" 24#include "chrome/test/in_process_browser_test.h" 25#include "chrome/test/ui_test_utils.h" 26#include "net/test/test_server.h" 27 28#if defined(TOOLKIT_VIEWS) || defined(OS_WIN) 29#include "views/focus/focus_manager.h" 30#include "views/view.h" 31#include "views/window/window.h" 32#endif 33 34#if defined(TOOLKIT_VIEWS) 35#include "chrome/browser/views/frame/browser_view.h" 36#include "chrome/browser/views/location_bar/location_bar_view.h" 37#include "chrome/browser/views/tab_contents/tab_contents_container.h" 38#endif 39 40#if defined(TOOLKIT_USES_GTK) 41#include "chrome/browser/gtk/view_id_util.h" 42#endif 43 44#if defined(OS_LINUX) 45#define MAYBE_FocusTraversal FocusTraversal 46#define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial 47// TODO(jcampan): http://crbug.com/23683 48#define MAYBE_TabsRememberFocusFindInPage FAILS_TabsRememberFocusFindInPage 49#elif defined(OS_MACOSX) 50// TODO(suzhe): http://crbug.com/49738 (following two tests) 51#define MAYBE_FocusTraversal FAILS_FocusTraversal 52#define MAYBE_FocusTraversalOnInterstitial FAILS_FocusTraversalOnInterstitial 53// TODO(suzhe): http://crbug.com/49737 54#define MAYBE_TabsRememberFocusFindInPage FAILS_TabsRememberFocusFindInPage 55#elif defined(OS_WIN) 56#define MAYBE_FocusTraversal FocusTraversal 57#define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial 58#define MAYBE_TabsRememberFocusFindInPage TabsRememberFocusFindInPage 59#endif 60 61namespace { 62 63// The delay waited in some cases where we don't have a notifications for an 64// action we take. 65const int kActionDelayMs = 500; 66 67const char kSimplePage[] = "files/focus/page_with_focus.html"; 68const char kStealFocusPage[] = "files/focus/page_steals_focus.html"; 69const char kTypicalPage[] = "files/focus/typical_page.html"; 70const char kTypicalPageName[] = "typical_page.html"; 71 72class BrowserFocusTest : public InProcessBrowserTest { 73 public: 74 BrowserFocusTest() { 75 set_show_window(true); 76 EnableDOMAutomation(); 77 } 78 79 bool IsViewFocused(ViewID vid) { 80 return ui_test_utils::IsViewFocused(browser(), vid); 81 } 82 83 void ClickOnView(ViewID vid) { 84 ui_test_utils::ClickOnView(browser(), vid); 85 } 86}; 87 88class TestInterstitialPage : public InterstitialPage { 89 public: 90 TestInterstitialPage(TabContents* tab, bool new_navigation, const GURL& url) 91 : InterstitialPage(tab, new_navigation, url) { 92 FilePath file_path; 93 bool r = PathService::Get(chrome::DIR_TEST_DATA, &file_path); 94 EXPECT_TRUE(r); 95 file_path = file_path.AppendASCII("focus"); 96 file_path = file_path.AppendASCII(kTypicalPageName); 97 r = file_util::ReadFileToString(file_path, &html_contents_); 98 EXPECT_TRUE(r); 99 } 100 101 virtual std::string GetHTMLContents() { 102 return html_contents_; 103 } 104 105 // Exposing render_view_host() to be public; it is declared as protected in 106 // the superclass. 107 virtual RenderViewHost* render_view_host() { 108 return InterstitialPage::render_view_host(); 109 } 110 111 bool HasFocus() { 112 return render_view_host()->view()->HasFocus(); 113 } 114 115 protected: 116 virtual void FocusedNodeChanged() { 117 NotificationService::current()->Notify( 118 NotificationType::FOCUS_CHANGED_IN_PAGE, 119 Source<RenderViewHost>(render_view_host()), 120 NotificationService::NoDetails()); 121 } 122 123 private: 124 std::string html_contents_; 125}; 126 127IN_PROC_BROWSER_TEST_F(BrowserFocusTest, ClickingMovesFocus) { 128 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 129#if defined(USE_X11) || defined(OS_MACOSX) 130 // It seems we have to wait a little bit for the widgets to spin up before 131 // we can start clicking on them. 132 MessageLoop::current()->PostDelayedTask(FROM_HERE, 133 new MessageLoop::QuitTask(), 134 kActionDelayMs); 135 ui_test_utils::RunMessageLoop(); 136#endif 137 138 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 139 140 ClickOnView(VIEW_ID_TAB_CONTAINER); 141 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 142 143 ClickOnView(VIEW_ID_LOCATION_BAR); 144 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 145} 146 147IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BrowsersRememberFocus) { 148 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 149 ASSERT_TRUE(test_server()->Start()); 150 151 // First we navigate to our test page. 152 GURL url = test_server()->GetURL(kSimplePage); 153 ui_test_utils::NavigateToURL(browser(), url); 154 155 gfx::NativeWindow window = browser()->window()->GetNativeHandle(); 156 157 // The focus should be on the Tab contents. 158 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 159 // Now hide the window, show it again, the focus should not have changed. 160 ui_test_utils::HideNativeWindow(window); 161 ui_test_utils::ShowAndFocusNativeWindow(window); 162 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 163 164 browser()->FocusLocationBar(); 165 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 166 // Hide the window, show it again, the focus should not have changed. 167 ui_test_utils::HideNativeWindow(window); 168 ui_test_utils::ShowAndFocusNativeWindow(window); 169 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 170 171 // The rest of this test does not make sense on Linux because the behavior 172 // of Activate() is not well defined and can vary by window manager. 173#if defined(OS_WIN) 174 // Open a new browser window. 175 Browser* browser2 = Browser::Create(browser()->profile()); 176 ASSERT_TRUE(browser2); 177 browser2->tabstrip_model()->delegate()->AddBlankTab(true); 178 browser2->window()->Show(); 179 ui_test_utils::NavigateToURL(browser2, url); 180 181 HWND hwnd2 = reinterpret_cast<HWND>(browser2->window()->GetNativeHandle()); 182 BrowserView* browser_view2 = 183 BrowserView::GetBrowserViewForNativeWindow(hwnd2); 184 ASSERT_TRUE(browser_view2); 185 views::FocusManager* focus_manager2 = 186 views::FocusManager::GetFocusManagerForNativeView(hwnd2); 187 ASSERT_TRUE(focus_manager2); 188 EXPECT_EQ(browser_view2->GetTabContentsContainerView(), 189 focus_manager2->GetFocusedView()); 190 191 // Switch to the 1st browser window, focus should still be on the location 192 // bar and the second browser should have nothing focused. 193 browser()->window()->Activate(); 194 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 195 EXPECT_EQ(NULL, focus_manager2->GetFocusedView()); 196 197 // Switch back to the second browser, focus should still be on the page. 198 browser2->window()->Activate(); 199 EXPECT_EQ(NULL, 200 views::FocusManager::GetFocusManagerForNativeView( 201 browser()->window()->GetNativeHandle())->GetFocusedView()); 202 EXPECT_EQ(browser_view2->GetTabContentsContainerView(), 203 focus_manager2->GetFocusedView()); 204 205 // Close the 2nd browser to avoid a DCHECK(). 206 browser_view2->Close(); 207#endif 208} 209 210// Tabs remember focus. 211IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocus) { 212 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 213 ASSERT_TRUE(test_server()->Start()); 214 215 // First we navigate to our test page. 216 GURL url = test_server()->GetURL(kSimplePage); 217 ui_test_utils::NavigateToURL(browser(), url); 218 219 // Create several tabs. 220 for (int i = 0; i < 4; ++i) { 221 Browser::AddTabWithURLParams params(url, PageTransition::TYPED); 222 browser()->AddTabWithURL(¶ms); 223 EXPECT_EQ(browser(), params.target); 224 } 225 226 // Alternate focus for the tab. 227 const bool kFocusPage[3][5] = { 228 { true, true, true, true, false }, 229 { false, false, false, false, false }, 230 { false, true, false, true, false } 231 }; 232 233 for (int i = 1; i < 3; i++) { 234 for (int j = 0; j < 5; j++) { 235 // Activate the tab. 236 browser()->SelectTabContentsAt(j, true); 237 238 // Activate the location bar or the page. 239 if (kFocusPage[i][j]) { 240 browser()->GetTabContentsAt(j)->view()->Focus(); 241 } else { 242 browser()->FocusLocationBar(); 243 } 244 } 245 246 // Now come back to the tab and check the right view is focused. 247 for (int j = 0; j < 5; j++) { 248 // Activate the tab. 249 browser()->SelectTabContentsAt(j, true); 250 251 ViewID vid = kFocusPage[i][j] ? VIEW_ID_TAB_CONTAINER_FOCUS_VIEW : 252 VIEW_ID_LOCATION_BAR; 253 ASSERT_TRUE(IsViewFocused(vid)); 254 } 255 256 browser()->SelectTabContentsAt(0, true); 257 // Try the above, but with ctrl+tab. Since tab normally changes focus, 258 // this has regressed in the past. Loop through several times to be sure. 259 for (int j = 0; j < 15; j++) { 260 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER_FOCUS_VIEW : 261 VIEW_ID_LOCATION_BAR; 262 ASSERT_TRUE(IsViewFocused(vid)); 263 264 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 265 browser(), app::VKEY_TAB, true, false, false, false)); 266 } 267 268 // As above, but with ctrl+shift+tab. 269 browser()->SelectTabContentsAt(4, true); 270 for (int j = 14; j >= 0; --j) { 271 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER_FOCUS_VIEW : 272 VIEW_ID_LOCATION_BAR; 273 ASSERT_TRUE(IsViewFocused(vid)); 274 275 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 276 browser(), app::VKEY_TAB, true, true, false, false)); 277 } 278 } 279} 280 281// Tabs remember focus with find-in-page box. 282IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) { 283 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 284 ASSERT_TRUE(test_server()->Start()); 285 286 // First we navigate to our test page. 287 GURL url = test_server()->GetURL(kSimplePage); 288 ui_test_utils::NavigateToURL(browser(), url); 289 290 browser()->Find(); 291 ui_test_utils::FindInPage(browser()->GetSelectedTabContents(), 292 ASCIIToUTF16("a"), true, false, NULL); 293 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 294 295 // Focus the location bar. 296 browser()->FocusLocationBar(); 297 298 // Create a 2nd tab. 299 Browser::AddTabWithURLParams params(url, PageTransition::TYPED); 300 browser()->AddTabWithURL(¶ms); 301 EXPECT_EQ(browser(), params.target); 302 303 // Focus should be on the recently opened tab page. 304 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 305 306 // Select 1st tab, focus should still be on the location-bar. 307 // (bug http://crbug.com/23296) 308 browser()->SelectTabContentsAt(0, true); 309 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 310 311 // Now open the find box again, switch to another tab and come back, the focus 312 // should return to the find box. 313 browser()->Find(); 314 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 315 browser()->SelectTabContentsAt(1, true); 316 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 317 browser()->SelectTabContentsAt(0, true); 318 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 319} 320 321// Background window does not steal focus. 322IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BackgroundBrowserDontStealFocus) { 323 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 324 ASSERT_TRUE(test_server()->Start()); 325 326 // Open a new browser window. 327 Browser* browser2 = Browser::Create(browser()->profile()); 328 ASSERT_TRUE(browser2); 329 browser2->tabstrip_model()->delegate()->AddBlankTab(true); 330 browser2->window()->Show(); 331 332 Browser* focused_browser = NULL; 333 Browser* unfocused_browser = NULL; 334#if defined(USE_X11) 335 // On X11, calling Activate() is not guaranteed to move focus, so we have 336 // to figure out which browser does have focus. 337 if (browser2->window()->IsActive()) { 338 focused_browser = browser2; 339 unfocused_browser = browser(); 340 } else if (browser()->window()->IsActive()) { 341 focused_browser = browser(); 342 unfocused_browser = browser2; 343 } else { 344 FAIL() << "Could not determine which browser has focus"; 345 } 346#elif defined(OS_WIN) 347 focused_browser = browser(); 348 unfocused_browser = browser2; 349#elif defined(OS_MACOSX) 350 // On Mac, the newly created window always gets the focus. 351 focused_browser = browser2; 352 unfocused_browser = browser(); 353#endif 354 355 GURL steal_focus_url = test_server()->GetURL(kStealFocusPage); 356 ui_test_utils::NavigateToURL(unfocused_browser, steal_focus_url); 357 358 // Activate the first browser. 359 focused_browser->window()->Activate(); 360 361 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( 362 unfocused_browser->GetSelectedTabContents()->render_view_host(), L"", 363 L"stealFocus();")); 364 365 // Make sure the first browser is still active. 366 EXPECT_TRUE(focused_browser->window()->IsActive()); 367} 368 369// Page cannot steal focus when focus is on location bar. 370IN_PROC_BROWSER_TEST_F(BrowserFocusTest, LocationBarLockFocus) { 371 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 372 ASSERT_TRUE(test_server()->Start()); 373 374 // Open the page that steals focus. 375 GURL url = test_server()->GetURL(kStealFocusPage); 376 ui_test_utils::NavigateToURL(browser(), url); 377 378 browser()->FocusLocationBar(); 379 380 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( 381 browser()->GetSelectedTabContents()->render_view_host(), L"", 382 L"stealFocus();")); 383 384 // Make sure the location bar is still focused. 385 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 386} 387 388// Focus traversal on a regular page. 389// Note that this test relies on a notification from the renderer that the 390// focus has changed in the page. The notification in the renderer may change 391// at which point this test would fail (see comment in 392// RenderWidget::didFocus()). 393IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversal) { 394 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 395 ASSERT_TRUE(test_server()->Start()); 396 397 // First we navigate to our test page. 398 GURL url = test_server()->GetURL(kTypicalPage); 399 ui_test_utils::NavigateToURL(browser(), url); 400 401 browser()->FocusLocationBar(); 402 403 const char* kExpElementIDs[] = { 404 "", // Initially no element in the page should be focused 405 // (the location bar is focused). 406 "textEdit", "searchButton", "luckyButton", "googleLink", "gmailLink", 407 "gmapLink" 408 }; 409 410 // Test forward focus traversal. 411 for (int i = 0; i < 3; ++i) { 412 SCOPED_TRACE(StringPrintf("outer loop: %d", i)); 413 // Location bar should be focused. 414 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 415 416 // Now let's press tab to move the focus. 417 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) { 418 SCOPED_TRACE(StringPrintf("inner loop %" PRIuS, j)); 419 // Let's make sure the focus is on the expected element in the page. 420 std::string actual; 421 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 422 browser()->GetSelectedTabContents()->render_view_host(), 423 L"", 424 L"window.domAutomationController.send(getFocusedElement());", 425 &actual)); 426 ASSERT_STREQ(kExpElementIDs[j], actual.c_str()); 427 428 NotificationType::Type notification_type; 429 NotificationSource notification_source = 430 NotificationService::AllSources(); 431 if (j < arraysize(kExpElementIDs) - 1) { 432 notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE; 433 notification_source = Source<RenderViewHost>( 434 browser()->GetSelectedTabContents()->render_view_host()); 435 } else { 436 // On the last tab key press, the focus returns to the browser. 437 notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER; 438 notification_source = Source<Browser>(browser()); 439 } 440 441 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( 442 browser(), app::VKEY_TAB, false, false, false, false, 443 notification_type, notification_source)); 444 } 445 446 // At this point the renderer has sent us a message asking to advance the 447 // focus (as the end of the focus loop was reached in the renderer). 448 // We need to run the message loop to process it. 449 ui_test_utils::RunAllPendingInMessageLoop(); 450 } 451 452 // Now let's try reverse focus traversal. 453 for (int i = 0; i < 3; ++i) { 454 SCOPED_TRACE(StringPrintf("outer loop: %d", i)); 455 // Location bar should be focused. 456 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 457 458 // Now let's press shift-tab to move the focus in reverse. 459 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) { 460 SCOPED_TRACE(StringPrintf("inner loop: %" PRIuS, j)); 461 462 NotificationType::Type notification_type; 463 NotificationSource notification_source = 464 NotificationService::AllSources(); 465 if (j < arraysize(kExpElementIDs) - 1) { 466 notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE; 467 notification_source = Source<RenderViewHost>( 468 browser()->GetSelectedTabContents()->render_view_host()); 469 } else { 470 // On the last tab key press, the focus returns to the browser. 471 notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER; 472 notification_source = Source<Browser>(browser()); 473 } 474 475 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( 476 browser(), app::VKEY_TAB, false, true, false, false, 477 notification_type, notification_source)); 478 479 // Let's make sure the focus is on the expected element in the page. 480 std::string actual; 481 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 482 browser()->GetSelectedTabContents()->render_view_host(), 483 L"", 484 L"window.domAutomationController.send(getFocusedElement());", 485 &actual)); 486 ASSERT_STREQ(kExpElementIDs[6 - j], actual.c_str()); 487 } 488 489 // At this point the renderer has sent us a message asking to advance the 490 // focus (as the end of the focus loop was reached in the renderer). 491 // We need to run the message loop to process it. 492 ui_test_utils::RunAllPendingInMessageLoop(); 493 } 494} 495 496// Focus traversal while an interstitial is showing. 497IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) { 498 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 499 ASSERT_TRUE(test_server()->Start()); 500 501 // First we navigate to our test page. 502 GURL url = test_server()->GetURL(kSimplePage); 503 ui_test_utils::NavigateToURL(browser(), url); 504 505 // Focus should be on the page. 506 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 507 508 // Let's show an interstitial. 509 TestInterstitialPage* interstitial_page = 510 new TestInterstitialPage(browser()->GetSelectedTabContents(), 511 true, GURL("http://interstitial.com")); 512 interstitial_page->Show(); 513 // Give some time for the interstitial to show. 514 MessageLoop::current()->PostDelayedTask(FROM_HERE, 515 new MessageLoop::QuitTask(), 516 1000); 517 ui_test_utils::RunMessageLoop(); 518 519 browser()->FocusLocationBar(); 520 521 const char* kExpElementIDs[] = { 522 "", // Initially no element in the page should be focused 523 // (the location bar is focused). 524 "textEdit", "searchButton", "luckyButton", "googleLink", "gmailLink", 525 "gmapLink" 526 }; 527 528 // Test forward focus traversal. 529 for (int i = 0; i < 2; ++i) { 530 // Location bar should be focused. 531 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 532 533 // Now let's press tab to move the focus. 534 for (size_t j = 0; j < 7; ++j) { 535 // Let's make sure the focus is on the expected element in the page. 536 std::string actual; 537 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 538 interstitial_page->render_view_host(), L"", 539 L"window.domAutomationController.send(getFocusedElement());", 540 &actual)); 541 ASSERT_STREQ(kExpElementIDs[j], actual.c_str()); 542 543 NotificationType::Type notification_type; 544 NotificationSource notification_source = 545 NotificationService::AllSources(); 546 if (j < arraysize(kExpElementIDs) - 1) { 547 notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE; 548 notification_source = Source<RenderViewHost>( 549 interstitial_page->render_view_host()); 550 } else { 551 // On the last tab key press, the focus returns to the browser. 552 notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER; 553 notification_source = Source<Browser>(browser()); 554 } 555 556 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( 557 browser(), app::VKEY_TAB, false, false, false, false, 558 notification_type, notification_source)); 559 } 560 561 // At this point the renderer has sent us a message asking to advance the 562 // focus (as the end of the focus loop was reached in the renderer). 563 // We need to run the message loop to process it. 564 ui_test_utils::RunAllPendingInMessageLoop(); 565 } 566 567 // Now let's try reverse focus traversal. 568 for (int i = 0; i < 2; ++i) { 569 // Location bar should be focused. 570 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 571 572 // Now let's press shift-tab to move the focus in reverse. 573 for (size_t j = 0; j < 7; ++j) { 574 NotificationType::Type notification_type; 575 NotificationSource notification_source = 576 NotificationService::AllSources(); 577 if (j < arraysize(kExpElementIDs) - 1) { 578 notification_type = NotificationType::FOCUS_CHANGED_IN_PAGE; 579 notification_source = Source<RenderViewHost>( 580 interstitial_page->render_view_host()); 581 } else { 582 // On the last tab key press, the focus returns to the browser. 583 notification_type = NotificationType::FOCUS_RETURNED_TO_BROWSER; 584 notification_source = Source<Browser>(browser()); 585 } 586 587 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( 588 browser(), app::VKEY_TAB, false, true, false, false, 589 notification_type, notification_source)); 590 591 // Let's make sure the focus is on the expected element in the page. 592 std::string actual; 593 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 594 interstitial_page->render_view_host(), L"", 595 L"window.domAutomationController.send(getFocusedElement());", 596 &actual)); 597 ASSERT_STREQ(kExpElementIDs[6 - j], actual.c_str()); 598 } 599 600 // At this point the renderer has sent us a message asking to advance the 601 // focus (as the end of the focus loop was reached in the renderer). 602 // We need to run the message loop to process it. 603 ui_test_utils::RunAllPendingInMessageLoop(); 604 } 605} 606 607// Focus stays on page with interstitials. 608IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) { 609 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 610 ASSERT_TRUE(test_server()->Start()); 611 612 // First we navigate to our test page. 613 GURL url = test_server()->GetURL(kSimplePage); 614 ui_test_utils::NavigateToURL(browser(), url); 615 616 // Page should have focus. 617 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 618 EXPECT_TRUE(browser()->GetSelectedTabContents()->render_view_host()->view()-> 619 HasFocus()); 620 621 // Let's show an interstitial. 622 TestInterstitialPage* interstitial_page = 623 new TestInterstitialPage(browser()->GetSelectedTabContents(), 624 true, GURL("http://interstitial.com")); 625 interstitial_page->Show(); 626 // Give some time for the interstitial to show. 627 MessageLoop::current()->PostDelayedTask(FROM_HERE, 628 new MessageLoop::QuitTask(), 629 1000); 630 ui_test_utils::RunMessageLoop(); 631 632 // The interstitial should have focus now. 633 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 634 EXPECT_TRUE(interstitial_page->HasFocus()); 635 636 // Hide the interstitial. 637 interstitial_page->DontProceed(); 638 639 // Focus should be back on the original page. 640 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 641} 642 643// Make sure Find box can request focus, even when it is already open. 644IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) { 645 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 646 ASSERT_TRUE(test_server()->Start()); 647 648 // Open some page (any page that doesn't steal focus). 649 GURL url = test_server()->GetURL(kTypicalPage); 650 ui_test_utils::NavigateToURL(browser(), url); 651 652#if defined(OS_MACOSX) 653 // Press Cmd+F, which will make the Find box open and request focus. 654 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 655 browser(), app::VKEY_F, false, false, false, true)); 656#else 657 // Press Ctrl+F, which will make the Find box open and request focus. 658 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 659 browser(), app::VKEY_F, true, false, false, false)); 660#endif 661 662 // Ideally, we wouldn't sleep here and instead would intercept the 663 // RenderViewHostDelegate::HandleKeyboardEvent() callback. To do that, we 664 // could create a RenderViewHostDelegate wrapper and hook-it up by either: 665 // - creating a factory used to create the delegate 666 // - making the test a private and overwriting the delegate member directly. 667 MessageLoop::current()->PostDelayedTask( 668 FROM_HERE, new MessageLoop::QuitTask(), kActionDelayMs); 669 ui_test_utils::RunMessageLoop(); 670 671 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 672 673 browser()->FocusLocationBar(); 674 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 675 676 // Now press Ctrl+F again and focus should move to the Find box. 677#if defined(OS_MACOSX) 678 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 679 browser(), app::VKEY_F, false, false, false, true)); 680#else 681 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 682 browser(), app::VKEY_F, true, false, false, false)); 683#endif 684 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 685 686 // Set focus to the page. 687 ClickOnView(VIEW_ID_TAB_CONTAINER); 688 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 689 690 // Now press Ctrl+F again and focus should move to the Find box. 691#if defined(OS_MACOSX) 692 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 693 browser(), app::VKEY_F, false, false, false, true)); 694#else 695 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 696 browser(), app::VKEY_F, true, false, false, false)); 697#endif 698 699 // See remark above on why we wait. 700 MessageLoop::current()->PostDelayedTask( 701 FROM_HERE, new MessageLoop::QuitTask(), kActionDelayMs); 702 ui_test_utils::RunMessageLoop(); 703 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 704} 705 706// Makes sure the focus is in the right location when opening the different 707// types of tabs. 708IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) { 709 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 710 711 // Open the history tab, focus should be on the tab contents. 712 browser()->ShowHistoryTab(); 713 ASSERT_NO_FATAL_FAILURE(ui_test_utils::WaitForLoadStop( 714 &browser()->GetSelectedTabContents()->controller())); 715 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 716 717 // Open the new tab, focus should be on the location bar. 718 browser()->NewTab(); 719 ASSERT_NO_FATAL_FAILURE(ui_test_utils::WaitForLoadStop( 720 &browser()->GetSelectedTabContents()->controller())); 721 EXPECT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 722 723 // Open the download tab, focus should be on the tab contents. 724 browser()->ShowDownloadsTab(); 725 ASSERT_NO_FATAL_FAILURE(ui_test_utils::WaitForLoadStop( 726 &browser()->GetSelectedTabContents()->controller())); 727 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 728 729 // Open about:blank, focus should be on the location bar. 730 browser()->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL), 731 PageTransition::LINK); 732 ASSERT_NO_FATAL_FAILURE(ui_test_utils::WaitForLoadStop( 733 &browser()->GetSelectedTabContents()->controller())); 734 EXPECT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 735} 736 737// Tests that focus goes where expected when using reload. 738IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusOnReload) { 739 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 740 ASSERT_TRUE(test_server()->Start()); 741 742 // Open the new tab, reload. 743 browser()->NewTab(); 744 ui_test_utils::RunAllPendingInMessageLoop(); 745 746 browser()->Reload(CURRENT_TAB); 747 ASSERT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser())); 748 // Focus should stay on the location bar. 749 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 750 751 // Open a regular page, focus the location bar, reload. 752 ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage)); 753 browser()->FocusLocationBar(); 754 ASSERT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); 755 browser()->Reload(CURRENT_TAB); 756 ASSERT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser())); 757 758 // Focus should now be on the tab contents. 759 browser()->ShowDownloadsTab(); 760 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 761} 762 763#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && !defined(NDEBUG) 764// Hangy, http://crbug.com/50025. 765#define MAYBE_FocusOnReloadCrashedTab DISABLED_FocusOnReloadCrashedTab 766#else 767#define MAYBE_FocusOnReloadCrashedTab FocusOnReloadCrashedTab 768#endif 769 770// Tests that focus goes where expected when using reload on a crashed tab. 771IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusOnReloadCrashedTab) { 772 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 773 ASSERT_TRUE(test_server()->Start()); 774 775 // Open a regular page, crash, reload. 776 ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage)); 777 ui_test_utils::CrashTab(browser()->GetSelectedTabContents()); 778 browser()->Reload(CURRENT_TAB); 779 ASSERT_TRUE(ui_test_utils::WaitForNavigationInCurrentTab(browser())); 780 781 // Focus should now be on the tab contents. 782 browser()->ShowDownloadsTab(); 783 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); 784} 785 786} // namespace 787