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) ...@@ -121,6 +121,7 @@ AXObjectCacheImpl::AXObjectCacheImpl(Document& document)
AddPermissionStatusListener(); AddPermissionStatusListener();
documents_.insert(&document); documents_.insert(&document);
document.View()->RegisterForLifecycleNotifications(this); document.View()->RegisterForLifecycleNotifications(this);
relation_cache_->Init();
} }
AXObjectCacheImpl::~AXObjectCacheImpl() { AXObjectCacheImpl::~AXObjectCacheImpl() {
......
...@@ -396,5 +396,55 @@ TEST_F(AccessibilityTest, CheckNoDuplicateChildren) { ...@@ -396,5 +396,55 @@ TEST_F(AccessibilityTest, CheckNoDuplicateChildren) {
ASSERT_EQ(ax_select->FirstChild()->ChildCount(), 1); 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 test
} // namespace blink } // namespace blink
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h" #include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
#include "base/memory/ptr_util.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" #include "third_party/blink/renderer/core/html/forms/html_label_element.h"
namespace blink { namespace blink {
...@@ -16,6 +17,24 @@ AXRelationCache::AXRelationCache(AXObjectCacheImpl* object_cache) ...@@ -16,6 +17,24 @@ AXRelationCache::AXRelationCache(AXObjectCacheImpl* object_cache)
AXRelationCache::~AXRelationCache() = default; 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 { bool AXRelationCache::IsAriaOwned(const AXObject* child) const {
return aria_owned_child_to_owner_mapping_.Contains(child->AXObjectID()); return aria_owned_child_to_owner_mapping_.Contains(child->AXObjectID());
} }
...@@ -271,6 +290,7 @@ void AXRelationCache::TextChanged(AXObject* object) { ...@@ -271,6 +290,7 @@ void AXRelationCache::TextChanged(AXObject* object) {
void AXRelationCache::LabelChanged(Node* node) { void AXRelationCache::LabelChanged(Node* node) {
const auto& id = To<HTMLElement>(node)->FastGetAttribute(kForAttr); const auto& id = To<HTMLElement>(node)->FastGetAttribute(kForAttr);
LOG(ERROR) << "LabelChanged " << id;
if (!id.IsEmpty()) { if (!id.IsEmpty()) {
all_previously_seen_label_target_ids_.insert(id); all_previously_seen_label_target_ids_.insert(id);
if (auto* control = To<HTMLLabelElement>(node)->control()) if (auto* control = To<HTMLLabelElement>(node)->control())
......
...@@ -22,6 +22,9 @@ class AXRelationCache { ...@@ -22,6 +22,9 @@ class AXRelationCache {
explicit AXRelationCache(AXObjectCacheImpl*); explicit AXRelationCache(AXObjectCacheImpl*);
virtual ~AXRelationCache(); virtual ~AXRelationCache();
// Scan the initial document.
void Init();
// Returns true if the given object's position in the tree was due to // Returns true if the given object's position in the tree was due to
// aria-owns. // aria-owns.
bool IsAriaOwned(const AXObject*) const; bool IsAriaOwned(const AXObject*) const;
......
...@@ -44,12 +44,13 @@ class AccessibilityTest : public RenderingTest { ...@@ -44,12 +44,13 @@ class AccessibilityTest : public RenderingTest {
std::string PrintAXTree() const; std::string PrintAXTree() const;
protected:
std::unique_ptr<AXContext> ax_context_;
private: private:
std::ostringstream& PrintAXTreeHelper(std::ostringstream&, std::ostringstream& PrintAXTreeHelper(std::ostringstream&,
const AXObject* root, const AXObject* root,
size_t level) const; size_t level) const;
std::unique_ptr<AXContext> ax_context_;
}; };
} // namespace test } // 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