Commit cae06dfe authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Chromium LUCI CQ

Reland: wait until safe time to create root accessibility object

It is only safe to create an accessibility object when a document's
style has been computed and layout is clean.

Previously, tests failed because an extra kLoadComplete event
was sometimes fired for the initial empty document, before navigating
to the actual data: url with the test's contents. The extra event
only seems to occur in ChromeOS debug builds.

Bug: 1156939
Change-Id: I95f4afdb5471a98ed87fb1cf8e8a208e5ebfc453
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2611559Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarAaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842329}
parent f1a9be90
......@@ -265,14 +265,9 @@ void RenderAccessibilityImpl::AccessibilityModeChanged(const ui::AXMode& mode) {
if (!document.IsNull()) {
StartOrStopLabelingImages(old_mode, mode);
// If there are any events in flight, |HandleAXEvent| will refuse to process
// our new event.
pending_events_.clear();
auto root_object = WebAXObject::FromWebDocument(document, false);
ax::mojom::Event event = root_object.IsLoaded()
? ax::mojom::Event::kLoadComplete
: ax::mojom::Event::kLayoutComplete;
HandleAXEvent(ui::AXEvent(root_object.AxID(), event));
needs_initial_ax_tree_root_ = true;
event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately;
ScheduleSendPendingAccessibilityEvents();
}
}
......@@ -476,11 +471,11 @@ void RenderAccessibilityImpl::Reset(int32_t reset_token) {
if (!document.IsNull()) {
// Tree-only mode gets used by the automation extension API which requires a
// load complete event to invoke listener callbacks.
auto root_object = WebAXObject::FromWebDocument(document, false);
ax::mojom::Event event = root_object.IsLoaded()
? ax::mojom::Event::kLoadComplete
: ax::mojom::Event::kLayoutComplete;
HandleAXEvent(ui::AXEvent(root_object.AxID(), event));
// SendPendingAccessibilityEvents() will fire the load complete event
// if the page is loaded.
needs_initial_ax_tree_root_ = true;
event_schedule_mode_ = EventScheduleMode::kProcessEventsImmediately;
ScheduleSendPendingAccessibilityEvents();
}
}
......@@ -797,10 +792,20 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() {
// complete for the entire document, in order to initialize the browser's
// cached accessibility tree.
needs_initial_ax_tree_root_ = false;
auto obj = WebAXObject::FromWebDocument(document);
auto root_obj = WebAXObject::FromWebDocument(document);
// Always fire layout complete for a new root object.
pending_events_.insert(
pending_events_.begin(),
ui::AXEvent(obj.AxID(), ax::mojom::Event::kLayoutComplete));
ui::AXEvent(root_obj.AxID(), ax::mojom::Event::kLayoutComplete));
// If loaded and has some content, insert load complete at the top, so that
// screen readers are informed a new document is ready.
if (root_obj.IsLoaded() && !document.Body().IsNull() &&
!document.Body().FirstChild().IsNull()) {
pending_events_.insert(
pending_events_.begin(),
ui::AXEvent(root_obj.AxID(), ax::mojom::Event::kLoadComplete));
}
}
if (pending_events_.empty() && dirty_objects_.empty()) {
......@@ -834,8 +839,8 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() {
// location changes.
bool need_to_send_location_changes = false;
// If there's a load complete message, we need to change the event schedule
// mode.
// Keep track of load complete messages. When a load completes, it's a good
// time to inject a stylesheet for image annotation debugging.
bool had_load_complete_messages = false;
ScopedFreezeBlinkAXTreeSource freeze(tree_source_.get());
......
......@@ -81,9 +81,7 @@ class WebAXObject {
BLINK_EXPORT bool operator>(const WebAXObject& other) const;
BLINK_EXPORT bool operator>=(const WebAXObject& other) const;
BLINK_EXPORT static WebAXObject FromWebNode(const WebNode&);
BLINK_EXPORT static WebAXObject FromWebDocument(
const WebDocument&,
bool update_layout_if_necessary = true);
BLINK_EXPORT static WebAXObject FromWebDocument(const WebDocument&);
BLINK_EXPORT static WebAXObject FromWebDocumentByID(const WebDocument&, int);
BLINK_EXPORT static WebAXObject FromWebDocumentFocused(
const WebDocument&,
......
......@@ -1443,12 +1443,9 @@ WebAXObject WebAXObject::FromWebNode(const WebNode& web_node) {
}
// static
WebAXObject WebAXObject::FromWebDocument(const WebDocument& web_document,
bool update_layout_if_necessary) {
if (update_layout_if_necessary &&
!MaybeUpdateLayoutAndCheckValidity(web_document)) {
WebAXObject WebAXObject::FromWebDocument(const WebDocument& web_document) {
if (!MaybeUpdateLayoutAndCheckValidity(web_document))
return WebAXObject();
}
const Document* document = web_document.ConstUnwrap<Document>();
auto* cache = To<AXObjectCacheImpl>(document->ExistingAXObjectCache());
return cache ? WebAXObject(cache->GetOrCreate(document->GetLayoutView()))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment