Skip to content
Permalink
Browse files
WTR::AccessibilityController::focusedElement() cannot get the focused…
… object via WKAccessibilityFocusedObject in isolated tree mode.

https://bugs.webkit.org/show_bug.cgi?id=232756
<rdar://problem/85069882>

Reviewed by Chris Fleizach.

WTR::AccessibilityController::focusedElement() was getting the focused
object from WKAccessibilityFocusedObject, which has to run on the main
thread. WKAccessibilityFocusedObject was in turn calling AXObjectCache::
focusedUIElementForPage that tried to return the isolated focused
object. The problem with this is that the isolated focused object can
only be retrieved on the secondary thread.
The solution in this patch is to retrieve the focused object from the
root object as an AT client would do.
Source/WebCore:

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::focusedObjectForPage):
(WebCore::AXObjectCache::isolatedTreeFocusedObject): Deleted, not needed any more.
(WebCore::AXObjectCache::focusedUIElementForPage): Deleted, using focusedObjectForPage instead.
* accessibility/AXObjectCache.h:
Moved the following inlines out of the class declaration.
(WebCore::AXObjectCache::accessibilityEnhancedUserInterfaceEnabled):
(WebCore::AXObjectCache::~AXObjectCache):
(WebCore::AXObjectCache::focusedObjectForPage):
(WebCore::AXObjectCache::enableAccessibility):
(WebCore::AXObjectCache::disableAccessibility):
(WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility):
(WebCore::AXObjectCache::accessibilityEnabled):
(WebCore::AXObjectCache::focusedUIElementForPage): Deleted.
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper accessibilityFocusedUIElement]): Code cleanup.
* accessibility/win/AXObjectCacheWin.cpp:
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):

Source/WebKit:

* WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
(WKAccessibilityFocusedObject):
Now uses AXObjectCache::focusedObejctForPage().

Tools:

Added AccessibilityUIElement::focusedElement in order to retrieve the
focused object from the root object.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::focusedElement):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::focusedElement const):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::focusedElement const):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::focusedElement const):



Canonical link: https://commits.webkit.org/243956@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@285399 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
AndresGonzalezApple committed Nov 8, 2021
1 parent bda5558 commit 80a3f4df82d5a2a27251e2aa6dd32f94d35c724f
Showing 13 changed files with 130 additions and 59 deletions.
@@ -1,3 +1,39 @@
2021-11-08 Andres Gonzalez <andresg_22@apple.com>

WTR::AccessibilityController::focusedElement() cannot get the focused object via WKAccessibilityFocusedObject in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=232756
<rdar://problem/85069882>

Reviewed by Chris Fleizach.

WTR::AccessibilityController::focusedElement() was getting the focused
object from WKAccessibilityFocusedObject, which has to run on the main
thread. WKAccessibilityFocusedObject was in turn calling AXObjectCache::
focusedUIElementForPage that tried to return the isolated focused
object. The problem with this is that the isolated focused object can
only be retrieved on the secondary thread.
The solution in this patch is to retrieve the focused object from the
root object as an AT client would do.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::focusedObjectForPage):
(WebCore::AXObjectCache::isolatedTreeFocusedObject): Deleted, not needed any more.
(WebCore::AXObjectCache::focusedUIElementForPage): Deleted, using focusedObjectForPage instead.
* accessibility/AXObjectCache.h:
Moved the following inlines out of the class declaration.
(WebCore::AXObjectCache::accessibilityEnhancedUserInterfaceEnabled):
(WebCore::AXObjectCache::~AXObjectCache):
(WebCore::AXObjectCache::focusedObjectForPage):
(WebCore::AXObjectCache::enableAccessibility):
(WebCore::AXObjectCache::disableAccessibility):
(WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility):
(WebCore::AXObjectCache::accessibilityEnabled):
(WebCore::AXObjectCache::focusedUIElementForPage): Deleted.
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper accessibilityFocusedUIElement]): Code cleanup.
* accessibility/win/AXObjectCacheWin.cpp:
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):

2021-11-08 Antoine Quint <graouts@webkit.org>

[Web Animations] Add support for composite operations for software animations
@@ -374,7 +374,7 @@ AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* ar
return nullptr;
}

