blob: 72878a880a7159b41ba7e570c8b153ddf9c9ec55 [file] [log] [blame]
// Copyright 2019 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 "ui/accessibility/platform/ax_platform_node_win.h"
#include "base/win/scoped_variant.h"
#include "content/browser/accessibility/accessibility_content_browsertest.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_com_win.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
using Microsoft::WRL::ComPtr;
namespace content {
class AXPlatformNodeWinBrowserTest : public AccessibilityContentBrowserTest {
protected:
template <typename T>
ComPtr<T> QueryInterfaceFromNode(
BrowserAccessibility* browser_accessibility) {
ComPtr<T> result;
EXPECT_HRESULT_SUCCEEDED(
browser_accessibility->GetNativeViewAccessible()->QueryInterface(
__uuidof(T), &result));
return result;
}
ComPtr<IAccessible> IAccessibleFromNode(
BrowserAccessibility* browser_accessibility) {
return QueryInterfaceFromNode<IAccessible>(browser_accessibility);
}
ComPtr<IAccessible2> ToIAccessible2(ComPtr<IAccessible> accessible) {
CHECK(accessible);
ComPtr<IServiceProvider> service_provider;
accessible.As(&service_provider);
ComPtr<IAccessible2> result;
CHECK(SUCCEEDED(service_provider->QueryService(IID_IAccessible2,
IID_PPV_ARGS(&result))));
return result;
}
void UIAGetPropertyValueFlowsFromBrowserTestTemplate(
const BrowserAccessibility* target_browser_accessibility,
const std::vector<std::string>& expected_names) {
ASSERT_NE(nullptr, target_browser_accessibility);
auto* target_browser_accessibility_com_win =
ToBrowserAccessibilityWin(target_browser_accessibility)->GetCOM();
ASSERT_NE(nullptr, target_browser_accessibility_com_win);
base::win::ScopedVariant flows_from_variant;
target_browser_accessibility_com_win->GetPropertyValue(
UIA_FlowsFromPropertyId, flows_from_variant.Receive());
ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, flows_from_variant.type());
ASSERT_EQ(1u, SafeArrayGetDim(V_ARRAY(flows_from_variant.ptr())));
LONG lower_bound, upper_bound, size;
ASSERT_HRESULT_SUCCEEDED(
SafeArrayGetLBound(V_ARRAY(flows_from_variant.ptr()), 1, &lower_bound));
ASSERT_HRESULT_SUCCEEDED(
SafeArrayGetUBound(V_ARRAY(flows_from_variant.ptr()), 1, &upper_bound));
size = upper_bound - lower_bound + 1;
ASSERT_EQ(static_cast<LONG>(expected_names.size()), size);
std::vector<std::string> names;
for (LONG i = 0; i < size; ++i) {
CComPtr<IUnknown> unknown_element = nullptr;
ASSERT_HRESULT_SUCCEEDED(SafeArrayGetElement(
V_ARRAY(flows_from_variant.ptr()), &i, &unknown_element));
ASSERT_NE(nullptr, unknown_element);
CComPtr<IRawElementProviderSimple> raw_element_provider_simple = nullptr;
ASSERT_HRESULT_SUCCEEDED(
unknown_element->QueryInterface(&raw_element_provider_simple));
ASSERT_NE(nullptr, raw_element_provider_simple);
base::win::ScopedVariant name;
ASSERT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPropertyValue(
UIA_NamePropertyId, name.Receive()));
ASSERT_EQ(VT_BSTR, name.type());
names.push_back(base::UTF16ToUTF8(
std::wstring(V_BSTR(name.ptr()), SysStringLen(V_BSTR(name.ptr())))));
}
ASSERT_THAT(names, testing::UnorderedElementsAreArray(expected_names));
}
void UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role expected_role,
content::BrowserAccessibility* (content::BrowserAccessibility::*f)(
uint32_t) const,
uint32_t index_arg,
bool expected_is_modal,
bool expected_is_window_provider_available) {
BrowserAccessibility* root_browser_accessibility =
GetRootAndAssertNonNull();
BrowserAccessibilityComWin* root_browser_accessibility_com_win =
ToBrowserAccessibilityWin(root_browser_accessibility)->GetCOM();
ASSERT_NE(nullptr, root_browser_accessibility_com_win);
BrowserAccessibility* browser_accessibility =
(root_browser_accessibility->*f)(index_arg);
ASSERT_NE(nullptr, browser_accessibility);
ASSERT_EQ(expected_role, browser_accessibility->GetRole());
BrowserAccessibilityComWin* browser_accessibility_com_win =
ToBrowserAccessibilityWin(browser_accessibility)->GetCOM();
ASSERT_NE(nullptr, browser_accessibility_com_win);
ComPtr<IWindowProvider> window_provider = nullptr;
ASSERT_HRESULT_SUCCEEDED(browser_accessibility_com_win->GetPatternProvider(
UIA_WindowPatternId, &window_provider));
if (expected_is_window_provider_available) {
ASSERT_NE(nullptr, window_provider.Get());
BOOL is_modal = FALSE;
ASSERT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
ASSERT_EQ(expected_is_modal, is_modal);
} else {
ASSERT_EQ(nullptr, window_provider.Get());
}
}
};
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
IA2ScrollToPointIframeText) {
LoadInitialAccessibilityTreeFromHtmlFilePath(
"/accessibility/scrolling/iframe-text.html");
WaitForAccessibilityTreeToContainNodeWithName(
shell()->web_contents(),
"Game theory is \"the study of Mathematical model mathematical models of "
"conflict and cooperation between intelligent rational decision-makers."
"\"");
BrowserAccessibility* browser_accessibility =
GetRootAndAssertNonNull()->PlatformDeepestLastChild();
ASSERT_NE(nullptr, browser_accessibility);
ASSERT_EQ(ax::mojom::Role::kStaticText, browser_accessibility->GetRole());
BrowserAccessibility* iframe_browser_accessibility =
browser_accessibility->manager()->GetRoot();
ASSERT_NE(nullptr, iframe_browser_accessibility);
ASSERT_EQ(ax::mojom::Role::kRootWebArea,
iframe_browser_accessibility->GetRole());
gfx::Rect iframe_screen_bounds = iframe_browser_accessibility->GetBoundsRect(
ui::AXCoordinateSystem::kScreen, ui::AXClippingBehavior::kUnclipped);
AccessibilityNotificationWaiter location_changed_waiter(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kLocationChanged);
ComPtr<IAccessible2> root_iaccessible2 =
ToIAccessible2(IAccessibleFromNode(browser_accessibility));
ASSERT_EQ(S_OK, root_iaccessible2->scrollToPoint(
IA2_COORDTYPE_SCREEN_RELATIVE, iframe_screen_bounds.x(),
iframe_screen_bounds.y()));
location_changed_waiter.WaitForNotification();
gfx::Rect bounds = browser_accessibility->GetBoundsRect(
ui::AXCoordinateSystem::kScreen, ui::AXClippingBehavior::kUnclipped);
ASSERT_EQ(iframe_screen_bounds.y(), bounds.y());
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAGetPropertyValueFlowsFromNone) {
LoadInitialAccessibilityTreeFromHtmlFilePath(
"/accessibility/aria/aria-label.html");
base::win::ScopedVariant flows_from_variant;
ComPtr<IRawElementProviderSimple> node_provider =
QueryInterfaceFromNode<IRawElementProviderSimple>(
FindNode(ax::mojom::Role::kCheckBox, "aria label"));
node_provider->GetPropertyValue(UIA_FlowsFromPropertyId,
flows_from_variant.Receive());
ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, flows_from_variant.type());
ASSERT_EQ(nullptr, V_ARRAY(flows_from_variant.ptr()));
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAGetPropertyValueFlowsFromSingle) {
LoadInitialAccessibilityTreeFromHtmlFilePath(
"/accessibility/aria/aria-flowto.html");
UIAGetPropertyValueFlowsFromBrowserTestTemplate(
FindNode(ax::mojom::Role::kFooter, "next"), {"current"});
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAGetPropertyValueFlowsFromMultiple) {
LoadInitialAccessibilityTreeFromHtmlFilePath(
"/accessibility/aria/aria-flowto-multiple.html");
UIAGetPropertyValueFlowsFromBrowserTestTemplate(
FindNode(ax::mojom::Role::kGenericContainer, "b3"), {"a3", "c3"});
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDialog) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<dialog open>Example Text</dialog>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDialogAriaModalFalse) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<dialog open aria-modal="false">Example Text</dialog>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDialogAriaModalTrue) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<dialog open aria-modal="true">Example Text</dialog>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
true, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDiv) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div>Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kGenericContainer,
&BrowserAccessibility::PlatformGetChild, 0, false, false);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivAriaModalFalse) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div aria-modal="false">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kGenericContainer,
&BrowserAccessibility::PlatformGetChild, 0, false, false);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivAriaModalTrue) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div aria-modal="true">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kGenericContainer,
&BrowserAccessibility::PlatformGetChild, 0, false, false);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivDialog) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="dialog">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivDialogAriaModalFalse) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="dialog" aria-modal="false">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivDialogAriaModalTrue) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="dialog" aria-modal="true">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
true, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivAlertDialog) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="alertdialog">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(
AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivAlertDialogAriaModalFalse) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="alertdialog" aria-modal="false">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
false, true);
}
IN_PROC_BROWSER_TEST_F(
AXPlatformNodeWinBrowserTest,
UIAIWindowProviderGetIsModalOnDivAlertDialogAriaModalTrue) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
<body>
<div role="alertdialog" aria-modal="true">Example Text</div>
</body>
</html>
)HTML"));
UIAIWindowProviderGetIsModalBrowserTestTemplate(
ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
true, true);
}
IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
UIAGetPropertyValueAutomationId) {
LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
<!DOCTYPE html>
<html>
</body>
<div id="id"></div>
</body>
</html>
)HTML"));
BrowserAccessibility* root_browser_accessibility = GetRootAndAssertNonNull();
BrowserAccessibilityComWin* root_browser_accessibility_com_win =
ToBrowserAccessibilityWin(root_browser_accessibility)->GetCOM();
ASSERT_NE(nullptr, root_browser_accessibility_com_win);
BrowserAccessibility* browser_accessibility =
root_browser_accessibility->PlatformDeepestLastChild();
ASSERT_NE(nullptr, browser_accessibility);
ASSERT_EQ(ax::mojom::Role::kGenericContainer,
browser_accessibility->GetRole());
BrowserAccessibilityComWin* browser_accessibility_com_win =
ToBrowserAccessibilityWin(browser_accessibility)->GetCOM();
ASSERT_NE(nullptr, browser_accessibility_com_win);
base::win::ScopedVariant expected_scoped_variant;
expected_scoped_variant.Set(SysAllocString(L"id"));
base::win::ScopedVariant scoped_variant;
EXPECT_HRESULT_SUCCEEDED(browser_accessibility_com_win->GetPropertyValue(
UIA_AutomationIdPropertyId, scoped_variant.Receive()));
EXPECT_EQ(0, expected_scoped_variant.Compare(scoped_variant));
}
} // namespace content