diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 18:36:03 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 18:36:03 +0000 |
commit | 84e8bdeaaf5c35c0e55dd9eca21422e7bfdc588f (patch) | |
tree | f6acb0420c94ea6a6990cedf68ef563bab0445a3 /chrome/test | |
parent | 55098791c5380e4cc3a9be4de11c1b5fa23c8140 (diff) | |
download | chromium_src-84e8bdeaaf5c35c0e55dd9eca21422e7bfdc588f.zip chromium_src-84e8bdeaaf5c35c0e55dd9eca21422e7bfdc588f.tar.gz chromium_src-84e8bdeaaf5c35c0e55dd9eca21422e7bfdc588f.tar.bz2 |
Keyboard accessibility for the page and app menus.
Works on Windows, and on Linux with toolkit_views.
The goal is to make Chrome behave more like a standard Windows
application, for users who rely on the keyboard and expect standard
keyboard accelerators to work.
Pressing F10, or pressing and releasing Alt, will set focus to the
Page menu, as if it was the first item in a menu bar.
Pressing enter, space, up arrow, or down arrow will open the focused menu.
Once a menu is opened, pressing left and right arrows will switch between
the two menus. Pressing escape will return focus to the title of the
previously open menu.
A new UI test attempts to select something from the menus using only the
keyboard. It works on Linux (with toolkit_views) and on Windows.
BUG=none
TEST=New keyboard accessibility interactive ui test.
Review URL: http://codereview.chromium.org/660323
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42498 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test')
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 19 | ||||
-rw-r--r-- | chrome/test/automation/browser_proxy.cc | 23 | ||||
-rw-r--r-- | chrome/test/automation/browser_proxy.h | 9 | ||||
-rw-r--r-- | chrome/test/automation/window_proxy.cc | 9 | ||||
-rw-r--r-- | chrome/test/automation/window_proxy.h | 4 | ||||
-rw-r--r-- | chrome/test/interactive_ui/interactive_ui_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/test/interactive_ui/keyboard_access_uitest.cc | 104 | ||||
-rw-r--r-- | chrome/test/test_browser_window.h | 1 |
8 files changed, 169 insertions, 1 deletions
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 7447020..0e82155 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -1288,4 +1288,23 @@ IPC_BEGIN_MESSAGES(Automation) int64 /* id */, bool /* success */) + // Block until the focused view id changes to something other than + // |previous_view_id|. + IPC_SYNC_MESSAGE_ROUTED2_2(AutomationMsg_WaitForFocusedViewIDToChange, + int /* window handle */, + int /* previous_view_id */, + bool /* success */, + int /* new_view_id */) + + // To avoid race conditions, waiting until a popup menu opens is a + // three-step process: + // 1. Call StartTrackingPopupMenus. + // 2. Call an automation method that results in opening the popup menu. + // 3. Call WaitForPopupMenuToOpen and check for success. + IPC_SYNC_MESSAGE_ROUTED1_1(AutomationMsg_StartTrackingPopupMenus, + int /* browser handle */, + bool /* success */) + IPC_SYNC_MESSAGE_ROUTED0_1(AutomationMsg_WaitForPopupMenuToOpen, + bool /* success */) + IPC_END_MESSAGES(Automation) diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc index 6db138e..f0825a0 100644 --- a/chrome/test/automation/browser_proxy.cc +++ b/chrome/test/automation/browser_proxy.cc @@ -91,7 +91,7 @@ bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const { *active_tab_index = active_tab_index_response; return true; } - + return false; } @@ -561,3 +561,24 @@ bool BrowserProxy::ShutdownSessionService() { return did_shutdown; } +bool BrowserProxy::StartTrackingPopupMenus() { + if (!is_valid()) + return false; + + bool result = false; + if (!sender_->Send(new AutomationMsg_StartTrackingPopupMenus + (0, handle_, &result))) + return false; + return result; +} + +bool BrowserProxy::WaitForPopupMenuToOpen() { + if (!is_valid()) + return false; + + bool result = false; + if (!sender_->Send(new AutomationMsg_WaitForPopupMenuToOpen + (0, &result))) + return false; + return result; +} diff --git a/chrome/test/automation/browser_proxy.h b/chrome/test/automation/browser_proxy.h index a21bfe6..509a630 100644 --- a/chrome/test/automation/browser_proxy.h +++ b/chrome/test/automation/browser_proxy.h @@ -217,6 +217,15 @@ class BrowserProxy : public AutomationResourceProxy { // on success. bool ShutdownSessionService() WARN_UNUSED_RESULT; + // To avoid race conditions, waiting until a popup menu opens is a + // three-step process: + // 1. Call StartTrackingPopupMenus. + // 2. Call an automation method that results in opening the popup menu. + // 3. Call WaitForPopupMenuToOpen and check for success. + // Both methods return true on success. + bool StartTrackingPopupMenus() WARN_UNUSED_RESULT; + bool WaitForPopupMenuToOpen() WARN_UNUSED_RESULT; + protected: virtual ~BrowserProxy() {} private: diff --git a/chrome/test/automation/window_proxy.cc b/chrome/test/automation/window_proxy.cc index 295f05b..c098abd 100644 --- a/chrome/test/automation/window_proxy.cc +++ b/chrome/test/automation/window_proxy.cc @@ -123,6 +123,15 @@ bool WindowProxy::GetFocusedViewID(int* view_id) { view_id)); } +bool WindowProxy::WaitForFocusedViewIDToChange( + int old_view_id, int* new_view_id) { + bool result = false; + if (!sender_->Send(new AutomationMsg_WaitForFocusedViewIDToChange + (0, handle_, old_view_id, &result, new_view_id))) + return false; + return result; +} + scoped_refptr<BrowserProxy> WindowProxy::GetBrowser() { return GetBrowserWithTimeout(base::kNoTimeout, NULL); } diff --git a/chrome/test/automation/window_proxy.h b/chrome/test/automation/window_proxy.h index 3c5deca..3f6fa8a 100644 --- a/chrome/test/automation/window_proxy.h +++ b/chrome/test/automation/window_proxy.h @@ -90,6 +90,10 @@ class WindowProxy : public AutomationResourceProxy { // was retrieved. bool GetFocusedViewID(int* view_id); + // Waits until the focused view ID changes to something other than + // |old_view_id|. Returns true if the focused view ID did change. + bool WaitForFocusedViewIDToChange(int old_view_id, int* new_view_id); + // Returns the browser this window corresponds to, or NULL if this window // is not a browser. The caller owns the returned BrowserProxy. scoped_refptr<BrowserProxy> GetBrowser(); diff --git a/chrome/test/interactive_ui/interactive_ui_tests.gypi b/chrome/test/interactive_ui/interactive_ui_tests.gypi index 1b993be..ebeb970 100644 --- a/chrome/test/interactive_ui/interactive_ui_tests.gypi +++ b/chrome/test/interactive_ui/interactive_ui_tests.gypi @@ -41,6 +41,7 @@ '<(DEPTH)/chrome/test/interactive_ui/npapi_interactive_test.cc', '<(DEPTH)/chrome/test/interactive_ui/view_event_test_base.cc', '<(DEPTH)/chrome/test/interactive_ui/view_event_test_base.h', + '<(DEPTH)/chrome/test/interactive_ui/keyboard_access_uitest.cc', # TODO(jcampan): we should use in_proc_test_runner on Windows. '<(DEPTH)/chrome/test/test_launcher/out_of_proc_test_runner.cc', '<(DEPTH)/chrome/test/test_launcher/test_runner.cc', diff --git a/chrome/test/interactive_ui/keyboard_access_uitest.cc b/chrome/test/interactive_ui/keyboard_access_uitest.cc new file mode 100644 index 0000000..f5c339e --- /dev/null +++ b/chrome/test/interactive_ui/keyboard_access_uitest.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2010 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 "base/keyboard_codes.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "googleurl/src/gurl.h" + +// This functionality currently works on Windows and on Linux when +// toolkit_views is defined (i.e. for Chrome OS). It's not needed +// on the Mac, and it's not yet implemented on Linux. +#if defined(TOOLKIT_VIEWS) + +namespace { + +class KeyboardAccessTest : public UITest { + public: + KeyboardAccessTest() { + dom_automation_enabled_ = true; + show_window_ = true; + } + + // Use the keyboard to select "New Tab" from the app menu. + // This test depends on the fact that there are two menus and that + // New Tab is the first item in the app menu. If the menus change, + // this test will need to be changed to reflect that. + // + // If alternate_key_sequence is true, use "Alt" instead of "F10" to + // open the menu bar, and "Down" instead of "Enter" to open a menu. + void TestMenuKeyboardAccess(bool alternate_key_sequence); + + DISALLOW_COPY_AND_ASSIGN(KeyboardAccessTest); +}; + +void KeyboardAccessTest::TestMenuKeyboardAccess(bool alternate_key_sequence) { + scoped_refptr<BrowserProxy> browser = automation()->GetBrowserWindow(0); + ASSERT_TRUE(browser.get()); + scoped_refptr<WindowProxy> window = browser->GetWindow(); + ASSERT_TRUE(window.get()); + + // Navigate to a page in the first tab, which makes sure that focus is + // set to the browser window. + scoped_refptr<TabProxy> tab(GetActiveTab()); + ASSERT_TRUE(tab.get()); + + ASSERT_TRUE(tab->NavigateToURL(GURL("about:"))); + + // The initial tab index should be 0. + int tab_index = -1; + ASSERT_TRUE(browser->GetActiveTabIndex(&tab_index)); + ASSERT_EQ(0, tab_index); + + // Get the focused view ID, then press a key to activate the + // page menu, then wait until the focused view changes. + int original_view_id = -1; + ASSERT_TRUE(window->GetFocusedViewID(&original_view_id)); + + if (alternate_key_sequence) + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_MENU, 0)); + else + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_F10, 0)); + + int new_view_id = -1; + ASSERT_TRUE(window->WaitForFocusedViewIDToChange( + original_view_id, &new_view_id)); + + ASSERT_TRUE(browser->StartTrackingPopupMenus()); + + // Press RIGHT to focus the app menu, then RETURN or DOWN to open it. + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_RIGHT, 0)); + if (alternate_key_sequence) + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_DOWN, 0)); + else + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_RETURN, 0)); + + // Wait until the popup menu actually opens. + ASSERT_TRUE(browser->WaitForPopupMenuToOpen()); + + // Press DOWN to select the first item, then RETURN to select it. + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_DOWN, 0)); + ASSERT_TRUE(window->SimulateOSKeyPress(base::VKEY_RETURN, 0)); + + // Wait for the new tab to appear. + ASSERT_TRUE(browser->WaitForTabCountToBecome(2, sleep_timeout_ms())); + + // Make sure that the new tab index is 1. + ASSERT_TRUE(browser->GetActiveTabIndex(&tab_index)); + ASSERT_EQ(1, tab_index); +} + +TEST_F(KeyboardAccessTest, TestMenuKeyboardAccess) { + TestMenuKeyboardAccess(false); +} + +TEST_F(KeyboardAccessTest, TestAltMenuKeyboardAccess) { + TestMenuKeyboardAccess(true); +} + +} // namespace + +#endif // defined(TOOLKIT_VIEWS) diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index c53c563..c81ff1c 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -48,6 +48,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void UpdateToolbar(TabContents* contents, bool should_restore_state) {} virtual void FocusToolbar() {} + virtual void FocusPageAndAppMenus() {} virtual void ShowPageMenu() {} virtual void ShowAppMenu() {} virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, |