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