Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(868)

Side by Side Diff: Source/modules/accessibility/AXObject.cpp

Issue 885163002: [Contextual Search] Check for ARIA widget roles. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added aria-attribute check and unit test. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 22 matching lines...) Expand all
33 #include "core/editing/VisibleUnits.h" 33 #include "core/editing/VisibleUnits.h"
34 #include "core/editing/htmlediting.h" 34 #include "core/editing/htmlediting.h"
35 #include "core/frame/LocalFrame.h" 35 #include "core/frame/LocalFrame.h"
36 #include "core/frame/Settings.h" 36 #include "core/frame/Settings.h"
37 #include "core/layout/LayoutTheme.h" 37 #include "core/layout/LayoutTheme.h"
38 #include "core/rendering/RenderListItem.h" 38 #include "core/rendering/RenderListItem.h"
39 #include "core/rendering/RenderView.h" 39 #include "core/rendering/RenderView.h"
40 #include "modules/accessibility/AXObjectCacheImpl.h" 40 #include "modules/accessibility/AXObjectCacheImpl.h"
41 #include "platform/UserGestureIndicator.h" 41 #include "platform/UserGestureIndicator.h"
42 #include "platform/text/PlatformLocale.h" 42 #include "platform/text/PlatformLocale.h"
43 // #include "public/web/WebElement.h"
44 // #include "public/web/WebNode.h"
45 #include "wtf/HashSet.h"
43 #include "wtf/StdLibExtras.h" 46 #include "wtf/StdLibExtras.h"
44 #include "wtf/text/WTFString.h" 47 #include "wtf/text/WTFString.h"
45 48
46 using blink::WebLocalizedString; 49 using blink::WebLocalizedString;
47 50
48 namespace blink { 51 namespace blink {
49 52
50 using namespace HTMLNames; 53 using namespace HTMLNames;
51 54
52 namespace { 55 namespace {
53 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; 56 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap;
57 typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet;
54 58
55 struct RoleEntry { 59 struct RoleEntry {
56 const char* ariaRole; 60 const char* ariaRole;
57 AccessibilityRole webcoreRole; 61 AccessibilityRole webcoreRole;
58 }; 62 };
59 63
60 const RoleEntry roles[] = { 64 const RoleEntry roles[] = {
61 { "alert", AlertRole }, 65 { "alert", AlertRole },
62 { "alertdialog", AlertDialogRole }, 66 { "alertdialog", AlertDialogRole },
63 { "application", ApplicationRole }, 67 { "application", ApplicationRole },
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 Vector<AtomicString>* roleNameVector = new Vector<AtomicString>(NumRoles); 140 Vector<AtomicString>* roleNameVector = new Vector<AtomicString>(NumRoles);
137 for (int i = 0; i < NumRoles; i++) 141 for (int i = 0; i < NumRoles; i++)
138 (*roleNameVector)[i] = nullAtom; 142 (*roleNameVector)[i] = nullAtom;
139 143
140 for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i) 144 for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i)
141 (*roleNameVector)[roles[i].webcoreRole] = AtomicString(roles[i].ariaRole ); 145 (*roleNameVector)[roles[i].webcoreRole] = AtomicString(roles[i].ariaRole );
142 146
143 return roleNameVector; 147 return roleNameVector;
144 } 148 }
145 149
150 const char* ariaWidgets[] = {
151 // From http://www.w3.org/TR/wai-aria/roles#widget_roles
152 "alert",
153 "alertdialog",
154 "button",
155 "checkbox",
156 "dialog",
157 "gridcell",
158 "link",
159 "log",
160 "marquee",
161 "menuitem",
162 "menuitemcheckbox",
163 "menuitemradio",
164 "option",
165 "progressbar",
166 "radio",
167 "scrollbar",
168 "slider",
169 "spinbutton",
170 "status",
171 "tab",
172 "tabpanel",
173 "textbox",
174 "timer",
175 "tooltip",
176 "treeitem",
177 // Composite user interface widgets. This list is also from w3.org site ref rerenced above.
178 "combobox",
179 "grid",
180 "listbox",
181 "menu",
182 "menubar",
183 "radiogroup",
184 "tablist",
185 "tree",
186 "treegrid"
187 };
188
189 static ARIAWidgetSet* createARIARoleWidgetSet()
190 {
191 ARIAWidgetSet* widgetSet = new HashSet<String, CaseFoldingHash>();
192 for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaWidgets); ++i)
193 widgetSet->add(String(ariaWidgets[i]));
194 return widgetSet;
195 }
196
197 const char* ariaInteractiveWidgetAttributes[] = {
198 // These attributes implicitly indicate the given widget is interactive.
199 // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets
200 "aria-activedescendant",
201 "aria-checked",
202 "aria-controls",
203 "aria-disabled", // If it's disabled, it can be made interactive.
204 "aria-expanded",
205 "aria-haspopup", // Interactive only if this attribute has a value of "true" .
206 "aria-multiselectable",
207 "aria-pressed",
208 "aria-required",
209 "aria-selected"
210 };
211
146 } // namespace 212 } // namespace
147 213
148 AXObject::AXObject(AXObjectCacheImpl* axObjectCache) 214 AXObject::AXObject(AXObjectCacheImpl* axObjectCache)
149 : m_id(0) 215 : m_id(0)
150 , m_haveChildren(false) 216 , m_haveChildren(false)
151 , m_role(UnknownRole) 217 , m_role(UnknownRole)
152 , m_lastKnownIsIgnoredValue(DefaultBehavior) 218 , m_lastKnownIsIgnoredValue(DefaultBehavior)
153 , m_detached(false) 219 , m_detached(false)
154 , m_parent(0) 220 , m_parent(0)
155 , m_lastModificationCount(-1) 221 , m_lastModificationCount(-1)
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 for (unsigned i = 0; i < size; ++i) { 1015 for (unsigned i = 0; i < size; ++i) {
950 String roleName = roleVector[i]; 1016 String roleName = roleVector[i];
951 role = roleMap->get(roleName); 1017 role = roleMap->get(roleName);
952 if (role) 1018 if (role)
953 return role; 1019 return role;
954 } 1020 }
955 1021
956 return role; 1022 return role;
957 } 1023 }
958 1024
1025 bool AXObject::isARIAWidget(const WebNode& webNode)
1026 {
1027 WebNode curNode = webNode;
1028 do {
1029 if (curNode.isElementNode()) {
1030 const WebElement& element = curNode.toConst<blink::WebElement>();
1031 if (element.isFocusable())
dmazzoni 2015/02/05 00:40:23 It seems odd to check for focusability in a functi
Donn Denman 2015/02/06 22:53:36 I changed the name, thanks for the suggestion!
1032 return true;
1033 String role = element.getAttribute("role");
1034 if (!role.isEmpty() && AXObject::includesARIAWidgetRole(role))
1035 return true;
1036 if (hasInteractiveARIAAttribute(element))
1037 return true;
1038 }
1039 curNode = curNode.parentNode();
1040 } while (!curNode.isNull() && curNode.nodeName() != "BODY");
dmazzoni 2015/02/05 00:40:23 Now that you're inside Blink you can call isHTMLBo
Donn Denman 2015/02/06 22:53:36 Done.
1041 return false;
1042 }
1043
1044 bool AXObject::hasInteractiveARIAAttribute(const WebElement& element)
1045 {
1046 for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaInteractiveWidgetAttributes); ++ i) {
1047 const char* attribute = ariaInteractiveWidgetAttributes[i];
1048 if (element.hasAttribute(WebString::fromUTF8(attribute))) {
1049 if (!strcmp("aria-haspopup", attribute))
1050 return element.getAttribute(WebString::fromUTF8(attribute)) == " true";
1051 return true;
1052 }
1053 }
1054 return false;
1055 }
1056
1057 bool AXObject::includesARIAWidgetRole(const String& role)
1058 {
1059 static const HashSet<String, CaseFoldingHash>* roleSet = createARIARoleWidge tSet();
1060
1061 Vector<String> roleVector;
1062 role.split(' ', roleVector);
1063 unsigned size = roleVector.size();
1064 for (unsigned i = 0; i < size; ++i) {
1065 String roleName = roleVector[i];
1066 if (roleSet->contains(roleName))
1067 return true;
1068 }
1069 return false;
1070 }
1071
959 AccessibilityRole AXObject::buttonRoleType() const 1072 AccessibilityRole AXObject::buttonRoleType() const
960 { 1073 {
961 // If aria-pressed is present, then it should be exposed as a toggle button. 1074 // If aria-pressed is present, then it should be exposed as a toggle button.
962 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed 1075 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed
963 if (ariaPressedIsPresent()) 1076 if (ariaPressedIsPresent())
964 return ToggleButtonRole; 1077 return ToggleButtonRole;
965 if (ariaHasPopup()) 1078 if (ariaHasPopup())
966 return PopUpButtonRole; 1079 return PopUpButtonRole;
967 // We don't contemplate RadioButtonRole, as it depends on the input 1080 // We don't contemplate RadioButtonRole, as it depends on the input
968 // type. 1081 // type.
969 1082
970 return ButtonRole; 1083 return ButtonRole;
971 } 1084 }
972 1085
973 const AtomicString& AXObject::roleName(AccessibilityRole role) 1086 const AtomicString& AXObject::roleName(AccessibilityRole role)
974 { 1087 {
975 static const Vector<AtomicString>* roleNameVector = createRoleNameVector(); 1088 static const Vector<AtomicString>* roleNameVector = createRoleNameVector();
976 1089
977 return roleNameVector->at(role); 1090 return roleNameVector->at(role);
978 } 1091 }
979 1092
980 } // namespace blink 1093 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698