| // 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/macros.h" |
| #include "base/strings/stringprintf.h" |
| #include "gin/handle.h" |
| #include "third_party/WebKit/public/platform/WebFloatRect.h" |
| #include "third_party/WebKit/public/platform/WebPoint.h" |
| #include "third_party/WebKit/public/platform/WebRect.h" |
| #include "third_party/WebKit/public/platform/WebString.h" |
| #include "third_party/WebKit/public/web/WebFrame.h" |
| #include "third_party/WebKit/public/web/WebKit.h" |
| #include "third_party/skia/include/core/SkMatrix44.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 layout tests. |
| std::string RoleToString(blink::WebAXRole role) { |
| std::string result = "AXRole: AX"; |
| switch (role) { |
| case blink::WebAXRoleAbbr: |
| return result.append("Abbr"); |
| case blink::WebAXRoleAlertDialog: |
| return result.append("AlertDialog"); |
| case blink::WebAXRoleAlert: |
| return result.append("Alert"); |
| case blink::WebAXRoleAnnotation: |
| return result.append("Annotation"); |
| case blink::WebAXRoleApplication: |
| return result.append("Application"); |
| case blink::WebAXRoleArticle: |
| return result.append("Article"); |
| case blink::WebAXRoleAudio: |
| return result.append("Audio"); |
| case blink::WebAXRoleBanner: |
| return result.append("Banner"); |
| case blink::WebAXRoleBlockquote: |
| return result.append("Blockquote"); |
| case blink::WebAXRoleBusyIndicator: |
| return result.append("BusyIndicator"); |
| case blink::WebAXRoleButton: |
| return result.append("Button"); |
| case blink::WebAXRoleCanvas: |
| return result.append("Canvas"); |
| case blink::WebAXRoleCaption: |
| return result.append("Caption"); |
| case blink::WebAXRoleCell: |
| return result.append("Cell"); |
| case blink::WebAXRoleCheckBox: |
| return result.append("CheckBox"); |
| case blink::WebAXRoleColorWell: |
| return result.append("ColorWell"); |
| case blink::WebAXRoleColumnHeader: |
| return result.append("ColumnHeader"); |
| case blink::WebAXRoleColumn: |
| return result.append("Column"); |
| case blink::WebAXRoleComboBox: |
| return result.append("ComboBox"); |
| case blink::WebAXRoleComplementary: |
| return result.append("Complementary"); |
| case blink::WebAXRoleContentInfo: |
| return result.append("ContentInfo"); |
| case blink::WebAXRoleDate: |
| return result.append("DateField"); |
| case blink::WebAXRoleDateTime: |
| return result.append("DateTimeField"); |
| case blink::WebAXRoleDefinition: |
| return result.append("Definition"); |
| case blink::WebAXRoleDescriptionListDetail: |
| return result.append("DescriptionListDetail"); |
| case blink::WebAXRoleDescriptionList: |
| return result.append("DescriptionList"); |
| case blink::WebAXRoleDescriptionListTerm: |
| return result.append("DescriptionListTerm"); |
| case blink::WebAXRoleDetails: |
| return result.append("Details"); |
| case blink::WebAXRoleDialog: |
| return result.append("Dialog"); |
| case blink::WebAXRoleDirectory: |
| return result.append("Directory"); |
| case blink::WebAXRoleDisclosureTriangle: |
| return result.append("DisclosureTriangle"); |
| case blink::WebAXRoleDiv: |
| return result.append("Div"); |
| case blink::WebAXRoleDocument: |
| return result.append("Document"); |
| case blink::WebAXRoleEmbeddedObject: |
| return result.append("EmbeddedObject"); |
| case blink::WebAXRoleFigcaption: |
| return result.append("Figcaption"); |
| case blink::WebAXRoleFigure: |
| return result.append("Figure"); |
| case blink::WebAXRoleFooter: |
| return result.append("Footer"); |
| case blink::WebAXRoleForm: |
| return result.append("Form"); |
| case blink::WebAXRoleGrid: |
| return result.append("Grid"); |
| case blink::WebAXRoleGroup: |
| return result.append("Group"); |
| case blink::WebAXRoleHeading: |
| return result.append("Heading"); |
| case blink::WebAXRoleIgnored: |
| return result.append("Ignored"); |
| case blink::WebAXRoleImageMapLink: |
| return result.append("ImageMapLink"); |
| case blink::WebAXRoleImageMap: |
| return result.append("ImageMap"); |
| case blink::WebAXRoleImage: |
| return result.append("Image"); |
| case blink::WebAXRoleInlineTextBox: |
| return result.append("InlineTextBox"); |
| case blink::WebAXRoleInputTime: |
| return result.append("InputTime"); |
| case blink::WebAXRoleLabel: |
| return result.append("Label"); |
| case blink::WebAXRoleLegend: |
| return result.append("Legend"); |
| case blink::WebAXRoleLink: |
| return result.append("Link"); |
| case blink::WebAXRoleLineBreak: |
| return result.append("LineBreak"); |
| case blink::WebAXRoleListBoxOption: |
| return result.append("ListBoxOption"); |
| case blink::WebAXRoleListBox: |
| return result.append("ListBox"); |
| case blink::WebAXRoleListItem: |
| return result.append("ListItem"); |
| case blink::WebAXRoleListMarker: |
| return result.append("ListMarker"); |
| case blink::WebAXRoleList: |
| return result.append("List"); |
| case blink::WebAXRoleLog: |
| return result.append("Log"); |
| case blink::WebAXRoleMain: |
| return result.append("Main"); |
| case blink::WebAXRoleMark: |
| return result.append("Mark"); |
| case blink::WebAXRoleMarquee: |
| return result.append("Marquee"); |
| case blink::WebAXRoleMath: |
| return result.append("Math"); |
| case blink::WebAXRoleMenuBar: |
| return result.append("MenuBar"); |
| case blink::WebAXRoleMenuButton: |
| return result.append("MenuButton"); |
| case blink::WebAXRoleMenuItem: |
| return result.append("MenuItem"); |
| case blink::WebAXRoleMenuItemCheckBox: |
| return result.append("MenuItemCheckBox"); |
| case blink::WebAXRoleMenuItemRadio: |
| return result.append("MenuItemRadio"); |
| case blink::WebAXRoleMenuListOption: |
| return result.append("MenuListOption"); |
| case blink::WebAXRoleMenuListPopup: |
| return result.append("MenuListPopup"); |
| case blink::WebAXRoleMenu: |
| return result.append("Menu"); |
| case blink::WebAXRoleMeter: |
| return result.append("Meter"); |
| case blink::WebAXRoleNavigation: |
| return result.append("Navigation"); |
| case blink::WebAXRoleNone: |
| return result.append("None"); |
| case blink::WebAXRoleNote: |
| return result.append("Note"); |
| case blink::WebAXRoleOutline: |
| return result.append("Outline"); |
| case blink::WebAXRoleParagraph: |
| return result.append("Paragraph"); |
| case blink::WebAXRolePopUpButton: |
| return result.append("PopUpButton"); |
| case blink::WebAXRolePre: |
| return result.append("Pre"); |
| case blink::WebAXRolePresentational: |
| return result.append("Presentational"); |
| case blink::WebAXRoleProgressIndicator: |
| return result.append("ProgressIndicator"); |
| case blink::WebAXRoleRadioButton: |
| return result.append("RadioButton"); |
| case blink::WebAXRoleRadioGroup: |
| return result.append("RadioGroup"); |
| case blink::WebAXRoleRegion: |
| return result.append("Region"); |
| case blink::WebAXRoleRootWebArea: |
| return result.append("RootWebArea"); |
| case blink::WebAXRoleRowHeader: |
| return result.append("RowHeader"); |
| case blink::WebAXRoleRow: |
| return result.append("Row"); |
| case blink::WebAXRoleRuby: |
| return result.append("Ruby"); |
| case blink::WebAXRoleRuler: |
| return result.append("Ruler"); |
| case blink::WebAXRoleSVGRoot: |
| return result.append("SVGRoot"); |
| case blink::WebAXRoleScrollArea: |
| return result.append("ScrollArea"); |
| case blink::WebAXRoleScrollBar: |
| return result.append("ScrollBar"); |
| case blink::WebAXRoleSeamlessWebArea: |
| return result.append("SeamlessWebArea"); |
| case blink::WebAXRoleSearch: |
| return result.append("Search"); |
| case blink::WebAXRoleSearchBox: |
| return result.append("SearchBox"); |
| case blink::WebAXRoleSlider: |
| return result.append("Slider"); |
| case blink::WebAXRoleSliderThumb: |
| return result.append("SliderThumb"); |
| case blink::WebAXRoleSpinButtonPart: |
| return result.append("SpinButtonPart"); |
| case blink::WebAXRoleSpinButton: |
| return result.append("SpinButton"); |
| case blink::WebAXRoleSplitter: |
| return result.append("Splitter"); |
| case blink::WebAXRoleStaticText: |
| return result.append("StaticText"); |
| case blink::WebAXRoleStatus: |
| return result.append("Status"); |
| case blink::WebAXRoleSwitch: |
| return result.append("Switch"); |
| case blink::WebAXRoleTabGroup: |
| return result.append("TabGroup"); |
| case blink::WebAXRoleTabList: |
| return result.append("TabList"); |
| case blink::WebAXRoleTabPanel: |
| return result.append("TabPanel"); |
| case blink::WebAXRoleTab: |
| return result.append("Tab"); |
| case blink::WebAXRoleTableHeaderContainer: |
| return result.append("TableHeaderContainer"); |
| case blink::WebAXRoleTable: |
| return result.append("Table"); |
| case blink::WebAXRoleTextField: |
| return result.append("TextField"); |
| case blink::WebAXRoleTime: |
| return result.append("Time"); |
| case blink::WebAXRoleTimer: |
| return result.append("Timer"); |
| case blink::WebAXRoleToggleButton: |
| return result.append("ToggleButton"); |
| case blink::WebAXRoleToolbar: |
| return result.append("Toolbar"); |
| case blink::WebAXRoleTreeGrid: |
| return result.append("TreeGrid"); |
| case blink::WebAXRoleTreeItem: |
| return result.append("TreeItem"); |
| case blink::WebAXRoleTree: |
| return result.append("Tree"); |
| case blink::WebAXRoleUnknown: |
| return result.append("Unknown"); |
| case blink::WebAXRoleUserInterfaceTooltip: |
| return result.append("UserInterfaceTooltip"); |
| case blink::WebAXRoleVideo: |
| return result.append("Video"); |
| case blink::WebAXRoleWebArea: |
| return result.append("WebArea"); |
| case blink::WebAXRoleWindow: |
| return result.append("Window"); |
| default: |
| return result.append("Unknown"); |
| } |
| } |
| |
| std::string GetStringValue(const blink::WebAXObject& object) { |
| std::string value; |
| if (object.role() == blink::WebAXRoleColorWell) { |
| 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() == blink::WebAXRoleCanvas && |
| 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.name().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(), blink::WebAXRoleStaticText); |
| 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(), blink::WebAXRoleInlineTextBox); |
| int start = end; |
| blink::WebString name = inline_text_box.name(); |
| 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.textDirection()) { |
| case blink::WebAXTextDirectionLR: { |
| 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 blink::WebAXTextDirectionRL: { |
| 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 blink::WebAXTextDirectionTB: { |
| 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 blink::WebAXTextDirectionBT: { |
| 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]); |
| } |
| } |
| } |
| |
| DCHECK(false); |
| return blink::WebRect(); |
| } |
| |
| std::vector<std::string> GetMisspellings(blink::WebAXObject& object) { |
| std::vector<std::string> misspellings; |
| std::string text(object.name().utf8()); |
| |
| blink::WebVector<blink::WebAXMarkerType> 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] & blink::WebAXMarkerTypeSpelling) { |
| 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(), blink::WebAXRoleInlineTextBox); |
| int start = end; |
| blink::WebString name = inline_text_box.name(); |
| end += name.length(); |
| if (end <= character_index) |
| continue; |
| int localIndex = character_index - start; |
| |
| blink::WebVector<int> starts; |
| blink::WebVector<int> ends; |
| inline_text_box.wordBoundaries(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::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 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("valueDescription", &WebAXObjectProxy::ValueDescription) |
| .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount) |
| .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("selectionStart", &WebAXObjectProxy::SelectionStart) |
| .SetProperty("selectionEnd", &WebAXObjectProxy::SelectionEnd) |
| .SetProperty("selectionStartLineNumber", |
| &WebAXObjectProxy::SelectionStartLineNumber) |
| .SetProperty("selectionEndLineNumber", |
| &WebAXObjectProxy::SelectionEndLineNumber) |
| .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled) |
| .SetProperty("isRequired", &WebAXObjectProxy::IsRequired) |
| .SetProperty("isEditable", &WebAXObjectProxy::IsEditable) |
| .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("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable) |
| .SetProperty("isSelectedOptionActive", |
| &WebAXObjectProxy::IsSelectedOptionActive) |
| .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded) |
| .SetProperty("isChecked", &WebAXObjectProxy::IsChecked) |
| .SetProperty("isVisible", &WebAXObjectProxy::IsVisible) |
| .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen) |
| .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed) |
| .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup) |
| .SetProperty("isValid", &WebAXObjectProxy::IsValid) |
| .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly) |
| .SetProperty("backgroundColor", &WebAXObjectProxy::BackgroundColor) |
| .SetProperty("color", &WebAXObjectProxy::Color) |
| .SetProperty("colorValue", &WebAXObjectProxy::ColorValue) |
| .SetProperty("fontFamily", &WebAXObjectProxy::FontFamily) |
| .SetProperty("fontSize", &WebAXObjectProxy::FontSize) |
| .SetProperty("orientation", &WebAXObjectProxy::Orientation) |
| .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) |
| .SetProperty("isButtonStateMixed", &WebAXObjectProxy::IsButtonStateMixed) |
| // |
| // 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("ariaControlsElementAtIndex", |
| &WebAXObjectProxy::AriaControlsElementAtIndex) |
| .SetMethod("ariaFlowToElementAtIndex", |
| &WebAXObjectProxy::AriaFlowToElementAtIndex) |
| .SetMethod("ariaOwnsElementAtIndex", |
| &WebAXObjectProxy::AriaOwnsElementAtIndex) |
| .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex) |
| .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange) |
| .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex) |
| .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint) |
| .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader) |
| .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("isIncrementActionSupported", |
| &WebAXObjectProxy::IsIncrementActionSupported) |
| .SetMethod("isDecrementActionSupported", |
| &WebAXObjectProxy::IsDecrementActionSupported) |
| .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("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::WebFrame* 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::String::kNormalString, |
| notification_name.size()), |
| }; |
| frame->callFunctionEvenIfScriptDisabled( |
| v8::Local<v8::Function>::New(isolate, notification_callback_), |
| context->Global(), arraysize(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()) |
| return accessibility_object_.valueForRange(); |
| else if (accessibility_object_.role() == blink::WebAXRoleHeading) |
| return accessibility_object_.headingLevel(); |
| else |
| return atoi(accessibility_object_.stringValue().utf8().data()); |
| } |
| |
| int WebAXObjectProxy::MinValue() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.minValueForRange(); |
| } |
| |
| int WebAXObjectProxy::MaxValue() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.maxValueForRange(); |
| } |
| |
| 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; |
| } |
| |
| v8::Local<v8::Value> WebAXObjectProxy::SelectionAnchorObject() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| if (anchorObject.isNull()) |
| return v8::Null(blink::mainThreadIsolate()); |
| |
| return factory_->GetOrCreate(anchorObject); |
| } |
| |
| int WebAXObjectProxy::SelectionAnchorOffset() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| if (anchorOffset < 0) |
| return -1; |
| |
| return anchorOffset; |
| } |
| |
| std::string WebAXObjectProxy::SelectionAnchorAffinity() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| return anchorAffinity == blink::WebAXTextAffinityUpstream ? "upstream" |
| : "downstream"; |
| } |
| |
| v8::Local<v8::Value> WebAXObjectProxy::SelectionFocusObject() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| if (focusObject.isNull()) |
| return v8::Null(blink::mainThreadIsolate()); |
| |
| return factory_->GetOrCreate(focusObject); |
| } |
| |
| int WebAXObjectProxy::SelectionFocusOffset() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| if (focusOffset < 0) |
| return -1; |
| |
| return focusOffset; |
| } |
| |
| std::string WebAXObjectProxy::SelectionFocusAffinity() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| |
| blink::WebAXObject anchorObject; |
| int anchorOffset = -1; |
| blink::WebAXTextAffinity anchorAffinity; |
| blink::WebAXObject focusObject; |
| int focusOffset = -1; |
| blink::WebAXTextAffinity focusAffinity; |
| accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, |
| focusObject, focusOffset, focusAffinity); |
| return focusAffinity == blink::WebAXTextAffinityUpstream ? "upstream" |
| : "downstream"; |
| } |
| |
| int WebAXObjectProxy::SelectionStart() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.selectionStart(); |
| } |
| |
| int WebAXObjectProxy::SelectionEnd() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.selectionEnd(); |
| } |
| |
| int WebAXObjectProxy::SelectionStartLineNumber() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.selectionStartLineNumber(); |
| } |
| |
| int WebAXObjectProxy::SelectionEndLineNumber() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.selectionEndLineNumber(); |
| } |
| |
| bool WebAXObjectProxy::IsEnabled() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isEnabled(); |
| } |
| |
| bool WebAXObjectProxy::IsRequired() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isRequired(); |
| } |
| |
| 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(); |
| } |
| |
| bool WebAXObjectProxy::IsSelectable() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.canSetSelectedAttribute(); |
| } |
| |
| 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::WebAXExpandedExpanded; |
| } |
| |
| bool WebAXObjectProxy::IsChecked() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isChecked(); |
| } |
| |
| bool WebAXObjectProxy::IsCollapsed() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isExpanded() == blink::WebAXExpandedCollapsed; |
| } |
| |
| bool WebAXObjectProxy::IsVisible() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isVisible(); |
| } |
| |
| bool WebAXObjectProxy::IsOffScreen() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isOffScreen(); |
| } |
| |
| bool WebAXObjectProxy::HasPopup() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.ariaHasPopup(); |
| } |
| |
| bool WebAXObjectProxy::IsValid() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return !accessibility_object_.isDetached(); |
| } |
| |
| bool WebAXObjectProxy::IsReadOnly() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isReadOnly(); |
| } |
| |
| unsigned int WebAXObjectProxy::BackgroundColor() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.backgroundColor(); |
| } |
| |
| unsigned int WebAXObjectProxy::Color() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| unsigned int color = accessibility_object_.color(); |
| // 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::Orientation() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| if (accessibility_object_.orientation() == blink::WebAXOrientationVertical) |
| return "AXOrientation: AXVerticalOrientation"; |
| else if (accessibility_object_.orientation() == |
| blink::WebAXOrientationHorizontal) |
| return "AXOrientation: AXHorizontalOrientation"; |
| |
| return std::string(); |
| } |
| |
| 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(); |
| } |
| |
| bool WebAXObjectProxy::IsButtonStateMixed() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.isButtonStateMixed(); |
| } |
| |
| 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::AriaControls]; |
| size_t elementCount = elements.size(); |
| if (index >= elementCount) |
| return v8::Local<v8::Object>(); |
| |
| return factory_->GetOrCreate(elements[index]); |
| } |
| |
| 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::AriaFlowTo]; |
| 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(); |
| } |
| |
| int WebAXObjectProxy::LineForIndex(int index) { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebVector<int> line_breaks; |
| accessibility_object_.lineBreaks(line_breaks); |
| int line = 0; |
| int vector_size = static_cast<int>(line_breaks.size()); |
| while (line < vector_size && line_breaks[line] <= index) |
| line++; |
| return line; |
| } |
| |
| std::string WebAXObjectProxy::BoundsForRange(int start, int end) { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| if (accessibility_object_.role() != blink::WebAXRoleStaticText) |
| 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::TableHeader() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXObject obj = accessibility_object_.headerContainerObject(); |
| 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_.setSelectedTextRange(selection_start, |
| selection_start + length); |
| } |
| |
| void 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; |
| } |
| |
| WebAXObjectProxy* web_ax_anchor = nullptr; |
| if (!gin::ConvertFromV8(blink::mainThreadIsolate(), anchor_object, |
| &web_ax_anchor)) { |
| return; |
| } |
| DCHECK(web_ax_anchor); |
| |
| WebAXObjectProxy* web_ax_focus = nullptr; |
| if (!gin::ConvertFromV8(blink::mainThreadIsolate(), focus_object, |
| &web_ax_focus)) { |
| return; |
| } |
| DCHECK(web_ax_focus); |
| |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| 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(); |
| } |
| |
| bool WebAXObjectProxy::IsIncrementActionSupported() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.canIncrement(); |
| } |
| |
| bool WebAXObjectProxy::IsDecrementActionSupported() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| return accessibility_object_.canDecrement(); |
| } |
| |
| v8::Local<v8::Object> WebAXObjectProxy::ParentElement() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXObject parent_object = accessibility_object_.parentObject(); |
| while (parent_object.accessibilityIsIgnored()) |
| 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_.press(); |
| } |
| |
| bool WebAXObjectProxy::SetValue(const std::string& value) { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| if (!accessibility_object_.canSetValueAttribute()) |
| return false; |
| |
| accessibility_object_.setValue(blink::WebString::fromUTF8(value)); |
| return true; |
| } |
| |
| bool WebAXObjectProxy::IsEqual(v8::Local<v8::Object> proxy) { |
| WebAXObjectProxy* unwrapped_proxy = NULL; |
| 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_.setFocused(true); |
| } |
| |
| 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; |
| } |
| |
| 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() != blink::WebAXRoleStaticText) |
| 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() != blink::WebAXRoleStaticText) |
| 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_.name().utf8(); |
| } |
| |
| std::string WebAXObjectProxy::NameFrom() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom = blink::WebAXNameFromUninitialized; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| switch (nameFrom) { |
| case blink::WebAXNameFromUninitialized: |
| return ""; |
| case blink::WebAXNameFromAttribute: |
| return "attribute"; |
| case blink::WebAXNameFromCaption: |
| return "caption"; |
| case blink::WebAXNameFromContents: |
| return "contents"; |
| case blink::WebAXNameFromPlaceholder: |
| return "placeholder"; |
| case blink::WebAXNameFromRelatedElement: |
| return "relatedElement"; |
| case blink::WebAXNameFromValue: |
| return "value"; |
| case blink::WebAXNameFromTitle: |
| return "title"; |
| } |
| |
| NOTREACHED(); |
| return std::string(); |
| } |
| |
| int WebAXObjectProxy::NameElementCount() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| return static_cast<int>(nameObjects.size()); |
| } |
| |
| v8::Local<v8::Object> WebAXObjectProxy::NameElementAtIndex(unsigned index) { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| if (index >= nameObjects.size()) |
| return v8::Local<v8::Object>(); |
| return factory_->GetOrCreate(nameObjects[index]); |
| } |
| |
| std::string WebAXObjectProxy::Description() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| blink::WebAXDescriptionFrom descriptionFrom; |
| blink::WebVector<blink::WebAXObject> descriptionObjects; |
| return accessibility_object_ |
| .description(nameFrom, descriptionFrom, descriptionObjects) |
| .utf8(); |
| } |
| |
| std::string WebAXObjectProxy::DescriptionFrom() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| blink::WebAXDescriptionFrom descriptionFrom = |
| blink::WebAXDescriptionFromUninitialized; |
| blink::WebVector<blink::WebAXObject> descriptionObjects; |
| accessibility_object_.description(nameFrom, descriptionFrom, |
| descriptionObjects); |
| switch (descriptionFrom) { |
| case blink::WebAXDescriptionFromUninitialized: |
| return ""; |
| case blink::WebAXDescriptionFromAttribute: |
| return "attribute"; |
| case blink::WebAXDescriptionFromContents: |
| return "contents"; |
| case blink::WebAXDescriptionFromRelatedElement: |
| return "relatedElement"; |
| } |
| |
| NOTREACHED(); |
| return std::string(); |
| } |
| |
| std::string WebAXObjectProxy::Placeholder() { |
| accessibility_object_.updateLayoutAndCheckValidity(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(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(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| blink::WebAXDescriptionFrom 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(); |
| blink::WebAXNameFrom nameFrom; |
| blink::WebVector<blink::WebAXObject> nameObjects; |
| accessibility_object_.name(nameFrom, nameObjects); |
| blink::WebAXDescriptionFrom 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(); |
| 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 = NULL; |
| 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 = NULL; |
| 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(); |
| if (value_handle.IsEmpty()) |
| return v8::Local<v8::Object>(); |
| v8::Local<v8::Object> handle = value_handle->ToObject(isolate); |
| elements_.Append(handle); |
| return handle; |
| } |
| |
| } // namespace test_runner |