| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/accessibility/accessibility_node_serializer.h" | 5 #include "content/renderer/accessibility/accessibility_node_serializer.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "third_party/WebKit/public/platform/WebRect.h" | 12 #include "third_party/WebKit/public/platform/WebRect.h" |
| 13 #include "third_party/WebKit/public/platform/WebSize.h" | 13 #include "third_party/WebKit/public/platform/WebSize.h" |
| 14 #include "third_party/WebKit/public/platform/WebString.h" | 14 #include "third_party/WebKit/public/platform/WebString.h" |
| 15 #include "third_party/WebKit/public/platform/WebVector.h" | 15 #include "third_party/WebKit/public/platform/WebVector.h" |
| 16 #include "third_party/WebKit/public/web/WebAXEnums.h" | 16 #include "third_party/WebKit/public/web/WebAXEnums.h" |
| 17 #include "third_party/WebKit/public/web/WebAXObject.h" | 17 #include "third_party/WebKit/public/web/WebAXObject.h" |
| 18 #include "third_party/WebKit/public/web/WebDocument.h" | 18 #include "third_party/WebKit/public/web/WebDocument.h" |
| 19 #include "third_party/WebKit/public/web/WebDocumentType.h" | 19 #include "third_party/WebKit/public/web/WebDocumentType.h" |
| 20 #include "third_party/WebKit/public/web/WebElement.h" | 20 #include "third_party/WebKit/public/web/WebElement.h" |
| 21 #include "third_party/WebKit/public/web/WebFormControlElement.h" | 21 #include "third_party/WebKit/public/web/WebFormControlElement.h" |
| 22 #include "third_party/WebKit/public/web/WebFrame.h" | 22 #include "third_party/WebKit/public/web/WebFrame.h" |
| 23 #include "third_party/WebKit/public/web/WebInputElement.h" | 23 #include "third_party/WebKit/public/web/WebInputElement.h" |
| 24 #include "third_party/WebKit/public/web/WebNode.h" | 24 #include "third_party/WebKit/public/web/WebNode.h" |
| 25 | 25 |
| 26 using WebKit::WebAXObject; | 26 using blink::WebAXObject; |
| 27 using WebKit::WebDocument; | 27 using blink::WebDocument; |
| 28 using WebKit::WebDocumentType; | 28 using blink::WebDocumentType; |
| 29 using WebKit::WebElement; | 29 using blink::WebElement; |
| 30 using WebKit::WebNode; | 30 using blink::WebNode; |
| 31 using WebKit::WebVector; | 31 using blink::WebVector; |
| 32 | 32 |
| 33 namespace content { | 33 namespace content { |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // Returns true if |ancestor| is the first unignored parent of |child|, | 36 // Returns true if |ancestor| is the first unignored parent of |child|, |
| 37 // which means that when walking up the parent chain from |child|, | 37 // which means that when walking up the parent chain from |child|, |
| 38 // |ancestor| is the *first* ancestor that isn't marked as | 38 // |ancestor| is the *first* ancestor that isn't marked as |
| 39 // accessibilityIsIgnored(). | 39 // accessibilityIsIgnored(). |
| 40 bool IsParentUnignoredOf(const WebAXObject& ancestor, | 40 bool IsParentUnignoredOf(const WebAXObject& ancestor, |
| 41 const WebAXObject& child) { | 41 const WebAXObject& child) { |
| 42 WebAXObject parent = child.parentObject(); | 42 WebAXObject parent = child.parentObject(); |
| 43 while (!parent.isDetached() && parent.accessibilityIsIgnored()) | 43 while (!parent.isDetached() && parent.accessibilityIsIgnored()) |
| 44 parent = parent.parentObject(); | 44 parent = parent.parentObject(); |
| 45 return parent.equals(ancestor); | 45 return parent.equals(ancestor); |
| 46 } | 46 } |
| 47 | 47 |
| 48 bool IsTrue(std::string html_value) { | 48 bool IsTrue(std::string html_value) { |
| 49 return LowerCaseEqualsASCII(html_value, "true"); | 49 return LowerCaseEqualsASCII(html_value, "true"); |
| 50 } | 50 } |
| 51 | 51 |
| 52 // Provides a conversion between the WebAXObject state | 52 // Provides a conversion between the WebAXObject state |
| 53 // accessors and a state bitmask that can be serialized and sent to the | 53 // accessors and a state bitmask that can be serialized and sent to the |
| 54 // Browser process. Rare state are sent as boolean attributes instead. | 54 // Browser process. Rare state are sent as boolean attributes instead. |
| 55 uint32 ConvertState(const WebAXObject& o) { | 55 uint32 ConvertState(const WebAXObject& o) { |
| 56 uint32 state = 0; | 56 uint32 state = 0; |
| 57 if (o.isChecked()) | 57 if (o.isChecked()) |
| 58 state |= (1 << WebKit::WebAXStateChecked); | 58 state |= (1 << blink::WebAXStateChecked); |
| 59 | 59 |
| 60 if (o.isCollapsed()) | 60 if (o.isCollapsed()) |
| 61 state |= (1 << WebKit::WebAXStateCollapsed); | 61 state |= (1 << blink::WebAXStateCollapsed); |
| 62 | 62 |
| 63 if (o.canSetFocusAttribute()) | 63 if (o.canSetFocusAttribute()) |
| 64 state |= (1 << WebKit::WebAXStateFocusable); | 64 state |= (1 << blink::WebAXStateFocusable); |
| 65 | 65 |
| 66 if (o.isFocused()) | 66 if (o.isFocused()) |
| 67 state |= (1 << WebKit::WebAXStateFocused); | 67 state |= (1 << blink::WebAXStateFocused); |
| 68 | 68 |
| 69 if (o.role() == WebKit::WebAXRolePopUpButton || | 69 if (o.role() == blink::WebAXRolePopUpButton || |
| 70 o.ariaHasPopup()) { | 70 o.ariaHasPopup()) { |
| 71 state |= (1 << WebKit::WebAXStateHaspopup); | 71 state |= (1 << blink::WebAXStateHaspopup); |
| 72 if (!o.isCollapsed()) | 72 if (!o.isCollapsed()) |
| 73 state |= (1 << WebKit::WebAXStateExpanded); | 73 state |= (1 << blink::WebAXStateExpanded); |
| 74 } | 74 } |
| 75 | 75 |
| 76 if (o.isHovered()) | 76 if (o.isHovered()) |
| 77 state |= (1 << WebKit::WebAXStateHovered); | 77 state |= (1 << blink::WebAXStateHovered); |
| 78 | 78 |
| 79 if (o.isIndeterminate()) | 79 if (o.isIndeterminate()) |
| 80 state |= (1 << WebKit::WebAXStateIndeterminate); | 80 state |= (1 << blink::WebAXStateIndeterminate); |
| 81 | 81 |
| 82 if (!o.isVisible()) | 82 if (!o.isVisible()) |
| 83 state |= (1 << WebKit::WebAXStateInvisible); | 83 state |= (1 << blink::WebAXStateInvisible); |
| 84 | 84 |
| 85 if (o.isLinked()) | 85 if (o.isLinked()) |
| 86 state |= (1 << WebKit::WebAXStateLinked); | 86 state |= (1 << blink::WebAXStateLinked); |
| 87 | 87 |
| 88 if (o.isMultiSelectable()) | 88 if (o.isMultiSelectable()) |
| 89 state |= (1 << WebKit::WebAXStateMultiselectable); | 89 state |= (1 << blink::WebAXStateMultiselectable); |
| 90 | 90 |
| 91 if (o.isOffScreen()) | 91 if (o.isOffScreen()) |
| 92 state |= (1 << WebKit::WebAXStateOffscreen); | 92 state |= (1 << blink::WebAXStateOffscreen); |
| 93 | 93 |
| 94 if (o.isPressed()) | 94 if (o.isPressed()) |
| 95 state |= (1 << WebKit::WebAXStatePressed); | 95 state |= (1 << blink::WebAXStatePressed); |
| 96 | 96 |
| 97 if (o.isPasswordField()) | 97 if (o.isPasswordField()) |
| 98 state |= (1 << WebKit::WebAXStateProtected); | 98 state |= (1 << blink::WebAXStateProtected); |
| 99 | 99 |
| 100 if (o.isReadOnly()) | 100 if (o.isReadOnly()) |
| 101 state |= (1 << WebKit::WebAXStateReadonly); | 101 state |= (1 << blink::WebAXStateReadonly); |
| 102 | 102 |
| 103 if (o.isRequired()) | 103 if (o.isRequired()) |
| 104 state |= (1 << WebKit::WebAXStateRequired); | 104 state |= (1 << blink::WebAXStateRequired); |
| 105 | 105 |
| 106 if (o.canSetSelectedAttribute()) | 106 if (o.canSetSelectedAttribute()) |
| 107 state |= (1 << WebKit::WebAXStateSelectable); | 107 state |= (1 << blink::WebAXStateSelectable); |
| 108 | 108 |
| 109 if (o.isSelected()) | 109 if (o.isSelected()) |
| 110 state |= (1 << WebKit::WebAXStateSelected); | 110 state |= (1 << blink::WebAXStateSelected); |
| 111 | 111 |
| 112 if (o.isVisited()) | 112 if (o.isVisited()) |
| 113 state |= (1 << WebKit::WebAXStateVisited); | 113 state |= (1 << blink::WebAXStateVisited); |
| 114 | 114 |
| 115 if (o.isEnabled()) | 115 if (o.isEnabled()) |
| 116 state |= (1 << WebKit::WebAXStateEnabled); | 116 state |= (1 << blink::WebAXStateEnabled); |
| 117 | 117 |
| 118 if (o.isVertical()) | 118 if (o.isVertical()) |
| 119 state |= (1 << WebKit::WebAXStateVertical); | 119 state |= (1 << blink::WebAXStateVertical); |
| 120 | 120 |
| 121 if (o.isVisited()) | 121 if (o.isVisited()) |
| 122 state |= (1 << WebKit::WebAXStateVisited); | 122 state |= (1 << blink::WebAXStateVisited); |
| 123 | 123 |
| 124 return state; | 124 return state; |
| 125 } | 125 } |
| 126 | 126 |
| 127 } // Anonymous namespace | 127 } // Anonymous namespace |
| 128 | 128 |
| 129 void SerializeAccessibilityNode( | 129 void SerializeAccessibilityNode( |
| 130 const WebAXObject& src, | 130 const WebAXObject& src, |
| 131 AccessibilityNodeData* dst) { | 131 AccessibilityNodeData* dst) { |
| 132 dst->role = src.role(); | 132 dst->role = src.role(); |
| 133 dst->state = ConvertState(src); | 133 dst->state = ConvertState(src); |
| 134 dst->location = src.boundingBoxRect(); | 134 dst->location = src.boundingBoxRect(); |
| 135 dst->id = src.axID(); | 135 dst->id = src.axID(); |
| 136 std::string name = UTF16ToUTF8(src.title()); | 136 std::string name = UTF16ToUTF8(src.title()); |
| 137 | 137 |
| 138 std::string value; | 138 std::string value; |
| 139 if (src.valueDescription().length()) { | 139 if (src.valueDescription().length()) { |
| 140 dst->AddStringAttribute(dst->ATTR_VALUE, | 140 dst->AddStringAttribute(dst->ATTR_VALUE, |
| 141 UTF16ToUTF8(src.valueDescription())); | 141 UTF16ToUTF8(src.valueDescription())); |
| 142 } else { | 142 } else { |
| 143 dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); | 143 dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); |
| 144 } | 144 } |
| 145 | 145 |
| 146 if (dst->role == WebKit::WebAXRoleColorWell) { | 146 if (dst->role == blink::WebAXRoleColorWell) { |
| 147 int r, g, b; | 147 int r, g, b; |
| 148 src.colorValue(r, g, b); | 148 src.colorValue(r, g, b); |
| 149 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); | 149 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); |
| 150 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); | 150 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); |
| 151 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); | 151 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); |
| 152 } | 152 } |
| 153 | 153 |
| 154 if (dst->role == WebKit::WebAXRoleInlineTextBox) { | 154 if (dst->role == blink::WebAXRoleInlineTextBox) { |
| 155 dst->AddIntAttribute(dst->ATTR_TEXT_DIRECTION, src.textDirection()); | 155 dst->AddIntAttribute(dst->ATTR_TEXT_DIRECTION, src.textDirection()); |
| 156 | 156 |
| 157 WebVector<int> src_character_offsets; | 157 WebVector<int> src_character_offsets; |
| 158 src.characterOffsets(src_character_offsets); | 158 src.characterOffsets(src_character_offsets); |
| 159 std::vector<int32> character_offsets; | 159 std::vector<int32> character_offsets; |
| 160 character_offsets.reserve(src_character_offsets.size()); | 160 character_offsets.reserve(src_character_offsets.size()); |
| 161 for (size_t i = 0; i < src_character_offsets.size(); ++i) | 161 for (size_t i = 0; i < src_character_offsets.size(); ++i) |
| 162 character_offsets.push_back(src_character_offsets[i]); | 162 character_offsets.push_back(src_character_offsets[i]); |
| 163 dst->AddIntListAttribute(dst->ATTR_CHARACTER_OFFSETS, character_offsets); | 163 dst->AddIntListAttribute(dst->ATTR_CHARACTER_OFFSETS, character_offsets); |
| 164 | 164 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 dst->AddStringAttribute(dst->ATTR_SHORTCUT, | 201 dst->AddStringAttribute(dst->ATTR_SHORTCUT, |
| 202 UTF16ToUTF8(src.keyboardShortcut())); | 202 UTF16ToUTF8(src.keyboardShortcut())); |
| 203 } | 203 } |
| 204 if (!src.titleUIElement().isDetached()) { | 204 if (!src.titleUIElement().isDetached()) { |
| 205 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, | 205 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, |
| 206 src.titleUIElement().axID()); | 206 src.titleUIElement().axID()); |
| 207 } | 207 } |
| 208 if (!src.url().isEmpty()) | 208 if (!src.url().isEmpty()) |
| 209 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); | 209 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); |
| 210 | 210 |
| 211 if (dst->role == WebKit::WebAXRoleHeading) | 211 if (dst->role == blink::WebAXRoleHeading) |
| 212 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); | 212 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); |
| 213 else if ((dst->role == WebKit::WebAXRoleTreeItem || | 213 else if ((dst->role == blink::WebAXRoleTreeItem || |
| 214 dst->role == WebKit::WebAXRoleRow) && | 214 dst->role == blink::WebAXRoleRow) && |
| 215 src.hierarchicalLevel() > 0) { | 215 src.hierarchicalLevel() > 0) { |
| 216 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); | 216 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); |
| 217 } | 217 } |
| 218 | 218 |
| 219 // Treat the active list box item as focused. | 219 // Treat the active list box item as focused. |
| 220 if (dst->role == WebKit::WebAXRoleListBoxOption && | 220 if (dst->role == blink::WebAXRoleListBoxOption && |
| 221 src.isSelectedOptionActive()) { | 221 src.isSelectedOptionActive()) { |
| 222 dst->state |= (1 << WebKit::WebAXStateFocused); | 222 dst->state |= (1 << blink::WebAXStateFocused); |
| 223 } | 223 } |
| 224 | 224 |
| 225 if (src.canvasHasFallbackContent()) | 225 if (src.canvasHasFallbackContent()) |
| 226 dst->AddBoolAttribute(dst->ATTR_CANVAS_HAS_FALLBACK, true); | 226 dst->AddBoolAttribute(dst->ATTR_CANVAS_HAS_FALLBACK, true); |
| 227 | 227 |
| 228 WebNode node = src.node(); | 228 WebNode node = src.node(); |
| 229 bool is_iframe = false; | 229 bool is_iframe = false; |
| 230 std::string live_atomic; | 230 std::string live_atomic; |
| 231 std::string live_busy; | 231 std::string live_busy; |
| 232 std::string live_status; | 232 std::string live_status; |
| 233 std::string live_relevant; | 233 std::string live_relevant; |
| 234 | 234 |
| 235 if (!node.isNull() && node.isElementNode()) { | 235 if (!node.isNull() && node.isElementNode()) { |
| 236 WebElement element = node.to<WebElement>(); | 236 WebElement element = node.to<WebElement>(); |
| 237 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 237 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
| 238 | 238 |
| 239 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) | 239 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) |
| 240 dst->state |= (1 << WebKit::WebAXStateExpanded); | 240 dst->state |= (1 << blink::WebAXStateExpanded); |
| 241 | 241 |
| 242 // TODO(ctguil): The tagName in WebKit is lower cased but | 242 // TODO(ctguil): The tagName in WebKit is lower cased but |
| 243 // HTMLElement::nodeName calls localNameUpper. Consider adding | 243 // HTMLElement::nodeName calls localNameUpper. Consider adding |
| 244 // a WebElement method that returns the original lower cased tagName. | 244 // a WebElement method that returns the original lower cased tagName. |
| 245 dst->AddStringAttribute( | 245 dst->AddStringAttribute( |
| 246 dst->ATTR_HTML_TAG, | 246 dst->ATTR_HTML_TAG, |
| 247 StringToLowerASCII(UTF16ToUTF8(element.tagName()))); | 247 StringToLowerASCII(UTF16ToUTF8(element.tagName()))); |
| 248 for (unsigned i = 0; i < element.attributeCount(); ++i) { | 248 for (unsigned i = 0; i < element.attributeCount(); ++i) { |
| 249 std::string name = StringToLowerASCII(UTF16ToUTF8( | 249 std::string name = StringToLowerASCII(UTF16ToUTF8( |
| 250 element.attributeLocalName(i))); | 250 element.attributeLocalName(i))); |
| 251 std::string value = UTF16ToUTF8(element.attributeValue(i)); | 251 std::string value = UTF16ToUTF8(element.attributeValue(i)); |
| 252 dst->html_attributes.push_back(std::make_pair(name, value)); | 252 dst->html_attributes.push_back(std::make_pair(name, value)); |
| 253 } | 253 } |
| 254 | 254 |
| 255 if (dst->role == WebKit::WebAXRoleEditableText || | 255 if (dst->role == blink::WebAXRoleEditableText || |
| 256 dst->role == WebKit::WebAXRoleTextArea || | 256 dst->role == blink::WebAXRoleTextArea || |
| 257 dst->role == WebKit::WebAXRoleTextField) { | 257 dst->role == blink::WebAXRoleTextField) { |
| 258 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); | 258 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); |
| 259 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); | 259 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); |
| 260 | 260 |
| 261 WebVector<int> src_line_breaks; | 261 WebVector<int> src_line_breaks; |
| 262 src.lineBreaks(src_line_breaks); | 262 src.lineBreaks(src_line_breaks); |
| 263 if (src_line_breaks.size() > 0) { | 263 if (src_line_breaks.size() > 0) { |
| 264 std::vector<int32> line_breaks; | 264 std::vector<int32> line_breaks; |
| 265 line_breaks.reserve(src_line_breaks.size()); | 265 line_breaks.reserve(src_line_breaks.size()); |
| 266 for (size_t i = 0; i < src_line_breaks.size(); ++i) | 266 for (size_t i = 0; i < src_line_breaks.size(); ++i) |
| 267 line_breaks.push_back(src_line_breaks[i]); | 267 line_breaks.push_back(src_line_breaks[i]); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 } | 335 } |
| 336 if (!container_live_status.empty()) { | 336 if (!container_live_status.empty()) { |
| 337 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_STATUS, | 337 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_STATUS, |
| 338 container_live_status); | 338 container_live_status); |
| 339 } | 339 } |
| 340 if (!container_live_relevant.empty()) { | 340 if (!container_live_relevant.empty()) { |
| 341 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_RELEVANT, | 341 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_RELEVANT, |
| 342 container_live_relevant); | 342 container_live_relevant); |
| 343 } | 343 } |
| 344 | 344 |
| 345 if (dst->role == WebKit::WebAXRoleProgressIndicator || | 345 if (dst->role == blink::WebAXRoleProgressIndicator || |
| 346 dst->role == WebKit::WebAXRoleScrollBar || | 346 dst->role == blink::WebAXRoleScrollBar || |
| 347 dst->role == WebKit::WebAXRoleSlider || | 347 dst->role == blink::WebAXRoleSlider || |
| 348 dst->role == WebKit::WebAXRoleSpinButton) { | 348 dst->role == blink::WebAXRoleSpinButton) { |
| 349 dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); | 349 dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); |
| 350 dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, | 350 dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, |
| 351 src.maxValueForRange()); | 351 src.maxValueForRange()); |
| 352 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, | 352 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, |
| 353 src.minValueForRange()); | 353 src.minValueForRange()); |
| 354 } | 354 } |
| 355 | 355 |
| 356 if (dst->role == WebKit::WebAXRoleDocument || | 356 if (dst->role == blink::WebAXRoleDocument || |
| 357 dst->role == WebKit::WebAXRoleWebArea) { | 357 dst->role == blink::WebAXRoleWebArea) { |
| 358 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); | 358 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); |
| 359 const WebDocument& document = src.document(); | 359 const WebDocument& document = src.document(); |
| 360 if (name.empty()) | 360 if (name.empty()) |
| 361 name = UTF16ToUTF8(document.title()); | 361 name = UTF16ToUTF8(document.title()); |
| 362 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, UTF16ToUTF8(document.title())); | 362 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, UTF16ToUTF8(document.title())); |
| 363 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); | 363 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); |
| 364 dst->AddStringAttribute( | 364 dst->AddStringAttribute( |
| 365 dst->ATTR_DOC_MIMETYPE, | 365 dst->ATTR_DOC_MIMETYPE, |
| 366 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); | 366 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); |
| 367 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); | 367 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 380 | 380 |
| 381 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); | 381 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); |
| 382 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); | 382 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); |
| 383 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); | 383 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); |
| 384 | 384 |
| 385 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); | 385 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); |
| 386 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MAX, max_offset.width()); | 386 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MAX, max_offset.width()); |
| 387 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); | 387 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); |
| 388 } | 388 } |
| 389 | 389 |
| 390 if (dst->role == WebKit::WebAXRoleTable) { | 390 if (dst->role == blink::WebAXRoleTable) { |
| 391 int column_count = src.columnCount(); | 391 int column_count = src.columnCount(); |
| 392 int row_count = src.rowCount(); | 392 int row_count = src.rowCount(); |
| 393 if (column_count > 0 && row_count > 0) { | 393 if (column_count > 0 && row_count > 0) { |
| 394 std::set<int32> unique_cell_id_set; | 394 std::set<int32> unique_cell_id_set; |
| 395 std::vector<int32> cell_ids; | 395 std::vector<int32> cell_ids; |
| 396 std::vector<int32> unique_cell_ids; | 396 std::vector<int32> unique_cell_ids; |
| 397 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_COUNT, column_count); | 397 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_COUNT, column_count); |
| 398 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_COUNT, row_count); | 398 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_COUNT, row_count); |
| 399 WebAXObject header = src.headerContainerObject(); | 399 WebAXObject header = src.headerContainerObject(); |
| 400 if (!header.isDetached()) | 400 if (!header.isDetached()) |
| 401 dst->AddIntAttribute(dst->ATTR_TABLE_HEADER_ID, header.axID()); | 401 dst->AddIntAttribute(dst->ATTR_TABLE_HEADER_ID, header.axID()); |
| 402 for (int i = 0; i < column_count * row_count; ++i) { | 402 for (int i = 0; i < column_count * row_count; ++i) { |
| 403 WebAXObject cell = src.cellForColumnAndRow( | 403 WebAXObject cell = src.cellForColumnAndRow( |
| 404 i % column_count, i / column_count); | 404 i % column_count, i / column_count); |
| 405 int cell_id = -1; | 405 int cell_id = -1; |
| 406 if (!cell.isDetached()) { | 406 if (!cell.isDetached()) { |
| 407 cell_id = cell.axID(); | 407 cell_id = cell.axID(); |
| 408 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { | 408 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { |
| 409 unique_cell_id_set.insert(cell_id); | 409 unique_cell_id_set.insert(cell_id); |
| 410 unique_cell_ids.push_back(cell_id); | 410 unique_cell_ids.push_back(cell_id); |
| 411 } | 411 } |
| 412 } | 412 } |
| 413 cell_ids.push_back(cell_id); | 413 cell_ids.push_back(cell_id); |
| 414 } | 414 } |
| 415 dst->AddIntListAttribute(dst->ATTR_CELL_IDS, cell_ids); | 415 dst->AddIntListAttribute(dst->ATTR_CELL_IDS, cell_ids); |
| 416 dst->AddIntListAttribute(dst->ATTR_UNIQUE_CELL_IDS, unique_cell_ids); | 416 dst->AddIntListAttribute(dst->ATTR_UNIQUE_CELL_IDS, unique_cell_ids); |
| 417 } | 417 } |
| 418 } | 418 } |
| 419 | 419 |
| 420 if (dst->role == WebKit::WebAXRoleRow) { | 420 if (dst->role == blink::WebAXRoleRow) { |
| 421 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); | 421 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); |
| 422 WebAXObject header = src.rowHeader(); | 422 WebAXObject header = src.rowHeader(); |
| 423 if (!header.isDetached()) | 423 if (!header.isDetached()) |
| 424 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); | 424 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); |
| 425 } | 425 } |
| 426 | 426 |
| 427 if (dst->role == WebKit::WebAXRoleColumn) { | 427 if (dst->role == blink::WebAXRoleColumn) { |
| 428 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); | 428 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); |
| 429 WebAXObject header = src.columnHeader(); | 429 WebAXObject header = src.columnHeader(); |
| 430 if (!header.isDetached()) | 430 if (!header.isDetached()) |
| 431 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); | 431 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); |
| 432 } | 432 } |
| 433 | 433 |
| 434 if (dst->role == WebKit::WebAXRoleCell || | 434 if (dst->role == blink::WebAXRoleCell || |
| 435 dst->role == WebKit::WebAXRoleRowHeader || | 435 dst->role == blink::WebAXRoleRowHeader || |
| 436 dst->role == WebKit::WebAXRoleColumnHeader) { | 436 dst->role == blink::WebAXRoleColumnHeader) { |
| 437 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, | 437 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, |
| 438 src.cellColumnIndex()); | 438 src.cellColumnIndex()); |
| 439 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN, | 439 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN, |
| 440 src.cellColumnSpan()); | 440 src.cellColumnSpan()); |
| 441 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex()); | 441 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex()); |
| 442 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); | 442 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); |
| 443 } | 443 } |
| 444 | 444 |
| 445 dst->AddStringAttribute(dst->ATTR_NAME, name); | 445 dst->AddStringAttribute(dst->ATTR_NAME, name); |
| 446 | 446 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 459 dst->AddIntListAttribute( | 459 dst->AddIntListAttribute( |
| 460 dst->ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); | 460 dst->ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); |
| 461 } | 461 } |
| 462 } | 462 } |
| 463 } | 463 } |
| 464 | 464 |
| 465 bool ShouldIncludeChildNode( | 465 bool ShouldIncludeChildNode( |
| 466 const WebAXObject& parent, | 466 const WebAXObject& parent, |
| 467 const WebAXObject& child) { | 467 const WebAXObject& child) { |
| 468 switch(parent.role()) { | 468 switch(parent.role()) { |
| 469 case WebKit::WebAXRoleSlider: | 469 case blink::WebAXRoleSlider: |
| 470 case WebKit::WebAXRoleEditableText: | 470 case blink::WebAXRoleEditableText: |
| 471 case WebKit::WebAXRoleTextArea: | 471 case blink::WebAXRoleTextArea: |
| 472 case WebKit::WebAXRoleTextField: | 472 case blink::WebAXRoleTextField: |
| 473 return false; | 473 return false; |
| 474 default: | 474 default: |
| 475 break; | 475 break; |
| 476 } | 476 } |
| 477 | 477 |
| 478 // The child may be invalid due to issues in webkit accessibility code. | 478 // The child may be invalid due to issues in webkit accessibility code. |
| 479 // Don't add children that are invalid thus preventing a crash. | 479 // Don't add children that are invalid thus preventing a crash. |
| 480 // https://bugs.webkit.org/show_bug.cgi?id=44149 | 480 // https://bugs.webkit.org/show_bug.cgi?id=44149 |
| 481 // TODO(ctguil): We may want to remove this check as webkit stabilizes. | 481 // TODO(ctguil): We may want to remove this check as webkit stabilizes. |
| 482 if (child.isDetached()) | 482 if (child.isDetached()) |
| 483 return false; | 483 return false; |
| 484 | 484 |
| 485 // Skip children whose parent isn't this - see indirect_child_ids, above. | 485 // Skip children whose parent isn't this - see indirect_child_ids, above. |
| 486 // As an exception, include children of an iframe element. | 486 // As an exception, include children of an iframe element. |
| 487 bool is_iframe = false; | 487 bool is_iframe = false; |
| 488 WebNode node = parent.node(); | 488 WebNode node = parent.node(); |
| 489 if (!node.isNull() && node.isElementNode()) { | 489 if (!node.isNull() && node.isElementNode()) { |
| 490 WebElement element = node.to<WebElement>(); | 490 WebElement element = node.to<WebElement>(); |
| 491 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 491 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
| 492 } | 492 } |
| 493 | 493 |
| 494 return (is_iframe || IsParentUnignoredOf(parent, child)); | 494 return (is_iframe || IsParentUnignoredOf(parent, child)); |
| 495 } | 495 } |
| 496 | 496 |
| 497 } // namespace content | 497 } // namespace content |
| OLD | NEW |