Focus tracking support in the accessibility isolatedtree.
authorandresg_22@apple.com <andresg_22@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Dec 2019 03:44:53 +0000 (03:44 +0000)
committerandresg_22@apple.com <andresg_22@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Dec 2019 03:44:53 +0000 (03:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204535

Reviewed by Chris Fleizach.

Source/WebCore:

The AXIsolatedTree focused object is now set during the tree generation.
It is updated on handleFocusedUIElementChanged.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::focusedImageMapUIElement):
(WebCore::AXObjectCache::focusedObject):
(WebCore::AXObjectCache::isolatedTreeFocusedObject):
(WebCore::AXObjectCache::setIsolatedTreeFocusedObject):
(WebCore::AXObjectCache::focusedUIElementForPage):
(WebCore::AXObjectCache::isolatedTreeRootObject):
(WebCore::AXObjectCache::handleFocusedUIElementChanged):
(WebCore::AXObjectCache::createIsolatedTreeHierarchy):
(WebCore::AXObjectCache::generateIsolatedTree):
* accessibility/AXObjectCache.h:
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::focusedUIElement const):

Source/WebKit:

* WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
(WKAccessibilityFocusedObject):

Tools:

FocusElement can run on the secondary AXThread.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::focusedElement):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253088 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/accessibility/AXObjectCache.h
Source/WebCore/accessibility/AccessibilityObject.cpp
Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp

index 2ce99e2..cb39972 100644 (file)
@@ -1,3 +1,27 @@
+2019-12-03  Andres Gonzalez  <andresg_22@apple.com>
+
+        Focus tracking support in the accessibility isolatedtree.
+        https://bugs.webkit.org/show_bug.cgi?id=204535
+
+        Reviewed by Chris Fleizach.
+
+        The AXIsolatedTree focused object is now set during the tree generation.
+        It is updated on handleFocusedUIElementChanged.
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::focusedImageMapUIElement):
+        (WebCore::AXObjectCache::focusedObject):
+        (WebCore::AXObjectCache::isolatedTreeFocusedObject):
+        (WebCore::AXObjectCache::setIsolatedTreeFocusedObject):
+        (WebCore::AXObjectCache::focusedUIElementForPage):
+        (WebCore::AXObjectCache::isolatedTreeRootObject):
+        (WebCore::AXObjectCache::handleFocusedUIElementChanged):
+        (WebCore::AXObjectCache::createIsolatedTreeHierarchy):
+        (WebCore::AXObjectCache::generateIsolatedTree):
+        * accessibility/AXObjectCache.h:
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::focusedUIElement const):
+
 2019-12-03  Ryosuke Niwa  <rniwa@webkit.org>
 
         Use the event loop instead of DocumentEventQueue and WorkerEventQueue
index e2ac72a..03e6004 100644 (file)
@@ -348,32 +348,86 @@ AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* ar
     
     return nullptr;
 }
