Home | History | Annotate | Download | only in browser
      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 "build/build_config.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/chrome_notification_types.h"
     14 #include "chrome/browser/ui/browser.h"
     15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     16 #include "chrome/common/chrome_paths.h"
     17 #include "chrome/test/base/in_process_browser_test.h"
     18 #include "chrome/test/base/interactive_test_utils.h"
     19 #include "chrome/test/base/ui_test_utils.h"
     20 #include "content/public/browser/dom_operation_notification_details.h"
     21 #include "content/public/browser/notification_registrar.h"
     22 #include "content/public/browser/notification_service.h"
     23 #include "content/public/browser/render_view_host.h"
     24 #include "content/public/browser/render_widget_host_view.h"
     25 #include "content/public/browser/web_contents.h"
     26 #include "content/public/browser/web_contents_view.h"
     27 #include "content/public/test/browser_test_utils.h"
     28 #include "net/test/embedded_test_server/embedded_test_server.h"
     29 #include "ui/base/keycodes/keyboard_codes.h"
     30 #include "ui/views/controls/textfield/textfield.h"
     31 
     32 // TODO(kbr): remove: http://crbug.com/222296
     33 #if defined(OS_MACOSX)
     34 #import "base/mac/mac_util.h"
     35 #endif
     36 
     37 using content::DomOperationNotificationDetails;
     38 using content::NavigationController;
     39 using content::RenderViewHost;
     40 
     41 namespace {
     42 
     43 const char kTestingPage[] = "/keyevents_test.html";
     44 const char kSuppressEventJS[] =
     45     "window.domAutomationController.send(setDefaultAction('%ls', %ls));";
     46 const char kGetResultJS[] =
     47     "window.domAutomationController.send(keyEventResult[%d]);";
     48 const char kGetResultLengthJS[] =
     49     "window.domAutomationController.send(keyEventResult.length);";
     50 const char kGetFocusedElementJS[] =
     51     "window.domAutomationController.send(focusedElement);";
     52 const char kSetFocusedElementJS[] =
     53     "window.domAutomationController.send(setFocusedElement('%ls'));";
     54 const char kGetTextBoxValueJS[] =
     55     "window.domAutomationController.send("
     56     "    document.getElementById('%ls').value);";
     57 const char kSetTextBoxValueJS[] =
     58     "window.domAutomationController.send("
     59     "    document.getElementById('%ls').value = '%ls');";
     60 const char kStartTestJS[] =
     61     "window.domAutomationController.send(startTest(%d));";
     62 
     63 // Maximum lenght of the result array in KeyEventTestData structure.
     64 const size_t kMaxResultLength = 10;
     65 
     66 // A structure holding test data of a keyboard event.
     67 // Each keyboard event may generate multiple result strings representing
     68 // the result of keydown, keypress, keyup and textInput events.
     69 // For keydown, keypress and keyup events, the format of the result string is:
     70 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
     71 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
     72 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
     73 // the state of corresponding modifier key.
     74 // For textInput event, the format is: T <text>, where <text> is the text to be
     75 // input.
     76 // Please refer to chrome/test/data/keyevents_test.html for details.
     77 struct KeyEventTestData {
     78   ui::KeyboardCode key;
     79   bool ctrl;
     80   bool shift;
     81   bool alt;
     82   bool command;
     83 
     84   bool suppress_keydown;
     85   bool suppress_keypress;
     86   bool suppress_keyup;
     87   bool suppress_textinput;
     88 
     89   int result_length;
     90   const char* const result[kMaxResultLength];
     91 };
     92 
     93 const wchar_t* GetBoolString(bool value) {
     94   return value ? L"true" : L"false";
     95 }
     96 
     97 // A class to help wait for the finish of a key event test.
     98 class TestFinishObserver : public content::NotificationObserver {
     99  public:
    100   explicit TestFinishObserver(RenderViewHost* render_view_host)
    101       : finished_(false), waiting_(false) {
    102     registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
    103                    content::Source<RenderViewHost>(render_view_host));
    104   }
    105 
    106   bool WaitForFinish() {
    107     if (!finished_) {
    108       waiting_ = true;
    109       content::RunMessageLoop();
    110       waiting_ = false;
    111     }
    112     return finished_;
    113   }
    114 
    115   virtual void Observe(int type,
    116                        const content::NotificationSource& source,
    117                        const content::NotificationDetails& details) OVERRIDE {
    118     DCHECK(type == content::NOTIFICATION_DOM_OPERATION_RESPONSE);
    119     content::Details<DomOperationNotificationDetails> dom_op_details(details);
    120     // We might receive responses for other script execution, but we only
    121     // care about the test finished message.
    122     if (dom_op_details->json == "\"FINISHED\"") {
    123       finished_ = true;
    124       if (waiting_)
    125         base::MessageLoopForUI::current()->Quit();
    126     }
    127   }
    128 
    129  private:
    130   bool finished_;
    131   bool waiting_;
    132   content::NotificationRegistrar registrar_;
    133 
    134   DISALLOW_COPY_AND_ASSIGN(TestFinishObserver);
    135 };
    136 
    137 class BrowserKeyEventsTest : public InProcessBrowserTest {
    138  public:
    139   BrowserKeyEventsTest() {}
    140 
    141   bool IsViewFocused(ViewID vid) {
    142     return ui_test_utils::IsViewFocused(browser(), vid);
    143   }
    144 
    145   void ClickOnView(ViewID vid) {
    146     ui_test_utils::ClickOnView(browser(), vid);
    147   }
    148 
    149   // Set the suppress flag of an event specified by |type|. If |suppress| is
    150   // true then the web page will suppress all events with |type|. Following
    151   // event types are supported: keydown, keypress, keyup and textInput.
    152   void SuppressEventByType(int tab_index, const wchar_t* type, bool suppress) {
    153     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    154     bool actual;
    155     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    156         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    157         base::StringPrintf(kSuppressEventJS, type, GetBoolString(!suppress)),
    158         &actual));
    159     ASSERT_EQ(!suppress, actual);
    160   }
    161 
    162   void SuppressEvents(int tab_index, bool keydown, bool keypress,
    163                       bool keyup, bool textinput) {
    164     ASSERT_NO_FATAL_FAILURE(
    165         SuppressEventByType(tab_index, L"keydown", keydown));
    166     ASSERT_NO_FATAL_FAILURE(
    167         SuppressEventByType(tab_index, L"keypress", keypress));
    168     ASSERT_NO_FATAL_FAILURE(
    169         SuppressEventByType(tab_index, L"keyup", keyup));
    170     ASSERT_NO_FATAL_FAILURE(
    171         SuppressEventByType(tab_index, L"textInput", textinput));
    172   }
    173 
    174   void SuppressAllEvents(int tab_index, bool suppress) {
    175     SuppressEvents(tab_index, suppress, suppress, suppress, suppress);
    176   }
    177 
    178   void GetResultLength(int tab_index, int* length) {
    179     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    180     ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
    181         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    182         kGetResultLengthJS,
    183         length));
    184   }
    185 
    186   void CheckResult(int tab_index, int length, const char* const result[]) {
    187     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    188     int actual_length;
    189     ASSERT_NO_FATAL_FAILURE(GetResultLength(tab_index, &actual_length));
    190     ASSERT_GE(actual_length, length);
    191     for (int i = 0; i < actual_length; ++i) {
    192       std::string actual;
    193       ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    194           browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    195           base::StringPrintf(kGetResultJS, i),
    196           &actual));
    197 
    198       // If more events were received than expected, then the additional events
    199       // must be keyup events.
    200       if (i < length)
    201         ASSERT_STREQ(result[i], actual.c_str());
    202       else
    203         ASSERT_EQ('U', actual[0]);
    204     }
    205   }
    206 
    207   void CheckFocusedElement(int tab_index, const wchar_t* focused) {
    208     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    209     std::string actual;
    210     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    211         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    212         kGetFocusedElementJS,
    213         &actual));
    214     ASSERT_EQ(WideToUTF8(focused), actual);
    215   }
    216 
    217   void SetFocusedElement(int tab_index, const wchar_t* focused) {
    218     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    219     bool actual;
    220     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    221         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    222         base::StringPrintf(kSetFocusedElementJS, focused),
    223         &actual));
    224     ASSERT_TRUE(actual);
    225   }
    226 
    227   void CheckTextBoxValue(int tab_index, const wchar_t* id,
    228                          const wchar_t* value) {
    229     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    230     std::string actual;
    231     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    232         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    233         base::StringPrintf(kGetTextBoxValueJS, id),
    234         &actual));
    235     ASSERT_EQ(WideToUTF8(value), actual);
    236   }
    237 
    238   void SetTextBoxValue(int tab_index, const wchar_t* id,
    239                        const wchar_t* value) {
    240     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    241     std::string actual;
    242     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
    243         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    244         base::StringPrintf(kSetTextBoxValueJS, id, value),
    245         &actual));
    246     ASSERT_EQ(WideToUTF8(value), actual);
    247   }
    248 
    249   void StartTest(int tab_index, int result_length) {
    250     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    251     bool actual;
    252     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
    253         browser()->tab_strip_model()->GetWebContentsAt(tab_index),
    254         base::StringPrintf(kStartTestJS, result_length),
    255         &actual));
    256     ASSERT_TRUE(actual);
    257   }
    258 
    259   void TestKeyEvent(int tab_index, const KeyEventTestData& test) {
    260     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
    261     ASSERT_EQ(tab_index, browser()->tab_strip_model()->active_index());
    262 
    263     // Inform our testing web page that we are about to start testing a key
    264     // event.
    265     ASSERT_NO_FATAL_FAILURE(StartTest(tab_index, test.result_length));
    266     ASSERT_NO_FATAL_FAILURE(SuppressEvents(
    267         tab_index, test.suppress_keydown, test.suppress_keypress,
    268         test.suppress_keyup, test.suppress_textinput));
    269 
    270     // We need to create a finish observer before sending the key event,
    271     // because the test finished message might be arrived before returning
    272     // from the SendKeyPressSync() method.
    273     TestFinishObserver finish_observer(
    274         browser()->tab_strip_model()->GetWebContentsAt(tab_index)->
    275             GetRenderViewHost());
    276 
    277     ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
    278         browser(), test.key, test.ctrl, test.shift, test.alt, test.command));
    279     ASSERT_TRUE(finish_observer.WaitForFinish());
    280     ASSERT_NO_FATAL_FAILURE(CheckResult(
    281         tab_index, test.result_length, test.result));
    282   }
    283 
    284   std::string GetTestDataDescription(const KeyEventTestData& data) {
    285     std::string desc = base::StringPrintf(
    286         " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n"
    287         " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n"
    288         " Expected results(%d):\n",
    289         data.key, data.ctrl, data.shift, data.alt, data.command,
    290         data.suppress_keydown, data.suppress_keypress, data.suppress_keyup,
    291         data.suppress_textinput, data.result_length);
    292     for (int i = 0; i < data.result_length; ++i) {
    293       desc.append("  ");
    294       desc.append(data.result[i]);
    295       desc.append("\n");
    296     }
    297     return desc;
    298   }
    299 };
    300 
    301 #if defined(OS_MACOSX)
    302 // http://crbug.com/81451
    303 #define MAYBE_NormalKeyEvents DISABLED_NormalKeyEvents
    304 #elif defined(OS_LINUX)
    305 // http://crbug.com/129235
    306 #define MAYBE_NormalKeyEvents DISABLED_NormalKeyEvents
    307 #else
    308 #define MAYBE_NormalKeyEvents NormalKeyEvents
    309 #endif
    310 
    311 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_NormalKeyEvents) {
    312   static const KeyEventTestData kTestNoInput[] = {
    313     // a
    314     { ui::VKEY_A, false, false, false, false,
    315       false, false, false, false, 3,
    316       { "D 65 0 false false false false",
    317         "P 97 97 false false false false",
    318         "U 65 0 false false false false" } },
    319     // shift-a
    320     { ui::VKEY_A, false, true, false, false,
    321       false, false, false, false, 5,
    322       { "D 16 0 false true false false",
    323         "D 65 0 false true false false",
    324         "P 65 65 false true false false",
    325         "U 65 0 false true false false",
    326         "U 16 0 false true false false" } },
    327     // a, suppress keydown
    328     { ui::VKEY_A, false, false, false, false,
    329       true, false, false, false, 2,
    330       { "D 65 0 false false false false",
    331         "U 65 0 false false false false" } },
    332   };
    333 
    334   static const KeyEventTestData kTestWithInput[] = {
    335     // a
    336     { ui::VKEY_A, false, false, false, false,
    337       false, false, false, false, 4,
    338       { "D 65 0 false false false false",
    339         "P 97 97 false false false false",
    340         "T a",
    341         "U 65 0 false false false false" } },
    342     // shift-a
    343     { ui::VKEY_A, false, true, false, false,
    344       false, false, false, false, 6,
    345       { "D 16 0 false true false false",
    346         "D 65 0 false true false false",
    347         "P 65 65 false true false false",
    348         "T A",
    349         "U 65 0 false true false false",
    350         "U 16 0 false true false false" } },
    351     // a, suppress keydown
    352     { ui::VKEY_A, false, false, false, false,
    353       true, false, false, false, 2,
    354       { "D 65 0 false false false false",
    355         "U 65 0 false false false false" } },
    356     // a, suppress keypress
    357     { ui::VKEY_A, false, false, false, false,
    358       false, true, false, false, 3,
    359       { "D 65 0 false false false false",
    360         "P 97 97 false false false false",
    361         "U 65 0 false false false false" } },
    362     // a, suppress textInput
    363     { ui::VKEY_A, false, false, false, false,
    364       false, false, false, true, 4,
    365       { "D 65 0 false false false false",
    366         "P 97 97 false false false false",
    367         "T a",
    368         "U 65 0 false false false false" } },
    369   };
    370 
    371   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    372 
    373   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    374   GURL url = embedded_test_server()->GetURL(kTestingPage);
    375   ui_test_utils::NavigateToURL(browser(), url);
    376 
    377   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    378   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    379 
    380   int tab_index = browser()->tab_strip_model()->active_index();
    381   for (size_t i = 0; i < arraysize(kTestNoInput); ++i) {
    382     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
    383         << "kTestNoInput[" << i << "] failed:\n"
    384         << GetTestDataDescription(kTestNoInput[i]);
    385   }
    386 
    387   // Input in normal text box.
    388   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
    389   for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
    390     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
    391         << "kTestWithInput[" << i << "] in text box failed:\n"
    392         << GetTestDataDescription(kTestWithInput[i]);
    393   }
    394   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA"));
    395 
    396   // Input in password box.
    397   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B"));
    398   for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
    399     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
    400         << "kTestWithInput[" << i << "] in password box failed:\n"
    401         << GetTestDataDescription(kTestWithInput[i]);
    402   }
    403   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA"));
    404 }
    405 
    406 #if defined(OS_WIN) || defined(OS_LINUX)
    407 
    408 #if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA))
    409 // Linux: http://crbug.com/129235
    410 // Win Aura: crbug.com/269564
    411 #define MAYBE_CtrlKeyEvents DISABLED_CtrlKeyEvents
    412 #else
    413 #define MAYBE_CtrlKeyEvents CtrlKeyEvents
    414 #endif
    415 
    416 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_CtrlKeyEvents) {
    417   static const KeyEventTestData kTestCtrlF = {
    418     ui::VKEY_F, true, false, false, false,
    419     false, false, false, false, 2,
    420     { "D 17 0 true false false false",
    421       "D 70 0 true false false false" }
    422   };
    423 
    424   static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
    425     ui::VKEY_F, true, false, false, false,
    426     true, false, false, false, 4,
    427     { "D 17 0 true false false false",
    428       "D 70 0 true false false false",
    429       "U 70 0 true false false false",
    430       "U 17 0 true false false false" }
    431   };
    432 
    433   // Ctrl+Z doesn't bind to any accelerators, which then should generate a
    434   // keypress event with charCode=26.
    435   static const KeyEventTestData kTestCtrlZ = {
    436     ui::VKEY_Z, true, false, false, false,
    437     false, false, false, false, 5,
    438     { "D 17 0 true false false false",
    439       "D 90 0 true false false false",
    440       "P 26 26 true false false false",
    441       "U 90 0 true false false false",
    442       "U 17 0 true false false false" }
    443   };
    444 
    445   static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
    446     ui::VKEY_Z, true, false, false, false,
    447     true, false, false, false, 4,
    448     { "D 17 0 true false false false",
    449       "D 90 0 true false false false",
    450       "U 90 0 true false false false",
    451       "U 17 0 true false false false" }
    452   };
    453 
    454   // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
    455   static const KeyEventTestData kTestCtrlEnter = {
    456     ui::VKEY_RETURN, true, false, false, false,
    457     false, false, false, false, 5,
    458     { "D 17 0 true false false false",
    459       "D 13 0 true false false false",
    460       "P 10 10 true false false false",
    461       "U 13 0 true false false false",
    462       "U 17 0 true false false false" }
    463   };
    464 
    465   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    466 
    467   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    468   GURL url = embedded_test_server()->GetURL(kTestingPage);
    469   ui_test_utils::NavigateToURL(browser(), url);
    470 
    471   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    472   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    473 
    474   int tab_index = browser()->tab_strip_model()->active_index();
    475   // Press Ctrl+F, which will make the Find box open and request focus.
    476   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
    477   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
    478 
    479   // Press Escape to close the Find box and move the focus back to the web page.
    480   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
    481       browser(), ui::VKEY_ESCAPE, false, false, false, false));
    482   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    483 
    484   // Press Ctrl+F with keydown suppressed shall not open the find box.
    485   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown));
    486   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    487 
    488   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ));
    489   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown));
    490   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter));
    491 }
    492 #elif defined(OS_MACOSX)
    493 // http://crbug.com/81451
    494 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_CommandKeyEvents) {
    495   static const KeyEventTestData kTestCmdF = {
    496     ui::VKEY_F, false, false, false, true,
    497     false, false, false, false, 2,
    498     { "D 91 0 false false false true",
    499       "D 70 0 false false false true" }
    500   };
    501 
    502   // On Mac we don't send key up events when command modifier is down.
    503   static const KeyEventTestData kTestCmdFSuppressKeyDown = {
    504     ui::VKEY_F, false, false, false, true,
    505     true, false, false, false, 3,
    506     { "D 91 0 false false false true",
    507       "D 70 0 false false false true",
    508       "U 91 0 false false false true" }
    509   };
    510 
    511   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    512 
    513   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    514   GURL url = embedded_test_server()->GetURL(kTestingPage);
    515   ui_test_utils::NavigateToURL(browser(), url);
    516 
    517   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    518   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    519 
    520   int tab_index = browser()->tab_strip_model()->active_index();
    521   // Press Cmd+F, which will make the Find box open and request focus.
    522   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF));
    523   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
    524 
    525   // Press Escape to close the Find box and move the focus back to the web page.
    526   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
    527       browser(), ui::VKEY_ESCAPE, false, false, false, false));
    528   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    529 
    530   // Press Cmd+F with keydown suppressed shall not open the find box.
    531   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown));
    532   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    533 }
    534 #endif
    535 
    536 // Flaky: http://crbug.com/81451 , http://crbug.com/129235 ,
    537 // also fails on Windows.
    538 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_AccessKeys) {
    539 #if defined(OS_MACOSX)
    540   // On Mac, access keys use ctrl+alt modifiers.
    541   static const KeyEventTestData kTestAccessA = {
    542     ui::VKEY_A, true, false, true, false,
    543     false, false, false, false, 6,
    544     { "D 17 0 true false false false",
    545       "D 18 0 true false true false",
    546       "D 65 0 true false true false",
    547       "U 65 0 true false true false",
    548       "U 18 0 true false true false",
    549       "U 17 0 true false false false" }
    550   };
    551 
    552   static const KeyEventTestData kTestAccessDSuppress = {
    553     ui::VKEY_D, true, false, true, false,
    554     true, true, true, false, 6,
    555     { "D 17 0 true false false false",
    556       "D 18 0 true false true false",
    557       "D 68 0 true false true false",
    558       "U 68 0 true false true false",
    559       "U 18 0 true false true false",
    560       "U 17 0 true false false false" }
    561   };
    562 
    563   static const KeyEventTestData kTestAccess1 = {
    564     ui::VKEY_1, true, false, true, false,
    565     false, false, false, false, 6,
    566     { "D 17 0 true false false false",
    567       "D 18 0 true false true false",
    568       "D 49 0 true false true false",
    569       "U 49 0 true false true false",
    570       "U 18 0 true false true false",
    571       "U 17 0 true false false false" }
    572   };
    573 #else
    574   static const KeyEventTestData kTestAccessA = {
    575     ui::VKEY_A, false, false, true, false,
    576     false, false, false, false, 4,
    577     { "D 18 0 false false true false",
    578       "D 65 0 false false true false",
    579       "U 65 0 false false true false",
    580       "U 18 0 false false true false" }
    581   };
    582 
    583   static const KeyEventTestData kTestAccessD = {
    584     ui::VKEY_D, false, false, true, false,
    585     false, false, false, false, 2,
    586     { "D 18 0 false false true false",
    587       "D 68 0 false false true false" }
    588   };
    589 
    590   static const KeyEventTestData kTestAccessDSuppress = {
    591     ui::VKEY_D, false, false, true, false,
    592     true, true, true, false, 4,
    593     { "D 18 0 false false true false",
    594       "D 68 0 false false true false",
    595       "U 68 0 false false true false",
    596       "U 18 0 false false true false" }
    597   };
    598 
    599 #if !defined(USE_ASH)
    600   static const KeyEventTestData kTestAccess1 = {
    601     ui::VKEY_1, false, false, true, false,
    602     false, false, false, false, 4,
    603     { "D 18 0 false false true false",
    604       "D 49 0 false false true false",
    605       "U 49 0 false false true false",
    606       "U 18 0 false false true false" }
    607   };
    608 #endif
    609 #endif
    610 
    611   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    612 
    613   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    614   GURL url = embedded_test_server()->GetURL(kTestingPage);
    615   ui_test_utils::NavigateToURL(browser(), url);
    616 
    617   content::RunAllPendingInMessageLoop();
    618   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    619   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    620 
    621   int tab_index = browser()->tab_strip_model()->active_index();
    622   // Make sure no element is focused.
    623   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    624   // Alt+A should focus the element with accesskey = "A".
    625   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA));
    626   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A"));
    627 
    628   // Blur the focused element.
    629   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
    630   // Make sure no element is focused.
    631   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    632 
    633 #if !defined(OS_MACOSX)
    634   // Alt+D should move the focus to the location entry.
    635   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD));
    636 
    637   // TODO(isherman): This is an experimental change to help diagnose
    638   // http://crbug.com/55713
    639   content::RunAllPendingInMessageLoop();
    640   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
    641   // No element should be focused, as Alt+D was handled by the browser.
    642   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    643 
    644   // Move the focus back to the web page.
    645   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    646   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    647 
    648   // Make sure no element is focused.
    649   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    650 #endif
    651 
    652   // If the keydown event is suppressed, then Alt+D should be handled as an
    653   // accesskey rather than an accelerator key. Activation of an accesskey is not
    654   // a part of the default action of the key event, so it should not be
    655   // suppressed at all.
    656   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress));
    657   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    658   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D"));
    659 
    660   // Blur the focused element.
    661   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
    662   // Make sure no element is focused.
    663   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    664 #if !defined(USE_ASH)
    665   // On Ash, alt-1..9 are assigned as window selection global accelerators, so
    666   // they can not be used as accesskeys.
    667   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1));
    668 #if defined(TOOLKIT_GTK)
    669   // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can
    670   // not be used as accesskeys.
    671   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
    672 #else
    673   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1"));
    674 #endif
    675 #endif
    676 }
    677 
    678 // Flaky, http://crbug.com/69475.
    679 #if defined(OS_LINUX)
    680 #define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators
    681 #else
    682 #define MAYBE_ReservedAccelerators ReservedAccelerators
    683 #endif
    684 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) {
    685   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    686 
    687   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    688   GURL url = embedded_test_server()->GetURL(kTestingPage);
    689   ui_test_utils::NavigateToURL(browser(), url);
    690 
    691   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    692   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    693 
    694   ASSERT_EQ(1, browser()->tab_strip_model()->count());
    695 
    696   static const KeyEventTestData kTestCtrlOrCmdT = {
    697 #if defined(OS_MACOSX)
    698     ui::VKEY_T, false, false, false, true,
    699     true, false, false, false, 1,
    700     { "D 91 0 false false false true" }
    701 #else
    702     ui::VKEY_T, true, false, false, false,
    703     true, false, false, false, 1,
    704     { "D 17 0 true false false false" }
    705 #endif
    706   };
    707 
    708   content::WindowedNotificationObserver wait_for_new_tab(
    709       chrome::NOTIFICATION_TAB_PARENTED,
    710       content::NotificationService::AllSources());
    711 
    712   // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
    713   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT));
    714   wait_for_new_tab.Wait();
    715 
    716   int result_length;
    717   ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length));
    718   EXPECT_EQ(1, result_length);
    719 
    720   EXPECT_EQ(2, browser()->tab_strip_model()->count());
    721   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
    722 
    723   // Because of issue <http://crbug.com/65375>, switching back to the first tab
    724   // may cause the focus to be grabbed by omnibox. So instead, we load our
    725   // testing page in the newly created tab and try Cmd-W here.
    726   ui_test_utils::NavigateToURL(browser(), url);
    727 
    728   // Make sure the focus is in the testing page.
    729   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    730   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    731 
    732   // Reserved accelerators can't be suppressed.
    733   ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
    734 
    735   content::WindowedNotificationObserver wait_for_tab_closed(
    736       content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
    737       content::Source<content::WebContents>(
    738           browser()->tab_strip_model()->GetWebContentsAt(1)));
    739 
    740   // Press Ctrl/Cmd+W, which will close the tab.
    741 #if defined(OS_MACOSX)
    742   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
    743       browser(), ui::VKEY_W, false, false, false, true));
    744 #else
    745   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
    746       browser(), ui::VKEY_W, true, false, false, false));
    747 #endif
    748 
    749   ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed.Wait());
    750 
    751   EXPECT_EQ(1, browser()->tab_strip_model()->count());
    752 }
    753 
    754 #if defined(OS_MACOSX)
    755 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
    756   // TODO(kbr): re-enable: http://crbug.com/222296
    757   if (base::mac::IsOSMountainLionOrLater())
    758     return;
    759 
    760   static const KeyEventTestData kTestCtrlA = {
    761     ui::VKEY_A, true, false, false, false,
    762     false, false, false, false, 4,
    763     { "D 17 0 true false false false",
    764       "D 65 0 true false false false",
    765       "U 65 0 true false false false",
    766       "U 17 0 true false false false" }
    767   };
    768 
    769   static const KeyEventTestData kTestCtrlF = {
    770     ui::VKEY_F, true, false, false, false,
    771     false, false, false, false, 4,
    772     { "D 17 0 true false false false",
    773       "D 70 0 true false false false",
    774       "U 70 0 true false false false",
    775       "U 17 0 true false false false" }
    776   };
    777 
    778   static const KeyEventTestData kTestCtrlK = {
    779     ui::VKEY_K, true, false, false, false,
    780     false, false, false, false, 4,
    781     { "D 17 0 true false false false",
    782       "D 75 0 true false false false",
    783       "U 75 0 true false false false",
    784       "U 17 0 true false false false" }
    785   };
    786 
    787   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    788 
    789   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    790   GURL url = embedded_test_server()->GetURL(kTestingPage);
    791   ui_test_utils::NavigateToURL(browser(), url);
    792 
    793   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    794   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    795 
    796   int tab_index = browser()->tab_strip_model()->active_index();
    797   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
    798   ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello"));
    799   // Move the caret to the beginning of the line.
    800   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA));
    801   // Forward one character
    802   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
    803   // Delete to the end of the line.
    804   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK));
    805   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H"));
    806 }
    807 #endif
    808 
    809 // See http://crbug.com/147579
    810 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_PageUpDownKeys) {
    811   static const KeyEventTestData kTestPageUp = {
    812     ui::VKEY_PRIOR, false, false, false, false,
    813     false, false, false, false, 2,
    814     { "D 33 0 false false false false",
    815       "U 33 0 false false false false" }
    816   };
    817 
    818   static const KeyEventTestData kTestPageDown = {
    819     ui::VKEY_NEXT, false, false, false, false,
    820     false, false, false, false, 2,
    821     { "D 34 0 false false false false",
    822       "U 34 0 false false false false" }
    823   };
    824 
    825   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    826 
    827   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    828   GURL url = embedded_test_server()->GetURL(kTestingPage);
    829   ui_test_utils::NavigateToURL(browser(), url);
    830 
    831   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    832   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    833 
    834   int tab_index = browser()->tab_strip_model()->active_index();
    835   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
    836   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp));
    837   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown));
    838   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L""));
    839 }
    840 
    841 #if defined(OS_WIN)
    842 // AltKey is enabled only on Windows. See crbug.com/114537.
    843 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
    844   static const KeyEventTestData kTestAltKey = {
    845     ui::VKEY_MENU, false, false, false, false,
    846     false, false, false, false, 2,
    847     { "D 18 0 false false true false",
    848       "U 18 0 false false true false" }
    849   };
    850 
    851   static const KeyEventTestData kTestAltKeySuppress = {
    852     ui::VKEY_MENU, false, false, false, false,
    853     true, false, false, false, 2,
    854     { "D 18 0 false false true false",
    855       "U 18 0 false false true false" }
    856   };
    857 
    858   static const KeyEventTestData kTestCtrlAltKey = {
    859     ui::VKEY_MENU, true, false, false, false,
    860     false, false, false, false, 4,
    861     { "D 17 0 true false false false",
    862       "D 18 0 true false true false",
    863       "U 18 0 true false true false",
    864       "U 17 0 true false false false" }
    865   };
    866 
    867   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    868 
    869   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
    870   GURL url = embedded_test_server()->GetURL(kTestingPage);
    871   ui_test_utils::NavigateToURL(browser(), url);
    872 
    873   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    874   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    875 
    876   int tab_index = browser()->tab_strip_model()->active_index();
    877   // Press and release Alt key to focus wrench menu button.
    878   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey));
    879   EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU));
    880 
    881   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
    882   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    883 
    884   // Alt key can be suppressed.
    885   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
    886   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    887 
    888   // Ctrl+Alt should have no effect.
    889   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
    890   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
    891 }
    892 #endif
    893 
    894 }  // namespace
    895