1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/check.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "build/build_config.h"
13 #include "build/chromeos_buildflags.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/render_widget_host_view.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/browser_test.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "net/test/embedded_test_server/embedded_test_server.h"
25 #include "third_party/blink/public/common/switches.h"
26 #include "ui/events/keycodes/keyboard_codes.h"
28 using content::NavigationController;
32 constexpr char kTestingPage[] = "/keyevents_test.html";
33 constexpr char kSuppressEventJS[] = "setDefaultAction('%s', %s);";
34 constexpr char kGetResultJS[] = "keyEventResult[%d];";
35 constexpr char kGetResultLengthJS[] = "keyEventResult.length;";
36 constexpr char kGetFocusedElementJS[] = "focusedElement;";
37 constexpr char kSetFocusedElementJS[] = "setFocusedElement('%s');";
38 constexpr char kGetTextBoxValueJS[] = "document.getElementById('%s').value;";
39 constexpr char kSetTextBoxValueJS[] =
40 "document.getElementById('%s').value = '%s';";
41 constexpr char kStartTestJS[] = "startTest(%d);";
43 // Maximum length of the result array in KeyEventTestData structure.
44 constexpr size_t kMaxResultLength = 10;
46 // A structure holding test data of a keyboard event.
47 // Each keyboard event may generate multiple result strings representing
48 // the result of keydown, keypress, keyup and textInput events.
49 // For keydown, keypress and keyup events, the format of the result string is:
50 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
51 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
52 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
53 // the state of corresponding modifier key.
54 // For textInput event, the format is: T <text>, where <text> is the text to be
56 // Please refer to chrome/test/data/keyevents_test.html for details.
57 struct KeyEventTestData {
64 bool suppress_keydown;
65 bool suppress_keypress;
67 bool suppress_textinput;
70 const char* const result[kMaxResultLength];
73 // A class to help wait for the finish of a key event test.
74 class TestFinishObserver : public content::WebContentsObserver {
76 explicit TestFinishObserver(content::WebContents* web_contents)
77 : content::WebContentsObserver(web_contents),
81 TestFinishObserver(const TestFinishObserver&) = delete;
82 TestFinishObserver& operator=(const TestFinishObserver&) = delete;
84 bool WaitForFinish() {
87 content::RunMessageLoop();
93 void DomOperationResponse(content::RenderFrameHost* render_frame_host,
94 const std::string& dom_op_result) override {
95 // We might receive responses for other script execution, but we only
96 // care about the test finished message.
97 if (dom_op_result == "\"FINISHED\"") {
100 base::RunLoop::QuitCurrentWhenIdleDeprecated();
109 class BrowserKeyEventsTest : public InProcessBrowserTest {
111 BrowserKeyEventsTest() {}
113 void SetUpCommandLine(base::CommandLine* command_line) override {
114 // Some builders are flaky due to slower loading interacting with
116 command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
119 bool IsViewFocused(ViewID vid) {
120 return ui_test_utils::IsViewFocused(browser(), vid);
123 void ClickOnView(ViewID vid) {
124 ui_test_utils::ClickOnView(browser(), vid);
127 // Set the suppress flag of an event specified by |type|. If |suppress| is
128 // true then the web page will suppress all events with |type|. Following
129 // event types are supported: keydown, keypress, keyup and textInput.
130 void SuppressEventByType(int tab_index, const char* type, bool suppress) {
131 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
134 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
135 base::StringPrintf(kSuppressEventJS, type,
136 suppress ? "false" : "true")));
139 void SuppressEvents(int tab_index, bool keydown, bool keypress,
140 bool keyup, bool textinput) {
141 ASSERT_NO_FATAL_FAILURE(SuppressEventByType(tab_index, "keydown", keydown));
142 ASSERT_NO_FATAL_FAILURE(
143 SuppressEventByType(tab_index, "keypress", keypress));
144 ASSERT_NO_FATAL_FAILURE(SuppressEventByType(tab_index, "keyup", keyup));
145 ASSERT_NO_FATAL_FAILURE(
146 SuppressEventByType(tab_index, "textInput", textinput));
149 void SuppressAllEvents(int tab_index, bool suppress) {
150 SuppressEvents(tab_index, suppress, suppress, suppress, suppress);
153 int GetResultLength(int tab_index) {
154 CHECK_LT(tab_index, browser()->tab_strip_model()->count());
155 return content::EvalJs(
156 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
161 void CheckResult(int tab_index, int length, const char* const result[]) {
162 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
163 int actual_length = GetResultLength(tab_index);
164 ASSERT_GE(actual_length, length);
165 for (int i = 0; i < actual_length; ++i) {
168 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
169 base::StringPrintf(kGetResultJS, i))
172 // If more events were received than expected, then the additional events
173 // must be keyup events.
175 ASSERT_STREQ(result[i], actual.c_str());
177 ASSERT_EQ('U', actual[0]);
181 void CheckFocusedElement(int tab_index, const char* focused) {
182 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
185 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
186 kGetFocusedElementJS));
189 void SetFocusedElement(int tab_index, const char* focused) {
190 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
193 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
194 base::StringPrintf(kSetFocusedElementJS, focused)));
197 void CheckTextBoxValue(int tab_index, const char* id, const char* value) {
198 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
201 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
202 base::StringPrintf(kGetTextBoxValueJS, id)));
205 void SetTextBoxValue(int tab_index, const char* id, const char* value) {
206 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
209 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
210 base::StringPrintf(kSetTextBoxValueJS, id, value)));
213 void StartTest(int tab_index, int result_length) {
214 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
217 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
218 base::StringPrintf(kStartTestJS, result_length)));
221 void TestKeyEvent(int tab_index, const KeyEventTestData& test) {
222 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
223 ASSERT_EQ(tab_index, browser()->tab_strip_model()->active_index());
225 // Inform our testing web page that we are about to start testing a key
227 ASSERT_NO_FATAL_FAILURE(StartTest(tab_index, test.result_length));
228 ASSERT_NO_FATAL_FAILURE(SuppressEvents(
229 tab_index, test.suppress_keydown, test.suppress_keypress,
230 test.suppress_keyup, test.suppress_textinput));
232 // We need to create a finish observer before sending the key event,
233 // because the test finished message might be arrived before returning
234 // from the SendKeyPressSync() method.
235 TestFinishObserver finish_observer(
236 browser()->tab_strip_model()->GetWebContentsAt(tab_index));
238 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
239 browser(), test.key, test.ctrl, test.shift, test.alt, test.command));
240 ASSERT_TRUE(finish_observer.WaitForFinish());
241 ASSERT_NO_FATAL_FAILURE(CheckResult(
242 tab_index, test.result_length, test.result));
245 std::string GetTestDataDescription(const KeyEventTestData& data) {
246 std::string desc = base::StringPrintf(
247 " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n"
248 " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n"
249 " Expected results(%d):\n",
250 data.key, data.ctrl, data.shift, data.alt, data.command,
251 data.suppress_keydown, data.suppress_keypress, data.suppress_keyup,
252 data.suppress_textinput, data.result_length);
253 for (int i = 0; i < data.result_length; ++i) {
255 desc.append(data.result[i]);
262 // TODO(crbug.com/1338416): Re-enable this test
263 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) {
264 static const KeyEventTestData kTestNoInput[] = {
266 { ui::VKEY_A, false, false, false, false,
267 false, false, false, false, 3,
268 { "D 65 0 false false false false",
269 "P 97 97 false false false false",
270 "U 65 0 false false false false" } },
272 { ui::VKEY_A, false, true, false, false,
273 false, false, false, false, 5,
274 { "D 16 0 false true false false",
275 "D 65 0 false true false false",
276 "P 65 65 false true false false",
277 "U 65 0 false true false false",
278 "U 16 0 false true false false" } },
279 // a, suppress keydown
280 { ui::VKEY_A, false, false, false, false,
281 true, false, false, false, 2,
282 { "D 65 0 false false false false",
283 "U 65 0 false false false false" } },
286 static const KeyEventTestData kTestWithInput[] = {
288 { ui::VKEY_A, false, false, false, false,
289 false, false, false, false, 4,
290 { "D 65 0 false false false false",
291 "P 97 97 false false false false",
293 "U 65 0 false false false false" } },
295 { ui::VKEY_A, false, true, false, false,
296 false, false, false, false, 6,
297 { "D 16 0 false true false false",
298 "D 65 0 false true false false",
299 "P 65 65 false true false false",
301 "U 65 0 false true false false",
302 "U 16 0 false true false false" } },
303 // a, suppress keydown
304 { ui::VKEY_A, false, false, false, false,
305 true, false, false, false, 2,
306 { "D 65 0 false false false false",
307 "U 65 0 false false false false" } },
308 // a, suppress keypress
309 { ui::VKEY_A, false, false, false, false,
310 false, true, false, false, 3,
311 { "D 65 0 false false false false",
312 "P 97 97 false false false false",
313 "U 65 0 false false false false" } },
314 // a, suppress textInput
315 { ui::VKEY_A, false, false, false, false,
316 false, false, false, true, 4,
317 { "D 65 0 false false false false",
318 "P 97 97 false false false false",
320 "U 65 0 false false false false" } },
323 ASSERT_TRUE(embedded_test_server()->Start());
325 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
326 GURL url = embedded_test_server()->GetURL(kTestingPage);
327 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
329 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
330 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
332 int tab_index = browser()->tab_strip_model()->active_index();
333 for (size_t i = 0; i < std::size(kTestNoInput); ++i) {
334 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
335 << "kTestNoInput[" << i << "] failed:\n"
336 << GetTestDataDescription(kTestNoInput[i]);
339 // Input in normal text box.
340 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
341 for (size_t i = 0; i < std::size(kTestWithInput); ++i) {
342 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
343 << "kTestWithInput[" << i << "] in text box failed:\n"
344 << GetTestDataDescription(kTestWithInput[i]);
346 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", "aA"));
348 // Input in password box.
349 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "B"));
350 for (size_t i = 0; i < std::size(kTestWithInput); ++i) {
351 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
352 << "kTestWithInput[" << i << "] in password box failed:\n"
353 << GetTestDataDescription(kTestWithInput[i]);
355 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "B", "aA"));
358 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
360 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CtrlKeyEvents) {
361 static const KeyEventTestData kTestCtrlF = {
362 ui::VKEY_F, true, false, false, false,
363 false, false, false, false, 2,
364 { "D 17 0 true false false false",
365 "D 70 0 true false false false" }
368 static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
369 ui::VKEY_F, true, false, false, false,
370 true, false, false, false, 4,
371 { "D 17 0 true false false false",
372 "D 70 0 true false false false",
373 "U 70 0 true false false false",
374 "U 17 0 true false false false" }
377 // Ctrl+Z doesn't bind to any accelerators, which then should generate a
378 // keypress event with charCode=26.
379 static const KeyEventTestData kTestCtrlZ = {
380 ui::VKEY_Z, true, false, false, false,
381 false, false, false, false, 5,
382 { "D 17 0 true false false false",
383 "D 90 0 true false false false",
384 "P 26 26 true false false false",
385 "U 90 0 true false false false",
386 "U 17 0 true false false false" }
389 static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
390 ui::VKEY_Z, true, false, false, false,
391 true, false, false, false, 4,
392 { "D 17 0 true false false false",
393 "D 90 0 true false false false",
394 "U 90 0 true false false false",
395 "U 17 0 true false false false" }
398 // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
399 static const KeyEventTestData kTestCtrlEnter = {
400 ui::VKEY_RETURN, true, false, false, false,
401 false, false, false, false, 5,
402 { "D 17 0 true false false false",
403 "D 13 0 true false false false",
404 "P 10 10 true false false false",
405 "U 13 0 true false false false",
406 "U 17 0 true false false false" }
409 static const KeyEventTestData kTestEscape = {
410 ui::VKEY_ESCAPE, false, false, false, false, false,
411 false, false, false, 0, {}};
413 ASSERT_TRUE(embedded_test_server()->Start());
415 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
416 GURL url = embedded_test_server()->GetURL(kTestingPage);
417 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
419 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
420 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
422 int tab_index = browser()->tab_strip_model()->active_index();
423 // Press Ctrl+F, which will make the Find box open and request focus.
424 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
425 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
427 // Press Escape to close the Find box and move the focus back to the web page.
428 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestEscape));
429 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
431 // Press Ctrl+F with keydown suppressed shall not open the find box.
432 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown));
433 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
435 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ));
436 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown));
437 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter));
439 #elif BUILDFLAG(IS_MAC)
440 // http://crbug.com/81451
441 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CommandKeyEvents) {
442 static const KeyEventTestData kTestCmdF = {
443 ui::VKEY_F, false, false, false, true,
444 false, false, false, false, 2,
445 { "D 91 0 false false false true",
446 "D 70 0 false false false true" }
449 // On Mac we don't send key up events when command modifier is down.
450 static const KeyEventTestData kTestCmdFSuppressKeyDown = {
451 ui::VKEY_F, false, false, false, true,
452 true, false, false, false, 3,
453 { "D 91 0 false false false true",
454 "D 70 0 false false false true",
455 "U 91 0 false false false true" }
458 ASSERT_TRUE(embedded_test_server()->Start());
460 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
461 GURL url = embedded_test_server()->GetURL(kTestingPage);
462 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
464 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
465 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
467 int tab_index = browser()->tab_strip_model()->active_index();
468 // Press Cmd+F, which will make the Find box open and request focus.
469 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF));
470 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
472 // Press Escape to close the Find box and move the focus back to the web page.
473 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
474 browser(), ui::VKEY_ESCAPE, false, false, false, false));
475 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
477 // Press Cmd+F with keydown suppressed shall not open the find box.
478 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown));
479 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
483 // https://crbug.com/81451 for mac
484 // https://crbug.com/1249688 for Lacros
485 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS)
486 #define MAYBE_AccessKeys DISABLED_AccessKeys
488 #define MAYBE_AccessKeys AccessKeys
490 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_AccessKeys) {
491 #if BUILDFLAG(IS_MAC)
492 // On Mac, access keys use ctrl+alt modifiers.
493 static const KeyEventTestData kTestAccessA = {
494 ui::VKEY_A, true, false, true, false,
495 false, false, false, false, 6,
496 { "D 17 0 true false false false",
497 "D 18 0 true false true false",
498 "D 65 0 true false true false",
499 "U 65 0 true false true false",
500 "U 18 0 true false true false",
501 "U 17 0 true false false false" }
504 static const KeyEventTestData kTestAccessDSuppress = {
505 ui::VKEY_D, true, false, true, false,
506 true, true, true, false, 6,
507 { "D 17 0 true false false false",
508 "D 18 0 true false true false",
509 "D 68 0 true false true false",
510 "U 68 0 true false true false",
511 "U 18 0 true false true false",
512 "U 17 0 true false false false" }
515 static const KeyEventTestData kTestAccessA = {
516 ui::VKEY_A, false, false, true, false,
517 false, false, false, false, 4,
518 { "D 18 0 false false true false",
519 "D 65 0 false false true false",
520 "U 65 0 false false true false",
521 "U 18 0 false false true false" }
524 static const KeyEventTestData kTestAccessD = {
525 ui::VKEY_D, false, false, true, false,
526 false, false, false, false, 2,
527 { "D 18 0 false false true false",
528 "D 68 0 false false true false" }
531 static const KeyEventTestData kTestAccessDSuppress = {
532 ui::VKEY_D, false, false, true, false,
533 true, true, true, false, 4,
534 { "D 18 0 false false true false",
535 "D 68 0 false false true false",
536 "U 68 0 false false true false",
537 "U 18 0 false false true false" }
542 ASSERT_TRUE(embedded_test_server()->Start());
544 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
545 GURL url = embedded_test_server()->GetURL(kTestingPage);
546 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
548 content::RunAllPendingInMessageLoop();
549 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
550 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
552 int tab_index = browser()->tab_strip_model()->active_index();
553 // Make sure no element is focused.
554 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
555 // Alt+A should focus the element with accesskey = "A".
556 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA));
557 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, "A"));
559 // Blur the focused element.
560 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, ""));
561 // Make sure no element is focused.
562 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
564 #if !BUILDFLAG(IS_MAC)
565 // Alt+D should move the focus to the location entry.
566 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD));
568 // TODO(isherman): This is an experimental change to help diagnose
569 // http://crbug.com/55713
570 content::RunAllPendingInMessageLoop();
571 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
572 // No element should be focused, as Alt+D was handled by the browser.
573 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
575 // Move the focus back to the web page.
576 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
577 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
579 // Make sure no element is focused.
580 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
583 // If the keydown event is suppressed, then Alt+D should be handled as an
584 // accesskey rather than an accelerator key. Activation of an accesskey is not
585 // a part of the default action of the key event, so it should not be
586 // suppressed at all.
587 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress));
588 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
589 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, "D"));
591 // Blur the focused element.
592 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, ""));
593 // Make sure no element is focused.
594 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
597 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, ReservedAccelerators) {
598 ASSERT_TRUE(embedded_test_server()->Start());
600 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
601 GURL url = embedded_test_server()->GetURL(kTestingPage);
602 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
604 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
605 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
607 ASSERT_EQ(1, browser()->tab_strip_model()->count());
609 static const KeyEventTestData kTestCtrlOrCmdT = {
610 #if BUILDFLAG(IS_MAC)
621 {"D 91 0 false false false true"}
623 ui::VKEY_T, true, false, false, false,
624 true, false, false, false, 1,
625 { "D 17 0 true false false false" }
629 ui_test_utils::TabAddedWaiter wait_for_new_tab(browser());
631 // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
632 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT));
633 wait_for_new_tab.Wait();
635 EXPECT_EQ(1, GetResultLength(0));
637 EXPECT_EQ(2, browser()->tab_strip_model()->count());
638 ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
640 // Because of issue <http://crbug.com/65375>, switching back to the first tab
641 // may cause the focus to be grabbed by omnibox. So instead, we load our
642 // testing page in the newly created tab and try Cmd-W here.
643 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
645 // Make sure the focus is in the testing page.
646 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
647 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
649 // Reserved accelerators can't be suppressed.
650 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
652 content::WebContentsDestroyedWatcher destroyed_watcher(
653 browser()->tab_strip_model()->GetWebContentsAt(1));
655 // Press Ctrl/Cmd+W, which will close the tab.
656 #if BUILDFLAG(IS_MAC)
657 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
658 browser(), ui::VKEY_W, false, false, false, true));
660 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
661 browser(), ui::VKEY_W, true, false, false, false));
664 ASSERT_NO_FATAL_FAILURE(destroyed_watcher.Wait());
666 EXPECT_EQ(1, browser()->tab_strip_model()->count());
669 #if BUILDFLAG(IS_MAC)
670 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
671 static const KeyEventTestData kTestCtrlA = {
672 ui::VKEY_A, true, false, false, false,
673 false, false, false, false, 4,
674 { "D 17 0 true false false false",
675 "D 65 0 true false false false",
676 "U 65 0 true false false false",
677 "U 17 0 true false false false" }
680 static const KeyEventTestData kTestCtrlF = {
681 ui::VKEY_F, true, false, false, false,
682 false, false, false, false, 4,
683 { "D 17 0 true false false false",
684 "D 70 0 true false false false",
685 "U 70 0 true false false false",
686 "U 17 0 true false false false" }
689 static const KeyEventTestData kTestCtrlK = {
690 ui::VKEY_K, true, false, false, false,
691 false, false, false, false, 4,
692 { "D 17 0 true false false false",
693 "D 75 0 true false false false",
694 "U 75 0 true false false false",
695 "U 17 0 true false false false" }
698 ASSERT_TRUE(embedded_test_server()->Start());
700 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
701 GURL url = embedded_test_server()->GetURL(kTestingPage);
702 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
704 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
705 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
707 int tab_index = browser()->tab_strip_model()->active_index();
708 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
709 ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, "A", "Hello"));
710 // Move the caret to the beginning of the line.
711 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA));
712 // Forward one character
713 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
714 // Delete to the end of the line.
715 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK));
716 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", "H"));
720 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, PageUpDownKeys) {
721 static const KeyEventTestData kTestPageUp = {
722 ui::VKEY_PRIOR, false, false, false, false,
723 false, false, false, false, 2,
724 { "D 33 0 false false false false",
725 "U 33 0 false false false false" }
728 static const KeyEventTestData kTestPageDown = {
729 ui::VKEY_NEXT, false, false, false, false,
730 false, false, false, false, 2,
731 { "D 34 0 false false false false",
732 "U 34 0 false false false false" }
735 ASSERT_TRUE(embedded_test_server()->Start());
737 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
738 GURL url = embedded_test_server()->GetURL(kTestingPage);
739 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
741 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
742 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
744 int tab_index = browser()->tab_strip_model()->active_index();
745 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
746 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp));
747 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown));
748 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", ""));
751 // AltKey is enabled only on Windows. See crbug.com/114537.
752 #if BUILDFLAG(IS_WIN)
753 // If this flakes, disable and log details in http://crbug.com/523255.
754 // TODO(sky): remove comment if proves stable and reenable other tests.
755 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
756 static const KeyEventTestData kTestAltKey = {
757 ui::VKEY_MENU, false, false, false, false,
758 false, false, false, false, 2,
759 { "D 18 0 false false true false",
760 "U 18 0 false false true false" }
763 static const KeyEventTestData kTestAltKeySuppress = {
764 ui::VKEY_MENU, false, false, false, false,
765 true, false, false, false, 2,
766 { "D 18 0 false false true false",
767 "U 18 0 false false true false" }
770 static const KeyEventTestData kTestCtrlAltKey = {
771 ui::VKEY_MENU, true, false, false, false,
772 false, false, false, false, 4,
773 { "D 17 0 true false false false",
774 "D 18 0 true false true false",
775 "U 18 0 true false true false",
776 "U 17 0 true false false false" }
779 ASSERT_TRUE(embedded_test_server()->Start());
781 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
782 GURL url = embedded_test_server()->GetURL(kTestingPage);
783 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
785 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
786 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
788 int tab_index = browser()->tab_strip_model()->active_index();
789 // Press and release Alt key to focus wrench menu button.
790 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey));
791 EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU));
793 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
794 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
796 // Alt key can be suppressed.
797 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
798 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
800 // Ctrl+Alt should have no effect.
801 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
802 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));