- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / browser_keyevents_browsertest.cc
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/events/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 // Flaky: http://crbug.com/129235, http://crbug.com/81451.
302 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) {
303   static const KeyEventTestData kTestNoInput[] = {
304     // a
305     { ui::VKEY_A, false, false, false, false,
306       false, false, false, false, 3,
307       { "D 65 0 false false false false",
308         "P 97 97 false false false false",
309         "U 65 0 false false false false" } },
310     // shift-a
311     { ui::VKEY_A, false, true, false, false,
312       false, false, false, false, 5,
313       { "D 16 0 false true false false",
314         "D 65 0 false true false false",
315         "P 65 65 false true false false",
316         "U 65 0 false true false false",
317         "U 16 0 false true false false" } },
318     // a, suppress keydown
319     { ui::VKEY_A, false, false, false, false,
320       true, false, false, false, 2,
321       { "D 65 0 false false false false",
322         "U 65 0 false false false false" } },
323   };
324
325   static const KeyEventTestData kTestWithInput[] = {
326     // a
327     { ui::VKEY_A, false, false, false, false,
328       false, false, false, false, 4,
329       { "D 65 0 false false false false",
330         "P 97 97 false false false false",
331         "T a",
332         "U 65 0 false false false false" } },
333     // shift-a
334     { ui::VKEY_A, false, true, false, false,
335       false, false, false, false, 6,
336       { "D 16 0 false true false false",
337         "D 65 0 false true false false",
338         "P 65 65 false true false false",
339         "T A",
340         "U 65 0 false true false false",
341         "U 16 0 false true false false" } },
342     // a, suppress keydown
343     { ui::VKEY_A, false, false, false, false,
344       true, false, false, false, 2,
345       { "D 65 0 false false false false",
346         "U 65 0 false false false false" } },
347     // a, suppress keypress
348     { ui::VKEY_A, false, false, false, false,
349       false, true, false, false, 3,
350       { "D 65 0 false false false false",
351         "P 97 97 false false false false",
352         "U 65 0 false false false false" } },
353     // a, suppress textInput
354     { ui::VKEY_A, false, false, false, false,
355       false, false, false, true, 4,
356       { "D 65 0 false false false false",
357         "P 97 97 false false false false",
358         "T a",
359         "U 65 0 false false false false" } },
360   };
361
362   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
363
364   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
365   GURL url = embedded_test_server()->GetURL(kTestingPage);
366   ui_test_utils::NavigateToURL(browser(), url);
367
368   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
369   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
370
371   int tab_index = browser()->tab_strip_model()->active_index();
372   for (size_t i = 0; i < arraysize(kTestNoInput); ++i) {
373     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
374         << "kTestNoInput[" << i << "] failed:\n"
375         << GetTestDataDescription(kTestNoInput[i]);
376   }
377
378   // Input in normal text box.
379   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
380   for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
381     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
382         << "kTestWithInput[" << i << "] in text box failed:\n"
383         << GetTestDataDescription(kTestWithInput[i]);
384   }
385   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA"));
386
387   // Input in password box.
388   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B"));
389   for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
390     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
391         << "kTestWithInput[" << i << "] in password box failed:\n"
392         << GetTestDataDescription(kTestWithInput[i]);
393   }
394   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA"));
395 }
396
397 #if defined(OS_WIN) || defined(OS_LINUX)
398
399 #if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA))
400 // Linux: http://crbug.com/129235
401 // Win Aura: crbug.com/269564
402 #define MAYBE_CtrlKeyEvents DISABLED_CtrlKeyEvents
403 #else
404 #define MAYBE_CtrlKeyEvents CtrlKeyEvents
405 #endif
406
407 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_CtrlKeyEvents) {
408   static const KeyEventTestData kTestCtrlF = {
409     ui::VKEY_F, true, false, false, false,
410     false, false, false, false, 2,
411     { "D 17 0 true false false false",
412       "D 70 0 true false false false" }
413   };
414
415   static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
416     ui::VKEY_F, true, false, false, false,
417     true, false, false, false, 4,
418     { "D 17 0 true false false false",
419       "D 70 0 true false false false",
420       "U 70 0 true false false false",
421       "U 17 0 true false false false" }
422   };
423
424   // Ctrl+Z doesn't bind to any accelerators, which then should generate a
425   // keypress event with charCode=26.
426   static const KeyEventTestData kTestCtrlZ = {
427     ui::VKEY_Z, true, false, false, false,
428     false, false, false, false, 5,
429     { "D 17 0 true false false false",
430       "D 90 0 true false false false",
431       "P 26 26 true false false false",
432       "U 90 0 true false false false",
433       "U 17 0 true false false false" }
434   };
435
436   static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
437     ui::VKEY_Z, true, false, false, false,
438     true, false, false, false, 4,
439     { "D 17 0 true false false false",
440       "D 90 0 true false false false",
441       "U 90 0 true false false false",
442       "U 17 0 true false false false" }
443   };
444
445   // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
446   static const KeyEventTestData kTestCtrlEnter = {
447     ui::VKEY_RETURN, true, false, false, false,
448     false, false, false, false, 5,
449     { "D 17 0 true false false false",
450       "D 13 0 true false false false",
451       "P 10 10 true false false false",
452       "U 13 0 true false false false",
453       "U 17 0 true false false false" }
454   };
455
456   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
457
458   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
459   GURL url = embedded_test_server()->GetURL(kTestingPage);
460   ui_test_utils::NavigateToURL(browser(), url);
461
462   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
463   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
464
465   int tab_index = browser()->tab_strip_model()->active_index();
466   // Press Ctrl+F, which will make the Find box open and request focus.
467   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
468   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
469
470   // Press Escape to close the Find box and move the focus back to the web page.
471   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
472       browser(), ui::VKEY_ESCAPE, false, false, false, false));
473   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
474
475   // Press Ctrl+F with keydown suppressed shall not open the find box.
476   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown));
477   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
478
479   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ));
480   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown));
481   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter));
482 }
483 #elif defined(OS_MACOSX)
484 // http://crbug.com/81451
485 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_CommandKeyEvents) {
486   static const KeyEventTestData kTestCmdF = {
487     ui::VKEY_F, false, false, false, true,
488     false, false, false, false, 2,
489     { "D 91 0 false false false true",
490       "D 70 0 false false false true" }
491   };
492
493   // On Mac we don't send key up events when command modifier is down.
494   static const KeyEventTestData kTestCmdFSuppressKeyDown = {
495     ui::VKEY_F, false, false, false, true,
496     true, false, false, false, 3,
497     { "D 91 0 false false false true",
498       "D 70 0 false false false true",
499       "U 91 0 false false false true" }
500   };
501
502   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
503
504   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
505   GURL url = embedded_test_server()->GetURL(kTestingPage);
506   ui_test_utils::NavigateToURL(browser(), url);
507
508   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
509   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
510
511   int tab_index = browser()->tab_strip_model()->active_index();
512   // Press Cmd+F, which will make the Find box open and request focus.
513   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF));
514   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
515
516   // Press Escape to close the Find box and move the focus back to the web page.
517   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
518       browser(), ui::VKEY_ESCAPE, false, false, false, false));
519   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
520
521   // Press Cmd+F with keydown suppressed shall not open the find box.
522   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown));
523   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
524 }
525 #endif
526
527 // Flaky: http://crbug.com/81451 , http://crbug.com/129235 ,
528 // also fails on Windows.
529 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_AccessKeys) {
530 #if defined(OS_MACOSX)
531   // On Mac, access keys use ctrl+alt modifiers.
532   static const KeyEventTestData kTestAccessA = {
533     ui::VKEY_A, true, false, true, false,
534     false, false, false, false, 6,
535     { "D 17 0 true false false false",
536       "D 18 0 true false true false",
537       "D 65 0 true false true false",
538       "U 65 0 true false true false",
539       "U 18 0 true false true false",
540       "U 17 0 true false false false" }
541   };
542
543   static const KeyEventTestData kTestAccessDSuppress = {
544     ui::VKEY_D, true, false, true, false,
545     true, true, true, false, 6,
546     { "D 17 0 true false false false",
547       "D 18 0 true false true false",
548       "D 68 0 true false true false",
549       "U 68 0 true false true false",
550       "U 18 0 true false true false",
551       "U 17 0 true false false false" }
552   };
553
554   static const KeyEventTestData kTestAccess1 = {
555     ui::VKEY_1, true, false, true, false,
556     false, false, false, false, 6,
557     { "D 17 0 true false false false",
558       "D 18 0 true false true false",
559       "D 49 0 true false true false",
560       "U 49 0 true false true false",
561       "U 18 0 true false true false",
562       "U 17 0 true false false false" }
563   };
564 #else
565   static const KeyEventTestData kTestAccessA = {
566     ui::VKEY_A, false, false, true, false,
567     false, false, false, false, 4,
568     { "D 18 0 false false true false",
569       "D 65 0 false false true false",
570       "U 65 0 false false true false",
571       "U 18 0 false false true false" }
572   };
573
574   static const KeyEventTestData kTestAccessD = {
575     ui::VKEY_D, false, false, true, false,
576     false, false, false, false, 2,
577     { "D 18 0 false false true false",
578       "D 68 0 false false true false" }
579   };
580
581   static const KeyEventTestData kTestAccessDSuppress = {
582     ui::VKEY_D, false, false, true, false,
583     true, true, true, false, 4,
584     { "D 18 0 false false true false",
585       "D 68 0 false false true false",
586       "U 68 0 false false true false",
587       "U 18 0 false false true false" }
588   };
589
590 #if !defined(USE_ASH)
591   static const KeyEventTestData kTestAccess1 = {
592     ui::VKEY_1, false, false, true, false,
593     false, false, false, false, 4,
594     { "D 18 0 false false true false",
595       "D 49 0 false false true false",
596       "U 49 0 false false true false",
597       "U 18 0 false false true false" }
598   };
599 #endif
600 #endif
601
602   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
603
604   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
605   GURL url = embedded_test_server()->GetURL(kTestingPage);
606   ui_test_utils::NavigateToURL(browser(), url);
607
608   content::RunAllPendingInMessageLoop();
609   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
610   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
611
612   int tab_index = browser()->tab_strip_model()->active_index();
613   // Make sure no element is focused.
614   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
615   // Alt+A should focus the element with accesskey = "A".
616   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA));
617   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A"));
618
619   // Blur the focused element.
620   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
621   // Make sure no element is focused.
622   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
623
624 #if !defined(OS_MACOSX)
625   // Alt+D should move the focus to the location entry.
626   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD));
627
628   // TODO(isherman): This is an experimental change to help diagnose
629   // http://crbug.com/55713
630   content::RunAllPendingInMessageLoop();
631   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
632   // No element should be focused, as Alt+D was handled by the browser.
633   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
634
635   // Move the focus back to the web page.
636   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
637   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
638
639   // Make sure no element is focused.
640   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
641 #endif
642
643   // If the keydown event is suppressed, then Alt+D should be handled as an
644   // accesskey rather than an accelerator key. Activation of an accesskey is not
645   // a part of the default action of the key event, so it should not be
646   // suppressed at all.
647   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress));
648   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
649   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D"));
650
651   // Blur the focused element.
652   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
653   // Make sure no element is focused.
654   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
655 #if !defined(USE_ASH)
656   // On Ash, alt-1..9 are assigned as window selection global accelerators, so
657   // they can not be used as accesskeys.
658   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1));
659 #if defined(TOOLKIT_GTK)
660   // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can
661   // not be used as accesskeys.
662   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
663 #else
664   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1"));
665 #endif
666 #endif
667 }
668
669 // Flaky, http://crbug.com/69475.
670 #if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA))
671 #define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators
672 #else
673 #define MAYBE_ReservedAccelerators ReservedAccelerators
674 #endif
675 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) {
676   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
677
678   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
679   GURL url = embedded_test_server()->GetURL(kTestingPage);
680   ui_test_utils::NavigateToURL(browser(), url);
681
682   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
683   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
684
685   ASSERT_EQ(1, browser()->tab_strip_model()->count());
686
687   static const KeyEventTestData kTestCtrlOrCmdT = {
688 #if defined(OS_MACOSX)
689     ui::VKEY_T, false, false, false, true,
690     true, false, false, false, 1,
691     { "D 91 0 false false false true" }
692 #else
693     ui::VKEY_T, true, false, false, false,
694     true, false, false, false, 1,
695     { "D 17 0 true false false false" }
696 #endif
697   };
698
699   content::WindowedNotificationObserver wait_for_new_tab(
700       chrome::NOTIFICATION_TAB_PARENTED,
701       content::NotificationService::AllSources());
702
703   // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
704   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT));
705   wait_for_new_tab.Wait();
706
707   int result_length;
708   ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length));
709   EXPECT_EQ(1, result_length);
710
711   EXPECT_EQ(2, browser()->tab_strip_model()->count());
712   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
713
714   // Because of issue <http://crbug.com/65375>, switching back to the first tab
715   // may cause the focus to be grabbed by omnibox. So instead, we load our
716   // testing page in the newly created tab and try Cmd-W here.
717   ui_test_utils::NavigateToURL(browser(), url);
718
719   // Make sure the focus is in the testing page.
720   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
721   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
722
723   // Reserved accelerators can't be suppressed.
724   ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
725
726   content::WebContentsDestroyedWatcher destroyed_watcher(
727       browser()->tab_strip_model()->GetWebContentsAt(1));
728
729   // Press Ctrl/Cmd+W, which will close the tab.
730 #if defined(OS_MACOSX)
731   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
732       browser(), ui::VKEY_W, false, false, false, true));
733 #else
734   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
735       browser(), ui::VKEY_W, true, false, false, false));
736 #endif
737
738   ASSERT_NO_FATAL_FAILURE(destroyed_watcher.Wait());
739
740   EXPECT_EQ(1, browser()->tab_strip_model()->count());
741 }
742
743 #if defined(OS_MACOSX)
744 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
745   // TODO(kbr): re-enable: http://crbug.com/222296
746   if (base::mac::IsOSMountainLionOrLater())
747     return;
748
749   static const KeyEventTestData kTestCtrlA = {
750     ui::VKEY_A, true, false, false, false,
751     false, false, false, false, 4,
752     { "D 17 0 true false false false",
753       "D 65 0 true false false false",
754       "U 65 0 true false false false",
755       "U 17 0 true false false false" }
756   };
757
758   static const KeyEventTestData kTestCtrlF = {
759     ui::VKEY_F, true, false, false, false,
760     false, false, false, false, 4,
761     { "D 17 0 true false false false",
762       "D 70 0 true false false false",
763       "U 70 0 true false false false",
764       "U 17 0 true false false false" }
765   };
766
767   static const KeyEventTestData kTestCtrlK = {
768     ui::VKEY_K, true, false, false, false,
769     false, false, false, false, 4,
770     { "D 17 0 true false false false",
771       "D 75 0 true false false false",
772       "U 75 0 true false false false",
773       "U 17 0 true false false false" }
774   };
775
776   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
777
778   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
779   GURL url = embedded_test_server()->GetURL(kTestingPage);
780   ui_test_utils::NavigateToURL(browser(), url);
781
782   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
783   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
784
785   int tab_index = browser()->tab_strip_model()->active_index();
786   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
787   ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello"));
788   // Move the caret to the beginning of the line.
789   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA));
790   // Forward one character
791   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
792   // Delete to the end of the line.
793   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK));
794   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H"));
795 }
796 #endif
797
798 // See http://crbug.com/147579
799 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_PageUpDownKeys) {
800   static const KeyEventTestData kTestPageUp = {
801     ui::VKEY_PRIOR, false, false, false, false,
802     false, false, false, false, 2,
803     { "D 33 0 false false false false",
804       "U 33 0 false false false false" }
805   };
806
807   static const KeyEventTestData kTestPageDown = {
808     ui::VKEY_NEXT, false, false, false, false,
809     false, false, false, false, 2,
810     { "D 34 0 false false false false",
811       "U 34 0 false false false false" }
812   };
813
814   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
815
816   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
817   GURL url = embedded_test_server()->GetURL(kTestingPage);
818   ui_test_utils::NavigateToURL(browser(), url);
819
820   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
821   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
822
823   int tab_index = browser()->tab_strip_model()->active_index();
824   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
825   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp));
826   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown));
827   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L""));
828 }
829
830 #if defined(OS_WIN)
831 // AltKey is enabled only on Windows. See crbug.com/114537.
832 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
833   static const KeyEventTestData kTestAltKey = {
834     ui::VKEY_MENU, false, false, false, false,
835     false, false, false, false, 2,
836     { "D 18 0 false false true false",
837       "U 18 0 false false true false" }
838   };
839
840   static const KeyEventTestData kTestAltKeySuppress = {
841     ui::VKEY_MENU, false, false, false, false,
842     true, false, false, false, 2,
843     { "D 18 0 false false true false",
844       "U 18 0 false false true false" }
845   };
846
847   static const KeyEventTestData kTestCtrlAltKey = {
848     ui::VKEY_MENU, true, false, false, false,
849     false, false, false, false, 4,
850     { "D 17 0 true false false false",
851       "D 18 0 true false true false",
852       "U 18 0 true false true false",
853       "U 17 0 true false false false" }
854   };
855
856   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
857
858   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
859   GURL url = embedded_test_server()->GetURL(kTestingPage);
860   ui_test_utils::NavigateToURL(browser(), url);
861
862   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
863   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
864
865   int tab_index = browser()->tab_strip_model()->active_index();
866   // Press and release Alt key to focus wrench menu button.
867   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey));
868   EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU));
869
870   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
871   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
872
873   // Alt key can be suppressed.
874   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
875   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
876
877   // Ctrl+Alt should have no effect.
878   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
879   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
880 }
881 #endif
882
883 }  // namespace