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

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

Issue 1348503003: One AXObjectCache per frame (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Send focus notifications when focus is cleared Created 5 years, 3 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) 2014, Google Inc. All rights reserved. 2 * Copyright (C) 2014, Google 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 #include "modules/accessibility/AXLayoutObject.h" 61 #include "modules/accessibility/AXLayoutObject.h"
62 #include "modules/accessibility/AXList.h" 62 #include "modules/accessibility/AXList.h"
63 #include "modules/accessibility/AXListBox.h" 63 #include "modules/accessibility/AXListBox.h"
64 #include "modules/accessibility/AXListBoxOption.h" 64 #include "modules/accessibility/AXListBoxOption.h"
65 #include "modules/accessibility/AXMediaControls.h" 65 #include "modules/accessibility/AXMediaControls.h"
66 #include "modules/accessibility/AXMenuList.h" 66 #include "modules/accessibility/AXMenuList.h"
67 #include "modules/accessibility/AXMenuListOption.h" 67 #include "modules/accessibility/AXMenuListOption.h"
68 #include "modules/accessibility/AXMenuListPopup.h" 68 #include "modules/accessibility/AXMenuListPopup.h"
69 #include "modules/accessibility/AXProgressIndicator.h" 69 #include "modules/accessibility/AXProgressIndicator.h"
70 #include "modules/accessibility/AXSVGRoot.h" 70 #include "modules/accessibility/AXSVGRoot.h"
71 #include "modules/accessibility/AXScrollView.h"
72 #include "modules/accessibility/AXScrollbar.h"
73 #include "modules/accessibility/AXSlider.h" 71 #include "modules/accessibility/AXSlider.h"
74 #include "modules/accessibility/AXSpinButton.h" 72 #include "modules/accessibility/AXSpinButton.h"
75 #include "modules/accessibility/AXTable.h" 73 #include "modules/accessibility/AXTable.h"
76 #include "modules/accessibility/AXTableCell.h" 74 #include "modules/accessibility/AXTableCell.h"
77 #include "modules/accessibility/AXTableColumn.h" 75 #include "modules/accessibility/AXTableColumn.h"
78 #include "modules/accessibility/AXTableHeaderContainer.h" 76 #include "modules/accessibility/AXTableHeaderContainer.h"
79 #include "modules/accessibility/AXTableRow.h" 77 #include "modules/accessibility/AXTableRow.h"
80 #include "wtf/PassRefPtr.h" 78 #include "wtf/PassRefPtr.h"
81 79
82 namespace blink { 80 namespace blink {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 if (!child->isImageMapLink()) 144 if (!child->isImageMapLink())
147 continue; 145 continue;
148 146
149 if (toAXImageMapLink(child)->areaElement() == areaElement) 147 if (toAXImageMapLink(child)->areaElement() == areaElement)
150 return child; 148 return child;
151 } 149 }
152 150
153 return 0; 151 return 0;
154 } 152 }
155 153
156 AXObject* AXObjectCacheImpl::focusedUIElementForPage(const Page* page)
157 {
158 if (!page->settings().accessibilityEnabled())
159 return 0;
160
161 // Cross-process accessibility is not yet implemented.
162 if (!page->focusController().focusedOrMainFrame()->isLocalFrame())
163 return 0;
164
165 // get the focused node in the page
166 Document* focusedDocument = toLocalFrame(page->focusController().focusedOrMa inFrame())->document();
167 Node* focusedNode = focusedDocument->focusedElement();
168 if (!focusedNode)
169 focusedNode = focusedDocument;
170
171 if (isHTMLAreaElement(*focusedNode))
172 return focusedImageMapUIElement(toHTMLAreaElement(focusedNode));
173
174 AXObject* obj = getOrCreate(focusedNode);
175 if (!obj)
176 return 0;
177
178 if (obj->shouldFocusActiveDescendant()) {
179 if (AXObject* descendant = obj->activeDescendant())
180 obj = descendant;
181 }
182
183 // the HTML element, for example, is focusable but has an AX object that is ignored
184 if (obj->accessibilityIsIgnored())
185 obj = obj->parentObjectUnignored();
186
187 return obj;
188 }
189
190 AXObject* AXObjectCacheImpl::get(Widget* widget)
191 {
192 if (!widget)
193 return 0;
194
195 AXID axID = m_widgetObjectMapping.get(widget);
196 ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
197 if (!axID)
198 return 0;
199
200 return m_objects.get(axID);
201 }
202
203 AXObject* AXObjectCacheImpl::get(LayoutObject* layoutObject) 154 AXObject* AXObjectCacheImpl::get(LayoutObject* layoutObject)
204 { 155 {
205 if (!layoutObject) 156 if (!layoutObject)
206 return 0; 157 return 0;
207 158
208 AXID axID = m_layoutObjectMapping.get(layoutObject); 159 AXID axID = m_layoutObjectMapping.get(layoutObject);
209 ASSERT(!HashTraits<AXID>::isDeletedValue(axID)); 160 ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
210 if (!axID) 161 if (!axID)
211 return 0; 162 return 0;
212 163
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 return AXMenuListOption::create(toHTMLOptionElement(node), *this); 290 return AXMenuListOption::create(toHTMLOptionElement(node), *this);
340 291
341 return AXNodeObject::create(node, *this); 292 return AXNodeObject::create(node, *this);
342 } 293 }
343 294
344 AXObject* AXObjectCacheImpl::createFromInlineTextBox(AbstractInlineTextBox* inli neTextBox) 295 AXObject* AXObjectCacheImpl::createFromInlineTextBox(AbstractInlineTextBox* inli neTextBox)
345 { 296 {
346 return AXInlineTextBox::create(inlineTextBox, *this); 297 return AXInlineTextBox::create(inlineTextBox, *this);
347 } 298 }
348 299
349 AXObject* AXObjectCacheImpl::getOrCreate(Widget* widget)
350 {
351 if (!widget)
352 return 0;
353
354 if (AXObject* obj = get(widget))
355 return obj;
356
357 AXObject* newObj = nullptr;
358 if (widget->isFrameView()) {
359 FrameView* frameView = toFrameView(widget);
360
361 // Don't create an AXScrollView for a FrameView that isn't attached to a frame,
362 // for example if it's in the process of being disposed.
363 if (frameView->frame().view() != frameView || !frameView->layoutView())
364 return 0;
365
366 newObj = AXScrollView::create(toFrameView(widget), *this);
367 } else if (widget->isScrollbar()) {
368 newObj = AXScrollbar::create(toScrollbar(widget), *this);
369 }
370
371 // Will crash later if we have two objects for the same widget.
372 ASSERT(!get(widget));
373
374 // Catch the case if an (unsupported) widget type is used. Only FrameView an d ScrollBar are supported now.
375 ASSERT(newObj);
376 if (!newObj)
377 return 0;
378
379 getAXID(newObj);
380
381 m_widgetObjectMapping.set(widget, newObj->axObjectID());
382 m_objects.set(newObj->axObjectID(), newObj);
383 newObj->init();
384 return newObj;
385 }
386
387 AXObject* AXObjectCacheImpl::getOrCreate(Node* node) 300 AXObject* AXObjectCacheImpl::getOrCreate(Node* node)
388 { 301 {
389 if (!node) 302 if (!node)
390 return 0; 303 return 0;
391 304
392 if (AXObject* obj = get(node)) 305 if (AXObject* obj = get(node))
393 return obj; 306 return obj;
394 307
395 if (node->layoutObject()) 308 if (node->layoutObject())
396 return getOrCreate(node->layoutObject()); 309 return getOrCreate(node->layoutObject());
397 310
398 if (!node->parentElement()) 311 if (!node->parentElement())
399 return 0; 312 return 0;
400 313
401 if (isHTMLHeadElement(node)) 314 if (isHTMLHeadElement(node))
402 return 0; 315 return 0;
403 316
317 if (!node->document().frame())
318 return 0;
319
320 if (node->document().frame()->pagePopupOwner() && &node->document().frame()- >pagePopupOwner()->document() != m_document)
321 return 0;
322
323 if (&node->document() != m_document)
324 return 0;
325
404 AXObject* newObj = createFromNode(node); 326 AXObject* newObj = createFromNode(node);
405 327
406 // Will crash later if we have two objects for the same node. 328 // Will crash later if we have two objects for the same node.
407 ASSERT(!get(node)); 329 ASSERT(!get(node));
408 330
409 getAXID(newObj); 331 getAXID(newObj);
410 332
411 m_nodeObjectMapping.set(node, newObj->axObjectID()); 333 m_nodeObjectMapping.set(node, newObj->axObjectID());
412 m_objects.set(newObj->axObjectID(), newObj); 334 m_objects.set(newObj->axObjectID(), newObj);
413 newObj->init(); 335 newObj->init();
414 newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored()); 336 newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored());
415 337
416 if (node->isElementNode()) 338 if (node->isElementNode())
417 updateTreeIfElementIdIsAriaOwned(toElement(node)); 339 updateTreeIfElementIdIsAriaOwned(toElement(node));
418 340
419 return newObj; 341 return newObj;
420 } 342 }
421 343
422 AXObject* AXObjectCacheImpl::getOrCreate(LayoutObject* layoutObject) 344 AXObject* AXObjectCacheImpl::getOrCreate(LayoutObject* layoutObject)
423 { 345 {
424 if (!layoutObject) 346 if (!layoutObject)
425 return 0; 347 return 0;
426 348
349 if (&layoutObject->document() != m_document)
350 return 0;
351
427 if (AXObject* obj = get(layoutObject)) 352 if (AXObject* obj = get(layoutObject))
428 return obj; 353 return obj;
429 354
430 AXObject* newObj = createFromRenderer(layoutObject); 355 AXObject* newObj = createFromRenderer(layoutObject);
431 356
432 // Will crash later if we have two objects for the same layoutObject. 357 // Will crash later if we have two objects for the same layoutObject.
433 ASSERT(!get(layoutObject)); 358 ASSERT(!get(layoutObject));
434 359
435 getAXID(newObj); 360 getAXID(newObj);
436 361
(...skipping 26 matching lines...) Expand all
463 newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored()); 388 newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored());
464 389
465 return newObj; 390 return newObj;
466 } 391 }
467 392
468 AXObject* AXObjectCacheImpl::rootObject() 393 AXObject* AXObjectCacheImpl::rootObject()
469 { 394 {
470 if (!accessibilityEnabled()) 395 if (!accessibilityEnabled())
471 return 0; 396 return 0;
472 397
473 return getOrCreate(m_document->view()); 398 return getOrCreate(m_document);
474 } 399 }
475 400
476 AXObject* AXObjectCacheImpl::getOrCreate(AccessibilityRole role) 401 AXObject* AXObjectCacheImpl::getOrCreate(AccessibilityRole role)
477 { 402 {
478 AXObject* obj = nullptr; 403 AXObject* obj = nullptr;
479 404
480 // will be filled in... 405 // will be filled in...
481 switch (role) { 406 switch (role) {
482 case ImageMapLinkRole: 407 case ImageMapLinkRole:
483 obj = AXImageMapLink::create(*this); 408 obj = AXImageMapLink::create(*this);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 AXID axID = m_nodeObjectMapping.get(node); 478 AXID axID = m_nodeObjectMapping.get(node);
554 remove(axID); 479 remove(axID);
555 m_nodeObjectMapping.remove(node); 480 m_nodeObjectMapping.remove(node);
556 481
557 if (node->layoutObject()) { 482 if (node->layoutObject()) {
558 remove(node->layoutObject()); 483 remove(node->layoutObject());
559 return; 484 return;
560 } 485 }
561 } 486 }
562 487
563 void AXObjectCacheImpl::remove(Widget* view)
564 {
565 if (!view)
566 return;
567
568 AXID axID = m_widgetObjectMapping.get(view);
569 remove(axID);
570 m_widgetObjectMapping.remove(view);
571 }
572
573 void AXObjectCacheImpl::remove(AbstractInlineTextBox* inlineTextBox) 488 void AXObjectCacheImpl::remove(AbstractInlineTextBox* inlineTextBox)
574 { 489 {
575 if (!inlineTextBox) 490 if (!inlineTextBox)
576 return; 491 return;
577 492
578 AXID axID = m_inlineTextBoxObjectMapping.get(inlineTextBox); 493 AXID axID = m_inlineTextBoxObjectMapping.get(inlineTextBox);
579 remove(axID); 494 remove(axID);
580 m_inlineTextBoxObjectMapping.remove(inlineTextBox); 495 m_inlineTextBoxObjectMapping.remove(inlineTextBox);
581 } 496 }
582 497
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 874
960 void AXObjectCacheImpl::listboxActiveIndexChanged(HTMLSelectElement* select) 875 void AXObjectCacheImpl::listboxActiveIndexChanged(HTMLSelectElement* select)
961 { 876 {
962 AXObject* obj = get(select); 877 AXObject* obj = get(select);
963 if (!obj || !obj->isAXListBox()) 878 if (!obj || !obj->isAXListBox())
964 return; 879 return;
965 880
966 toAXListBox(obj)->activeIndexChanged(); 881 toAXListBox(obj)->activeIndexChanged();
967 } 882 }
968 883
969 void AXObjectCacheImpl::handleScrollbarUpdate(FrameView* view)
970 {
971 if (!view)
972 return;
973
974 // We don't want to create a scroll view from this method, only update an ex isting one.
975 if (AXObject* scrollViewObject = get(view)) {
976 m_modificationCount++;
977 scrollViewObject->updateChildrenIfNecessary();
978 }
979 }
980
981 void AXObjectCacheImpl::handleLayoutComplete(LayoutObject* layoutObject) 884 void AXObjectCacheImpl::handleLayoutComplete(LayoutObject* layoutObject)
982 { 885 {
983 if (!layoutObject) 886 if (!layoutObject)
984 return; 887 return;
985 888
986 m_modificationCount++; 889 m_modificationCount++;
987 890
988 // Create the AXObject if it didn't yet exist - that's always safe at the en d of a layout, and it 891 // Create the AXObject if it didn't yet exist - that's always safe at the en d of a layout, and it
989 // allows an AX notification to be sent when a page has its first layout, ra ther than when the 892 // allows an AX notification to be sent when a page has its first layout, ra ther than when the
990 // document first loads. 893 // document first loads.
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 return false; 1061 return false;
1159 1062
1160 if (!node->isElementNode()) 1063 if (!node->isElementNode())
1161 return false; 1064 return false;
1162 1065
1163 return equalIgnoringCase(toElement(node)->getAttribute(aria_hiddenAttr), "fa lse"); 1066 return equalIgnoringCase(toElement(node)->getAttribute(aria_hiddenAttr), "fa lse");
1164 } 1067 }
1165 1068
1166 void AXObjectCacheImpl::postPlatformNotification(AXObject* obj, AXNotification n otification) 1069 void AXObjectCacheImpl::postPlatformNotification(AXObject* obj, AXNotification n otification)
1167 { 1070 {
1168 if (obj && obj->isAXScrollbar() && notification == AXValueChanged) {
1169 // Send document value changed on scrollbar value changed notification.
1170 Scrollbar* scrollBar = toAXScrollbar(obj)->scrollbar();
1171 if (!scrollBar || !scrollBar->parent() || !scrollBar->parent()->isFrameV iew())
1172 return;
1173 Document* document = toFrameView(scrollBar->parent())->frame().document( );
1174 if (document != document->topDocument())
1175 return;
1176 obj = get(document->layoutView());
1177 }
1178
1179 if (!obj || !obj->document() || !obj->documentFrameView() || !obj->documentF rameView()->frame().page()) 1071 if (!obj || !obj->document() || !obj->documentFrameView() || !obj->documentF rameView()->frame().page())
1180 return; 1072 return;
1181 1073
1182 ChromeClient& client = obj->document()->axObjectCacheOwner().page()->chromeC lient(); 1074 ChromeClient& client = obj->document()->axObjectCacheOwner().page()->chromeC lient();
1183 1075
1184 if (notification == AXActiveDescendantChanged 1076 if (notification == AXActiveDescendantChanged
1185 && obj->document()->focusedElement() 1077 && obj->document()->focusedElement()
1186 && obj->node() == obj->document()->focusedElement()) { 1078 && obj->node() == obj->document()->focusedElement()) {
1187 // Calling handleFocusedUIElementChanged will focus the new active 1079 // Calling handleFocusedUIElementChanged will focus the new active
1188 // descendant and send the AXFocusedUIElementChanged notification. 1080 // descendant and send the AXFocusedUIElementChanged notification.
1189 handleFocusedUIElementChanged(0, obj->document()->focusedElement()); 1081 handleFocusedUIElementChanged(0, obj->document()->focusedElement());
1190 } 1082 }
1191 1083
1192 client.postAccessibilityNotification(obj, notification); 1084 client.postAccessibilityNotification(obj, notification);
1193 } 1085 }
1194 1086
1195 void AXObjectCacheImpl::handleFocusedUIElementChanged(Node*, Node* newFocusedNod e) 1087 void AXObjectCacheImpl::handleFocusedUIElementChanged(Node*, Node* newFocusedNod e)
1196 { 1088 {
1197 if (!newFocusedNode) 1089 if (!newFocusedNode)
1090 newFocusedNode = m_document.get();
aboxhall 2015/09/22 21:48:27 This seems like a major change. Is this functional
dmazzoni 2015/09/22 22:08:44 This is more or less equivalent. Internally, a do
1091
1092 AXObject* obj = getOrCreate(newFocusedNode);
1093
1094 if (isHTMLAreaElement(newFocusedNode))
aboxhall 2015/09/22 21:48:27 Can you explain why this is now needed?
dmazzoni 2015/09/22 22:08:44 This is just coming from AXObjectCacheImpl::focuse
1095 obj = focusedImageMapUIElement(toHTMLAreaElement(newFocusedNode));
1096
1097 if (!obj)
1198 return; 1098 return;
1199 1099
1200 Page* page = newFocusedNode->document().page(); 1100 if (obj->shouldFocusActiveDescendant()) {
1201 if (!page) 1101 if (AXObject* descendant = obj->activeDescendant())
1202 return; 1102 obj = descendant;
1103 }
1203 1104
1204 AXObject* focusedObject = focusedUIElementForPage(page); 1105 if (obj->accessibilityIsIgnored())
1205 if (!focusedObject) 1106 obj = obj->parentObjectUnignored();
1206 return;
1207 1107
1208 postPlatformNotification(focusedObject, AXFocusedUIElementChanged); 1108 postPlatformNotification(obj, AXFocusedUIElementChanged);
1209 } 1109 }
1210 1110
1211 void AXObjectCacheImpl::handleInitialFocus() 1111 void AXObjectCacheImpl::handleInitialFocus()
1212 { 1112 {
1213 postNotification(m_document, AXObjectCache::AXFocusedUIElementChanged); 1113 postNotification(m_document, AXObjectCache::AXFocusedUIElementChanged);
1214 } 1114 }
1215 1115
1216 void AXObjectCacheImpl::handleEditableTextContentChanged(Node* node) 1116 void AXObjectCacheImpl::handleEditableTextContentChanged(Node* node)
1217 { 1117 {
1218 AXObject* obj = get(node); 1118 AXObject* obj = get(node);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 1170
1271 void AXObjectCacheImpl::handleScrolledToAnchor(const Node* anchorNode) 1171 void AXObjectCacheImpl::handleScrolledToAnchor(const Node* anchorNode)
1272 { 1172 {
1273 // The anchor node may not be accessible. Post the notification for the 1173 // The anchor node may not be accessible. Post the notification for the
1274 // first accessible object. 1174 // first accessible object.
1275 postPlatformNotification(firstAccessibleObjectFromNode(anchorNode), AXScroll edToAnchor); 1175 postPlatformNotification(firstAccessibleObjectFromNode(anchorNode), AXScroll edToAnchor);
1276 } 1176 }
1277 1177
1278 void AXObjectCacheImpl::handleScrollPositionChanged(FrameView* frameView) 1178 void AXObjectCacheImpl::handleScrollPositionChanged(FrameView* frameView)
1279 { 1179 {
1280 // Prefer to fire the scroll position changed event on the frame view's chil d web area, if possible. 1180 Document* doc = frameView->frame().document();
1281 AXObject* targetAXObject = getOrCreate(frameView); 1181 AXObject* targetAXObject = getOrCreate(doc);
1282 if (targetAXObject && !targetAXObject->children().isEmpty())
1283 targetAXObject = targetAXObject->children()[0].get();
1284 postPlatformNotification(targetAXObject, AXScrollPositionChanged); 1182 postPlatformNotification(targetAXObject, AXScrollPositionChanged);
1285 } 1183 }
1286 1184
1287 void AXObjectCacheImpl::handleScrollPositionChanged(LayoutObject* layoutObject) 1185 void AXObjectCacheImpl::handleScrollPositionChanged(LayoutObject* layoutObject)
1288 { 1186 {
1289 postPlatformNotification(getOrCreate(layoutObject), AXScrollPositionChanged) ; 1187 postPlatformNotification(getOrCreate(layoutObject), AXScrollPositionChanged) ;
1290 } 1188 }
1291 1189
1292 const AtomicString& AXObjectCacheImpl::computedRoleForNode(Node* node) 1190 const AtomicString& AXObjectCacheImpl::computedRoleForNode(Node* node)
1293 { 1191 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 if (!obj) 1237 if (!obj)
1340 return; 1238 return;
1341 1239
1342 obj->setElementRect(rect); 1240 obj->setElementRect(rect);
1343 } 1241 }
1344 1242
1345 DEFINE_TRACE(AXObjectCacheImpl) 1243 DEFINE_TRACE(AXObjectCacheImpl)
1346 { 1244 {
1347 #if ENABLE(OILPAN) 1245 #if ENABLE(OILPAN)
1348 visitor->trace(m_document); 1246 visitor->trace(m_document);
1349 visitor->trace(m_widgetObjectMapping);
1350 visitor->trace(m_nodeObjectMapping); 1247 visitor->trace(m_nodeObjectMapping);
1351 #endif 1248 #endif
1352 1249
1353 visitor->trace(m_objects); 1250 visitor->trace(m_objects);
1354 visitor->trace(m_notificationsToPost); 1251 visitor->trace(m_notificationsToPost);
1355 1252
1356 AXObjectCache::trace(visitor); 1253 AXObjectCache::trace(visitor);
1357 } 1254 }
1358 1255
1359 } // namespace blink 1256 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698