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