Commit 867d0031 authored by Victor Fei's avatar Victor Fei Committed by Commit Bot

AXEventGenerator::PostProcess to remove empty event sets at end

AXEventGenerator::Iterator iterates over the generated events in
std::map<AXNode*, std::set<EventParams>> tree_events_. Often there
could be entry with empty event sets (std::set<EventParams) in
|tree_events_|, and if these empty event sets happen to be the first
entry when we iterate over |tree_events_|, AXEventGenerator::Iterator
::operator++ would increment AXEventGenerator::Iterator::set_iter_
past its end, causing an exception.

This CL fixes this issue by looping over |tree_events_| in
AXEventGenerator::PostprocessEvents a second time to delete empty
empty std::set<EventParams> entry; so AXEventGenerator::Iterator
should only iterate over non-empty std::set<EventParams> entry.
DCHECKs are also added in AXEventGenerator::Iterator to check the
condition that only non-empty event sets remain.

AX-Relnotes: n/a

Bug: 1120281

Change-Id: I6c049be2cfb786c9777b4b840d598c77a8362e37
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410925Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Victor Fei <vicfei@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#807115}
parent f5eb2e72
...@@ -91,6 +91,8 @@ AXEventGenerator::EventParams::EventParams( ...@@ -91,6 +91,8 @@ AXEventGenerator::EventParams::EventParams(
const std::vector<AXEventIntent>& event_intents) const std::vector<AXEventIntent>& event_intents)
: event(event), event_from(event_from), event_intents(event_intents) {} : event(event), event_from(event_from), event_intents(event_intents) {}
AXEventGenerator::EventParams::EventParams(const EventParams& other) = default;
AXEventGenerator::EventParams::~EventParams() = default; AXEventGenerator::EventParams::~EventParams() = default;
AXEventGenerator::TargetedEvent::TargetedEvent(AXNode* node, AXEventGenerator::TargetedEvent::TargetedEvent(AXNode* node,
...@@ -130,11 +132,17 @@ AXEventGenerator::Iterator& AXEventGenerator::Iterator::operator++() { ...@@ -130,11 +132,17 @@ AXEventGenerator::Iterator& AXEventGenerator::Iterator::operator++() {
if (map_iter_ == map_.end()) if (map_iter_ == map_.end())
return *this; return *this;
DCHECK(set_iter_ != map_iter_->second.end())
<< "The set of events should not be empty";
set_iter_++; set_iter_++;
while (map_iter_ != map_.end() && set_iter_ == map_iter_->second.end()) {
if (set_iter_ == map_iter_->second.end()) {
map_iter_++; map_iter_++;
if (map_iter_ != map_.end()) if (map_iter_ != map_.end()) {
set_iter_ = map_iter_->second.begin(); set_iter_ = map_iter_->second.begin();
DCHECK(set_iter_ != map_iter_->second.end())
<< "The set of events should not be empty";
}
} }
return *this; return *this;
...@@ -809,10 +817,11 @@ void AXEventGenerator::TrimEventsDueToAncestorIgnoredChanged( ...@@ -809,10 +817,11 @@ void AXEventGenerator::TrimEventsDueToAncestorIgnoredChanged(
void AXEventGenerator::PostprocessEvents() { void AXEventGenerator::PostprocessEvents() {
std::map<AXNode*, IgnoredChangedStatesBitset> ancestor_ignored_changed_map; std::map<AXNode*, IgnoredChangedStatesBitset> ancestor_ignored_changed_map;
std::set<AXNode*> removed_subtree_created_nodes; std::set<AXNode*> removed_subtree_created_nodes;
auto iter = tree_events_.begin();
while (iter != tree_events_.end()) { // First pass through |tree_events_|, remove events that we do not need.
AXNode* node = iter->first; for (auto& iter : tree_events_) {
std::set<EventParams>& node_events = iter->second; AXNode* node = iter.first;
std::set<EventParams>& node_events = iter.second;
// A newly created live region or alert should not *also* fire a // A newly created live region or alert should not *also* fire a
// live region changed event. // live region changed event.
...@@ -864,10 +873,14 @@ void AXEventGenerator::PostprocessEvents() { ...@@ -864,10 +873,14 @@ void AXEventGenerator::PostprocessEvents() {
parent = parent->GetUnignoredParent(); parent = parent->GetUnignoredParent();
} }
} }
}
// If this was the only event, remove the node entirely from the // Second pass through |tree_events_|, remove nodes that do not have any
// tree events. // events left.
if (node_events.size() == 0) auto iter = tree_events_.begin();
while (iter != tree_events_.end()) {
std::set<EventParams>& node_events = iter->second;
if (node_events.empty())
iter = tree_events_.erase(iter); iter = tree_events_.erase(iter);
else else
++iter; ++iter;
......
...@@ -106,10 +106,11 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { ...@@ -106,10 +106,11 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
// IGNORED_CHANGED event. // IGNORED_CHANGED event.
enum class IgnoredChangedState : uint8_t { kShow, kHide, kCount = 2 }; enum class IgnoredChangedState : uint8_t { kShow, kHide, kCount = 2 };
struct EventParams { struct AX_EXPORT EventParams {
EventParams(Event event, EventParams(Event event,
ax::mojom::EventFrom event_from, ax::mojom::EventFrom event_from,
const std::vector<AXEventIntent>& event_intents); const std::vector<AXEventIntent>& event_intents);
EventParams(const EventParams& other);
~EventParams(); ~EventParams();
Event event; Event event;
ax::mojom::EventFrom event_from; ax::mojom::EventFrom event_from;
......
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