[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / browser_focus_uitest.cc
blob7c95050983f68d9a17f442efb096f9b3eca720e7
1 // Copyright (c) 2012 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 "base/bind.h"
6 #include "base/file_util.h"
7 #include "base/format_macros.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/browser_tabstrip.h"
17 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/browser/ui/omnibox/location_bar.h"
20 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
21 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
22 #include "chrome/browser/ui/omnibox/omnibox_view.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/browser/ui/view_ids.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "chrome/test/base/interactive_test_utils.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "content/public/browser/interstitial_page.h"
31 #include "content/public/browser/interstitial_page_delegate.h"
32 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/render_view_host.h"
34 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/test/browser_test_utils.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h"
39 #if defined(OS_WIN)
40 #include <windows.h>
41 #include <Psapi.h>
42 #include "base/strings/string_util.h"
43 #endif
45 using content::InterstitialPage;
46 using content::NavigationController;
47 using content::RenderViewHost;
48 using content::WebContents;
50 #if defined(OS_MACOSX)
51 // TODO(suzhe): http://crbug.com/60973
52 #define MAYBE_FocusTraversal DISABLED_FocusTraversal
53 #define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial
54 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
55 // TODO(erg): http://crbug.com/163931
56 #define MAYBE_FocusTraversal DISABLED_FocusTraversal
57 #define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial
58 #elif defined(OS_WIN) || defined(OS_CHROMEOS)
59 // http://crbug.com/109770 and http://crbug.com/62544
60 #define MAYBE_FocusTraversal FocusTraversal
61 #define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial
62 #else
63 #define MAYBE_FocusTraversal FocusTraversal
64 #define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial
65 #endif
67 #if defined(OS_LINUX) || defined(OS_MACOSX)
68 // TODO(jcampan): http://crbug.com/23683 for linux.
69 // TODO(suzhe): http://crbug.com/49737 for mac.
70 #define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
71 #elif defined(OS_WIN)
72 // Flaky, http://crbug.com/62537.
73 #define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
74 #endif
76 namespace {
78 // The delay waited in some cases where we don't have a notifications for an
79 // action we take.
80 const int kActionDelayMs = 500;
82 // Maxiumum time to wait until the focus is moved to expected view.
83 const int kFocusChangeTimeoutMs = 500;
85 const char kSimplePage[] = "/focus/page_with_focus.html";
86 const char kStealFocusPage[] = "/focus/page_steals_focus.html";
87 const char kTypicalPage[] = "/focus/typical_page.html";
88 const char kTypicalPageName[] = "typical_page.html";
90 // Test to make sure Chrome is in the foreground as we start testing. This is
91 // required for tests that synthesize input to the Chrome window.
92 bool ChromeInForeground() {
93 #if defined(OS_WIN)
94 HWND window = ::GetForegroundWindow();
95 std::wstring caption;
96 std::wstring filename;
97 int len = ::GetWindowTextLength(window) + 1;
98 if (len > 1)
99 ::GetWindowText(window, WriteInto(&caption, len), len);
100 bool chrome_window_in_foreground =
101 EndsWith(caption, L" - Google Chrome", true) ||
102 EndsWith(caption, L" - Chromium", true);
103 if (!chrome_window_in_foreground) {
104 DWORD process_id;
105 int thread_id = ::GetWindowThreadProcessId(window, &process_id);
107 base::ProcessHandle process;
108 if (base::OpenProcessHandleWithAccess(process_id,
109 PROCESS_QUERY_LIMITED_INFORMATION,
110 &process)) {
111 if (!GetProcessImageFileName(process, WriteInto(&filename, MAX_PATH),
112 MAX_PATH)) {
113 int error = GetLastError();
114 filename = std::wstring(L"Unable to read filename for process id '" +
115 base::IntToString16(process_id) +
116 L"' (error ") +
117 base::IntToString16(error) + L")";
119 base::CloseProcessHandle(process);
122 EXPECT_TRUE(chrome_window_in_foreground)
123 << "Chrome must be in the foreground when running interactive tests\n"
124 << "Process in foreground: " << filename.c_str() << "\n"
125 << "Window: " << window << "\n"
126 << "Caption: " << caption.c_str();
127 return chrome_window_in_foreground;
128 #else
129 // Windows only at the moment.
130 return true;
131 #endif
134 // Wait the focus change in message loop.
135 void CheckFocus(Browser* browser, ViewID id, const base::Time& timeout) {
136 if (ui_test_utils::IsViewFocused(browser, id) ||
137 base::Time::Now() > timeout) {
138 base::MessageLoop::current()->PostTask(FROM_HERE,
139 base::MessageLoop::QuitClosure());
140 } else {
141 base::MessageLoop::current()->PostDelayedTask(
142 FROM_HERE,
143 base::Bind(&CheckFocus, browser, id, timeout),
144 base::TimeDelta::FromMilliseconds(10));
148 class BrowserFocusTest : public InProcessBrowserTest {
149 public:
150 bool IsViewFocused(ViewID vid) {
151 return ui_test_utils::IsViewFocused(browser(), vid);
154 void ClickOnView(ViewID vid) {
155 ui_test_utils::ClickOnView(browser(), vid);
158 bool WaitForFocusChange(ViewID vid) {
159 const base::Time timeout = base::Time::Now() +
160 base::TimeDelta::FromMilliseconds(kFocusChangeTimeoutMs);
161 base::MessageLoop::current()->PostDelayedTask(
162 FROM_HERE,
163 base::Bind(&CheckFocus, browser(), vid, timeout),
164 base::TimeDelta::FromMilliseconds(100));
165 content::RunMessageLoop();
166 return IsViewFocused(vid);
170 class TestInterstitialPage : public content::InterstitialPageDelegate {
171 public:
172 TestInterstitialPage(WebContents* tab, bool new_navigation, const GURL& url) {
173 base::FilePath file_path;
174 bool r = PathService::Get(chrome::DIR_TEST_DATA, &file_path);
175 EXPECT_TRUE(r);
176 file_path = file_path.AppendASCII("focus");
177 file_path = file_path.AppendASCII(kTypicalPageName);
178 r = base::ReadFileToString(file_path, &html_contents_);
179 EXPECT_TRUE(r);
180 interstitial_page_ = InterstitialPage::Create(
181 tab, new_navigation, url , this);
182 interstitial_page_->Show();
185 virtual std::string GetHTMLContents() OVERRIDE {
186 return html_contents_;
189 RenderViewHost* render_view_host() {
190 return interstitial_page_->GetRenderViewHostForTesting();
193 void DontProceed() {
194 interstitial_page_->DontProceed();
197 bool HasFocus() {
198 return render_view_host()->GetView()->HasFocus();
201 private:
202 std::string html_contents_;
203 InterstitialPage* interstitial_page_; // Owns us.
206 // Flaky on mac. http://crbug.com/67301.
207 #if defined(OS_MACOSX)
208 #define MAYBE_ClickingMovesFocus DISABLED_ClickingMovesFocus
209 #else
210 #define MAYBE_ClickingMovesFocus ClickingMovesFocus
211 #endif
212 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_ClickingMovesFocus) {
213 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
214 #if defined(OS_POSIX)
215 // It seems we have to wait a little bit for the widgets to spin up before
216 // we can start clicking on them.
217 base::MessageLoop::current()->PostDelayedTask(
218 FROM_HERE,
219 base::MessageLoop::QuitClosure(),
220 base::TimeDelta::FromMilliseconds(kActionDelayMs));
221 content::RunMessageLoop();
222 #endif // defined(OS_POSIX)
224 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
226 ClickOnView(VIEW_ID_TAB_CONTAINER);
227 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
229 ClickOnView(VIEW_ID_OMNIBOX);
230 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
233 // Flaky, http://crbug.com/69034.
234 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
235 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
236 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
238 // First we navigate to our test page.
239 GURL url = embedded_test_server()->GetURL(kSimplePage);
240 ui_test_utils::NavigateToURL(browser(), url);
242 gfx::NativeWindow window = browser()->window()->GetNativeWindow();
244 // The focus should be on the Tab contents.
245 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
246 // Now hide the window, show it again, the focus should not have changed.
247 ui_test_utils::HideNativeWindow(window);
248 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
249 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
251 chrome::FocusLocationBar(browser());
252 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
253 // Hide the window, show it again, the focus should not have changed.
254 ui_test_utils::HideNativeWindow(window);
255 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
256 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
259 // Tabs remember focus.
260 // Disabled, http://crbug.com/62542.
261 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabsRememberFocus) {
262 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
263 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
265 // First we navigate to our test page.
266 GURL url = embedded_test_server()->GetURL(kSimplePage);
267 ui_test_utils::NavigateToURL(browser(), url);
269 // Create several tabs.
270 for (int i = 0; i < 4; ++i) {
271 chrome::AddSelectedTabWithURL(browser(), url,
272 content::PAGE_TRANSITION_TYPED);
275 // Alternate focus for the tab.
276 const bool kFocusPage[3][5] = {
277 { true, true, true, true, false },
278 { false, false, false, false, false },
279 { false, true, false, true, false }
282 for (int i = 1; i < 3; i++) {
283 for (int j = 0; j < 5; j++) {
284 // Activate the tab.
285 browser()->tab_strip_model()->ActivateTabAt(j, true);
287 // Activate the location bar or the page.
288 if (kFocusPage[i][j]) {
289 browser()->tab_strip_model()->GetWebContentsAt(j)->Focus();
290 } else {
291 chrome::FocusLocationBar(browser());
295 // Now come back to the tab and check the right view is focused.
296 for (int j = 0; j < 5; j++) {
297 // Activate the tab.
298 browser()->tab_strip_model()->ActivateTabAt(j, true);
300 ViewID vid = kFocusPage[i][j] ? VIEW_ID_TAB_CONTAINER : VIEW_ID_OMNIBOX;
301 ASSERT_TRUE(IsViewFocused(vid));
304 browser()->tab_strip_model()->ActivateTabAt(0, true);
305 // Try the above, but with ctrl+tab. Since tab normally changes focus,
306 // this has regressed in the past. Loop through several times to be sure.
307 for (int j = 0; j < 15; j++) {
308 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
309 VIEW_ID_OMNIBOX;
310 ASSERT_TRUE(IsViewFocused(vid));
312 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
313 browser(), ui::VKEY_TAB, true, false, false, false));
316 // As above, but with ctrl+shift+tab.
317 browser()->tab_strip_model()->ActivateTabAt(4, true);
318 for (int j = 14; j >= 0; --j) {
319 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
320 VIEW_ID_OMNIBOX;
321 ASSERT_TRUE(IsViewFocused(vid));
323 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
324 browser(), ui::VKEY_TAB, true, true, false, false));
329 // Tabs remember focus with find-in-page box.
330 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) {
331 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
332 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
334 // First we navigate to our test page.
335 GURL url = embedded_test_server()->GetURL(kSimplePage);
336 ui_test_utils::NavigateToURL(browser(), url);
338 chrome::Find(browser());
339 ui_test_utils::FindInPage(
340 browser()->tab_strip_model()->GetActiveWebContents(),
341 base::ASCIIToUTF16("a"), true, false, NULL, NULL);
342 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
344 // Focus the location bar.
345 chrome::FocusLocationBar(browser());
347 // Create a 2nd tab.
348 chrome::AddSelectedTabWithURL(browser(), url, content::PAGE_TRANSITION_TYPED);
350 // Focus should be on the recently opened tab page.
351 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
353 // Select 1st tab, focus should still be on the location-bar.
354 // (bug http://crbug.com/23296)
355 browser()->tab_strip_model()->ActivateTabAt(0, true);
356 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
358 // Now open the find box again, switch to another tab and come back, the focus
359 // should return to the find box.
360 chrome::Find(browser());
361 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
362 browser()->tab_strip_model()->ActivateTabAt(1, true);
363 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
364 browser()->tab_strip_model()->ActivateTabAt(0, true);
365 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
368 // Background window does not steal focus.
369 // Flaky, http://crbug.com/62538.
370 IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
371 DISABLED_BackgroundBrowserDontStealFocus) {
372 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
373 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
375 // Open a new browser window.
376 Browser* browser2 =
377 new Browser(Browser::CreateParams(browser()->profile(),
378 browser()->host_desktop_type()));
379 ASSERT_TRUE(browser2);
380 chrome::AddTabAt(browser2, GURL(), -1, true);
381 browser2->window()->Show();
383 Browser* focused_browser = NULL;
384 Browser* unfocused_browser = NULL;
385 #if defined(USE_X11)
386 // On X11, calling Activate() is not guaranteed to move focus, so we have
387 // to figure out which browser does have focus.
388 if (browser2->window()->IsActive()) {
389 focused_browser = browser2;
390 unfocused_browser = browser();
391 } else if (browser()->window()->IsActive()) {
392 focused_browser = browser();
393 unfocused_browser = browser2;
394 } else {
395 FAIL() << "Could not determine which browser has focus";
397 #elif defined(OS_WIN)
398 focused_browser = browser();
399 unfocused_browser = browser2;
400 #elif defined(OS_MACOSX)
401 // On Mac, the newly created window always gets the focus.
402 focused_browser = browser2;
403 unfocused_browser = browser();
404 #endif
406 GURL steal_focus_url = embedded_test_server()->GetURL(kStealFocusPage);
407 ui_test_utils::NavigateToURL(unfocused_browser, steal_focus_url);
409 // Activate the first browser.
410 focused_browser->window()->Activate();
412 ASSERT_TRUE(content::ExecuteScript(
413 unfocused_browser->tab_strip_model()->GetActiveWebContents(),
414 "stealFocus();"));
416 // Make sure the first browser is still active.
417 EXPECT_TRUE(focused_browser->window()->IsActive());
420 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
421 // TODO(erg): http://crbug.com/163931
422 #define MAYBE_LocationBarLockFocus DISABLED_LocationBarLockFocus
423 #else
424 #define MAYBE_LocationBarLockFocus LocationBarLockFocus
425 #endif
427 // Page cannot steal focus when focus is on location bar.
428 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_LocationBarLockFocus) {
429 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
430 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
432 // Open the page that steals focus.
433 GURL url = embedded_test_server()->GetURL(kStealFocusPage);
434 ui_test_utils::NavigateToURL(browser(), url);
436 chrome::FocusLocationBar(browser());
438 ASSERT_TRUE(content::ExecuteScript(
439 browser()->tab_strip_model()->GetActiveWebContents(),
440 "stealFocus();"));
442 // Make sure the location bar is still focused.
443 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
446 // Focus traversal on a regular page.
447 // Note that this test relies on a notification from the renderer that the
448 // focus has changed in the page. The notification in the renderer may change
449 // at which point this test would fail (see comment in
450 // RenderWidget::didFocus()).
451 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversal) {
452 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
453 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
455 // First we navigate to our test page.
456 GURL url = embedded_test_server()->GetURL(kTypicalPage);
457 ui_test_utils::NavigateToURL(browser(), url);
459 chrome::FocusLocationBar(browser());
461 const char* kTextElementID = "textEdit";
462 const char* kExpElementIDs[] = {
463 "", // Initially no element in the page should be focused
464 // (the location bar is focused).
465 kTextElementID, "searchButton", "luckyButton", "googleLink", "gmailLink",
466 "gmapLink"
469 // Test forward focus traversal.
470 for (int i = 0; i < 3; ++i) {
471 SCOPED_TRACE(base::StringPrintf("outer loop: %d", i));
472 // Location bar should be focused.
473 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
475 // Move the caret to the end, otherwise the next Tab key may not move focus.
476 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
477 browser(), ui::VKEY_END, false, false, false, false));
479 // Now let's press tab to move the focus.
480 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
481 SCOPED_TRACE(base::StringPrintf("inner loop %" PRIuS, j));
482 // Let's make sure the focus is on the expected element in the page.
483 std::string actual;
484 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
485 browser()->tab_strip_model()->GetActiveWebContents(),
486 "window.domAutomationController.send(getFocusedElement());",
487 &actual));
488 ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
490 if (j < arraysize(kExpElementIDs) - 1) {
491 // If the next element is the kTextElementID, we expect to be
492 // notified we have switched to an editable node.
493 bool is_editable_node =
494 (strcmp(kTextElementID, kExpElementIDs[j + 1]) == 0);
495 content::Details<bool> details(&is_editable_node);
497 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
498 browser(), ui::VKEY_TAB, false, false, false, false,
499 content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
500 content::NotificationSource(content::Source<RenderViewHost>(
501 browser()->tab_strip_model()->GetActiveWebContents()->
502 GetRenderViewHost())),
503 details));
504 } else {
505 // On the last tab key press, the focus returns to the browser.
506 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
507 browser(), ui::VKEY_TAB, false, false, false, false,
508 chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
509 content::NotificationSource(content::Source<Browser>(browser()))));
513 // At this point the renderer has sent us a message asking to advance the
514 // focus (as the end of the focus loop was reached in the renderer).
515 // We need to run the message loop to process it.
516 content::RunAllPendingInMessageLoop();
519 // Now let's try reverse focus traversal.
520 for (int i = 0; i < 3; ++i) {
521 SCOPED_TRACE(base::StringPrintf("outer loop: %d", i));
522 // Location bar should be focused.
523 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
525 // Move the caret to the end, otherwise the next Tab key may not move focus.
526 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
527 browser(), ui::VKEY_END, false, false, false, false));
529 // Now let's press shift-tab to move the focus in reverse.
530 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
531 SCOPED_TRACE(base::StringPrintf("inner loop: %" PRIuS, j));
532 const char* next_element =
533 kExpElementIDs[arraysize(kExpElementIDs) - 1 - j];
535 if (j < arraysize(kExpElementIDs) - 1) {
536 // If the next element is the kTextElementID, we expect to be
537 // notified we have switched to an editable node.
538 bool is_editable_node = (strcmp(kTextElementID, next_element) == 0);
539 content::Details<bool> details(&is_editable_node);
541 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
542 browser(), ui::VKEY_TAB, false, true, false, false,
543 content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
544 content::NotificationSource(content::Source<RenderViewHost>(
545 browser()->tab_strip_model()->GetActiveWebContents()->
546 GetRenderViewHost())),
547 details));
548 } else {
549 // On the last tab key press, the focus returns to the browser.
550 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
551 browser(), ui::VKEY_TAB, false, true, false, false,
552 chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
553 content::NotificationSource(content::Source<Browser>(browser()))));
556 // Let's make sure the focus is on the expected element in the page.
557 std::string actual;
558 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
559 browser()->tab_strip_model()->GetActiveWebContents(),
560 "window.domAutomationController.send(getFocusedElement());",
561 &actual));
562 ASSERT_STREQ(next_element, actual.c_str());
565 // At this point the renderer has sent us a message asking to advance the
566 // focus (as the end of the focus loop was reached in the renderer).
567 // We need to run the message loop to process it.
568 content::RunAllPendingInMessageLoop();
572 // Focus traversal while an interstitial is showing.
573 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
574 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
575 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
577 // First we navigate to our test page.
578 GURL url = embedded_test_server()->GetURL(kSimplePage);
579 ui_test_utils::NavigateToURL(browser(), url);
581 // Focus should be on the page.
582 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
584 // Let's show an interstitial.
585 TestInterstitialPage* interstitial_page = new TestInterstitialPage(
586 browser()->tab_strip_model()->GetActiveWebContents(),
587 true, GURL("http://interstitial.com"));
588 // Give some time for the interstitial to show.
589 base::MessageLoop::current()->PostDelayedTask(
590 FROM_HERE,
591 base::MessageLoop::QuitClosure(),
592 base::TimeDelta::FromSeconds(1));
593 content::RunMessageLoop();
595 chrome::FocusLocationBar(browser());
597 const char* kExpElementIDs[] = {
598 "", // Initially no element in the page should be focused
599 // (the location bar is focused).
600 "textEdit", "searchButton", "luckyButton", "googleLink", "gmailLink",
601 "gmapLink"
604 // Test forward focus traversal.
605 for (int i = 0; i < 2; ++i) {
606 // Location bar should be focused.
607 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
609 // Move the caret to the end, otherwise the next Tab key may not move focus.
610 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
611 browser(), ui::VKEY_END, false, false, false, false));
613 // Now let's press tab to move the focus.
614 for (size_t j = 0; j < 7; ++j) {
615 // Let's make sure the focus is on the expected element in the page.
616 std::string actual;
617 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
618 interstitial_page->render_view_host(),
619 "window.domAutomationController.send(getFocusedElement());",
620 &actual));
621 ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
623 int notification_type;
624 content::NotificationSource notification_source =
625 content::NotificationService::AllSources();
626 if (j < arraysize(kExpElementIDs) - 1) {
627 notification_type = content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE;
628 notification_source = content::Source<RenderViewHost>(
629 interstitial_page->render_view_host());
630 } else {
631 // On the last tab key press, the focus returns to the browser.
632 notification_type = chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER;
633 notification_source = content::Source<Browser>(browser());
636 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
637 browser(), ui::VKEY_TAB, false, false, false, false,
638 notification_type, notification_source));
641 // At this point the renderer has sent us a message asking to advance the
642 // focus (as the end of the focus loop was reached in the renderer).
643 // We need to run the message loop to process it.
644 content::RunAllPendingInMessageLoop();
647 // Now let's try reverse focus traversal.
648 for (int i = 0; i < 2; ++i) {
649 // Location bar should be focused.
650 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
652 // Move the caret to the end, otherwise the next Tab key may not move focus.
653 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
654 browser(), ui::VKEY_END, false, false, false, false));
656 // Now let's press shift-tab to move the focus in reverse.
657 for (size_t j = 0; j < 7; ++j) {
658 int notification_type;
659 content::NotificationSource notification_source =
660 content::NotificationService::AllSources();
661 if (j < arraysize(kExpElementIDs) - 1) {
662 notification_type = content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE;
663 notification_source = content::Source<RenderViewHost>(
664 interstitial_page->render_view_host());
665 } else {
666 // On the last tab key press, the focus returns to the browser.
667 notification_type = chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER;
668 notification_source = content::Source<Browser>(browser());
671 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
672 browser(), ui::VKEY_TAB, false, true, false, false,
673 notification_type, notification_source));
675 // Let's make sure the focus is on the expected element in the page.
676 std::string actual;
677 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
678 interstitial_page->render_view_host(),
679 "window.domAutomationController.send(getFocusedElement());",
680 &actual));
681 ASSERT_STREQ(kExpElementIDs[6 - j], actual.c_str());
684 // At this point the renderer has sent us a message asking to advance the
685 // focus (as the end of the focus loop was reached in the renderer).
686 // We need to run the message loop to process it.
687 content::RunAllPendingInMessageLoop();
691 // Focus stays on page with interstitials.
692 // http://crbug.com/81451
693 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_InterstitialFocus) {
694 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
695 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
697 // First we navigate to our test page.
698 GURL url = embedded_test_server()->GetURL(kSimplePage);
699 ui_test_utils::NavigateToURL(browser(), url);
701 // Page should have focus.
702 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
703 EXPECT_TRUE(browser()->tab_strip_model()->GetActiveWebContents()->
704 GetRenderViewHost()->GetView()->HasFocus());
706 // Let's show an interstitial.
707 TestInterstitialPage* interstitial_page = new TestInterstitialPage(
708 browser()->tab_strip_model()->GetActiveWebContents(),
709 true, GURL("http://interstitial.com"));
710 // Give some time for the interstitial to show.
711 base::MessageLoop::current()->PostDelayedTask(
712 FROM_HERE,
713 base::MessageLoop::QuitClosure(),
714 base::TimeDelta::FromSeconds(1));
715 content::RunMessageLoop();
717 // The interstitial should have focus now.
718 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
719 EXPECT_TRUE(interstitial_page->HasFocus());
721 // Hide the interstitial.
722 interstitial_page->DontProceed();
724 // Focus should be back on the original page.
725 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
728 // Make sure Find box can request focus, even when it is already open.
729 // Disabled due to flakiness. http://crbug.com/67301.
730 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FindFocusTest) {
731 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
732 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
734 // Open some page (any page that doesn't steal focus).
735 GURL url = embedded_test_server()->GetURL(kTypicalPage);
736 ui_test_utils::NavigateToURL(browser(), url);
738 EXPECT_TRUE(ChromeInForeground());
740 #if defined(OS_MACOSX)
741 // Press Cmd+F, which will make the Find box open and request focus.
742 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
743 browser(), ui::VKEY_F, false, false, false, true));
744 #else
745 // Press Ctrl+F, which will make the Find box open and request focus.
746 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
747 browser(), ui::VKEY_F, true, false, false, false));
748 #endif
750 ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
752 chrome::FocusLocationBar(browser());
753 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
755 // Now press Ctrl+F again and focus should move to the Find box.
756 #if defined(OS_MACOSX)
757 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
758 browser(), ui::VKEY_F, false, false, false, true));
759 #else
760 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
761 browser(), ui::VKEY_F, true, false, false, false));
762 #endif
763 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
765 // Set focus to the page.
766 ClickOnView(VIEW_ID_TAB_CONTAINER);
767 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
769 // Now press Ctrl+F again and focus should move to the Find box.
770 #if defined(OS_MACOSX)
771 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
772 browser(), ui::VKEY_F, false, false, false, true));
773 #else
774 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
775 browser(), ui::VKEY_F, true, false, false, false));
776 #endif
778 ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
781 // Makes sure the focus is in the right location when opening the different
782 // types of tabs.
783 // Flaky, http://crbug.com/62539.
784 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabInitialFocus) {
785 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
787 // Open the history tab, focus should be on the tab contents.
788 chrome::ShowHistory(browser());
789 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
790 browser()->tab_strip_model()->GetActiveWebContents()));
791 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
793 // Open the new tab, focus should be on the location bar.
794 chrome::NewTab(browser());
795 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
796 browser()->tab_strip_model()->GetActiveWebContents()));
797 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
799 // Open the download tab, focus should be on the tab contents.
800 chrome::ShowDownloads(browser());
801 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
802 browser()->tab_strip_model()->GetActiveWebContents()));
803 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
805 // Open about:blank, focus should be on the location bar.
806 chrome::AddSelectedTabWithURL(browser(), GURL(content::kAboutBlankURL),
807 content::PAGE_TRANSITION_LINK);
808 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
809 browser()->tab_strip_model()->GetActiveWebContents()));
810 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
813 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
814 // TODO(erg): http://crbug.com/163931
815 #define MAYBE_FocusOnReload DISABLED_FocusOnReload
816 #else
817 #define MAYBE_FocusOnReload FocusOnReload
818 #endif
820 // Tests that focus goes where expected when using reload.
821 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusOnReload) {
822 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
823 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
825 // Open the new tab, reload.
827 content::WindowedNotificationObserver observer(
828 content::NOTIFICATION_LOAD_STOP,
829 content::NotificationService::AllSources());
830 chrome::NewTab(browser());
831 observer.Wait();
833 content::RunAllPendingInMessageLoop();
836 content::WindowedNotificationObserver observer(
837 content::NOTIFICATION_LOAD_STOP,
838 content::Source<NavigationController>(
839 &browser()->tab_strip_model()->GetActiveWebContents()->
840 GetController()));
841 chrome::Reload(browser(), CURRENT_TAB);
842 observer.Wait();
844 // Focus should stay on the location bar.
845 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
847 // Open a regular page, focus the location bar, reload.
848 ui_test_utils::NavigateToURL(browser(),
849 embedded_test_server()->GetURL(kSimplePage));
850 chrome::FocusLocationBar(browser());
851 ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
853 content::WindowedNotificationObserver observer(
854 content::NOTIFICATION_LOAD_STOP,
855 content::Source<NavigationController>(
856 &browser()->tab_strip_model()->GetActiveWebContents()->
857 GetController()));
858 chrome::Reload(browser(), CURRENT_TAB);
859 observer.Wait();
862 // Focus should now be on the tab contents.
863 chrome::ShowDownloads(browser());
864 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
867 // Tests that focus goes where expected when using reload on a crashed tab.
868 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnReloadCrashedTab) {
869 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
870 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
872 // Open a regular page, crash, reload.
873 ui_test_utils::NavigateToURL(browser(),
874 embedded_test_server()->GetURL(kSimplePage));
875 content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
877 content::WindowedNotificationObserver observer(
878 content::NOTIFICATION_LOAD_STOP,
879 content::Source<NavigationController>(
880 &browser()->tab_strip_model()->GetActiveWebContents()->
881 GetController()));
882 chrome::Reload(browser(), CURRENT_TAB);
883 observer.Wait();
886 // Focus should now be on the tab contents.
887 chrome::ShowDownloads(browser());
888 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
891 // Tests that focus goes to frame after crashed tab.
892 // TODO(shrikant): Find out where the focus should be deterministically.
893 // Currently focused_view after crash seem to be non null in debug mode
894 // (invalidated pointer 0xcccccc).
895 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusAfterCrashedTab) {
896 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
897 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
899 content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
901 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
904 // Tests that when a new tab is opened from the omnibox, the focus is moved from
905 // the omnibox for the current tab.
906 IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
907 NavigateFromOmniboxIntoNewTab) {
908 GURL url("http://www.google.com/");
909 GURL url2("http://maps.google.com/");
911 // Navigate to url.
912 chrome::NavigateParams p(browser(), url, content::PAGE_TRANSITION_LINK);
913 p.window_action = chrome::NavigateParams::SHOW_WINDOW;
914 p.disposition = CURRENT_TAB;
915 chrome::Navigate(&p);
917 // Focus the omnibox.
918 chrome::FocusLocationBar(browser());
920 OmniboxEditController* controller =
921 browser()->window()->GetLocationBar()->GetOmniboxView()->model()->
922 controller();
924 // Simulate an alt-enter.
925 controller->OnAutocompleteAccept(url2, NEW_FOREGROUND_TAB,
926 content::PAGE_TRANSITION_TYPED);
928 // Make sure the second tab is selected.
929 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
931 // The tab contents should have the focus in the second tab.
932 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
934 // Go back to the first tab. The focus should not be in the omnibox.
935 chrome::SelectPreviousTab(browser());
936 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
937 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
940 // This functionality is currently broken. http://crbug.com/304865.
942 //#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
943 //// TODO(erg): http://crbug.com/163931
944 //#define MAYBE_FocusOnNavigate DISABLED_FocusOnNavigate
945 //#else
946 //#define MAYBE_FocusOnNavigate FocusOnNavigate
947 //#endif
949 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnNavigate) {
950 // Needed on Mac.
951 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
952 // Load the NTP.
953 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
954 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
956 // Navigate to another page.
957 const base::FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html");
958 GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
959 base::FilePath::kCurrentDirectory), base::FilePath(kEmptyFile)));
960 ui_test_utils::NavigateToURL(browser(), file_url);
962 ClickOnView(VIEW_ID_TAB_CONTAINER);
964 // Navigate back. Should focus the location bar.
966 content::WindowedNotificationObserver back_nav_observer(
967 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
968 content::NotificationService::AllSources());
969 chrome::GoBack(browser(), CURRENT_TAB);
970 back_nav_observer.Wait();
973 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
975 // Navigate forward. Shouldn't focus the location bar.
976 ClickOnView(VIEW_ID_TAB_CONTAINER);
978 content::WindowedNotificationObserver forward_nav_observer(
979 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
980 content::NotificationService::AllSources());
981 chrome::GoForward(browser(), CURRENT_TAB);
982 forward_nav_observer.Wait();
985 EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
988 } // namespace