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"
30 #include "ui/views/controls/textfield/textfield.h"
32 // TODO(kbr): remove: http://crbug.com/222296
33 #if defined(OS_MACOSX)
34 #import "base/mac/mac_util.h"
37 using content::DomOperationNotificationDetails;
38 using content::NavigationController;
39 using content::RenderViewHost;
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));";
63 // Maximum lenght of the result array in KeyEventTestData structure.
64 const size_t kMaxResultLength = 10;
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
76 // Please refer to chrome/test/data/keyevents_test.html for details.
77 struct KeyEventTestData {
84 bool suppress_keydown;
85 bool suppress_keypress;
87 bool suppress_textinput;
90 const char* const result[kMaxResultLength];
93 const wchar_t* GetBoolString(bool value) {
94 return value ? L"true" : L"false";
97 // A class to help wait for the finish of a key event test.
98 class TestFinishObserver : public content::NotificationObserver {
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));
106 bool WaitForFinish() {
109 content::RunMessageLoop();
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\"") {
125 base::MessageLoopForUI::current()->Quit();
132 content::NotificationRegistrar registrar_;
134 DISALLOW_COPY_AND_ASSIGN(TestFinishObserver);
137 class BrowserKeyEventsTest : public InProcessBrowserTest {
139 BrowserKeyEventsTest() {}
141 bool IsViewFocused(ViewID vid) {
142 return ui_test_utils::IsViewFocused(browser(), vid);
145 void ClickOnView(ViewID vid) {
146 ui_test_utils::ClickOnView(browser(), vid);
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());
155 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
156 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
157 base::StringPrintf(kSuppressEventJS, type, GetBoolString(!suppress)),
159 ASSERT_EQ(!suppress, actual);
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));
174 void SuppressAllEvents(int tab_index, bool suppress) {
175 SuppressEvents(tab_index, suppress, suppress, suppress, suppress);
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),
186 void CheckResult(int tab_index, int length, const char* const result[]) {
187 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
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) {
193 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
194 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
195 base::StringPrintf(kGetResultJS, i),
198 // If more events were received than expected, then the additional events
199 // must be keyup events.
201 ASSERT_STREQ(result[i], actual.c_str());
203 ASSERT_EQ('U', actual[0]);
207 void CheckFocusedElement(int tab_index, const wchar_t* focused) {
208 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
210 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
211 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
212 kGetFocusedElementJS,
214 ASSERT_EQ(WideToUTF8(focused), actual);
217 void SetFocusedElement(int tab_index, const wchar_t* focused) {
218 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
220 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
221 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
222 base::StringPrintf(kSetFocusedElementJS, focused),
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());
231 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
232 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
233 base::StringPrintf(kGetTextBoxValueJS, id),
235 ASSERT_EQ(WideToUTF8(value), actual);
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());
242 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
243 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
244 base::StringPrintf(kSetTextBoxValueJS, id, value),
246 ASSERT_EQ(WideToUTF8(value), actual);
249 void StartTest(int tab_index, int result_length) {
250 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
252 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
253 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
254 base::StringPrintf(kStartTestJS, result_length),
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());
263 // Inform our testing web page that we are about to start testing a key
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));
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());
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));
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) {
294 desc.append(data.result[i]);
301 // Flaky: http://crbug.com/129235, http://crbug.com/81451.
302 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) {
303 static const KeyEventTestData kTestNoInput[] = {
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" } },
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" } },
325 static const KeyEventTestData kTestWithInput[] = {
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",
332 "U 65 0 false false false false" } },
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",
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",
359 "U 65 0 false false false false" } },
362 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
364 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
365 GURL url = embedded_test_server()->GetURL(kTestingPage);
366 ui_test_utils::NavigateToURL(browser(), url);
368 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
369 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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]);
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]);
385 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA"));
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]);
394 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA"));
397 #if defined(OS_WIN) || defined(OS_LINUX)
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
404 #define MAYBE_CtrlKeyEvents CtrlKeyEvents
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" }
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" }
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" }
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" }
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" }
456 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
458 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
459 GURL url = embedded_test_server()->GetURL(kTestingPage);
460 ui_test_utils::NavigateToURL(browser(), url);
462 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
463 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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));
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));
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));
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));
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" }
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" }
502 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
504 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
505 GURL url = embedded_test_server()->GetURL(kTestingPage);
506 ui_test_utils::NavigateToURL(browser(), url);
508 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
509 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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));
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));
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));
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" }
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" }
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" }
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" }
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" }
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" }
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" }
602 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
604 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
605 GURL url = embedded_test_server()->GetURL(kTestingPage);
606 ui_test_utils::NavigateToURL(browser(), url);
608 content::RunAllPendingInMessageLoop();
609 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
610 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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"));
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""));
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));
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""));
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));
639 // Make sure no element is focused.
640 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
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"));
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""));
664 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1"));
669 // Flaky, http://crbug.com/69475.
670 #if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA))
671 #define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators
673 #define MAYBE_ReservedAccelerators ReservedAccelerators
675 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) {
676 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
678 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
679 GURL url = embedded_test_server()->GetURL(kTestingPage);
680 ui_test_utils::NavigateToURL(browser(), url);
682 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
683 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
685 ASSERT_EQ(1, browser()->tab_strip_model()->count());
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" }
693 ui::VKEY_T, true, false, false, false,
694 true, false, false, false, 1,
695 { "D 17 0 true false false false" }
699 content::WindowedNotificationObserver wait_for_new_tab(
700 chrome::NOTIFICATION_TAB_PARENTED,
701 content::NotificationService::AllSources());
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();
708 ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length));
709 EXPECT_EQ(1, result_length);
711 EXPECT_EQ(2, browser()->tab_strip_model()->count());
712 ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
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);
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));
723 // Reserved accelerators can't be suppressed.
724 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
726 content::WebContentsDestroyedWatcher destroyed_watcher(
727 browser()->tab_strip_model()->GetWebContentsAt(1));
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));
734 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
735 browser(), ui::VKEY_W, true, false, false, false));
738 ASSERT_NO_FATAL_FAILURE(destroyed_watcher.Wait());
740 EXPECT_EQ(1, browser()->tab_strip_model()->count());
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())
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" }
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" }
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" }
776 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
778 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
779 GURL url = embedded_test_server()->GetURL(kTestingPage);
780 ui_test_utils::NavigateToURL(browser(), url);
782 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
783 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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"));
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" }
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" }
814 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
816 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
817 GURL url = embedded_test_server()->GetURL(kTestingPage);
818 ui_test_utils::NavigateToURL(browser(), url);
820 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
821 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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""));
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" }
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" }
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" }
856 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
858 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
859 GURL url = embedded_test_server()->GetURL(kTestingPage);
860 ui_test_utils::NavigateToURL(browser(), url);
862 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
863 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
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));
870 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
871 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
873 // Alt key can be suppressed.
874 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
875 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
877 // Ctrl+Alt should have no effect.
878 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
879 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));