| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/dom/AXObject.h" |
| 6 |
| 7 #include "core/HTMLElementTypeHelpers.h" |
| 8 #include "core/dom/Element.h" |
| 9 #include "core/dom/Node.h" |
| 10 #include "platform/wtf/HashSet.h" |
| 11 #include "platform/wtf/text/StringHash.h" |
| 12 #include "platform/wtf/text/WTFString.h" |
| 13 |
| 14 namespace blink { |
| 15 |
| 16 namespace { |
| 17 |
| 18 typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet; |
| 19 |
| 20 const char* g_aria_widgets[] = { |
| 21 // From http://www.w3.org/TR/wai-aria/roles#widget_roles |
| 22 "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link", |
| 23 "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option", |
| 24 "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status", |
| 25 "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem", |
| 26 // Composite user interface widgets. |
| 27 // This list is also from the w3.org site referenced above. |
| 28 "combobox", "grid", "listbox", "menu", "menubar", "radiogroup", "tablist", |
| 29 "tree", "treegrid"}; |
| 30 |
| 31 static ARIAWidgetSet* CreateARIARoleWidgetSet() { |
| 32 ARIAWidgetSet* widget_set = new HashSet<String, CaseFoldingHash>(); |
| 33 for (size_t i = 0; i < WTF_ARRAY_LENGTH(g_aria_widgets); ++i) |
| 34 widget_set->insert(String(g_aria_widgets[i])); |
| 35 return widget_set; |
| 36 } |
| 37 |
| 38 bool IncludesARIAWidgetRole(const String& role) { |
| 39 static const HashSet<String, CaseFoldingHash>* role_set = |
| 40 CreateARIARoleWidgetSet(); |
| 41 |
| 42 Vector<String> role_vector; |
| 43 role.Split(' ', role_vector); |
| 44 for (const auto& child : role_vector) { |
| 45 if (role_set->Contains(child)) |
| 46 return true; |
| 47 } |
| 48 return false; |
| 49 } |
| 50 |
| 51 const char* g_aria_interactive_widget_attributes[] = { |
| 52 // These attributes implicitly indicate the given widget is interactive. |
| 53 // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets |
| 54 // clang-format off |
| 55 "aria-activedescendant", |
| 56 "aria-checked", |
| 57 "aria-controls", |
| 58 "aria-disabled", // If it's disabled, it can be made interactive. |
| 59 "aria-expanded", |
| 60 "aria-haspopup", |
| 61 "aria-multiselectable", |
| 62 "aria-pressed", |
| 63 "aria-required", |
| 64 "aria-selected" |
| 65 // clang-format on |
| 66 }; |
| 67 |
| 68 bool HasInteractiveARIAAttribute(const Element& element) { |
| 69 for (size_t i = 0; i < WTF_ARRAY_LENGTH(g_aria_interactive_widget_attributes); |
| 70 ++i) { |
| 71 const char* attribute = g_aria_interactive_widget_attributes[i]; |
| 72 if (element.hasAttribute(attribute)) { |
| 73 return true; |
| 74 } |
| 75 } |
| 76 return false; |
| 77 } |
| 78 |
| 79 } // namespace |
| 80 |
| 81 bool AXObject::IsInsideFocusableElementOrARIAWidget(const Node& node) { |
| 82 const Node* cur_node = &node; |
| 83 do { |
| 84 if (cur_node->IsElementNode()) { |
| 85 const Element* element = ToElement(cur_node); |
| 86 if (element->IsFocusable()) |
| 87 return true; |
| 88 String role = element->getAttribute("role"); |
| 89 if (!role.IsEmpty() && IncludesARIAWidgetRole(role)) |
| 90 return true; |
| 91 if (HasInteractiveARIAAttribute(*element)) |
| 92 return true; |
| 93 } |
| 94 cur_node = cur_node->parentNode(); |
| 95 } while (cur_node && !isHTMLBodyElement(node)); |
| 96 return false; |
| 97 } |
| 98 |
| 99 } // namespace blink |
| OLD | NEW |