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.
4 
5 #include <stddef.h>
6 
7 #include "base/bind.h"
8 #include "base/files/file_util.h"
9 #include "base/format_macros.h"
10 #include "base/location.h"
11 #include "base/path_service.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "build/build_config.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_commands.h"
22 #include "chrome/browser/ui/browser_navigator_params.h"
23 #include "chrome/browser/ui/browser_tabstrip.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/browser/ui/chrome_pages.h"
26 #include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h"
27 #include "chrome/browser/ui/location_bar/location_bar.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/browser/ui/view_ids.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/test/base/chrome_test_utils.h"
33 #include "chrome/test/base/in_process_browser_test.h"
34 #include "chrome/test/base/interactive_test_utils.h"
35 #include "chrome/test/base/ui_test_utils.h"
36 #include "components/omnibox/browser/autocomplete_match_type.h"
37 #include "components/omnibox/browser/omnibox_edit_controller.h"
38 #include "components/omnibox/browser/omnibox_edit_model.h"
39 #include "components/omnibox/browser/omnibox_view.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/notification_types.h"
42 #include "content/public/browser/render_frame_host.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/browser/render_widget_host.h"
45 #include "content/public/browser/render_widget_host_view.h"
46 #include "content/public/browser/web_contents.h"
47 #include "content/public/test/browser_test.h"
48 #include "content/public/test/browser_test_utils.h"
49 #include "content/public/test/test_navigation_observer.h"
50 #include "net/test/embedded_test_server/embedded_test_server.h"
51 #include "ui/base/test/ui_controls.h"
52 
53 namespace {
54 
55 using content::RenderViewHost;
56 using content::WebContents;
57 
58 #if defined(OS_POSIX)
59 // The delay waited in some cases where we don't have a notifications for an
60 // action we take.
61 const int kActionDelayMs = 500;
62 #endif
63 
64 const char kSimplePage[] = "/focus/page_with_focus.html";
65 const char kStealFocusPage[] = "/focus/page_steals_focus.html";
66 const char kTypicalPage[] = "/focus/typical_page.html";
67 
68 class BrowserFocusTest : public InProcessBrowserTest {
69  public:
70   // InProcessBrowserTest overrides:
SetUpOnMainThread()71   void SetUpOnMainThread() override {
72     ASSERT_TRUE(embedded_test_server()->Start());
73   }
74 
IsViewFocused(ViewID vid)75   bool IsViewFocused(ViewID vid) {
76     return ui_test_utils::IsViewFocused(browser(), vid);
77   }
78 
ClickOnView(ViewID vid)79   void ClickOnView(ViewID vid) { ui_test_utils::ClickOnView(browser(), vid); }
80 
TestFocusTraversal(RenderViewHost * render_view_host,bool reverse)81   void TestFocusTraversal(RenderViewHost* render_view_host, bool reverse) {
82     const char kGetFocusedElementJS[] =
83         "window.domAutomationController.send(getFocusedElement());";
84     const char* kExpectedIDs[] = {"textEdit",   "searchButton", "luckyButton",
85                                   "googleLink", "gmailLink",    "gmapLink"};
86     SCOPED_TRACE(base::StringPrintf("TestFocusTraversal: reverse=%d", reverse));
87     ui::KeyboardCode key = ui::VKEY_TAB;
88 #if defined(OS_MAC)
89     // TODO(msw): Mac requires ui::VKEY_BACKTAB for reverse cycling. Sigh...
90     key = reverse ? ui::VKEY_BACKTAB : ui::VKEY_TAB;
91 #endif
92 
93     // Loop through the focus chain twice for good measure.
94     for (size_t i = 0; i < 2; ++i) {
95       SCOPED_TRACE(base::StringPrintf("focus outer loop: %" PRIuS, i));
96       ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
97 
98       // Mac requires an extra Tab key press to traverse the app menu button
99       // iff "Full Keyboard Access" is enabled. In reverse, four Tab key presses
100       // are required to traverse the back/forward buttons and the tab strip.
101 #if defined(OS_MAC)
102       constexpr int kFocusableElementsBeforeOmnibox = 4;
103       constexpr int kFocusableElementsAfterOmnibox = 1;
104       if (ui_controls::IsFullKeyboardAccessEnabled()) {
105         for (int j = 0; j < (reverse ? kFocusableElementsBeforeOmnibox
106                                      : kFocusableElementsAfterOmnibox);
107              ++j) {
108           ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
109                                                       reverse, false, false));
110         }
111       }
112 #endif
113 
114       if (reverse) {
115         ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
116                                                     reverse, false, false));
117       }
118 
119       for (size_t j = 0; j < base::size(kExpectedIDs); ++j) {
120         SCOPED_TRACE(base::StringPrintf("focus inner loop %" PRIuS, j));
121         const size_t index = reverse ? base::size(kExpectedIDs) - 1 - j : j;
122         // The details are the node's editable state, i.e. true for "textEdit".
123         bool is_editable_node = index == 0;
124 
125         // Press Tab (or Shift+Tab) and check the focused element id.
126         auto source = content::Source<RenderViewHost>(render_view_host);
127         ui_test_utils::WindowedNotificationObserverWithDetails<bool> observer(
128             content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, source);
129         ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
130                                                     reverse, false, false));
131         observer.Wait();
132         bool observed_editable_node;
133         ASSERT_TRUE(
134             observer.GetDetailsFor(source.map_key(), &observed_editable_node));
135         EXPECT_EQ(is_editable_node, observed_editable_node);
136 
137         std::string focused_id;
138         EXPECT_TRUE(content::ExecuteScriptAndExtractString(
139             WebContents::FromRenderViewHost(render_view_host),
140             kGetFocusedElementJS, &focused_id));
141         EXPECT_STREQ(kExpectedIDs[index], focused_id.c_str());
142       }
143 
144       // On the last Tab key press, focus returns to the browser.
145       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
146                                                   reverse, false, false));
147 
148       // Except on Mac, where extra tabs are once again required to traverse the
149       // other top chrome elements.
150 #if defined(OS_MAC)
151       if (ui_controls::IsFullKeyboardAccessEnabled()) {
152         for (int j = 0; j < (reverse ? kFocusableElementsAfterOmnibox
153                                      : kFocusableElementsBeforeOmnibox);
154              ++j) {
155           ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
156                                                       reverse, false, false));
157         }
158       }
159 #endif
160 
161       ui_test_utils::WaitForViewFocus(
162           browser(), reverse ? VIEW_ID_OMNIBOX : VIEW_ID_LOCATION_ICON, true);
163 
164       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
165                                                   reverse, false, false));
166       ui_test_utils::WaitForViewFocus(
167           browser(), reverse ? VIEW_ID_LOCATION_ICON : VIEW_ID_OMNIBOX, true);
168       if (reverse) {
169         ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false,
170                                                     false, false, false));
171       }
172     }
173   }
174 };
175 
176 // Flaky on Mac (http://crbug.com/67301).
177 #if defined(OS_MAC)
178 #define MAYBE_ClickingMovesFocus DISABLED_ClickingMovesFocus
179 #else
180 // If this flakes, disable and log details in http://crbug.com/523255.
181 #define MAYBE_ClickingMovesFocus ClickingMovesFocus
182 #endif
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,MAYBE_ClickingMovesFocus)183 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_ClickingMovesFocus) {
184   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
185 #if defined(OS_POSIX)
186   // It seems we have to wait a little bit for the widgets to spin up before
187   // we can start clicking on them.
188   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
189       FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
190       base::TimeDelta::FromMilliseconds(kActionDelayMs));
191   content::RunMessageLoop();
192 #endif  // defined(OS_POSIX)
193 
194   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
195 
196   ClickOnView(VIEW_ID_TAB_CONTAINER);
197   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
198 
199   ClickOnView(VIEW_ID_OMNIBOX);
200   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
201 }
202 
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,BrowsersRememberFocus)203 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BrowsersRememberFocus) {
204   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
205   const GURL url = embedded_test_server()->GetURL(kSimplePage);
206   ui_test_utils::NavigateToURL(browser(), url);
207 
208   gfx::NativeWindow window = browser()->window()->GetNativeWindow();
209 
210   // The focus should be on the Tab contents.
211   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
212   // Now hide the window, show it again, the focus should not have changed.
213   ui_test_utils::HideNativeWindow(window);
214   ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
215   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
216 
217   chrome::FocusLocationBar(browser());
218   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
219   // Hide the window, show it again, the focus should not have changed.
220   ui_test_utils::HideNativeWindow(window);
221   ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
222   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
223 }
224 
225 // Tabs remember focus.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,TabsRememberFocus)226 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocus) {
227   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
228   const GURL url = embedded_test_server()->GetURL(kSimplePage);
229   ui_test_utils::NavigateToURL(browser(), url);
230 
231   // Create several tabs.
232   for (int i = 0; i < 4; ++i) {
233     chrome::AddSelectedTabWithURL(browser(), url, ui::PAGE_TRANSITION_TYPED);
234   }
235 
236   // Alternate focus for the tab.
237   const bool kFocusPage[3][5] = {{true, true, true, true, false},
238                                  {false, false, false, false, false},
239                                  {false, true, false, true, false}};
240 
241   for (int i = 0; i < 3; i++) {
242     for (int j = 0; j < 5; j++) {
243       // Activate the tab.
244       browser()->tab_strip_model()->ActivateTabAt(
245           j, {TabStripModel::GestureType::kOther});
246 
247       // Activate the location bar or the page.
248       if (kFocusPage[i][j]) {
249         browser()->tab_strip_model()->GetWebContentsAt(j)->Focus();
250       } else {
251         chrome::FocusLocationBar(browser());
252       }
253     }
254 
255     // Now come back to the tab and check the right view is focused.
256     for (int j = 0; j < 5; j++) {
257       // Activate the tab.
258       browser()->tab_strip_model()->ActivateTabAt(
259           j, {TabStripModel::GestureType::kOther});
260 
261       ViewID vid = kFocusPage[i][j] ? VIEW_ID_TAB_CONTAINER : VIEW_ID_OMNIBOX;
262       ASSERT_TRUE(IsViewFocused(vid));
263     }
264 
265     browser()->tab_strip_model()->ActivateTabAt(
266         0, {TabStripModel::GestureType::kOther});
267     // Try the above, but with ctrl+tab. Since tab normally changes focus,
268     // this has regressed in the past. Loop through several times to be sure.
269     for (int j = 0; j < 15; j++) {
270       ViewID vid =
271           kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER : VIEW_ID_OMNIBOX;
272       ASSERT_TRUE(IsViewFocused(vid));
273 
274       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB, true,
275                                                   false, false, false));
276     }
277 
278     // As above, but with ctrl+shift+tab.
279     browser()->tab_strip_model()->ActivateTabAt(
280         4, {TabStripModel::GestureType::kOther});
281     for (int j = 14; j >= 0; --j) {
282       ViewID vid =
283           kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER : VIEW_ID_OMNIBOX;
284       ASSERT_TRUE(IsViewFocused(vid));
285 
286       ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB, true,
287                                                   true, false, false));
288     }
289   }
290 }
291 
292 // Tabs remember focus with find-in-page box.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,TabsRememberFocusFindInPage)293 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocusFindInPage) {
294   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
295   const GURL url = embedded_test_server()->GetURL(kSimplePage);
296   ui_test_utils::NavigateToURL(browser(), url);
297 
298   chrome::Find(browser());
299   ui_test_utils::FindInPage(
300       browser()->tab_strip_model()->GetActiveWebContents(),
301       base::ASCIIToUTF16("a"), true, false, NULL, NULL);
302   ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
303 
304   // Focus the location bar.
305   chrome::FocusLocationBar(browser());
306 
307   // Create a 2nd tab.
308   chrome::AddSelectedTabWithURL(browser(), url, ui::PAGE_TRANSITION_TYPED);
309 
310   // Focus should be on the recently opened tab page.
311   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
312 
313   // Select 1st tab, focus should still be on the location-bar.
314   // (bug http://crbug.com/23296)
315   browser()->tab_strip_model()->ActivateTabAt(
316       0, {TabStripModel::GestureType::kOther});
317   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
318 
319   // Now open the find box again, switch to another tab and come back, the focus
320   // should return to the find box.
321   chrome::Find(browser());
322   ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
323   browser()->tab_strip_model()->ActivateTabAt(
324       1, {TabStripModel::GestureType::kOther});
325   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
326   browser()->tab_strip_model()->ActivateTabAt(
327       0, {TabStripModel::GestureType::kOther});
328   ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
329 }
330 
331 // Background window does not steal focus.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,BackgroundBrowserDontStealFocus)332 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BackgroundBrowserDontStealFocus) {
333   // Ensure the browser process state is in sync with the WindowServer process.
334   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
335 
336   // Open a new browser window.
337   Browser* background_browser =
338       Browser::Create(Browser::CreateParams(browser()->profile(), true));
339   chrome::AddTabAt(background_browser, GURL(), -1, true);
340   background_browser->window()->Show();
341 
342   const GURL steal_focus_url = embedded_test_server()->GetURL(kStealFocusPage);
343   ui_test_utils::NavigateToURL(background_browser, steal_focus_url);
344 
345   // The navigation will activate |background_browser|. Except, on some
346   // platforms, that may be asynchronous. Ensure the activation is properly
347   // reflected in the browser process by activating again.
348   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(background_browser));
349   EXPECT_TRUE(background_browser->window()->IsActive());
350 
351   // Activate the first browser (again). Note BringBrowserWindowToFront() does
352   // Show() and Focus(), but not Activate(), which is needed for Desktop Linux.
353   browser()->window()->Activate();
354   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
355   EXPECT_TRUE(browser()->window()->IsActive());
356   ASSERT_TRUE(content::ExecuteScript(
357       background_browser->tab_strip_model()->GetActiveWebContents(),
358       "stealFocus();"));
359 
360   // Try flushing tasks. Note that on Mac and Desktop Linux, window activation
361   // is asynchronous. There's no way to guarantee that the WindowServer process
362   // has actually activated a window without waiting for the activation event.
363   // But this test is checking that _no_ activation event occurs. So there is
364   // nothing to wait for. So, assuming the test fails and |unfocused_browser|
365   // _did_ activate, the expectation below still isn't guaranteed to fail after
366   // flushing run loops.
367   content::RunAllTasksUntilIdle();
368 
369   // Make sure the first browser is still active.
370   EXPECT_TRUE(browser()->window()->IsActive());
371 }
372 
373 // Page cannot steal focus when focus is on location bar.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,LocationBarLockFocus)374 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, LocationBarLockFocus) {
375   // Open the page that steals focus.
376   const GURL url = embedded_test_server()->GetURL(kStealFocusPage);
377   ui_test_utils::NavigateToURL(browser(), url);
378 
379   chrome::FocusLocationBar(browser());
380 
381   ASSERT_TRUE(content::ExecuteScript(
382       browser()->tab_strip_model()->GetActiveWebContents(), "stealFocus();"));
383 
384   // Make sure the location bar is still focused.
385   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
386 }
387 
388 // Test forward and reverse focus traversal on a typical page.
389 // Disabled for Mac because it is flaky on "Mac10.9 Tests (dbg)",
390 // see https://crbug.com/60973.
391 #if defined(OS_MAC)
392 #define MAYBE_FocusTraversal DISABLED_FocusTraversal
393 #else
394 #define MAYBE_FocusTraversal FocusTraversal
395 #endif
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,MAYBE_FocusTraversal)396 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusTraversal) {
397   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
398   const GURL url = embedded_test_server()->GetURL(kTypicalPage);
399   ui_test_utils::NavigateToURL(browser(), url);
400   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
401   chrome::FocusLocationBar(browser());
402 
403   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
404   EXPECT_NO_FATAL_FAILURE(
405       TestFocusTraversal(tab->GetMainFrame()->GetRenderViewHost(), false));
406   EXPECT_NO_FATAL_FAILURE(
407       TestFocusTraversal(tab->GetMainFrame()->GetRenderViewHost(), true));
408 }
409 
410 // Test that find-in-page UI can request focus, even when it is already open.
411 #if defined(OS_MAC)
412 #define MAYBE_FindFocusTest DISABLED_FindFocusTest
413 #else
414 // If this flakes, disable and log details in http://crbug.com/523255.
415 #define MAYBE_FindFocusTest FindFocusTest
416 #endif
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,MAYBE_FindFocusTest)417 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FindFocusTest) {
418   chrome::DisableFindBarAnimationsDuringTesting(true);
419   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
420   const GURL url = embedded_test_server()->GetURL(kTypicalPage);
421   ui_test_utils::NavigateToURL(browser(), url);
422   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
423 
424   chrome::Find(browser());
425   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
426 
427   chrome::FocusLocationBar(browser());
428   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
429 
430   chrome::Find(browser());
431   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
432 
433   ClickOnView(VIEW_ID_TAB_CONTAINER);
434   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
435 
436   chrome::Find(browser());
437   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
438 }
439 
440 // Makes sure the focus is in the right location when opening the different
441 // types of tabs.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,TabInitialFocus)442 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) {
443   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
444 
445   // Open the history tab, focus should be on the tab contents.
446   chrome::ShowHistory(browser());
447   ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(content::WaitForLoadStop(
448       browser()->tab_strip_model()->GetActiveWebContents())));
449   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
450 
451   // Open the new tab, focus should be on the location bar.
452   chrome::NewTab(browser());
453   ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(content::WaitForLoadStop(
454       browser()->tab_strip_model()->GetActiveWebContents())));
455   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
456 
457   // Open the download tab, focus should be on the tab contents.
458   chrome::ShowDownloads(browser());
459   ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(content::WaitForLoadStop(
460       browser()->tab_strip_model()->GetActiveWebContents())));
461   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
462 
463   // Open about:blank, focus should be on the location bar.
464   chrome::AddSelectedTabWithURL(browser(), GURL(url::kAboutBlankURL),
465                                 ui::PAGE_TRANSITION_LINK);
466   ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(content::WaitForLoadStop(
467       browser()->tab_strip_model()->GetActiveWebContents())));
468   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
469 }
470 
471 // Tests that focus goes where expected when using reload.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,FocusOnReload)472 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusOnReload) {
473   // Open the new tab, reload.
474   {
475     content::WindowedNotificationObserver observer(
476         content::NOTIFICATION_LOAD_STOP,
477         content::NotificationService::AllSources());
478     chrome::NewTab(browser());
479     observer.Wait();
480   }
481   content::RunAllPendingInMessageLoop();
482 
483   {
484     content::WindowedNotificationObserver observer(
485         content::NOTIFICATION_LOAD_STOP,
486         content::Source<content::NavigationController>(
487             &browser()
488                  ->tab_strip_model()
489                  ->GetActiveWebContents()
490                  ->GetController()));
491     chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
492     observer.Wait();
493   }
494   // Focus should stay on the location bar.
495   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
496 
497   // Open a regular page, focus the location bar, reload.
498   ui_test_utils::NavigateToURL(browser(),
499                                embedded_test_server()->GetURL(kSimplePage));
500   chrome::FocusLocationBar(browser());
501   ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
502   {
503     content::WindowedNotificationObserver observer(
504         content::NOTIFICATION_LOAD_STOP,
505         content::Source<content::NavigationController>(
506             &browser()
507                  ->tab_strip_model()
508                  ->GetActiveWebContents()
509                  ->GetController()));
510     chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
511     observer.Wait();
512   }
513 
514   // Focus should now be on the tab contents.
515   chrome::ShowDownloads(browser());
516   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
517 }
518 
519 // Tests that focus goes where expected when using reload on a crashed tab.
520 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
521 // Hangy, http://crbug.com/50025.
522 #define MAYBE_FocusOnReloadCrashedTab DISABLED_FocusOnReloadCrashedTab
523 #else
524 #define MAYBE_FocusOnReloadCrashedTab FocusOnReloadCrashedTab
525 #endif
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,MAYBE_FocusOnReloadCrashedTab)526 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusOnReloadCrashedTab) {
527   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
528 
529   // Open a regular page, crash, reload.
530   ui_test_utils::NavigateToURL(browser(),
531                                embedded_test_server()->GetURL(kSimplePage));
532   content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
533   {
534     content::WindowedNotificationObserver observer(
535         content::NOTIFICATION_LOAD_STOP,
536         content::Source<content::NavigationController>(
537             &browser()
538                  ->tab_strip_model()
539                  ->GetActiveWebContents()
540                  ->GetController()));
541     chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
542     observer.Wait();
543   }
544 
545   // Focus should now be on the tab contents.
546   chrome::ShowDownloads(browser());
547   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
548 }
549 
550 // Tests that focus goes to frame after crashed tab.
551 // TODO(shrikant): Find out where the focus should be deterministically.
552 // Currently focused_view after crash seem to be non null in debug mode
553 // (invalidated pointer 0xcccccc).
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,DISABLED_FocusAfterCrashedTab)554 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusAfterCrashedTab) {
555   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
556 
557   content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
558 
559   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
560 }
561 
562 // Tests that when omnibox triggers a navigation, then the focus is moved into
563 // the current tab.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,NavigateFromOmnibox)564 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NavigateFromOmnibox) {
565   const GURL url = embedded_test_server()->GetURL("/title1.html");
566 
567   // Focus the Omnibox.
568   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
569   chrome::FocusLocationBar(browser());
570   OmniboxView* view = browser()->window()->GetLocationBar()->GetOmniboxView();
571 
572   // Simulate typing a URL into the omnibox.
573   view->SetUserText(base::UTF8ToUTF16(url.spec()));
574   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
575   EXPECT_FALSE(view->IsSelectAll());
576 
577   // Simulate pressing Enter and wait until the navigation starts.
578   content::WebContents* web_contents =
579       chrome_test_utils::GetActiveWebContents(this);
580   content::TestNavigationManager nav_manager(web_contents, url);
581   ASSERT_TRUE(ui_controls::SendKeyPress(browser()->window()->GetNativeWindow(),
582                                         ui::VKEY_RETURN, false, false, false,
583                                         false));
584   ASSERT_TRUE(nav_manager.WaitForRequestStart());
585 
586   // Verify that a navigation has started.
587   EXPECT_TRUE(web_contents->GetController().GetPendingEntry());
588   // Verify that the Omnibox text is not selected - this is a regression test
589   // for https://crbug.com/1048742.
590   EXPECT_FALSE(view->IsSelectAll());
591   // Intentionally not asserting anything about IsViewFocused in this
592   // _intermediate_ state.
593 
594   // Wait for the navigation to finish and verify final, steady state.
595   nav_manager.WaitForNavigationFinished();
596   EXPECT_TRUE(nav_manager.was_successful());
597   EXPECT_EQ(url, web_contents->GetLastCommittedURL());
598   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
599   EXPECT_FALSE(view->IsSelectAll());
600 }
601 
602 // Tests that when a new tab is opened from the omnibox, the focus is moved from
603 // the omnibox for the current tab.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,NavigateFromOmniboxIntoNewTab)604 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NavigateFromOmniboxIntoNewTab) {
605   GURL url("http://www.google.com/");
606   GURL url2("http://maps.google.com/");
607 
608   // Navigate to url.
609   NavigateParams p(browser(), url, ui::PAGE_TRANSITION_LINK);
610   p.window_action = NavigateParams::SHOW_WINDOW;
611   p.disposition = WindowOpenDisposition::CURRENT_TAB;
612   Navigate(&p);
613 
614   // Focus the omnibox.
615   chrome::FocusLocationBar(browser());
616 
617   OmniboxEditController* controller = browser()
618                                           ->window()
619                                           ->GetLocationBar()
620                                           ->GetOmniboxView()
621                                           ->model()
622                                           ->controller();
623 
624   // Simulate an alt-enter.
625   controller->OnAutocompleteAccept(
626       url2, nullptr, WindowOpenDisposition::NEW_FOREGROUND_TAB,
627       ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::URL_WHAT_YOU_TYPED,
628       base::TimeTicks());
629 
630   // Make sure the second tab is selected.
631   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
632 
633   // The tab contents should have the focus in the second tab.
634   EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
635 
636   // Go back to the first tab. The focus should not be in the omnibox.
637   chrome::SelectPreviousTab(browser());
638   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
639   EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
640 }
641 
642 // Flaky on all platforms (http://crbug.com/665296).
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,DISABLED_FocusOnNavigate)643 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnNavigate) {
644   // Needed on Mac.
645   // TODO(warx): check why it is needed on Mac.
646   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
647   // Load the NTP.
648   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
649   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
650 
651   // Navigate to another page.
652   const base::FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html");
653   GURL file_url(ui_test_utils::GetTestUrl(
654       base::FilePath(base::FilePath::kCurrentDirectory),
655       base::FilePath(kEmptyFile)));
656   ui_test_utils::NavigateToURL(browser(), file_url);
657 
658   ClickOnView(VIEW_ID_TAB_CONTAINER);
659 
660   // Navigate back.  Should focus the location bar.
661   {
662     content::WindowedNotificationObserver back_nav_observer(
663         content::NOTIFICATION_NAV_ENTRY_COMMITTED,
664         content::NotificationService::AllSources());
665     chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
666     back_nav_observer.Wait();
667   }
668 
669   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
670 
671   // Navigate forward.  Shouldn't focus the location bar.
672   ClickOnView(VIEW_ID_TAB_CONTAINER);
673   {
674     content::WindowedNotificationObserver forward_nav_observer(
675         content::NOTIFICATION_NAV_ENTRY_COMMITTED,
676         content::NotificationService::AllSources());
677     chrome::GoForward(browser(), WindowOpenDisposition::CURRENT_TAB);
678     forward_nav_observer.Wait();
679   }
680 
681   EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
682 }
683 
684 // Ensure that crbug.com/567445 does not regress. This test checks that the
685 // Omnibox does not get focused when loading about:blank in a case where it's
686 // not the startup URL, e.g. when a page opens a popup to about:blank, with a
687 // null opener, and then navigates it. This is a potential security issue; see
688 // comments in |WebContentsImpl::FocusLocationBarByDefault|.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,AboutBlankNavigationLocationTest)689 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, AboutBlankNavigationLocationTest) {
690   const GURL url1 = embedded_test_server()->GetURL("/title1.html");
691   ui_test_utils::NavigateToURL(browser(), url1);
692 
693   TabStripModel* tab_strip = browser()->tab_strip_model();
694   WebContents* web_contents = tab_strip->GetActiveWebContents();
695 
696   const GURL url2 = embedded_test_server()->GetURL("/title2.html");
697   const std::string spoof =
698       "var w = window.open('about:blank'); w.opener = null;"
699       "w.document.location = '" +
700       url2.spec() + "';";
701 
702   ASSERT_TRUE(content::ExecuteScript(web_contents, spoof));
703   EXPECT_EQ(url1, web_contents->GetVisibleURL());
704   // After running the spoof code, |GetActiveWebContents| returns the new tab,
705   // not the same as |web_contents|.
706   ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(content::WaitForLoadStop(
707       browser()->tab_strip_model()->GetActiveWebContents())));
708   EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
709 }
710 
711 // Regression test for https://crbug.com/677716.  This ensures that the omnibox
712 // does not get focused if another tab in the same window navigates to the New
713 // Tab Page, since that can scroll the origin of the selected tab out of view.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,NoFocusForBackgroundNTP)714 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NoFocusForBackgroundNTP) {
715   // Start at the NTP and navigate to a test page.  We will later go back to the
716   // NTP, which gives the omnibox focus in some cases.
717   chrome::NewTab(browser());
718   ui_test_utils::NavigateToURL(browser(),
719                                embedded_test_server()->GetURL("/title1.html"));
720 
721   TabStripModel* tab_strip = browser()->tab_strip_model();
722   WebContents* opener_web_contents = tab_strip->GetActiveWebContents();
723 
724   // Open a second tab from the test page.
725   const GURL new_url = embedded_test_server()->GetURL("/title2.html");
726   const std::string open_script = "window.open('" + new_url.spec() + "');";
727   content::WebContentsAddedObserver open_observer;
728   ASSERT_TRUE(content::ExecuteScript(opener_web_contents, open_script));
729   WebContents* new_web_contents = open_observer.GetWebContents();
730 
731   // Tell the first (non-selected) tab to go back.  This should not give the
732   // omnibox focus, since the navigation occurred in a different tab.  Otherwise
733   // the focus may scroll the origin out of view, making a spoof possible.
734   const std::string go_back_script = "window.opener.history.back();";
735   content::TestNavigationObserver back_observer(opener_web_contents);
736   ASSERT_TRUE(content::ExecuteScript(new_web_contents, go_back_script));
737   back_observer.Wait();
738   EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
739 }
740 
741 // Tests that the location bar is focusable when showing, which is the case in
742 // popup windows.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,PopupLocationBar)743 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, PopupLocationBar) {
744   Browser* popup_browser = CreateBrowserForPopup(browser()->profile());
745 
746   // Make sure the popup is in the front. Otherwise the test is flaky.
747   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(popup_browser));
748 
749   ui_test_utils::FocusView(popup_browser, VIEW_ID_TAB_CONTAINER);
750   EXPECT_TRUE(
751       ui_test_utils::IsViewFocused(popup_browser, VIEW_ID_TAB_CONTAINER));
752 
753   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(popup_browser, ui::VKEY_TAB,
754                                               false, false, false, false));
755   ui_test_utils::WaitForViewFocus(popup_browser, VIEW_ID_LOCATION_ICON, true);
756 
757   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(popup_browser, ui::VKEY_TAB,
758                                               false, false, false, false));
759   ui_test_utils::WaitForViewFocus(popup_browser, VIEW_ID_OMNIBOX, true);
760 
761   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(popup_browser, ui::VKEY_TAB,
762                                               false, false, false, false));
763   ui_test_utils::WaitForViewFocus(popup_browser, VIEW_ID_TAB_CONTAINER, true);
764 }
765 
766 // Tests that the location bar is not focusable when hidden, which is the case
767 // in app windows.
IN_PROC_BROWSER_TEST_F(BrowserFocusTest,AppLocationBar)768 IN_PROC_BROWSER_TEST_F(BrowserFocusTest, AppLocationBar) {
769   Browser* app_browser = CreateBrowserForApp("foo", browser()->profile());
770 
771   // Make sure the app window is in the front. Otherwise the test is flaky.
772   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(app_browser));
773 
774   ui_test_utils::FocusView(app_browser, VIEW_ID_TAB_CONTAINER);
775   EXPECT_TRUE(ui_test_utils::IsViewFocused(app_browser, VIEW_ID_TAB_CONTAINER));
776 
777   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(app_browser, ui::VKEY_TAB, false,
778                                               false, false, false));
779   base::RunLoop().RunUntilIdle();
780   ui_test_utils::WaitForViewFocus(app_browser, VIEW_ID_TAB_CONTAINER, true);
781 }
782 
783 }  // namespace
784