| Index: content/browser/accessibility/one_shot_accessibility_tree_search.cc
|
| diff --git a/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a0b85f9e3ffb14d7fec318eceff1bc49452596ee
|
| --- /dev/null
|
| +++ b/content/browser/accessibility/one_shot_accessibility_tree_search.cc
|
| @@ -0,0 +1,182 @@
|
| +// Copyright 2015 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 "content/browser/accessibility/one_shot_accessibility_tree_search.h"
|
| +
|
| +#include "base/i18n/case_conversion.h"
|
| +#include "base/strings/string16.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "content/browser/accessibility/browser_accessibility.h"
|
| +#include "content/browser/accessibility/browser_accessibility_manager.h"
|
| +
|
| +namespace content {
|
| +
|
| +// Given a node, populate a vector with all of the strings from that node's
|
| +// attributes that might be relevant for a text search.
|
| +void GetNodeStrings(BrowserAccessibility* node,
|
| + std::vector<base::string16>* strings) {
|
| + if (node->HasStringAttribute(ui::AX_ATTR_NAME))
|
| + strings->push_back(node->GetString16Attribute(ui::AX_ATTR_NAME));
|
| + if (node->HasStringAttribute(ui::AX_ATTR_DESCRIPTION))
|
| + strings->push_back(node->GetString16Attribute(ui::AX_ATTR_DESCRIPTION));
|
| + if (node->HasStringAttribute(ui::AX_ATTR_HELP))
|
| + strings->push_back(node->GetString16Attribute(ui::AX_ATTR_HELP));
|
| + if (node->HasStringAttribute(ui::AX_ATTR_VALUE))
|
| + strings->push_back(node->GetString16Attribute(ui::AX_ATTR_VALUE));
|
| + if (node->HasStringAttribute(ui::AX_ATTR_PLACEHOLDER))
|
| + strings->push_back(node->GetString16Attribute(ui::AX_ATTR_PLACEHOLDER));
|
| +}
|
| +
|
| +OneShotAccessibilityTreeSearch::OneShotAccessibilityTreeSearch(
|
| + BrowserAccessibilityManager* tree)
|
| + : tree_(tree),
|
| + start_node_(nullptr),
|
| + direction_(OneShotAccessibilityTreeSearch::FORWARDS),
|
| + result_limit_(UNLIMITED_RESULTS),
|
| + immediate_descendants_only_(false),
|
| + visible_only_(false),
|
| + did_search_(false) {
|
| +}
|
| +
|
| +OneShotAccessibilityTreeSearch::~OneShotAccessibilityTreeSearch() {
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetStartNode(
|
| + BrowserAccessibility* start_node) {
|
| + DCHECK(!did_search_);
|
| + start_node_ = start_node;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetDirection(Direction direction) {
|
| + DCHECK(!did_search_);
|
| + direction_ = direction;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetResultLimit(int result_limit) {
|
| + DCHECK(!did_search_);
|
| + result_limit_ = result_limit;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetImmediateDescendantsOnly(
|
| + bool immediate_descendants_only) {
|
| + DCHECK(!did_search_);
|
| + immediate_descendants_only_ = immediate_descendants_only;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetVisibleOnly(bool visible_only) {
|
| + DCHECK(!did_search_);
|
| + visible_only_ = visible_only;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SetSearchText(const std::string& text) {
|
| + DCHECK(!did_search_);
|
| + search_text_ = text;
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::AddPredicate(
|
| + AccessibilityMatchPredicate predicate) {
|
| + DCHECK(!did_search_);
|
| + predicates_.push_back(predicate);
|
| +}
|
| +
|
| +size_t OneShotAccessibilityTreeSearch::CountMatches() {
|
| + if (!did_search_)
|
| + Search();
|
| +
|
| + return matches_.size();
|
| +}
|
| +
|
| +BrowserAccessibility* OneShotAccessibilityTreeSearch::GetMatchAtIndex(
|
| + size_t index) {
|
| + if (!did_search_)
|
| + Search();
|
| +
|
| + CHECK(index < matches_.size());
|
| + return matches_[index];
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::Search()
|
| +{
|
| + if (immediate_descendants_only_) {
|
| + SearchByIteratingOverChildren();
|
| + } else {
|
| + SearchByWalkingTree();
|
| + }
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SearchByIteratingOverChildren() {
|
| + if (!start_node_)
|
| + return;
|
| +
|
| + for (unsigned i = 0;
|
| + i < start_node_->PlatformChildCount() &&
|
| + (result_limit_ == UNLIMITED_RESULTS ||
|
| + static_cast<int>(matches_.size()) < result_limit_);
|
| + ++i) {
|
| + BrowserAccessibility* child = start_node_->PlatformGetChild(i);
|
| + if (Matches(child))
|
| + matches_.push_back(child);
|
| + }
|
| +}
|
| +
|
| +void OneShotAccessibilityTreeSearch::SearchByWalkingTree() {
|
| + BrowserAccessibility* node = nullptr;
|
| + if (start_node_) {
|
| + if (direction_ == FORWARDS)
|
| + node = tree_->NextInTreeOrder(start_node_);
|
| + else
|
| + node = tree_->PreviousInTreeOrder(start_node_);
|
| + } else {
|
| + start_node_ = tree_->GetRoot();
|
| + node = start_node_;
|
| + }
|
| +
|
| + while (node && (result_limit_ == UNLIMITED_RESULTS ||
|
| + static_cast<int>(matches_.size()) < result_limit_)) {
|
| + if (Matches(node))
|
| + matches_.push_back(node);
|
| +
|
| + if (direction_ == FORWARDS)
|
| + node = tree_->NextInTreeOrder(node);
|
| + else
|
| + node = tree_->PreviousInTreeOrder(node);
|
| + }
|
| +}
|
| +
|
| +bool OneShotAccessibilityTreeSearch::Matches(BrowserAccessibility* node) {
|
| + for (size_t i = 0; i < predicates_.size(); ++i) {
|
| + if (!predicates_[i](start_node_, node))
|
| + return false;
|
| + }
|
| +
|
| + if (visible_only_) {
|
| + if (node->HasState(ui::AX_STATE_INVISIBLE) ||
|
| + node->HasState(ui::AX_STATE_OFFSCREEN)) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + if (!search_text_.empty()) {
|
| + base::string16 search_text_lower =
|
| + base::i18n::ToLower(base::UTF8ToUTF16(search_text_));
|
| + std::vector<base::string16> node_strings;
|
| + GetNodeStrings(node, &node_strings);
|
| + bool found_text_match = false;
|
| + for (size_t i = 0; i < node_strings.size(); ++i) {
|
| + base::string16 node_string_lower =
|
| + base::i18n::ToLower(node_strings[i]);
|
| + if (node_string_lower.find(search_text_lower) !=
|
| + base::string16::npos) {
|
| + found_text_match = true;
|
| + break;
|
| + }
|
| + }
|
| + if (!found_text_match)
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace content
|
|
|