Skip to content

Commit

Permalink
AX: Sometimes web content becomes inaccessible to VoiceOver
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=261006
rdar://113994918

Reviewed by Tyler Wilcock.

The problem is caused by the following sequence of events:
1. An AXObjectCache and AXIsolatedTree exist for the current page.
2. When the page is reloaded, the cache is destroyed and the isolated tree ActivityState is set to an empty set. The isolated tree is also queued to be destroyed.
3. VoiceOver queries for the focus off the main thread, but no isolated tree with focus is found sin the ActivityState is now empty or the tree was completely removed at that point.
4. A new AXObjectcache is created, but no new isolated object is created because this new AXObjectCache does not receive any request for the focus, which is one of the triggers of creating a new isolated tree.
The solution in this patch is to dispatch to the main thread the request for the focus in this scenario, which will result in the creation of a new isolated tree.

* Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::accessibilityFocusedUIElement):

Canonical link: https://commits.webkit.org/267562@main
  • Loading branch information
AndresGonzalezApple committed Sep 1, 2023
1 parent 6c8b6f1 commit a36f0d1
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,15 @@

id WebProcess::accessibilityFocusedUIElement()
{
auto retrieveFocusedUIElementFromMainThread = [] () {
return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([] () -> RetainPtr<id> {
RefPtr page = WebProcess::singleton().focusedWebPage();
if (!page || !page->accessibilityRemoteObject())
return nil;
return [page->accessibilityRemoteObject() accessibilityFocusedUIElement];
});
};

#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
if (!isMainRunLoop()) {
// Avoid hitting the main thread by getting the focused object from the focused isolated tree.
Expand All @@ -223,23 +232,19 @@
);
return state.containsAll({ ActivityState::IsVisible, ActivityState::IsFocused, ActivityState::WindowIsActive });
});
auto* isolatedTree = std::get_if<RefPtr<AXIsolatedTree>>(&tree);
if (!isolatedTree) {
// There is no isolated tree that has focus. This may be because none has been created yet, or because the one previously focused is being destroyed.
// In any case, get the focus from the main thread.
return retrieveFocusedUIElementFromMainThread();
}

RefPtr object = switchOn(tree,
[] (RefPtr<AXIsolatedTree>& typedTree) -> RefPtr<AXIsolatedObject> {
return typedTree ? typedTree->focusedNode() : nullptr;
}
, [] (auto&) -> RefPtr<AXIsolatedObject> {
return nullptr;
}
);
RefPtr object = (*isolatedTree)->focusedNode();
return object ? object->wrapper() : nil;
}
#endif

RefPtr page = WebProcess::singleton().focusedWebPage();
if (!page || !page->accessibilityRemoteObject())
return nil;
return [page->accessibilityRemoteObject() accessibilityFocusedUIElement];
return retrieveFocusedUIElementFromMainThread();
}

#if USE(APPKIT)
Expand Down

0 comments on commit a36f0d1

Please sign in to comment.