AXCoreObject* AXObjectCache::focusedObjectForPage(const Page* page)
AccessibilityObject* AXObjectCache::focusedObjectForPage(const Page* page)
{
ASSERT(isMainThread());

@@ -392,11 +392,7 @@ AXCoreObject* AXObjectCache::focusedObjectForPage(const Page* page)
if (is<HTMLAreaElement>(focusedElement))
return focusedImageMapUIElement(downcast<HTMLAreaElement>(focusedElement));

auto* axObjectCache = document->axObjectCache();
if (!axObjectCache)
return nullptr;

AXCoreObject* focus = axObjectCache->getOrCreate(focusedElement ? focusedElement : static_cast<Node*>(document));
auto* focus = getOrCreate(focusedElement ? focusedElement : static_cast<Node*>(document));
if (!focus)
return nullptr;

@@ -407,22 +403,12 @@ AXCoreObject* AXObjectCache::focusedObjectForPage(const Page* page)

// the HTML element, for example, is focusable but has an AX object that is ignored
if (focus->accessibilityIsIgnored())
focus = focus->parentObjectUnignored();
focus = downcast<AccessibilityObject>(focus->parentObjectUnignored());

return focus;
}

#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
AXCoreObject* AXObjectCache::isolatedTreeFocusedObject()
{
if (auto tree = getOrCreateIsolatedTree())
return tree->focusedNode().get();

// Should not get here, couldn't create the IsolatedTree.
ASSERT_NOT_REACHED();
return nullptr;
}

void AXObjectCache::setIsolatedTreeFocusedObject(Node* focusedNode)
{
ASSERT(isMainThread());
@@ -436,16 +422,6 @@ void AXObjectCache::setIsolatedTreeFocusedObject(Node* focusedNode)
}
#endif

AXCoreObject* AXObjectCache::focusedUIElementForPage(const Page* page)
{
#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
if (isIsolatedTreeEnabled())
return isolatedTreeFocusedObject();
#endif

return focusedObjectForPage(page);
}

