Title: [261081] trunk
Revision
261081
Author
[email protected]
Date
2020-05-04 07:35:10 -0700 (Mon, 04 May 2020)

Log Message

Add WTR::AccessibilityUIElement::attributeValueAsync to retrieve attribute values in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=211341

Reviewed by Chris Fleizach.

Tools:

To simulate running WebAccessibilityObjectWrapper methods on the secondary
thread, WTR::AccessibilityUIElement dispatches those calls to the AX
thread. But some WebAccessibilityObjectWrapper calls cannot be fulfilled
on the secondary thread and in turn have to be dispatched to the main
thread. This was causing a thread lock during LayoutTests in isolated
tree mode since the initial dispatch to the secondary thread blocks the
main thread. The solution in this patch is to add an asynchronous
mechanism to retrieve attribute values.
- Added WTR::AccessibilityUIElement::attributeValueAsync.
- Made several fixes consisting of retaining variables in the main
thread whose values are computed on the secondary thread.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::executeOnAXThreadAndWait):
(WTR::AccessibilityController::executeOnAXThread):
(WTR::AccessibilityController::executeOnMainThread):
(WTR::AXThread::dispatchBarrier):
(WTR::AccessibilityController::executeOnAXThreadIfPossible): Renamed executeOnAXThreadAndWait.
* WebKitTestRunner/InjectedBundle/AccessibilityController.h:
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.h:
* WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.mm:
(WTR::webAccessibilityObjectWrapperClass):
(WTR::makeArrayRefForArray):
(WTR::makeObjectRefForDictionary):
(WTR::makeValueRefForValue):
(WTR::searchPredicateParameterizedAttributeForSearchCriteria):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
(WTR::AccessibilityController::accessibleElementById):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityNotificationHandler.mm:
(-[AccessibilityNotificationHandler startObserving]):
(-[AccessibilityNotificationHandler _notificationReceived:]):
(webAccessibilityObjectWrapperClass): Moved to AccessibilityCommonMac.
(makeValueRefForValue): Moved to AccessibilityCommonMac.
(makeArrayRefForArray): Moved to AccessibilityCommonMac.
(makeObjectRefForDictionary): Moved to AccessibilityCommonMac.
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::supportedAttributes):
(WTR::attributeValue):
(WTR::setAttributeValue):
(WTR::attributesOfElement):
(WTR::AccessibilityUIElement::getChildrenWithRange):
(WTR::AccessibilityUIElement::elementAtPoint):
(WTR::AccessibilityUIElement::indexOfChild):
(WTR::AccessibilityUIElement::selectedChildrenCount const):
(WTR::AccessibilityUIElement::attributeValueAsync):
(WTR::AccessibilityUIElement::selectTextWithCriteria):

LayoutTests:

This test exercises the new WTR::AccessibilityUIElement::atributeValueAsync method.
Instead of using shouldBeTrue that does not work with local variables,
uses debug to log results.

* accessibility/mac/primary-screen-height-expected.txt:
* accessibility/mac/primary-screen-height.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (261080 => 261081)


--- trunk/LayoutTests/ChangeLog	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/LayoutTests/ChangeLog	2020-05-04 14:35:10 UTC (rev 261081)
@@ -1,3 +1,17 @@
+2020-05-04  Andres Gonzalez  <[email protected]>
+
+        Add WTR::AccessibilityUIElement::attributeValueAsync to retrieve attribute values in isolated tree mode.
+        https://bugs.webkit.org/show_bug.cgi?id=211341
+
+        Reviewed by Chris Fleizach.
+
+        This test exercises the new WTR::AccessibilityUIElement::atributeValueAsync method.
+        Instead of using shouldBeTrue that does not work with local variables,
+        uses debug to log results.
+
+        * accessibility/mac/primary-screen-height-expected.txt:
+        * accessibility/mac/primary-screen-height.html:
+
 2020-05-03  Daniel Bates  <[email protected]>
 
         Sometimes cannot find <textarea> in list of editable elements

Modified: trunk/LayoutTests/accessibility/mac/primary-screen-height-expected.txt (261080 => 261081)


