Changeset 287020 in webkit
- Timestamp:
- Dec 14, 2021, 2:43:09 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
-
ChangeLog (modified) (1 diff)
-
accessibility/AXObjectCache.h (modified) (1 diff)
-
accessibility/atspi/AXObjectCacheAtspi.cpp (modified) (1 diff)
-
accessibility/atspi/AccessibilityAtspi.cpp (modified) (8 diffs)
-
accessibility/atspi/AccessibilityAtspi.h (modified) (3 diffs)
-
accessibility/atspi/AccessibilityObjectAtspi.cpp (modified) (6 diffs)
-
accessibility/atspi/AccessibilityObjectAtspi.h (modified) (4 diffs)
-
accessibility/atspi/AccessibilityRootAtspi.cpp (modified) (1 diff)
-
accessibility/atspi/AccessibilityRootAtspi.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r287019 r287020 1 2021-12-14 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GTK][a11y] Register the wrappers tree when org.a11y.atspi.Cache.GetItems() is called 4 https://bugs.webkit.org/show_bug.cgi?id=234292 5 6 Reviewed by Joanmarie Diggs. 7 8 This ensures wrappers always have a reference before being added to the cache. 9 10 * accessibility/AXObjectCache.h: 11 * accessibility/atspi/AXObjectCacheAtspi.cpp: 12 (WebCore::AXObjectCache::attachWrapper): Defer the set parent call to next cache update. 13 (WebCore::AXObjectCache::platformPerformDeferredCacheUpdate): Do the set parent call here. 14 * accessibility/atspi/AccessibilityAtspi.cpp: 15 (WebCore::AccessibilityAtspi::registerObject): Do not call addAccessible from here, since it needs the path, 16 it's now called from the caller of registerObject(). 17 (WebCore::AccessibilityAtspi::parentChanged): Notify about parent property change. 18 (WebCore::AccessibilityAtspi::childrenChanged): Always emit ChildrenChanged when the tree is registered because 19 the atspi cache always consumes it. 20 (WebCore::AccessibilityAtspi::addAccessible): We no longer need to dispath addAccessible in the next run loop iteration. 21 * accessibility/atspi/AccessibilityAtspi.h: 22 * accessibility/atspi/AccessibilityObjectAtspi.cpp: 23 (WebCore::AccessibilityObjectAtspi::registerObject): Helper to register the object when path is not needed. Also 24 ensure the isolated tree is created before registering the object. 25 (WebCore::AccessibilityObjectAtspi::path): Call registerObject(). 26 (WebCore::AccessibilityObjectAtspi::hyperlinkReference): Use registerObject() instead of path(). 27 (WebCore::AccessibilityObjectAtspi::setParent): Call AccessibilityAtspi::parentChanged() if the wrapper is still 28 and attached and not ignored. 29 (WebCore::AccessibilityObjectAtspi::parentReference const): Use the parent member instead of asking the main 30 thread again. 31 (WebCore::AccessibilityObjectAtspi::isDefunct const): Return true if wrapper has been detached. 32 (WebCore::AccessibilityObjectAtspi::childAdded): We no longer need to dispatch childrenChanged in next run loop iteration. 33 * accessibility/atspi/AccessibilityObjectAtspi.h: 34 * accessibility/atspi/AccessibilityRootAtspi.cpp: 35 (WebCore::registerSubtree): Helper to register the wrappers tree recursively. 36 (WebCore::AccessibilityRootAtspi::registerTree): Register the wrappers tree. 37 * accessibility/atspi/AccessibilityRootAtspi.h: 38 1 39 2021-12-14 Darin Adler <darin@apple.com> 2 40 -
trunk/Source/WebCore/accessibility/AXObjectCache.h
r285991 r287020 528 528 ListHashSet<RefPtr<AccessibilityObject>> m_deferredAttachedWrapperObjectList; 529 529 ListHashSet<GRefPtr<AccessibilityObjectWrapper>> m_deferredDetachedWrapperList; 530 #endif 531 #if USE(ATSPI) 532 ListHashSet<RefPtr<AXCoreObject>> m_deferredParentChangedList; 530 533 #endif 531 534 }; -
trunk/Source/WebCore/accessibility/atspi/AXObjectCacheAtspi.cpp
r286767 r287020 43 43 axObject->setWrapper(wrapper.ptr()); 44 44 45 auto* axParent = axObject->parentObjectUnignored(); 46 if (!axParent) { 47 if (axObject->isScrollView() && axObject->scrollView() == document().view()) 48 wrapper->setParent(nullptr); // nullptr parent means root. 49 return; 50 } 51 52 auto* axParentWrapper = axParent->wrapper(); 53 if (!axParentWrapper) 54 return; 55 56 wrapper->setParent(axParentWrapper); 45 m_deferredParentChangedList.add(axObject); 57 46 } 58 47 59 48 void AXObjectCache::platformPerformDeferredCacheUpdate() 60 49 { 50 auto handleParentChanged = [&](const AXCoreObject& axObject) { 51 auto* wrapper = axObject.wrapper(); 52 if (!wrapper) 53 return; 54 55 auto* axParent = axObject.parentObjectUnignored(); 56 if (!axParent) { 57 if (axObject.isScrollView() && axObject.scrollView() == document().view()) 58 wrapper->setParent(nullptr); // nullptr parent means root. 59 return; 60 } 61 62 if (auto* axParentWrapper = axParent->wrapper()) 63 wrapper->setParent(axParentWrapper); 64 }; 65 66 for (const auto& axObject : m_deferredParentChangedList) 67 handleParentChanged(*axObject); 68 m_deferredParentChangedList.clear(); 61 69 } 62 70 -
trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.cpp
r287014 r287020 27 27 #include <glib/gi18n-lib.h> 28 28 #include <wtf/MainThread.h> 29 #include <wtf/SetForScope.h> 29 30 #include <wtf/SortedArrayMap.h> 30 31 #include <wtf/UUID.h> … … 124 125 m_atspiObjects.add(&atspiObject, WTFMove(registeredObjects)); 125 126 126 addAccessible(atspiObject, path);127 128 127 return path; 129 128 } … … 171 170 } 172 171 172 void AccessibilityAtspi::parentChanged(AccessibilityObjectAtspi& atspiObject) 173 { 174 RELEASE_ASSERT(isMainThread()); 175 m_queue->dispatch([this, atspiObject = Ref { atspiObject }] { 176 if (!m_connection) 177 return; 178 179 // Always emit parentChanged when the tree is registered because the atspi cache always consumes it. 180 if (!atspiObject->root().isTreeRegistered()) 181 return; 182 183 // We call path here to ensure it happens before parentReference() in case objects are not registered yet. 184 auto path = atspiObject->path(); 185 g_dbus_connection_emit_signal(m_connection.get(), nullptr, path.utf8().data(), "org.a11y.atspi.Event.Object", "PropertyChange", 186 g_variant_new("(siiva{sv})", "accessible-parent", 0, 0, atspiObject->parentReference(), nullptr), nullptr); 187 }); 188 } 189 173 190 void AccessibilityAtspi::childrenChanged(AccessibilityObjectAtspi& atspiObject, AccessibilityObjectAtspi& child, ChildrenChanged change) 174 191 { … … 176 193 m_queue->dispatch([this, atspiObject = Ref { atspiObject }, child = Ref { child }, change] { 177 194 if (!m_connection) 195 return; 196 197 // Always emit ChildrenChanged when the tree is registered because the atspi cache always consumes it. 198 if (!atspiObject->root().isTreeRegistered()) 178 199 return; 179 200 … … 416 437 if (!g_strcmp0(methodName, "GetItems")) { 417 438 auto& atspi = *static_cast<AccessibilityAtspi*>(userData); 439 SetForScope<bool> inGetItems(atspi.m_inGetItems, true); 418 440 GVariantBuilder builder = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE("(" GET_ITEMS_SIGNATURE ")")); 419 441 g_variant_builder_open(&builder, G_VARIANT_TYPE(GET_ITEMS_SIGNATURE)); 420 for ( constauto* rootObject : atspi.m_rootObjects.keys()) {442 for (auto* rootObject : atspi.m_rootObjects.keys()) { 421 443 g_variant_builder_open(&builder, G_VARIANT_TYPE("(" ITEM_SIGNATURE ")")); 444 rootObject->registerTree(); 422 445 rootObject->serialize(&builder); 423 446 g_variant_builder_close(&builder); … … 430 453 auto wrapper = atspi.m_cache.get(path); 431 454 wrapper->updateBackingStore(); 432 if (!atspi.m_cache.contains(path) )455 if (!atspi.m_cache.contains(path) || wrapper->isDefunct()) 433 456 continue; 434 457 g_variant_builder_open(&builder, G_VARIANT_TYPE("(" ITEM_SIGNATURE ")")); … … 460 483 } 461 484 462 void AccessibilityAtspi::addAccessible(AccessibilityObjectAtspi& atspiObject , const String& path)485 void AccessibilityAtspi::addAccessible(AccessibilityObjectAtspi& atspiObject) 463 486 { 464 487 RELEASE_ASSERT(!isMainThread()); … … 466 489 return; 467 490 468 auto addResult = m_cache.add( path, &atspiObject);491 auto addResult = m_cache.add(atspiObject.path(), &atspiObject); 469 492 if (!addResult.isNewEntry) 470 493 return; 471 494 472 // AddAccessible needs to be emitted after ChildrenChanged. 473 RunLoop::current().dispatch([this, atspiObject = Ref { atspiObject }, path = path.isolatedCopy()] { 474 atspiObject->updateBackingStore(); 475 if (!m_cache.contains(path)) 476 return; 477 478 GVariantBuilder builder = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE("(" ITEM_SIGNATURE ")")); 479 atspiObject->serialize(&builder); 480 g_dbus_connection_emit_signal(m_connection.get(), nullptr, "/org/a11y/atspi/cache", "org.a11y.atspi.Cache", "AddAccessible", 481 g_variant_new("(@(" ITEM_SIGNATURE "))", g_variant_builder_end(&builder)), nullptr); 482 }); 495 if (m_inGetItems) 496 return; 497 498 GVariantBuilder builder = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE("(" ITEM_SIGNATURE ")")); 499 atspiObject.serialize(&builder); 500 g_dbus_connection_emit_signal(m_connection.get(), nullptr, "/org/a11y/atspi/cache", "org.a11y.atspi.Cache", "AddAccessible", 501 g_variant_new("(@(" ITEM_SIGNATURE "))", g_variant_builder_end(&builder)), nullptr); 483 502 } 484 503 -
trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.h
r286173 r287020 55 55 String registerHyperlink(AccessibilityObjectAtspi&, Vector<std::pair<GDBusInterfaceInfo*, GDBusInterfaceVTable*>>&&); 56 56 57 void parentChanged(AccessibilityObjectAtspi&); 57 58 enum class ChildrenChanged { Added, Removed }; 58 59 void childrenChanged(AccessibilityObjectAtspi&, AccessibilityObjectAtspi&, ChildrenChanged); … … 71 72 static const char* localizedRoleName(AccessibilityRole); 72 73 74 void addAccessible(AccessibilityObjectAtspi&); 75 73 76 private: 74 77 void ensureCache(); 75 void addAccessible(AccessibilityObjectAtspi&, const String&);76 78 void removeAccessible(AccessibilityObjectAtspi&); 77 79 … … 85 87 unsigned m_cacheID { 0 }; 86 88 HashMap<String, AccessibilityObjectAtspi*> m_cache; 89 bool m_inGetItems { false }; 87 90 }; 88 91 -
trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp
r286767 r287020 482 482 }; 483 483 484 bool AccessibilityObjectAtspi::registerObject() 485 { 486 RELEASE_ASSERT(!isMainThread()); 487 if (!m_path.isNull()) 488 return false; 489 490 m_isRegistered.store(true); 491 Vector<std::pair<GDBusInterfaceInfo*, GDBusInterfaceVTable*>> interfaces; 492 if (m_interfaces.contains(Interface::Accessible)) 493 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_accessible_interface), &s_accessibleFunctions }); 494 if (m_interfaces.contains(Interface::Component)) 495 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_component_interface), &s_componentFunctions }); 496 if (m_interfaces.contains(Interface::Text)) 497 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_text_interface), &s_textFunctions }); 498 if (m_interfaces.contains(Interface::Value)) 499 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_value_interface), &s_valueFunctions }); 500 if (m_interfaces.contains(Interface::Hyperlink)) 501 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_hyperlink_interface), &s_hyperlinkFunctions }); 502 if (m_interfaces.contains(Interface::Hypertext)) 503 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_hypertext_interface), &s_hypertextFunctions }); 504 if (m_interfaces.contains(Interface::Action)) 505 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_action_interface), &s_actionFunctions }); 506 if (m_interfaces.contains(Interface::Document)) 507 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_document_interface), &s_documentFunctions }); 508 if (m_interfaces.contains(Interface::Image)) 509 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_image_interface), &s_imageFunctions }); 510 if (m_interfaces.contains(Interface::Selection)) 511 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_selection_interface), &s_selectionFunctions }); 512 if (m_interfaces.contains(Interface::Table)) 513 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_table_interface), &s_tableFunctions }); 514 if (m_interfaces.contains(Interface::TableCell)) 515 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_table_cell_interface), &s_tableCellFunctions }); 516 if (!m_axObject) { 517 // Isolated tree hasn't been created yet, call AccessibilityRootAtspi::child() 518 // to create it before registering the object. 519 Accessibility::performFunctionOnMainThread([this] { 520 m_root.child(); 521 }); 522 } 523 m_path = m_root.atspi().registerObject(*this, WTFMove(interfaces)); 524 m_root.atspi().addAccessible(*this); 525 526 return true; 527 } 528 484 529 const String& AccessibilityObjectAtspi::path() 485 530 { 486 531 RELEASE_ASSERT(!isMainThread()); 487 if (m_path.isNull()) { 488 m_isRegistered.store(true); 489 490 Vector<std::pair<GDBusInterfaceInfo*, GDBusInterfaceVTable*>> interfaces; 491 if (m_interfaces.contains(Interface::Accessible)) 492 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_accessible_interface), &s_accessibleFunctions }); 493 if (m_interfaces.contains(Interface::Component)) 494 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_component_interface), &s_componentFunctions }); 495 if (m_interfaces.contains(Interface::Text)) 496 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_text_interface), &s_textFunctions }); 497 if (m_interfaces.contains(Interface::Value)) 498 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_value_interface), &s_valueFunctions }); 499 if (m_interfaces.contains(Interface::Hyperlink)) 500 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_hyperlink_interface), &s_hyperlinkFunctions }); 501 if (m_interfaces.contains(Interface::Hypertext)) 502 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_hypertext_interface), &s_hypertextFunctions }); 503 if (m_interfaces.contains(Interface::Action)) 504 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_action_interface), &s_actionFunctions }); 505 if (m_interfaces.contains(Interface::Document)) 506 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_document_interface), &s_documentFunctions }); 507 if (m_interfaces.contains(Interface::Image)) 508 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_image_interface), &s_imageFunctions }); 509 if (m_interfaces.contains(Interface::Selection)) 510 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_selection_interface), &s_selectionFunctions }); 511 if (m_interfaces.contains(Interface::Table)) 512 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_table_interface), &s_tableFunctions }); 513 if (m_interfaces.contains(Interface::TableCell)) 514 interfaces.append({ const_cast<GDBusInterfaceInfo*>(&webkit_table_cell_interface), &s_tableCellFunctions }); 515 m_path = m_root.atspi().registerObject(*this, WTFMove(interfaces)); 516 } 517 532 registerObject(); 518 533 return m_path; 519 534 } … … 529 544 RELEASE_ASSERT(!isMainThread()); 530 545 if (m_hyperlinkPath.isNull()) { 531 path();546 registerObject(); 532 547 m_hyperlinkPath = m_root.atspi().registerHyperlink(*this, { { const_cast<GDBusInterfaceInfo*>(&webkit_hyperlink_interface), &s_hyperlinkFunctions } }); 533 548 } … … 543 558 544 559 m_parent = atspiParent; 560 if (!m_coreObject || m_coreObject->accessibilityIsIgnored()) 561 return; 562 563 m_root.atspi().parentChanged(*this); 545 564 if (m_parent && *m_parent) 546 565 m_parent.value()->childAdded(*this); … … 565 584 GVariant* AccessibilityObjectAtspi::parentReference() const 566 585 { 567 auto parentAtspi = parent(); 568 if (!parentAtspi) 586 if (!m_parent) 569 587 return m_root.atspi().nullReference(); 570 588 571 if (! parentAtspi.value())589 if (!m_parent.value()) 572 590 return m_root.reference(); 573 591 574 return parentAtspi.value()->reference();592 return m_parent.value()->reference(); 575 593 } 576 594 … … 847 865 848 866 return states; 867 }); 868 } 869 870 bool AccessibilityObjectAtspi::isDefunct() const 871 { 872 return Accessibility::retrieveValueFromMainThread<bool>([this]() -> bool { 873 return !m_coreObject; 849 874 }); 850 875 } … … 1189 1214 return; 1190 1215 1191 RunLoop::main().dispatch([this, protectedThis = Ref { *this }, child = Ref { child }] { 1192 if (!m_coreObject) 1193 return; 1194 m_root.atspi().childrenChanged(*this, child, AccessibilityAtspi::ChildrenChanged::Added); 1195 }); 1216 m_root.atspi().childrenChanged(*this, child, AccessibilityAtspi::ChildrenChanged::Added); 1196 1217 } 1197 1218 -
trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.h
r286767 r287020 42 42 ~AccessibilityObjectAtspi() = default; 43 43 44 bool registerObject(); 45 44 46 enum class Interface : uint16_t { 45 47 Accessible = 1 << 0, … … 61 63 void setParent(std::optional<AccessibilityObjectAtspi*>); 62 64 WEBCORE_EXPORT std::optional<AccessibilityObjectAtspi*> parent() const; 65 GVariant* parentReference() const; 63 66 WEBCORE_EXPORT void updateBackingStore(); 64 67 … … 84 87 WEBCORE_EXPORT AccessibilityObjectAtspi* childAt(unsigned) const; 85 88 WEBCORE_EXPORT uint64_t state() const; 89 bool isDefunct() const; 86 90 void stateChanged(const char*, bool); 87 91 WEBCORE_EXPORT HashMap<String, String> attributes() const; … … 158 162 Vector<RefPtr<AccessibilityObjectAtspi>> wrapperVector(const Vector<RefPtr<AXCoreObject>>&) const; 159 163 int indexInParent() const; 160 GVariant* parentReference() const;161 164 void childAdded(AccessibilityObjectAtspi&); 162 165 void childRemoved(AccessibilityObjectAtspi&); -
trunk/Source/WebCore/accessibility/atspi/AccessibilityRootAtspi.cpp
r287014 r287020 186 186 if (m_page) 187 187 m_page->setAccessibilityRootObject(nullptr); 188 } 189 190 static void registerSubtree(AccessibilityObjectAtspi* atspiObject) 191 { 192 if (!atspiObject) 193 return; 194 195 if (!atspiObject->registerObject()) 196 return; 197 198 atspiObject->updateBackingStore(); 199 for (auto& child : atspiObject->children()) 200 registerSubtree(child.get()); 201 } 202 203 void AccessibilityRootAtspi::registerTree() 204 { 205 RELEASE_ASSERT(!isMainThread()); 206 if (m_parentUniqueName.isNull()) 207 return; 208 209 registerSubtree(Accessibility::retrieveValueFromMainThread<AccessibilityObjectAtspi*>([this]() -> AccessibilityObjectAtspi* { 210 return child(); 211 })); 212 m_isTreeRegistered.store(true); 188 213 } 189 214 -
trunk/Source/WebCore/accessibility/atspi/AccessibilityRootAtspi.h
r287014 r287020 23 23 #include "AccessibilityAtspi.h" 24 24 #include "IntRect.h" 25 #include <wtf/Atomics.h> 25 26 #include <wtf/FastMalloc.h> 26 27 #include <wtf/ThreadSafeRefCounted.h> … … 41 42 void registerObject(CompletionHandler<void(const String&)>&&); 42 43 void unregisterObject(); 44 void registerTree(); 45 bool isTreeRegistered() const { return m_isTreeRegistered.load(); } 43 46 void setPath(String&&); 44 47 … … 67 70 String m_parentUniqueName; 68 71 String m_parentPath; 72 Atomic<bool> m_isTreeRegistered { false }; 69 73 }; 70 74
Note:
See TracChangeset
for help on using the changeset viewer.