File: browser_accessibility_win.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (176 lines) | stat: -rw-r--r-- 6,407 bytes parent folder | download | duplicates (2)
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