Commit fa253bb4 authored by Dominic Mazzoni's avatar Dominic Mazzoni Committed by Commit Bot

Init AXRelationCache with the nodes already in the document.

Bug: 999236
Change-Id: I85ebdf7da06874cb55672fab6ec7071144858418
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825958Reviewed-by: default avatarAaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704259}
parent ec2c17d7
......@@ -121,6 +121,7 @@ AXObjectCacheImpl::AXObjectCacheImpl(Document& document)
AddPermissionStatusListener();
documents_.insert(&document);
document.View()->RegisterForLifecycleNotifications(this);
relation_cache_->Init();
}
AXObjectCacheImpl::~AXObjectCacheImpl() {
......
......@@ -396,5 +396,55 @@ TEST_F(AccessibilityTest, CheckNoDuplicateChildren) {
ASSERT_EQ(ax_select->FirstChild()->ChildCount(), 1);
}
TEST_F(AccessibilityTest, InitRelationCache) {
// All of the other tests already have accessibility initialized
// first, but we don't want to in this test.
//
// Get rid of the AXContext so the AXObjectCache is destroyed.
ax_context_.reset(nullptr);
SetBodyInnerHTML(R"HTML(
<ul id="ul" aria-owns="li"></ul>
<label for="a"></label>
<input id="a">
<input id="b">
<div role="section" id="div">
<li id="li"></li>
</div>
)HTML");
// Now recreate an AXContext, simulating what happens if accessibility
// is enabled after the document is loaded.
ax_context_.reset(new AXContext(GetDocument()));
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
const AXObject* input_a = GetAXObjectByElementId("a");
ASSERT_NE(nullptr, input_a);
const AXObject* input_b = GetAXObjectByElementId("b");
ASSERT_NE(nullptr, input_b);
EXPECT_TRUE(
GetAXObjectCache().MayHaveHTMLLabel(ToHTMLElement(*input_a->GetNode())));
EXPECT_FALSE(
GetAXObjectCache().MayHaveHTMLLabel(ToHTMLElement(*input_b->GetNode())));
// Note: retrieve the LI first and check that its parent is not
// the paragraph element. If we were to retrieve the UL element,
// that would trigger the aria-owns check and wouln't allow us to
// test whether the relation cache was initialized.
const AXObject* li = GetAXObjectByElementId("li");
ASSERT_NE(nullptr, li);
const AXObject* div = GetAXObjectByElementId("div");
ASSERT_NE(nullptr, div);
EXPECT_NE(li->ParentObjectUnignored(), div);
const AXObject* ul = GetAXObjectByElementId("ul");
ASSERT_NE(nullptr, ul);
EXPECT_EQ(li->ParentObjectUnignored(), ul);
}
} // namespace test
} // namespace blink
......@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/html/forms/html_label_element.h"
namespace blink {
......@@ -16,6 +17,24 @@ AXRelationCache::AXRelationCache(AXObjectCacheImpl* object_cache)
AXRelationCache::~AXRelationCache() = default;
void AXRelationCache::Init() {
// Init the relation cache with elements already in the document.
Document& document = object_cache_->GetDocument();
for (Element& element :
ElementTraversal::DescendantsOf(*document.documentElement())) {
const auto& id = element.FastGetAttribute(kForAttr);
if (!id.IsEmpty())
all_previously_seen_label_target_ids_.insert(id);
if (element.FastHasAttribute(kAriaOwnsAttr)) {
if (AXObject* obj = object_cache_->GetOrCreate(&element)) {
obj->ClearChildren();
obj->AddChildren();
}
}
}
}
bool AXRelationCache::IsAriaOwned(const AXObject* child) const {
return aria_owned_child_to_owner_mapping_.Contains(child->AXObjectID());
}
......@@ -271,6 +290,7 @@ void AXRelationCache::TextChanged(AXObject* object) {
void AXRelationCache::LabelChanged(Node* node) {
const auto& id = To<HTMLElement>(node)->FastGetAttribute(kForAttr);
LOG(ERROR) << "LabelChanged " << id;
if (!id.IsEmpty()) {
all_previously_seen_label_target_ids_.insert(id);
if (auto* control = To<HTMLLabelElement>(node)->control())
......
......@@ -22,6 +22,9 @@ class AXRelationCache {
explicit AXRelationCache(AXObjectCacheImpl*);
virtual ~AXRelationCache();
// Scan the initial document.
void Init();
// Returns true if the given object's position in the tree was due to
// aria-owns.
bool IsAriaOwned(const AXObject*) const;
......
......@@ -44,12 +44,13 @@ class AccessibilityTest : public RenderingTest {
std::string PrintAXTree() const;
protected:
std::unique_ptr<AXContext> ax_context_;
private:
std::ostringstream& PrintAXTreeHelper(std::ostringstream&,
const AXObject* root,
size_t level) const;
std::unique_ptr<AXContext> ax_context_;
};
} // namespace test
......
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