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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/accessibility/inspect/ax_utils.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
char kActiveTabSwitch[] = "active-tab";
char kChromeSwitch[] = "chrome";
char kChromiumSwitch[] = "chromium";
char kFirefoxSwitch[] = "firefox";
char kEdgeSwitch[] = "edge";
char kPatternSwitch[] = "pattern";
char kSafariSwitch[] = "safari";
char kFiltersSwitch[] = "filters";
#if BUILDFLAG(IS_OZONE) || BUILDFLAG(IS_MAC)
char kIdSwitch[] = "pid";
#else
char kIdSwitch[] = "window";
#endif // defined(WINDOWS)
using ui::AXTreeSelector;
gfx::AcceleratedWidget CastToAcceleratedWidget(unsigned int window_id) {
#if BUILDFLAG(IS_OZONE) || BUILDFLAG(IS_MAC)
return static_cast<gfx::AcceleratedWidget>(window_id);
#else
return reinterpret_cast<gfx::AcceleratedWidget>(window_id);
#endif
}
// Convert from string to int, whether in 0x hex format or decimal format.
bool StringToInt(std::string str, unsigned* result) {
if (str.empty())
return false;
bool is_hex =
str.size() > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X');
return is_hex ? base::HexStringToUInt(str, result)
: base::StringToUint(str, result);
}
namespace tools {
void PrintHelpShared() {
printf("options:\n");
PrintHelpTreeSelectors();
PrintHelpFilters();
PrintHelpFooter();
}
void PrintHelpTreeSelectors() {
printf(" --pattern\ttitle of an application\n");
#if defined(WINDOWS)
printf(" --window\tHWND of a window\n");
#else
printf(" --pid\t\tprocess id of an application\n");
#endif
printf(" pre-defined application selectors:\n");
printf(" --chrome\tChrome browser\n");
printf(" --chromium\tChromium browser\n");
#if defined(WINDOWS)
printf(" --edge\tEdge browser\n");
#endif
printf(" --firefox\tFirefox browser\n");
#if BUILDFLAG(IS_MAC)
printf(" --safari\tSafari browser\n");
#endif
printf(
" --active-tab\tactive tab of browser, if application is a browser\n");
}
void PrintHelpFilters() {
printf(
" --filters\tfile containing property filters used to filter out\n"
" \t\taccessible tree, for example:\n"
" \t\t--filters=/absolute/path/to/filters/file\n");
}
void PrintHelpFooter() {
printf(
"\nmore info at "
"https://www.chromium.org/developers/accessibility/testing/"
"automated-testing/ax-inspect\n");
}
std::optional<AXTreeSelector> TreeSelectorFromCommandLine(
const base::CommandLine& command_line) {
int selectors = AXTreeSelector::None;
if (command_line.HasSwitch(kChromeSwitch)) {
selectors = AXTreeSelector::Chrome;
} else if (command_line.HasSwitch(kChromiumSwitch)) {
selectors = AXTreeSelector::Chromium;
} else if (command_line.HasSwitch(kEdgeSwitch)) {
selectors = AXTreeSelector::Edge;
} else if (command_line.HasSwitch(kFirefoxSwitch)) {
selectors = AXTreeSelector::Firefox;
} else if (command_line.HasSwitch(kSafariSwitch)) {
selectors = AXTreeSelector::Safari;
}
if (command_line.HasSwitch(kActiveTabSwitch)) {
selectors |= AXTreeSelector::ActiveTab;
}
std::string pattern_str = command_line.GetSwitchValueASCII(kPatternSwitch);
std::string id_str = command_line.GetSwitchValueASCII(kIdSwitch);
if (!id_str.empty()) {
unsigned hwnd_or_pid = 0;
if (!StringToInt(id_str, &hwnd_or_pid)) {
LOG(ERROR) << "Error: can't convert window id string to integer.";
return std::nullopt;
}
return AXTreeSelector(selectors, pattern_str,
CastToAcceleratedWidget(hwnd_or_pid));
}
return AXTreeSelector(selectors, pattern_str);
}
std::string DirectivePrefixFromAPIType(ui::AXApiType::Type api) {
switch (api) {
case ui::AXApiType::kMac:
return "@AXAPI-";
case ui::AXApiType::kLinux:
return "@ATSPI-";
case ui::AXApiType::kWinIA2:
return "@IA2-";
case ui::AXApiType::kWinUIA:
return "@UIA-";
// If no or unsupported API, use the generic prefix
default:
return "@";
}
}
std::optional<ui::AXInspectScenario> ScenarioFromCommandLine(
const base::CommandLine& command_line,
ui::AXApiType::Type api) {
base::FilePath filters_path = command_line.GetSwitchValuePath(kFiltersSwitch);
if (filters_path.empty() && command_line.HasSwitch(kFiltersSwitch)) {
LOG(ERROR) << "Error: empty filter path given. Run with --help for help.";
return std::nullopt;
}
std::string directive_prefix = DirectivePrefixFromAPIType(api);
// Return with the default filter scenario if no file is provided.
if (filters_path.empty()) {
return ui::AXInspectScenario::From(directive_prefix,
std::vector<std::string>());
}
std::optional<ui::AXInspectScenario> scenario =
ui::AXInspectScenario::From(directive_prefix, filters_path);
if (!scenario) {
LOG(ERROR) << "Error: failed to open filters file " << filters_path
<< ". Note: path traversal components ('..') are not allowed "
"for security reasons";
return std::nullopt;
}
return scenario;
}
} // namespace tools
|