blob: 1a4fb905f2ded64910c3d37a811332e7fc1f81b8 [file] [log] [blame]
[email protected]a9c060ca2012-01-05 20:43:411// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]d9fde8d2009-10-08 19:59:305#include "build/build_config.h"
6
[email protected]a9c060ca2012-01-05 20:43:417#include "base/bind.h"
[email protected]3985ba82010-07-29 21:44:128#include "base/file_util.h"
[email protected]f07d7bf2010-04-06 08:02:429#include "base/format_macros.h"
[email protected]8bcdec92009-02-25 16:15:1810#include "base/message_loop.h"
[email protected]3985ba82010-07-29 21:44:1211#include "base/path_service.h"
[email protected]a711df102010-12-14 09:47:0312#include "base/string_number_conversions.h"
[email protected]477ae052011-11-18 23:53:5713#include "base/stringprintf.h"
[email protected]be1ce6a72010-08-03 14:35:2214#include "base/utf_string_conversions.h"
[email protected]7b5dc002010-11-16 23:08:1015#include "chrome/browser/ui/browser.h"
[email protected]a37d4b02012-06-25 21:56:1016#include "chrome/browser/ui/browser_commands.h"
[email protected]52877dbc62012-06-29 22:22:0317#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]00070c732011-04-09 15:31:3318#include "chrome/browser/ui/browser_window.h"
[email protected]5d9cace72012-06-21 16:07:1219#include "chrome/browser/ui/chrome_pages.h"
[email protected]871dc682012-06-11 19:35:3320#include "chrome/browser/ui/tab_contents/tab_contents.h"
[email protected]b56e2e32012-05-11 21:18:0421#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]6a3ec2312010-12-02 19:30:1922#include "chrome/browser/ui/view_ids.h"
[email protected]432115822011-07-10 15:52:2723#include "chrome/common/chrome_notification_types.h"
[email protected]9e0c83a2009-05-06 19:44:3724#include "chrome/common/chrome_paths.h"
[email protected]cecc93a2010-10-05 15:58:5525#include "chrome/common/url_constants.h"
[email protected]af44e7fb2011-07-29 18:32:3226#include "chrome/test/base/in_process_browser_test.h"
[email protected]477ae052011-11-18 23:53:5727#include "chrome/test/base/ui_test_utils.h"
[email protected]cadaec52012-02-08 21:53:1328#include "content/public/browser/interstitial_page.h"
[email protected]85f0a572012-02-07 22:20:1329#include "content/public/browser/interstitial_page_delegate.h"
[email protected]477ae052011-11-18 23:53:5730#include "content/public/browser/notification_service.h"
[email protected]9c1662b2012-03-06 15:44:3331#include "content/public/browser/render_view_host.h"
[email protected]5626b0892012-02-20 14:46:5832#include "content/public/browser/render_widget_host_view.h"
[email protected]6acde6352012-01-04 16:52:2033#include "content/public/browser/web_contents.h"
[email protected]8643e6d2012-01-18 20:26:1034#include "content/public/browser/web_contents_view.h"
[email protected]7d478cb2012-07-24 17:19:4235#include "content/public/test/browser_test_utils.h"
[email protected]3985ba82010-07-29 21:44:1236#include "net/test/test_server.h"
[email protected]853300a82010-07-27 21:17:5737
38#if defined(TOOLKIT_VIEWS) || defined(OS_WIN)
[email protected]477ae052011-11-18 23:53:5739#include "ui/views/focus/focus_manager.h"
[email protected]5025f862011-11-30 23:35:2040#include "ui/views/view.h"
[email protected]853300a82010-07-27 21:17:5741#endif
initial.commit09911bf2008-07-26 23:55:2942
[email protected]134c47b92009-08-19 03:33:4443#if defined(TOOLKIT_VIEWS)
[email protected]9e790bd2011-01-10 23:48:5444#include "chrome/browser/ui/views/frame/browser_view.h"
[email protected]134c47b92009-08-19 03:33:4445#endif
46
[email protected]a711df102010-12-14 09:47:0347#if defined(OS_WIN)
[email protected]a711df102010-12-14 09:47:0348#include <Psapi.h>
[email protected]93270d002011-01-19 22:32:5949#include <windows.h>
[email protected]1870d5cf2011-05-12 01:55:4050#include "base/string_util.h"
[email protected]a711df102010-12-14 09:47:0351#endif
52
[email protected]cadaec52012-02-08 21:53:1353using content::InterstitialPage;
[email protected]c5eed492012-01-04 17:07:5054using content::NavigationController;
[email protected]eaabba22012-03-07 15:02:1155using content::RenderViewHost;
[email protected]4b19ea52012-01-02 20:15:2556using content::WebContents;
57
[email protected]3a3cf4d2011-12-09 00:39:3558#if defined(OS_MACOSX)
59// TODO(suzhe): http://crbug.com/60973
[email protected]a5eb2d672010-10-22 07:24:4860#define MAYBE_FocusTraversal DISABLED_FocusTraversal
61#define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial
[email protected]871153922012-01-10 20:13:4862#elif defined(OS_WIN)
63// http://crbug.com/109770
[email protected]2f2bf1172012-01-10 22:17:1864#define MAYBE_FocusTraversal FocusTraversal
[email protected]871153922012-01-10 20:13:4865#define MAYBE_FocusTraversalOnInterstitial DISABLED_FocusTraversalOnInterstitial
[email protected]3a3cf4d2011-12-09 00:39:3566#else
67#define MAYBE_FocusTraversal FocusTraversal
68#define MAYBE_FocusTraversalOnInterstitial FocusTraversalOnInterstitial
69#endif
70
71#if defined(OS_LINUX) || defined(OS_MACOSX)
72// TODO(jcampan): http://crbug.com/23683 for linux.
73// TODO(suzhe): http://crbug.com/49737 for mac.
[email protected]e00ccc92012-11-01 17:32:3074#define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
[email protected]853300a82010-07-27 21:17:5775#elif defined(OS_WIN)
[email protected]c92928672010-11-09 18:31:0776// Flaky, http://crbug.com/62537.
[email protected]4d2451652012-02-14 23:54:2677#define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
[email protected]fc2e0872009-08-21 22:14:4178#endif
79
initial.commit09911bf2008-07-26 23:55:2980namespace {
81
[email protected]8bcdec92009-02-25 16:15:1882// The delay waited in some cases where we don't have a notifications for an
83// action we take.
initial.commit09911bf2008-07-26 23:55:2984const int kActionDelayMs = 500;
85
[email protected]a9c060ca2012-01-05 20:43:4186// Maxiumum time to wait until the focus is moved to expected view.
87const int kFocusChangeTimeoutMs = 500;
88
[email protected]f72a1cc2010-04-30 07:17:3089const char kSimplePage[] = "files/focus/page_with_focus.html";
90const char kStealFocusPage[] = "files/focus/page_steals_focus.html";
91const char kTypicalPage[] = "files/focus/typical_page.html";
[email protected]b65de8b92009-09-14 19:36:3192const char kTypicalPageName[] = "typical_page.html";
initial.commit09911bf2008-07-26 23:55:2993
[email protected]a711df102010-12-14 09:47:0394// Test to make sure Chrome is in the foreground as we start testing. This is
95// required for tests that synthesize input to the Chrome window.
96bool ChromeInForeground() {
97#if defined(OS_WIN)
98 HWND window = ::GetForegroundWindow();
99 std::wstring caption;
100 std::wstring filename;
101 int len = ::GetWindowTextLength(window) + 1;
[email protected]fdce4782011-11-29 20:06:18102 if (len > 1)
103 ::GetWindowText(window, WriteInto(&caption, len), len);
[email protected]a711df102010-12-14 09:47:03104 bool chrome_window_in_foreground =
105 EndsWith(caption, L" - Google Chrome", true) ||
106 EndsWith(caption, L" - Chromium", true);
107 if (!chrome_window_in_foreground) {
108 DWORD process_id;
109 int thread_id = ::GetWindowThreadProcessId(window, &process_id);
110
111 base::ProcessHandle process;
112 if (base::OpenProcessHandleWithAccess(process_id,
113 PROCESS_QUERY_LIMITED_INFORMATION,
114 &process)) {
[email protected]fdce4782011-11-29 20:06:18115 if (!GetProcessImageFileName(process, WriteInto(&filename, MAX_PATH),
116 MAX_PATH)) {
[email protected]a711df102010-12-14 09:47:03117 int error = GetLastError();
118 filename = std::wstring(L"Unable to read filename for process id '" +
119 base::IntToString16(process_id) +
120 L"' (error ") +
121 base::IntToString16(error) + L")";
122 }
123 base::CloseProcessHandle(process);
124 }
125 }
126 EXPECT_TRUE(chrome_window_in_foreground)
127 << "Chrome must be in the foreground when running interactive tests\n"
128 << "Process in foreground: " << filename.c_str() << "\n"
129 << "Window: " << window << "\n"
130 << "Caption: " << caption.c_str();
131 return chrome_window_in_foreground;
132#else
133 // Windows only at the moment.
134 return true;
135#endif
136}
137
[email protected]a9c060ca2012-01-05 20:43:41138// Wait the focus change in message loop.
139void CheckFocus(Browser* browser, ViewID id, const base::Time& timeout) {
140 if (ui_test_utils::IsViewFocused(browser, id) ||
141 base::Time::Now() > timeout) {
142 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
143 } else {
144 MessageLoop::current()->PostDelayedTask(
145 FROM_HERE,
146 base::Bind(&CheckFocus, browser, id, timeout),
[email protected]7e560102012-03-08 20:58:42147 base::TimeDelta::FromMilliseconds(10));
[email protected]a9c060ca2012-01-05 20:43:41148 }
149};
150
[email protected]8bcdec92009-02-25 16:15:18151class BrowserFocusTest : public InProcessBrowserTest {
initial.commit09911bf2008-07-26 23:55:29152 public:
[email protected]0b8fa8b2011-12-07 00:54:52153 BrowserFocusTest() :
154#if defined(USE_AURA)
155 location_bar_focus_view_id_(VIEW_ID_OMNIBOX)
156#else
157 location_bar_focus_view_id_(VIEW_ID_LOCATION_BAR)
158#endif
[email protected]90ca44272012-07-18 18:15:48159 {}
[email protected]b9821882009-08-17 22:25:17160
[email protected]21abcc742009-10-23 02:52:06161 bool IsViewFocused(ViewID vid) {
162 return ui_test_utils::IsViewFocused(browser(), vid);
[email protected]b9821882009-08-17 22:25:17163 }
164
[email protected]fc2e0872009-08-21 22:14:41165 void ClickOnView(ViewID vid) {
[email protected]21abcc742009-10-23 02:52:06166 ui_test_utils::ClickOnView(browser(), vid);
[email protected]fc2e0872009-08-21 22:14:41167 }
[email protected]0b8fa8b2011-12-07 00:54:52168
[email protected]a9c060ca2012-01-05 20:43:41169 bool WaitForFocusChange(ViewID vid) {
170 const base::Time timeout = base::Time::Now() +
171 base::TimeDelta::FromMilliseconds(kFocusChangeTimeoutMs);
172 MessageLoop::current()->PostDelayedTask(
173 FROM_HERE,
174 base::Bind(&CheckFocus, browser(), vid, timeout),
[email protected]7e560102012-03-08 20:58:42175 base::TimeDelta::FromMilliseconds(100));
[email protected]729eb632012-07-26 04:45:26176 content::RunMessageLoop();
[email protected]a9c060ca2012-01-05 20:43:41177 return IsViewFocused(vid);
178 }
179
[email protected]0b8fa8b2011-12-07 00:54:52180 ViewID location_bar_focus_view_id_;
initial.commit09911bf2008-07-26 23:55:29181};
182
[email protected]85f0a572012-02-07 22:20:13183class TestInterstitialPage : public content::InterstitialPageDelegate {
[email protected]9e0c83a2009-05-06 19:44:37184 public:
[email protected]85f0a572012-02-07 22:20:13185 TestInterstitialPage(WebContents* tab, bool new_navigation, const GURL& url) {
[email protected]b65de8b92009-09-14 19:36:31186 FilePath file_path;
[email protected]9e0c83a2009-05-06 19:44:37187 bool r = PathService::Get(chrome::DIR_TEST_DATA, &file_path);
188 EXPECT_TRUE(r);
[email protected]b65de8b92009-09-14 19:36:31189 file_path = file_path.AppendASCII("focus");
190 file_path = file_path.AppendASCII(kTypicalPageName);
[email protected]9e0c83a2009-05-06 19:44:37191 r = file_util::ReadFileToString(file_path, &html_contents_);
192 EXPECT_TRUE(r);
[email protected]85f0a572012-02-07 22:20:13193 interstitial_page_ = InterstitialPage::Create(
194 tab, new_navigation, url , this);
195 interstitial_page_->Show();
[email protected]9e0c83a2009-05-06 19:44:37196 }
197
198 virtual std::string GetHTMLContents() {
199 return html_contents_;
200 }
201
[email protected]85f0a572012-02-07 22:20:13202 RenderViewHost* render_view_host() {
[email protected]cadaec52012-02-08 21:53:13203 return interstitial_page_->GetRenderViewHostForTesting();
[email protected]9e0c83a2009-05-06 19:44:37204 }
205
[email protected]85f0a572012-02-07 22:20:13206 void DontProceed() {
207 interstitial_page_->DontProceed();
[email protected]4e85c112011-01-26 22:27:21208 }
209
[email protected]9e0c83a2009-05-06 19:44:37210 bool HasFocus() {
[email protected]9f76c1e2012-03-05 15:15:58211 return render_view_host()->GetView()->HasFocus();
[email protected]9e0c83a2009-05-06 19:44:37212 }
213
214 private:
215 std::string html_contents_;
[email protected]85f0a572012-02-07 22:20:13216 InterstitialPage* interstitial_page_; // Owns us.
[email protected]9e0c83a2009-05-06 19:44:37217};
[email protected]b9821882009-08-17 22:25:17218
[email protected]c39e233d2012-05-18 13:24:12219// Flaky on mac. http://crbug.com/67301.
220#if defined(OS_MACOSX)
[email protected]839e0802012-05-18 14:45:23221#define MAYBE_ClickingMovesFocus DISABLED_ClickingMovesFocus
[email protected]c39e233d2012-05-18 13:24:12222#else
[email protected]839e0802012-05-18 14:45:23223#define MAYBE_ClickingMovesFocus ClickingMovesFocus
[email protected]c39e233d2012-05-18 13:24:12224#endif
225IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_ClickingMovesFocus) {
[email protected]a6e602f2010-09-28 22:28:30226 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]0ff0ff32010-12-21 19:34:42227#if defined(OS_POSIX)
[email protected]fc2e0872009-08-21 22:14:41228 // It seems we have to wait a little bit for the widgets to spin up before
229 // we can start clicking on them.
[email protected]7e560102012-03-08 20:58:42230 MessageLoop::current()->PostDelayedTask(
231 FROM_HERE,
232 MessageLoop::QuitClosure(),
233 base::TimeDelta::FromMilliseconds(kActionDelayMs));
[email protected]729eb632012-07-26 04:45:26234 content::RunMessageLoop();
[email protected]0ff0ff32010-12-21 19:34:42235#endif // defined(OS_POSIX)
[email protected]fc2e0872009-08-21 22:14:41236
[email protected]0b8fa8b2011-12-07 00:54:52237 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]186f13f2009-08-19 20:34:00238
[email protected]fc2e0872009-08-21 22:14:41239 ClickOnView(VIEW_ID_TAB_CONTAINER);
[email protected]f2159ba2012-04-17 19:13:21240 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]186f13f2009-08-19 20:34:00241
[email protected]fc2e0872009-08-21 22:14:41242 ClickOnView(VIEW_ID_LOCATION_BAR);
[email protected]0b8fa8b2011-12-07 00:54:52243 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]186f13f2009-08-19 20:34:00244}
[email protected]186f13f2009-08-19 20:34:00245
[email protected]320948e02011-01-10 08:21:12246// Flaky, http://crbug.com/69034.
[email protected]4d2451652012-02-14 23:54:26247IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
[email protected]a6e602f2010-09-28 22:28:30248 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11249 ASSERT_TRUE(test_server()->Start());
initial.commit09911bf2008-07-26 23:55:29250
251 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11252 GURL url = test_server()->GetURL(kSimplePage);
[email protected]8bcdec92009-02-25 16:15:18253 ui_test_utils::NavigateToURL(browser(), url);
initial.commit09911bf2008-07-26 23:55:29254
[email protected]90556dd2012-06-07 20:26:18255 gfx::NativeWindow window = browser()->window()->GetNativeWindow();
[email protected]186f13f2009-08-19 20:34:00256
initial.commit09911bf2008-07-26 23:55:29257 // The focus should be on the Tab contents.
[email protected]f2159ba2012-04-17 19:13:21258 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
initial.commit09911bf2008-07-26 23:55:29259 // Now hide the window, show it again, the focus should not have changed.
[email protected]853300a82010-07-27 21:17:57260 ui_test_utils::HideNativeWindow(window);
[email protected]7807088c2011-11-09 15:16:29261 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
[email protected]f2159ba2012-04-17 19:13:21262 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
initial.commit09911bf2008-07-26 23:55:29263
[email protected]a37d4b02012-06-25 21:56:10264 chrome::FocusLocationBar(browser());
[email protected]0b8fa8b2011-12-07 00:54:52265 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
initial.commit09911bf2008-07-26 23:55:29266 // Hide the window, show it again, the focus should not have changed.
[email protected]853300a82010-07-27 21:17:57267 ui_test_utils::HideNativeWindow(window);
[email protected]7807088c2011-11-09 15:16:29268 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
[email protected]0b8fa8b2011-12-07 00:54:52269 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
initial.commit09911bf2008-07-26 23:55:29270
[email protected]186f13f2009-08-19 20:34:00271 // The rest of this test does not make sense on Linux because the behavior
272 // of Activate() is not well defined and can vary by window manager.
273#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29274 // Open a new browser window.
[email protected]a4fe67012012-07-25 20:14:29275 Browser* browser2 = new Browser(Browser::CreateParams(browser()->profile()));
[email protected]8bcdec92009-02-25 16:15:18276 ASSERT_TRUE(browser2);
[email protected]686221c2012-11-08 07:30:10277 chrome::AddBlankTabAt(browser2, -1, true);
[email protected]8bcdec92009-02-25 16:15:18278 browser2->window()->Show();
279 ui_test_utils::NavigateToURL(browser2, url);
initial.commit09911bf2008-07-26 23:55:29280
[email protected]90556dd2012-06-07 20:26:18281 gfx::NativeWindow window2 = browser2->window()->GetNativeWindow();
[email protected]4a507a62009-05-28 00:10:00282 BrowserView* browser_view2 =
[email protected]075b204c2011-09-30 19:02:16283 BrowserView::GetBrowserViewForBrowser(browser2);
[email protected]8bcdec92009-02-25 16:15:18284 ASSERT_TRUE(browser_view2);
[email protected]0aaa5282011-10-26 18:54:50285 const views::Widget* widget2 =
286 views::Widget::GetWidgetForNativeWindow(window2);
[email protected]0c966682011-08-02 18:22:10287 ASSERT_TRUE(widget2);
[email protected]0aaa5282011-10-26 18:54:50288 const views::FocusManager* focus_manager2 = widget2->GetFocusManager();
[email protected]8bcdec92009-02-25 16:15:18289 ASSERT_TRUE(focus_manager2);
[email protected]7e383692009-06-12 19:14:54290 EXPECT_EQ(browser_view2->GetTabContentsContainerView(),
[email protected]610d36a2009-05-22 23:00:38291 focus_manager2->GetFocusedView());
initial.commit09911bf2008-07-26 23:55:29292
293 // Switch to the 1st browser window, focus should still be on the location
294 // bar and the second browser should have nothing focused.
[email protected]8bcdec92009-02-25 16:15:18295 browser()->window()->Activate();
[email protected]0b8fa8b2011-12-07 00:54:52296 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]8bcdec92009-02-25 16:15:18297 EXPECT_EQ(NULL, focus_manager2->GetFocusedView());
initial.commit09911bf2008-07-26 23:55:29298
299 // Switch back to the second browser, focus should still be on the page.
[email protected]8bcdec92009-02-25 16:15:18300 browser2->window()->Activate();
[email protected]0c966682011-08-02 18:22:10301 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
302 ASSERT_TRUE(widget);
303 EXPECT_EQ(NULL, widget->GetFocusManager()->GetFocusedView());
[email protected]7e383692009-06-12 19:14:54304 EXPECT_EQ(browser_view2->GetTabContentsContainerView(),
[email protected]610d36a2009-05-22 23:00:38305 focus_manager2->GetFocusedView());
[email protected]8bcdec92009-02-25 16:15:18306
307 // Close the 2nd browser to avoid a DCHECK().
308 browser_view2->Close();
[email protected]186f13f2009-08-19 20:34:00309#endif
initial.commit09911bf2008-07-26 23:55:29310}
311
312// Tabs remember focus.
[email protected]26153732010-11-09 18:47:39313// Disabled, http://crbug.com/62542.
314IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabsRememberFocus) {
[email protected]a6e602f2010-09-28 22:28:30315 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11316 ASSERT_TRUE(test_server()->Start());
initial.commit09911bf2008-07-26 23:55:29317
318 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11319 GURL url = test_server()->GetURL(kSimplePage);
[email protected]8bcdec92009-02-25 16:15:18320 ui_test_utils::NavigateToURL(browser(), url);
321
initial.commit09911bf2008-07-26 23:55:29322 // Create several tabs.
[email protected]52877dbc62012-06-29 22:22:03323 for (int i = 0; i < 4; ++i) {
324 chrome::AddSelectedTabWithURL(browser(), url,
325 content::PAGE_TRANSITION_TYPED);
326 }
initial.commit09911bf2008-07-26 23:55:29327
328 // Alternate focus for the tab.
329 const bool kFocusPage[3][5] = {
330 { true, true, true, true, false },
331 { false, false, false, false, false },
332 { false, true, false, true, false }
333 };
334
335 for (int i = 1; i < 3; i++) {
336 for (int j = 0; j < 5; j++) {
[email protected]8bcdec92009-02-25 16:15:18337 // Activate the tab.
[email protected]52877dbc62012-06-29 22:22:03338 chrome::ActivateTabAt(browser(), j, true);
initial.commit09911bf2008-07-26 23:55:29339
340 // Activate the location bar or the page.
[email protected]7e383692009-06-12 19:14:54341 if (kFocusPage[i][j]) {
[email protected]52877dbc62012-06-29 22:22:03342 chrome::GetWebContentsAt(browser(), j)->GetView()->Focus();
[email protected]7e383692009-06-12 19:14:54343 } else {
[email protected]a37d4b02012-06-25 21:56:10344 chrome::FocusLocationBar(browser());
[email protected]7e383692009-06-12 19:14:54345 }
initial.commit09911bf2008-07-26 23:55:29346 }
347
348 // Now come back to the tab and check the right view is focused.
349 for (int j = 0; j < 5; j++) {
[email protected]8bcdec92009-02-25 16:15:18350 // Activate the tab.
[email protected]52877dbc62012-06-29 22:22:03351 chrome::ActivateTabAt(browser(), j, true);
initial.commit09911bf2008-07-26 23:55:29352
[email protected]f2159ba2012-04-17 19:13:21353 ViewID vid = kFocusPage[i][j] ? VIEW_ID_TAB_CONTAINER :
[email protected]0b8fa8b2011-12-07 00:54:52354 location_bar_focus_view_id_;
[email protected]21abcc742009-10-23 02:52:06355 ASSERT_TRUE(IsViewFocused(vid));
initial.commit09911bf2008-07-26 23:55:29356 }
[email protected]cb7e2542009-12-14 22:02:35357
[email protected]52877dbc62012-06-29 22:22:03358 chrome::ActivateTabAt(browser(), 0, true);
[email protected]cb7e2542009-12-14 22:02:35359 // Try the above, but with ctrl+tab. Since tab normally changes focus,
360 // this has regressed in the past. Loop through several times to be sure.
361 for (int j = 0; j < 15; j++) {
[email protected]f2159ba2012-04-17 19:13:21362 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
[email protected]0b8fa8b2011-12-07 00:54:52363 location_bar_focus_view_id_;
[email protected]cb7e2542009-12-14 22:02:35364 ASSERT_TRUE(IsViewFocused(vid));
365
[email protected]1d000682010-08-23 16:21:28366 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09367 browser(), ui::VKEY_TAB, true, false, false, false));
[email protected]cb7e2542009-12-14 22:02:35368 }
369
370 // As above, but with ctrl+shift+tab.
[email protected]52877dbc62012-06-29 22:22:03371 chrome::ActivateTabAt(browser(), 4, true);
[email protected]cb7e2542009-12-14 22:02:35372 for (int j = 14; j >= 0; --j) {
[email protected]f2159ba2012-04-17 19:13:21373 ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
[email protected]0b8fa8b2011-12-07 00:54:52374 location_bar_focus_view_id_;
[email protected]cb7e2542009-12-14 22:02:35375 ASSERT_TRUE(IsViewFocused(vid));
376
[email protected]1d000682010-08-23 16:21:28377 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09378 browser(), ui::VKEY_TAB, true, true, false, false));
[email protected]cb7e2542009-12-14 22:02:35379 }
initial.commit09911bf2008-07-26 23:55:29380 }
381}
382
[email protected]ae40b572009-10-02 21:17:45383// Tabs remember focus with find-in-page box.
[email protected]cb7e2542009-12-14 22:02:35384IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) {
[email protected]a6e602f2010-09-28 22:28:30385 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11386 ASSERT_TRUE(test_server()->Start());
[email protected]ae40b572009-10-02 21:17:45387
388 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11389 GURL url = test_server()->GetURL(kSimplePage);
[email protected]ae40b572009-10-02 21:17:45390 ui_test_utils::NavigateToURL(browser(), url);
391
[email protected]a37d4b02012-06-25 21:56:10392 chrome::Find(browser());
[email protected]ba3d09a12012-11-07 12:13:52393 ui_test_utils::FindInPage(chrome::GetActiveWebContents(browser()),
[email protected]864ebb52012-08-17 17:53:02394 ASCIIToUTF16("a"), true, false, NULL, NULL);
[email protected]21abcc742009-10-23 02:52:06395 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]ae40b572009-10-02 21:17:45396
397 // Focus the location bar.
[email protected]a37d4b02012-06-25 21:56:10398 chrome::FocusLocationBar(browser());
[email protected]ae40b572009-10-02 21:17:45399
400 // Create a 2nd tab.
[email protected]52877dbc62012-06-29 22:22:03401 chrome::AddSelectedTabWithURL(browser(), url, content::PAGE_TRANSITION_TYPED);
[email protected]ae40b572009-10-02 21:17:45402
403 // Focus should be on the recently opened tab page.
[email protected]f2159ba2012-04-17 19:13:21404 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]ae40b572009-10-02 21:17:45405
406 // Select 1st tab, focus should still be on the location-bar.
407 // (bug http://crbug.com/23296)
[email protected]52877dbc62012-06-29 22:22:03408 chrome::ActivateTabAt(browser(), 0, true);
[email protected]0b8fa8b2011-12-07 00:54:52409 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]ae40b572009-10-02 21:17:45410
411 // Now open the find box again, switch to another tab and come back, the focus
412 // should return to the find box.
[email protected]a37d4b02012-06-25 21:56:10413 chrome::Find(browser());
[email protected]21abcc742009-10-23 02:52:06414 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]52877dbc62012-06-29 22:22:03415 chrome::ActivateTabAt(browser(), 1, true);
[email protected]f2159ba2012-04-17 19:13:21416 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]52877dbc62012-06-29 22:22:03417 chrome::ActivateTabAt(browser(), 0, true);
[email protected]21abcc742009-10-23 02:52:06418 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]ae40b572009-10-02 21:17:45419}
420
initial.commit09911bf2008-07-26 23:55:29421// Background window does not steal focus.
[email protected]c92928672010-11-09 18:31:07422// Flaky, http://crbug.com/62538.
423IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
[email protected]4d2451652012-02-14 23:54:26424 DISABLED_BackgroundBrowserDontStealFocus) {
[email protected]a6e602f2010-09-28 22:28:30425 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11426 ASSERT_TRUE(test_server()->Start());
initial.commit09911bf2008-07-26 23:55:29427
initial.commit09911bf2008-07-26 23:55:29428 // Open a new browser window.
[email protected]a4fe67012012-07-25 20:14:29429 Browser* browser2 = new Browser(Browser::CreateParams(browser()->profile()));
[email protected]8bcdec92009-02-25 16:15:18430 ASSERT_TRUE(browser2);
[email protected]686221c2012-11-08 07:30:10431 chrome::AddBlankTabAt(browser2, -1, true);
[email protected]8bcdec92009-02-25 16:15:18432 browser2->window()->Show();
[email protected]186f13f2009-08-19 20:34:00433
[email protected]ed179ee2009-10-03 21:02:51434 Browser* focused_browser = NULL;
435 Browser* unfocused_browser = NULL;
[email protected]753efc42010-03-09 19:52:16436#if defined(USE_X11)
437 // On X11, calling Activate() is not guaranteed to move focus, so we have
[email protected]186f13f2009-08-19 20:34:00438 // to figure out which browser does have focus.
439 if (browser2->window()->IsActive()) {
440 focused_browser = browser2;
441 unfocused_browser = browser();
442 } else if (browser()->window()->IsActive()) {
443 focused_browser = browser();
444 unfocused_browser = browser2;
445 } else {
[email protected]579c3d82010-10-06 03:53:51446 FAIL() << "Could not determine which browser has focus";
[email protected]186f13f2009-08-19 20:34:00447 }
448#elif defined(OS_WIN)
449 focused_browser = browser();
450 unfocused_browser = browser2;
[email protected]853300a82010-07-27 21:17:57451#elif defined(OS_MACOSX)
452 // On Mac, the newly created window always gets the focus.
453 focused_browser = browser2;
454 unfocused_browser = browser();
[email protected]186f13f2009-08-19 20:34:00455#endif
456
[email protected]95409e12010-08-17 20:07:11457 GURL steal_focus_url = test_server()->GetURL(kStealFocusPage);
[email protected]186f13f2009-08-19 20:34:00458 ui_test_utils::NavigateToURL(unfocused_browser, steal_focus_url);
[email protected]1e187af2009-02-25 02:02:46459
[email protected]8bcdec92009-02-25 16:15:18460 // Activate the first browser.
[email protected]186f13f2009-08-19 20:34:00461 focused_browser->window()->Activate();
initial.commit09911bf2008-07-26 23:55:29462
[email protected]7d478cb2012-07-24 17:19:42463 ASSERT_TRUE(content::ExecuteJavaScript(
[email protected]52877dbc62012-06-29 22:22:03464 chrome::GetActiveWebContents(unfocused_browser)->GetRenderViewHost(), L"",
[email protected]579c3d82010-10-06 03:53:51465 L"stealFocus();"));
initial.commit09911bf2008-07-26 23:55:29466
[email protected]8bcdec92009-02-25 16:15:18467 // Make sure the first browser is still active.
[email protected]186f13f2009-08-19 20:34:00468 EXPECT_TRUE(focused_browser->window()->IsActive());
initial.commit09911bf2008-07-26 23:55:29469}
470
471// Page cannot steal focus when focus is on location bar.
[email protected]7ef7c6e2012-10-30 12:32:44472IN_PROC_BROWSER_TEST_F(BrowserFocusTest, LocationBarLockFocus) {
[email protected]a6e602f2010-09-28 22:28:30473 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11474 ASSERT_TRUE(test_server()->Start());
initial.commit09911bf2008-07-26 23:55:29475
476 // Open the page that steals focus.
[email protected]95409e12010-08-17 20:07:11477 GURL url = test_server()->GetURL(kStealFocusPage);
[email protected]8bcdec92009-02-25 16:15:18478 ui_test_utils::NavigateToURL(browser(), url);
initial.commit09911bf2008-07-26 23:55:29479
[email protected]a37d4b02012-06-25 21:56:10480 chrome::FocusLocationBar(browser());
initial.commit09911bf2008-07-26 23:55:29481
[email protected]7d478cb2012-07-24 17:19:42482 ASSERT_TRUE(content::ExecuteJavaScript(
[email protected]52877dbc62012-06-29 22:22:03483 chrome::GetActiveWebContents(browser())->GetRenderViewHost(), L"",
[email protected]579c3d82010-10-06 03:53:51484 L"stealFocus();"));
initial.commit09911bf2008-07-26 23:55:29485
486 // Make sure the location bar is still focused.
[email protected]0b8fa8b2011-12-07 00:54:52487 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
initial.commit09911bf2008-07-26 23:55:29488}
489
[email protected]9e0c83a2009-05-06 19:44:37490// Focus traversal on a regular page.
[email protected]130efb02009-09-18 18:54:35491// Note that this test relies on a notification from the renderer that the
492// focus has changed in the page. The notification in the renderer may change
493// at which point this test would fail (see comment in
494// RenderWidget::didFocus()).
[email protected]853300a82010-07-27 21:17:57495IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversal) {
[email protected]a6e602f2010-09-28 22:28:30496 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11497 ASSERT_TRUE(test_server()->Start());
initial.commit09911bf2008-07-26 23:55:29498
[email protected]8bcdec92009-02-25 16:15:18499 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11500 GURL url = test_server()->GetURL(kTypicalPage);
[email protected]8bcdec92009-02-25 16:15:18501 ui_test_utils::NavigateToURL(browser(), url);
initial.commit09911bf2008-07-26 23:55:29502
[email protected]a37d4b02012-06-25 21:56:10503 chrome::FocusLocationBar(browser());
initial.commit09911bf2008-07-26 23:55:29504
[email protected]546ae4e02010-12-08 14:57:19505 const char* kTextElementID = "textEdit";
[email protected]8bcdec92009-02-25 16:15:18506 const char* kExpElementIDs[] = {
507 "", // Initially no element in the page should be focused
508 // (the location bar is focused).
[email protected]546ae4e02010-12-08 14:57:19509 kTextElementID, "searchButton", "luckyButton", "googleLink", "gmailLink",
[email protected]8bcdec92009-02-25 16:15:18510 "gmapLink"
initial.commit09911bf2008-07-26 23:55:29511 };
512
513 // Test forward focus traversal.
514 for (int i = 0; i < 3; ++i) {
[email protected]1870d5cf2011-05-12 01:55:40515 SCOPED_TRACE(base::StringPrintf("outer loop: %d", i));
initial.commit09911bf2008-07-26 23:55:29516 // Location bar should be focused.
[email protected]0b8fa8b2011-12-07 00:54:52517 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
initial.commit09911bf2008-07-26 23:55:29518
[email protected]911696b2011-01-28 02:36:49519 // Move the caret to the end, otherwise the next Tab key may not move focus.
520 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
521 browser(), ui::VKEY_END, false, false, false, false));
522
initial.commit09911bf2008-07-26 23:55:29523 // Now let's press tab to move the focus.
[email protected]130efb02009-09-18 18:54:35524 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
[email protected]1870d5cf2011-05-12 01:55:40525 SCOPED_TRACE(base::StringPrintf("inner loop %" PRIuS, j));
initial.commit09911bf2008-07-26 23:55:29526 // Let's make sure the focus is on the expected element in the page.
[email protected]45671612009-04-29 22:24:01527 std::string actual;
[email protected]7d478cb2012-07-24 17:19:42528 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03529 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]8bcdec92009-02-25 16:15:18530 L"",
[email protected]45671612009-04-29 22:24:01531 L"window.domAutomationController.send(getFocusedElement());",
532 &actual));
initial.commit09911bf2008-07-26 23:55:29533 ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
534
[email protected]130efb02009-09-18 18:54:35535 if (j < arraysize(kExpElementIDs) - 1) {
[email protected]546ae4e02010-12-08 14:57:19536 // 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 =
539 (strcmp(kTextElementID, kExpElementIDs[j + 1]) == 0);
[email protected]6c2381d2011-10-19 02:52:53540 content::Details<bool> details(&is_editable_node);
[email protected]546ae4e02010-12-08 14:57:19541
542 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
[email protected]b6d81262011-01-13 17:36:09543 browser(), ui::VKEY_TAB, false, false, false, false,
[email protected]432115822011-07-10 15:52:27544 content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
[email protected]d53092652011-12-06 06:12:56545 content::NotificationSource(content::Source<RenderViewHost>(
[email protected]52877dbc62012-06-29 22:22:03546 chrome::GetActiveWebContents(browser())->GetRenderViewHost())),
[email protected]546ae4e02010-12-08 14:57:19547 details));
[email protected]130efb02009-09-18 18:54:35548 } else {
549 // On the last tab key press, the focus returns to the browser.
[email protected]546ae4e02010-12-08 14:57:19550 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
[email protected]b6d81262011-01-13 17:36:09551 browser(), ui::VKEY_TAB, false, false, false, false,
[email protected]432115822011-07-10 15:52:27552 chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
[email protected]6c2381d2011-10-19 02:52:53553 content::NotificationSource(content::Source<Browser>(browser()))));
[email protected]130efb02009-09-18 18:54:35554 }
initial.commit09911bf2008-07-26 23:55:29555 }
[email protected]8bcdec92009-02-25 16:15:18556
557 // At this point the renderer has sent us a message asking to advance the
558 // focus (as the end of the focus loop was reached in the renderer).
559 // We need to run the message loop to process it.
[email protected]b8deecd2012-07-30 21:09:44560 content::RunAllPendingInMessageLoop();
initial.commit09911bf2008-07-26 23:55:29561 }
562
563 // Now let's try reverse focus traversal.
564 for (int i = 0; i < 3; ++i) {
[email protected]1870d5cf2011-05-12 01:55:40565 SCOPED_TRACE(base::StringPrintf("outer loop: %d", i));
initial.commit09911bf2008-07-26 23:55:29566 // Location bar should be focused.
[email protected]0b8fa8b2011-12-07 00:54:52567 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
initial.commit09911bf2008-07-26 23:55:29568
[email protected]911696b2011-01-28 02:36:49569 // Move the caret to the end, otherwise the next Tab key may not move focus.
570 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
571 browser(), ui::VKEY_END, false, false, false, false));
572
[email protected]8bcdec92009-02-25 16:15:18573 // Now let's press shift-tab to move the focus in reverse.
[email protected]a6e602f2010-09-28 22:28:30574 for (size_t j = 0; j < arraysize(kExpElementIDs); ++j) {
[email protected]1870d5cf2011-05-12 01:55:40575 SCOPED_TRACE(base::StringPrintf("inner loop: %" PRIuS, j));
[email protected]546ae4e02010-12-08 14:57:19576 const char* next_element =
577 kExpElementIDs[arraysize(kExpElementIDs) - 1 - j];
[email protected]130efb02009-09-18 18:54:35578
579 if (j < arraysize(kExpElementIDs) - 1) {
[email protected]546ae4e02010-12-08 14:57:19580 // If the next element is the kTextElementID, we expect to be
581 // notified we have switched to an editable node.
582 bool is_editable_node = (strcmp(kTextElementID, next_element) == 0);
[email protected]6c2381d2011-10-19 02:52:53583 content::Details<bool> details(&is_editable_node);
[email protected]546ae4e02010-12-08 14:57:19584
585 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
[email protected]b6d81262011-01-13 17:36:09586 browser(), ui::VKEY_TAB, false, true, false, false,
[email protected]432115822011-07-10 15:52:27587 content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
[email protected]d53092652011-12-06 06:12:56588 content::NotificationSource(content::Source<RenderViewHost>(
[email protected]52877dbc62012-06-29 22:22:03589 chrome::GetActiveWebContents(browser())->GetRenderViewHost())),
[email protected]546ae4e02010-12-08 14:57:19590 details));
[email protected]130efb02009-09-18 18:54:35591 } else {
592 // On the last tab key press, the focus returns to the browser.
[email protected]546ae4e02010-12-08 14:57:19593 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
[email protected]b6d81262011-01-13 17:36:09594 browser(), ui::VKEY_TAB, false, true, false, false,
[email protected]432115822011-07-10 15:52:27595 chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
[email protected]6c2381d2011-10-19 02:52:53596 content::NotificationSource(content::Source<Browser>(browser()))));
[email protected]130efb02009-09-18 18:54:35597 }
initial.commit09911bf2008-07-26 23:55:29598
599 // Let's make sure the focus is on the expected element in the page.
[email protected]45671612009-04-29 22:24:01600 std::string actual;
[email protected]7d478cb2012-07-24 17:19:42601 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
[email protected]52877dbc62012-06-29 22:22:03602 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
[email protected]8bcdec92009-02-25 16:15:18603 L"",
[email protected]45671612009-04-29 22:24:01604 L"window.domAutomationController.send(getFocusedElement());",
605 &actual));
[email protected]546ae4e02010-12-08 14:57:19606 ASSERT_STREQ(next_element, actual.c_str());
initial.commit09911bf2008-07-26 23:55:29607 }
[email protected]8bcdec92009-02-25 16:15:18608
609 // At this point the renderer has sent us a message asking to advance the
610 // focus (as the end of the focus loop was reached in the renderer).
611 // We need to run the message loop to process it.
[email protected]b8deecd2012-07-30 21:09:44612 content::RunAllPendingInMessageLoop();
initial.commit09911bf2008-07-26 23:55:29613 }
614}
615
[email protected]9e0c83a2009-05-06 19:44:37616// Focus traversal while an interstitial is showing.
[email protected]fc2e0872009-08-21 22:14:41617IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversalOnInterstitial) {
[email protected]a6e602f2010-09-28 22:28:30618 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11619 ASSERT_TRUE(test_server()->Start());
[email protected]9e0c83a2009-05-06 19:44:37620
621 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11622 GURL url = test_server()->GetURL(kSimplePage);
[email protected]9e0c83a2009-05-06 19:44:37623 ui_test_utils::NavigateToURL(browser(), url);
624
[email protected]9e0c83a2009-05-06 19:44:37625 // Focus should be on the page.
[email protected]f2159ba2012-04-17 19:13:21626 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9e0c83a2009-05-06 19:44:37627
628 // Let's show an interstitial.
629 TestInterstitialPage* interstitial_page =
[email protected]52877dbc62012-06-29 22:22:03630 new TestInterstitialPage(chrome::GetActiveWebContents(browser()),
[email protected]9e0c83a2009-05-06 19:44:37631 true, GURL("http://interstitial.com"));
[email protected]9e0c83a2009-05-06 19:44:37632 // Give some time for the interstitial to show.
633 MessageLoop::current()->PostDelayedTask(FROM_HERE,
[email protected]a778709f2011-12-10 00:28:17634 MessageLoop::QuitClosure(),
[email protected]7e560102012-03-08 20:58:42635 base::TimeDelta::FromSeconds(1));
[email protected]729eb632012-07-26 04:45:26636 content::RunMessageLoop();
[email protected]9e0c83a2009-05-06 19:44:37637
[email protected]a37d4b02012-06-25 21:56:10638 chrome::FocusLocationBar(browser());
[email protected]9e0c83a2009-05-06 19:44:37639
640 const char* kExpElementIDs[] = {
641 "", // Initially no element in the page should be focused
642 // (the location bar is focused).
643 "textEdit", "searchButton", "luckyButton", "googleLink", "gmailLink",
644 "gmapLink"
645 };
646
647 // Test forward focus traversal.
648 for (int i = 0; i < 2; ++i) {
649 // Location bar should be focused.
[email protected]0b8fa8b2011-12-07 00:54:52650 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]9e0c83a2009-05-06 19:44:37651
[email protected]911696b2011-01-28 02:36:49652 // 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));
655
[email protected]9e0c83a2009-05-06 19:44:37656 // Now let's press tab to move the focus.
[email protected]130efb02009-09-18 18:54:35657 for (size_t j = 0; j < 7; ++j) {
[email protected]9e0c83a2009-05-06 19:44:37658 // Let's make sure the focus is on the expected element in the page.
[email protected]a6e602f2010-09-28 22:28:30659 std::string actual;
[email protected]7d478cb2012-07-24 17:19:42660 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
[email protected]a6e602f2010-09-28 22:28:30661 interstitial_page->render_view_host(), L"",
662 L"window.domAutomationController.send(getFocusedElement());",
663 &actual));
[email protected]9e0c83a2009-05-06 19:44:37664 ASSERT_STREQ(kExpElementIDs[j], actual.c_str());
665
[email protected]432115822011-07-10 15:52:27666 int notification_type;
[email protected]6c2381d2011-10-19 02:52:53667 content::NotificationSource notification_source =
[email protected]ad50def52011-10-19 23:17:07668 content::NotificationService::AllSources();
[email protected]130efb02009-09-18 18:54:35669 if (j < arraysize(kExpElementIDs) - 1) {
[email protected]432115822011-07-10 15:52:27670 notification_type = content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE;
[email protected]d53092652011-12-06 06:12:56671 notification_source = content::Source<RenderViewHost>(
672 interstitial_page->render_view_host());
[email protected]130efb02009-09-18 18:54:35673 } else {
674 // On the last tab key press, the focus returns to the browser.
[email protected]432115822011-07-10 15:52:27675 notification_type = chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER;
[email protected]6c2381d2011-10-19 02:52:53676 notification_source = content::Source<Browser>(browser());
[email protected]130efb02009-09-18 18:54:35677 }
[email protected]a6e602f2010-09-28 22:28:30678
679 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
[email protected]b6d81262011-01-13 17:36:09680 browser(), ui::VKEY_TAB, false, false, false, false,
[email protected]a6e602f2010-09-28 22:28:30681 notification_type, notification_source));
[email protected]9e0c83a2009-05-06 19:44:37682 }
683
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.
[email protected]b8deecd2012-07-30 21:09:44687 content::RunAllPendingInMessageLoop();
[email protected]9e0c83a2009-05-06 19:44:37688 }
689
690 // Now let's try reverse focus traversal.
691 for (int i = 0; i < 2; ++i) {
692 // Location bar should be focused.
[email protected]0b8fa8b2011-12-07 00:54:52693 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]9e0c83a2009-05-06 19:44:37694
[email protected]911696b2011-01-28 02:36:49695 // Move the caret to the end, otherwise the next Tab key may not move focus.
696 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
697 browser(), ui::VKEY_END, false, false, false, false));
698
[email protected]9e0c83a2009-05-06 19:44:37699 // Now let's press shift-tab to move the focus in reverse.
[email protected]130efb02009-09-18 18:54:35700 for (size_t j = 0; j < 7; ++j) {
[email protected]432115822011-07-10 15:52:27701 int notification_type;
[email protected]6c2381d2011-10-19 02:52:53702 content::NotificationSource notification_source =
[email protected]ad50def52011-10-19 23:17:07703 content::NotificationService::AllSources();
[email protected]130efb02009-09-18 18:54:35704 if (j < arraysize(kExpElementIDs) - 1) {
[email protected]432115822011-07-10 15:52:27705 notification_type = content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE;
[email protected]d53092652011-12-06 06:12:56706 notification_source = content::Source<RenderViewHost>(
707 interstitial_page->render_view_host());
[email protected]130efb02009-09-18 18:54:35708 } else {
709 // On the last tab key press, the focus returns to the browser.
[email protected]432115822011-07-10 15:52:27710 notification_type = chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER;
[email protected]6c2381d2011-10-19 02:52:53711 notification_source = content::Source<Browser>(browser());
[email protected]130efb02009-09-18 18:54:35712 }
[email protected]9e0c83a2009-05-06 19:44:37713
[email protected]a6e602f2010-09-28 22:28:30714 ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
[email protected]b6d81262011-01-13 17:36:09715 browser(), ui::VKEY_TAB, false, true, false, false,
[email protected]a6e602f2010-09-28 22:28:30716 notification_type, notification_source));
717
[email protected]9e0c83a2009-05-06 19:44:37718 // Let's make sure the focus is on the expected element in the page.
[email protected]a6e602f2010-09-28 22:28:30719 std::string actual;
[email protected]7d478cb2012-07-24 17:19:42720 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
[email protected]a6e602f2010-09-28 22:28:30721 interstitial_page->render_view_host(), L"",
722 L"window.domAutomationController.send(getFocusedElement());",
723 &actual));
[email protected]9e0c83a2009-05-06 19:44:37724 ASSERT_STREQ(kExpElementIDs[6 - j], actual.c_str());
725 }
726
727 // At this point the renderer has sent us a message asking to advance the
728 // focus (as the end of the focus loop was reached in the renderer).
729 // We need to run the message loop to process it.
[email protected]b8deecd2012-07-30 21:09:44730 content::RunAllPendingInMessageLoop();
[email protected]9e0c83a2009-05-06 19:44:37731 }
732}
733
734// Focus stays on page with interstitials.
[email protected]cb931932011-05-03 19:57:33735// http://crbug.com/81451
[email protected]fd5a53e2011-09-15 14:09:05736#if defined(OS_MACOSX) || defined(OS_WIN)
[email protected]4d2451652012-02-14 23:54:26737IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_InterstitialFocus) {
[email protected]cb931932011-05-03 19:57:33738#else
[email protected]e4f4e0b2009-10-13 19:58:21739IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) {
[email protected]cb931932011-05-03 19:57:33740#endif
[email protected]a6e602f2010-09-28 22:28:30741 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11742 ASSERT_TRUE(test_server()->Start());
[email protected]9e0c83a2009-05-06 19:44:37743
744 // First we navigate to our test page.
[email protected]95409e12010-08-17 20:07:11745 GURL url = test_server()->GetURL(kSimplePage);
[email protected]9e0c83a2009-05-06 19:44:37746 ui_test_utils::NavigateToURL(browser(), url);
747
[email protected]9e0c83a2009-05-06 19:44:37748 // Page should have focus.
[email protected]f2159ba2012-04-17 19:13:21749 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]52877dbc62012-06-29 22:22:03750 EXPECT_TRUE(chrome::GetActiveWebContents(browser())->GetRenderViewHost()->
[email protected]9f76c1e2012-03-05 15:15:58751 GetView()->HasFocus());
[email protected]9e0c83a2009-05-06 19:44:37752
[email protected]9d8a4642009-07-29 17:25:30753 // Let's show an interstitial.
[email protected]9e0c83a2009-05-06 19:44:37754 TestInterstitialPage* interstitial_page =
[email protected]52877dbc62012-06-29 22:22:03755 new TestInterstitialPage(chrome::GetActiveWebContents(browser()),
[email protected]9e0c83a2009-05-06 19:44:37756 true, GURL("http://interstitial.com"));
[email protected]9e0c83a2009-05-06 19:44:37757 // Give some time for the interstitial to show.
758 MessageLoop::current()->PostDelayedTask(FROM_HERE,
[email protected]a778709f2011-12-10 00:28:17759 MessageLoop::QuitClosure(),
[email protected]7e560102012-03-08 20:58:42760 base::TimeDelta::FromSeconds(1));
[email protected]729eb632012-07-26 04:45:26761 content::RunMessageLoop();
[email protected]9e0c83a2009-05-06 19:44:37762
763 // The interstitial should have focus now.
[email protected]f2159ba2012-04-17 19:13:21764 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9e0c83a2009-05-06 19:44:37765 EXPECT_TRUE(interstitial_page->HasFocus());
766
767 // Hide the interstitial.
768 interstitial_page->DontProceed();
769
770 // Focus should be back on the original page.
[email protected]f2159ba2012-04-17 19:13:21771 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9e0c83a2009-05-06 19:44:37772}
773
[email protected]9bd491ee2008-12-10 22:31:07774// Make sure Find box can request focus, even when it is already open.
[email protected]06e85dfd2012-10-31 01:32:35775// Disabled due to flakiness. http://crbug.com/67301.
776IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FindFocusTest) {
[email protected]a6e602f2010-09-28 22:28:30777 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11778 ASSERT_TRUE(test_server()->Start());
license.botbf09a502008-08-24 00:55:55779
[email protected]9bd491ee2008-12-10 22:31:07780 // Open some page (any page that doesn't steal focus).
[email protected]95409e12010-08-17 20:07:11781 GURL url = test_server()->GetURL(kTypicalPage);
[email protected]8bcdec92009-02-25 16:15:18782 ui_test_utils::NavigateToURL(browser(), url);
[email protected]9bd491ee2008-12-10 22:31:07783
[email protected]a711df102010-12-14 09:47:03784 EXPECT_TRUE(ChromeInForeground());
785
[email protected]853300a82010-07-27 21:17:57786#if defined(OS_MACOSX)
787 // Press Cmd+F, which will make the Find box open and request focus.
[email protected]1d000682010-08-23 16:21:28788 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09789 browser(), ui::VKEY_F, false, false, false, true));
[email protected]853300a82010-07-27 21:17:57790#else
[email protected]9bd491ee2008-12-10 22:31:07791 // Press Ctrl+F, which will make the Find box open and request focus.
[email protected]1d000682010-08-23 16:21:28792 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09793 browser(), ui::VKEY_F, true, false, false, false));
[email protected]853300a82010-07-27 21:17:57794#endif
[email protected]8bcdec92009-02-25 16:15:18795
[email protected]a9c060ca2012-01-05 20:43:41796 ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]9bd491ee2008-12-10 22:31:07797
[email protected]a37d4b02012-06-25 21:56:10798 chrome::FocusLocationBar(browser());
[email protected]0b8fa8b2011-12-07 00:54:52799 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]9bd491ee2008-12-10 22:31:07800
801 // Now press Ctrl+F again and focus should move to the Find box.
[email protected]853300a82010-07-27 21:17:57802#if defined(OS_MACOSX)
[email protected]1d000682010-08-23 16:21:28803 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09804 browser(), ui::VKEY_F, false, false, false, true));
[email protected]853300a82010-07-27 21:17:57805#else
[email protected]1d000682010-08-23 16:21:28806 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09807 browser(), ui::VKEY_F, true, false, false, false));
[email protected]853300a82010-07-27 21:17:57808#endif
[email protected]21abcc742009-10-23 02:52:06809 ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]9bd491ee2008-12-10 22:31:07810
811 // Set focus to the page.
[email protected]fc2e0872009-08-21 22:14:41812 ClickOnView(VIEW_ID_TAB_CONTAINER);
[email protected]f2159ba2012-04-17 19:13:21813 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9bd491ee2008-12-10 22:31:07814
815 // Now press Ctrl+F again and focus should move to the Find box.
[email protected]853300a82010-07-27 21:17:57816#if defined(OS_MACOSX)
[email protected]1d000682010-08-23 16:21:28817 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09818 browser(), ui::VKEY_F, false, false, false, true));
[email protected]853300a82010-07-27 21:17:57819#else
[email protected]1d000682010-08-23 16:21:28820 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
[email protected]b6d81262011-01-13 17:36:09821 browser(), ui::VKEY_F, true, false, false, false));
[email protected]853300a82010-07-27 21:17:57822#endif
[email protected]8bcdec92009-02-25 16:15:18823
[email protected]a9c060ca2012-01-05 20:43:41824 ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
[email protected]9bd491ee2008-12-10 22:31:07825}
[email protected]401513c2009-03-12 00:21:28826
827// Makes sure the focus is in the right location when opening the different
828// types of tabs.
[email protected]c92928672010-11-09 18:31:07829// Flaky, http://crbug.com/62539.
[email protected]4d2451652012-02-14 23:54:26830IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabInitialFocus) {
[email protected]a6e602f2010-09-28 22:28:30831 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]9ba21ede2010-07-30 01:11:07832
[email protected]401513c2009-03-12 00:21:28833 // Open the history tab, focus should be on the tab contents.
[email protected]5d9cace72012-06-21 16:07:12834 chrome::ShowHistory(browser());
[email protected]6ddc6e3f22012-07-26 01:15:35835 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
[email protected]52877dbc62012-06-29 22:22:03836 chrome::GetActiveWebContents(browser())));
[email protected]f2159ba2012-04-17 19:13:21837 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]401513c2009-03-12 00:21:28838
839 // Open the new tab, focus should be on the location bar.
[email protected]a37d4b02012-06-25 21:56:10840 chrome::NewTab(browser());
[email protected]6ddc6e3f22012-07-26 01:15:35841 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
[email protected]52877dbc62012-06-29 22:22:03842 chrome::GetActiveWebContents(browser())));
[email protected]0b8fa8b2011-12-07 00:54:52843 EXPECT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]401513c2009-03-12 00:21:28844
845 // Open the download tab, focus should be on the tab contents.
[email protected]5d9cace72012-06-21 16:07:12846 chrome::ShowDownloads(browser());
[email protected]6ddc6e3f22012-07-26 01:15:35847 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
[email protected]52877dbc62012-06-29 22:22:03848 chrome::GetActiveWebContents(browser())));
[email protected]f2159ba2012-04-17 19:13:21849 EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]3e3f0eb2009-06-22 18:33:43850
851 // Open about:blank, focus should be on the location bar.
[email protected]52877dbc62012-06-29 22:22:03852 chrome::AddSelectedTabWithURL(browser(), GURL(chrome::kAboutBlankURL),
853 content::PAGE_TRANSITION_LINK);
[email protected]6ddc6e3f22012-07-26 01:15:35854 ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
[email protected]52877dbc62012-06-29 22:22:03855 chrome::GetActiveWebContents(browser())));
[email protected]0b8fa8b2011-12-07 00:54:52856 EXPECT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]401513c2009-03-12 00:21:28857}
[email protected]9d8a4642009-07-29 17:25:30858
859// Tests that focus goes where expected when using reload.
[email protected]e4f4e0b2009-10-13 19:58:21860IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusOnReload) {
[email protected]a6e602f2010-09-28 22:28:30861 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11862 ASSERT_TRUE(test_server()->Start());
[email protected]9d8a4642009-07-29 17:25:30863
[email protected]9d8a4642009-07-29 17:25:30864 // Open the new tab, reload.
[email protected]6b4e8e42011-08-17 19:36:06865 {
[email protected]a7fe9112012-07-20 02:34:45866 content::WindowedNotificationObserver observer(
[email protected]6b4e8e42011-08-17 19:36:06867 content::NOTIFICATION_LOAD_STOP,
[email protected]ad50def52011-10-19 23:17:07868 content::NotificationService::AllSources());
[email protected]a37d4b02012-06-25 21:56:10869 chrome::NewTab(browser());
[email protected]6b4e8e42011-08-17 19:36:06870 observer.Wait();
871 }
[email protected]b8deecd2012-07-30 21:09:44872 content::RunAllPendingInMessageLoop();
[email protected]f07d7bf2010-04-06 08:02:42873
[email protected]6b4e8e42011-08-17 19:36:06874 {
[email protected]a7fe9112012-07-20 02:34:45875 content::WindowedNotificationObserver observer(
[email protected]6b4e8e42011-08-17 19:36:06876 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50877 content::Source<NavigationController>(
[email protected]52877dbc62012-06-29 22:22:03878 &chrome::GetActiveWebContents(browser())->GetController()));
[email protected]a37d4b02012-06-25 21:56:10879 chrome::Reload(browser(), CURRENT_TAB);
[email protected]6b4e8e42011-08-17 19:36:06880 observer.Wait();
881 }
[email protected]9d8a4642009-07-29 17:25:30882 // Focus should stay on the location bar.
[email protected]0b8fa8b2011-12-07 00:54:52883 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]9d8a4642009-07-29 17:25:30884
885 // Open a regular page, focus the location bar, reload.
[email protected]95409e12010-08-17 20:07:11886 ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage));
[email protected]a37d4b02012-06-25 21:56:10887 chrome::FocusLocationBar(browser());
[email protected]0b8fa8b2011-12-07 00:54:52888 ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_));
[email protected]6b4e8e42011-08-17 19:36:06889 {
[email protected]a7fe9112012-07-20 02:34:45890 content::WindowedNotificationObserver observer(
[email protected]6b4e8e42011-08-17 19:36:06891 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50892 content::Source<NavigationController>(
[email protected]52877dbc62012-06-29 22:22:03893 &chrome::GetActiveWebContents(browser())->GetController()));
[email protected]a37d4b02012-06-25 21:56:10894 chrome::Reload(browser(), CURRENT_TAB);
[email protected]6b4e8e42011-08-17 19:36:06895 observer.Wait();
896 }
[email protected]9ba21ede2010-07-30 01:11:07897
[email protected]9d8a4642009-07-29 17:25:30898 // Focus should now be on the tab contents.
[email protected]5d9cace72012-06-21 16:07:12899 chrome::ShowDownloads(browser());
[email protected]f2159ba2012-04-17 19:13:21900 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9d8a4642009-07-29 17:25:30901}
902
903// Tests that focus goes where expected when using reload on a crashed tab.
[email protected]160f29ad2010-10-28 15:43:27904IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnReloadCrashedTab) {
[email protected]a6e602f2010-09-28 22:28:30905 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
[email protected]95409e12010-08-17 20:07:11906 ASSERT_TRUE(test_server()->Start());
[email protected]9d8a4642009-07-29 17:25:30907
[email protected]9d8a4642009-07-29 17:25:30908 // Open a regular page, crash, reload.
[email protected]95409e12010-08-17 20:07:11909 ui_test_utils::NavigateToURL(browser(), test_server()->GetURL(kSimplePage));
[email protected]e0f3e142012-07-26 03:31:34910 content::CrashTab(chrome::GetActiveWebContents(browser()));
[email protected]6b4e8e42011-08-17 19:36:06911 {
[email protected]a7fe9112012-07-20 02:34:45912 content::WindowedNotificationObserver observer(
[email protected]6b4e8e42011-08-17 19:36:06913 content::NOTIFICATION_LOAD_STOP,
[email protected]c5eed492012-01-04 17:07:50914 content::Source<NavigationController>(
[email protected]52877dbc62012-06-29 22:22:03915 &chrome::GetActiveWebContents(browser())->GetController()));
[email protected]a37d4b02012-06-25 21:56:10916 chrome::Reload(browser(), CURRENT_TAB);
[email protected]6b4e8e42011-08-17 19:36:06917 observer.Wait();
918 }
[email protected]9ba21ede2010-07-30 01:11:07919
[email protected]9d8a4642009-07-29 17:25:30920 // Focus should now be on the tab contents.
[email protected]5d9cace72012-06-21 16:07:12921 chrome::ShowDownloads(browser());
[email protected]f2159ba2012-04-17 19:13:21922 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
[email protected]9d8a4642009-07-29 17:25:30923}
[email protected]629e0342010-07-27 23:30:13924
925} // namespace