diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 17:39:35 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 17:39:35 +0000 |
commit | 9201662e1c9ce2c9afae43c2e6c74c673f7aed17 (patch) | |
tree | cc73c6141a81f9202ef14e83605d1b2f614e7217 /chrome/test | |
parent | c6cd2dbcec52a90b3a97e931a36757151f23b6ed (diff) | |
download | chromium_src-9201662e1c9ce2c9afae43c2e6c74c673f7aed17.zip chromium_src-9201662e1c9ce2c9afae43c2e6c74c673f7aed17.tar.gz chromium_src-9201662e1c9ce2c9afae43c2e6c74c673f7aed17.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 ui test.
Review URL: http://codereview.chromium.org/660323
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42234 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test')
-rw-r--r-- | chrome/test/automated_ui_tests/keyboard_access_uitest.cc | 99 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 14 | ||||
-rw-r--r-- | chrome/test/automation/window_proxy.cc | 31 | ||||
-rw-r--r-- | chrome/test/automation/window_proxy.h | 8 | ||||
-rw-r--r-- | chrome/test/test_browser_window.h | 1 |
5 files changed, 153 insertions, 0 deletions
diff --git a/chrome/test/automated_ui_tests/keyboard_access_uitest.cc b/chrome/test/automated_ui_tests/keyboard_access_uitest.cc new file mode 100644 index 0000000..fd7cdda --- /dev/null +++ b/chrome/test/automated_ui_tests/keyboard_access_uitest.cc @@ -0,0 +1,99 @@ +// 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/automated_ui_tests/automated_ui_test_base.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/window_proxy.h" +#include "googleurl/src/gurl.h" + +// Menu keyboard access 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 AutomatedUITestBase { + 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); + scoped_refptr<WindowProxy> window = browser->GetWindow(); + + // 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)); + + // 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(window->WaitForPopupMenuOpen(sleep_timeout_ms())); + + // 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/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 7447020..b73ef4b 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -348,6 +348,14 @@ IPC_BEGIN_MESSAGES(Automation) int /* view_handle */, int /* focused_view_id */) + // 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 */) + // This message shows/hides the window. IPC_SYNC_MESSAGE_ROUTED2_1(AutomationMsg_SetWindowVisible, int /* view_handle */, @@ -1288,4 +1296,10 @@ IPC_BEGIN_MESSAGES(Automation) int64 /* id */, bool /* success */) + // Determine if a pop-up menu is open. + IPC_SYNC_MESSAGE_ROUTED1_2(AutomationMsg_IsPopUpMenuOpen, + int /* window handle */, + bool /* success */, + bool /* is_open */) + IPC_END_MESSAGES(Automation) diff --git a/chrome/test/automation/window_proxy.cc b/chrome/test/automation/window_proxy.cc index 295f05b..5f18f6b 100644 --- a/chrome/test/automation/window_proxy.cc +++ b/chrome/test/automation/window_proxy.cc @@ -8,6 +8,7 @@ #include <algorithm> #include "base/logging.h" +#include "base/time.h" #include "chrome/test/automation/automation_constants.h" #include "chrome/test/automation/automation_messages.h" #include "chrome/test/automation/automation_proxy.h" @@ -16,6 +17,9 @@ #include "gfx/rect.h" #include "googleurl/src/gurl.h" +using base::TimeDelta; +using base::TimeTicks; + bool WindowProxy::SimulateOSClick(const gfx::Point& click, int flags) { if (!is_valid()) return false; @@ -123,6 +127,14 @@ bool WindowProxy::GetFocusedViewID(int* view_id) { view_id)); } +bool WindowProxy::WaitForFocusedViewIDToChange( + int old_view_id, int* new_view_id) { + bool result = false; + sender_->Send(new AutomationMsg_WaitForFocusedViewIDToChange + (0, handle_, old_view_id, &result, new_view_id)); + return result; +} + scoped_refptr<BrowserProxy> WindowProxy::GetBrowser() { return GetBrowserWithTimeout(base::kNoTimeout, NULL); } @@ -163,3 +175,22 @@ bool WindowProxy::IsMaximized(bool* maximized) { &result)); return result; } + +bool WindowProxy::WaitForPopupMenuOpen(uint32 timeout_ms) { + const TimeTicks start = TimeTicks::Now(); + const TimeDelta timeout = TimeDelta::FromMilliseconds(timeout_ms); + while (TimeTicks::Now() - start < timeout) { + PlatformThread::Sleep(automation::kSleepTime); + + bool is_open = false; + bool success = false; + if (!sender_->Send(new AutomationMsg_IsPopUpMenuOpen( + 0, handle_, &success, &is_open))) + return false; + if (!success) + return false; + if (is_open) + return true; + } + return false; +} diff --git a/chrome/test/automation/window_proxy.h b/chrome/test/automation/window_proxy.h index 3c5deca..be7ed64 100644 --- a/chrome/test/automation/window_proxy.h +++ b/chrome/test/automation/window_proxy.h @@ -90,6 +90,14 @@ 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); + + // Waits until a pop-up menu is opened. Returns true on success, or false + // if a pop-up menu is not opened within the timeout period. + bool WaitForPopupMenuOpen(uint32 timeout_ms); + // 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/test_browser_window.h b/chrome/test/test_browser_window.h index 169afdb..1390dd8 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, |