AccessibilityObject* AXObjectCache::get(Widget* widget)
{
if (!widget)
@@ -148,8 +148,6 @@ class AXObjectCache {
explicit AXObjectCache(Document&);
~AXObjectCache();

WEBCORE_EXPORT AXCoreObject* focusedUIElementForPage(const Page*);

// Returns the root object for the entire document.
WEBCORE_EXPORT AXCoreObject* rootObject();
// Returns the root object for a specific frame.
@@ -201,26 +199,17 @@ class AXObjectCache {
void recomputeIsIgnored(RenderObject*);
void recomputeIsIgnored(Node*);

#if ENABLE(ACCESSIBILITY)
WEBCORE_EXPORT static void enableAccessibility();
WEBCORE_EXPORT static void disableAccessibility();

static AXCoreObject* focusedObjectForPage(const Page*);
WEBCORE_EXPORT AccessibilityObject* focusedObjectForPage(const Page*);

// Enhanced user interface accessibility can be toggled by the assistive technology.
WEBCORE_EXPORT static void setEnhancedUserInterfaceAccessibility(bool flag);

// Note: these may be called from a non-main thread concurrently as other readers.
static bool accessibilityEnabled() { return gAccessibilityEnabled; }
static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
#else
static AXCoreObject* focusedObjectForPage(const Page*) { return nullptr; }
static void enableAccessibility() { }
static void disableAccessibility() { }
static void setEnhancedUserInterfaceAccessibility(bool) { }
static bool accessibilityEnabled() { return false; }
static bool accessibilityEnhancedUserInterfaceEnabled() { return false; }
#endif

const Element* rootAXEditableElement(const Node*);
bool nodeIsTextControl(const Node*);
@@ -383,7 +372,6 @@ class AXObjectCache {
private:
static bool clientSupportsIsolatedTree();
AXCoreObject* isolatedTreeRootObject();
AXCoreObject* isolatedTreeFocusedObject();
void setIsolatedTreeFocusedObject(Node*);
RefPtr<AXIsolatedTree> getOrCreateIsolatedTree() const;
void updateIsolatedTree(AXCoreObject&, AXNotification);
@@ -559,7 +547,6 @@ inline void AccessibilityReplacedText::postTextStateChangeNotification(AXObjectC
inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(*this, &AXObjectCache::notificationPostTimerFired), m_passwordNotificationPostTimer(*this, &AXObjectCache::passwordNotificationPostTimerFired), m_liveRegionChangedPostTimer(*this, &AXObjectCache::liveRegionChangedNotificationPostTimerFired), m_focusModalNodeTimer(*this, &AXObjectCache::focusModalNodeTimerFired), m_performCacheUpdateTimer(*this, &AXObjectCache::performCacheUpdateTimerFired) { }
inline AXObjectCache::~AXObjectCache() { }
inline AXCoreObject* AXObjectCache::focusedUIElementForPage(const Page*) { return nullptr; }
inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return nullptr; }
inline AccessibilityObject* AXObjectCache::get(Node*) { return nullptr; }
inline AccessibilityObject* AXObjectCache::get(Widget*) { return nullptr; }
@@ -569,6 +556,12 @@ inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return nullptr;
inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return nullptr; }
inline AXCoreObject* AXObjectCache::rootObject() { return nullptr; }
inline AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame*) { return nullptr; }
inline AccessibilityObject* AXObjectCache::focusedObjectForPage(const Page*) { return nullptr; }
inline static void AXObjectCache::enableAccessibility() { }
inline static void AXObjectCache::disableAccessibility() { }
inline static void AXObjectCache::setEnhancedUserInterfaceAccessibility(bool) { }
inline static bool AXObjectCache::accessibilityEnabled() { return false; }
inline static bool AXObjectCache::accessibilityEnhancedUserInterfaceEnabled() { return false; }
inline bool nodeHasRole(Node*, const String&) { return false; }
inline void AXObjectCache::startCachingComputedObjectAttributesUntilTreeMutates() { }
inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
@@ -1767,13 +1767,9 @@ - (id)accessibilityFocusedUIElement
{
if (![self _prepareAccessibilityCall])
return nil;

AccessibilityObject* focusedObj = downcast<AccessibilityObject>(self.axBackingObject->focusedUIElement());

if (!focusedObj)
return nil;

return focusedObj->wrapper();

auto* focus = self.axBackingObject->focusedUIElement();
return focus ? focus->wrapper() : nil;
}

- (id)_accessibilityWebDocumentView
@@ -174,7 +174,7 @@ void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node* newFocuse
if (!page || !page->chrome().platformPageClient())
return;

AXCoreObject* focusedObject = focusedUIElementForPage(page);
auto* focusedObject = focusedObjectForPage(page);
if (!focusedObject)
return;

@@ -1,3 +1,24 @@
2021-11-08 Andres Gonzalez <andresg_22@apple.com>

WTR::AccessibilityController::focusedElement() cannot get the focused object via WKAccessibilityFocusedObject in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=232756
<rdar://problem/85069882>

Reviewed by Chris Fleizach.

WTR::AccessibilityController::focusedElement() was getting the focused
object from WKAccessibilityFocusedObject, which has to run on the main
thread. WKAccessibilityFocusedObject was in turn calling AXObjectCache::
focusedUIElementForPage that tried to return the isolated focused
object. The problem with this is that the isolated focused object can
only be retrieved on the secondary thread.
The solution in this patch is to retrieve the focused object from the
root object as an AT client would do.

* WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
(WKAccessibilityFocusedObject):
Now uses AXObjectCache::focusedObejctForPage().

2021-11-08 Philippe Normand <pnormand@igalia.com>

[GStreamer] fast/mediastream/media-stream-video-track-interrupted.html is failing since added in 242093@main
@@ -273,7 +273,7 @@ void* WKAccessibilityFocusedObject(WKBundlePageRef pageRef)
#if ENABLE(ACCESSIBILITY)
if (!pageRef)
return 0;

WebCore::Page* page = WebKit::toImpl(pageRef)->corePage();
if (!page)
return 0;
@@ -288,11 +288,8 @@ void* WKAccessibilityFocusedObject(WKBundlePageRef pageRef)
if (!axObjectCache)
return 0;

auto* focusedObject = axObjectCache->focusedUIElementForPage(page);
if (!focusedObject)
return 0;

return focusedObject->wrapper();
auto* focus = axObjectCache->focusedObjectForPage(page);
return focus ? focus->wrapper() : 0;
#else
UNUSED_PARAM(pageRef);
return 0;
@@ -1,3 +1,32 @@
2021-11-08 Andres Gonzalez <andresg_22@apple.com>

WTR::AccessibilityController::focusedElement() cannot get the focused object via WKAccessibilityFocusedObject in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=232756
<rdar://problem/85069882>

Reviewed by Chris Fleizach.

WTR::AccessibilityController::focusedElement() was getting the focused
object from WKAccessibilityFocusedObject, which has to run on the main
thread. WKAccessibilityFocusedObject was in turn calling AXObjectCache::
focusedUIElementForPage that tried to return the isolated focused
object. The problem with this is that the isolated focused object can
only be retrieved on the secondary thread.
The solution in this patch is to retrieve the focused object from the
root object as an AT client would do.
Added AccessibilityUIElement::focusedElement in order to retrieve the
focused object from the root object.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::focusedElement):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::focusedElement const):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::focusedElement const):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::focusedElement const):