--- trunk/LayoutTests/accessibility/mac/primary-screen-height-expected.txt	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/LayoutTests/accessibility/mac/primary-screen-height-expected.txt	2020-05-04 14:35:10 UTC (rev 261081)
@@ -4,8 +4,8 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS screenHeightFromRootElement > 0 is true
-PASS screenHeightFromWebArea > 0 is true
+The screen height from the root element is > 0.
+The screen height from the web area is > 0.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/accessibility/mac/primary-screen-height.html (261080 => 261081)


--- trunk/LayoutTests/accessibility/mac/primary-screen-height.html	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/LayoutTests/accessibility/mac/primary-screen-height.html	2020-05-04 14:35:10 UTC (rev 261081)
@@ -13,16 +13,23 @@
 <script>
     description("This tests the primary screen height is exposed to AX API from web process.");
     if (window.accessibilityController) {
-    	var rootElement = accessibilityController.rootElement;
+        window.jsTestIsAsync = true;
+
+        var rootElement = accessibilityController.rootElement;
         var webArea = accessibilityController.rootElement.childAtIndex(0);
 
-        var screenHeightFromRootElement = rootElement.numberAttributeValue("_AXPrimaryScreenHeight");
-        shouldBeTrue("screenHeightFromRootElement > 0");
+        rootElement.attributeValueAsync("_AXPrimaryScreenHeight", function(value) {
+            debug(value > 0 ? "The screen height from the root element is > 0."
+                  : "The screen height from the root element should be > 0 but it is not.");
+        });
 
-        var screenHeightFromWebArea = webArea.numberAttributeValue("_AXPrimaryScreenHeight");
-        shouldBeTrue("screenHeightFromWebArea > 0");
+        webArea.attributeValueAsync("_AXPrimaryScreenHeight", function(value) {
+            debug(value > 0 ? "The screen height from the web area is > 0."
+                  : "The screen height from the web area should be > 0 but it is not.");
+
+            finishJSTest();
+        });
     }
-
 </script>
 <script src=""
 </body>

Modified: trunk/Tools/ChangeLog (261080 => 261081)


--- trunk/Tools/ChangeLog	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/ChangeLog	2020-05-04 14:35:10 UTC (rev 261081)
@@ -1,3 +1,59 @@
+2020-05-04  Andres Gonzalez  <[email protected]>
+
+        Add WTR::AccessibilityUIElement::attributeValueAsync to retrieve attribute values in isolated tree mode.
+        https://bugs.webkit.org/show_bug.cgi?id=211341
+
+        Reviewed by Chris Fleizach.
+
+        To simulate running WebAccessibilityObjectWrapper methods on the secondary
+        thread, WTR::AccessibilityUIElement dispatches those calls to the AX
+        thread. But some WebAccessibilityObjectWrapper calls cannot be fulfilled
+        on the secondary thread and in turn have to be dispatched to the main
+        thread. This was causing a thread lock during LayoutTests in isolated
+        tree mode since the initial dispatch to the secondary thread blocks the
+        main thread. The solution in this patch is to add an asynchronous
+        mechanism to retrieve attribute values.
+        - Added WTR::AccessibilityUIElement::attributeValueAsync.
+        - Made several fixes consisting of retaining variables in the main
+        thread whose values are computed on the secondary thread.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
+        (WTR::AccessibilityController::executeOnAXThreadAndWait):
+        (WTR::AccessibilityController::executeOnAXThread):
+        (WTR::AccessibilityController::executeOnMainThread):
+        (WTR::AXThread::dispatchBarrier):
+        (WTR::AccessibilityController::executeOnAXThreadIfPossible): Renamed executeOnAXThreadAndWait.
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.h:
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+        * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.h:
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.mm:
+        (WTR::webAccessibilityObjectWrapperClass):
+        (WTR::makeArrayRefForArray):
+        (WTR::makeObjectRefForDictionary):
+        (WTR::makeValueRefForValue):
+        (WTR::searchPredicateParameterizedAttributeForSearchCriteria):
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
+        (WTR::AccessibilityController::accessibleElementById):
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityNotificationHandler.mm:
+        (-[AccessibilityNotificationHandler startObserving]):
+        (-[AccessibilityNotificationHandler _notificationReceived:]):
+        (webAccessibilityObjectWrapperClass): Moved to AccessibilityCommonMac.
+        (makeValueRefForValue): Moved to AccessibilityCommonMac.
+        (makeArrayRefForArray): Moved to AccessibilityCommonMac.
+        (makeObjectRefForDictionary): Moved to AccessibilityCommonMac.
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+        (WTR::supportedAttributes):
+        (WTR::attributeValue):
+        (WTR::setAttributeValue):
+        (WTR::attributesOfElement):
+        (WTR::AccessibilityUIElement::getChildrenWithRange):
+        (WTR::AccessibilityUIElement::elementAtPoint):
+        (WTR::AccessibilityUIElement::indexOfChild):
+        (WTR::AccessibilityUIElement::selectedChildrenCount const):
+        (WTR::AccessibilityUIElement::attributeValueAsync):
+        (WTR::AccessibilityUIElement::selectTextWithCriteria):
+
 2020-05-04  Commit Queue  <[email protected]>
 
         Unreviewed, reverting r261076.

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2020-05-04 14:35:10 UTC (rev 261081)
@@ -107,7 +107,7 @@
     return AccessibilityUIElement::create(focusedElement);
 }
 
