| Index: content/renderer/accessibility/blink_ax_tree_source.cc
|
| diff --git a/content/renderer/accessibility/accessibility_node_serializer.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
|
| similarity index 81%
|
| rename from content/renderer/accessibility/accessibility_node_serializer.cc
|
| rename to content/renderer/accessibility/blink_ax_tree_source.cc
|
| index 56f977fce9e27388648a76bd9de3365096f5d8ef..c6db99fa4f7dd717a225179cbfafdf2b9683896e 100644
|
| --- a/content/renderer/accessibility/accessibility_node_serializer.cc
|
| +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
|
| @@ -1,8 +1,8 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/renderer/accessibility/accessibility_node_serializer.h"
|
| +#include "content/renderer/accessibility/blink_ax_tree_source.h"
|
|
|
| #include <set>
|
|
|
| @@ -10,6 +10,7 @@
|
| #include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "content/renderer/accessibility/blink_ax_enum_conversion.h"
|
| +#include "content/renderer/render_view_impl.h"
|
| #include "third_party/WebKit/public/platform/WebRect.h"
|
| #include "third_party/WebKit/public/platform/WebSize.h"
|
| #include "third_party/WebKit/public/platform/WebString.h"
|
| @@ -23,31 +24,36 @@
|
| #include "third_party/WebKit/public/web/WebFrame.h"
|
| #include "third_party/WebKit/public/web/WebInputElement.h"
|
| #include "third_party/WebKit/public/web/WebNode.h"
|
| +#include "third_party/WebKit/public/web/WebView.h"
|
|
|
| +using base::ASCIIToUTF16;
|
| using base::UTF16ToUTF8;
|
| using blink::WebAXObject;
|
| using blink::WebDocument;
|
| using blink::WebDocumentType;
|
| using blink::WebElement;
|
| +using blink::WebFrame;
|
| using blink::WebNode;
|
| using blink::WebVector;
|
| +using blink::WebView;
|
|
|
| namespace content {
|
| +
|
| namespace {
|
|
|
| // Returns true if |ancestor| is the first unignored parent of |child|,
|
| // which means that when walking up the parent chain from |child|,
|
| // |ancestor| is the *first* ancestor that isn't marked as
|
| // accessibilityIsIgnored().
|
| -bool IsParentUnignoredOf(const WebAXObject& ancestor,
|
| - const WebAXObject& child) {
|
| +bool IsParentUnignoredOf(WebAXObject ancestor,
|
| + WebAXObject child) {
|
| WebAXObject parent = child.parentObject();
|
| while (!parent.isDetached() && parent.accessibilityIsIgnored())
|
| parent = parent.parentObject();
|
| return parent.equals(ancestor);
|
| }
|
|
|
| - bool IsTrue(std::string html_value) {
|
| +bool IsTrue(std::string html_value) {
|
| return LowerCaseEqualsASCII(html_value, "true");
|
| }
|
|
|
| @@ -85,17 +91,88 @@ void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
|
| dst->AddIntListAttribute(attr, ids);
|
| }
|
|
|
| -
|
| } // Anonymous namespace
|
|
|
| -void SerializeAccessibilityNode(
|
| - const WebAXObject& src,
|
| - ui::AXNodeData* dst) {
|
| +BlinkAXTreeSource::BlinkAXTreeSource(RenderViewImpl* render_view)
|
| + : render_view_(render_view) {
|
| +}
|
| +
|
| +BlinkAXTreeSource::~BlinkAXTreeSource() {
|
| +}
|
| +
|
| +blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
|
| + return GetMainDocument().accessibilityObject();
|
| +}
|
| +
|
| +blink::WebAXObject BlinkAXTreeSource::GetFromId(int32 id) const {
|
| + return GetMainDocument().accessibilityObjectFromID(id);
|
| +}
|
| +
|
| +int32 BlinkAXTreeSource::GetId(blink::WebAXObject node) const {
|
| + return node.axID();
|
| +}
|
| +
|
| +void BlinkAXTreeSource::GetChildren(
|
| + blink::WebAXObject parent,
|
| + std::vector<blink::WebAXObject>* out_children) const {
|
| + bool is_iframe = false;
|
| + WebNode node = parent.node();
|
| + if (!node.isNull() && node.isElementNode()) {
|
| + WebElement element = node.to<WebElement>();
|
| + is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME"));
|
| + }
|
| +
|
| + for (unsigned i = 0; i < parent.childCount(); i++) {
|
| + blink::WebAXObject child = parent.childAt(i);
|
| +
|
| + // The child may be invalid due to issues in blink accessibility code.
|
| + if (child.isDetached())
|
| + continue;
|
| +
|
| + // Skip children whose parent isn't |parent|.
|
| + // As an exception, include children of an iframe element.
|
| + if (!is_iframe && !IsParentUnignoredOf(parent, child))
|
| + continue;
|
| +
|
| + out_children->push_back(child);
|
| + }
|
| +}
|
| +
|
| +blink::WebAXObject BlinkAXTreeSource::GetParent(
|
| + blink::WebAXObject node) const {
|
| + // Blink returns ignored objects when walking up the parent chain,
|
| + // we have to skip those here. Also, stop when we get to the root
|
| + // element.
|
| + blink::WebAXObject root = GetRoot();
|
| + do {
|
| + if (node.equals(root))
|
| + return blink::WebAXObject();
|
| + node = node.parentObject();
|
| + } while (!node.isDetached() && node.accessibilityIsIgnored());
|
| +
|
| + return node;
|
| +}
|
| +
|
| +bool BlinkAXTreeSource::IsValid(blink::WebAXObject node) const {
|
| + return !node.isDetached(); // This also checks if it's null.
|
| +}
|
| +
|
| +bool BlinkAXTreeSource::IsEqual(blink::WebAXObject node1,
|
| + blink::WebAXObject node2) const {
|
| + return node1.equals(node2);
|
| +}
|
| +
|
| +blink::WebAXObject BlinkAXTreeSource::GetNull() const {
|
| + return blink::WebAXObject();
|
| +}
|
| +
|
| +void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
|
| + ui::AXNodeData* dst) const {
|
| dst->role = AXRoleFromBlink(src.role());
|
| dst->state = AXStateFromBlink(src);
|
| dst->location = src.boundingBoxRect();
|
| dst->id = src.axID();
|
| - std::string name = base::UTF16ToUTF8(src.title());
|
| + std::string name = UTF16ToUTF8(src.title());
|
|
|
| std::string value;
|
| if (src.valueDescription().length()) {
|
| @@ -140,9 +217,10 @@ void SerializeAccessibilityNode(
|
| dst->AddIntListAttribute(ui::AX_ATTR_WORD_ENDS, word_ends);
|
| }
|
|
|
| - if (src.accessKey().length())
|
| + if (src.accessKey().length()) {
|
| dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY,
|
| - UTF16ToUTF8(src.accessKey()));
|
| + UTF16ToUTF8(src.accessKey()));
|
| + }
|
| if (src.actionVerb().length())
|
| dst->AddStringAttribute(ui::AX_ATTR_ACTION, UTF16ToUTF8(src.actionVerb()));
|
| if (src.isAriaReadOnly())
|
| @@ -183,7 +261,7 @@ void SerializeAccessibilityNode(
|
| dst->role == ui::AX_ROLE_ROW) &&
|
| src.hierarchicalLevel() > 0) {
|
| dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL,
|
| - src.hierarchicalLevel());
|
| + src.hierarchicalLevel());
|
| }
|
|
|
| // Treat the active list box item as focused.
|
| @@ -204,7 +282,7 @@ void SerializeAccessibilityNode(
|
|
|
| if (!node.isNull() && node.isElementNode()) {
|
| WebElement element = node.to<WebElement>();
|
| - is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME"));
|
| + is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME"));
|
|
|
| if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true"))
|
| dst->state |= (1 << ui::AX_STATE_EXPANDED);
|
| @@ -216,9 +294,9 @@ void SerializeAccessibilityNode(
|
| ui::AX_ATTR_HTML_TAG,
|
| StringToLowerASCII(UTF16ToUTF8(element.tagName())));
|
| for (unsigned i = 0; i < element.attributeCount(); ++i) {
|
| - std::string name = StringToLowerASCII(base::UTF16ToUTF8(
|
| + std::string name = StringToLowerASCII(UTF16ToUTF8(
|
| element.attributeLocalName(i)));
|
| - std::string value = base::UTF16ToUTF8(element.attributeValue(i));
|
| + std::string value = UTF16ToUTF8(element.attributeValue(i));
|
| dst->html_attributes.push_back(std::make_pair(name, value));
|
| }
|
|
|
| @@ -250,10 +328,10 @@ void SerializeAccessibilityNode(
|
| }
|
|
|
| // Live region attributes
|
| - live_atomic = base::UTF16ToUTF8(element.getAttribute("aria-atomic"));
|
| - live_busy = base::UTF16ToUTF8(element.getAttribute("aria-busy"));
|
| - live_status = base::UTF16ToUTF8(element.getAttribute("aria-live"));
|
| - live_relevant = base::UTF16ToUTF8(element.getAttribute("aria-relevant"));
|
| + live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic"));
|
| + live_busy = UTF16ToUTF8(element.getAttribute("aria-busy"));
|
| + live_status = UTF16ToUTF8(element.getAttribute("aria-live"));
|
| + live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant"));
|
| }
|
|
|
| // Walk up the parent chain to set live region attributes of containers
|
| @@ -269,22 +347,22 @@ void SerializeAccessibilityNode(
|
| if (container_elem.hasAttribute("aria-atomic") &&
|
| container_live_atomic.empty()) {
|
| container_live_atomic =
|
| - base::UTF16ToUTF8(container_elem.getAttribute("aria-atomic"));
|
| + UTF16ToUTF8(container_elem.getAttribute("aria-atomic"));
|
| }
|
| if (container_elem.hasAttribute("aria-busy") &&
|
| container_live_busy.empty()) {
|
| container_live_busy =
|
| - base::UTF16ToUTF8(container_elem.getAttribute("aria-busy"));
|
| + UTF16ToUTF8(container_elem.getAttribute("aria-busy"));
|
| }
|
| if (container_elem.hasAttribute("aria-live") &&
|
| container_live_status.empty()) {
|
| container_live_status =
|
| - base::UTF16ToUTF8(container_elem.getAttribute("aria-live"));
|
| + UTF16ToUTF8(container_elem.getAttribute("aria-live"));
|
| }
|
| if (container_elem.hasAttribute("aria-relevant") &&
|
| container_live_relevant.empty()) {
|
| container_live_relevant =
|
| - base::UTF16ToUTF8(container_elem.getAttribute("aria-relevant"));
|
| + UTF16ToUTF8(container_elem.getAttribute("aria-relevant"));
|
| }
|
| }
|
| container_accessible = container_accessible.parentObject();
|
| @@ -334,7 +412,7 @@ void SerializeAccessibilityNode(
|
| if (name.empty())
|
| name = UTF16ToUTF8(document.title());
|
| dst->AddStringAttribute(ui::AX_ATTR_DOC_TITLE,
|
| - UTF16ToUTF8(document.title()));
|
| + UTF16ToUTF8(document.title()));
|
| dst->AddStringAttribute(ui::AX_ATTR_DOC_URL, document.url().spec());
|
| dst->AddStringAttribute(
|
| ui::AX_ATTR_DOC_MIMETYPE,
|
| @@ -425,15 +503,15 @@ void SerializeAccessibilityNode(
|
| // parent is the row, the row adds it as a child, and the column adds it
|
| // as an indirect child.
|
| int child_count = src.childCount();
|
| - std::vector<int32> indirect_child_ids;
|
| for (int i = 0; i < child_count; ++i) {
|
| WebAXObject child = src.childAt(i);
|
| + std::vector<int32> indirect_child_ids;
|
| if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child))
|
| indirect_child_ids.push_back(child.axID());
|
| - }
|
| - if (indirect_child_ids.size() > 0) {
|
| - dst->AddIntListAttribute(ui::AX_ATTR_INDIRECT_CHILD_IDS,
|
| - indirect_child_ids);
|
| + if (indirect_child_ids.size() > 0) {
|
| + dst->AddIntListAttribute(
|
| + ui::AX_ATTR_INDIRECT_CHILD_IDS, indirect_child_ids);
|
| + }
|
| }
|
|
|
| WebVector<WebAXObject> controls;
|
| @@ -461,26 +539,14 @@ void SerializeAccessibilityNode(
|
| AddIntListAttributeFromWebObjects(ui::AX_ATTR_OWNS_IDS, owns, dst);
|
| }
|
|
|
| -bool ShouldIncludeChildNode(
|
| - const WebAXObject& parent,
|
| - const WebAXObject& child) {
|
| - // The child may be invalid due to issues in webkit accessibility code.
|
| - // Don't add children that are invalid thus preventing a crash.
|
| - // https://bugs.webkit.org/show_bug.cgi?id=44149
|
| - // TODO(ctguil): We may want to remove this check as webkit stabilizes.
|
| - if (child.isDetached())
|
| - return false;
|
| -
|
| - // Skip children whose parent isn't this - see indirect_child_ids, above.
|
| - // As an exception, include children of an iframe element.
|
| - bool is_iframe = false;
|
| - WebNode node = parent.node();
|
| - if (!node.isNull() && node.isElementNode()) {
|
| - WebElement element = node.to<WebElement>();
|
| - is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME"));
|
| - }
|
| +blink::WebDocument BlinkAXTreeSource::GetMainDocument() const {
|
| + WebView* view = render_view_->GetWebView();
|
| + WebFrame* main_frame = view ? view->mainFrame() : NULL;
|
| +
|
| + if (main_frame)
|
| + return main_frame->document();
|
|
|
| - return (is_iframe || IsParentUnignoredOf(parent, child));
|
| + return WebDocument();
|
| }
|
|
|
| } // namespace content
|
|
|