Commit 756820dd authored by Kevin Babbitt's avatar Kevin Babbitt Committed by Commit Bot

Ensure UI Automation GetFocus reaches focused node in web content

AXPlatformNodeDelegate::GetFocus() returns the node within the called
node's subtree that currently has focus. When an element in web content
has focus, and a delegate in Views is asked for focus, that delegate can
only reach as far as the web content root. Calling GetFocus() again on
the web content root ensures that the platform API returns the currently
focused node.

Bug: 928811
Change-Id: Ice47eed0a8ea4281beb48624942ac2428fb1950f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2099162Reviewed-by: default avatarIan Prest <iapres@microsoft.com>
Commit-Queue: Kevin Babbitt <kbabbitt@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#749386}
parent c129b43c
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "third_party/isimpledom/ISimpleDOMNode.h" #include "third_party/isimpledom/ISimpleDOMNode.h"
#include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/ax_event_generator.h" #include "ui/accessibility/ax_event_generator.h"
#include "ui/accessibility/platform/ax_fragment_root_win.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
...@@ -4265,6 +4266,44 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinUIABrowserTest, ...@@ -4265,6 +4266,44 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinUIABrowserTest,
EXPECT_EQ(window_text_str16, name_str16); EXPECT_EQ(window_text_str16, name_str16);
} }
IN_PROC_BROWSER_TEST_F(AccessibilityWinUIABrowserTest,
GetFocusFromRootReachesWebContent) {
LoadInitialAccessibilityTreeFromHtml(
R"HTML(<!DOCTYPE html>
<html>
<button>Focus target</button>
<script>
document.querySelector('button').focus();
</script>
</html>)HTML");
// Obtain the fragment root from the top-level HWND.
HWND hwnd = shell()->window()->GetHost()->GetAcceleratedWidget();
ASSERT_NE(gfx::kNullAcceleratedWidget, hwnd);
ui::AXFragmentRootWin* fragment_root =
ui::AXFragmentRootWin::GetForAcceleratedWidget(hwnd);
ASSERT_NE(nullptr, fragment_root);
Microsoft::WRL::ComPtr<IRawElementProviderFragmentRoot> uia_fragment_root;
ASSERT_HRESULT_SUCCEEDED(
fragment_root->GetNativeViewAccessible()->QueryInterface(
IID_PPV_ARGS(&uia_fragment_root)));
// Verify that calling GetFocus on the fragment root reaches web content.
Microsoft::WRL::ComPtr<IRawElementProviderFragment> focused_fragment;
ASSERT_HRESULT_SUCCEEDED(uia_fragment_root->GetFocus(&focused_fragment));
Microsoft::WRL::ComPtr<IRawElementProviderSimple> focused_element;
ASSERT_HRESULT_SUCCEEDED(focused_fragment.As(&focused_element));
base::win::ScopedVariant name_property;
ASSERT_HRESULT_SUCCEEDED(focused_element->GetPropertyValue(
UIA_NamePropertyId, name_property.Receive()));
ASSERT_EQ(name_property.type(), VT_BSTR);
BSTR name_bstr = name_property.ptr()->bstrVal;
base::string16 actual_name(name_bstr, ::SysStringLen(name_bstr));
EXPECT_EQ(L"Focus target", actual_name);
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinUIABrowserTest, IN_PROC_BROWSER_TEST_F(AccessibilityWinUIABrowserTest,
LegacyWindowIsNotControlElement) { LegacyWindowIsNotControlElement) {
LoadInitialAccessibilityTreeFromHtml( LoadInitialAccessibilityTreeFromHtml(
......
...@@ -129,10 +129,26 @@ class AXFragmentRootPlatformNodeWin : public AXPlatformNodeWin, ...@@ -129,10 +129,26 @@ class AXFragmentRootPlatformNodeWin : public AXPlatformNodeWin,
*focus = nullptr; *focus = nullptr;
gfx::NativeViewAccessible focused_element = GetDelegate()->GetFocus(); gfx::NativeViewAccessible focused_element = nullptr;
if (focused_element != nullptr) {
// GetFocus() can return a node at the root of a subtree, for example when
// transitioning from Views into web content. In such cases we want to
// continue drilling to retrieve the actual focused element.
AXPlatformNode* node_to_test = this;
do {
gfx::NativeViewAccessible test_result =
node_to_test->GetDelegate()->GetFocus();
if (test_result != nullptr && test_result != focused_element) {
focused_element = test_result;
node_to_test =
AXPlatformNode::FromNativeViewAccessible(focused_element);
} else {
node_to_test = nullptr;
}
} while (node_to_test);
if (focused_element)
focused_element->QueryInterface(IID_PPV_ARGS(focus)); focused_element->QueryInterface(IID_PPV_ARGS(focus));
}
return S_OK; return S_OK;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment