diff options
author | ctguil@chromium.org <ctguil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-03 17:33:14 +0000 |
---|---|---|
committer | ctguil@chromium.org <ctguil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-03 17:33:14 +0000 |
commit | b953062aec66a8c20fbbc50396c23fac2696ef1d (patch) | |
tree | d207c629950ce4daaa3e174f4f31486dd9522c73 /chrome/browser/accessibility_win_browsertest.cc | |
parent | 9deebf20b712a0b1701a3d508a4a85528e05486e (diff) | |
download | chromium_src-b953062aec66a8c20fbbc50396c23fac2696ef1d.zip chromium_src-b953062aec66a8c20fbbc50396c23fac2696ef1d.tar.gz chromium_src-b953062aec66a8c20fbbc50396c23fac2696ef1d.tar.bz2 |
Add browser test to verify that MSAA clients can correctly retrieve accessibility tree from renderer.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/1806001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46238 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/accessibility_win_browsertest.cc')
-rw-r--r-- | chrome/browser/accessibility_win_browsertest.cc | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/chrome/browser/accessibility_win_browsertest.cc b/chrome/browser/accessibility_win_browsertest.cc new file mode 100644 index 0000000..1fc03a1 --- /dev/null +++ b/chrome/browser/accessibility_win_browsertest.cc @@ -0,0 +1,222 @@ +// 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 <atlbase.h> +#include <vector> + +#include "base/file_path.h" +#include "base/scoped_comptr_win.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/renderer_host/render_widget_host_view_win.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" + +namespace { + +class AccessibilityWinBrowserTest : public InProcessBrowserTest { + public: + void SetUpCommandLine(CommandLine* command_line) { + // Turns on the accessibility in the renderer. Off by default until + // http://b/issue?id=1432077 is fixed. + command_line->AppendSwitch(switches::kEnableRendererAccessibility); + } + + protected: + IAccessible* GetRenderWidgetHostViewClientAccessible(); +}; + +class AccessibleChecker { + public: + AccessibleChecker(std::wstring expected_name, int32 expected_role); + + // Append an AccessibleChecker that verifies accessibility information for + // a child IAccessible. Order is important. + void AppendExpectedChild(AccessibleChecker* expected_child); + + // Check that the name and role of the given IAccessible instance and its + // descendants match the expected names and roles that this object was + // initialized with. + void CheckAccessible(IAccessible* accessible); + + typedef std::vector<AccessibleChecker*> AccessibleCheckerVector; + + private: + void CheckAccessibleName(IAccessible* accessible); + void CheckAccessibleRole(IAccessible* accessible); + void CheckAccessibleChildren(IAccessible* accessible); + + private: + // Expected accessible name. Checked against IAccessible::get_accName. + std::wstring name_; + + // Expected accessible role. Checked against IAccessible::get_accRole. + int32 role_; + + // Expected accessible children. Checked using IAccessible::get_accChildCount + // and ::AccessibleChildren. + AccessibleCheckerVector children_; +}; + +VARIANT CreateI4Variant(LONG value) { + VARIANT variant = {0}; + + V_VT(&variant) = VT_I4; + V_I4(&variant) = value; + + return variant; +} + +IAccessible* GetAccessibleFromResultVariant(IAccessible* parent, VARIANT *var) { + switch (V_VT(var)) { + case VT_DISPATCH: + return CComQIPtr<IAccessible>(V_DISPATCH(var)).Detach(); + break; + + case VT_I4: { + CComPtr<IDispatch> dispatch; + HRESULT hr = parent->get_accChild(CreateI4Variant(V_I4(var)), &dispatch); + EXPECT_EQ(hr, S_OK); + return CComQIPtr<IAccessible>(dispatch).Detach(); + break; + } + } + + return NULL; +} + +// Retrieve the MSAA client accessibility object for the Render Widget Host View +// of the selected tab. +IAccessible* +AccessibilityWinBrowserTest::GetRenderWidgetHostViewClientAccessible() { + HWND hwnd_render_widget_host_view = + browser()->GetSelectedTabContents()->GetRenderWidgetHostView()-> + GetNativeView(); + + IAccessible* accessible; + HRESULT hr = AccessibleObjectFromWindow( + hwnd_render_widget_host_view, OBJID_CLIENT, + IID_IAccessible, reinterpret_cast<void**>(&accessible)); + EXPECT_EQ(S_OK, hr); + EXPECT_NE(accessible, reinterpret_cast<IAccessible*>(NULL)); + + return accessible; +} + +AccessibleChecker::AccessibleChecker( + std::wstring expected_name, int32 expected_role) : + name_(expected_name), + role_(expected_role) { +} + +void AccessibleChecker::AppendExpectedChild( + AccessibleChecker* expected_child) { + children_.push_back(expected_child); +} + +void AccessibleChecker::CheckAccessible(IAccessible* accessible) { + CheckAccessibleName(accessible); + CheckAccessibleRole(accessible); + CheckAccessibleChildren(accessible); +} + +void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { + CComBSTR name; + HRESULT hr = + accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); + + if (name_.empty()) { + // If the object doesn't have name S_FALSE should be returned. + EXPECT_EQ(hr, S_FALSE); + } else { + // Test that the correct string was returned. + EXPECT_EQ(hr, S_OK); + EXPECT_EQ(CompareString(LOCALE_NEUTRAL, 0, name, SysStringLen(name), + name_.c_str(), name_.length()), + CSTR_EQUAL); + } +} + +void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { + VARIANT var_role = {0}; + HRESULT hr = + accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role); + EXPECT_EQ(hr, S_OK); + EXPECT_EQ(V_VT(&var_role), VT_I4); + EXPECT_EQ(V_I4(&var_role), role_); +} + +void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { + LONG child_count = 0; + HRESULT hr = parent->get_accChildCount(&child_count); + EXPECT_EQ(hr, S_OK); + ASSERT_EQ(child_count, children_.size()); + + std::auto_ptr<VARIANT> child_array(new VARIANT[child_count]); + LONG obtained_count = 0; + hr = AccessibleChildren(parent, 0, child_count, + child_array.get(), &obtained_count); + ASSERT_EQ(hr, S_OK); + ASSERT_EQ(child_count, obtained_count); + + VARIANT* child = child_array.get(); + for (AccessibleCheckerVector::iterator child_checker = children_.begin(); + child_checker != children_.end(); + ++child_checker, ++child) { + ScopedComPtr<IAccessible> child_accessible; + child_accessible.Attach(GetAccessibleFromResultVariant(parent, child)); + (*child_checker)->CheckAccessible(child_accessible); + } +} + +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, + TestRendererAccessibilityTree) { + GURL tree_url( + "data:text/html,<html><head><title>Accessibility Win Test</title></head>" + "<body><input type='button' value='push' /><input type='checkbox' />" + "</body></html>"); + ui_test_utils::NavigateToURL(browser(), tree_url); + + ScopedComPtr<IAccessible> document_accessible( + GetRenderWidgetHostViewClientAccessible()); + + AccessibleChecker button_checker(L"push", ROLE_SYSTEM_PUSHBUTTON); + AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON); + + AccessibleChecker grouping_checker(L"", ROLE_SYSTEM_GROUPING); + grouping_checker.AppendExpectedChild(&button_checker); + grouping_checker.AppendExpectedChild(&checkbox_checker); + + AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT); + document_checker.AppendExpectedChild(&grouping_checker); + + // Check the accessible tree of the renderer. + document_checker.CheckAccessible(document_accessible); + + // Check that document accessible has a parent accessible. + ScopedComPtr<IDispatch> parent_dispatch; + HRESULT hr = document_accessible->get_accParent(parent_dispatch.Receive()); + EXPECT_EQ(hr, S_OK); + EXPECT_NE(parent_dispatch, reinterpret_cast<IDispatch*>(NULL)); + + // Navigate to another page. + GURL about_url("about:"); + ui_test_utils::NavigateToURL(browser(), about_url); + + // Verify that the IAccessible reference still points to a valid object and + // that it calls to its methods fail since the tree is no longer valid after + // the page navagation. + // Todo(ctguil): Currently this is giving a false positive because E_FAIL is + // returned when BrowserAccessibilityManager::RequestAccessibilityInfo fails + // since the previous render view host connection is lost. Verify that + // instances are actually marked as invalid once the browse side cache is + // checked in. + CComBSTR name; + hr = document_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); + ASSERT_EQ(E_FAIL, hr); +} +} // namespace. + |