0

[A11y] Invalidate AXIDs when those objects are removed

After CL:4185636, an AXObject may have been detached and recreated
with the same DOM node, and therefore has the same id (the dom node id).
This breaks the accessibility object caching mechanism used for web
tests, which assumes that if it sees the same ID, it can assume the
object is still the same one. The fix is to notify the caching
mechanism of detached AXObjects so that it can invalidate the
corresponding entries.

Bug: none
Change-Id: I152538644f9dc24d4e7fbfe68057deb4ab4d34aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5262560
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1256301}
This commit is contained in:
Aaron Leventhal
2024-02-05 18:37:11 +00:00
committed by Chromium LUCI CQ
parent 0db3d2ad7c
commit 408b51a92e
7 changed files with 29 additions and 2 deletions

@ -343,4 +343,10 @@ blink::WebAXObject AccessibilityController::GetAccessibilityObjectForMainFrame()
web_view()->MainFrame()->ToWebLocalFrame()->GetDocument());
}
void AccessibilityController::Remove(unsigned axid) {
if (IsInstalled()) {
elements_->Remove(axid);
}
}
} // namespace content

@ -51,6 +51,8 @@ class AccessibilityController {
const std::string& notification_name,
const std::vector<ui::AXEventIntent>& event_intents);
void Remove(unsigned axid);
private:
friend class AccessibilityControllerBindings;

@ -267,6 +267,7 @@ class WebAXObjectProxyList : public WebAXObjectProxy::Factory {
~WebAXObjectProxyList() override;
void Clear();
void Remove(unsigned axid) { ax_objects_.erase(axid); }
v8::Local<v8::Object> GetOrCreate(const blink::WebAXObject&) override;
blink::WebAXContext* GetAXContext() override;

@ -561,6 +561,10 @@ void WebFrameTestProxy::PostAccessibilityEvent(const ui::AXEvent& event) {
RenderFrameImpl::PostAccessibilityEvent(event);
}
void WebFrameTestProxy::HandleAXObjectDetachedForTest(unsigned axid) {
accessibility_controller_.Remove(axid);
}
void WebFrameTestProxy::HandleWebAccessibilityEventForTest(
const blink::WebAXObject& object,
const char* event_name,

@ -89,6 +89,7 @@ class WebFrameTestProxy : public RenderFrameImpl,
bool should_reset_browser_interface_broker,
const blink::ParsedPermissionsPolicy& permissions_policy_header,
const blink::DocumentPolicyFeatureState& document_policy_header) override;
void HandleAXObjectDetachedForTest(unsigned axid) override;
void HandleWebAccessibilityEventForTest(
const blink::WebAXObject& object,
const char* event_name,

@ -818,6 +818,11 @@ class BLINK_EXPORT WebLocalFrameClient {
// a window.print() call.
virtual void ScriptedPrint() {}
// This method is ONLY for web tests and is not supposed to be overridden in
// classes other than web_frame_test_proxy. It's called from accessibility and
// is used as a way to notify that an accessibility object has been destroyed.
virtual void HandleAXObjectDetachedForTest(unsigned axid) {}
// This method is ONLY for web tests and is not supposed to be overridden in
// classes other than web_frame_test_proxy. It's called from accessibility and
// is used as a way to tunnel events to the accessibility_controller in web

@ -1775,8 +1775,16 @@ void AXObjectCacheImpl::Remove(AXID ax_id, bool notify_parent) {
}
#endif
if (notify_parent && !has_been_disposed_) {
ChildrenChangedOnAncestorOf(obj);
if (!has_been_disposed_) {
if (notify_parent) {
ChildrenChangedOnAncestorOf(obj);
}
// TODO(aleventhal) This is for web tests only, in order to record MarkDirty
// events. Is there a way to avoid these calls for normal browsing?
// Maybe we should use dependency injection from AccessibilityController.
if (auto* client = GetWebLocalFrameClient()) {
client->HandleAXObjectDetachedForTest(ax_id);
}
}
obj->Detach();