Isolated object implementation of parameterized attribute SelectTextWithCriteria.
authorandresg_22@apple.com <andresg_22@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Dec 2019 18:47:54 +0000 (18:47 +0000)
committerandresg_22@apple.com <andresg_22@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Dec 2019 18:47:54 +0000 (18:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=205210

Reviewed by Chris Fleizach.

Source/WebCore:

LayoutTests/accessibility/mac/find-and-replace-match-capitalization.html exercise this functionality.

Requests for parameterized attributes that require computations in
the WebCore DOM need to be dispatched to the main thread. This
change is the blueprint for all other attributes to follow.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::isolatedTreeRootObject): The isolated tree root object is always retrieved in the main thread.
(WebCore::AXObjectCache::generateIsolatedTree): Sets the AXObjectCache for the generated IsolatedTree.
* accessibility/AccessibilityObjectInterface.h: Added the template functions to dispatch to the main thread.
(WebCore::Accessibility::performFunctionOnMainThread):
(WebCore::Accessibility::retrieveValueFromMainThread):
* accessibility/AccessibilityRenderObject.cpp: Removed obsolete asserts.
(WebCore::AccessibilityRenderObject::visibleChildren):
(WebCore::AccessibilityRenderObject::tabChildren):
* accessibility/isolatedtree/AXIsolatedTree.h: It now holds a reference to the AXObjectCache.
(WebCore::AXIsolatedTree::axObjectCache const):
(WebCore::AXIsolatedTree::setAXObjectCache):
* accessibility/isolatedtree/AXIsolatedTreeNode.cpp:
(WebCore::AXIsolatedObject::findTextRanges const):
(WebCore::AXIsolatedObject::performTextOperation):
(WebCore::AXIsolatedObject::axObjectCache const):
* accessibility/isolatedtree/AXIsolatedTreeNode.h:
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm: Moved template functions to dispatch to the main thread into the Accessibility namespace to use them in the isolated object implementation.
(-[WebAccessibilityObjectWrapper attachmentView]):
(-[WebAccessibilityObjectWrapper renderWidgetChildren]):
(-[WebAccessibilityObjectWrapper associatedPluginParent]):
(-[WebAccessibilityObjectWrapper scrollViewParent]):
(-[WebAccessibilityObjectWrapper windowElement:]):
(-[WebAccessibilityObjectWrapper accessibilityShowContextMenu]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
(performAccessibilityFunctionOnMainThread): Moved.
(retrieveAccessibilityValueFromMainThread): Moved.

Tools:

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::rootElement): Always run in my thread.
(WTR::AccessibilityController::execute): Dispatches to the secondary thread. Spins the main loop to allow parameterized attributes methods to execute in main thread.
* WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
(WTR::findAccessibleObjectById):
(WTR::AccessibilityController::accessibleElementById):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::selectTextWithCriteria):

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

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/accessibility/AccessibilityObjectInterface.h
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.h
Source/WebCore/accessibility/isolatedtree/AXIsolatedTreeNode.cpp
Source/WebCore/accessibility/isolatedtree/AXIsolatedTreeNode.h
Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp
Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h
Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm
Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm

