blob: 0f04b9352ac9e177796221507289cfb1d5668d9e [file] [log] [blame]
// Copyright 2014 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 "content/shell/test_runner/web_ax_object_proxy.h"
#include <stddef.h>
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "gin/handle.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/accessibility/ax_enums.mojom-shared.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/transform.h"
namespace test_runner {
namespace {
// Map role value to string, matching Safari/Mac platform implementation to
// avoid rebaselining web tests.
std::string RoleToString(ax::mojom::Role role) {
std::string result = "AXRole: AX";
switch (role) {
case ax::mojom::Role::kAbbr:
return result.append("Abbr");
case ax::mojom::Role::kAlertDialog:
return result.append("AlertDialog");
case ax::mojom::Role::kAlert:
return result.append("Alert");
case ax::mojom::Role::kAnchor:
return result.append("Anchor");
case ax::mojom::Role::kApplication:
return result.append("Application");
case ax::mojom::Role::kArticle:
return result.append("Article");
case ax::mojom::Role::kAudio:
return result.append("Audio");
case ax::mojom::Role::kBanner:
return result.append("Banner");
case ax::mojom::Role::kBlockquote:
return result.append("Blockquote");
case ax::mojom::Role::kButton:
return result.append("Button");
case ax::mojom::Role::kCanvas:
return result.append("Canvas");
case ax::mojom::Role::kCaption:
return result.append("Caption");
case ax::mojom::Role::kCell:
return result.append("Cell");
case ax::mojom::Role::kCode:
return result.append("Code");
case ax::mojom::Role::kCheckBox:
return result.append("CheckBox");
case ax::mojom::Role::kColorWell:
return result.append("ColorWell");
case ax::mojom::Role::kColumnHeader:
return result.append("ColumnHeader");
case ax::mojom::Role::kColumn:
return result.append("Column");
case ax::mojom::Role::kComboBoxGrouping:
return result.append("ComboBoxGrouping");
case ax::mojom::Role::kComboBoxMenuButton:
return result.append("ComboBoxMenuButton");
case ax::mojom::Role::kComment:
return result.append("Comment");
case ax::mojom::Role::kCommentSection:
return result.append("CommentSection");
case ax::mojom::Role::kComplementary:
return result.append("Complementary");
case ax::mojom::Role::kContentDeletion:
return result.append("ContentDeletion");
case ax::mojom::Role::kContentInsertion:
return result.append("ContentInsertion");
case ax::mojom::Role::kContentInfo:
return result.append("ContentInfo");
case ax::mojom::Role::kDate:
return result.append("DateField");
case ax::mojom::Role::kDateTime:
return result.append("DateTimeField");
case ax::mojom::Role::kDefinition:
return result.append("Definition");
case ax::mojom::Role::kDescriptionListDetail:
return result.append("DescriptionListDetail");
case ax::mojom::Role::kDescriptionList:
return result.append("DescriptionList");
case ax::mojom::Role::kDescriptionListTerm:
return result.append("DescriptionListTerm");
case ax::mojom::Role::kDetails:
return result.append("Details");
case ax::mojom::Role::kDialog:
return result.append("Dialog");
case ax::mojom::Role::kDirectory:
return result.append("Directory");
case ax::mojom::Role::kDisclosureTriangle:
return result.append("DisclosureTriangle");
case ax::mojom::Role::kDocAbstract:
return result.append("DocAbstract");
case ax::mojom::Role::kDocAcknowledgments:
return result.append("DocAcknowledgments");
case ax::mojom::Role::kDocAfterword:
return result.append("DocAfterword");
case ax::mojom::Role::kDocAppendix:
return result.append("DocAppendix");
case ax::mojom::Role::kDocBackLink:
return result.append("DocBackLink");
case ax::mojom::Role::kDocBiblioEntry:
return result.append("DocBiblioEntry");
case ax::mojom::Role::kDocBibliography:
return result.append("DocBibliography");
case ax::mojom::Role::kDocBiblioRef:
return result.append("DocBiblioRef");
case ax::mojom::Role::kDocChapter:
return result.append("DocChapter");
case ax::mojom::Role::kDocColophon:
return result.append("DocColophon");
case ax::mojom::Role::kDocConclusion:
return result.append("DocConclusion");
case ax::mojom::Role::kDocCover:
return result.append("DocCover");
case ax::mojom::Role::kDocCredit:
return result.append("DocCredit");
case ax::mojom::Role::kDocCredits:
return result.append("DocCredits");
case ax::mojom::Role::kDocDedication:
return result.append("DocDedication");
case ax::mojom::Role::kDocEndnote:
return result.append("DocEndnote");
case ax::mojom::Role::kDocEndnotes:
return result.append("DocEndnotes");
case ax::mojom::Role::kDocEpigraph:
return result.append("DocEpigraph");
case ax::mojom::Role::kDocEpilogue:
return result.append("DocEpilogue");
case ax::mojom::Role::kDocErrata:
return result.append("DocErrata");
case ax::mojom::Role::kDocExample:
return result.append("DocExample");
case ax::mojom::Role::kDocFootnote:
return result.append("DocFootnote");
case ax::mojom::Role::kDocForeword:
return result.append("DocForeword");
case ax::mojom::Role::kDocGlossary:
return result.append("DocGlossary");
case ax::mojom::Role::kDocGlossRef:
return result.append("DocGlossRef");
case ax::mojom::Role::kDocIndex:
return result.append("DocIndex");
case ax::mojom::Role::kDocIntroduction:
return result.append("DocIntroduction");
case ax::mojom::Role::kDocNoteRef:
return result.append("DocNoteRef");
case ax::mojom::Role::kDocNotice:
return result.append("DocNotice");
case ax::mojom::Role::kDocPageBreak:
return result.append("DocPageBreak");
case ax::mojom::Role::kDocPageList:
return result.append("DocPageList");
case ax::mojom::Role::kDocPart:
return result.append("DocPart");
case ax::mojom::Role::kDocPreface:
return result.append("DocPreface");
case ax::mojom::Role::kDocPrologue:
return result.append("DocPrologue");
case ax::mojom::Role::kDocPullquote:
return result.append("DocPullquote");
case ax::mojom::Role::kDocQna:
return result.append("DocQna");
case ax::mojom::Role::kDocSubtitle:
return result.append("DocSubtitle");
case ax::mojom::Role::kDocTip:
return result.append("DocTip");
case ax::mojom::Role::kDocToc:
return result.append("DocToc");
case ax::mojom::Role::kDocument:
return result.append("Document");
case ax::mojom::Role::kEmbeddedObject:
return result.append("EmbeddedObject");
case ax::mojom::Role::kEmphasis:
return result.append("Emphasis");
case ax::mojom::Role::kFigcaption:
return result.append("Figcaption");
case ax::mojom::Role::kFigure:
return result.append("Figure");
case ax::mojom::Role::kFooter:
return result.append("Footer");
case ax::mojom::Role::kFooterAsNonLandmark:
return result.append("FooterAsNonLandmark");
case ax::mojom::Role::kForm:
return result.append("Form");
case ax::mojom::Role::kGenericContainer:
return result.append("GenericContainer");
case ax::mojom::Role::kGraphicsDocument:
return result.append("GraphicsDocument");
case ax::mojom::Role::kGraphicsObject:
return result.append("GraphicsObject");
case ax::mojom::Role::kGraphicsSymbol:
return result.append("GraphicsSymbol");
case ax::mojom::Role::kGrid:
return result.append("Grid");
case ax::mojom::Role::kGroup:
return result.append("Group");
case ax::mojom::Role::kHeader:
return result.append("Header");
case ax::mojom::Role::kHeaderAsNonLandmark:
return result.append("HeaderAsNonLandmark");
case ax::mojom::Role::kHeading:
return result.append("Heading");
case ax::mojom::Role::kIgnored:
return result.append("Ignored");
case ax::mojom::Role::kImageMap:
return result.append("ImageMap");
case ax::mojom::Role::kImage:
return result.append("Image");
case ax::mojom::Role::kInlineTextBox:
return result.append("InlineTextBox");
case ax::mojom::Role::kInputTime:
return result.append("InputTime");
case ax::mojom::Role::kLabelText:
return result.append("Label");
case ax::mojom::Role::kLayoutTable:
return result.append("LayoutTable");
case ax::mojom::Role::kLayoutTableCell:
return result.append("LayoutTableCell");
case ax::mojom::Role::kLayoutTableColumn:
return result.append("LayoutTableColumn");
case ax::mojom::Role::kLayoutTableRow:
return result.append("LayoutTableRow");
case ax::mojom::Role::kLegend:
return result.append("Legend");
case ax::mojom::Role::kLink:
return result.append("Link");
case ax::mojom::Role::kLineBreak:
return result.append("LineBreak");
case ax::mojom::Role::kListBoxOption:
return result.append("ListBoxOption");
case ax::mojom::Role::kListBox:
return result.append("ListBox");
case ax::mojom::Role::kListItem:
return result.append("ListItem");
case ax::mojom::Role::kListMarker:
return result.append("ListMarker");
case ax::mojom::Role::kList:
return result.append("List");
case ax::mojom::Role::kLog:
return result.append("Log");
case ax::mojom::Role::kMain:
return result.append("Main");
case ax::mojom::Role::kMark:
return result.append("Mark");
case ax::mojom::Role::kMarquee:
return result.append("Marquee");
case ax::mojom::Role::kMath:
return result.append("Math");
case ax::mojom::Role::kMenuBar:
return result.append("MenuBar");
case ax::mojom::Role::kMenuButton:
return result.append("MenuButton");
case ax::mojom::Role::kMenuItem:
return result.append("MenuItem");
case ax::mojom::Role::kMenuItemCheckBox:
return result.append("MenuItemCheckBox");
case ax::mojom::Role::kMenuItemRadio:
return result.append("MenuItemRadio");
case ax::mojom::Role::kMenuListOption:
return result.append("MenuListOption");
case ax::mojom::Role::kMenuListPopup:
return result.append("MenuListPopup");
case ax::mojom::Role::kMenu:
return result.append("Menu");
case ax::mojom::Role::kMeter:
return result.append("Meter");
case ax::mojom::Role::kNavigation:
return result.append("Navigation");
case ax::mojom::Role::kNone:
return result.append("None");
case ax::mojom::Role::kNote:
return result.append("Note");
case ax::mojom::Role::kParagraph:
return result.append("Paragraph");
case ax::mojom::Role::kPopUpButton:
return result.append("PopUpButton");
case ax::mojom::Role::kPre:
return result.append("Pre");
case ax::mojom::Role::kPresentational:
return result.append("Presentational");
case ax::mojom::Role::kProgressIndicator:
return result.append("ProgressIndicator");
case ax::mojom::Role::kRadioButton:
return result.append("RadioButton");
case ax::mojom::Role::kRadioGroup:
return result.append("RadioGroup");
case ax::mojom::Role::kRegion:
return result.append("Region");
case ax::mojom::Role::kRevision:
return result.append("Revision");
case ax::mojom::Role::kRow:
return result.append("Row");
case ax::mojom::Role::kRowGroup:
return result.append("RowGroup");
case ax::mojom::Role::kRowHeader:
return result.append("RowHeader");
case ax::mojom::Role::kRuby:
return result.append("Ruby");
case ax::mojom::Role::kRubyAnnotation:
return result.append("RubyAnnotation");
case ax::mojom::Role::kSection:
return result.append("Section");
case ax::mojom::Role::kSvgRoot:
return result.append("SVGRoot");
case ax::mojom::Role::kScrollBar:
return result.append("ScrollBar");
case ax::mojom::Role::kSearch:
return result.append("Search");
case ax::mojom::Role::kSearchBox:
return result.append("SearchBox");
case ax::mojom::Role::kSlider:
return result.append("Slider");
case ax::mojom::Role::kSliderThumb:
return result.append("SliderThumb");
case ax::mojom::Role::kSpinButton:
return result.append("SpinButton");
case ax::mojom::Role::kSplitter:
return result.append("Splitter");
case ax::mojom::Role::kStaticText:
return result.append("StaticText");
case ax::mojom::Role::kStatus:
return result.append("Status");
case ax::mojom::Role::kStrong:
return result.append("Strong");
case ax::mojom::Role::kSwitch:
return result.append("Switch");
case ax::mojom::Role::kSuggestion:
return result.append("Suggestion");
case ax::mojom::Role::kTabList:
return result.append("TabList");
case ax::mojom::Role::kTabPanel:
return result.append("TabPanel");
case ax::mojom::Role::kTab:
return result.append("Tab");
case ax::mojom::Role::kTableHeaderContainer:
return result.append("TableHeaderContainer");
case ax::mojom::Role::kTable:
return result.append("Table");
case ax::mojom::Role::kTextField:
return result.append("TextField");
case ax::mojom::Role::kTextFieldWithComboBox:
return result.append("TextFieldWithComboBox");
case ax::mojom::Role::kTime:
return result.append("Time");
case ax::mojom::Role::kTimer:
return result.append("Timer");
case ax::mojom::Role::kToggleButton:
return result.append("ToggleButton");
case ax::mojom::Role::kToolbar:
return result.append("Toolbar");
case ax::mojom::Role::kTreeGrid:
return result.append("TreeGrid");
case ax::mojom::Role::kTreeItem:
return result.append("TreeItem");
case ax::mojom::Role::kTree:
return result.append("Tree");
case ax::mojom::Role::kUnknown:
return result.append("Unknown");
case ax::mojom::Role::kTooltip:
return result.append("UserInterfaceTooltip");
case ax::mojom::Role::kVideo:
return result.append("Video");
case ax::mojom::Role::kRootWebArea:
return result.append("WebArea");
default:
return result.append("Unknown");
}
}
std::string GetStringValue(const blink::WebAXObject& object) {
std::string value;
if (object.Role() == ax::mojom::Role::kColorWell) {
unsigned int color = object.ColorValue();
unsigned int red = (color >> 16) & 0xFF;
unsigned int green = (color >> 8) & 0xFF;
unsigned int blue = color & 0xFF;
value = base::StringPrintf("rgba(%d, %d, %d, 1)", red, green, blue);
} else {
value = object.StringValue().Utf8();
}
return value.insert(0, "AXValue: ");
}
std::string GetRole(const blink::WebAXObject& object) {
std::string role_string = RoleToString(object.Role());
// Special-case canvas with fallback content because Chromium wants to treat
// this as essentially a separate role that it can map differently depending
// on the platform.
if (object.Role() == ax::mojom::Role::kCanvas &&
object.CanvasHasFallbackContent()) {
role_string += "WithFallbackContent";
}
return role_string;
}
std::string GetValueDescription(const blink::WebAXObject& object) {
std::string value_description = object.ValueDescription().Utf8();
return value_description.insert(0, "AXValueDescription: ");
}
std::string GetLanguage(const blink::WebAXObject& object) {
std::string language = object.Language().Utf8();
return language.insert(0, "AXLanguage: ");
}
std::string GetAttributes(const blink::WebAXObject& object) {
std::string attributes(object.GetName().Utf8());
attributes.append("\n");
attributes.append(GetRole(object));
return attributes;
}
// New bounds calculation algorithm. Retrieves the frame-relative bounds
// of an object by calling getRelativeBounds and then applying the offsets
// and transforms recursively on each container of this object.
blink::WebFloatRect BoundsForObject(const blink::WebAXObject& object) {
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
object.GetRelativeBounds(container, bounds, matrix);
gfx::RectF computedBounds(0, 0, bounds.width, bounds.height);
while (!container.IsDetached()) {
computedBounds.Offset(bounds.x, bounds.y);
computedBounds.Offset(-container.GetScrollOffset().x,
-container.GetScrollOffset().y);
if (!matrix.isIdentity()) {
gfx::Transform transform(matrix);
transform.TransformRect(&computedBounds);
}
container.GetRelativeBounds(container, bounds, matrix);
}
return blink::WebFloatRect(computedBounds.x(), computedBounds.y(),
computedBounds.width(), computedBounds.height());
}
blink::WebRect BoundsForCharacter(const blink::WebAXObject& object,
int characterIndex) {
DCHECK_EQ(object.Role(), ax::mojom::Role::kStaticText);
int end = 0;
for (unsigned i = 0; i < object.ChildCount(); i++) {
blink::WebAXObject inline_text_box = object.ChildAt(i);
DCHECK_EQ(inline_text_box.Role(), ax::mojom::Role::kInlineTextBox);
int start = end;
blink::WebString name = inline_text_box.GetName();
end += name.length();
if (characterIndex < start || characterIndex >= end)
continue;
blink::WebFloatRect inline_text_box_rect = BoundsForObject(inline_text_box);
int localIndex = characterIndex - start;
blink::WebVector<int> character_offsets;
inline_text_box.CharacterOffsets(character_offsets);
if (character_offsets.size() != name.length())
return blink::WebRect();
switch (inline_text_box.GetTextDirection()) {
case ax::mojom::TextDirection::kLtr: {
if (localIndex) {
int left = inline_text_box_rect.x + character_offsets[localIndex - 1];
int width =
character_offsets[localIndex] - character_offsets[localIndex - 1];
return blink::WebRect(left, inline_text_box_rect.y, width,
inline_text_box_rect.height);
}
return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
character_offsets[0],
inline_text_box_rect.height);
}
case ax::mojom::TextDirection::kRtl: {
int right = inline_text_box_rect.x + inline_text_box_rect.width;
if (localIndex) {
int left = right - character_offsets[localIndex];
int width =
character_offsets[localIndex] - character_offsets[localIndex - 1];
return blink::WebRect(left, inline_text_box_rect.y, width,
inline_text_box_rect.height);
}
int left = right - character_offsets[0];
return blink::WebRect(left, inline_text_box_rect.y,
character_offsets[0],
inline_text_box_rect.height);
}
case ax::mojom::TextDirection::kTtb: {
if (localIndex) {
int top = inline_text_box_rect.y + character_offsets[localIndex - 1];
int height =
character_offsets[localIndex] - character_offsets[localIndex - 1];
return blink::WebRect(inline_text_box_rect.x, top,
inline_text_box_rect.width, height);
}
return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
inline_text_box_rect.width, character_offsets[0]);
}
case ax::mojom::TextDirection::kBtt: {
int bottom = inline_text_box_rect.y + inline_text_box_rect.height;
if (localIndex) {
int top = bottom - character_offsets[localIndex];
int height =
character_offsets[localIndex] - character_offsets[localIndex - 1];
return blink::WebRect(inline_text_box_rect.x, top,
inline_text_box_rect.width, height);
}
int top = bottom - character_offsets[0];
return blink::WebRect(inline_text_box_rect.x, top,
inline_text_box_rect.width, character_offsets[0]);
}
default:
NOTREACHED();
return blink::WebRect();
}
}
DCHECK(false);
return blink::WebRect();
}
std::vector<std::string> GetMisspellings(blink::WebAXObject& object) {
std::vector<std::string> misspellings;
std::string text(object.GetName().Utf8());
blink::WebVector<ax::mojom::MarkerType> marker_types;
blink::WebVector<int> marker_starts;
blink::WebVector<int> marker_ends;
object.Markers(marker_types, marker_starts, marker_ends);
DCHECK_EQ(marker_types.size(), marker_starts.size());
DCHECK_EQ(marker_starts.size(), marker_ends.size());
for (size_t i = 0; i < marker_types.size(); ++i) {
if (marker_types[i] == ax::mojom::MarkerType::kSpelling) {
misspellings.push_back(
text.substr(marker_starts[i], marker_ends[i] - marker_starts[i]));
}
}
return misspellings;
}
void GetBoundariesForOneWord(const blink::WebAXObject& object,
int character_index,
int& word_start,
int& word_end) {
int end = 0;
for (size_t i = 0; i < object.ChildCount(); i++) {
blink::WebAXObject inline_text_box = object.ChildAt(i);
DCHECK_EQ(inline_text_box.Role(), ax::mojom::Role::kInlineTextBox);
int start = end;
blink::WebString name = inline_text_box.GetName();
end += name.length();
if (end <= character_index)
continue;
int localIndex = character_index - start;
blink::WebVector<int> starts;
blink::WebVector<int> ends;
inline_text_box.GetWordBoundaries(starts, ends);
size_t word_count = starts.size();
DCHECK_EQ(ends.size(), word_count);
// If there are no words, use the InlineTextBox boundaries.
if (!word_count) {
word_start = start;
word_end = end;
return;
}
// Look for a character within any word other than the last.
for (size_t j = 0; j < word_count - 1; j++) {
if (localIndex <= ends[j]) {
word_start = start + starts[j];
word_end = start + ends[j];
return;
}
}
// Return the last word by default.
word_start = start + starts[word_count - 1];
word_end = start + ends[word_count - 1];
return;
}
}
// Collects attributes into a string, delimited by dashes. Used by all methods
// that output lists of attributes: attributesOfLinkedUIElementsCallback,
// AttributesOfChildrenCallback, etc.
class AttributesCollector {
public:
AttributesCollector() {}
~AttributesCollector() {}
void CollectAttributes(const blink::WebAXObject& object) {
attributes_.append("\n------------\n");
attributes_.append(GetAttributes(object));
}
std::string attributes() const { return attributes_; }
private:
std::string attributes_;
DISALLOW_COPY_AND_ASSIGN(AttributesCollector);
};
class SparseAttributeAdapter : public blink::WebAXSparseAttributeClient {
public:
SparseAttributeAdapter() {}
~SparseAttributeAdapter() override {}
std::map<blink::WebAXBoolAttribute, bool> bool_attributes;
std::map<blink::WebAXIntAttribute, int32_t> int_attributes;
std::map<blink::WebAXUIntAttribute, int32_t> uint_attributes;
std::map<blink::WebAXStringAttribute, blink::WebString> string_attributes;
std::map<blink::WebAXObjectAttribute, blink::WebAXObject> object_attributes;
std::map<blink::WebAXObjectVectorAttribute,
blink::WebVector<blink::WebAXObject>>
object_vector_attributes;
private:
void AddBoolAttribute(blink::WebAXBoolAttribute attribute,
bool value) override {
bool_attributes[attribute] = value;
}
void AddIntAttribute(blink::WebAXIntAttribute attribute,
int32_t value) override {
int_attributes[attribute] = value;
}
void AddUIntAttribute(blink::WebAXUIntAttribute attribute,
uint32_t value) override {
uint_attributes[attribute] = value;
}
void AddStringAttribute(blink::WebAXStringAttribute attribute,
const blink::WebString& value) override {
string_attributes[attribute] = value;
}
void AddObjectAttribute(blink::WebAXObjectAttribute attribute,
const blink::WebAXObject& value) override {
object_attributes[attribute] = value;
}
void AddObjectVectorAttribute(
blink::WebAXObjectVectorAttribute attribute,
const blink::WebVector<blink::WebAXObject>& value) override {
object_vector_attributes[attribute] = value;
}
};
} // namespace
gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = {gin::kEmbedderNativeGin};
WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object,
WebAXObjectProxy::Factory* factory)
: accessibility_object_(object), factory_(factory) {}
WebAXObjectProxy::~WebAXObjectProxy() {}
gin::ObjectTemplateBuilder WebAXObjectProxy::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate)
.SetProperty("role", &WebAXObjectProxy::Role)
.SetProperty("stringValue", &WebAXObjectProxy::StringValue)
.SetProperty("language", &WebAXObjectProxy::Language)
.SetProperty("x", &WebAXObjectProxy::X)
.SetProperty("y", &WebAXObjectProxy::Y)
.SetProperty("width", &WebAXObjectProxy::Width)
.SetProperty("height", &WebAXObjectProxy::Height)
.SetProperty("inPageLinkTarget", &WebAXObjectProxy::InPageLinkTarget)
.SetProperty("intValue", &WebAXObjectProxy::IntValue)
.SetProperty("minValue", &WebAXObjectProxy::MinValue)
.SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
.SetProperty("stepValue", &WebAXObjectProxy::StepValue)
.SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
.SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
.SetProperty("selectionIsBackward",
&WebAXObjectProxy::SelectionIsBackward)
.SetProperty("selectionAnchorObject",
&WebAXObjectProxy::SelectionAnchorObject)
.SetProperty("selectionAnchorOffset",
&WebAXObjectProxy::SelectionAnchorOffset)
.SetProperty("selectionAnchorAffinity",
&WebAXObjectProxy::SelectionAnchorAffinity)
.SetProperty("selectionFocusObject",
&WebAXObjectProxy::SelectionFocusObject)
.SetProperty("selectionFocusOffset",
&WebAXObjectProxy::SelectionFocusOffset)
.SetProperty("selectionFocusAffinity",
&WebAXObjectProxy::SelectionFocusAffinity)
.SetProperty("isAtomic", &WebAXObjectProxy::IsAtomic)
.SetProperty("isAutofillAvailable",
&WebAXObjectProxy::IsAutofillAvailable)
.SetProperty("isBusy", &WebAXObjectProxy::IsBusy)
.SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
.SetProperty("isEditable", &WebAXObjectProxy::IsEditable)
.SetProperty("isEditableRoot", &WebAXObjectProxy::IsEditableRoot)
.SetProperty("isRichlyEditable", &WebAXObjectProxy::IsRichlyEditable)
.SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
.SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
.SetProperty("isModal", &WebAXObjectProxy::IsModal)
.SetProperty("isSelected", &WebAXObjectProxy::IsSelected)
.SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable)
.SetProperty("isMultiLine", &WebAXObjectProxy::IsMultiLine)
.SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable)
.SetProperty("isSelectedOptionActive",
&WebAXObjectProxy::IsSelectedOptionActive)
.SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded)
.SetProperty("checked", &WebAXObjectProxy::Checked)
.SetProperty("isVisible", &WebAXObjectProxy::IsVisible)
.SetProperty("isVisited", &WebAXObjectProxy::IsVisited)
.SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen)
.SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed)
.SetProperty("hasPopup", &WebAXObjectProxy::HasPopup)
.SetProperty("isValid", &WebAXObjectProxy::IsValid)
.SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly)
.SetProperty("isIgnored", &WebAXObjectProxy::IsIgnored)
.SetProperty("restriction", &WebAXObjectProxy::Restriction)
.SetProperty("activeDescendant", &WebAXObjectProxy::ActiveDescendant)
.SetProperty("backgroundColor", &WebAXObjectProxy::BackgroundColor)
.SetProperty("color", &WebAXObjectProxy::Color)
.SetProperty("colorValue", &WebAXObjectProxy::ColorValue)
.SetProperty("fontFamily", &WebAXObjectProxy::FontFamily)
.SetProperty("fontSize", &WebAXObjectProxy::FontSize)
.SetProperty("autocomplete", &WebAXObjectProxy::Autocomplete)
.SetProperty("current", &WebAXObjectProxy::Current)
.SetProperty("invalid", &WebAXObjectProxy::Invalid)
.SetProperty("keyShortcuts", &WebAXObjectProxy::KeyShortcuts)
.SetProperty("ariaColumnCount", &WebAXObjectProxy::AriaColumnCount)
.SetProperty("ariaColumnIndex", &WebAXObjectProxy::AriaColumnIndex)
.SetProperty("ariaColumnSpan", &WebAXObjectProxy::AriaColumnSpan)
.SetProperty("ariaRowCount", &WebAXObjectProxy::AriaRowCount)
.SetProperty("ariaRowIndex", &WebAXObjectProxy::AriaRowIndex)
.SetProperty("ariaRowSpan", &WebAXObjectProxy::AriaRowSpan)
.SetProperty("live", &WebAXObjectProxy::Live)
.SetProperty("orientation", &WebAXObjectProxy::Orientation)
.SetProperty("relevant", &WebAXObjectProxy::Relevant)
.SetProperty("roleDescription", &WebAXObjectProxy::RoleDescription)
.SetProperty("sort", &WebAXObjectProxy::Sort)
.SetProperty("url", &WebAXObjectProxy::Url)
.SetProperty("hierarchicalLevel", &WebAXObjectProxy::HierarchicalLevel)
.SetProperty("posInSet", &WebAXObjectProxy::PosInSet)
.SetProperty("setSize", &WebAXObjectProxy::SetSize)
.SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
.SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
.SetProperty("rowCount", &WebAXObjectProxy::RowCount)
.SetProperty("rowHeadersCount", &WebAXObjectProxy::RowHeadersCount)
.SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
.SetProperty("columnHeadersCount", &WebAXObjectProxy::ColumnHeadersCount)
.SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
//
// NEW bounding rect calculation - high-level interface
//
.SetProperty("boundsX", &WebAXObjectProxy::BoundsX)
.SetProperty("boundsY", &WebAXObjectProxy::BoundsY)
.SetProperty("boundsWidth", &WebAXObjectProxy::BoundsWidth)
.SetProperty("boundsHeight", &WebAXObjectProxy::BoundsHeight)
.SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
.SetMethod("attributesOfChildren",
&WebAXObjectProxy::AttributesOfChildren)
.SetMethod("ariaActiveDescendantElement",
&WebAXObjectProxy::AriaActiveDescendantElement)
.SetMethod("ariaControlsElementAtIndex",
&WebAXObjectProxy::AriaControlsElementAtIndex)
.SetMethod("ariaDetailsElement", &WebAXObjectProxy::AriaDetailsElement)
.SetMethod("ariaErrorMessageElement",
&WebAXObjectProxy::AriaErrorMessageElement)
.SetMethod("ariaFlowToElementAtIndex",
&WebAXObjectProxy::AriaFlowToElementAtIndex)
.SetMethod("ariaOwnsElementAtIndex",
&WebAXObjectProxy::AriaOwnsElementAtIndex)
.SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
.SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
.SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
.SetMethod("rowHeaderAtIndex", &WebAXObjectProxy::RowHeaderAtIndex)
.SetMethod("columnHeaderAtIndex", &WebAXObjectProxy::ColumnHeaderAtIndex)
.SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
.SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
.SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
.SetMethod("setSelectedTextRange",
&WebAXObjectProxy::SetSelectedTextRange)
.SetMethod("setSelection", &WebAXObjectProxy::SetSelection)
.SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
.SetMethod("isPressActionSupported",
&WebAXObjectProxy::IsPressActionSupported)
.SetMethod("parentElement", &WebAXObjectProxy::ParentElement)
.SetMethod("increment", &WebAXObjectProxy::Increment)
.SetMethod("decrement", &WebAXObjectProxy::Decrement)
.SetMethod("showMenu", &WebAXObjectProxy::ShowMenu)
.SetMethod("press", &WebAXObjectProxy::Press)
.SetMethod("setValue", &WebAXObjectProxy::SetValue)
.SetMethod("isEqual", &WebAXObjectProxy::IsEqual)
.SetMethod("setNotificationListener",
&WebAXObjectProxy::SetNotificationListener)
.SetMethod("unsetNotificationListener",
&WebAXObjectProxy::UnsetNotificationListener)
.SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus)
.SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible)
.SetMethod("scrollToMakeVisibleWithSubFocus",
&WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus)
.SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint)
.SetMethod("scrollX", &WebAXObjectProxy::ScrollX)
.SetMethod("scrollY", &WebAXObjectProxy::ScrollY)
.SetMethod("toString", &WebAXObjectProxy::ToString)
.SetMethod("wordStart", &WebAXObjectProxy::WordStart)
.SetMethod("wordEnd", &WebAXObjectProxy::WordEnd)
.SetMethod("nextOnLine", &WebAXObjectProxy::NextOnLine)
.SetMethod("previousOnLine", &WebAXObjectProxy::PreviousOnLine)
.SetMethod("misspellingAtIndex", &WebAXObjectProxy::MisspellingAtIndex)
// TODO(hajimehoshi): This is for backward compatibility. Remove them.
.SetMethod("addNotificationListener",
&WebAXObjectProxy::SetNotificationListener)
.SetMethod("removeNotificationListener",
&WebAXObjectProxy::UnsetNotificationListener)
//
// NEW accessible name and description accessors
//
.SetProperty("name", &WebAXObjectProxy::Name)
.SetProperty("nameFrom", &WebAXObjectProxy::NameFrom)
.SetMethod("nameElementCount", &WebAXObjectProxy::NameElementCount)
.SetMethod("nameElementAtIndex", &WebAXObjectProxy::NameElementAtIndex)
.SetProperty("description", &WebAXObjectProxy::Description)
.SetProperty("descriptionFrom", &WebAXObjectProxy::DescriptionFrom)
.SetProperty("placeholder", &WebAXObjectProxy::Placeholder)
.SetProperty("misspellingsCount", &WebAXObjectProxy::MisspellingsCount)
.SetMethod("descriptionElementCount",
&WebAXObjectProxy::DescriptionElementCount)
.SetMethod("descriptionElementAtIndex",
&WebAXObjectProxy::DescriptionElementAtIndex)
//
// NEW bounding rect calculation - low-level interface
//
.SetMethod("offsetContainer", &WebAXObjectProxy::OffsetContainer)
.SetMethod("boundsInContainerX", &WebAXObjectProxy::BoundsInContainerX)
.SetMethod("boundsInContainerY", &WebAXObjectProxy::BoundsInContainerY)
.SetMethod("boundsInContainerWidth",
&WebAXObjectProxy::BoundsInContainerWidth)
.SetMethod("boundsInContainerHeight",
&WebAXObjectProxy::BoundsInContainerHeight)
.SetMethod("hasNonIdentityTransform",
&WebAXObjectProxy::HasNonIdentityTransform);
}
v8::Local<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
return factory_->GetOrCreate(accessibility_object_.ChildAt(index));
}
bool WebAXObjectProxy::IsRoot() const {
return false;
}
bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) {
return accessibility_object_.Equals(other);
}
void WebAXObjectProxy::NotificationReceived(
blink::WebLocalFrame* frame,
const std::string& notification_name) {
if (notification_callback_.IsEmpty())
return;
v8::Local<v8::Context> context = frame->MainWorldScriptContext();
if (context.IsEmpty())
return;
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::Local<v8::Value> argv[] = {
v8::String::NewFromUtf8(isolate, notification_name.data(),
v8::NewStringType::kNormal,
notification_name.size())
.ToLocalChecked(),
};
// TODO(aboxhall): Can we force this to run in a new task, to avoid
// dirtying layout during post-layout hooks?
frame->CallFunctionEvenIfScriptDisabled(
v8::Local<v8::Function>::New(isolate, notification_callback_),
context->Global(), base::size(argv), argv);
}
void WebAXObjectProxy::Reset() {
notification_callback_.Reset();
}
std::string WebAXObjectProxy::Role() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetRole(accessibility_object_);
}
std::string WebAXObjectProxy::StringValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetStringValue(accessibility_object_);
}
std::string WebAXObjectProxy::Language() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetLanguage(accessibility_object_);
}
int WebAXObjectProxy::X() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).x;
}
int WebAXObjectProxy::Y() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).y;
}
int WebAXObjectProxy::Width() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).width;
}
int WebAXObjectProxy::Height() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).height;
}
v8::Local<v8::Value> WebAXObjectProxy::InPageLinkTarget() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject target = accessibility_object_.InPageLinkTarget();
if (target.IsNull())
return v8::Null(blink::MainThreadIsolate());
return factory_->GetOrCreate(target);
}
int WebAXObjectProxy::IntValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.SupportsRangeValue()) {
float value = 0.0f;
accessibility_object_.ValueForRange(&value);
return static_cast<int>(value);
} else if (accessibility_object_.Role() == ax::mojom::Role::kHeading) {
return accessibility_object_.HeadingLevel();
} else {
return atoi(accessibility_object_.StringValue().Utf8().data());
}
}
int WebAXObjectProxy::MinValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
float min_value = 0.0f;
accessibility_object_.MinValueForRange(&min_value);
return min_value;
}
int WebAXObjectProxy::MaxValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
float max_value = 0.0f;
accessibility_object_.MaxValueForRange(&max_value);
return max_value;
}
int WebAXObjectProxy::StepValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
float step_value = 0.0f;
accessibility_object_.StepValueForRange(&step_value);
return step_value;
}
std::string WebAXObjectProxy::ValueDescription() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetValueDescription(accessibility_object_);
}
int WebAXObjectProxy::ChildrenCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
int count = 1; // Root object always has only one child, the WebView.
if (!IsRoot())
count = accessibility_object_.ChildCount();
return count;
}
bool WebAXObjectProxy::SelectionIsBackward() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
return is_selection_backward;
}
v8::Local<v8::Value> WebAXObjectProxy::SelectionAnchorObject() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
if (anchorObject.IsNull())
return v8::Null(blink::MainThreadIsolate());
return factory_->GetOrCreate(anchorObject);
}
int WebAXObjectProxy::SelectionAnchorOffset() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
if (anchorOffset < 0)
return -1;
return anchorOffset;
}
std::string WebAXObjectProxy::SelectionAnchorAffinity() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
return anchorAffinity == ax::mojom::TextAffinity::kUpstream ? "upstream"
: "downstream";
}
v8::Local<v8::Value> WebAXObjectProxy::SelectionFocusObject() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
if (focusObject.IsNull())
return v8::Null(blink::MainThreadIsolate());
return factory_->GetOrCreate(focusObject);
}
int WebAXObjectProxy::SelectionFocusOffset() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
if (focusOffset < 0)
return -1;
return focusOffset;
}
std::string WebAXObjectProxy::SelectionFocusAffinity() {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool is_selection_backward = false;
blink::WebAXObject anchorObject;
int anchorOffset = -1;
ax::mojom::TextAffinity anchorAffinity;
blink::WebAXObject focusObject;
int focusOffset = -1;
ax::mojom::TextAffinity focusAffinity;
accessibility_object_.Selection(is_selection_backward, anchorObject,
anchorOffset, anchorAffinity, focusObject,
focusOffset, focusAffinity);
return focusAffinity == ax::mojom::TextAffinity::kUpstream ? "upstream"
: "downstream";
}
bool WebAXObjectProxy::IsAtomic() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.LiveRegionAtomic();
}
bool WebAXObjectProxy::IsAutofillAvailable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsAutofillAvailable();
}
bool WebAXObjectProxy::IsBusy() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.bool_attributes[blink::WebAXBoolAttribute::kAriaBusy];
}
std::string WebAXObjectProxy::Restriction() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.Restriction()) {
case blink::kWebAXRestrictionReadOnly:
return "readOnly";
case blink::kWebAXRestrictionDisabled:
return "disabled";
case blink::kWebAXRestrictionNone:
break;
}
return "none";
}
bool WebAXObjectProxy::IsRequired() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsRequired();
}
bool WebAXObjectProxy::IsEditableRoot() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsEditableRoot();
}
bool WebAXObjectProxy::IsEditable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsEditable();
}
bool WebAXObjectProxy::IsRichlyEditable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsRichlyEditable();
}
bool WebAXObjectProxy::IsFocused() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsFocused();
}
bool WebAXObjectProxy::IsFocusable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.CanSetFocusAttribute();
}
bool WebAXObjectProxy::IsModal() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsModal();
}
bool WebAXObjectProxy::IsSelected() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsSelected() == blink::kWebAXSelectedStateTrue;
}
bool WebAXObjectProxy::IsSelectable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsSelected() !=
blink::kWebAXSelectedStateUndefined;
}
bool WebAXObjectProxy::IsMultiLine() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsMultiline();
}
bool WebAXObjectProxy::IsMultiSelectable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsMultiSelectable();
}
bool WebAXObjectProxy::IsSelectedOptionActive() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsSelectedOptionActive();
}
bool WebAXObjectProxy::IsExpanded() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsExpanded() == blink::kWebAXExpandedExpanded;
}
std::string WebAXObjectProxy::Checked() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.CheckedState()) {
case ax::mojom::CheckedState::kTrue:
return "true";
case ax::mojom::CheckedState::kMixed:
return "mixed";
case ax::mojom::CheckedState::kFalse:
return "false";
default:
return std::string();
}
}
bool WebAXObjectProxy::IsCollapsed() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsExpanded() == blink::kWebAXExpandedCollapsed;
}
bool WebAXObjectProxy::IsVisible() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsVisible();
}
bool WebAXObjectProxy::IsVisited() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsVisited();
}
bool WebAXObjectProxy::IsOffScreen() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsOffScreen();
}
bool WebAXObjectProxy::IsValid() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return !accessibility_object_.IsDetached();
}
bool WebAXObjectProxy::IsReadOnly() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.Restriction() ==
blink::kWebAXRestrictionReadOnly;
}
bool WebAXObjectProxy::IsIgnored() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.AccessibilityIsIgnored();
}
v8::Local<v8::Object> WebAXObjectProxy::ActiveDescendant() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject element = accessibility_object_.AriaActiveDescendant();
return factory_->GetOrCreate(element);
}
unsigned int WebAXObjectProxy::BackgroundColor() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.BackgroundColor();
}
unsigned int WebAXObjectProxy::Color() {
accessibility_object_.UpdateLayoutAndCheckValidity();
unsigned int color = accessibility_object_.GetColor();
// Remove the alpha because it's always 1 and thus not informative.
return color & 0xFFFFFF;
}
// For input elements of type color.
unsigned int WebAXObjectProxy::ColorValue() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.ColorValue();
}
std::string WebAXObjectProxy::FontFamily() {
accessibility_object_.UpdateLayoutAndCheckValidity();
std::string font_family(accessibility_object_.FontFamily().Utf8());
return font_family.insert(0, "AXFontFamily: ");
}
float WebAXObjectProxy::FontSize() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.FontSize();
}
std::string WebAXObjectProxy::Autocomplete() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.AutoComplete().Utf8();
}
std::string WebAXObjectProxy::Current() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.AriaCurrentState()) {
case ax::mojom::AriaCurrentState::kFalse:
return "false";
case ax::mojom::AriaCurrentState::kTrue:
return "true";
case ax::mojom::AriaCurrentState::kPage:
return "page";
case ax::mojom::AriaCurrentState::kStep:
return "step";
case ax::mojom::AriaCurrentState::kLocation:
return "location";
case ax::mojom::AriaCurrentState::kDate:
return "date";
case ax::mojom::AriaCurrentState::kTime:
return "time";
default:
return std::string();
}
}
std::string WebAXObjectProxy::HasPopup() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.HasPopup()) {
case ax::mojom::HasPopup::kTrue:
return "true";
case ax::mojom::HasPopup::kMenu:
return "menu";
case ax::mojom::HasPopup::kListbox:
return "listbox";
case ax::mojom::HasPopup::kTree:
return "tree";
case ax::mojom::HasPopup::kGrid:
return "grid";
case ax::mojom::HasPopup::kDialog:
return "dialog";
default:
return std::string();
}
}
std::string WebAXObjectProxy::Invalid() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.InvalidState()) {
case ax::mojom::InvalidState::kFalse:
return "false";
case ax::mojom::InvalidState::kTrue:
return "true";
case ax::mojom::InvalidState::kOther:
return "other";
default:
return std::string();
}
}
std::string WebAXObjectProxy::KeyShortcuts() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.string_attributes[blink::WebAXStringAttribute::kAriaKeyShortcuts]
.Utf8();
}
int32_t WebAXObjectProxy::AriaColumnCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.int_attributes[blink::WebAXIntAttribute::kAriaColumnCount];
}
uint32_t WebAXObjectProxy::AriaColumnIndex() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.uint_attributes[blink::WebAXUIntAttribute::kAriaColumnIndex];
}
uint32_t WebAXObjectProxy::AriaColumnSpan() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.uint_attributes[blink::WebAXUIntAttribute::kAriaColumnSpan];
}
int32_t WebAXObjectProxy::AriaRowCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.int_attributes[blink::WebAXIntAttribute::kAriaRowCount];
}
uint32_t WebAXObjectProxy::AriaRowIndex() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.uint_attributes[blink::WebAXUIntAttribute::kAriaRowIndex];
}
uint32_t WebAXObjectProxy::AriaRowSpan() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.uint_attributes[blink::WebAXUIntAttribute::kAriaRowSpan];
}
std::string WebAXObjectProxy::Live() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.LiveRegionStatus().Utf8();
}
std::string WebAXObjectProxy::Orientation() {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.Orientation() == blink::kWebAXOrientationVertical)
return "AXOrientation: AXVerticalOrientation";
else if (accessibility_object_.Orientation() ==
blink::kWebAXOrientationHorizontal)
return "AXOrientation: AXHorizontalOrientation";
return std::string();
}
std::string WebAXObjectProxy::Relevant() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.LiveRegionRelevant().Utf8();
}
std::string WebAXObjectProxy::RoleDescription() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
return attribute_adapter
.string_attributes[blink::WebAXStringAttribute::kAriaRoleDescription]
.Utf8();
}
std::string WebAXObjectProxy::Sort() {
accessibility_object_.UpdateLayoutAndCheckValidity();
switch (accessibility_object_.SortDirection()) {
case ax::mojom::SortDirection::kAscending:
return "ascending";
case ax::mojom::SortDirection::kDescending:
return "descending";
case ax::mojom::SortDirection::kOther:
return "other";
default:
return std::string();
}
}
std::string WebAXObjectProxy::Url() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.Url().GetString().Utf8();
}
int WebAXObjectProxy::HierarchicalLevel() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.HierarchicalLevel();
}
int WebAXObjectProxy::PosInSet() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.PosInSet();
}
int WebAXObjectProxy::SetSize() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.SetSize();
}
int WebAXObjectProxy::ClickPointX() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebFloatRect bounds = BoundsForObject(accessibility_object_);
return bounds.x + bounds.width / 2;
}
int WebAXObjectProxy::ClickPointY() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebFloatRect bounds = BoundsForObject(accessibility_object_);
return bounds.y + bounds.height / 2;
}
int32_t WebAXObjectProxy::RowCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return static_cast<int32_t>(accessibility_object_.RowCount());
}
int32_t WebAXObjectProxy::RowHeadersCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebVector<blink::WebAXObject> headers;
accessibility_object_.RowHeaders(headers);
return static_cast<int32_t>(headers.size());
}
int32_t WebAXObjectProxy::ColumnCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return static_cast<int32_t>(accessibility_object_.ColumnCount());
}
int32_t WebAXObjectProxy::ColumnHeadersCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebVector<blink::WebAXObject> headers;
accessibility_object_.ColumnHeaders(headers);
return static_cast<int32_t>(headers.size());
}
bool WebAXObjectProxy::IsClickable() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.IsClickable();
}
v8::Local<v8::Object> WebAXObjectProxy::AriaActiveDescendantElement() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
blink::WebAXObject element =
attribute_adapter.object_attributes
[blink::WebAXObjectAttribute::kAriaActiveDescendant];
return factory_->GetOrCreate(element);
}
v8::Local<v8::Object> WebAXObjectProxy::AriaControlsElementAtIndex(
unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
blink::WebVector<blink::WebAXObject> elements =
attribute_adapter.object_vector_attributes
[blink::WebAXObjectVectorAttribute::kAriaControls];
size_t elementCount = elements.size();
if (index >= elementCount)
return v8::Local<v8::Object>();
return factory_->GetOrCreate(elements[index]);
}
v8::Local<v8::Object> WebAXObjectProxy::AriaDetailsElement() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
blink::WebAXObject element =
attribute_adapter
.object_attributes[blink::WebAXObjectAttribute::kAriaDetails];
return factory_->GetOrCreate(element);
}
v8::Local<v8::Object> WebAXObjectProxy::AriaErrorMessageElement() {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
blink::WebAXObject element =
attribute_adapter
.object_attributes[blink::WebAXObjectAttribute::kAriaErrorMessage];
return factory_->GetOrCreate(element);
}
v8::Local<v8::Object> WebAXObjectProxy::AriaFlowToElementAtIndex(
unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
SparseAttributeAdapter attribute_adapter;
accessibility_object_.GetSparseAXAttributes(attribute_adapter);
blink::WebVector<blink::WebAXObject> elements =
attribute_adapter.object_vector_attributes
[blink::WebAXObjectVectorAttribute::kAriaFlowTo];
size_t elementCount = elements.size();
if (index >= elementCount)
return v8::Local<v8::Object>();
return factory_->GetOrCreate(elements[index]);
}
v8::Local<v8::Object> WebAXObjectProxy::AriaOwnsElementAtIndex(unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebVector<blink::WebAXObject> elements;
accessibility_object_.AriaOwns(elements);
size_t elementCount = elements.size();
if (index >= elementCount)
return v8::Local<v8::Object>();
return factory_->GetOrCreate(elements[index]);
}
std::string WebAXObjectProxy::AllAttributes() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetAttributes(accessibility_object_);
}
std::string WebAXObjectProxy::AttributesOfChildren() {
accessibility_object_.UpdateLayoutAndCheckValidity();
AttributesCollector collector;
unsigned size = accessibility_object_.ChildCount();
for (unsigned i = 0; i < size; ++i)
collector.CollectAttributes(accessibility_object_.ChildAt(i));
return collector.attributes();
}
std::string WebAXObjectProxy::BoundsForRange(int start, int end) {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.Role() != ax::mojom::Role::kStaticText)
return std::string();
if (!accessibility_object_.UpdateLayoutAndCheckValidity())
return std::string();
int len = end - start;
// Get the bounds for each character and union them into one large rectangle.
// This is just for testing so it doesn't need to be efficient.
blink::WebRect bounds = BoundsForCharacter(accessibility_object_, start);
for (int i = 1; i < len; i++) {
blink::WebRect next = BoundsForCharacter(accessibility_object_, start + i);
int right = std::max(bounds.x + bounds.width, next.x + next.width);
int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
bounds.x = std::min(bounds.x, next.x);
bounds.y = std::min(bounds.y, next.y);
bounds.width = right - bounds.x;
bounds.height = bottom - bounds.y;
}
return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}", bounds.x,
bounds.y, bounds.width, bounds.height);
}
v8::Local<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetChildAtIndex(index);
}
v8::Local<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebPoint point(x, y);
blink::WebAXObject obj = accessibility_object_.HitTest(point);
if (obj.IsNull())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(obj);
}
v8::Local<v8::Object> WebAXObjectProxy::RowHeaderAtIndex(unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebVector<blink::WebAXObject> headers;
accessibility_object_.RowHeaders(headers);
size_t headerCount = headers.size();
if (index >= headerCount)
return v8::Local<v8::Object>();
return factory_->GetOrCreate(headers[index]);
}
v8::Local<v8::Object> WebAXObjectProxy::ColumnHeaderAtIndex(unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebVector<blink::WebAXObject> headers;
accessibility_object_.ColumnHeaders(headers);
size_t headerCount = headers.size();
if (index >= headerCount)
return v8::Local<v8::Object>();
return factory_->GetOrCreate(headers[index]);
}
std::string WebAXObjectProxy::RowIndexRange() {
accessibility_object_.UpdateLayoutAndCheckValidity();
unsigned row_index = accessibility_object_.CellRowIndex();
unsigned row_span = accessibility_object_.CellRowSpan();
return base::StringPrintf("{%d, %d}", row_index, row_span);
}
std::string WebAXObjectProxy::ColumnIndexRange() {
accessibility_object_.UpdateLayoutAndCheckValidity();
unsigned column_index = accessibility_object_.CellColumnIndex();
unsigned column_span = accessibility_object_.CellColumnSpan();
return base::StringPrintf("{%d, %d}", column_index, column_span);
}
v8::Local<v8::Object> WebAXObjectProxy::CellForColumnAndRow(int column,
int row) {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject obj =
accessibility_object_.CellForColumnAndRow(column, row);
if (obj.IsNull())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(obj);
}
void WebAXObjectProxy::SetSelectedTextRange(int selection_start, int length) {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.SetSelection(accessibility_object_, selection_start,
accessibility_object_,
selection_start + length);
}
bool WebAXObjectProxy::SetSelection(v8::Local<v8::Value> anchor_object,
int anchor_offset,
v8::Local<v8::Value> focus_object,
int focus_offset) {
if (anchor_object.IsEmpty() || focus_object.IsEmpty() ||
!anchor_object->IsObject() || !focus_object->IsObject() ||
anchor_offset < 0 || focus_offset < 0) {
return false;
}
WebAXObjectProxy* web_ax_anchor = nullptr;
if (!gin::ConvertFromV8(blink::MainThreadIsolate(), anchor_object,
&web_ax_anchor)) {
return false;
}
DCHECK(web_ax_anchor);
WebAXObjectProxy* web_ax_focus = nullptr;
if (!gin::ConvertFromV8(blink::MainThreadIsolate(), focus_object,
&web_ax_focus)) {
return false;
}
DCHECK(web_ax_focus);
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.SetSelection(
web_ax_anchor->accessibility_object_, anchor_offset,
web_ax_focus->accessibility_object_, focus_offset);
}
bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
accessibility_object_.UpdateLayoutAndCheckValidity();
bool settable = false;
if (attribute == "AXValue")
settable = accessibility_object_.CanSetValueAttribute();
return settable;
}
bool WebAXObjectProxy::IsPressActionSupported() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.CanPress();
}
v8::Local<v8::Object> WebAXObjectProxy::ParentElement() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject parent_object = accessibility_object_.ParentObject();
while (!parent_object.IsNull() &&
!parent_object.AccessibilityIsIncludedInTree())
parent_object = parent_object.ParentObject();
return factory_->GetOrCreate(parent_object);
}
void WebAXObjectProxy::Increment() {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.Increment();
}
void WebAXObjectProxy::Decrement() {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.Decrement();
}
void WebAXObjectProxy::ShowMenu() {
accessibility_object_.ShowContextMenu();
}
void WebAXObjectProxy::Press() {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.Click();
}
bool WebAXObjectProxy::SetValue(const std::string& value) {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.Restriction() != blink::kWebAXRestrictionNone ||
accessibility_object_.StringValue().IsEmpty())
return false;
accessibility_object_.SetValue(blink::WebString::FromUTF8(value));
return true;
}
bool WebAXObjectProxy::IsEqual(v8::Local<v8::Object> proxy) {
WebAXObjectProxy* unwrapped_proxy = nullptr;
if (!gin::ConvertFromV8(blink::MainThreadIsolate(), proxy, &unwrapped_proxy))
return false;
return unwrapped_proxy->IsEqualToObject(accessibility_object_);
}
void WebAXObjectProxy::SetNotificationListener(
v8::Local<v8::Function> callback) {
v8::Isolate* isolate = blink::MainThreadIsolate();
notification_callback_.Reset(isolate, callback);
}
void WebAXObjectProxy::UnsetNotificationListener() {
notification_callback_.Reset();
}
void WebAXObjectProxy::TakeFocus() {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.Focus();
}
void WebAXObjectProxy::ScrollToMakeVisible() {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.ScrollToMakeVisible();
}
void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x,
int y,
int width,
int height) {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.ScrollToMakeVisibleWithSubFocus(
blink::WebRect(x, y, width, height));
}
void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
accessibility_object_.UpdateLayoutAndCheckValidity();
accessibility_object_.ScrollToGlobalPoint(blink::WebPoint(x, y));
}
int WebAXObjectProxy::ScrollX() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.GetScrollOffset().x;
}
int WebAXObjectProxy::ScrollY() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.GetScrollOffset().y;
}
std::string WebAXObjectProxy::ToString() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.ToString().Utf8();
}
float WebAXObjectProxy::BoundsX() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).x;
}
float WebAXObjectProxy::BoundsY() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).y;
}
float WebAXObjectProxy::BoundsWidth() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).width;
}
float WebAXObjectProxy::BoundsHeight() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return BoundsForObject(accessibility_object_).height;
}
int WebAXObjectProxy::WordStart(int character_index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.Role() != ax::mojom::Role::kStaticText)
return -1;
int word_start = 0, word_end = 0;
GetBoundariesForOneWord(accessibility_object_, character_index, word_start,
word_end);
return word_start;
}
int WebAXObjectProxy::WordEnd(int character_index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (accessibility_object_.Role() != ax::mojom::Role::kStaticText)
return -1;
int word_start = 0, word_end = 0;
GetBoundariesForOneWord(accessibility_object_, character_index, word_start,
word_end);
return word_end;
}
v8::Local<v8::Object> WebAXObjectProxy::NextOnLine() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject obj = accessibility_object_.NextOnLine();
if (obj.IsNull())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(obj);
}
v8::Local<v8::Object> WebAXObjectProxy::PreviousOnLine() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject obj = accessibility_object_.PreviousOnLine();
if (obj.IsNull())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(obj);
}
std::string WebAXObjectProxy::MisspellingAtIndex(int index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
if (index < 0 || index >= MisspellingsCount())
return std::string();
return GetMisspellings(accessibility_object_)[index];
}
std::string WebAXObjectProxy::Name() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return accessibility_object_.GetName().Utf8();
}
std::string WebAXObjectProxy::NameFrom() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom = ax::mojom::NameFrom::kUninitialized;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
switch (nameFrom) {
case ax::mojom::NameFrom::kUninitialized:
case ax::mojom::NameFrom::kNone:
return "";
case ax::mojom::NameFrom::kAttribute:
return "attribute";
case ax::mojom::NameFrom::kAttributeExplicitlyEmpty:
return "attributeExplicitlyEmpty";
case ax::mojom::NameFrom::kCaption:
return "caption";
case ax::mojom::NameFrom::kContents:
return "contents";
case ax::mojom::NameFrom::kPlaceholder:
return "placeholder";
case ax::mojom::NameFrom::kRelatedElement:
return "relatedElement";
case ax::mojom::NameFrom::kValue:
return "value";
case ax::mojom::NameFrom::kTitle:
return "title";
}
NOTREACHED();
return std::string();
}
int WebAXObjectProxy::NameElementCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
return static_cast<int>(nameObjects.size());
}
v8::Local<v8::Object> WebAXObjectProxy::NameElementAtIndex(unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
if (index >= nameObjects.size())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(nameObjects[index]);
}
std::string WebAXObjectProxy::Description() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
ax::mojom::DescriptionFrom descriptionFrom;
blink::WebVector<blink::WebAXObject> descriptionObjects;
return accessibility_object_
.Description(nameFrom, descriptionFrom, descriptionObjects)
.Utf8();
}
std::string WebAXObjectProxy::DescriptionFrom() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
ax::mojom::DescriptionFrom descriptionFrom =
ax::mojom::DescriptionFrom::kUninitialized;
blink::WebVector<blink::WebAXObject> descriptionObjects;
accessibility_object_.Description(nameFrom, descriptionFrom,
descriptionObjects);
switch (descriptionFrom) {
case ax::mojom::DescriptionFrom::kUninitialized:
case ax::mojom::DescriptionFrom::kNone:
return "";
case ax::mojom::DescriptionFrom::kAttribute:
return "attribute";
case ax::mojom::DescriptionFrom::kContents:
return "contents";
case ax::mojom::DescriptionFrom::kRelatedElement:
return "relatedElement";
case ax::mojom::DescriptionFrom::kTitle:
return "title";
}
NOTREACHED();
return std::string();
}
std::string WebAXObjectProxy::Placeholder() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
return accessibility_object_.Placeholder(nameFrom).Utf8();
}
int WebAXObjectProxy::MisspellingsCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
return GetMisspellings(accessibility_object_).size();
}
int WebAXObjectProxy::DescriptionElementCount() {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
ax::mojom::DescriptionFrom descriptionFrom;
blink::WebVector<blink::WebAXObject> descriptionObjects;
accessibility_object_.Description(nameFrom, descriptionFrom,
descriptionObjects);
return static_cast<int>(descriptionObjects.size());
}
v8::Local<v8::Object> WebAXObjectProxy::DescriptionElementAtIndex(
unsigned index) {
accessibility_object_.UpdateLayoutAndCheckValidity();
ax::mojom::NameFrom nameFrom;
blink::WebVector<blink::WebAXObject> nameObjects;
accessibility_object_.GetName(nameFrom, nameObjects);
ax::mojom::DescriptionFrom descriptionFrom;
blink::WebVector<blink::WebAXObject> descriptionObjects;
accessibility_object_.Description(nameFrom, descriptionFrom,
descriptionObjects);
if (index >= descriptionObjects.size())
return v8::Local<v8::Object>();
return factory_->GetOrCreate(descriptionObjects[index]);
}
v8::Local<v8::Object> WebAXObjectProxy::OffsetContainer() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return factory_->GetOrCreate(container);
}
float WebAXObjectProxy::BoundsInContainerX() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return bounds.x;
}
float WebAXObjectProxy::BoundsInContainerY() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return bounds.y;
}
float WebAXObjectProxy::BoundsInContainerWidth() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return bounds.width;
}
float WebAXObjectProxy::BoundsInContainerHeight() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return bounds.height;
}
bool WebAXObjectProxy::HasNonIdentityTransform() {
accessibility_object_.UpdateLayoutAndCheckValidity();
blink::WebAXObject container;
blink::WebFloatRect bounds;
SkMatrix44 matrix;
accessibility_object_.GetRelativeBounds(container, bounds, matrix);
return !matrix.isIdentity();
}
RootWebAXObjectProxy::RootWebAXObjectProxy(const blink::WebAXObject& object,
Factory* factory)
: WebAXObjectProxy(object, factory) {}
v8::Local<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
if (index)
return v8::Local<v8::Object>();
return factory()->GetOrCreate(accessibility_object());
}
bool RootWebAXObjectProxy::IsRoot() const {
return true;
}
WebAXObjectProxyList::WebAXObjectProxyList()
: elements_(blink::MainThreadIsolate()) {}
WebAXObjectProxyList::~WebAXObjectProxyList() {
Clear();
}
void WebAXObjectProxyList::Clear() {
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
size_t elementCount = elements_.Size();
for (size_t i = 0; i < elementCount; i++) {
WebAXObjectProxy* unwrapped_object = nullptr;
bool result =
gin::ConvertFromV8(isolate, elements_.Get(i), &unwrapped_object);
DCHECK(result);
DCHECK(unwrapped_object);
unwrapped_object->Reset();
}
elements_.Clear();
}
v8::Local<v8::Object> WebAXObjectProxyList::GetOrCreate(
const blink::WebAXObject& object) {
if (object.IsNull())
return v8::Local<v8::Object>();
v8::Isolate* isolate = blink::MainThreadIsolate();
size_t elementCount = elements_.Size();
for (size_t i = 0; i < elementCount; i++) {
WebAXObjectProxy* unwrapped_object = nullptr;
bool result =
gin::ConvertFromV8(isolate, elements_.Get(i), &unwrapped_object);
DCHECK(result);
DCHECK(unwrapped_object);
if (unwrapped_object->IsEqualToObject(object))
return elements_.Get(i);
}
v8::Local<v8::Value> value_handle =
gin::CreateHandle(isolate, new WebAXObjectProxy(object, this)).ToV8();
v8::Local<v8::Object> handle;
if (value_handle.IsEmpty() ||
!value_handle->ToObject(isolate->GetCurrentContext()).ToLocal(&handle)) {
return v8::Local<v8::Object>();
}
elements_.Append(handle);
return handle;
}
} // namespace test_runner