-void AccessibilityController::executeOnAXThreadIfPossible(Function<void()>&& function)
+void AccessibilityController::executeOnAXThreadAndWait(Function<void()>&& function)
 {
 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
     if (m_useMockAXThread) {
@@ -121,6 +121,30 @@
 #endif
         function();
 }
+
+void AccessibilityController::executeOnAXThread(Function<void()>&& function)
+{
+#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
+    if (m_useMockAXThread) {
+        AXThread::dispatch([function = WTFMove(function)] {
+            function();
+        });
+    } else
+#endif
+        function();
+}
+
+void AccessibilityController::executeOnMainThread(Function<void()>&& function)
+{
+    if (isMainThread()) {
+        function();
+        return;
+    }
+
+    AXThread::dispatchBarrier([function = WTFMove(function)] {
+        function();
+    });
+}
 #endif // PLATFORM(COCOA)
 
 RefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y)
@@ -157,7 +181,7 @@
 
 void AXThread::dispatchBarrier(Function<void()>&& function)
 {
-    dispatch([function = WTFMove(function)]() mutable {
+    dispatch([function = WTFMove(function)] () mutable {
         callOnMainThread(WTFMove(function));
     });
 }

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2020-05-04 14:35:10 UTC (rev 261081)
@@ -67,7 +67,9 @@
     RefPtr<AccessibilityUIElement> accessibleElementById(JSStringRef idAttribute);
 
 #if PLATFORM(COCOA)
-    void executeOnAXThreadIfPossible(Function<void()>&&);
+    void executeOnAXThreadAndWait(Function<void()>&&);
+    void executeOnAXThread(Function<void()>&&);
+    void executeOnMainThread(Function<void()>&&);
 #endif
 
     bool addNotificationListener(JSValueRef functionCallback);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2020-05-04 14:35:10 UTC (rev 261081)
@@ -55,7 +55,7 @@
 class AccessibilityUIElement : public JSWrappable {
 #if PLATFORM(COCOA)
     // Helper functions that dispatch the corresponding AccessibilityObjectWrapper method to the AX secondary thread when appropriate.
-    friend NSArray* supportedAttributes(id);
+    friend RetainPtr<NSArray> supportedAttributes(id);
     friend id attributeValue(id, NSString *);
     friend void setAttributeValue(id, NSString *, id, bool synchronous);
 #endif
@@ -121,6 +121,11 @@
     JSValueRef uiElementArrayAttributeValue(JSStringRef attribute) const;
     RefPtr<AccessibilityUIElement> uiElementAttributeValue(JSStringRef attribute) const;
     bool boolAttributeValue(JSStringRef attribute);
+#if PLATFORM(MAC)
+    void attributeValueAsync(JSStringRef attribute, JSValueRef callback);
+#else
+    void attributeValueAsync(JSStringRef attribute, JSValueRef callback) { }
+#endif
     void setBoolAttributeValue(JSStringRef attribute, bool value);
     bool isAttributeSupported(JSStringRef attribute);
     bool isAttributeSettable(JSStringRef attribute);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2020-05-04 14:35:10 UTC (rev 261081)
@@ -66,6 +66,7 @@
     object uiElementArrayAttributeValue(DOMString attr);
     AccessibilityUIElement uiElementAttributeValue(DOMString attr);  
     boolean boolAttributeValue(DOMString attr);
+    void attributeValueAsync(DOMString attributeName, object callbackFunction);
     void setBoolAttributeValue(DOMString attr, boolean value);
     boolean isAttributeSupported(DOMString attr);
     boolean isAttributeSettable(DOMString attr);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.h (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.h	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.h	2020-05-04 14:35:10 UTC (rev 261081)
@@ -42,7 +42,9 @@
 @end
 
 namespace WTR {
-    
+
+Class webAccessibilityObjectWrapperClass();
+JSValueRef makeValueRefForValue(JSContextRef, id value);
 extern NSDictionary *searchPredicateParameterizedAttributeForSearchCriteria(JSContextRef, AccessibilityUIElement *startElement, bool isDirectionNext, unsigned resultsLimit, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
 
 };

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.mm (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.mm	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityCommonMac.mm	2020-05-04 14:35:10 UTC (rev 261081)
@@ -31,7 +31,9 @@
 #import "config.h"
 #import "AccessibilityCommonMac.h"
 
+#import "JSWrapper.h"
 #import <_javascript_Core/JSStringRefCF.h>
+#import <objc/runtime.h>
 
 @implementation NSString (JSStringRefAdditions)
 
@@ -48,19 +50,69 @@
     return adopt(JSStringCreateWithCFString((__bridge CFStringRef)self));
 }
 
+@end
+
 namespace WTR {
 
+Class webAccessibilityObjectWrapperClass()
+{
+    static Class cls = objc_getClass("WebAccessibilityObjectWrapper");
+    ASSERT(cls);
+    return cls;
+}
+
+static JSValueRef makeArrayRefForArray(JSContextRef context, NSArray *array)
+{
+    NSUInteger count = array.count;
+    JSValueRef arguments[count];
+
+    for (NSUInteger i = 0; i < count; i++)
+        arguments[i] = makeValueRefForValue(context, [array objectAtIndex:i]);
+
+    return JSObjectMakeArray(context, count, arguments, nullptr);
+}
+
+static JSValueRef makeObjectRefForDictionary(JSContextRef context, NSDictionary *dictionary)
+{
+    JSObjectRef object = JSObjectMake(context, nullptr, nullptr);
+
+    [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *) {
+        if (JSValueRef propertyValue = makeValueRefForValue(context, obj))
+            JSObjectSetProperty(context, object, [key createJSStringRef].get(), propertyValue, kJSPropertyAttributeNone, nullptr);
+    }];
+
+    return object;
+}
+
+JSValueRef makeValueRefForValue(JSContextRef context, id value)
+{
+    if ([value isKindOfClass:[NSString class]])
+        return JSValueMakeString(context, [value createJSStringRef].get());
+    if ([value isKindOfClass:[NSNumber class]]) {
+        if (!strcmp([value objCType], @encode(BOOL)))
+            return JSValueMakeBoolean(context, [value boolValue]);
+        return JSValueMakeNumber(context, [value doubleValue]);
+    }
+    if ([value isKindOfClass:webAccessibilityObjectWrapperClass()])
+        return toJS(context, WTR::AccessibilityUIElement::create(static_cast<PlatformUIElement>(value)).ptr());
+    if ([value isKindOfClass:[NSDictionary class]])
+        return makeObjectRefForDictionary(context, value);
+    if ([value isKindOfClass:[NSArray class]])
+        return makeArrayRefForArray(context, value);
+    return nullptr;
+}
+
 NSDictionary *searchPredicateParameterizedAttributeForSearchCriteria(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, unsigned resultsLimit, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
 {
     NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
-    
+
     if (startElement && startElement->platformUIElement())
         [parameterizedAttribute setObject:startElement->platformUIElement() forKey:@"AXStartElement"];
-    
+
     [parameterizedAttribute setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
-    
+
     [parameterizedAttribute setObject:@(resultsLimit) forKey:@"AXResultsLimit"];
-    
+
     if (searchKey) {
         id searchKeyParameter = nil;
         if (JSValueIsString(context, searchKey)) {
@@ -70,12 +122,12 @@
         } else if (JSValueIsObject(context, searchKey)) {
             JSObjectRef searchKeyArray = JSValueToObject(context, searchKey, nullptr);
             unsigned searchKeyArrayLength = 0;
-            
+
             auto lengthPropertyString = adopt(JSStringCreateWithUTF8CString("length"));
             JSValueRef searchKeyArrayLengthValue = JSObjectGetProperty(context, searchKeyArray, lengthPropertyString.get(), nullptr);
             if (searchKeyArrayLengthValue && JSValueIsNumber(context, searchKeyArrayLengthValue))
                 searchKeyArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchKeyArrayLengthValue, nullptr));
-            
+
             for (unsigned i = 0; i < searchKeyArrayLength; ++i) {
                 JSValueRef searchKeyValue = JSObjectGetPropertyAtIndex(context, searchKeyArray, i, nullptr);
                 JSStringRef searchKeyString = JSValueToStringCopy(context, searchKeyValue, nullptr);
@@ -90,17 +142,16 @@
         if (searchKeyParameter)
             [parameterizedAttribute setObject:searchKeyParameter forKey:@"AXSearchKey"];
     }
-    
+
     if (searchText && JSStringGetLength(searchText))
         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
-    
+
     [parameterizedAttribute setObject:@(visibleOnly) forKey:@"AXVisibleOnly"];
-    
+
     [parameterizedAttribute setObject:@(immediateDescendantsOnly) forKey:@"AXImmediateDescendantsOnly"];
-    
+
     return parameterizedAttribute;
 }
-    
+
 } // namespace WTR
 
-@end

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm	2020-05-04 14:35:10 UTC (rev 261081)
@@ -100,7 +100,7 @@
     PlatformUIElement root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
 
     RetainPtr<id> result;
-    executeOnAXThreadIfPossible([&root, &idAttribute, &result] {
+    executeOnAXThreadAndWait([&root, &idAttribute, &result] {
         result = findAccessibleObjectById(root, [NSString stringWithJSStringRef:idAttribute]);
     });
 

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityNotificationHandler.mm (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityNotificationHandler.mm	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityNotificationHandler.mm	2020-05-04 14:35:10 UTC (rev 261081)
@@ -40,7 +40,6 @@
 #import <_javascript_Core/JSStringRef.h>
 #import <_javascript_Core/JSStringRefCF.h>
 #import <WebKit/WKBundleFrame.h>
-#import <objc/runtime.h>
 #import <wtf/RetainPtr.h>
 
 @interface NSObject (WebAccessibilityObjectWrapperAdditions)
@@ -90,19 +89,12 @@
     JSValueProtect(context, m_notificationFunctionCallback);
 }
 
-static Class webAccessibilityObjectWrapperClass()
-{
-    static Class cls = objc_getClass("WebAccessibilityObjectWrapper");
-    ASSERT(cls);
-    return cls;
-}
-
 - (void)startObserving
 {
     // Once we start requesting notifications, it's on for the duration of the program.
     // This is to avoid any race conditions between tests turning this flag on and off. Instead
     // AccessibilityNotificationHandler can ignore events it doesn't care about.
-    [webAccessibilityObjectWrapperClass() accessibilitySetShouldRepostNotifications:YES];
+    [WTR::webAccessibilityObjectWrapperClass() accessibilitySetShouldRepostNotifications:YES];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notificationReceived:) name:@"AXDRTNotification" object:nil];
 }
 
@@ -111,48 +103,6 @@
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
-static JSValueRef makeValueRefForValue(JSContextRef context, id value)
-{
-    if ([value isKindOfClass:[NSString class]])
-        return JSValueMakeString(context, [value createJSStringRef].get());
-    if ([value isKindOfClass:[NSNumber class]]) {
-        if (!strcmp([value objCType], @encode(BOOL)))
-            return JSValueMakeBoolean(context, [value boolValue]);
-        return JSValueMakeNumber(context, [value doubleValue]);
-    }
-    if ([value isKindOfClass:webAccessibilityObjectWrapperClass()])
-        return toJS(context, WTR::AccessibilityUIElement::create(static_cast<PlatformUIElement>(value)).ptr());
-    if ([value isKindOfClass:[NSDictionary class]])
-        return makeObjectRefForDictionary(context, value);
-    if ([value isKindOfClass:[NSArray class]])
-        return makeArrayRefForArray(context, value);
-    return nullptr;
-}
-
-static JSValueRef makeArrayRefForArray(JSContextRef context, NSArray *array)
-{
-    NSUInteger count = array.count;
-    JSValueRef arguments[count];
-
-    for (NSUInteger i = 0; i < count; i++)
-        arguments[i] = makeValueRefForValue(context, [array objectAtIndex:i]);
-
-    return JSObjectMakeArray(context, count, arguments, nullptr);
-}
-
-static JSValueRef makeObjectRefForDictionary(JSContextRef context, NSDictionary *dictionary)
-{
-    JSObjectRef object = JSObjectMake(context, nullptr, nullptr);
-
-    [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop)
-    {
-        if (JSValueRef propertyValue = makeValueRefForValue(context, obj))
-            JSObjectSetProperty(context, object, [key createJSStringRef].get(), propertyValue, kJSPropertyAttributeNone, nullptr);
-    }];
-
-    return object;
-}
-
 - (void)_notificationReceived:(NSNotification *)notification
 {
     NSString *notificationName = [[notification userInfo] objectForKey:@"notificationName"];
@@ -167,7 +117,7 @@
     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
 
     JSValueRef notificationNameArgument = JSValueMakeString(context, [notificationName createJSStringRef].get());
-    JSValueRef userInfoArgument = makeObjectRefForDictionary(context, userInfo);
+    JSValueRef userInfoArgument = WTR::makeValueRefForValue(context, userInfo);
     if (m_platformElement) {
         // Listener for one element gets the notification name and userInfo.
         JSValueRef arguments[2];

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (261080 => 261081)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2020-05-04 14:13:24 UTC (rev 261080)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2020-05-04 14:35:10 UTC (rev 261081)
@@ -117,12 +117,12 @@
     return platformUIElement() == otherElement->platformUIElement();
 }
 
-NSArray* supportedAttributes(id element)
+RetainPtr<NSArray> supportedAttributes(id element)
 {
-    NSArray *attributes;
+    RetainPtr<NSArray> attributes;
 
     BEGIN_AX_OBJC_EXCEPTIONS
-    AccessibilityUIElement::s_controller->executeOnAXThreadIfPossible([&attributes, &element] {
+    AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([&attributes, &element] {
         attributes = [element accessibilityAttributeNames];
     });
     END_AX_OBJC_EXCEPTIONS
@@ -132,21 +132,21 @@
 
 id attributeValue(id element, NSString *attribute)
 {
-    id value;
+    RetainPtr<id> value;
 
     BEGIN_AX_OBJC_EXCEPTIONS
-    AccessibilityUIElement::s_controller->executeOnAXThreadIfPossible([&element, &attribute, &value] {
+    AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([&element, &attribute, &value] {
         value = [element accessibilityAttributeValue:attribute];
     });
     END_AX_OBJC_EXCEPTIONS
 
-    return value;
+    return value.get();
 }
 
 void setAttributeValue(id element, NSString* attribute, id value, bool synchronous = false)
 {
     BEGIN_AX_OBJC_EXCEPTIONS
-    AccessibilityUIElement::s_controller->executeOnAXThreadIfPossible([&element, &attribute, &value, &synchronous] {
+    AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([&element, &attribute, &value, &synchronous] {
         // FIXME: should always be asynchronous, fix tests.
         synchronous ? [element _accessibilitySetValue:value forAttribute:attribute] :
             [element accessibilitySetValue:value forAttribute:attribute];;;
@@ -198,10 +198,10 @@
 
 static NSString *attributesOfElement(id accessibilityObject)
 {
-    NSArray* attributes = supportedAttributes(accessibilityObject);
+    RetainPtr<NSArray> attributes = supportedAttributes(accessibilityObject);
 
     NSMutableString* attributesString = [NSMutableString string];
-    for (NSString* attribute in attributes) {
+    for (NSString* attribute in attributes.get()) {
         // Position provides useless and screen-specific information, so we do not
         // want to include it for the sake of universally passing tests.
         if ([attribute isEqualToString:@"AXPosition"])
@@ -373,7 +373,7 @@
 {
     BEGIN_AX_OBJC_EXCEPTIONS
     RetainPtr<NSArray> children;
-    s_controller->executeOnAXThreadIfPossible([&children, location, length, this] {
+    s_controller->executeOnAXThreadAndWait([&children, location, length, this] {
         children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
     });
     elementVector = makeVector<RefPtr<AccessibilityUIElement>>(children.get());
@@ -418,8 +418,8 @@
 
 RefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y)
 {
-    id element;
-    s_controller->executeOnAXThreadIfPossible([&x, &y, &element, this] {
+    RetainPtr<id> element;
+    s_controller->executeOnAXThreadAndWait([&x, &y, &element, this] {
         element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
     });
 
@@ -426,7 +426,7 @@
     if (!element)
         return nullptr;
 
-    return AccessibilityUIElement::create(element);
+    return AccessibilityUIElement::create(element.get());
 }
 
 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
@@ -433,7 +433,7 @@
 {
     unsigned index;
     id platformElement = element->platformUIElement();
-    s_controller->executeOnAXThreadIfPossible([&platformElement, &index, this] {
+    s_controller->executeOnAXThreadAndWait([&platformElement, &index, this] {
         index = [m_element accessibilityIndexOfChild:platformElement];
     });
     return index;
@@ -511,7 +511,7 @@
     unsigned count = 0;
 
     BEGIN_AX_OBJC_EXCEPTIONS
-    s_controller->executeOnAXThreadIfPossible([&count, this] {
+    s_controller->executeOnAXThreadAndWait([&count, this] {
         count = [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
     });
     END_AX_OBJC_EXCEPTIONS
@@ -613,6 +613,27 @@
     return false;
 }
 
+void AccessibilityUIElement::attributeValueAsync(JSStringRef attribute, JSValueRef callback)
+{
+    if (!attribute || !callback)
+        return;
+
+    BEGIN_AX_OBJC_EXCEPTIONS
+    s_controller->executeOnAXThread([attribute = retainPtr([NSString stringWithJSStringRef:attribute]), callback = WTFMove(callback), this] () mutable {
+        id value = [m_element accessibilityAttributeValue:attribute.get()];
+
+        s_controller->executeOnMainThread([value = retainPtr(value), callback = WTFMove(callback)] () {
+            auto mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
+            auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
+
+            JSValueRef arguments[1];
+            arguments[0] = makeValueRefForValue(context, value.get());
+            JSObjectCallAsFunction(context, const_cast<JSObjectRef>(callback), 0, 1, arguments, 0);
+        });
+    });
+    END_AX_OBJC_EXCEPTIONS
+}
+
 void AccessibilityUIElement::setBoolAttributeValue(JSStringRef attribute, bool value)
 {
     setAttributeValue(m_element.get(), [NSString stringWithJSStringRef:attribute], @(value), true);
@@ -1177,14 +1198,14 @@
 {
     BEGIN_AX_OBJC_EXCEPTIONS
     NSDictionary *parameterizedAttribute = selectTextParameterizedAttributeForCriteria(context, ambiguityResolution, searchStrings, replacementString, activity);
-    id result;
-    s_controller->executeOnAXThreadIfPossible([&parameterizedAttribute, &result, this] {
+    RetainPtr<id> result;
+    s_controller->executeOnAXThreadAndWait([&parameterizedAttribute, &result, this] {
         result = [m_element accessibilityAttributeValue:@"AXSelectTextWithCriteria" forParameter:parameterizedAttribute];
     });
-    if ([result isKindOfClass:[NSString class]])
-        return [result createJSStringRef];
+    if ([result.get() isKindOfClass:[NSString class]])
+        return [result.get() createJSStringRef];
     END_AX_OBJC_EXCEPTIONS
-    
+
     return nullptr;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to