| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "build/build_config.h" |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "base/message_loop.h" |
| #include "base/string_util.h" |
| #include "base/utf_string_conversions.h" |
| #include "base/values.h" |
| #include "chrome/browser/dom_operation_notification_details.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/test/in_process_browser_test.h" |
| #include "chrome/test/ui_test_utils.h" |
| #include "content/browser/renderer_host/render_view_host.h" |
| #include "content/browser/renderer_host/render_widget_host_view.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/browser/tab_contents/tab_contents_view.h" |
| #include "content/common/notification_registrar.h" |
| #include "content/common/notification_service.h" |
| #include "net/test/test_server.h" |
| #include "ui/base/keycodes/keyboard_codes.h" |
| |
| namespace { |
| |
| const char kTestingPage[] = "files/keyevents_test.html"; |
| const wchar_t kSuppressEventJS[] = |
| L"window.domAutomationController.send(setDefaultAction('%ls', %ls));"; |
| const wchar_t kGetResultJS[] = |
| L"window.domAutomationController.send(keyEventResult[%d]);"; |
| const wchar_t kGetResultLengthJS[] = |
| L"window.domAutomationController.send(keyEventResult.length);"; |
| const wchar_t kGetFocusedElementJS[] = |
| L"window.domAutomationController.send(focusedElement);"; |
| const wchar_t kSetFocusedElementJS[] = |
| L"window.domAutomationController.send(setFocusedElement('%ls'));"; |
| const wchar_t kGetTextBoxValueJS[] = |
| L"window.domAutomationController.send(" |
| L"document.getElementById('%ls').value);"; |
| const wchar_t kSetTextBoxValueJS[] = |
| L"window.domAutomationController.send(" |
| L"document.getElementById('%ls').value = '%ls');"; |
| const wchar_t kStartTestJS[] = |
| L"window.domAutomationController.send(startTest(%d));"; |
| |
| // Maximum lenght of the result array in KeyEventTestData structure. |
| const size_t kMaxResultLength = 10; |
| |
| // A structure holding test data of a keyboard event. |
| // Each keyboard event may generate multiple result strings representing |
| // the result of keydown, keypress, keyup and textInput events. |
| // For keydown, keypress and keyup events, the format of the result string is: |
| // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey> |
| // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup). |
| // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating |
| // the state of corresponding modifier key. |
| // For textInput event, the format is: T <text>, where <text> is the text to be |
| // input. |
| // Please refer to chrome/test/data/keyevents_test.html for details. |
| struct KeyEventTestData { |
| ui::KeyboardCode key; |
| bool ctrl; |
| bool shift; |
| bool alt; |
| bool command; |
| |
| bool suppress_keydown; |
| bool suppress_keypress; |
| bool suppress_keyup; |
| bool suppress_textinput; |
| |
| int result_length; |
| const char* const result[kMaxResultLength]; |
| }; |
| |
| const wchar_t* GetBoolString(bool value) { |
| return value ? L"true" : L"false"; |
| } |
| |
| // A class to help wait for the finish of a key event test. |
| class TestFinishObserver : public NotificationObserver { |
| public: |
| explicit TestFinishObserver(RenderViewHost* render_view_host) |
| : finished_(false), waiting_(false) { |
| registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, |
| Source<RenderViewHost>(render_view_host)); |
| } |
| |
| bool WaitForFinish() { |
| if (!finished_) { |
| waiting_ = true; |
| ui_test_utils::RunMessageLoop(); |
| waiting_ = false; |
| } |
| return finished_; |
| } |
| |
| virtual void Observe(NotificationType type, |
| const NotificationSource& source, |
| const NotificationDetails& details) { |
| DCHECK(type == NotificationType::DOM_OPERATION_RESPONSE); |
| Details<DomOperationNotificationDetails> dom_op_details(details); |
| // We might receive responses for other script execution, but we only |
| // care about the test finished message. |
| if (dom_op_details->json() == "\"FINISHED\"") { |
| finished_ = true; |
| if (waiting_) |
| MessageLoopForUI::current()->Quit(); |
| } |
| } |
| |
| private: |
| bool finished_; |
| bool waiting_; |
| NotificationRegistrar registrar_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestFinishObserver); |
| }; |
| |
| class BrowserKeyEventsTest : public InProcessBrowserTest { |
| public: |
| BrowserKeyEventsTest() { |
| set_show_window(true); |
| EnableDOMAutomation(); |
| } |
| |
| bool IsViewFocused(ViewID vid) { |
| return ui_test_utils::IsViewFocused(browser(), vid); |
| } |
| |
| void ClickOnView(ViewID vid) { |
| ui_test_utils::ClickOnView(browser(), vid); |
| } |
| |
| // Set the suppress flag of an event specified by |type|. If |suppress| is |
| // true then the web page will suppress all events with |type|. Following |
| // event types are supported: keydown, keypress, keyup and textInput. |
| void SuppressEventByType(int tab_index, const wchar_t* type, bool suppress) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| bool actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", |
| StringPrintf(kSuppressEventJS, type, GetBoolString(!suppress)), |
| &actual)); |
| ASSERT_EQ(!suppress, actual); |
| } |
| |
| void SuppressEvents(int tab_index, bool keydown, bool keypress, |
| bool keyup, bool textinput) { |
| ASSERT_NO_FATAL_FAILURE( |
| SuppressEventByType(tab_index, L"keydown", keydown)); |
| ASSERT_NO_FATAL_FAILURE( |
| SuppressEventByType(tab_index, L"keypress", keypress)); |
| ASSERT_NO_FATAL_FAILURE( |
| SuppressEventByType(tab_index, L"keyup", keyup)); |
| ASSERT_NO_FATAL_FAILURE( |
| SuppressEventByType(tab_index, L"textInput", textinput)); |
| } |
| |
| void SuppressAllEvents(int tab_index, bool suppress) { |
| SuppressEvents(tab_index, suppress, suppress, suppress, suppress); |
| } |
| |
| void GetResultLength(int tab_index, int* length) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", kGetResultLengthJS, length)); |
| } |
| |
| void CheckResult(int tab_index, int length, const char* const result[]) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| int actual_length; |
| ASSERT_NO_FATAL_FAILURE(GetResultLength(tab_index, &actual_length)); |
| ASSERT_GE(actual_length, length); |
| for (int i = 0; i < actual_length; ++i) { |
| std::string actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", StringPrintf(kGetResultJS, i), &actual)); |
| |
| // If more events were received than expected, then the additional events |
| // must be keyup events. |
| if (i < length) |
| ASSERT_STREQ(result[i], actual.c_str()); |
| else |
| ASSERT_EQ('U', actual[0]); |
| } |
| } |
| |
| void CheckFocusedElement(int tab_index, const wchar_t* focused) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| std::string actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", kGetFocusedElementJS, &actual)); |
| ASSERT_EQ(WideToUTF8(focused), actual); |
| } |
| |
| void SetFocusedElement(int tab_index, const wchar_t* focused) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| bool actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", |
| StringPrintf(kSetFocusedElementJS, focused), |
| &actual)); |
| ASSERT_TRUE(actual); |
| } |
| |
| void CheckTextBoxValue(int tab_index, const wchar_t* id, |
| const wchar_t* value) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| std::string actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", |
| StringPrintf(kGetTextBoxValueJS, id), |
| &actual)); |
| ASSERT_EQ(WideToUTF8(value), actual); |
| } |
| |
| void SetTextBoxValue(int tab_index, const wchar_t* id, |
| const wchar_t* value) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| std::string actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", |
| StringPrintf(kSetTextBoxValueJS, id, value), |
| &actual)); |
| ASSERT_EQ(WideToUTF8(value), actual); |
| } |
| |
| void StartTest(int tab_index, int result_length) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| bool actual; |
| ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( |
| browser()->GetTabContentsAt(tab_index)->render_view_host(), |
| L"", StringPrintf(kStartTestJS, result_length), &actual)); |
| ASSERT_TRUE(actual); |
| } |
| |
| void TestKeyEvent(int tab_index, const KeyEventTestData& test) { |
| ASSERT_LT(tab_index, browser()->tab_count()); |
| ASSERT_EQ(tab_index, browser()->active_index()); |
| |
| // Inform our testing web page that we are about to start testing a key |
| // event. |
| ASSERT_NO_FATAL_FAILURE(StartTest(tab_index, test.result_length)); |
| ASSERT_NO_FATAL_FAILURE(SuppressEvents( |
| tab_index, test.suppress_keydown, test.suppress_keypress, |
| test.suppress_keyup, test.suppress_textinput)); |
| |
| // We need to create a finish observer before sending the key event, |
| // because the test finished message might be arrived before returning |
| // from the SendKeyPressSync() method. |
| TestFinishObserver finish_observer( |
| browser()->GetTabContentsAt(tab_index)->render_view_host()); |
| |
| ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| browser(), test.key, test.ctrl, test.shift, test.alt, test.command)); |
| ASSERT_TRUE(finish_observer.WaitForFinish()); |
| ASSERT_NO_FATAL_FAILURE(CheckResult( |
| tab_index, test.result_length, test.result)); |
| } |
| |
| std::string GetTestDataDescription(const KeyEventTestData& data) { |
| std::string desc = StringPrintf( |
| " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n" |
| " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n" |
| " Expected results(%d):\n", |
| data.key, data.ctrl, data.shift, data.alt, data.command, |
| data.suppress_keydown, data.suppress_keypress, data.suppress_keyup, |
| data.suppress_textinput, data.result_length); |
| for (int i = 0; i < data.result_length; ++i) { |
| desc.append(" "); |
| desc.append(data.result[i]); |
| desc.append("\n"); |
| } |
| return desc; |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, NormalKeyEvents) { |
| static const KeyEventTestData kTestNoInput[] = { |
| // a |
| { ui::VKEY_A, false, false, false, false, |
| false, false, false, false, 3, |
| { "D 65 0 false false false false", |
| "P 97 97 false false false false", |
| "U 65 0 false false false false" } }, |
| // shift-a |
| { ui::VKEY_A, false, true, false, false, |
| false, false, false, false, 5, |
| { "D 16 0 false true false false", |
| "D 65 0 false true false false", |
| "P 65 65 false true false false", |
| "U 65 0 false true false false", |
| "U 16 0 false true false false" } }, |
| // a, suppress keydown |
| { ui::VKEY_A, false, false, false, false, |
| true, false, false, false, 2, |
| { "D 65 0 false false false false", |
| "U 65 0 false false false false" } }, |
| }; |
| |
| static const KeyEventTestData kTestWithInput[] = { |
| // a |
| { ui::VKEY_A, false, false, false, false, |
| false, false, false, false, 4, |
| { "D 65 0 false false false false", |
| "P 97 97 false false false false", |
| "T a", |
| "U 65 0 false false false false" } }, |
| // shift-a |
| { ui::VKEY_A, false, true, false, false, |
| false, false, false, false, 6, |
| { "D 16 0 false true false false", |
| "D 65 0 false true false false", |
| "P 65 65 false true false false", |
| "T A", |
| "U 65 0 false true false false", |
| "U 16 0 false true false false" } }, |
| // a, suppress keydown |
| { ui::VKEY_A, false, false, false, false, |
| true, false, false, false, 2, |
| { "D 65 0 false false false false", |
| "U 65 0 false false false false" } }, |
| // a, suppress keypress |
| { ui::VKEY_A, false, false, false, false, |
| false, true, false, false, 3, |
| { "D 65 0 false false false false", |
| "P 97 97 false false false false", |
| "U 65 0 false false false false" } }, |
| // a, suppress textInput |
| { ui::VKEY_A, false, false, false, false, |
| false, false, false, true, 4, |
| { "D 65 0 false false false false", |
| "P 97 97 false false false false", |
| "T a", |
| "U 65 0 false false false false" } }, |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| for (size_t i = 0; i < arraysize(kTestNoInput); ++i) { |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i])) |
| << "kTestNoInput[" << i << "] failed:\n" |
| << GetTestDataDescription(kTestNoInput[i]); |
| } |
| |
| // Input in normal text box. |
| ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); |
| for (size_t i = 0; i < arraysize(kTestWithInput); ++i) { |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i])) |
| << "kTestWithInput[" << i << "] in text box failed:\n" |
| << GetTestDataDescription(kTestWithInput[i]); |
| } |
| EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA")); |
| |
| // Input in password box. |
| ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B")); |
| for (size_t i = 0; i < arraysize(kTestWithInput); ++i) { |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i])) |
| << "kTestWithInput[" << i << "] in password box failed:\n" |
| << GetTestDataDescription(kTestWithInput[i]); |
| } |
| EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA")); |
| } |
| |
| #if defined(OS_WIN) || defined(OS_LINUX) |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CtrlKeyEvents) { |
| static const KeyEventTestData kTestCtrlF = { |
| ui::VKEY_F, true, false, false, false, |
| false, false, false, false, 2, |
| { "D 17 0 true false false false", |
| "D 70 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestCtrlFSuppressKeyDown = { |
| ui::VKEY_F, true, false, false, false, |
| true, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 70 0 true false false false", |
| "U 70 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| // Ctrl+Z doesn't bind to any accelerators, which then should generate a |
| // keypress event with charCode=26. |
| static const KeyEventTestData kTestCtrlZ = { |
| ui::VKEY_Z, true, false, false, false, |
| false, false, false, false, 5, |
| { "D 17 0 true false false false", |
| "D 90 0 true false false false", |
| "P 26 26 true false false false", |
| "U 90 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestCtrlZSuppressKeyDown = { |
| ui::VKEY_Z, true, false, false, false, |
| true, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 90 0 true false false false", |
| "U 90 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| // Ctrl+Enter shall generate a keypress event with charCode=10 (LF). |
| static const KeyEventTestData kTestCtrlEnter = { |
| ui::VKEY_RETURN, true, false, false, false, |
| false, false, false, false, 5, |
| { "D 17 0 true false false false", |
| "D 13 0 true false false false", |
| "P 10 10 true false false false", |
| "U 13 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| // Press Ctrl+F, which will make the Find box open and request focus. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); |
| EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); |
| |
| // Press Escape to close the Find box and move the focus back to the web page. |
| ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| browser(), ui::VKEY_ESCAPE, false, false, false, false)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Press Ctrl+F with keydown suppressed shall not open the find box. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ)); |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown)); |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter)); |
| } |
| #elif defined(OS_MACOSX) |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CommandKeyEvents) { |
| static const KeyEventTestData kTestCmdF = { |
| ui::VKEY_F, false, false, false, true, |
| false, false, false, false, 2, |
| { "D 91 0 false false false true", |
| "D 70 0 false false false true" } |
| }; |
| |
| // On Mac we don't send key up events when command modifier is down. |
| static const KeyEventTestData kTestCmdFSuppressKeyDown = { |
| ui::VKEY_F, false, false, false, true, |
| true, false, false, false, 3, |
| { "D 91 0 false false false true", |
| "D 70 0 false false false true", |
| "U 91 0 false false false true" } |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| // Press Cmd+F, which will make the Find box open and request focus. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF)); |
| EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); |
| |
| // Press Escape to close the Find box and move the focus back to the web page. |
| ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| browser(), ui::VKEY_ESCAPE, false, false, false, false)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Press Cmd+F with keydown suppressed shall not open the find box. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| } |
| #endif |
| |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, AccessKeys) { |
| #if defined(OS_MACOSX) |
| // On Mac, access keys use ctrl+alt modifiers. |
| static const KeyEventTestData kTestAccessA = { |
| ui::VKEY_A, true, false, true, false, |
| false, false, false, false, 6, |
| { "D 17 0 true false false false", |
| "D 18 0 true false true false", |
| "D 65 0 true false true false", |
| "U 65 0 true false true false", |
| "U 18 0 true false true false", |
| "U 17 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestAccessDSuppress = { |
| ui::VKEY_D, true, false, true, false, |
| true, true, true, false, 6, |
| { "D 17 0 true false false false", |
| "D 18 0 true false true false", |
| "D 68 0 true false true false", |
| "U 68 0 true false true false", |
| "U 18 0 true false true false", |
| "U 17 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestAccess1 = { |
| ui::VKEY_1, true, false, true, false, |
| false, false, false, false, 6, |
| { "D 17 0 true false false false", |
| "D 18 0 true false true false", |
| "D 49 0 true false true false", |
| "U 49 0 true false true false", |
| "U 18 0 true false true false", |
| "U 17 0 true false false false" } |
| }; |
| #else |
| static const KeyEventTestData kTestAccessA = { |
| ui::VKEY_A, false, false, true, false, |
| false, false, false, false, 4, |
| { "D 18 0 false false true false", |
| "D 65 0 false false true false", |
| "U 65 0 false false true false", |
| "U 18 0 false false true false" } |
| }; |
| |
| static const KeyEventTestData kTestAccessD = { |
| ui::VKEY_D, false, false, true, false, |
| false, false, false, false, 2, |
| { "D 18 0 false false true false", |
| "D 68 0 false false true false" } |
| }; |
| |
| static const KeyEventTestData kTestAccessDSuppress = { |
| ui::VKEY_D, false, false, true, false, |
| true, true, true, false, 4, |
| { "D 18 0 false false true false", |
| "D 68 0 false false true false", |
| "U 68 0 false false true false", |
| "U 18 0 false false true false" } |
| }; |
| |
| static const KeyEventTestData kTestAccess1 = { |
| ui::VKEY_1, false, false, true, false, |
| false, false, false, false, 4, |
| { "D 18 0 false false true false", |
| "D 49 0 false false true false", |
| "U 49 0 false false true false", |
| "U 18 0 false false true false" } |
| }; |
| #endif |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ui_test_utils::RunAllPendingInMessageLoop(); |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| // Make sure no element is focused. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| // Alt+A should focus the element with accesskey = "A". |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA)); |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A")); |
| |
| // Blur the focused element. |
| EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); |
| // Make sure no element is focused. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| |
| #if !defined(OS_MACOSX) |
| // Alt+D should move the focus to the location entry. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD)); |
| |
| // TODO(isherman): This is an experimental change to help diagnose |
| // http://crbug.com/55713 |
| ui_test_utils::RunAllPendingInMessageLoop(); |
| |
| EXPECT_TRUE(IsViewFocused(VIEW_ID_LOCATION_BAR)); |
| // No element should be focused, as Alt+D was handled by the browser. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| |
| // Move the focus back to the web page. |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Make sure no element is focused. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| #endif |
| |
| // If the keydown event is suppressed, then Alt+D should be handled as an |
| // accesskey rather than an accelerator key. Activation of an accesskey is not |
| // a part of the default action of the key event, so it should not be |
| // suppressed at all. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D")); |
| |
| // Blur the focused element. |
| EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); |
| // Make sure no element is focused. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1)); |
| #if defined(TOOLKIT_GTK) |
| // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can |
| // not be used as accesskeys. |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); |
| #else |
| EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1")); |
| #endif |
| } |
| |
| // Disabled, http://crbug.com/69475. |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_ReservedAccelerators) { |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| ASSERT_EQ(1, browser()->tab_count()); |
| |
| static const KeyEventTestData kTestCtrlOrCmdT = { |
| #if defined(OS_MACOSX) |
| ui::VKEY_T, false, false, false, true, |
| true, false, false, false, 1, |
| { "D 91 0 false false false true" } |
| #else |
| ui::VKEY_T, true, false, false, false, |
| true, false, false, false, 1, |
| { "D 17 0 true false false false" } |
| #endif |
| }; |
| |
| ui_test_utils::WindowedNotificationObserver wait_for_new_tab( |
| NotificationType::TAB_PARENTED, |
| NotificationService::AllSources()); |
| |
| // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT)); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| wait_for_new_tab.WaitFor(Source<NavigationController>( |
| &browser()->GetTabContentsAt(1)->controller()))); |
| |
| int result_length; |
| ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length)); |
| EXPECT_EQ(1, result_length); |
| |
| EXPECT_EQ(2, browser()->tab_count()); |
| ASSERT_EQ(1, browser()->active_index()); |
| |
| // Because of issue http://crbug.com/65375, switching back to the first tab |
| // may cause the focus to be grabbed by omnibox. So instead, we load our |
| // testing page in the newly created tab and try Cmd-W here. |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| // Make sure the focus is in the testing page. |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Reserved accelerators can't be suppressed. |
| ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true)); |
| |
| ui_test_utils::WindowedNotificationObserver wait_for_tab_closed( |
| NotificationType::TAB_CLOSED, Source<NavigationController>( |
| &browser()->GetTabContentsAt(1)->controller())); |
| |
| // Press Ctrl/Cmd+W, which will close the tab. |
| #if defined(OS_MACOSX) |
| ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| browser(), ui::VKEY_W, false, false, false, true)); |
| #else |
| ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| browser(), ui::VKEY_W, true, false, false, false)); |
| #endif |
| |
| ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed.Wait()); |
| |
| EXPECT_EQ(1, browser()->tab_count()); |
| } |
| |
| #if defined(OS_MACOSX) |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) { |
| static const KeyEventTestData kTestCtrlA = { |
| ui::VKEY_A, true, false, false, false, |
| false, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 65 0 true false false false", |
| "U 65 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestCtrlF = { |
| ui::VKEY_F, true, false, false, false, |
| false, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 70 0 true false false false", |
| "U 70 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| static const KeyEventTestData kTestCtrlK = { |
| ui::VKEY_K, true, false, false, false, |
| false, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 75 0 true false false false", |
| "U 75 0 true false false false", |
| "U 17 0 true false false false" } |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); |
| ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello")); |
| // Move the caret to the beginning of the line. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA)); |
| // Forward one character |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); |
| // Delete to the end of the line. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK)); |
| EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H")); |
| } |
| #endif |
| |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, PageUpDownKeys) { |
| static const KeyEventTestData kTestPageUp = { |
| ui::VKEY_PRIOR, false, false, false, false, |
| false, false, false, false, 2, |
| { "D 33 0 false false false false", |
| "U 33 0 false false false false" } |
| }; |
| |
| static const KeyEventTestData kTestPageDown = { |
| ui::VKEY_NEXT, false, false, false, false, |
| false, false, false, false, 2, |
| { "D 34 0 false false false false", |
| "U 34 0 false false false false" } |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp)); |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown)); |
| EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"")); |
| } |
| |
| #if defined(OS_WIN) || defined(TOOLKIT_VIEWS) |
| IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) { |
| static const KeyEventTestData kTestAltKey = { |
| ui::VKEY_MENU, false, false, false, false, |
| false, false, false, false, 2, |
| { "D 18 0 false false true false", |
| "U 18 0 false false true false" } |
| }; |
| |
| static const KeyEventTestData kTestAltKeySuppress = { |
| ui::VKEY_MENU, false, false, false, false, |
| true, false, false, false, 2, |
| { "D 18 0 false false true false", |
| "U 18 0 false false true false" } |
| }; |
| |
| static const KeyEventTestData kTestCtrlAltKey = { |
| ui::VKEY_MENU, true, false, false, false, |
| false, false, false, false, 4, |
| { "D 17 0 true false false false", |
| "D 18 0 true false true false", |
| "U 18 0 true false true false", |
| "U 17 0 true false false false" } |
| }; |
| |
| ASSERT_TRUE(test_server()->Start()); |
| |
| ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); |
| GURL url = test_server()->GetURL(kTestingPage); |
| ui_test_utils::NavigateToURL(browser(), url); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| int tab_index = browser()->active_index(); |
| // Press and release Alt key to focus wrench menu button. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey)); |
| EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU)); |
| |
| ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Alt key can be suppressed. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| |
| // Ctrl+Alt should have no effect. |
| EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey)); |
| ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); |
| } |
| #endif |
| |
| } // namespace |