1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/accessibility/platform/inspect/ax_inspect_utils.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
namespace ui {
constexpr char kConstValuePrefix[] = "_const_";
constexpr char kSetKeyPrefixDictAttr[] = "_setkey_";
constexpr char kOrderedKeyPrefixDictAttr[] = "_index_";
std::string AXMakeConst(const std::string& value) {
return kConstValuePrefix + value;
}
std::string AXMakeSetKey(const std::string& key_name) {
return kSetKeyPrefixDictAttr + key_name;
}
std::string AXMakeOrderedKey(const std::string& key_name, int position) {
// Works for single-diget orders.
return kOrderedKeyPrefixDictAttr + base::NumberToString(position) + key_name;
}
std::string AXFormatValue(const base::Value& value) {
// String.
if (value.is_string()) {
// Special handling for constants which are exposed as is, i.e. with no
// quotation marks.
std::string const_prefix = kConstValuePrefix;
if (value.GetString().starts_with(const_prefix)) {
return value.GetString().substr(const_prefix.length());
}
// TODO: escape quotation marks if any to make the output unambiguous.
return "'" + value.GetString() + "'";
}
// Integer.
if (value.is_int()) {
return base::NumberToString(value.GetInt());
}
// Double.
if (value.is_double()) {
return base::NumberToString(value.GetDouble());
}
// List: exposed as [value1, ..., valueN];
if (value.is_list()) {
std::string output;
for (const auto& item : value.GetList()) {
if (!output.empty()) {
output += ", ";
}
output += AXFormatValue(item);
}
return "[" + output + "]";
}
// Dictionary. Exposed as {key1: value1, ..., keyN: valueN}. Set-like
// dictionary is exposed as {value1, ..., valueN}.
if (value.is_dict()) {
const std::string setkey_prefix(kSetKeyPrefixDictAttr);
const std::string orderedkey_prefix(kOrderedKeyPrefixDictAttr);
std::string output;
for (auto item : value.GetDict()) {
if (!output.empty()) {
output += ", ";
}
if (item.first.starts_with(setkey_prefix)) {
// Some of the dictionary's keys should not be appended to the output,
// so that the dictionary can also be used as a set. Such keys start
// with the _setkey_ prefix.
output += AXFormatValue(item.second);
} else if (item.first.starts_with(orderedkey_prefix)) {
// Process ordered dictionaries. Remove order number from keys before
// formatting.
std::string key = item.first;
key.erase(0, orderedkey_prefix.length() + 1);
output += key + ": " + AXFormatValue(item.second);
} else {
output += item.first + ": " + AXFormatValue(item.second);
}
}
return "{" + output + "}";
}
return "";
}
} // namespace ui
|