-    
-AXCoreObject* AXObjectCache::focusedUIElementForPage(const Page* page)
-{
-    if (!gAccessibilityEnabled)
-        return nullptr;
 
-    // get the focused node in the page
-    Document* focusedDocument = page->focusController().focusedOrMainFrame().document();
-    Element* focusedElement = focusedDocument->focusedElement();
+AXCoreObject* AXObjectCache::focusedObject(Document& document)
+{
+    Element* focusedElement = document.focusedElement();
     if (is<HTMLAreaElement>(focusedElement))
         return focusedImageMapUIElement(downcast<HTMLAreaElement>(focusedElement));
 
-    AXCoreObject* obj = focusedDocument->axObjectCache()->getOrCreate(focusedElement ? static_cast<Node*>(focusedElement) : focusedDocument);
-    if (!obj)
+    auto* axObjectCache = document.axObjectCache();
+    if (!axObjectCache)
+        return nullptr;
+
+    AXCoreObject* focus = axObjectCache->getOrCreate(focusedElement ? focusedElement : static_cast<Node*>(&document));
+    if (!focus)
         return nullptr;
 
-    if (obj->shouldFocusActiveDescendant()) {
-        if (AXCoreObject* descendant = obj->activeDescendant())
-            obj = descendant;
+    if (focus->shouldFocusActiveDescendant()) {
+        if (auto* descendant = focus->activeDescendant())
+            focus = descendant;
     }
 
     // the HTML element, for example, is focusable but has an AX object that is ignored
-    if (obj->accessibilityIsIgnored())
-        obj = obj->parentObjectUnignored();
+    if (focus->accessibilityIsIgnored())
+        focus = focus->parentObjectUnignored();
 
-    return obj;
+    return focus;
+}
+
+#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
+AXCoreObject* AXObjectCache::isolatedTreeFocusedObject(Document& document)
+{
+    auto pageID = document.pageID();
+    if (!pageID)
+        return nullptr;
+
+    auto tree = AXIsolatedTree::treeForPageID(*pageID);
+    if (!tree) {
+        tree = generateIsolatedTree(*pageID, document);
+        // Now that we have created our tree, initialize the secondary thread,
+        // so future requests come in on the other thread.
+        _AXUIElementUseSecondaryAXThread(true);
+    }
+
+    if (tree)
+        return tree->focusedUIElement().get();
+
+    // Should not get here, couldn't create the IsolatedTree.
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+void AXObjectCache::setIsolatedTreeFocusedObject(Node* focusedNode)
+{
+    ASSERT(isMainThread());
+    auto* focus = getOrCreate(focusedNode);
+    auto pageID = m_document.pageID();
+    if (!pageID)
+        return;
+
+    if (auto tree = AXIsolatedTree::treeForPageID(*pageID))
+        tree->setFocusedNodeID(focus ? focus->objectID() : InvalidAXID);
+}
+#endif
+
+AXCoreObject* AXObjectCache::focusedUIElementForPage(const Page* page)
+{
+    ASSERT(isMainThread());
+    if (!gAccessibilityEnabled)
+        return nullptr;
+
+    // get the focused node in the page
+    Document* focusedDocument = page->focusController().focusedOrMainFrame().document();
+    if (!focusedDocument)
+        return nullptr;
+
+#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
+    if (clientSupportsIsolatedTree())
+        return isolatedTreeFocusedObject(*focusedDocument);
+#endif
+
+    return focusedObject(*focusedDocument);
 }
 
 AccessibilityObject* AXObjectCache::get(Widget* widget)
@@ -687,7 +741,7 @@ AXCoreObject* AXObjectCache::isolatedTreeRootObject()
 
     auto tree = AXIsolatedTree::treeForPageID(*pageID);
     if (!tree && isMainThread()) {
-        tree = generateIsolatedTree(*pageID);
+        tree = generateIsolatedTree(*pageID, m_document);
         // Now that we have created our tree, initialize the secondary thread,
         // so future requests come in on the other thread.
         _AXUIElementUseSecondaryAXThread(true);
@@ -700,7 +754,7 @@ AXCoreObject* AXObjectCache::isolatedTreeRootObject()
     }
 
     // Should not get here, couldn't create or update the IsolatedTree.
-    ASSERT(false);
+    ASSERT_NOT_REACHED();
     return nullptr;
 }
 #endif
@@ -1103,6 +1157,10 @@ void AXObjectCache::deferFocusedUIElementChangeIfNeeded(Node* oldNode, Node* new
     
 void AXObjectCache::handleFocusedUIElementChanged(Node* oldNode, Node* newNode)
 {
+#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
+    setIsolatedTreeFocusedObject(newNode);
+#endif
+
     handleMenuItemSelected(newNode);
     platformHandleFocusedUIElementChanged(oldNode, newNode);
 }
@@ -3006,36 +3064,48 @@ void AXObjectCache::performDeferredCacheUpdate()
 }
     
 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
-Ref<AXIsolatedObject> AXObjectCache::createIsolatedTreeHierarchy(AXCoreObject& object, AXID parentID, AXIsolatedTree& tree, Vector<Ref<AXIsolatedObject>>& nodeChanges)
+Ref<AXIsolatedObject> AXObjectCache::createIsolatedTreeHierarchy(AXCoreObject& object, AXID parentID, AXObjectCache* axObjectCache, AXIsolatedTree& tree, Vector<Ref<AXIsolatedObject>>& nodeChanges)
 {
     auto isolatedTreeNode = AXIsolatedObject::create(object);
     nodeChanges.append(isolatedTreeNode.copyRef());
 
     isolatedTreeNode->setTreeIdentifier(tree.treeIdentifier());
     isolatedTreeNode->setParent(parentID);
-    attachWrapper(&isolatedTreeNode.get());
+    axObjectCache->attachWrapper(&isolatedTreeNode.get());
 
     for (const auto& child : object.children()) {
-        auto staticChild = createIsolatedTreeHierarchy(*child, isolatedTreeNode->objectID(), tree, nodeChanges);
+        auto staticChild = createIsolatedTreeHierarchy(*child, isolatedTreeNode->objectID(), axObjectCache, tree, nodeChanges);
         isolatedTreeNode->appendChild(staticChild->objectID());
     }
 
     return isolatedTreeNode;
 }
-    
-Ref<AXIsolatedTree> AXObjectCache::generateIsolatedTree(PageIdentifier pageID)
+
+Ref<AXIsolatedTree> AXObjectCache::generateIsolatedTree(PageIdentifier pageID, Document& document)
 {
     RELEASE_ASSERT(isMainThread());
 
     auto tree = AXIsolatedTree::treeForPageID(pageID);
     if (!tree)
         tree = AXIsolatedTree::createTreeForPageID(pageID);
-    
-    Vector<Ref<AXIsolatedObject>> nodeChanges;
-    AccessibilityObject* axRoot = getOrCreate(m_document.view());
-    auto isolatedRoot = createIsolatedTreeHierarchy(*axRoot, InvalidAXID, *tree, nodeChanges);
-    tree->setRoot(isolatedRoot);
-    tree->appendNodeChanges(nodeChanges);
+
+    // Set the root and focused objects in the isolated tree. For that, we need
+    // the root and the focused object in the AXObject tree.
+    auto* axObjectCache = document.axObjectCache();
+    if (!axObjectCache)
+        return makeRef(*tree);
+
+    auto* axRoot = axObjectCache->getOrCreate(document.view());
+    if (axRoot) {
+        Vector<Ref<AXIsolatedObject>> nodeChanges;
+        auto isolatedRoot = createIsolatedTreeHierarchy(*axRoot, InvalidAXID, axObjectCache, *tree, nodeChanges);
+        tree->setRoot(isolatedRoot);
+        tree->appendNodeChanges(nodeChanges);
+    }
+
+    auto* axFocus = axObjectCache->focusedObject(document);
+    if (axFocus)
+        tree->setFocusedNodeID(axFocus->objectID());
 
     return makeRef(*tree);
 }
index c013ec0..e59e220 100644 (file)
@@ -195,8 +195,10 @@ public:
     WEBCORE_EXPORT static bool clientSupportsIsolatedTree();
 private:
     AXCoreObject* isolatedTreeRootObject();
-    Ref<AXIsolatedTree> generateIsolatedTree(PageIdentifier);
-    Ref<AXIsolatedObject> createIsolatedTreeHierarchy(AXCoreObject&, AXID, AXIsolatedTree&, Vector<Ref<AXIsolatedObject>>&);
+    static AXCoreObject* isolatedTreeFocusedObject(Document&);
+    void setIsolatedTreeFocusedObject(Node*);
+    static Ref<AXIsolatedTree> generateIsolatedTree(PageIdentifier, Document&);
+    static Ref<AXIsolatedObject> createIsolatedTreeHierarchy(AXCoreObject&, AXID, AXObjectCache*, AXIsolatedTree&, Vector<Ref<AXIsolatedObject>>&);
 #endif
 
 public:
@@ -413,6 +415,7 @@ private:
     AccessibilityObject* rootWebArea();
 
     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
+    static AXCoreObject* focusedObject(Document&);
 
     AXID getAXID(AccessibilityObject*);
 
index 461e4bf..80ac1ee 100644 (file)
@@ -2867,7 +2867,8 @@ AXObjectCache* AccessibilityObject::axObjectCache() const
 AXCoreObject* AccessibilityObject::focusedUIElement() const
 {
     auto* page = this->page();
-    return page ? AXObjectCache::focusedUIElementForPage(page) : nullptr;
+    auto* axObjectCache = this->axObjectCache();
+    return page && axObjectCache ? axObjectCache->focusedUIElementForPage(page) : nullptr;
 }
     
 AccessibilitySortDirection AccessibilityObject::sortDirection() const
index 07cbc2b..5d3fcba 100644 (file)
@@ -106,6 +106,7 @@ RefPtr<AXIsolatedObject> AXIsolatedTree::nodeForID(AXID axID) const
 
 RefPtr<AXIsolatedObject> AXIsolatedTree::focusedUIElement()
 {
+    m_focusedNodeID = m_pendingFocusedNodeID;
     return nodeForID(m_focusedNodeID);
 }
     
index bda9bb9..3a5f7ed 100644 (file)
@@ -1,3 +1,13 @@
+2019-12-03  Andres Gonzalez  <andresg_22@apple.com>
+
+        Focus tracking support in the accessibility isolatedtree.
+        https://bugs.webkit.org/show_bug.cgi?id=204535
+
+        Reviewed by Chris Fleizach.
+
+        * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
+        (WKAccessibilityFocusedObject):
+
 2019-12-03  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics (experimental): Delete non-cookie website data after 7 days of no user interaction
index efb3694..c6c2a6a 100644 (file)
@@ -58,6 +58,7 @@
 #include <WebCore/AXObjectCache.h>
 #include <WebCore/AccessibilityObjectInterface.h>
 #include <WebCore/ApplicationCacheStorage.h>
+#include <WebCore/FocusController.h>
 #include <WebCore/Frame.h>
 #include <WebCore/Page.h>
 #include <WebCore/PageOverlay.h>
@@ -269,9 +270,17 @@ void* WKAccessibilityFocusedObject(WKBundlePageRef pageRef)
     if (!page)
         return 0;
 
+    auto* focusedDocument = page->focusController().focusedOrMainFrame().document();
+    if (!focusedDocument)
+        return 0;
+
     WebCore::AXObjectCache::enableAccessibility();
 
-    WebCore::AXCoreObject* focusedObject = WebCore::AXObjectCache::focusedUIElementForPage(page);
+    auto* axObjectCache = focusedDocument->axObjectCache();
+    if (!axObjectCache)
+        return 0;
+
+    auto* focusedObject = axObjectCache->focusedUIElementForPage(page);
     if (!focusedObject)
         return 0;
     
index de6855c..a825384 100644 (file)
@@ -1,3 +1,15 @@
+2019-12-03  Andres Gonzalez  <andresg_22@apple.com>
+
+        Focus tracking support in the accessibility isolatedtree.
+        https://bugs.webkit.org/show_bug.cgi?id=204535
+
+        Reviewed by Chris Fleizach.
+
+        FocusElement can run on the secondary AXThread.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
+        (WTR::AccessibilityController::focusedElement):
+
 2019-12-03  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics (experimental): Delete non-cookie website data after 7 days of no user interaction
index 160a2e0..f8a3486 100644 (file)
@@ -99,9 +99,8 @@ Ref<AccessibilityUIElement> AccessibilityController::rootElement()
 Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
 {
     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
-    void* root = WKAccessibilityFocusedObject(page);
-    
-    return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));    
+    PlatformUIElement focusedElement = static_cast<PlatformUIElement>(WKAccessibilityFocusedObject(page));
+    return AccessibilityUIElement::create(focusedElement);
 }
 
 void AccessibilityController::execute(Function<void()>&& function)