index e0da59a..c76e36c 100644 (file)
@@ -1,3 +1,44 @@
+2019-12-16  Andres Gonzalez  <andresg_22@apple.com>
+
+        Isolated object implementation of parameterized attribute SelectTextWithCriteria.
+        https://bugs.webkit.org/show_bug.cgi?id=205210
+
+        Reviewed by Chris Fleizach.
+
+        LayoutTests/accessibility/mac/find-and-replace-match-capitalization.html exercise this functionality.
+
+        Requests for parameterized attributes that require computations in
+        the WebCore DOM need to be dispatched to the main thread. This
+        change is the blueprint for all other attributes to follow.
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::isolatedTreeRootObject): The isolated tree root object is always retrieved in the main thread.
+        (WebCore::AXObjectCache::generateIsolatedTree): Sets the AXObjectCache for the generated IsolatedTree.
+        * accessibility/AccessibilityObjectInterface.h: Added the template functions to dispatch to the main thread.
+        (WebCore::Accessibility::performFunctionOnMainThread):
+        (WebCore::Accessibility::retrieveValueFromMainThread):
+        * accessibility/AccessibilityRenderObject.cpp: Removed obsolete asserts.
+        (WebCore::AccessibilityRenderObject::visibleChildren):
+        (WebCore::AccessibilityRenderObject::tabChildren):
+        * accessibility/isolatedtree/AXIsolatedTree.h: It now holds a reference to the AXObjectCache.
+        (WebCore::AXIsolatedTree::axObjectCache const):
+        (WebCore::AXIsolatedTree::setAXObjectCache):
+        * accessibility/isolatedtree/AXIsolatedTreeNode.cpp:
+        (WebCore::AXIsolatedObject::findTextRanges const):
+        (WebCore::AXIsolatedObject::performTextOperation):
+        (WebCore::AXIsolatedObject::axObjectCache const):
+        * accessibility/isolatedtree/AXIsolatedTreeNode.h:
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm: Moved template functions to dispatch to the main thread into the Accessibility namespace to use them in the isolated object implementation.
+        (-[WebAccessibilityObjectWrapper attachmentView]):
+        (-[WebAccessibilityObjectWrapper renderWidgetChildren]):
+        (-[WebAccessibilityObjectWrapper associatedPluginParent]):
+        (-[WebAccessibilityObjectWrapper scrollViewParent]):
+        (-[WebAccessibilityObjectWrapper windowElement:]):
+        (-[WebAccessibilityObjectWrapper accessibilityShowContextMenu]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+        (performAccessibilityFunctionOnMainThread): Moved.
+        (retrieveAccessibilityValueFromMainThread): Moved.
+
 2019-12-16  youenn fablet  <youenn@apple.com>
 
         Consider top-level context whose origin is unique as insecure
index 5a20244..f86f373 100644 (file)
@@ -735,25 +735,23 @@ AXCoreObject* AXObjectCache::rootObject()
 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
 AXCoreObject* AXObjectCache::isolatedTreeRootObject()
 {
+    ASSERT(isMainThread());
     auto pageID = m_document.pageID();
     if (!pageID)
         return nullptr;
 
     auto tree = AXIsolatedTree::treeForPageID(*pageID);
-    if (!tree && isMainThread()) {
+    if (!tree) {
         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);
-        return tree->rootNode().get();
     }
 
-    if (tree && !isMainThread()) {
-        tree->applyPendingChanges();
+    if (tree)
         return tree->rootNode().get();
-    }
 
-    // Should not get here, couldn't create or update the IsolatedTree.
+    // Should not get here, couldn't create the IsolatedTree.
     ASSERT_NOT_REACHED();
     return nullptr;
 }
@@ -3094,6 +3092,7 @@ Ref<AXIsolatedTree> AXObjectCache::generateIsolatedTree(PageIdentifier pageID, D
     auto* axObjectCache = document.axObjectCache();
     if (!axObjectCache)
         return makeRef(*tree);
+    tree->setAXObjectCache(axObjectCache);
 
     auto* axRoot = axObjectCache->getOrCreate(document.view());
     if (axRoot) {
index 91b9823..ff44f77 100644 (file)
@@ -1129,6 +1129,28 @@ T* findAncestor(const T& object, bool includeSelf, const F& matches)
     return nullptr;
 }
 
+template<typename U> inline void performFunctionOnMainThread(U&& lambda)
+{
+    if (isMainThread())
+        return lambda();
+
+    callOnMainThread([&lambda] {
+        lambda();
+    });
+}
+
+template<typename T, typename U> inline T retrieveValueFromMainThread(U&& lambda)
+{
+    if (isMainThread())
+        return lambda();
+
+    T value;
+    callOnMainThreadAndWait([&value, &lambda] {
+        value = lambda();
+    });
+    return value;
+}
+
 } // namespace Accessibility
 
 } // namespace WebCore
