blob: 2dec5cfb6d0890032ac93c8a2dc6499348858bc1 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/macros.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
// This class should only be used from inside the accessibility directory.
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;
// Returns the parent of the given object due to aria-owns.
AXObject* GetAriaOwnedParent(const AXObject*) const;
// Given an object that has an aria-owns attributes, and a vector of ids from
// the value of that attribute, updates the internal state to reflect the new
// set of children owned by this object, returning the result in
// |ownedChildren|. The result is validated - illegal, duplicate, or cyclical
// references have been removed.
void UpdateAriaOwns(const AXObject* owner,
const Vector<String>& id_vector,
HeapVector<Member<AXObject>>& owned_children);
// Return true if any label ever pointed to the element via the for attribute.
bool MayHaveHTMLLabelViaForAttribute(const HTMLElement&);
// Given an element in the DOM tree that was either just added or whose id
// just changed, check to see if another object wants to be its parent due to
// aria-owns. If so, update the tree by calling childrenChanged() on the
// potential owner, possibly reparenting this element.
void UpdateRelatedTree(Node*);
// Remove given AXID from cache.
void RemoveAXID(AXID);
// Update map of ids to related objects.
// If one or more ids aren't found, they're added to a lookup table so that if
// an element with that id appears later, it can be added when you call
// UpdateRelatedTree.
void UpdateReverseRelations(const AXObject* relation_source,
const Vector<String>& target_ids);
void LabelChanged(Node*);
// If any object is related to this object via <label for>, aria-owns,
// aria-describedby or aria-labeledby, update the text for the related object.
void UpdateRelatedText(Node*);
bool IsValidOwnsRelation(AXObject* owner, AXObject* child) const;
void UnmapOwnedChildren(const AXObject* owner, Vector<AXID>);
void MapOwnedChildren(const AXObject* owner, Vector<AXID>);
void GetReverseRelated(Node*, HeapVector<Member<AXObject>>& sources);
WeakPersistent<AXObjectCacheImpl> object_cache_;
// Map from the AXID of the owner to the AXIDs of the children.
// This is a validated map, it doesn't contain illegal, duplicate,
// or cyclical matches, or references to IDs that don't exist.
HashMap<AXID, Vector<AXID>> aria_owner_to_children_mapping_;
// Map from the AXID of a child to the AXID of the parent that owns it.
HashMap<AXID, AXID> aria_owned_child_to_owner_mapping_;
// Map from the AXID of a child to the AXID of its real parent in the tree if
// we ignored aria-owns. This is needed in case the owner no longer wants to
// own it.
HashMap<AXID, AXID> aria_owned_child_to_real_parent_mapping_;
// Reverse relation map from an ID (the ID attribute of a DOM element) to the
// set of elements that at some time pointed to that ID via aria-owns,
// aria-labelledby, aria-desribedby. This is *unvalidated*, it includes
// possible extras and duplicates.
// This is used so that:
// - When an element with an ID is added to the tree or changes its ID, we can
// quickly determine if it affects an aria-owns relationship.
// - When text changes, we can recompute any label or description based on it
// and fire the appropriate change events.
HashMap<String, HashSet<AXID>> id_attr_to_related_mapping_;
// HTML id attributes that at one time havehad a <label for> pointing to it.
// IDs are not necessarily removed from this set. It is not necessary to
// remove IDs as false positives are ok. Being able to determine that a
// labelable element has never had an associated label allows the accessible
// name calculation to be optimized.
HashSet<AtomicString> all_previously_seen_label_target_ids_;
// Helpers that call back into object cache
AXObject* ObjectFromAXID(AXID) const;
AXObject* GetOrCreate(Node*);
AXObject* Get(Node*);
void ChildrenChanged(AXObject*);
void TextChanged(AXObject*);
} // namespace blink