2021-11-07 Simon Fraser <simon.fraser@apple.com>

Implement UIScriptController.sendEventStream() on macOS for wheel events
@@ -93,8 +93,11 @@ Ref<AccessibilityUIElement> AccessibilityController::rootElement()
Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
{
auto page = InjectedBundle::singleton().page()->page();
PlatformUIElement focusedElement = static_cast<PlatformUIElement>(WKAccessibilityFocusedObject(page));
return AccessibilityUIElement::create(focusedElement);
auto root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
auto rootElement = AccessibilityUIElement::create(root);
if (auto focusedElement = rootElement->focusedElement())
return *focusedElement;
return AccessibilityUIElement::create(nullptr);
}

void AccessibilityController::executeOnAXThreadAndWait(Function<void()>&& function)
@@ -114,6 +114,7 @@ JSValueRef AccessibilityUIElement::mathRootRadicand() const { return { }; }
#endif

#if !PLATFORM(COCOA) || !HAVE(ACCESSIBILITY)
RefPtr<AccessibilityUIElement> AccessibilityUIElement::focusedElement() const { return nullptr; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::domIdentifier() const { return nullptr; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::currentStateValue() const { return nullptr; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::sortDirection() const { return nullptr; }
@@ -169,7 +169,8 @@ class AccessibilityUIElement : public JSWrappable {
JSRetainPtr<JSStringRef> selectedTextRange();
bool isEnabled();
bool isRequired() const;


RefPtr<AccessibilityUIElement> focusedElement() const;
bool isFocused() const;
bool isFocusable() const;
bool isSelected() const;
@@ -42,6 +42,7 @@
typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);

@interface NSObject (UIAccessibilityHidden)
- (id)accessibilityFocusedUIElement;
- (id)accessibilityHitTest:(CGPoint)point;
- (id)accessibilityLinkedElement;
- (id)accessibilityTitleElement;
@@ -630,6 +631,11 @@ + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef
return false;
}

RefPtr<AccessibilityUIElement> AccessibilityUIElement::focusedElement() const
{
return AccessibilityUIElement::create([m_element accessibilityFocusedUIElement]);
}

bool AccessibilityUIElement::isFocused() const
{
return false;
@@ -156,6 +156,8 @@ - (void)_accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName;
value = [element accessibilityRole];
else if ([attribute isEqual:NSAccessibilityValueAttribute] && [element respondsToSelector:@selector(accessibilityValue)])
value = [element accessibilityValue];
else if ([attribute isEqual:NSAccessibilityFocusedUIElementAttribute] && [element respondsToSelector:@selector(accessibilityFocusedUIElement)])
value = [element accessibilityFocusedUIElement];
else
value = [element accessibilityAttributeValue:attribute];
});
@@ -970,6 +972,16 @@ void setAttributeValue(id element, NSString* attribute, id value, bool synchrono
return false;
}

RefPtr<AccessibilityUIElement> AccessibilityUIElement::focusedElement() const
{
BEGIN_AX_OBJC_EXCEPTIONS
if (auto focus = attributeValue(NSAccessibilityFocusedUIElementAttribute))
return AccessibilityUIElement::create(focus.get());
END_AX_OBJC_EXCEPTIONS

return nullptr;
}

bool AccessibilityUIElement::isFocused() const
{
BEGIN_AX_OBJC_EXCEPTIONS

0 comments on commit 80a3f4d

Please sign in to comment.