index b7da6aa..a87237c 100644 (file)
@@ -3562,20 +3562,19 @@ void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildren
 void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& result)
 {
     ASSERT(result.isEmpty());
-        
-    // only listboxes are asked for their visible children. 
-    if (ariaRoleAttribute() != AccessibilityRole::ListBox) {
-        // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
-        ASSERT_NOT_REACHED();
+
+    // Only listboxes are asked for their visible children.
+    // Native list boxes would be AccessibilityListBoxes, so only check for aria list boxes.
+    if (ariaRoleAttribute() != AccessibilityRole::ListBox)
         return;
-    }
     return ariaListboxVisibleChildren(result);
 }
  
 void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
 {
-    ASSERT(roleValue() == AccessibilityRole::TabList);
-    
+    if (roleValue() != AccessibilityRole::TabList)
+        return;
+
     for (const auto& child : children()) {
         if (child->isTabItem())
             result.append(child);
index 9efb22b..68f5231 100644 (file)
@@ -47,6 +47,8 @@ public:
     WEBCORE_EXPORT static Ref<AXIsolatedTree> createTreeForPageID(PageIdentifier);
     WEBCORE_EXPORT static RefPtr<AXIsolatedTree> treeForPageID(PageIdentifier);
     WEBCORE_EXPORT static RefPtr<AXIsolatedTree> treeForID(AXIsolatedTreeID);
+    AXObjectCache* axObjectCache() const { return m_axObjectCache; }
+    void setAXObjectCache(AXObjectCache* axObjectCache) { m_axObjectCache = axObjectCache; }
 
     WEBCORE_EXPORT RefPtr<AXIsolatedObject> rootNode();
     WEBCORE_EXPORT RefPtr<AXIsolatedObject> focusedUIElement();
@@ -71,6 +73,8 @@ private:
     static HashMap<AXIsolatedTreeID, Ref<AXIsolatedTree>>& treeIDCache();
     static HashMap<PageIdentifier, Ref<AXIsolatedTree>>& treePageCache();
 
+    AXObjectCache* m_axObjectCache { nullptr };
+
     // Only access on AX thread requesting data.
     HashMap<AXID, Ref<AXIsolatedObject>> m_readerThreadNodeMap;
 
index 71e5dc2..f5b0dea 100644 (file)
@@ -693,6 +693,20 @@ void AXIsolatedObject::updateBackingStore()
     }
 }
 
