1 // Copyright (c) 2011 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.
5 #include "build/build_config.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/stringprintf.h"
11 #include "base/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/dom_operation_notification_details.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/test/in_process_browser_test.h"
17 #include "chrome/test/ui_test_utils.h"
18 #include "content/browser/renderer_host/render_view_host.h"
19 #include "content/browser/renderer_host/render_widget_host_view.h"
20 #include "content/browser/tab_contents/tab_contents.h"
21 #include "content/browser/tab_contents/tab_contents_view.h"
22 #include "content/common/notification_registrar.h"
23 #include "content/common/notification_service.h"
24 #include "net/test/test_server.h"
25 #include "ui/base/keycodes/keyboard_codes.h"
29 const char kTestingPage
[] = "files/keyevents_test.html";
30 const wchar_t kSuppressEventJS
[] =
31 L
"window.domAutomationController.send(setDefaultAction('%ls', %ls));";
32 const wchar_t kGetResultJS
[] =
33 L
"window.domAutomationController.send(keyEventResult[%d]);";
34 const wchar_t kGetResultLengthJS
[] =
35 L
"window.domAutomationController.send(keyEventResult.length);";
36 const wchar_t kGetFocusedElementJS
[] =
37 L
"window.domAutomationController.send(focusedElement);";
38 const wchar_t kSetFocusedElementJS
[] =
39 L
"window.domAutomationController.send(setFocusedElement('%ls'));";
40 const wchar_t kGetTextBoxValueJS
[] =
41 L
"window.domAutomationController.send("
42 L
"document.getElementById('%ls').value);";
43 const wchar_t kSetTextBoxValueJS
[] =
44 L
"window.domAutomationController.send("
45 L
"document.getElementById('%ls').value = '%ls');";
46 const wchar_t kStartTestJS
[] =
47 L
"window.domAutomationController.send(startTest(%d));";
49 // Maximum lenght of the result array in KeyEventTestData structure.
50 const size_t kMaxResultLength
= 10;
52 // A structure holding test data of a keyboard event.
53 // Each keyboard event may generate multiple result strings representing
54 // the result of keydown, keypress, keyup and textInput events.
55 // For keydown, keypress and keyup events, the format of the result string is:
56 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
57 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
58 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
59 // the state of corresponding modifier key.
60 // For textInput event, the format is: T <text>, where <text> is the text to be
62 // Please refer to chrome/test/data/keyevents_test.html for details.
63 struct KeyEventTestData
{
70 bool suppress_keydown
;
71 bool suppress_keypress
;
73 bool suppress_textinput
;
76 const char* const result
[kMaxResultLength
];
79 const wchar_t* GetBoolString(bool value
) {
80 return value
? L
"true" : L
"false";
83 // A class to help wait for the finish of a key event test.
84 class TestFinishObserver
: public NotificationObserver
{
86 explicit TestFinishObserver(RenderViewHost
* render_view_host
)
87 : finished_(false), waiting_(false) {
88 registrar_
.Add(this, NotificationType::DOM_OPERATION_RESPONSE
,
89 Source
<RenderViewHost
>(render_view_host
));
92 bool WaitForFinish() {
95 ui_test_utils::RunMessageLoop();
101 virtual void Observe(NotificationType type
,
102 const NotificationSource
& source
,
103 const NotificationDetails
& details
) {
104 DCHECK(type
== NotificationType::DOM_OPERATION_RESPONSE
);
105 Details
<DomOperationNotificationDetails
> dom_op_details(details
);
106 // We might receive responses for other script execution, but we only
107 // care about the test finished message.
108 if (dom_op_details
->json() == "\"FINISHED\"") {
111 MessageLoopForUI::current()->Quit();
118 NotificationRegistrar registrar_
;
120 DISALLOW_COPY_AND_ASSIGN(TestFinishObserver
);
123 class BrowserKeyEventsTest
: public InProcessBrowserTest
{
125 BrowserKeyEventsTest() {
126 set_show_window(true);
127 EnableDOMAutomation();
130 bool IsViewFocused(ViewID vid
) {
131 return ui_test_utils::IsViewFocused(browser(), vid
);
134 void ClickOnView(ViewID vid
) {
135 ui_test_utils::ClickOnView(browser(), vid
);
138 // Set the suppress flag of an event specified by |type|. If |suppress| is
139 // true then the web page will suppress all events with |type|. Following
140 // event types are supported: keydown, keypress, keyup and textInput.
141 void SuppressEventByType(int tab_index
, const wchar_t* type
, bool suppress
) {
142 ASSERT_LT(tab_index
, browser()->tab_count());
144 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
145 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
147 base::StringPrintf(kSuppressEventJS
, type
, GetBoolString(!suppress
)),
149 ASSERT_EQ(!suppress
, actual
);
152 void SuppressEvents(int tab_index
, bool keydown
, bool keypress
,
153 bool keyup
, bool textinput
) {
154 ASSERT_NO_FATAL_FAILURE(
155 SuppressEventByType(tab_index
, L
"keydown", keydown
));
156 ASSERT_NO_FATAL_FAILURE(
157 SuppressEventByType(tab_index
, L
"keypress", keypress
));
158 ASSERT_NO_FATAL_FAILURE(
159 SuppressEventByType(tab_index
, L
"keyup", keyup
));
160 ASSERT_NO_FATAL_FAILURE(
161 SuppressEventByType(tab_index
, L
"textInput", textinput
));
164 void SuppressAllEvents(int tab_index
, bool suppress
) {
165 SuppressEvents(tab_index
, suppress
, suppress
, suppress
, suppress
);
168 void GetResultLength(int tab_index
, int* length
) {
169 ASSERT_LT(tab_index
, browser()->tab_count());
170 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
171 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
172 L
"", kGetResultLengthJS
, length
));
175 void CheckResult(int tab_index
, int length
, const char* const result
[]) {
176 ASSERT_LT(tab_index
, browser()->tab_count());
178 ASSERT_NO_FATAL_FAILURE(GetResultLength(tab_index
, &actual_length
));
179 ASSERT_GE(actual_length
, length
);
180 for (int i
= 0; i
< actual_length
; ++i
) {
182 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
183 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
184 L
"", base::StringPrintf(kGetResultJS
, i
), &actual
));
186 // If more events were received than expected, then the additional events
187 // must be keyup events.
189 ASSERT_STREQ(result
[i
], actual
.c_str());
191 ASSERT_EQ('U', actual
[0]);
195 void CheckFocusedElement(int tab_index
, const wchar_t* focused
) {
196 ASSERT_LT(tab_index
, browser()->tab_count());
198 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
199 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
200 L
"", kGetFocusedElementJS
, &actual
));
201 ASSERT_EQ(WideToUTF8(focused
), actual
);
204 void SetFocusedElement(int tab_index
, const wchar_t* focused
) {
205 ASSERT_LT(tab_index
, browser()->tab_count());
207 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
208 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
210 base::StringPrintf(kSetFocusedElementJS
, focused
),
215 void CheckTextBoxValue(int tab_index
, const wchar_t* id
,
216 const wchar_t* value
) {
217 ASSERT_LT(tab_index
, browser()->tab_count());
219 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
220 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
222 base::StringPrintf(kGetTextBoxValueJS
, id
),
224 ASSERT_EQ(WideToUTF8(value
), actual
);
227 void SetTextBoxValue(int tab_index
, const wchar_t* id
,
228 const wchar_t* value
) {
229 ASSERT_LT(tab_index
, browser()->tab_count());
231 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
232 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
234 base::StringPrintf(kSetTextBoxValueJS
, id
, value
),
236 ASSERT_EQ(WideToUTF8(value
), actual
);
239 void StartTest(int tab_index
, int result_length
) {
240 ASSERT_LT(tab_index
, browser()->tab_count());
242 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
243 browser()->GetTabContentsAt(tab_index
)->render_view_host(),
244 L
"", base::StringPrintf(kStartTestJS
, result_length
), &actual
));
248 void TestKeyEvent(int tab_index
, const KeyEventTestData
& test
) {
249 ASSERT_LT(tab_index
, browser()->tab_count());
250 ASSERT_EQ(tab_index
, browser()->active_index());
252 // Inform our testing web page that we are about to start testing a key
254 ASSERT_NO_FATAL_FAILURE(StartTest(tab_index
, test
.result_length
));
255 ASSERT_NO_FATAL_FAILURE(SuppressEvents(
256 tab_index
, test
.suppress_keydown
, test
.suppress_keypress
,
257 test
.suppress_keyup
, test
.suppress_textinput
));
259 // We need to create a finish observer before sending the key event,
260 // because the test finished message might be arrived before returning
261 // from the SendKeyPressSync() method.
262 TestFinishObserver
finish_observer(
263 browser()->GetTabContentsAt(tab_index
)->render_view_host());
265 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
266 browser(), test
.key
, test
.ctrl
, test
.shift
, test
.alt
, test
.command
));
267 ASSERT_TRUE(finish_observer
.WaitForFinish());
268 ASSERT_NO_FATAL_FAILURE(CheckResult(
269 tab_index
, test
.result_length
, test
.result
));
272 std::string
GetTestDataDescription(const KeyEventTestData
& data
) {
273 std::string desc
= base::StringPrintf(
274 " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n"
275 " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n"
276 " Expected results(%d):\n",
277 data
.key
, data
.ctrl
, data
.shift
, data
.alt
, data
.command
,
278 data
.suppress_keydown
, data
.suppress_keypress
, data
.suppress_keyup
,
279 data
.suppress_textinput
, data
.result_length
);
280 for (int i
= 0; i
< data
.result_length
; ++i
) {
282 desc
.append(data
.result
[i
]);
289 #if defined(OS_MACOSX)
290 // http://crbug.com/81451
291 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, DISABLED_NormalKeyEvents
) {
293 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, NormalKeyEvents
) {
296 static const KeyEventTestData kTestNoInput
[] = {
298 { ui::VKEY_A
, false, false, false, false,
299 false, false, false, false, 3,
300 { "D 65 0 false false false false",
301 "P 97 97 false false false false",
302 "U 65 0 false false false false" } },
304 { ui::VKEY_A
, false, true, false, false,
305 false, false, false, false, 5,
306 { "D 16 0 false true false false",
307 "D 65 0 false true false false",
308 "P 65 65 false true false false",
309 "U 65 0 false true false false",
310 "U 16 0 false true false false" } },
311 // a, suppress keydown
312 { ui::VKEY_A
, false, false, false, false,
313 true, false, false, false, 2,
314 { "D 65 0 false false false false",
315 "U 65 0 false false false false" } },
318 static const KeyEventTestData kTestWithInput
[] = {
320 { ui::VKEY_A
, false, false, false, false,
321 false, false, false, false, 4,
322 { "D 65 0 false false false false",
323 "P 97 97 false false false false",
325 "U 65 0 false false false false" } },
327 { ui::VKEY_A
, false, true, false, false,
328 false, false, false, false, 6,
329 { "D 16 0 false true false false",
330 "D 65 0 false true false false",
331 "P 65 65 false true false false",
333 "U 65 0 false true false false",
334 "U 16 0 false true false false" } },
335 // a, suppress keydown
336 { ui::VKEY_A
, false, false, false, false,
337 true, false, false, false, 2,
338 { "D 65 0 false false false false",
339 "U 65 0 false false false false" } },
340 // a, suppress keypress
341 { ui::VKEY_A
, false, false, false, false,
342 false, true, false, false, 3,
343 { "D 65 0 false false false false",
344 "P 97 97 false false false false",
345 "U 65 0 false false false false" } },
346 // a, suppress textInput
347 { ui::VKEY_A
, false, false, false, false,
348 false, false, false, true, 4,
349 { "D 65 0 false false false false",
350 "P 97 97 false false false false",
352 "U 65 0 false false false false" } },
355 ASSERT_TRUE(test_server()->Start());
357 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
358 GURL url
= test_server()->GetURL(kTestingPage
);
359 ui_test_utils::NavigateToURL(browser(), url
);
361 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
362 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
364 int tab_index
= browser()->active_index();
365 for (size_t i
= 0; i
< arraysize(kTestNoInput
); ++i
) {
366 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestNoInput
[i
]))
367 << "kTestNoInput[" << i
<< "] failed:\n"
368 << GetTestDataDescription(kTestNoInput
[i
]);
371 // Input in normal text box.
372 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
"A"));
373 for (size_t i
= 0; i
< arraysize(kTestWithInput
); ++i
) {
374 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestWithInput
[i
]))
375 << "kTestWithInput[" << i
<< "] in text box failed:\n"
376 << GetTestDataDescription(kTestWithInput
[i
]);
378 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index
, L
"A", L
"aA"));
380 // Input in password box.
381 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
"B"));
382 for (size_t i
= 0; i
< arraysize(kTestWithInput
); ++i
) {
383 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestWithInput
[i
]))
384 << "kTestWithInput[" << i
<< "] in password box failed:\n"
385 << GetTestDataDescription(kTestWithInput
[i
]);
387 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index
, L
"B", L
"aA"));
390 #if defined(OS_WIN) || defined(OS_LINUX)
391 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, CtrlKeyEvents
) {
392 static const KeyEventTestData kTestCtrlF
= {
393 ui::VKEY_F
, true, false, false, false,
394 false, false, false, false, 2,
395 { "D 17 0 true false false false",
396 "D 70 0 true false false false" }
399 static const KeyEventTestData kTestCtrlFSuppressKeyDown
= {
400 ui::VKEY_F
, true, false, false, false,
401 true, false, false, false, 4,
402 { "D 17 0 true false false false",
403 "D 70 0 true false false false",
404 "U 70 0 true false false false",
405 "U 17 0 true false false false" }
408 // Ctrl+Z doesn't bind to any accelerators, which then should generate a
409 // keypress event with charCode=26.
410 static const KeyEventTestData kTestCtrlZ
= {
411 ui::VKEY_Z
, true, false, false, false,
412 false, false, false, false, 5,
413 { "D 17 0 true false false false",
414 "D 90 0 true false false false",
415 "P 26 26 true false false false",
416 "U 90 0 true false false false",
417 "U 17 0 true false false false" }
420 static const KeyEventTestData kTestCtrlZSuppressKeyDown
= {
421 ui::VKEY_Z
, true, false, false, false,
422 true, false, false, false, 4,
423 { "D 17 0 true false false false",
424 "D 90 0 true false false false",
425 "U 90 0 true false false false",
426 "U 17 0 true false false false" }
429 // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
430 static const KeyEventTestData kTestCtrlEnter
= {
431 ui::VKEY_RETURN
, true, false, false, false,
432 false, false, false, false, 5,
433 { "D 17 0 true false false false",
434 "D 13 0 true false false false",
435 "P 10 10 true false false false",
436 "U 13 0 true false false false",
437 "U 17 0 true false false false" }
440 ASSERT_TRUE(test_server()->Start());
442 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
443 GURL url
= test_server()->GetURL(kTestingPage
);
444 ui_test_utils::NavigateToURL(browser(), url
);
446 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
447 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
449 int tab_index
= browser()->active_index();
450 // Press Ctrl+F, which will make the Find box open and request focus.
451 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlF
));
452 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD
));
454 // Press Escape to close the Find box and move the focus back to the web page.
455 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
456 browser(), ui::VKEY_ESCAPE
, false, false, false, false));
457 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
459 // Press Ctrl+F with keydown suppressed shall not open the find box.
460 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlFSuppressKeyDown
));
461 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
463 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlZ
));
464 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlZSuppressKeyDown
));
465 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlEnter
));
467 #elif defined(OS_MACOSX)
468 // http://crbug.com/81451
469 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, FLAKY_CommandKeyEvents
) {
470 static const KeyEventTestData kTestCmdF
= {
471 ui::VKEY_F
, false, false, false, true,
472 false, false, false, false, 2,
473 { "D 91 0 false false false true",
474 "D 70 0 false false false true" }
477 // On Mac we don't send key up events when command modifier is down.
478 static const KeyEventTestData kTestCmdFSuppressKeyDown
= {
479 ui::VKEY_F
, false, false, false, true,
480 true, false, false, false, 3,
481 { "D 91 0 false false false true",
482 "D 70 0 false false false true",
483 "U 91 0 false false false true" }
486 ASSERT_TRUE(test_server()->Start());
488 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
489 GURL url
= test_server()->GetURL(kTestingPage
);
490 ui_test_utils::NavigateToURL(browser(), url
);
492 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
493 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
495 int tab_index
= browser()->active_index();
496 // Press Cmd+F, which will make the Find box open and request focus.
497 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCmdF
));
498 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD
));
500 // Press Escape to close the Find box and move the focus back to the web page.
501 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
502 browser(), ui::VKEY_ESCAPE
, false, false, false, false));
503 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
505 // Press Cmd+F with keydown suppressed shall not open the find box.
506 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCmdFSuppressKeyDown
));
507 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
511 // http://crbug.com/81451
512 #if defined(OS_MACOSX)
513 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, DISABLED_AccessKeys
) {
515 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, AccessKeys
) {
517 #if defined(OS_MACOSX)
518 // On Mac, access keys use ctrl+alt modifiers.
519 static const KeyEventTestData kTestAccessA
= {
520 ui::VKEY_A
, true, false, true, false,
521 false, false, false, false, 6,
522 { "D 17 0 true false false false",
523 "D 18 0 true false true false",
524 "D 65 0 true false true false",
525 "U 65 0 true false true false",
526 "U 18 0 true false true false",
527 "U 17 0 true false false false" }
530 static const KeyEventTestData kTestAccessDSuppress
= {
531 ui::VKEY_D
, true, false, true, false,
532 true, true, true, false, 6,
533 { "D 17 0 true false false false",
534 "D 18 0 true false true false",
535 "D 68 0 true false true false",
536 "U 68 0 true false true false",
537 "U 18 0 true false true false",
538 "U 17 0 true false false false" }
541 static const KeyEventTestData kTestAccess1
= {
542 ui::VKEY_1
, 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 49 0 true false true false",
547 "U 49 0 true false true false",
548 "U 18 0 true false true false",
549 "U 17 0 true false false false" }
552 static const KeyEventTestData kTestAccessA
= {
553 ui::VKEY_A
, false, false, true, false,
554 false, false, false, false, 4,
555 { "D 18 0 false false true false",
556 "D 65 0 false false true false",
557 "U 65 0 false false true false",
558 "U 18 0 false false true false" }
561 static const KeyEventTestData kTestAccessD
= {
562 ui::VKEY_D
, false, false, true, false,
563 false, false, false, false, 2,
564 { "D 18 0 false false true false",
565 "D 68 0 false false true false" }
568 static const KeyEventTestData kTestAccessDSuppress
= {
569 ui::VKEY_D
, false, false, true, false,
570 true, true, true, false, 4,
571 { "D 18 0 false false true false",
572 "D 68 0 false false true false",
573 "U 68 0 false false true false",
574 "U 18 0 false false true false" }
577 static const KeyEventTestData kTestAccess1
= {
578 ui::VKEY_1
, false, false, true, false,
579 false, false, false, false, 4,
580 { "D 18 0 false false true false",
581 "D 49 0 false false true false",
582 "U 49 0 false false true false",
583 "U 18 0 false false true false" }
587 ASSERT_TRUE(test_server()->Start());
589 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
590 GURL url
= test_server()->GetURL(kTestingPage
);
591 ui_test_utils::NavigateToURL(browser(), url
);
593 ui_test_utils::RunAllPendingInMessageLoop();
594 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
595 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
597 int tab_index
= browser()->active_index();
598 // Make sure no element is focused.
599 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
600 // Alt+A should focus the element with accesskey = "A".
601 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAccessA
));
602 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
"A"));
604 // Blur the focused element.
605 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
""));
606 // Make sure no element is focused.
607 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
609 #if !defined(OS_MACOSX)
610 // Alt+D should move the focus to the location entry.
611 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAccessD
));
613 // TODO(isherman): This is an experimental change to help diagnose
614 // http://crbug.com/55713
615 ui_test_utils::RunAllPendingInMessageLoop();
617 EXPECT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR
));
618 // No element should be focused, as Alt+D was handled by the browser.
619 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
621 // Move the focus back to the web page.
622 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
623 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
625 // Make sure no element is focused.
626 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
629 // If the keydown event is suppressed, then Alt+D should be handled as an
630 // accesskey rather than an accelerator key. Activation of an accesskey is not
631 // a part of the default action of the key event, so it should not be
632 // suppressed at all.
633 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAccessDSuppress
));
634 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
635 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
"D"));
637 // Blur the focused element.
638 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
""));
639 // Make sure no element is focused.
640 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
641 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAccess1
));
642 #if defined(TOOLKIT_GTK)
643 // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can
644 // not be used as accesskeys.
645 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
""));
647 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index
, L
"1"));
651 // Disabled, http://crbug.com/69475.
652 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, DISABLED_ReservedAccelerators
) {
653 ASSERT_TRUE(test_server()->Start());
655 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
656 GURL url
= test_server()->GetURL(kTestingPage
);
657 ui_test_utils::NavigateToURL(browser(), url
);
659 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
660 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
662 ASSERT_EQ(1, browser()->tab_count());
664 static const KeyEventTestData kTestCtrlOrCmdT
= {
665 #if defined(OS_MACOSX)
666 ui::VKEY_T
, false, false, false, true,
667 true, false, false, false, 1,
668 { "D 91 0 false false false true" }
670 ui::VKEY_T
, true, false, false, false,
671 true, false, false, false, 1,
672 { "D 17 0 true false false false" }
676 ui_test_utils::WindowedNotificationObserver
wait_for_new_tab(
677 NotificationType::TAB_PARENTED
,
678 NotificationService::AllSources());
680 // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
681 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT
));
683 ASSERT_NO_FATAL_FAILURE(
684 wait_for_new_tab
.WaitFor(Source
<NavigationController
>(
685 &browser()->GetTabContentsAt(1)->controller())));
688 ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length
));
689 EXPECT_EQ(1, result_length
);
691 EXPECT_EQ(2, browser()->tab_count());
692 ASSERT_EQ(1, browser()->active_index());
694 // Because of issue http://crbug.com/65375, switching back to the first tab
695 // may cause the focus to be grabbed by omnibox. So instead, we load our
696 // testing page in the newly created tab and try Cmd-W here.
697 ui_test_utils::NavigateToURL(browser(), url
);
699 // Make sure the focus is in the testing page.
700 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
701 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
703 // Reserved accelerators can't be suppressed.
704 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
706 ui_test_utils::WindowedNotificationObserver
wait_for_tab_closed(
707 NotificationType::TAB_CLOSED
, Source
<NavigationController
>(
708 &browser()->GetTabContentsAt(1)->controller()));
710 // Press Ctrl/Cmd+W, which will close the tab.
711 #if defined(OS_MACOSX)
712 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
713 browser(), ui::VKEY_W
, false, false, false, true));
715 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
716 browser(), ui::VKEY_W
, true, false, false, false));
719 ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed
.Wait());
721 EXPECT_EQ(1, browser()->tab_count());
724 #if defined(OS_MACOSX)
725 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, EditorKeyBindings
) {
726 static const KeyEventTestData kTestCtrlA
= {
727 ui::VKEY_A
, true, false, false, false,
728 false, false, false, false, 4,
729 { "D 17 0 true false false false",
730 "D 65 0 true false false false",
731 "U 65 0 true false false false",
732 "U 17 0 true false false false" }
735 static const KeyEventTestData kTestCtrlF
= {
736 ui::VKEY_F
, true, false, false, false,
737 false, false, false, false, 4,
738 { "D 17 0 true false false false",
739 "D 70 0 true false false false",
740 "U 70 0 true false false false",
741 "U 17 0 true false false false" }
744 static const KeyEventTestData kTestCtrlK
= {
745 ui::VKEY_K
, true, false, false, false,
746 false, false, false, false, 4,
747 { "D 17 0 true false false false",
748 "D 75 0 true false false false",
749 "U 75 0 true false false false",
750 "U 17 0 true false false false" }
753 ASSERT_TRUE(test_server()->Start());
755 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
756 GURL url
= test_server()->GetURL(kTestingPage
);
757 ui_test_utils::NavigateToURL(browser(), url
);
759 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
760 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
762 int tab_index
= browser()->active_index();
763 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
"A"));
764 ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index
, L
"A", L
"Hello"));
765 // Move the caret to the beginning of the line.
766 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlA
));
767 // Forward one character
768 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlF
));
769 // Delete to the end of the line.
770 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlK
));
771 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index
, L
"A", L
"H"));
775 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, PageUpDownKeys
) {
776 static const KeyEventTestData kTestPageUp
= {
777 ui::VKEY_PRIOR
, false, false, false, false,
778 false, false, false, false, 2,
779 { "D 33 0 false false false false",
780 "U 33 0 false false false false" }
783 static const KeyEventTestData kTestPageDown
= {
784 ui::VKEY_NEXT
, false, false, false, false,
785 false, false, false, false, 2,
786 { "D 34 0 false false false false",
787 "U 34 0 false false false false" }
790 ASSERT_TRUE(test_server()->Start());
792 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
793 GURL url
= test_server()->GetURL(kTestingPage
);
794 ui_test_utils::NavigateToURL(browser(), url
);
796 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
797 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
799 int tab_index
= browser()->active_index();
800 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index
, L
"A"));
801 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestPageUp
));
802 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestPageDown
));
803 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index
, L
"A", L
""));
806 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
807 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest
, FocusMenuBarByAltKey
) {
808 static const KeyEventTestData kTestAltKey
= {
809 ui::VKEY_MENU
, false, false, false, false,
810 false, false, false, false, 2,
811 { "D 18 0 false false true false",
812 "U 18 0 false false true false" }
815 static const KeyEventTestData kTestAltKeySuppress
= {
816 ui::VKEY_MENU
, false, false, false, false,
817 true, false, false, false, 2,
818 { "D 18 0 false false true false",
819 "U 18 0 false false true false" }
822 static const KeyEventTestData kTestCtrlAltKey
= {
823 ui::VKEY_MENU
, true, false, false, false,
824 false, false, false, false, 4,
825 { "D 17 0 true false false false",
826 "D 18 0 true false true false",
827 "U 18 0 true false true false",
828 "U 17 0 true false false false" }
831 ASSERT_TRUE(test_server()->Start());
833 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
834 GURL url
= test_server()->GetURL(kTestingPage
);
835 ui_test_utils::NavigateToURL(browser(), url
);
837 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
838 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
840 int tab_index
= browser()->active_index();
841 // Press and release Alt key to focus wrench menu button.
842 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAltKey
));
843 EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU
));
845 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER
));
846 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
848 // Alt key can be suppressed.
849 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestAltKeySuppress
));
850 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));
852 // Ctrl+Alt should have no effect.
853 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index
, kTestCtrlAltKey
));
854 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW
));