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..13788796c3bbdefa4373edb733ac816a2f6c37e8 |
--- /dev/null |
+++ b/content/shell/renderer/test_runner/web_ax_object_proxy.cc |
@@ -0,0 +1,1038 @@ |
+// 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 "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; |
+ char buffer[100]; |
+ object.colorValue(r, g, b); |
+ snprintf(buffer, sizeof(buffer), "rgb %7.5f %7.5f %7.5f 1", |
+ r / 255., g / 255., b / 255.); |
+ value = buffer; |
+ } 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() { |
+ ClearNotificationCallbacks(); |
+} |
+ |
+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("addNotificationListener", |
+ &WebAXObjectProxy::AddNotificationListener) |
+ .SetMethod("removeNotificationListener", |
+ &WebAXObjectProxy::RemoveNotificationListener) |
+ .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus) |
+ .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible) |
+ .SetMethod("scrollToMakeVisibleWithSubFocus", |
+ &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus) |
+ .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint) |
+ .SetMethod("wordStart", &WebAXObjectProxy::WordStart) |
+ .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd); |
+} |
+ |
+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) { |
+ 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()), |
+ }; |
+ for (CallbackList::iterator it = notification_callbacks_.begin(); |
+ it != notification_callbacks_.end(); ++it) { |
+ frame->callFunctionEvenIfScriptDisabled((*it).NewLocal(isolate), |
+ 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(); |
+ char buffer[100]; |
+ snprintf(buffer, sizeof(buffer), "{%d, %d}", |
+ selection_start, selection_end - selection_start); |
+ return std::string(buffer); |
+} |
+ |
+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; |
+ } |
+ |
+ char buffer[100]; |
+ snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}", |
+ bounds.x, bounds.y, bounds.width, bounds.height); |
+ return std::string(buffer); |
+} |
+ |
+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(); |
+ char buffer[100]; |
+ snprintf(buffer, sizeof(buffer), "{%d, %d}", row_index, row_span); |
+ return std::string(buffer); |
+} |
+ |
+std::string WebAXObjectProxy::ColumnIndexRange() { |
+ unsigned column_index = accessibility_object().cellColumnIndex(); |
+ unsigned column_span = accessibility_object().cellColumnSpan(); |
+ char buffer[100]; |
+ snprintf(buffer, sizeof(buffer), "{%d, %d}", column_index, column_span); |
+ return std::string(buffer); |
+} |
+ |
+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::AddNotificationListener( |
+ v8::Handle<v8::Function> callback) { |
+ v8::Isolate* isolate = blink::mainThreadIsolate(); |
+ notification_callbacks_.push_back( |
+ UnsafePersistent<v8::Function>(isolate, callback)); |
+} |
+ |
+void WebAXObjectProxy::RemoveNotificationListener() { |
+ // FIXME: Implement this. |
+} |
+ |
+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; |
+} |
+ |
+void WebAXObjectProxy::ClearNotificationCallbacks() { |
+ for (CallbackList::iterator it = notification_callbacks_.begin(); |
+ it != notification_callbacks_.end(); ++it) { |
+ it->Dispose(); |
+ } |
+ notification_callbacks_.clear(); |
+} |
+ |
+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::Object> handle = gin::CreateHandle( |
+ isolate, new WebAXObjectProxy(object, this)).ToV8()->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::Object> handle = gin::CreateHandle( |
+ isolate, new RootWebAXObjectProxy(object, this)).ToV8()->ToObject(); |
+ UnsafePersistent<v8::Object> unsafe_handle(isolate, handle); |
+ elements_.push_back(unsafe_handle); |
+ return unsafe_handle.NewLocal(isolate); |
+} |
+ |
+} // namespace content |