| // Copyright 2017 The Fuchsia 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 "context_writer_bridge.h" |
| |
| #include <unordered_set> |
| |
| #include "rapidjson/document.h" |
| #include "rapidjson/stringbuffer.h" |
| #include "rapidjson/writer.h" |
| |
| namespace flutter { |
| |
| ContextWriterBridge::ContextWriterBridge( |
| fidl::InterfaceHandle<fuchsia::modular::ContextWriter> writer) |
| : writer_(writer.Bind()) {} |
| |
| ContextWriterBridge::~ContextWriterBridge() = default; |
| |
| void ContextWriterBridge::UpdateSemantics( |
| const blink::SemanticsNodeUpdates& update) { |
| for (const auto& update : update) { |
| const auto& node = update.second; |
| semantics_nodes_[node.id] = node; |
| } |
| std::vector<int> visited_nodes; |
| UpdateVisitedForNodeAndChildren(0, &visited_nodes); |
| EraseUnvisitedNodes(visited_nodes); |
| |
| // The data sent to the Context Service is a JSON formatted list of labels |
| // for all on screen widgets. |
| rapidjson::Document nodes_json(rapidjson::kArrayType); |
| for (const int node_index : visited_nodes) { |
| const auto& node = semantics_nodes_[node_index]; |
| if (!node.label.empty()) { |
| rapidjson::Value value; |
| value.SetString(node.label.data(), node.label.size()); |
| nodes_json.PushBack(value, nodes_json.GetAllocator()); |
| } |
| } |
| |
| if (nodes_json.Size() > 0) { |
| rapidjson::StringBuffer buffer; |
| rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); |
| nodes_json.Accept(writer); |
| writer_->WriteEntityTopic("/inferred/accessibility_text", |
| buffer.GetString()); |
| } |
| } |
| |
| void ContextWriterBridge::UpdateVisitedForNodeAndChildren( |
| const int id, std::vector<int>* visited_nodes) { |
| std::map<int, blink::SemanticsNode>::const_iterator it = |
| semantics_nodes_.find(id); |
| if (it == semantics_nodes_.end()) { |
| return; |
| } |
| |
| visited_nodes->push_back(id); |
| for (const int child : it->second.childrenInTraversalOrder) { |
| UpdateVisitedForNodeAndChildren(child, visited_nodes); |
| } |
| } |
| |
| void ContextWriterBridge::EraseUnvisitedNodes( |
| const std::vector<int>& visited_nodes) { |
| const std::unordered_set<int> visited_nodes_lookup(visited_nodes.begin(), |
| visited_nodes.end()); |
| for (auto it = semantics_nodes_.begin(); it != semantics_nodes_.end();) { |
| if (visited_nodes_lookup.find((*it).first) == visited_nodes_lookup.end()) { |
| it = semantics_nodes_.erase(it); |
| } else { |
| ++it; |
| } |
| } |
| } |
| |
| } // namespace flutter |