OLD | NEW |
---|---|
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 Loading... | |
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 "wtf/HashSet.h" | |
43 #include "wtf/StdLibExtras.h" | 44 #include "wtf/StdLibExtras.h" |
44 #include "wtf/text/WTFString.h" | 45 #include "wtf/text/WTFString.h" |
45 | 46 |
46 using blink::WebLocalizedString; | 47 using blink::WebLocalizedString; |
47 | 48 |
48 namespace blink { | 49 namespace blink { |
49 | 50 |
50 using namespace HTMLNames; | 51 using namespace HTMLNames; |
51 | 52 |
52 namespace { | 53 namespace { |
53 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; | 54 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; |
55 typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet; | |
54 | 56 |
55 struct RoleEntry { | 57 struct RoleEntry { |
56 const char* ariaRole; | 58 const char* ariaRole; |
57 AccessibilityRole webcoreRole; | 59 AccessibilityRole webcoreRole; |
58 }; | 60 }; |
59 | 61 |
60 const RoleEntry roles[] = { | 62 const RoleEntry roles[] = { |
61 { "alert", AlertRole }, | 63 { "alert", AlertRole }, |
62 { "alertdialog", AlertDialogRole }, | 64 { "alertdialog", AlertDialogRole }, |
63 { "application", ApplicationRole }, | 65 { "application", ApplicationRole }, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 | 152 |
151 for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i) | 153 for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i) |
152 (*roleNameVector)[roles[i].webcoreRole] = AtomicString(roles[i].ariaRole ); | 154 (*roleNameVector)[roles[i].webcoreRole] = AtomicString(roles[i].ariaRole ); |
153 | 155 |
154 for (size_t i = 0; i < WTF_ARRAY_LENGTH(reverseRoles); ++i) | 156 for (size_t i = 0; i < WTF_ARRAY_LENGTH(reverseRoles); ++i) |
155 (*roleNameVector)[reverseRoles[i].webcoreRole] = AtomicString(reverseRol es[i].ariaRole); | 157 (*roleNameVector)[reverseRoles[i].webcoreRole] = AtomicString(reverseRol es[i].ariaRole); |
156 | 158 |
157 return roleNameVector; | 159 return roleNameVector; |
158 } | 160 } |
159 | 161 |
162 const char* ariaWidgets[] = { | |
163 // From http://www.w3.org/TR/wai-aria/roles#widget_roles | |
164 "alert", | |
165 "alertdialog", | |
166 "button", | |
167 "checkbox", | |
168 "dialog", | |
169 "gridcell", | |
170 "link", | |
171 "log", | |
172 "marquee", | |
173 "menuitem", | |
174 "menuitemcheckbox", | |
175 "menuitemradio", | |
176 "option", | |
177 "progressbar", | |
178 "radio", | |
179 "scrollbar", | |
180 "slider", | |
181 "spinbutton", | |
182 "status", | |
183 "tab", | |
184 "tabpanel", | |
185 "textbox", | |
186 "timer", | |
187 "tooltip", | |
188 "treeitem", | |
189 // Composite user interface widgets. This list is also from w3.org site ref rerenced above. | |
190 "combobox", | |
191 "grid", | |
192 "listbox", | |
193 "menu", | |
194 "menubar", | |
195 "radiogroup", | |
196 "tablist", | |
197 "tree", | |
198 "treegrid" | |
199 }; | |
200 | |
201 static ARIAWidgetSet* createARIARoleWidgetSet() | |
202 { | |
203 ARIAWidgetSet* widgetSet = new HashSet<String, CaseFoldingHash>(); | |
204 for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaWidgets); ++i) | |
205 widgetSet->add(String(ariaWidgets[i])); | |
206 return widgetSet; | |
207 } | |
208 | |
209 const char* ariaInteractiveWidgetAttributes[] = { | |
210 // These attributes implicitly indicate the given widget is interactive. | |
211 // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets | |
212 "aria-activedescendant", | |
213 "aria-checked", | |
214 "aria-controls", | |
215 "aria-disabled", // If it's disabled, it can be made interactive. | |
216 "aria-expanded", | |
217 "aria-haspopup", // Interactive only if this attribute has a value of "true" . | |
218 "aria-multiselectable", | |
219 "aria-pressed", | |
220 "aria-required", | |
221 "aria-selected" | |
222 }; | |
223 | |
160 } // namespace | 224 } // namespace |
161 | 225 |
162 AXObject::AXObject(AXObjectCacheImpl* axObjectCache) | 226 AXObject::AXObject(AXObjectCacheImpl* axObjectCache) |
163 : m_id(0) | 227 : m_id(0) |
164 , m_haveChildren(false) | 228 , m_haveChildren(false) |
165 , m_role(UnknownRole) | 229 , m_role(UnknownRole) |
166 , m_lastKnownIsIgnoredValue(DefaultBehavior) | 230 , m_lastKnownIsIgnoredValue(DefaultBehavior) |
167 , m_detached(false) | 231 , m_detached(false) |
168 , m_parent(0) | 232 , m_parent(0) |
169 , m_lastModificationCount(-1) | 233 , m_lastModificationCount(-1) |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
962 for (unsigned i = 0; i < size; ++i) { | 1026 for (unsigned i = 0; i < size; ++i) { |
963 String roleName = roleVector[i]; | 1027 String roleName = roleVector[i]; |
964 role = roleMap->get(roleName); | 1028 role = roleMap->get(roleName); |
965 if (role) | 1029 if (role) |
966 return role; | 1030 return role; |
967 } | 1031 } |
968 | 1032 |
969 return role; | 1033 return role; |
970 } | 1034 } |
971 | 1035 |
1036 bool AXObject::isInsideFocusableElementOrARIAWidget(const Node& node) | |
1037 { | |
1038 const Node* curNode = &node; | |
1039 do { | |
1040 if (curNode->isElementNode()) { | |
1041 const Element* element = toElement(curNode); | |
1042 if (element->isFocusable()) | |
1043 return true; | |
1044 String role = element->getAttribute("role"); | |
1045 if (!role.isEmpty() && AXObject::includesARIAWidgetRole(role)) | |
1046 return true; | |
1047 if (hasInteractiveARIAAttribute(*element)) | |
1048 return true; | |
1049 } | |
1050 curNode = curNode->parentNode(); | |
1051 } while (curNode && !isHTMLBodyElement(node)); | |
1052 return false; | |
1053 } | |
1054 | |
1055 bool AXObject::hasInteractiveARIAAttribute(const Element& element) | |
1056 { | |
1057 for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaInteractiveWidgetAttributes); ++ i) { | |
1058 const char* attribute = ariaInteractiveWidgetAttributes[i]; | |
1059 if (element.hasAttribute(attribute)) { | |
1060 if (!strcmp("aria-haspopup", attribute)) | |
dmazzoni
2015/02/10 07:40:54
Why are you special-casing aria-haspopup? Since yo
Donn Denman
2015/02/24 23:37:52
Makes sense -- done. It looked to me like this wa
| |
1061 return element.getAttribute(attribute) == "true"; | |
1062 return true; | |
1063 } | |
1064 } | |
1065 return false; | |
1066 } | |
1067 | |
1068 bool AXObject::includesARIAWidgetRole(const String& role) | |
1069 { | |
1070 static const HashSet<String, CaseFoldingHash>* roleSet = createARIARoleWidge tSet(); | |
1071 | |
1072 Vector<String> roleVector; | |
1073 role.split(' ', roleVector); | |
1074 unsigned size = roleVector.size(); | |
1075 for (unsigned i = 0; i < size; ++i) { | |
1076 String roleName = roleVector[i]; | |
1077 if (roleSet->contains(roleName)) | |
1078 return true; | |
1079 } | |
1080 return false; | |
1081 } | |
1082 | |
972 AccessibilityRole AXObject::buttonRoleType() const | 1083 AccessibilityRole AXObject::buttonRoleType() const |
973 { | 1084 { |
974 // If aria-pressed is present, then it should be exposed as a toggle button. | 1085 // If aria-pressed is present, then it should be exposed as a toggle button. |
975 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed | 1086 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed |
976 if (ariaPressedIsPresent()) | 1087 if (ariaPressedIsPresent()) |
977 return ToggleButtonRole; | 1088 return ToggleButtonRole; |
978 if (ariaHasPopup()) | 1089 if (ariaHasPopup()) |
979 return PopUpButtonRole; | 1090 return PopUpButtonRole; |
980 // We don't contemplate RadioButtonRole, as it depends on the input | 1091 // We don't contemplate RadioButtonRole, as it depends on the input |
981 // type. | 1092 // type. |
982 | 1093 |
983 return ButtonRole; | 1094 return ButtonRole; |
984 } | 1095 } |
985 | 1096 |
986 const AtomicString& AXObject::roleName(AccessibilityRole role) | 1097 const AtomicString& AXObject::roleName(AccessibilityRole role) |
987 { | 1098 { |
988 static const Vector<AtomicString>* roleNameVector = createRoleNameVector(); | 1099 static const Vector<AtomicString>* roleNameVector = createRoleNameVector(); |
989 | 1100 |
990 return roleNameVector->at(role); | 1101 return roleNameVector->at(role); |
991 } | 1102 } |
992 | 1103 |
993 } // namespace blink | 1104 } // namespace blink |
OLD | NEW |