1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWebEngine module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
41 // Use of this source code is governed by a BSD-style license that can be
42 // found in the LICENSE.Chromium file.
43 
44 #include "browser_accessibility_qt.h"
45 
46 #if QT_CONFIG(accessibility)
47 
48 #include "ui/accessibility/ax_enums.mojom.h"
49 
50 #include "browser_accessibility_manager_qt.h"
51 #include "qtwebenginecoreglobal_p.h"
52 #include "type_conversion.h"
53 
54 using namespace blink;
55 using QtWebEngineCore::toQt;
56 
57 namespace content {
58 
ToBrowserAccessibilityQt(const BrowserAccessibility * obj)59 const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibility *obj)
60 {
61     return static_cast<const BrowserAccessibilityQt *>(obj);
62 }
63 
toQAccessibleInterface(BrowserAccessibility * obj)64 QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj)
65 {
66     return static_cast<BrowserAccessibilityQt *>(obj);
67 }
68 
BrowserAccessibilityQt()69 BrowserAccessibilityQt::BrowserAccessibilityQt()
70 {
71     QAccessible::registerAccessibleInterface(this);
72 }
73 
isValid() const74 bool BrowserAccessibilityQt::isValid() const
75 {
76     auto managerQt = static_cast<BrowserAccessibilityManagerQt *>(manager_);
77     return managerQt && managerQt->isValid();
78 }
79 
object() const80 QObject *BrowserAccessibilityQt::object() const
81 {
82     return 0;
83 }
84 
childAt(int x,int y) const85 QAccessibleInterface *BrowserAccessibilityQt::childAt(int x, int y) const
86 {
87     for (int i = 0; i < childCount(); ++i) {
88         QAccessibleInterface *childIface = child(i);
89         Q_ASSERT(childIface);
90         if (childIface->rect().contains(x,y))
91             return childIface;
92     }
93     return 0;
94 }
95 
interface_cast(QAccessible::InterfaceType type)96 void *BrowserAccessibilityQt::interface_cast(QAccessible::InterfaceType type)
97 {
98     switch (type) {
99     case QAccessible::ActionInterface:
100         if (!actionNames().isEmpty())
101             return static_cast<QAccessibleActionInterface*>(this);
102         break;
103     case QAccessible::TextInterface:
104         if (HasState(ax::mojom::State::kEditable))
105             return static_cast<QAccessibleTextInterface*>(this);
106         break;
107     case QAccessible::ValueInterface: {
108         QAccessible::Role r = role();
109         if (r == QAccessible::ProgressBar ||
110                 r == QAccessible::Slider ||
111                 r == QAccessible::ScrollBar ||
112                 r == QAccessible::SpinBox)
113             return static_cast<QAccessibleValueInterface*>(this);
114         break;
115     }
116     case QAccessible::TableInterface: {
117         QAccessible::Role r = role();
118         if (r == QAccessible::Table ||
119             r == QAccessible::List ||
120             r == QAccessible::Tree)
121             return static_cast<QAccessibleTableInterface*>(this);
122         break;
123     }
124     case QAccessible::TableCellInterface: {
125         QAccessible::Role r = role();
126         if (r == QAccessible::Cell ||
127             r == QAccessible::ListItem ||
128             r == QAccessible::TreeItem)
129             return static_cast<QAccessibleTableCellInterface*>(this);
130         break;
131     }
132     default:
133         break;
134     }
135     return 0;
136 }
137 
parent() const138 QAccessibleInterface *BrowserAccessibilityQt::parent() const
139 {
140     BrowserAccessibility *p = PlatformGetParent();
141     if (p)
142         return static_cast<BrowserAccessibilityQt*>(p);
143     return static_cast<BrowserAccessibilityManagerQt*>(manager())->rootParentAccessible();
144 }
145 
child(int index) const146 QAccessibleInterface *BrowserAccessibilityQt::child(int index) const
147 {
148     return static_cast<BrowserAccessibilityQt*>(BrowserAccessibility::PlatformGetChild(index));
149 }
150 
focusChild() const151 QAccessibleInterface *BrowserAccessibilityQt::focusChild() const
152 {
153     if (state().focused)
154         return const_cast<BrowserAccessibilityQt *>(this);
155 
156     for (int i = 0; i < childCount(); ++i) {
157         if (QAccessibleInterface *iface = child(i)->focusChild())
158             return iface;
159     }
160 
161     return nullptr;
162 }
163 
childCount() const164 int BrowserAccessibilityQt::childCount() const
165 {
166     return PlatformChildCount();
167 }
168 
indexOfChild(const QAccessibleInterface * iface) const169 int BrowserAccessibilityQt::indexOfChild(const QAccessibleInterface *iface) const
170 {
171 
172     const BrowserAccessibilityQt *child = static_cast<const BrowserAccessibilityQt*>(iface);
173     return const_cast<BrowserAccessibilityQt *>(child)->GetIndexInParent();
174 }
175 
text(QAccessible::Text t) const176 QString BrowserAccessibilityQt::text(QAccessible::Text t) const
177 {
178     switch (t) {
179     case QAccessible::Name:
180         return toQt(GetStringAttribute(ax::mojom::StringAttribute::kName));
181     case QAccessible::Description:
182         return toQt(GetStringAttribute(ax::mojom::StringAttribute::kDescription));
183     case QAccessible::Value:
184         return toQt(GetStringAttribute(ax::mojom::StringAttribute::kValue));
185     case QAccessible::Accelerator:
186         return toQt(GetStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts));
187     default:
188         break;
189     }
190     return QString();
191 }
192 
setText(QAccessible::Text t,const QString & text)193 void BrowserAccessibilityQt::setText(QAccessible::Text t, const QString &text)
194 {
195 }
196 
rect() const197 QRect BrowserAccessibilityQt::rect() const
198 {
199     if (!manager()) // needed implicitly by GetScreenBoundsRect()
200         return QRect();
201     gfx::Rect bounds = GetUnclippedScreenBoundsRect();
202     return QRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
203 }
204 
role() const205 QAccessible::Role BrowserAccessibilityQt::role() const
206 {
207     switch (GetRole()) {
208     case ax::mojom::Role::kNone:
209     case ax::mojom::Role::kUnknown:
210         return QAccessible::NoRole;
211 
212     // Used by Chromium to distinguish between the root of the tree
213     // for this page, and a web area for a frame within this page.
214     case ax::mojom::Role::kWebArea:
215     case ax::mojom::Role::kWebView:
216     case ax::mojom::Role::kRootWebArea: // not sure if we need to make a diff here, but this seems common
217         return QAccessible::WebDocument;
218 
219     // These roles all directly correspond to blink accessibility roles,
220     // keep these alphabetical.
221     case ax::mojom::Role::kAbbr:
222         return QAccessible::StaticText;
223     case ax::mojom::Role::kAlert:
224     case ax::mojom::Role::kAlertDialog:
225         return QAccessible::AlertMessage;
226     case ax::mojom::Role::kAnchor:
227         return QAccessible::Link;
228     case ax::mojom::Role::kApplication:
229         return QAccessible::Document; // returning Application here makes Qt return the top level app object
230     case ax::mojom::Role::kArticle:
231         return QAccessible::Section;
232     case ax::mojom::Role::kAudio:
233         return QAccessible::Sound;
234     case ax::mojom::Role::kBanner:
235         return QAccessible::Section;
236     case ax::mojom::Role::kBlockquote:
237         return QAccessible::Section;
238     case ax::mojom::Role::kButton:
239         return QAccessible::Button;
240     case ax::mojom::Role::kCanvas:
241         return QAccessible::Canvas;
242     case ax::mojom::Role::kCaption:
243         return QAccessible::Heading;
244     case ax::mojom::Role::kCaret:
245         return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003
246     case ax::mojom::Role::kCell:
247         return QAccessible::Cell;
248     case ax::mojom::Role::kCheckBox:
249         return QAccessible::CheckBox;
250     case ax::mojom::Role::kClient:
251         return QAccessible::Client;
252     case ax::mojom::Role::kCode:
253         return QAccessible::StaticText;
254     case ax::mojom::Role::kColorWell:
255         return QAccessible::ColorChooser;
256     case ax::mojom::Role::kColumn:
257         return QAccessible::Column;
258     case ax::mojom::Role::kColumnHeader:
259         return QAccessible::ColumnHeader;
260     case ax::mojom::Role::kComboBoxGrouping:
261     case ax::mojom::Role::kComboBoxMenuButton:
262     case ax::mojom::Role::kTextFieldWithComboBox:
263         return QAccessible::ComboBox;
264     case ax::mojom::Role::kComplementary:
265         return QAccessible::ComplementaryContent;
266     case ax::mojom::Role::kComment:
267         return QAccessible::Section;
268     case ax::mojom::Role::kContentDeletion:
269     case ax::mojom::Role::kContentInsertion:
270         return QAccessible::Grouping;
271     case ax::mojom::Role::kContentInfo:
272         return QAccessible::Section;
273     case ax::mojom::Role::kDate:
274     case ax::mojom::Role::kDateTime:
275         return QAccessible::Clock;
276     case ax::mojom::Role::kDefinition:
277         return QAccessible::Paragraph;
278     case ax::mojom::Role::kDescriptionList:
279         return QAccessible::List;
280     case ax::mojom::Role::kDescriptionListDetail:
281         return QAccessible::Paragraph;
282     case ax::mojom::Role::kDescriptionListTerm:
283         return QAccessible::ListItem;
284     case ax::mojom::Role::kDetails:
285         return QAccessible::Grouping;
286     case ax::mojom::Role::kDesktop:
287         return QAccessible::Pane;
288     case ax::mojom::Role::kDialog:
289         return QAccessible::Dialog;
290     case ax::mojom::Role::kDirectory:
291         return QAccessible::List;
292     case ax::mojom::Role::kDisclosureTriangle:
293         return QAccessible::Button;
294     case ax::mojom::Role::kGenericContainer:
295         return QAccessible::Section;
296     case ax::mojom::Role::kDocCover:
297         return QAccessible::Graphic;
298     case ax::mojom::Role::kDocBackLink:
299     case ax::mojom::Role::kDocBiblioRef:
300     case ax::mojom::Role::kDocGlossRef:
301     case ax::mojom::Role::kDocNoteRef:
302         return QAccessible::Link;
303     case ax::mojom::Role::kDocBiblioEntry:
304     case ax::mojom::Role::kDocEndnote:
305     case ax::mojom::Role::kDocFootnote:
306         return QAccessible::ListItem;
307     case ax::mojom::Role::kDocPageBreak:
308         return QAccessible::Separator;
309     case ax::mojom::Role::kDocAbstract:
310     case ax::mojom::Role::kDocAcknowledgments:
311     case ax::mojom::Role::kDocAfterword:
312     case ax::mojom::Role::kDocAppendix:
313     case ax::mojom::Role::kDocBibliography:
314     case ax::mojom::Role::kDocChapter:
315     case ax::mojom::Role::kDocColophon:
316     case ax::mojom::Role::kDocConclusion:
317     case ax::mojom::Role::kDocCredit:
318     case ax::mojom::Role::kDocCredits:
319     case ax::mojom::Role::kDocDedication:
320     case ax::mojom::Role::kDocEndnotes:
321     case ax::mojom::Role::kDocEpigraph:
322     case ax::mojom::Role::kDocEpilogue:
323     case ax::mojom::Role::kDocErrata:
324     case ax::mojom::Role::kDocExample:
325     case ax::mojom::Role::kDocForeword:
326     case ax::mojom::Role::kDocGlossary:
327     case ax::mojom::Role::kDocIndex:
328     case ax::mojom::Role::kDocIntroduction:
329     case ax::mojom::Role::kDocNotice:
330     case ax::mojom::Role::kDocPageList:
331     case ax::mojom::Role::kDocPart:
332     case ax::mojom::Role::kDocPreface:
333     case ax::mojom::Role::kDocPrologue:
334     case ax::mojom::Role::kDocPullquote:
335     case ax::mojom::Role::kDocQna:
336         return QAccessible::Section;
337     case ax::mojom::Role::kDocSubtitle:
338         return QAccessible::Heading;
339     case ax::mojom::Role::kDocTip:
340     case ax::mojom::Role::kDocToc:
341         return QAccessible::Section;
342     case ax::mojom::Role::kDocument:
343         return QAccessible::Document;
344     case ax::mojom::Role::kEmbeddedObject:
345         return QAccessible::Grouping;
346     case ax::mojom::Role::kEmphasis:
347         return QAccessible::StaticText;
348     case ax::mojom::Role::kFeed:
349         return QAccessible::Section;
350     case ax::mojom::Role::kFigcaption:
351         return QAccessible::Heading;
352     case ax::mojom::Role::kFigure:
353         return QAccessible::Section;
354     case ax::mojom::Role::kFooter:
355         return QAccessible::Footer;
356     case ax::mojom::Role::kFooterAsNonLandmark:
357         return QAccessible::Section;
358     case ax::mojom::Role::kForm:
359         return QAccessible::Form;
360     case ax::mojom::Role::kGraphicsDocument:
361         return QAccessible::Document;
362     case ax::mojom::Role::kGraphicsObject:
363         return QAccessible::Pane;
364     case ax::mojom::Role::kGraphicsSymbol:
365         return QAccessible::Graphic;
366     case ax::mojom::Role::kGrid:
367         return QAccessible::Table;
368     case ax::mojom::Role::kGroup:
369         return QAccessible::Grouping;
370     case ax::mojom::Role::kHeader:
371     case ax::mojom::Role::kHeaderAsNonLandmark:
372         return QAccessible::Section;
373     case ax::mojom::Role::kHeading:
374         return QAccessible::Heading;
375     case ax::mojom::Role::kIframe:
376         return QAccessible::WebDocument;
377     case ax::mojom::Role::kIframePresentational:
378         return QAccessible::Grouping;
379     case ax::mojom::Role::kIgnored:
380         return QAccessible::NoRole;
381     case ax::mojom::Role::kImage:
382         return QAccessible::Graphic;
383     case ax::mojom::Role::kImageMap:
384         return QAccessible::Document;
385     case ax::mojom::Role::kInlineTextBox:
386         return QAccessible::StaticText;
387     case ax::mojom::Role::kInputTime:
388         return QAccessible::SpinBox;
389     case ax::mojom::Role::kKeyboard:
390         return QAccessible::NoRole; // FIXME
391     case ax::mojom::Role::kLabelText:
392         return QAccessible::StaticText;
393     case ax::mojom::Role::kLayoutTable:
394     case ax::mojom::Role::kLayoutTableCell:
395     case ax::mojom::Role::kLayoutTableRow:
396         return QAccessible::Section;
397     case ax::mojom::Role::kLegend:
398         return QAccessible::StaticText;
399     case ax::mojom::Role::kLineBreak:
400         return QAccessible::Separator;
401     case ax::mojom::Role::kLink:
402         return QAccessible::Link;
403     case ax::mojom::Role::kList:
404         return QAccessible::List;
405     case ax::mojom::Role::kListBox:
406         return QAccessible::ComboBox;
407     case ax::mojom::Role::kListBoxOption:
408         return QAccessible::ListItem;
409     case ax::mojom::Role::kListItem:
410         return QAccessible::ListItem;
411     case ax::mojom::Role::kListGrid:
412         return  QAccessible::List;
413     case ax::mojom::Role::kListMarker:
414         return QAccessible::StaticText;
415     case ax::mojom::Role::kLog:
416         return QAccessible::Section;
417     case ax::mojom::Role::kMain:
418         return QAccessible::Grouping;
419     case ax::mojom::Role::kMark:
420         return QAccessible::StaticText;
421     case ax::mojom::Role::kMarquee:
422         return QAccessible::Section;
423     case ax::mojom::Role::kMath:
424         return QAccessible::Equation;
425     case ax::mojom::Role::kMenu:
426         return QAccessible::PopupMenu;
427     case ax::mojom::Role::kMenuBar:
428         return QAccessible::MenuBar;
429     case ax::mojom::Role::kMenuItem:
430         return QAccessible::MenuItem;
431     case ax::mojom::Role::kMenuItemCheckBox:
432         return QAccessible::CheckBox;
433     case ax::mojom::Role::kMenuItemRadio:
434         return QAccessible::RadioButton;
435     case ax::mojom::Role::kMenuButton:
436         return QAccessible::MenuItem;
437     case ax::mojom::Role::kMenuListOption:
438         return QAccessible::MenuItem;
439     case ax::mojom::Role::kMenuListPopup:
440         return QAccessible::PopupMenu;
441     case ax::mojom::Role::kMeter:
442         return QAccessible::Chart;
443     case ax::mojom::Role::kNavigation:
444         return QAccessible::Section;
445     case ax::mojom::Role::kNote:
446         return QAccessible::Note;
447     case ax::mojom::Role::kPane:
448         return QAccessible::Pane;
449     case ax::mojom::Role::kParagraph:
450         return QAccessible::Paragraph;
451     case ax::mojom::Role::kPdfActionableHighlight:
452         return QAccessible::Button;
453     case ax::mojom::Role::kPluginObject:
454         return QAccessible::Grouping;
455     case ax::mojom::Role::kPopUpButton:
456         return QAccessible::ComboBox;
457     case ax::mojom::Role::kPortal:
458         return QAccessible::Button;
459     case ax::mojom::Role::kPre:
460         return QAccessible::Section;
461     case ax::mojom::Role::kPresentational:
462         return QAccessible::NoRole; // FIXME
463     case ax::mojom::Role::kProgressIndicator:
464         return QAccessible::ProgressBar;
465     case ax::mojom::Role::kRadioButton:
466         return QAccessible::RadioButton;
467     case ax::mojom::Role::kRadioGroup:
468         return QAccessible::Grouping;
469     case ax::mojom::Role::kRegion:
470         return QAccessible::Section;
471     case ax::mojom::Role::kRow:
472         return QAccessible::Row;
473     case ax::mojom::Role::kRowGroup:
474         return QAccessible::Section;
475     case ax::mojom::Role::kRowHeader:
476         return QAccessible::RowHeader;
477     case ax::mojom::Role::kRuby:
478         return QAccessible::StaticText;
479     case ax::mojom::Role::kRubyAnnotation:
480         return QAccessible::StaticText;
481     case ax::mojom::Role::kScrollBar:
482         return QAccessible::ScrollBar;
483     case ax::mojom::Role::kScrollView:
484         return QAccessible::Pane;
485     case ax::mojom::Role::kSearch:
486         return QAccessible::Section;
487     case ax::mojom::Role::kSearchBox:
488         return QAccessible::EditableText;
489     case ax::mojom::Role::kSection:
490         return QAccessible::Section;
491     case ax::mojom::Role::kSlider:
492     case ax::mojom::Role::kSliderThumb:
493         return QAccessible::Slider;
494     case ax::mojom::Role::kSpinButton:
495         return QAccessible::SpinBox;
496     case ax::mojom::Role::kSplitter:
497         return QAccessible::Splitter;
498     case ax::mojom::Role::kStaticText:
499         return QAccessible::StaticText;
500     case ax::mojom::Role::kStatus:
501         return QAccessible::Indicator;
502     case ax::mojom::Role::kStrong:
503         return QAccessible::StaticText;
504     case ax::mojom::Role::kSuggestion:
505         return QAccessible::Section;
506     case ax::mojom::Role::kSvgRoot:
507         return QAccessible::Graphic;
508     case ax::mojom::Role::kSwitch:
509         return QAccessible::Button;
510     case ax::mojom::Role::kTable:
511         return QAccessible::Table;
512     case ax::mojom::Role::kTableHeaderContainer:
513         return QAccessible::Section;
514     case ax::mojom::Role::kTab:
515         return QAccessible::PageTab;
516     case ax::mojom::Role::kTabList:
517         return QAccessible::PageTabList;
518     case ax::mojom::Role::kTabPanel:
519         return QAccessible::Pane;
520     case ax::mojom::Role::kTerm:
521         return QAccessible::StaticText;
522     case ax::mojom::Role::kTextField:
523         return QAccessible::EditableText;
524     case ax::mojom::Role::kTime:
525     case ax::mojom::Role::kTimer:
526         return QAccessible::Clock;
527     case ax::mojom::Role::kTitleBar:
528         return QAccessible::Document;
529     case ax::mojom::Role::kToggleButton:
530         return QAccessible::Button;
531     case ax::mojom::Role::kToolbar:
532         return QAccessible::ToolBar;
533     case ax::mojom::Role::kTooltip:
534         return QAccessible::ToolTip;
535     case ax::mojom::Role::kTree:
536         return QAccessible::Tree;
537     case ax::mojom::Role::kTreeGrid:
538         return QAccessible::Tree;
539     case ax::mojom::Role::kTreeItem:
540         return QAccessible::TreeItem;
541     case ax::mojom::Role::kVideo:
542         return QAccessible::Animation;
543     case ax::mojom::Role::kWindow:
544         return QAccessible::Window;
545     }
546     return QAccessible::NoRole;
547 }
548 
state() const549 QAccessible::State BrowserAccessibilityQt::state() const
550 {
551     QAccessible::State state = QAccessible::State();
552     if (HasState(ax::mojom::State::kCollapsed))
553         state.collapsed = true;
554     if (HasState(ax::mojom::State::kDefault))
555         state.defaultButton = true;
556     if (HasState(ax::mojom::State::kEditable))
557         state.editable = true;
558     if (HasState(ax::mojom::State::kExpanded))
559         state.expanded = true;
560     if (HasState(ax::mojom::State::kFocusable))
561         state.focusable = true;
562     if (HasState(ax::mojom::State::kHorizontal))
563     {} // FIXME
564     if (HasState(ax::mojom::State::kHovered))
565         state.hotTracked = true;
566     if (HasState(ax::mojom::State::kIgnored))
567     {} // FIXME
568     if (HasState(ax::mojom::State::kInvisible))
569         state.invisible = true;
570     if (HasState(ax::mojom::State::kLinked))
571         state.linked = true;
572     if (HasState(ax::mojom::State::kMultiline))
573         state.multiLine = true;
574     if (HasState(ax::mojom::State::kMultiselectable))
575         state.multiSelectable = true;
576     if (HasState(ax::mojom::State::kProtected))
577         state.passwordEdit = true;
578     if (HasState(ax::mojom::State::kRequired))
579     {} // FIXME
580     if (HasState(ax::mojom::State::kRichlyEditable))
581     {} // FIXME
582     if (HasState(ax::mojom::State::kVertical))
583     {} // FIXME
584     if (HasState(ax::mojom::State::kVisited))
585         state.traversed = true;
586 
587     if (IsOffscreen())
588         state.offscreen = true;
589     if (manager()->GetFocus() == this)
590         state.focused = true;
591     if (GetBoolAttribute(ax::mojom::BoolAttribute::kBusy))
592         state.busy = true;
593     if (GetBoolAttribute(ax::mojom::BoolAttribute::kModal))
594         state.modal = true;
595     if (HasBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
596         state.selectable = true;
597         state.selected = GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
598     }
599     if (HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) {
600         state.checkable = true;
601         const ax::mojom::CheckedState checkedState =
602                 static_cast<ax::mojom::CheckedState>(GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
603         switch (checkedState) {
604         case ax::mojom::CheckedState::kTrue:
605             if (GetRole() == ax::mojom::Role::kToggleButton)
606                 state.pressed = true;
607             else
608                 state.checked = true;
609             break;
610         case ax::mojom::CheckedState::kMixed:
611             state.checkStateMixed = true;
612             break;
613         case ax::mojom::CheckedState::kFalse:
614         case ax::mojom::CheckedState::kNone:
615             break;
616         }
617     }
618     if (HasIntAttribute(ax::mojom::IntAttribute::kRestriction)) {
619         const ax::mojom::Restriction restriction = static_cast<ax::mojom::Restriction>(GetIntAttribute(ax::mojom::IntAttribute::kRestriction));
620         switch (restriction) {
621         case ax::mojom::Restriction::kReadOnly:
622             state.readOnly = true;
623             break;
624         case ax::mojom::Restriction::kDisabled:
625             state.disabled = true;
626             break;
627         case ax::mojom::Restriction::kNone:
628             break;
629         }
630     }
631     if (HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) {
632         const ax::mojom::HasPopup hasPopup = static_cast<ax::mojom::HasPopup>(GetIntAttribute(ax::mojom::IntAttribute::kHasPopup));
633         switch (hasPopup) {
634         case ax::mojom::HasPopup::kFalse:
635             break;
636         case ax::mojom::HasPopup::kTrue:
637         case ax::mojom::HasPopup::kMenu:
638         case ax::mojom::HasPopup::kListbox:
639         case ax::mojom::HasPopup::kTree:
640         case ax::mojom::HasPopup::kGrid:
641         case ax::mojom::HasPopup::kDialog:
642             state.hasPopup = true;
643             break;
644         }
645     }
646     return state;
647 }
648 
649 // Qt does not reference count accessibles
NativeAddReference()650 void BrowserAccessibilityQt::NativeAddReference()
651 {
652 }
653 
654 // there is no reference counting, but BrowserAccessibility::Destroy
655 // calls this (and that is the only place in the chromium sources,
656 // so we can safely use it to dispose of ourselves here
657 // (the default implementation of this function just contains a "delete this")
NativeReleaseReference()658 void BrowserAccessibilityQt::NativeReleaseReference()
659 {
660     // delete this
661     QAccessible::Id interfaceId = QAccessible::uniqueId(this);
662     QAccessible::deleteAccessibleInterface(interfaceId);
663 }
664 
actionNames() const665 QStringList BrowserAccessibilityQt::actionNames() const
666 {
667     QStringList actions;
668     if (HasState(ax::mojom::State::kFocusable))
669         actions << QAccessibleActionInterface::setFocusAction();
670     return actions;
671 }
672 
doAction(const QString & actionName)673 void BrowserAccessibilityQt::doAction(const QString &actionName)
674 {
675     if (actionName == QAccessibleActionInterface::setFocusAction())
676         manager()->SetFocus(*this);
677 }
678 
keyBindingsForAction(const QString & actionName) const679 QStringList BrowserAccessibilityQt::keyBindingsForAction(const QString &actionName) const
680 {
681     QT_NOT_YET_IMPLEMENTED
682     return QStringList();
683 }
684 
addSelection(int startOffset,int endOffset)685 void BrowserAccessibilityQt::addSelection(int startOffset, int endOffset)
686 {
687     manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset)));
688 }
689 
attributes(int offset,int * startOffset,int * endOffset) const690 QString BrowserAccessibilityQt::attributes(int offset, int *startOffset, int *endOffset) const
691 {
692     *startOffset = offset;
693     *endOffset = offset;
694     return QString();
695 }
696 
cursorPosition() const697 int BrowserAccessibilityQt::cursorPosition() const
698 {
699     int pos = 0;
700     GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &pos);
701     return pos;
702 }
703 
characterRect(int) const704 QRect BrowserAccessibilityQt::characterRect(int /*offset*/) const
705 {
706     QT_NOT_YET_IMPLEMENTED
707     return QRect();
708 }
709 
selectionCount() const710 int BrowserAccessibilityQt::selectionCount() const
711 {
712     int start = 0;
713     int end = 0;
714     GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &start);
715     GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &end);
716     if (start != end)
717         return 1;
718     return 0;
719 }
720 
offsetAtPoint(const QPoint &) const721 int BrowserAccessibilityQt::offsetAtPoint(const QPoint &/*point*/) const
722 {
723     QT_NOT_YET_IMPLEMENTED
724     return 0;
725 }
726 
selection(int selectionIndex,int * startOffset,int * endOffset) const727 void BrowserAccessibilityQt::selection(int selectionIndex, int *startOffset, int *endOffset) const
728 {
729     Q_ASSERT(startOffset && endOffset);
730     *startOffset = 0;
731     *endOffset = 0;
732     if (selectionIndex != 0)
733         return;
734     GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, startOffset);
735     GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, endOffset);
736 }
737 
text(int startOffset,int endOffset) const738 QString BrowserAccessibilityQt::text(int startOffset, int endOffset) const
739 {
740     return text(QAccessible::Value).mid(startOffset, endOffset - startOffset);
741 }
742 
removeSelection(int selectionIndex)743 void BrowserAccessibilityQt::removeSelection(int selectionIndex)
744 {
745     manager()->SetSelection(AXPlatformRange(CreatePositionAt(0), CreatePositionAt(0)));
746 }
747 
setCursorPosition(int position)748 void BrowserAccessibilityQt::setCursorPosition(int position)
749 {
750     manager()->SetSelection(AXPlatformRange(CreatePositionAt(position), CreatePositionAt(position)));
751 }
752 
setSelection(int selectionIndex,int startOffset,int endOffset)753 void BrowserAccessibilityQt::setSelection(int selectionIndex, int startOffset, int endOffset)
754 {
755     if (selectionIndex != 0)
756         return;
757     manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset)));
758 }
759 
characterCount() const760 int BrowserAccessibilityQt::characterCount() const
761 {
762     return text(QAccessible::Value).length();
763 }
764 
scrollToSubstring(int startIndex,int endIndex)765 void BrowserAccessibilityQt::scrollToSubstring(int startIndex, int endIndex)
766 {
767     int count = characterCount();
768     if (startIndex < endIndex && endIndex < count)
769         manager()->ScrollToMakeVisible(*this,
770                                        GetRootFrameHypertextRangeBoundsRect(
771                                            startIndex,
772                                            endIndex - startIndex,
773                                            ui::AXClippingBehavior::kUnclipped));
774 }
775 
currentValue() const776 QVariant BrowserAccessibilityQt::currentValue() const
777 {
778     QVariant result;
779     float value;
780     if (GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, &value)) {
781         result = (double) value;
782     }
783     return result;
784 }
785 
setCurrentValue(const QVariant & value)786 void BrowserAccessibilityQt::setCurrentValue(const QVariant &value)
787 {
788     // not yet implemented anywhere in blink
789     QT_NOT_YET_IMPLEMENTED
790 }
791 
maximumValue() const792 QVariant BrowserAccessibilityQt::maximumValue() const
793 {
794     QVariant result;
795     float value;
796     if (GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, &value)) {
797         result = (double) value;
798     }
799     return result;
800 }
801 
minimumValue() const802 QVariant BrowserAccessibilityQt::minimumValue() const
803 {
804     QVariant result;
805     float value;
806     if (GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, &value)) {
807         result = (double) value;
808     }
809     return result;
810 }
811 
minimumStepSize() const812 QVariant BrowserAccessibilityQt::minimumStepSize() const
813 {
814     QVariant result;
815     float value;
816     if (GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, &value)) {
817         result = (double) value;
818     }
819     return result;
820 }
821 
cellAt(int row,int column) const822 QAccessibleInterface *BrowserAccessibilityQt::cellAt(int row, int column) const
823 {
824     int columns = 0;
825     int rows = 0;
826     if (!GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns) ||
827         !GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows) ||
828         columns <= 0 ||
829         rows <= 0) {
830       return 0;
831     }
832 
833     if (row < 0 || row >= rows || column < 0 || column >= columns)
834       return 0;
835 
836     base::Optional<int> cell_id = GetCellId(row, column);
837     BrowserAccessibility* cell = cell_id ? manager()->GetFromID(*cell_id) : nullptr;
838     if (cell) {
839       QAccessibleInterface *iface = static_cast<BrowserAccessibilityQt*>(cell);
840       return iface;
841     }
842 
843     return nullptr;
844 }
845 
caption() const846 QAccessibleInterface *BrowserAccessibilityQt::caption() const
847 {
848     return nullptr;
849 }
850 
summary() const851 QAccessibleInterface *BrowserAccessibilityQt::summary() const
852 {
853     return nullptr;
854 }
855 
columnDescription(int column) const856 QString BrowserAccessibilityQt::columnDescription(int column) const
857 {
858     return QString();
859 }
860 
rowDescription(int row) const861 QString BrowserAccessibilityQt::rowDescription(int row) const
862 {
863     return QString();
864 }
865 
columnCount() const866 int BrowserAccessibilityQt::columnCount() const
867 {
868     int columns = 0;
869     if (GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, &columns))
870         return columns;
871 
872     return 0;
873 }
874 
rowCount() const875 int BrowserAccessibilityQt::rowCount() const
876 {
877     int rows = 0;
878     if (GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount, &rows))
879       return rows;
880     return 0;
881 }
882 
selectedCellCount() const883 int BrowserAccessibilityQt::selectedCellCount() const
884 {
885     return 0;
886 }
887 
selectedColumnCount() const888 int BrowserAccessibilityQt::selectedColumnCount() const
889 {
890     return 0;
891 }
892 
selectedRowCount() const893 int BrowserAccessibilityQt::selectedRowCount() const
894 {
895     return 0;
896 }
897 
selectedCells() const898 QList<QAccessibleInterface *> BrowserAccessibilityQt::selectedCells() const
899 {
900     return QList<QAccessibleInterface *>();
901 }
902 
selectedColumns() const903 QList<int> BrowserAccessibilityQt::selectedColumns() const
904 {
905     return QList<int>();
906 }
907 
selectedRows() const908 QList<int> BrowserAccessibilityQt::selectedRows() const
909 {
910     return QList<int>();
911 }
912 
isColumnSelected(int) const913 bool BrowserAccessibilityQt::isColumnSelected(int /*column*/) const
914 {
915     return false;
916 }
917 
isRowSelected(int) const918 bool BrowserAccessibilityQt::isRowSelected(int /*row*/) const
919 {
920     return false;
921 }
922 
selectRow(int)923 bool BrowserAccessibilityQt::selectRow(int /*row*/)
924 {
925     return false;
926 }
927 
selectColumn(int)928 bool BrowserAccessibilityQt::selectColumn(int /*column*/)
929 {
930     return false;
931 }
932 
unselectRow(int)933 bool BrowserAccessibilityQt::unselectRow(int /*row*/)
934 {
935     return false;
936 }
937 
unselectColumn(int)938 bool BrowserAccessibilityQt::unselectColumn(int /*column*/)
939 {
940     return false;
941 }
942 
columnExtent() const943 int BrowserAccessibilityQt::columnExtent() const
944 {
945     return 1;
946 }
947 
columnHeaderCells() const948 QList<QAccessibleInterface *> BrowserAccessibilityQt::columnHeaderCells() const
949 {
950     return QList<QAccessibleInterface*>();
951 }
952 
columnIndex() const953 int BrowserAccessibilityQt::columnIndex() const
954 {
955     int column = 0;
956     if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, &column))
957       return column;
958     return 0;
959 }
960 
rowExtent() const961 int BrowserAccessibilityQt::rowExtent() const
962 {
963     return 1;
964 }
965 
rowHeaderCells() const966 QList<QAccessibleInterface *> BrowserAccessibilityQt::rowHeaderCells() const
967 {
968     return QList<QAccessibleInterface*>();
969 }
970 
rowIndex() const971 int BrowserAccessibilityQt::rowIndex() const
972 {
973     int row = 0;
974     if (GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row))
975       return row;
976     return 0;
977 }
978 
isSelected() const979 bool BrowserAccessibilityQt::isSelected() const
980 {
981     return false;
982 }
983 
table() const984 QAccessibleInterface *BrowserAccessibilityQt::table() const
985 {
986     BrowserAccessibility* find_table = PlatformGetParent();
987     while (find_table && find_table->GetRole() != ax::mojom::Role::kTable)
988         find_table = find_table->PlatformGetParent();
989     if (!find_table)
990         return 0;
991     return static_cast<BrowserAccessibilityQt*>(find_table);
992 }
993 
modelChange(QAccessibleTableModelChangeEvent *)994 void BrowserAccessibilityQt::modelChange(QAccessibleTableModelChangeEvent *)
995 {
996 
997 }
998 
999 } // namespace content
1000 
1001 #endif // QT_CONFIG(accessibility)
1002