File: ax_utils.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (171 lines) | stat: -rw-r--r-- 5,363 bytes parent folder | download | duplicates (10)
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