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