summaryrefslogtreecommitdiffstats
path: root/chrome/test
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-22 17:39:35 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-22 17:39:35 +0000
commit9201662e1c9ce2c9afae43c2e6c74c673f7aed17 (patch)
treecc73c6141a81f9202ef14e83605d1b2f614e7217 /chrome/test
parentc6cd2dbcec52a90b3a97e931a36757151f23b6ed (diff)
downloadchromium_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.cc99
-rw-r--r--chrome/test/automation/automation_messages_internal.h14
-rw-r--r--chrome/test/automation/window_proxy.cc31
-rw-r--r--chrome/test/automation/window_proxy.h8
-rw-r--r--chrome/test/test_browser_window.h1
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,