1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/accessibility/platform/browser_accessibility_win.h"
#include "base/memory/ptr_util.h"
#include "ui/accessibility/platform/browser_accessibility_manager.h"
#include "ui/accessibility/platform/browser_accessibility_manager_win.h"
#include "ui/base/win/atl_module.h"
namespace ui {
// static
std::unique_ptr<BrowserAccessibility> BrowserAccessibility::Create(
BrowserAccessibilityManager* manager,
AXNode* node) {
return base::WrapUnique(new BrowserAccessibilityWin(manager, node));
}
BrowserAccessibilityWin::BrowserAccessibilityWin(
BrowserAccessibilityManager* manager,
AXNode* node)
: BrowserAccessibility(manager, node) {
win::CreateATLModuleIfNeeded();
CComObject<BrowserAccessibilityComWin>* instance = nullptr;
HRESULT hr =
CComObject<BrowserAccessibilityComWin>::CreateInstance(&instance);
DCHECK(SUCCEEDED(hr));
instance->Init(*this);
instance->AddRef();
browser_accessibility_com_.reset(instance);
}
BrowserAccessibilityWin::~BrowserAccessibilityWin() = default;
void BrowserAccessibilityWin::UpdatePlatformAttributes() {
GetCOM()->UpdateStep1ComputeWinAttributes();
GetCOM()->UpdateStep2ComputeHypertext();
GetCOM()->UpdateStep3FireEvents();
}
std::wstring BrowserAccessibilityWin::ComputeListItemNameFromContent() const {
DCHECK_EQ(GetRole(), ax::mojom::Role::kListItem);
DCHECK(!HasStringAttribute(ax::mojom::StringAttribute::kName));
std::wstring str;
int offset = 0;
if (node()->GetFirstChild() &&
node()->GetFirstChild()->GetRole() == ax::mojom::Role::kListMarker) {
offset = 1;
}
auto start_position = AXNodePosition::CreatePosition(*node(), offset);
auto end_position = start_position->CreatePositionAtEndOfAnchor();
auto range = AXRange(std::move(start_position), std::move(end_position));
// TODO(accessibility): We're aware that there is an issue with no space being
// generated between descendants' names in some cases when appending their
// names. For instance if we have a <li> with a child <ul> which has <li> as
// children.
str = base::UTF16ToWide(
range.GetText(AXTextConcatenationBehavior::kWithoutParagraphBreaks,
AXEmbeddedObjectBehavior::kSuppressCharacter));
return str;
}
bool BrowserAccessibilityWin::CanFireEvents() const {
// On Windows, we want to hide the subtree of a collapsed <select> element but
// we still need to fire events on those hidden nodes.
if (!IsIgnored() && GetCollapsedMenuListSelectAncestor())
return true;
// If the node changed its ignored state this frame then some events should be
// allowed, such as hide/show/structure events. If a node with no siblings
// changes aria-hidden value, this would affect whether it would be considered
// a "child of leaf" node which affects BrowserAccessibility::CanFireEvents.
if (manager()->ToBrowserAccessibilityManagerWin()->IsIgnoredChangedNode(this))
return true;
return BrowserAccessibility::CanFireEvents();
}
AXPlatformNode* BrowserAccessibilityWin::GetAXPlatformNode() const {
return GetCOM();
}
void BrowserAccessibilityWin::OnLocationChanged() {
GetCOM()->FireNativeEvent(EVENT_OBJECT_LOCATIONCHANGE);
}
std::u16string BrowserAccessibilityWin::GetHypertext() const {
return GetCOM()->AXPlatformNodeWin::GetHypertext();
}
const std::vector<gfx::NativeViewAccessible>
BrowserAccessibilityWin::GetUIADirectChildrenInRange(
AXPlatformNodeDelegate* start,
AXPlatformNodeDelegate* end) {
std::vector<gfx::NativeViewAccessible> descendants;
if (!IsIgnored() && !ShouldHideChildrenForUIA() && PlatformChildCount() > 0) {
BrowserAccessibility* start_wrapper = FromAXPlatformNodeDelegate(start);
DCHECK(start_wrapper);
BrowserAccessibility* end_wrapper = FromAXPlatformNodeDelegate(end);
DCHECK(end_wrapper);
// When either (or both) of the start/end node is the same as the common
// anchor, make them null. A null start node means that all UIA embedded
// objects from the start will be added, and a null end node means that all
// UIA embedded objects past the start of the range will be included. When
// both are null, all UIA embedded objects will be included.
if (this == start_wrapper)
start_wrapper = nullptr;
if (this == end_wrapper)
end_wrapper = nullptr;
// Don't include nodes that are before the start node - they are not in the
// range. If the start node is the one we're on right now (ie. the common
// anchor is the start anchor), include all nodes from the start.
bool in_range = !start_wrapper;
for (auto it = PlatformChildrenBegin(); it != PlatformChildrenEnd(); ++it) {
BrowserAccessibility* child = it.get();
DCHECK(child);
if (!in_range &&
(start_wrapper &&
(child == start_wrapper || start_wrapper->IsDescendantOf(child)))) {
in_range = true;
}
// The only children that should be returned are the ones that are
// unignored UIA embedded objects.
if (in_range && IsUIAEmbeddedObject(child->GetRole())) {
descendants.emplace_back(child->GetNativeViewAccessible());
}
// Don't include the nodes that follow the end of the range.
if (end_wrapper &&
(child == end_wrapper || end_wrapper->IsDescendantOf(child))) {
break;
}
}
}
return descendants;
}
gfx::NativeViewAccessible BrowserAccessibilityWin::GetNativeViewAccessible() {
return GetCOM();
}
BrowserAccessibilityComWin* BrowserAccessibilityWin::GetCOM() const {
DCHECK(browser_accessibility_com_);
return static_cast<BrowserAccessibilityComWin*>(
browser_accessibility_com_.get());
}
BrowserAccessibilityWin* ToBrowserAccessibilityWin(BrowserAccessibility* obj) {
return static_cast<BrowserAccessibilityWin*>(obj);
}
const BrowserAccessibilityWin* ToBrowserAccessibilityWin(
const BrowserAccessibility* obj) {
return static_cast<const BrowserAccessibilityWin*>(obj);
}
TextAttributeList BrowserAccessibilityWin::ComputeTextAttributes() const {
return GetCOM()->AXPlatformNodeWin::ComputeTextAttributes();
}
bool BrowserAccessibilityWin::ShouldHideChildrenForUIA() const {
return GetCOM()->AXPlatformNodeWin::ShouldHideChildrenForUIA();
}
} // namespace ui
|