+Vector<RefPtr<Range>> AXIsolatedObject::findTextRanges(AccessibilitySearchTextCriteria const& criteria) const
+{
+    return Accessibility::retrieveValueFromMainThread<Vector<RefPtr<Range>>>([&criteria, axID = objectID(), this] () -> Vector<RefPtr<Range>> {
+        return axObjectCache()->objectFromAXID(axID)->findTextRanges(criteria);
+    });
+}
+
+Vector<String> AXIsolatedObject::performTextOperation(AccessibilityTextOperation const& textOperation)
+{
+    return Accessibility::retrieveValueFromMainThread<Vector<String>>([&textOperation, axID = objectID(), this] () -> Vector<String> {
+        return axObjectCache()->objectFromAXID(axID)->performTextOperation(textOperation);
+    });
+}
+
 bool AXIsolatedObject::replaceTextInRange(const String&, const PlainTextRange&)
 {
     ASSERT_NOT_REACHED();
@@ -1331,8 +1345,7 @@ void AXIsolatedObject::elementsFromAttribute(Vector<Element*>&, const QualifiedN
 
 AXObjectCache* AXIsolatedObject::axObjectCache() const
 {
-    ASSERT_NOT_REACHED();
-    return nullptr;
+    return tree()->axObjectCache();
 }
 
 Element* AXIsolatedObject::anchorElement() const
index 9dae2f1..aea8fc1 100644 (file)
@@ -521,6 +521,10 @@ private:
     bool isBusy() const override { return boolAttributeValue(AXPropertyName::IsBusy); }
     bool isInlineText() const override { return boolAttributeValue(AXPropertyName::IsInlineText); }
 
+    // Parameterized attribute retrieval.
+    Vector<RefPtr<Range>> findTextRanges(AccessibilitySearchTextCriteria const&) const override;
+    Vector<String> performTextOperation(AccessibilityTextOperation const&) override;
+
     // Attributes retrieved from the root node only so that the data isn't duplicated on each node.
     uint64_t sessionID() const override;
     String documentURI() const override;
@@ -598,8 +602,6 @@ private:
     String textUnderElement(AccessibilityTextUnderElementMode = AccessibilityTextUnderElementMode()) const override { return String(); }
     RefPtr<Range> getMisspellingRange(RefPtr<Range> const&, AccessibilitySearchDirection) const override { return nullptr; }
     void findMatchingObjects(AccessibilitySearchCriteria*, AccessibilityChildrenVector&) override { }
-    Vector<RefPtr<Range>> findTextRanges(AccessibilitySearchTextCriteria const&) const override { return Vector<RefPtr<Range>>(); }
-    Vector<String> performTextOperation(AccessibilityTextOperation const&) override { return Vector<String>(); }
     FloatRect convertFrameToSpace(const FloatRect&, AccessibilityConversionSpace) const override { return FloatRect(); }
     void increment() override { }
     void decrement() override { }
index 66932d4..becbcfe 100644 (file)
@@ -555,33 +555,11 @@ extern "C" AXUIElementRef NSAccessibilityCreateAXUIElementRef(id element);
     [super detach];
 }
 
-template<typename U> inline void performAccessibilityFunctionOnMainThread(U&& lambda)
-{
-    if (isMainThread())
-        return lambda();
-
-    callOnMainThread([&lambda] {
-        lambda();
-    });
-}
-
-template<typename T, typename U> inline T retrieveAccessibilityValueFromMainThread(U&& lambda)
-{
-    if (isMainThread())
-        return lambda();
-    
-    T value;
-    callOnMainThreadAndWait([&value, &lambda] {
-        value = lambda();
-    });
-    return value;
-}
-
 - (id)attachmentView
 {
     ASSERT(m_object->isAttachment());
 
-    return retrieveAccessibilityValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
+    return Accessibility::retrieveValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
         auto* widget = protectedSelf->m_object->widgetForAttachmentView();
         if (!widget)
             return nil;
@@ -1920,7 +1898,7 @@ ALLOW_DEPRECATED_IMPLEMENTATIONS_END
 
 - (NSArray*)renderWidgetChildren
 {
-    return retrieveAccessibilityValueFromMainThread<NSArray *>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> NSArray * {
+    return Accessibility::retrieveValueFromMainThread<NSArray *>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> NSArray * {
         Widget* widget = protectedSelf->m_object->widget();
         if (!widget)
             return nil;
@@ -1973,7 +1951,7 @@ static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
 
 - (id)associatedPluginParent
 {
-    return retrieveAccessibilityValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
+    return Accessibility::retrieveValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
         if (!protectedSelf->m_object || !protectedSelf->m_object->hasApplePDFAnnotationAttribute())
             return nil;
     
@@ -2326,7 +2304,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
 - (id)scrollViewParent
 {
-    return retrieveAccessibilityValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
+    return Accessibility::retrieveValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
         if (!is<AccessibilityScrollView>(protectedSelf->m_object))
             return nil;
 
@@ -2371,7 +2349,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
 - (id)windowElement:(NSString*)attributeName
 {
-    return retrieveAccessibilityValueFromMainThread<id>([attributeName, protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
+    return Accessibility::retrieveValueFromMainThread<id>([attributeName, protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> id {
         id remoteParent = [protectedSelf remoteAccessibilityParentObject];
         if (remoteParent) {
             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
@@ -3497,7 +3475,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
 - (void)accessibilityShowContextMenu
 {
-    performAccessibilityFunctionOnMainThread([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] {
+    Accessibility::performFunctionOnMainThread([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] {
         [protectedSelf _accessibilityShowContextMenu];
     });
 }
@@ -3925,10 +3903,12 @@ ALLOW_DEPRECATED_IMPLEMENTATIONS_END
     // dispatch
     if ([attribute isEqualToString:NSAccessibilitySelectTextWithCriteriaParameterizedAttribute]) {
         // To be deprecated.
-        auto criteria = accessibilityTextCriteriaForParameterizedAttribute(dictionary);
-        criteria.second.textRanges = m_object->findTextRanges(criteria.first);
-        ASSERT(criteria.second.textRanges.size() <= 1);
-        Vector<String> result = m_object->performTextOperation(criteria.second);
+        auto result = Accessibility::retrieveValueFromMainThread<Vector<String>>([dictionary, self] () -> Vector<String> {
+            auto criteria = accessibilityTextCriteriaForParameterizedAttribute(dictionary);
+            criteria.second.textRanges = m_object->findTextRanges(criteria.first);
+            ASSERT(criteria.second.textRanges.size() <= 1);
+            return m_object->performTextOperation(criteria.second);
+        });
         ASSERT(result.size() <= 1);
         if (result.size() > 0)
             return result[0];
@@ -3937,20 +3917,24 @@ ALLOW_DEPRECATED_IMPLEMENTATIONS_END
 
     if ([attribute isEqualToString:NSAccessibilitySearchTextWithCriteriaParameterizedAttribute]) {
         auto criteria = accessibilitySearchTextCriteriaForParameterizedAttribute(dictionary);
-        auto ranges = m_object->findTextRanges(criteria);
-        if (ranges.isEmpty())
-            return nil;
-        NSMutableArray *markers = [NSMutableArray arrayWithCapacity:ranges.size()];
-        for (auto range : ranges) {
-            if (id marker = [self textMarkerRangeFromRange:range])
-                [markers addObject:marker];
-        }
-        return markers;
+        return Accessibility::retrieveValueFromMainThread<NSArray *>([&criteria, self] () -> NSArray * {
+            auto ranges = m_object->findTextRanges(criteria);
+            if (ranges.isEmpty())
+                return nil;
+            NSMutableArray *markers = [NSMutableArray arrayWithCapacity:ranges.size()];
+            for (auto range : ranges) {
+                if (id marker = [self textMarkerRangeFromRange:range])
+                    [markers addObject:marker];
+            }
+            return markers;
+        });
     }
 
     if ([attribute isEqualToString:NSAccessibilityTextOperationParameterizedAttribute]) {
-        auto textOperation = accessibilityTextOperationForParameterizedAttribute(self, dictionary);
-        auto operationResult = m_object->performTextOperation(textOperation);
+        auto operationResult = Accessibility::retrieveValueFromMainThread<Vector<String>>([dictionary, self] () -> Vector<String> {
+            auto textOperation = accessibilityTextOperationForParameterizedAttribute(self, dictionary);
+            return m_object->performTextOperation(textOperation);
+        });
         if (operationResult.isEmpty())
             return nil;
         NSMutableArray *result = [NSMutableArray arrayWithCapacity:operationResult.size()];
index f423f70..3d6f6fd 100644 (file)
@@ -1,3 +1,19 @@
+2019-12-16  Andres Gonzalez  <andresg_22@apple.com>
+
+        Isolated object implementation of parameterized attribute SelectTextWithCriteria.
+        https://bugs.webkit.org/show_bug.cgi?id=205210
+
+        Reviewed by Chris Fleizach.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
+        (WTR::AccessibilityController::rootElement): Always run in my thread.
+        (WTR::AccessibilityController::execute): Dispatches to the secondary thread. Spins the main loop to allow parameterized attributes methods to execute in main thread.
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
+        (WTR::findAccessibleObjectById):
+        (WTR::AccessibilityController::accessibleElementById):
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+        (WTR::AccessibilityUIElement::selectTextWithCriteria):
+
 2019-12-16  Per Arne Vollan  <pvollan@apple.com>
 
         Unreviewed build fix for tvOS after r253440.
index f8a3486..c9669c1 100644 (file)
@@ -76,22 +76,12 @@ bool AccessibilityController::enhancedAccessibilityEnabled()
 Ref<AccessibilityUIElement> AccessibilityController::rootElement()
 {
     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
-    PlatformUIElement root = nullptr;
+    PlatformUIElement root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
 
-    if (m_useAXThread) {
-        AXThread::dispatch([&root, page, this] {
-            root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
-            m_semaphore.signal();
-        });
-
-        m_semaphore.wait();
-    } else {
-        root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
-
-        // Set m_useAXThread to true for next request.
-        if (WKAccessibilityCanUseSecondaryAXThread(page))
-            m_useAXThread = true;
-    }
+    // Now that we have a root and the isolated tree is generated, set
+    // m_useAXThread to true for next request to be handled in the secondary thread.
+    if (WKAccessibilityCanUseSecondaryAXThread(InjectedBundle::singleton().page()->page()))
+        m_useAXThread = true;
 
     return AccessibilityUIElement::create(root);
 }
@@ -103,7 +93,7 @@ Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
     return AccessibilityUIElement::create(focusedElement);
 }
 
-void AccessibilityController::execute(Function<void()>&& function)
+void AccessibilityController::executeOnAXThreadIfPossible(Function<void()>&& function)
 {
     if (m_useAXThread) {
         AXThread::dispatch([&function, this] {
@@ -111,6 +101,11 @@ void AccessibilityController::execute(Function<void()>&& function)
             m_semaphore.signal();
         });
 
+        // Spin the main loop so that any required DOM processing can be
+        // executed in the main thread. That is the case of most parameterized
+        // attributes, where the attribute value has to be calculated
+        // back in the main thread.
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, .25, false);
         m_semaphore.wait();
     } else
         function();
index f8df3c8..cefaa43 100644 (file)
@@ -63,7 +63,7 @@ public:
     RefPtr<AccessibilityUIElement> accessibleElementById(JSStringRef idAttribute);
 
 #if PLATFORM(COCOA)
-    void execute(Function<void()>&&);
+    void executeOnAXThreadIfPossible(Function<void()>&&);
 #endif
 
     bool addNotificationListener(JSValueRef functionCallback);
index d1dd228..a94de38 100644 (file)
@@ -81,6 +81,7 @@ static id findAccessibleObjectById(id obj, NSString *idAttribute)
         return obj;
     END_AX_OBJC_EXCEPTIONS
 
+    BEGIN_AX_OBJC_EXCEPTIONS
     NSArray *children = [obj accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
     NSUInteger childrenCount = [children count];
     for (NSUInteger i = 0; i < childrenCount; ++i) {
@@ -88,6 +89,7 @@ static id findAccessibleObjectById(id obj, NSString *idAttribute)
         if (result)
             return result;
     }
+    END_AX_OBJC_EXCEPTIONS
 
     return nullptr;
 }
@@ -95,12 +97,24 @@ static id findAccessibleObjectById(id obj, NSString *idAttribute)
 RefPtr<AccessibilityUIElement> AccessibilityController::accessibleElementById(JSStringRef idAttribute)
 {
     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
-    id root = (__bridge id)WKAccessibilityRootObject(page);
+    PlatformUIElement root = nullptr;
+
+    executeOnAXThreadIfPossible([&page, &root] {
+        root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
+    });
+
+    // Now that we have a root and the isolated tree is generated, set
+    // m_useAXThread to true for next request to be handled in the secondary thread.
+    if (WKAccessibilityCanUseSecondaryAXThread(InjectedBundle::singleton().page()->page()))
+        m_useAXThread = true;
+
+    id result;
+    executeOnAXThreadIfPossible([&root, &idAttribute, &result] {
+        result = findAccessibleObjectById(root, [NSString stringWithJSStringRef:idAttribute]);
+    });
 
-    id result = findAccessibleObjectById(root, [NSString stringWithJSStringRef:idAttribute]);
     if (result)
         return AccessibilityUIElement::create(result);
-
     return nullptr;
 }
 
index c569f68..9b59bfc 100644 (file)
@@ -371,7 +371,7 @@ void AccessibilityUIElement::getChildrenWithRange(Vector<RefPtr<AccessibilityUIE
 {
     BEGIN_AX_OBJC_EXCEPTIONS
     auto accessibilityController = InjectedBundle::singleton().accessibilityController();
-    accessibilityController->execute([&elementVector, location, length, this] {
+    accessibilityController->executeOnAXThreadIfPossible([&elementVector, location, length, this] {
         NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
         elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(children);
     });
@@ -640,7 +640,7 @@ double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
     id value;
 
     auto accessibilityController = InjectedBundle::singleton().accessibilityController();
-    accessibilityController->execute([&attribute, &value, this] {
+    accessibilityController->executeOnAXThreadIfPossible([&attribute, &value, this] {
         value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
     });
 
@@ -1253,7 +1253,11 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContex
 {
     BEGIN_AX_OBJC_EXCEPTIONS
     NSDictionary *parameterizedAttribute = selectTextParameterizedAttributeForCriteria(context, ambiguityResolution, searchStrings, replacementString, activity);
-    id result = [m_element accessibilityAttributeValue:@"AXSelectTextWithCriteria" forParameter:parameterizedAttribute];
+    id result;
+    auto accessibilityController = InjectedBundle::singleton().accessibilityController();
+    accessibilityController->executeOnAXThreadIfPossible([&parameterizedAttribute, &result, this] {
+        result = [m_element accessibilityAttributeValue:@"AXSelectTextWithCriteria" forParameter:parameterizedAttribute];
+    });
     if ([result isKindOfClass:[NSString class]])
         return [result createJSStringRef];
     END_AX_OBJC_EXCEPTIONS