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 "base/bind.h"
6#include "base/files/file_util.h"
7#include "base/format_macros.h"
8#include "base/message_loop/message_loop.h"
9#include "base/path_service.h"
10#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
12#include "chrome/browser/chrome_notification_types.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/browser_commands.h"
15#include "chrome/browser/ui/browser_tabstrip.h"
16#include "chrome/browser/ui/browser_window.h"
17#include "chrome/browser/ui/chrome_pages.h"
18#include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h"
19#include "chrome/browser/ui/location_bar/location_bar.h"
20#include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
21#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
22#include "chrome/browser/ui/omnibox/omnibox_view.h"
23#include "chrome/browser/ui/tabs/tab_strip_model.h"
24#include "chrome/browser/ui/view_ids.h"
25#include "chrome/common/chrome_paths.h"
26#include "chrome/common/url_constants.h"
27#include "chrome/test/base/in_process_browser_test.h"
28#include "chrome/test/base/interactive_test_utils.h"
29#include "chrome/test/base/ui_test_utils.h"
30#include "content/public/browser/interstitial_page.h"
31#include "content/public/browser/interstitial_page_delegate.h"
32#include "content/public/browser/notification_service.h"
33#include "content/public/browser/render_view_host.h"
34#include "content/public/browser/render_widget_host_view.h"
35#include "content/public/browser/web_contents.h"
36#include "content/public/test/browser_test_utils.h"
37#include "net/test/embedded_test_server/embedded_test_server.h"
38
39#if defined(OS_WIN)
40#include "base/win/windows_version.h"
41#endif
42
43using content::RenderViewHost;
44using content::WebContents;
45
46#if defined(OS_LINUX) || defined(OS_MACOSX)
47// TODO(jcampan): http://crbug.com/23683 for linux.
48// TODO(suzhe): http://crbug.com/49737 for mac.
49#define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
50#elif defined(OS_WIN)
51// Flaky, http://crbug.com/62537.
52#define MAYBE_TabsRememberFocusFindInPage DISABLED_TabsRememberFocusFindInPage
53#endif
54
55namespace {
56
57// The delay waited in some cases where we don't have a notifications for an
58// action we take.
59const int kActionDelayMs = 500;
60
61const char kSimplePage[] = "/focus/page_with_focus.html";
62const char kStealFocusPage[] = "/focus/page_steals_focus.html";
63const char kTypicalPage[] = "/focus/typical_page.html";
64
65class BrowserFocusTest : public InProcessBrowserTest {
66 public:
67   // InProcessBrowserTest overrides:
68   virtual void SetUpOnMainThread() OVERRIDE {
69     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
70   }
71
72  bool IsViewFocused(ViewID vid) {
73    return ui_test_utils::IsViewFocused(browser(), vid);
74  }
75
76  void ClickOnView(ViewID vid) {
77    ui_test_utils::ClickOnView(browser(), vid);
78  }
79
80  void TestFocusTraversal(RenderViewHost* render_view_host, bool reverse) {
81    const char kGetFocusedElementJS[] =
82        "window.domAutomationController.send(getFocusedElement());";
83    const char* kExpectedIDs[] = { "textEdit", "searchButton", "luckyButton",
84                                   "googleLink", "gmailLink", "gmapLink" };
85    SCOPED_TRACE(base::StringPrintf("TestFocusTraversal: reverse=%d", reverse));
86    ui::KeyboardCode key = ui::VKEY_TAB;
87#if defined(OS_MACOSX)
88    // TODO(msw): Mac requires ui::VKEY_BACKTAB for reverse cycling. Sigh...
89    key = reverse ? ui::VKEY_BACKTAB : ui::VKEY_TAB;
90#elif defined(OS_WIN)
91    // This loop times out on Windows XP with no output. http://crbug.com/376635
92    if (base::win::GetVersion() < base::win::VERSION_VISTA)
93      return;
94#endif
95
96    // Loop through the focus chain twice for good measure.
97    for (size_t i = 0; i < 2; ++i) {
98      SCOPED_TRACE(base::StringPrintf("focus outer loop: %" PRIuS, i));
99      ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
100      // Mac requires an extra Tab key press to traverse the app menu button
101      // iff "Full Keyboard Access" is enabled. This test code should probably
102      // check the setting via NSApplication's isFullKeyboardAccessEnabled.
103
104      for (size_t j = 0; j < arraysize(kExpectedIDs); ++j) {
105        SCOPED_TRACE(base::StringPrintf("focus inner loop %" PRIuS, j));
106        const size_t index = reverse ? arraysize(kExpectedIDs) - 1 - j : j;
107        // The details are the node's editable state, i.e. true for "textEdit".
108        bool is_editable_node = index == 0;
109
110        // Press Tab (or Shift+Tab) and check the focused element id.
111        ASSERT_TRUE(ui_test_utils::SendKeyPressAndWaitWithDetails(
112            browser(), key, false, reverse, false, false,
113            content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
114            content::Source<RenderViewHost>(render_view_host),
115            content::Details<bool>(&is_editable_node)));
116        std::string focused_id;
117        EXPECT_TRUE(content::ExecuteScriptAndExtractString(
118            render_view_host, kGetFocusedElementJS, &focused_id));
119        EXPECT_STREQ(kExpectedIDs[index], focused_id.c_str());
120      }
121
122#if defined(OS_MACOSX)
123      // TODO(msw): Mac doesn't post NOTIFICATION_FOCUS_RETURNED_TO_BROWSER and
124      // would also apparently require extra Tab key presses here. Sigh...
125      chrome::FocusLocationBar(browser());
126#else
127      // On the last Tab key press, focus returns to the browser.
128      ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
129          browser(), key, false, reverse, false, false,
130          chrome::NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
131          content::Source<Browser>(browser())));
132#endif
133      content::RunAllPendingInMessageLoop();
134      EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
135    }
136  }
137};
138
139// A helper class that waits for an interstitial page to attach.
140class WaitForInterstitial : public content::WebContentsObserver {
141 public:
142  explicit WaitForInterstitial(content::WebContents* tab)
143      : WebContentsObserver(tab),
144        runner_(new content::MessageLoopRunner) {
145    runner_->Run();
146  }
147
148  virtual void DidAttachInterstitialPage() OVERRIDE { runner_->Quit(); }
149  virtual void DidDetachInterstitialPage() OVERRIDE { NOTREACHED(); }
150
151 private:
152  scoped_refptr<content::MessageLoopRunner> runner_;
153  DISALLOW_COPY_AND_ASSIGN(WaitForInterstitial);
154};
155
156// A test interstitial page with typical HTML contents.
157class TestInterstitialPage : public content::InterstitialPageDelegate {
158 public:
159  explicit TestInterstitialPage(WebContents* tab) {
160    base::FilePath file_path;
161    bool success = PathService::Get(chrome::DIR_TEST_DATA, &file_path);
162    EXPECT_TRUE(success);
163    file_path = file_path.AppendASCII("focus/typical_page.html");
164    success = base::ReadFileToString(file_path, &html_contents_);
165    EXPECT_TRUE(success);
166    interstitial_page_ = content::InterstitialPage::Create(
167        tab, true, GURL("http://interstitial.com"), this);
168
169    // Show the interstitial and delay return until it has attached.
170    interstitial_page_->Show();
171    WaitForInterstitial wait(tab);
172    EXPECT_TRUE(tab->ShowingInterstitialPage());
173  }
174
175  virtual std::string GetHTMLContents() OVERRIDE { return html_contents_; }
176
177  RenderViewHost* render_view_host() {
178    return interstitial_page_->GetRenderViewHostForTesting();
179  }
180
181  void DontProceed() { interstitial_page_->DontProceed(); }
182
183  bool HasFocus() { return render_view_host()->GetView()->HasFocus(); }
184
185 private:
186  std::string html_contents_;
187  content::InterstitialPage* interstitial_page_;  // Owns this.
188  DISALLOW_COPY_AND_ASSIGN(TestInterstitialPage);
189};
190
191// Flaky on mac. http://crbug.com/67301.
192#if defined(OS_MACOSX)
193#define MAYBE_ClickingMovesFocus DISABLED_ClickingMovesFocus
194#else
195#define MAYBE_ClickingMovesFocus ClickingMovesFocus
196#endif
197IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_ClickingMovesFocus) {
198  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
199#if defined(OS_POSIX)
200  // It seems we have to wait a little bit for the widgets to spin up before
201  // we can start clicking on them.
202  base::MessageLoop::current()->PostDelayedTask(
203      FROM_HERE,
204      base::MessageLoop::QuitClosure(),
205      base::TimeDelta::FromMilliseconds(kActionDelayMs));
206  content::RunMessageLoop();
207#endif  // defined(OS_POSIX)
208
209  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
210
211  ClickOnView(VIEW_ID_TAB_CONTAINER);
212  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
213
214  ClickOnView(VIEW_ID_OMNIBOX);
215  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
216}
217
218// Flaky, http://crbug.com/69034.
219IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
220  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
221  const GURL url = embedded_test_server()->GetURL(kSimplePage);
222  ui_test_utils::NavigateToURL(browser(), url);
223
224  gfx::NativeWindow window = browser()->window()->GetNativeWindow();
225
226  // The focus should be on the Tab contents.
227  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
228  // Now hide the window, show it again, the focus should not have changed.
229  ui_test_utils::HideNativeWindow(window);
230  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
231  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
232
233  chrome::FocusLocationBar(browser());
234  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
235  // Hide the window, show it again, the focus should not have changed.
236  ui_test_utils::HideNativeWindow(window);
237  ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
238  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
239}
240
241// Tabs remember focus.
242// Disabled, http://crbug.com/62542.
243IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabsRememberFocus) {
244  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
245  const GURL url = embedded_test_server()->GetURL(kSimplePage);
246  ui_test_utils::NavigateToURL(browser(), url);
247
248  // Create several tabs.
249  for (int i = 0; i < 4; ++i) {
250    chrome::AddSelectedTabWithURL(browser(), url,
251                                  ui::PAGE_TRANSITION_TYPED);
252  }
253
254  // Alternate focus for the tab.
255  const bool kFocusPage[3][5] = {
256    { true, true, true, true, false },
257    { false, false, false, false, false },
258    { false, true, false, true, false }
259  };
260
261  for (int i = 1; i < 3; i++) {
262    for (int j = 0; j < 5; j++) {
263      // Activate the tab.
264      browser()->tab_strip_model()->ActivateTabAt(j, true);
265
266      // Activate the location bar or the page.
267      if (kFocusPage[i][j]) {
268        browser()->tab_strip_model()->GetWebContentsAt(j)->Focus();
269      } else {
270        chrome::FocusLocationBar(browser());
271      }
272    }
273
274    // Now come back to the tab and check the right view is focused.
275    for (int j = 0; j < 5; j++) {
276      // Activate the tab.
277      browser()->tab_strip_model()->ActivateTabAt(j, true);
278
279      ViewID vid = kFocusPage[i][j] ? VIEW_ID_TAB_CONTAINER : VIEW_ID_OMNIBOX;
280      ASSERT_TRUE(IsViewFocused(vid));
281    }
282
283    browser()->tab_strip_model()->ActivateTabAt(0, true);
284    // Try the above, but with ctrl+tab. Since tab normally changes focus,
285    // this has regressed in the past. Loop through several times to be sure.
286    for (int j = 0; j < 15; j++) {
287      ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
288                                          VIEW_ID_OMNIBOX;
289      ASSERT_TRUE(IsViewFocused(vid));
290
291      ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
292          browser(), ui::VKEY_TAB, true, false, false, false));
293    }
294
295    // As above, but with ctrl+shift+tab.
296    browser()->tab_strip_model()->ActivateTabAt(4, true);
297    for (int j = 14; j >= 0; --j) {
298      ViewID vid = kFocusPage[i][j % 5] ? VIEW_ID_TAB_CONTAINER :
299                                          VIEW_ID_OMNIBOX;
300      ASSERT_TRUE(IsViewFocused(vid));
301
302      ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
303          browser(), ui::VKEY_TAB, true, true, false, false));
304    }
305  }
306}
307
308// Tabs remember focus with find-in-page box.
309IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_TabsRememberFocusFindInPage) {
310  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
311  const GURL url = embedded_test_server()->GetURL(kSimplePage);
312  ui_test_utils::NavigateToURL(browser(), url);
313
314  chrome::Find(browser());
315  ui_test_utils::FindInPage(
316      browser()->tab_strip_model()->GetActiveWebContents(),
317      base::ASCIIToUTF16("a"), true, false, NULL, NULL);
318  ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
319
320  // Focus the location bar.
321  chrome::FocusLocationBar(browser());
322
323  // Create a 2nd tab.
324  chrome::AddSelectedTabWithURL(browser(), url, ui::PAGE_TRANSITION_TYPED);
325
326  // Focus should be on the recently opened tab page.
327  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
328
329  // Select 1st tab, focus should still be on the location-bar.
330  // (bug http://crbug.com/23296)
331  browser()->tab_strip_model()->ActivateTabAt(0, true);
332  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
333
334  // Now open the find box again, switch to another tab and come back, the focus
335  // should return to the find box.
336  chrome::Find(browser());
337  ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
338  browser()->tab_strip_model()->ActivateTabAt(1, true);
339  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
340  browser()->tab_strip_model()->ActivateTabAt(0, true);
341  ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
342}
343
344// Background window does not steal focus.
345// Flaky, http://crbug.com/62538.
346IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
347                       DISABLED_BackgroundBrowserDontStealFocus) {
348  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
349
350  // Open a new browser window.
351  Browser* browser2 =
352      new Browser(Browser::CreateParams(browser()->profile(),
353                                        browser()->host_desktop_type()));
354  ASSERT_TRUE(browser2);
355  chrome::AddTabAt(browser2, GURL(), -1, true);
356  browser2->window()->Show();
357
358  Browser* focused_browser = NULL;
359  Browser* unfocused_browser = NULL;
360#if defined(USE_X11)
361  // On X11, calling Activate() is not guaranteed to move focus, so we have
362  // to figure out which browser does have focus.
363  if (browser2->window()->IsActive()) {
364    focused_browser = browser2;
365    unfocused_browser = browser();
366  } else if (browser()->window()->IsActive()) {
367    focused_browser = browser();
368    unfocused_browser = browser2;
369  } else {
370    FAIL() << "Could not determine which browser has focus";
371  }
372#elif defined(OS_WIN)
373  focused_browser = browser();
374  unfocused_browser = browser2;
375#elif defined(OS_MACOSX)
376  // On Mac, the newly created window always gets the focus.
377  focused_browser = browser2;
378  unfocused_browser = browser();
379#endif
380
381  const GURL steal_focus_url = embedded_test_server()->GetURL(kStealFocusPage);
382  ui_test_utils::NavigateToURL(unfocused_browser, steal_focus_url);
383
384  // Activate the first browser.
385  focused_browser->window()->Activate();
386
387  ASSERT_TRUE(content::ExecuteScript(
388      unfocused_browser->tab_strip_model()->GetActiveWebContents(),
389      "stealFocus();"));
390
391  // Make sure the first browser is still active.
392  EXPECT_TRUE(focused_browser->window()->IsActive());
393}
394
395#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
396// TODO(erg): http://crbug.com/163931
397#define MAYBE_LocationBarLockFocus DISABLED_LocationBarLockFocus
398#else
399#define MAYBE_LocationBarLockFocus LocationBarLockFocus
400#endif
401
402// Page cannot steal focus when focus is on location bar.
403IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_LocationBarLockFocus) {
404  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
405
406  // Open the page that steals focus.
407  const GURL url = embedded_test_server()->GetURL(kStealFocusPage);
408  ui_test_utils::NavigateToURL(browser(), url);
409
410  chrome::FocusLocationBar(browser());
411
412  ASSERT_TRUE(content::ExecuteScript(
413      browser()->tab_strip_model()->GetActiveWebContents(),
414      "stealFocus();"));
415
416  // Make sure the location bar is still focused.
417  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
418}
419
420// Test forward and reverse focus traversal on a typical page.
421IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) {
422  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
423  const GURL url = embedded_test_server()->GetURL(kTypicalPage);
424  ui_test_utils::NavigateToURL(browser(), url);
425  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
426  chrome::FocusLocationBar(browser());
427
428  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
429  EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(tab->GetRenderViewHost(), false));
430  EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(tab->GetRenderViewHost(), true));
431}
432
433// Test forward and reverse focus traversal while an interstitial is showing.
434// Disabled, see http://crbug.com/60973
435IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusTraversalOnInterstitial) {
436  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
437  const GURL url = embedded_test_server()->GetURL(kSimplePage);
438  ui_test_utils::NavigateToURL(browser(), url);
439  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
440
441  // Create and show a test interstitial page.
442  TestInterstitialPage* interstitial_page = new TestInterstitialPage(
443      browser()->tab_strip_model()->GetActiveWebContents());
444  content::RenderViewHost* host = interstitial_page->render_view_host();
445
446  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
447  chrome::FocusLocationBar(browser());
448  EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(host, false));
449  EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(host, true));
450}
451
452// Test the transfer of focus when an interstitial is shown and hidden.
453IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) {
454  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
455  const GURL url = embedded_test_server()->GetURL(kSimplePage);
456  ui_test_utils::NavigateToURL(browser(), url);
457  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
458  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
459  EXPECT_TRUE(tab->GetRenderViewHost()->GetView()->HasFocus());
460
461  // Create and show a test interstitial page; it should gain focus.
462  TestInterstitialPage* interstitial_page = new TestInterstitialPage(tab);
463  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
464  EXPECT_TRUE(interstitial_page->HasFocus());
465
466  // Hide the interstitial; the original page should gain focus.
467  interstitial_page->DontProceed();
468  content::RunAllPendingInMessageLoop();
469  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
470  EXPECT_TRUE(tab->GetRenderViewHost()->GetView()->HasFocus());
471}
472
473// Test that find-in-page UI can request focus, even when it is already open.
474#if defined(OS_MACOSX)
475#define MAYBE_FindFocusTest DISABLED_FindFocusTest
476#else
477#define MAYBE_FindFocusTest FindFocusTest
478#endif
479IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FindFocusTest) {
480  chrome::DisableFindBarAnimationsDuringTesting(true);
481  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
482  const GURL url = embedded_test_server()->GetURL(kTypicalPage);
483  ui_test_utils::NavigateToURL(browser(), url);
484  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
485
486  chrome::ShowFindBar(browser());
487  EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
488
489  chrome::FocusLocationBar(browser());
490  EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
491
492  chrome::ShowFindBar(browser());
493  EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
494
495  ClickOnView(VIEW_ID_TAB_CONTAINER);
496  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
497
498  chrome::ShowFindBar(browser());
499  EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
500}
501
502// Makes sure the focus is in the right location when opening the different
503// types of tabs.
504// Flaky, http://crbug.com/62539.
505IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_TabInitialFocus) {
506  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
507
508  // Open the history tab, focus should be on the tab contents.
509  chrome::ShowHistory(browser());
510  ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
511      browser()->tab_strip_model()->GetActiveWebContents()));
512  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
513
514  // Open the new tab, focus should be on the location bar.
515  chrome::NewTab(browser());
516  ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
517      browser()->tab_strip_model()->GetActiveWebContents()));
518  EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
519
520  // Open the download tab, focus should be on the tab contents.
521  chrome::ShowDownloads(browser());
522  ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
523      browser()->tab_strip_model()->GetActiveWebContents()));
524  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
525
526  // Open about:blank, focus should be on the location bar.
527  chrome::AddSelectedTabWithURL(
528      browser(), GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK);
529  ASSERT_NO_FATAL_FAILURE(content::WaitForLoadStop(
530      browser()->tab_strip_model()->GetActiveWebContents()));
531  EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
532}
533
534#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
535// TODO(erg): http://crbug.com/163931
536#define MAYBE_FocusOnReload DISABLED_FocusOnReload
537#else
538#define MAYBE_FocusOnReload FocusOnReload
539#endif
540
541// Tests that focus goes where expected when using reload.
542IN_PROC_BROWSER_TEST_F(BrowserFocusTest, MAYBE_FocusOnReload) {
543  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
544
545  // Open the new tab, reload.
546  {
547    content::WindowedNotificationObserver observer(
548        content::NOTIFICATION_LOAD_STOP,
549        content::NotificationService::AllSources());
550    chrome::NewTab(browser());
551    observer.Wait();
552  }
553  content::RunAllPendingInMessageLoop();
554
555  {
556    content::WindowedNotificationObserver observer(
557        content::NOTIFICATION_LOAD_STOP,
558        content::Source<content::NavigationController>(
559            &browser()->tab_strip_model()->GetActiveWebContents()->
560                GetController()));
561    chrome::Reload(browser(), CURRENT_TAB);
562    observer.Wait();
563  }
564  // Focus should stay on the location bar.
565  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
566
567  // Open a regular page, focus the location bar, reload.
568  ui_test_utils::NavigateToURL(browser(),
569                               embedded_test_server()->GetURL(kSimplePage));
570  chrome::FocusLocationBar(browser());
571  ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
572  {
573    content::WindowedNotificationObserver observer(
574        content::NOTIFICATION_LOAD_STOP,
575        content::Source<content::NavigationController>(
576            &browser()->tab_strip_model()->GetActiveWebContents()->
577                GetController()));
578    chrome::Reload(browser(), CURRENT_TAB);
579    observer.Wait();
580  }
581
582  // Focus should now be on the tab contents.
583  chrome::ShowDownloads(browser());
584  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
585}
586
587// Tests that focus goes where expected when using reload on a crashed tab.
588IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnReloadCrashedTab) {
589  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
590
591  // Open a regular page, crash, reload.
592  ui_test_utils::NavigateToURL(browser(),
593                               embedded_test_server()->GetURL(kSimplePage));
594  content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
595  {
596    content::WindowedNotificationObserver observer(
597        content::NOTIFICATION_LOAD_STOP,
598        content::Source<content::NavigationController>(
599            &browser()->tab_strip_model()->GetActiveWebContents()->
600                GetController()));
601    chrome::Reload(browser(), CURRENT_TAB);
602    observer.Wait();
603  }
604
605  // Focus should now be on the tab contents.
606  chrome::ShowDownloads(browser());
607  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
608}
609
610// Tests that focus goes to frame after crashed tab.
611// TODO(shrikant): Find out where the focus should be deterministically.
612// Currently focused_view after crash seem to be non null in debug mode
613// (invalidated pointer 0xcccccc).
614IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusAfterCrashedTab) {
615  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
616
617  content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
618
619  ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
620}
621
622// Tests that when a new tab is opened from the omnibox, the focus is moved from
623// the omnibox for the current tab.
624IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NavigateFromOmniboxIntoNewTab) {
625  GURL url("http://www.google.com/");
626  GURL url2("http://maps.google.com/");
627
628  // Navigate to url.
629  chrome::NavigateParams p(browser(), url, ui::PAGE_TRANSITION_LINK);
630  p.window_action = chrome::NavigateParams::SHOW_WINDOW;
631  p.disposition = CURRENT_TAB;
632  chrome::Navigate(&p);
633
634  // Focus the omnibox.
635  chrome::FocusLocationBar(browser());
636
637  OmniboxEditController* controller = browser()->window()->GetLocationBar()->
638      GetOmniboxView()->model()->controller();
639
640  // Simulate an alt-enter.
641  controller->OnAutocompleteAccept(url2, NEW_FOREGROUND_TAB,
642                                   ui::PAGE_TRANSITION_TYPED);
643
644  // Make sure the second tab is selected.
645  EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
646
647  // The tab contents should have the focus in the second tab.
648  EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
649
650  // Go back to the first tab. The focus should not be in the omnibox.
651  chrome::SelectPreviousTab(browser());
652  EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
653  EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
654}
655
656// This functionality is currently broken. http://crbug.com/304865.
657//
658//#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
659//// TODO(erg): http://crbug.com/163931
660//#define MAYBE_FocusOnNavigate DISABLED_FocusOnNavigate
661//#else
662//#define MAYBE_FocusOnNavigate FocusOnNavigate
663//#endif
664
665IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusOnNavigate) {
666  // Needed on Mac.
667  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
668  // Load the NTP.
669  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
670  EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
671
672  // Navigate to another page.
673  const base::FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html");
674  GURL file_url(ui_test_utils::GetTestUrl(base::FilePath(
675      base::FilePath::kCurrentDirectory), base::FilePath(kEmptyFile)));
676  ui_test_utils::NavigateToURL(browser(), file_url);
677
678  ClickOnView(VIEW_ID_TAB_CONTAINER);
679
680  // Navigate back.  Should focus the location bar.
681  {
682    content::WindowedNotificationObserver back_nav_observer(
683        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
684        content::NotificationService::AllSources());
685    chrome::GoBack(browser(), CURRENT_TAB);
686    back_nav_observer.Wait();
687  }
688
689  EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
690
691  // Navigate forward.  Shouldn't focus the location bar.
692  ClickOnView(VIEW_ID_TAB_CONTAINER);
693  {
694    content::WindowedNotificationObserver forward_nav_observer(
695        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
696        content::NotificationService::AllSources());
697    chrome::GoForward(browser(), CURRENT_TAB);
698    forward_nav_observer.Wait();
699  }
700
701  EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX));
702}
703
704}  // namespace
705