| Index: content/shell/renderer/test_runner/web_ax_object_proxy.cc
|
| diff --git a/content/shell/renderer/test_runner/web_ax_object_proxy.cc b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ee3ea43b71a1194f46866757e151a9b1a17d718d
|
| --- /dev/null
|
| +++ b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
|
| @@ -0,0 +1,1030 @@
|
| +// 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.
|
| +
|
| +// TODO(hajimehoshi): Remove this when UnsafePersistent is removed.
|
| +#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
|
| +
|
| +#include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
|
| +
|
| +#include "base/strings/stringprintf.h"
|
| +#include "gin/handle.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"
|
| +
|
| +namespace content {
|
| +
|
| +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::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::WebAXRoleBanner:
|
| + return result.append("Banner");
|
| + case blink::WebAXRoleBrowser:
|
| + return result.append("Browser");
|
| + case blink::WebAXRoleBusyIndicator:
|
| + return result.append("BusyIndicator");
|
| + case blink::WebAXRoleButton:
|
| + return result.append("Button");
|
| + case blink::WebAXRoleCanvas:
|
| + return result.append("Canvas");
|
| + 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::WebAXRoleDefinition:
|
| + return result.append("Definition");
|
| + case blink::WebAXRoleDescriptionListDetail:
|
| + return result.append("DescriptionListDetail");
|
| + case blink::WebAXRoleDescriptionListTerm:
|
| + return result.append("DescriptionListTerm");
|
| + 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::WebAXRoleDrawer:
|
| + return result.append("Drawer");
|
| + case blink::WebAXRoleEditableText:
|
| + return result.append("EditableText");
|
| + 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::WebAXRoleGrowArea:
|
| + return result.append("GrowArea");
|
| + case blink::WebAXRoleHeading:
|
| + return result.append("Heading");
|
| + case blink::WebAXRoleHelpTag:
|
| + return result.append("HelpTag");
|
| + case blink::WebAXRoleHorizontalRule:
|
| + return result.append("HorizontalRule");
|
| + 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::WebAXRoleIncrementor:
|
| + return result.append("Incrementor");
|
| + case blink::WebAXRoleInlineTextBox:
|
| + return result.append("InlineTextBox");
|
| + case blink::WebAXRoleLabel:
|
| + return result.append("Label");
|
| + case blink::WebAXRoleLegend:
|
| + return result.append("Legend");
|
| + case blink::WebAXRoleLink:
|
| + return result.append("Link");
|
| + 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::WebAXRoleMarquee:
|
| + return result.append("Marquee");
|
| + case blink::WebAXRoleMathElement:
|
| + return result.append("MathElement");
|
| + case blink::WebAXRoleMath:
|
| + return result.append("Math");
|
| + case blink::WebAXRoleMatte:
|
| + return result.append("Matte");
|
| + case blink::WebAXRoleMenuBar:
|
| + return result.append("MenuBar");
|
| + case blink::WebAXRoleMenuButton:
|
| + return result.append("MenuButton");
|
| + case blink::WebAXRoleMenuItem:
|
| + return result.append("MenuItem");
|
| + case blink::WebAXRoleMenuListOption:
|
| + return result.append("MenuListOption");
|
| + case blink::WebAXRoleMenuListPopup:
|
| + return result.append("MenuListPopup");
|
| + case blink::WebAXRoleMenu:
|
| + return result.append("Menu");
|
| + case blink::WebAXRoleNavigation:
|
| + return result.append("Navigation");
|
| + 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::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::WebAXRoleRulerMarker:
|
| + return result.append("RulerMarker");
|
| + 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::WebAXRoleSheet:
|
| + return result.append("Sheet");
|
| + 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::WebAXRoleSplitGroup:
|
| + return result.append("SplitGroup");
|
| + case blink::WebAXRoleSplitter:
|
| + return result.append("Splitter");
|
| + case blink::WebAXRoleStaticText:
|
| + return result.append("StaticText");
|
| + case blink::WebAXRoleStatus:
|
| + return result.append("Status");
|
| + case blink::WebAXRoleSystemWide:
|
| + return result.append("SystemWide");
|
| + 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::WebAXRoleTextArea:
|
| + return result.append("TextArea");
|
| + case blink::WebAXRoleTextField:
|
| + return result.append("TextField");
|
| + 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::WebAXRoleValueIndicator:
|
| + return result.append("ValueIndicator");
|
| + case blink::WebAXRoleWebArea:
|
| + return result.append("WebArea");
|
| + case blink::WebAXRoleWindow:
|
| + return result.append("Window");
|
| + default:
|
| + return result.append("Unknown");
|
| + }
|
| +}
|
| +
|
| +std::string GetDescription(const blink::WebAXObject& object) {
|
| + std::string description = object.accessibilityDescription().utf8();
|
| + return description.insert(0, "AXDescription: ");
|
| +}
|
| +
|
| +std::string GetHelpText(const blink::WebAXObject& object) {
|
| + std::string help_text = object.helpText().utf8();
|
| + return help_text.insert(0, "AXHelp: ");
|
| +}
|
| +
|
| +std::string GetStringValue(const blink::WebAXObject& object) {
|
| + std::string value;
|
| + if (object.role() == blink::WebAXRoleColorWell) {
|
| + int r, g, b;
|
| + object.colorValue(r, g, b);
|
| + value = base::StringPrintf("rgb %7.5f %7.5f %7.5f 1",
|
| + r / 255., g / 255., b / 255.);
|
| + } 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 GetTitle(const blink::WebAXObject& object) {
|
| + std::string title = object.title().utf8();
|
| + return title.insert(0, "AXTitle: ");
|
| +}
|
| +
|
| +std::string GetOrientation(const blink::WebAXObject& object) {
|
| + if (object.isVertical())
|
| + return "AXOrientation: AXVerticalOrientation";
|
| +
|
| + return "AXOrientation: AXHorizontalOrientation";
|
| +}
|
| +
|
| +std::string GetValueDescription(const blink::WebAXObject& object) {
|
| + std::string value_description = object.valueDescription().utf8();
|
| + return value_description.insert(0, "AXValueDescription: ");
|
| +}
|
| +
|
| +std::string GetAttributes(const blink::WebAXObject& object) {
|
| + // FIXME: Concatenate all attributes of the AXObject.
|
| + std::string attributes(GetTitle(object));
|
| + attributes.append("\n");
|
| + attributes.append(GetRole(object));
|
| + attributes.append("\n");
|
| + attributes.append(GetDescription(object));
|
| + return attributes;
|
| +}
|
| +
|
| +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;
|
| + end += inline_text_box.stringValue().length();
|
| + if (end <= characterIndex)
|
| + continue;
|
| + blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect();
|
| + int localIndex = characterIndex - start;
|
| + blink::WebVector<int> character_offsets;
|
| + inline_text_box.characterOffsets(character_offsets);
|
| + DCHECK(character_offsets.size() > 0 &&
|
| + character_offsets.size() == inline_text_box.stringValue().length());
|
| + 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();
|
| +}
|
| +
|
| +void GetBoundariesForOneWord(const blink::WebAXObject& object,
|
| + int character_index,
|
| + int& word_start,
|
| + int& word_end) {
|
| + 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;
|
| + end += inline_text_box.stringValue().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);
|
| +};
|
| +
|
| +} // 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("title", &WebAXObjectProxy::Title)
|
| + .SetProperty("description", &WebAXObjectProxy::Description)
|
| + .SetProperty("helpText", &WebAXObjectProxy::HelpText)
|
| + .SetProperty("stringValue", &WebAXObjectProxy::StringValue)
|
| + .SetProperty("x", &WebAXObjectProxy::X)
|
| + .SetProperty("y", &WebAXObjectProxy::Y)
|
| + .SetProperty("width", &WebAXObjectProxy::Width)
|
| + .SetProperty("height", &WebAXObjectProxy::Height)
|
| + .SetProperty("intValue", &WebAXObjectProxy::IntValue)
|
| + .SetProperty("minValue", &WebAXObjectProxy::MinValue)
|
| + .SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
|
| + .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
|
| + .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
|
| + .SetProperty("insertionPointLineNumber",
|
| + &WebAXObjectProxy::InsertionPointLineNumber)
|
| + .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange)
|
| + .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled)
|
| + .SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
|
| + .SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
|
| + .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
|
| + .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("orientation", &WebAXObjectProxy::Orientation)
|
| + .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
|
| + .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
|
| + .SetProperty("rowCount", &WebAXObjectProxy::RowCount)
|
| + .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
|
| + .SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
|
| + .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
|
| + .SetMethod("attributesOfChildren",
|
| + &WebAXObjectProxy::AttributesOfChildren)
|
| + .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex)
|
| + .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
|
| + .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
|
| + .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
|
| + .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader)
|
| + .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
|
| + .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
|
| + .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
|
| + .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement)
|
| + .SetMethod("setSelectedTextRange",
|
| + &WebAXObjectProxy::SetSelectedTextRange)
|
| + .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("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("wordStart", &WebAXObjectProxy::WordStart)
|
| + .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd)
|
| + // TODO(hajimehoshi): This is for backward compatibility. Remove them.
|
| + .SetMethod("addNotificationListener",
|
| + &WebAXObjectProxy::SetNotificationListener)
|
| + .SetMethod("removeNotificationListener",
|
| + &WebAXObjectProxy::UnsetNotificationListener);
|
| +}
|
| +
|
| +v8::Handle<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::Handle<v8::Context> context = frame->mainWorldScriptContext();
|
| + if (context.IsEmpty())
|
| + return;
|
| +
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| +
|
| + v8::Handle<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);
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::Role() {
|
| + return GetRole(accessibility_object());
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::Title() {
|
| + return GetTitle(accessibility_object());
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::Description() {
|
| + return GetDescription(accessibility_object());
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::HelpText() {
|
| + return GetHelpText(accessibility_object());
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::StringValue() {
|
| + return GetStringValue(accessibility_object());
|
| +}
|
| +
|
| +int WebAXObjectProxy::X() {
|
| + return accessibility_object().boundingBoxRect().x;
|
| +}
|
| +
|
| +int WebAXObjectProxy::Y() {
|
| + return accessibility_object().boundingBoxRect().y;
|
| +}
|
| +
|
| +int WebAXObjectProxy::Width() {
|
| + return accessibility_object().boundingBoxRect().width;
|
| +}
|
| +
|
| +int WebAXObjectProxy::Height() {
|
| + return accessibility_object().boundingBoxRect().height;
|
| +}
|
| +
|
| +int WebAXObjectProxy::IntValue() {
|
| + 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() {
|
| + return accessibility_object().minValueForRange();
|
| +}
|
| +
|
| +int WebAXObjectProxy::MaxValue() {
|
| + return accessibility_object().maxValueForRange();
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::ValueDescription() {
|
| + return GetValueDescription(accessibility_object());
|
| +}
|
| +
|
| +int WebAXObjectProxy::ChildrenCount() {
|
| + int count = 1; // Root object always has only one child, the WebView.
|
| + if (!IsRoot())
|
| + count = accessibility_object().childCount();
|
| + return count;
|
| +}
|
| +
|
| +int WebAXObjectProxy::InsertionPointLineNumber() {
|
| + if (!accessibility_object().isFocused())
|
| + return -1;
|
| + return accessibility_object().selectionEndLineNumber();
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::SelectedTextRange() {
|
| + unsigned selection_start = accessibility_object().selectionStart();
|
| + unsigned selection_end = accessibility_object().selectionEnd();
|
| + return base::StringPrintf("{%d, %d}",
|
| + selection_start, selection_end - selection_start);
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsEnabled() {
|
| + return accessibility_object().isEnabled();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsRequired() {
|
| + return accessibility_object().isRequired();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsFocused() {
|
| + return accessibility_object().isFocused();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsFocusable() {
|
| + return accessibility_object().canSetFocusAttribute();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsSelected() {
|
| + return accessibility_object().isSelected();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsSelectable() {
|
| + return accessibility_object().canSetSelectedAttribute();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsMultiSelectable() {
|
| + return accessibility_object().isMultiSelectable();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsSelectedOptionActive() {
|
| + return accessibility_object().isSelectedOptionActive();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsExpanded() {
|
| + return !accessibility_object().isCollapsed();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsChecked() {
|
| + return accessibility_object().isChecked();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsVisible() {
|
| + return accessibility_object().isVisible();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsOffScreen() {
|
| + return accessibility_object().isOffScreen();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsCollapsed() {
|
| + return accessibility_object().isCollapsed();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::HasPopup() {
|
| + return accessibility_object().ariaHasPopup();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsValid() {
|
| + return !accessibility_object().isDetached();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsReadOnly() {
|
| + return accessibility_object().isReadOnly();
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::Orientation() {
|
| + return GetOrientation(accessibility_object());
|
| +}
|
| +
|
| +int WebAXObjectProxy::ClickPointX() {
|
| + return accessibility_object().clickPoint().x;
|
| +}
|
| +
|
| +int WebAXObjectProxy::ClickPointY() {
|
| + return accessibility_object().clickPoint().y;
|
| +}
|
| +
|
| +int32_t WebAXObjectProxy::RowCount() {
|
| + return static_cast<int32_t>(accessibility_object().rowCount());
|
| +}
|
| +
|
| +int32_t WebAXObjectProxy::ColumnCount() {
|
| + return static_cast<int32_t>(accessibility_object().columnCount());
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsClickable() {
|
| + return accessibility_object().isClickable();
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::AllAttributes() {
|
| + return GetAttributes(accessibility_object());
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::AttributesOfChildren() {
|
| + 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) {
|
| + 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) {
|
| + if (accessibility_object().role() != blink::WebAXRoleStaticText)
|
| + 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::Handle<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
|
| + return GetChildAtIndex(index);
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
|
| + blink::WebPoint point(x, y);
|
| + blink::WebAXObject obj = accessibility_object().hitTest(point);
|
| + if (obj.isNull())
|
| + return v8::Handle<v8::Object>();
|
| +
|
| + return factory_->GetOrCreate(obj);
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxy::TableHeader() {
|
| + blink::WebAXObject obj = accessibility_object().headerContainerObject();
|
| + if (obj.isNull())
|
| + return v8::Handle<v8::Object>();
|
| +
|
| + return factory_->GetOrCreate(obj);
|
| +}
|
| +
|
| +std::string WebAXObjectProxy::RowIndexRange() {
|
| + 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() {
|
| + unsigned column_index = accessibility_object().cellColumnIndex();
|
| + unsigned column_span = accessibility_object().cellColumnSpan();
|
| + return base::StringPrintf("{%d, %d}", column_index, column_span);
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxy::CellForColumnAndRow(
|
| + int column, int row) {
|
| + blink::WebAXObject obj =
|
| + accessibility_object().cellForColumnAndRow(column, row);
|
| + if (obj.isNull())
|
| + return v8::Handle<v8::Object>();
|
| +
|
| + return factory_->GetOrCreate(obj);
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxy::TitleUIElement() {
|
| + blink::WebAXObject obj = accessibility_object().titleUIElement();
|
| + if (obj.isNull())
|
| + return v8::Handle<v8::Object>();
|
| +
|
| + return factory_->GetOrCreate(obj);
|
| +}
|
| +
|
| +void WebAXObjectProxy::SetSelectedTextRange(int selection_start,
|
| + int length) {
|
| + accessibility_object().setSelectedTextRange(selection_start,
|
| + selection_start + length);
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
|
| + bool settable = false;
|
| + if (attribute == "AXValue")
|
| + settable = accessibility_object().canSetValueAttribute();
|
| + return settable;
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsPressActionSupported() {
|
| + return accessibility_object().canPress();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsIncrementActionSupported() {
|
| + return accessibility_object().canIncrement();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsDecrementActionSupported() {
|
| + return accessibility_object().canDecrement();
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxy::ParentElement() {
|
| + 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().increment();
|
| +}
|
| +
|
| +void WebAXObjectProxy::Decrement() {
|
| + accessibility_object().decrement();
|
| +}
|
| +
|
| +void WebAXObjectProxy::ShowMenu() {
|
| +}
|
| +
|
| +void WebAXObjectProxy::Press() {
|
| + accessibility_object().press();
|
| +}
|
| +
|
| +bool WebAXObjectProxy::IsEqual(v8::Handle<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::Handle<v8::Function> callback) {
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| + notification_callback_.Reset(isolate, callback);
|
| +}
|
| +
|
| +void WebAXObjectProxy::UnsetNotificationListener() {
|
| + notification_callback_.Reset();
|
| +}
|
| +
|
| +void WebAXObjectProxy::TakeFocus() {
|
| + accessibility_object().setFocused(true);
|
| +}
|
| +
|
| +void WebAXObjectProxy::ScrollToMakeVisible() {
|
| + accessibility_object().scrollToMakeVisible();
|
| +}
|
| +
|
| +void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y,
|
| + int width, int height) {
|
| + accessibility_object().scrollToMakeVisibleWithSubFocus(
|
| + blink::WebRect(x, y, width, height));
|
| +}
|
| +
|
| +void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
|
| + accessibility_object().scrollToGlobalPoint(blink::WebPoint(x, y));
|
| +}
|
| +
|
| +int WebAXObjectProxy::WordStart(int character_index) {
|
| + if (accessibility_object().role() != blink::WebAXRoleStaticText)
|
| + return -1;
|
| +
|
| + int word_start, word_end;
|
| + GetBoundariesForOneWord(accessibility_object(), character_index,
|
| + word_start, word_end);
|
| + return word_start;
|
| +}
|
| +
|
| +int WebAXObjectProxy::WordEnd(int character_index) {
|
| + if (accessibility_object().role() != blink::WebAXRoleStaticText)
|
| + return -1;
|
| +
|
| + int word_start, word_end;
|
| + GetBoundariesForOneWord(accessibility_object(), character_index,
|
| + word_start, word_end);
|
| + return word_end;
|
| +}
|
| +
|
| +RootWebAXObjectProxy::RootWebAXObjectProxy(
|
| + const blink::WebAXObject &object, Factory *factory)
|
| + : WebAXObjectProxy(object, factory) {
|
| +}
|
| +
|
| +v8::Handle<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
|
| + if (index)
|
| + return v8::Handle<v8::Object>();
|
| +
|
| + return factory()->GetOrCreate(accessibility_object());
|
| +}
|
| +
|
| +bool RootWebAXObjectProxy::IsRoot() const {
|
| + return true;
|
| +}
|
| +
|
| +WebAXObjectProxyList::WebAXObjectProxyList() {
|
| +}
|
| +
|
| +WebAXObjectProxyList::~WebAXObjectProxyList() {
|
| + Clear();
|
| +}
|
| +
|
| +void WebAXObjectProxyList::Clear() {
|
| + for (ElementList::iterator i = elements_.begin(); i != elements_.end(); ++i)
|
| + i->Dispose();
|
| + elements_.clear();
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxyList::GetOrCreate(
|
| + const blink::WebAXObject& object) {
|
| + if (object.isNull())
|
| + return v8::Handle<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_[i].NewLocal(isolate),
|
| + &unwrapped_object);
|
| + DCHECK(result);
|
| + DCHECK(unwrapped_object);
|
| + if (unwrapped_object->IsEqualToObject(object))
|
| + return elements_[i].NewLocal(isolate);
|
| + }
|
| +
|
| + v8::Handle<v8::Value> value_handle = gin::CreateHandle(
|
| + isolate, new WebAXObjectProxy(object, this)).ToV8();
|
| + if (value_handle.IsEmpty())
|
| + return v8::Handle<v8::Object>();
|
| + v8::Handle<v8::Object> handle = value_handle->ToObject();
|
| + UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
|
| + elements_.push_back(unsafe_handle);
|
| + return unsafe_handle.NewLocal(isolate);
|
| +}
|
| +
|
| +v8::Handle<v8::Object> WebAXObjectProxyList::CreateRoot(
|
| + const blink::WebAXObject& object) {
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| + v8::Handle<v8::Value> value_handle = gin::CreateHandle(
|
| + isolate, new RootWebAXObjectProxy(object, this)).ToV8();
|
| + if (value_handle.IsEmpty())
|
| + return v8::Handle<v8::Object>();
|
| + v8::Handle<v8::Object> handle = value_handle->ToObject();
|
| + UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
|
| + elements_.push_back(unsafe_handle);
|
| + return unsafe_handle.NewLocal(isolate);
|
| +}
|
| +
|
| +} // namespace content
|
|
|