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.
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"
42 #include "base/strings/string_util.h"
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
63 #define MAYBE_FocusTraversal FocusTraversal
64 #define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial
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
72 // Flaky, http://crbug.com/62537.
73 #define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
78 // The delay waited in some cases where we don't have a notifications for an
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() {
94 HWND window
= ::GetForegroundWindow();
96 std::wstring filename
;
97 int len
= ::GetWindowTextLength(window
) + 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
) {
105 int thread_id
= ::GetWindowThreadProcessId(window
, &process_id
);
107 base::ProcessHandle process
;
108 if (base::OpenProcessHandleWithAccess(process_id
,
109 PROCESS_QUERY_LIMITED_INFORMATION
,
111 if (!GetProcessImageFileName(process
, WriteInto(&filename
, MAX_PATH
),
113 int error
= GetLastError();
114 filename
= std::wstring(L
"Unable to read filename for process id '" +
115 base::IntToString16(process_id
) +
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
;
129 // Windows only at the moment.
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());
141 base::MessageLoop::current()->PostDelayedTask(
143 base::Bind(&CheckFocus
, browser
, id
, timeout
),
144 base::TimeDelta::FromMilliseconds(10));
148 class BrowserFocusTest
: public InProcessBrowserTest
{
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(
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
{
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
);
176 file_path
= file_path
.AppendASCII("focus");
177 file_path
= file_path
.AppendASCII(kTypicalPageName
);
178 r
= base::ReadFileToString(file_path
, &html_contents_
);
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();
194 interstitial_page_
->DontProceed();
198 return render_view_host()->GetView()->HasFocus();
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
210 #define MAYBE_ClickingMovesFocus ClickingMovesFocus
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(
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
++) {
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();
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
++) {
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
:
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
:
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());
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.
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
;
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
;
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();
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(),
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
424 #define MAYBE_LocationBarLockFocus LocationBarLockFocus
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(),
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",
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.
484 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
485 browser()->tab_strip_model()->GetActiveWebContents(),
486 "window.domAutomationController.send(getFocusedElement());",
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())),
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())),
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.
558 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
559 browser()->tab_strip_model()->GetActiveWebContents(),
560 "window.domAutomationController.send(getFocusedElement());",
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(
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",
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.
617 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
618 interstitial_page
->render_view_host(),
619 "window.domAutomationController.send(getFocusedElement());",
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());
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());
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.
677 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
678 interstitial_page
->render_view_host(),
679 "window.domAutomationController.send(getFocusedElement());",
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(
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));
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));
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));
760 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
761 browser(), ui::VKEY_F
, true, false, false, false));
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));
774 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
775 browser(), ui::VKEY_F
, true, false, false, false));
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
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
817 #define MAYBE_FocusOnReload FocusOnReload
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());
833 content::RunAllPendingInMessageLoop();
836 content::WindowedNotificationObserver
observer(
837 content::NOTIFICATION_LOAD_STOP
,
838 content::Source
<NavigationController
>(
839 &browser()->tab_strip_model()->GetActiveWebContents()->
841 chrome::Reload(browser(), CURRENT_TAB
);
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()->
858 chrome::Reload(browser(), CURRENT_TAB
);
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()->
882 chrome::Reload(browser(), CURRENT_TAB
);
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/");
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()->
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
946 //#define MAYBE_FocusOnNavigate FocusOnNavigate
949 IN_PROC_BROWSER_TEST_F(BrowserFocusTest
, DISABLED_FocusOnNavigate
) {
951 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
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
));