refactor: address changes and fix errors in chrome://accessibility (#41948)

refactor: address changes and fix errors in chrome://accessibility

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
trop[bot] 2024-04-23 21:14:14 -05:00 committed by GitHub
parent 9437dd3ea8
commit 773777f209
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 243 additions and 191 deletions

View file

@ -52,7 +52,7 @@ crash_allow_setting_more_options.patch
upload_list_add_loadsync_method.patch
allow_setting_secondary_label_via_simplemenumodel.patch
feat_add_streaming-protocol_registry_to_multibuffer_data_source.patch
fix_patch_out_profile_refs_in_accessibility_ui.patch
adjust_accessibility_ui_for_electron.patch
skip_atk_toolchain_check.patch
worker_feat_add_hook_to_notify_script_ready.patch
chore_provide_iswebcontentscreationoverridden_with_full_params.patch

View file

@ -1,47 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 6 Jul 2020 13:46:06 -0700
Subject: fix: patch out Profile refs in accessibility_ui
Subject: Adjust accessibility_ui for Electron
This tweaks Chrome's Accessibility support at chrome://accessibility
to make it usable from Electron by removing Profile references.
to make it usable from Electron by replacing use of the Profile PrefService
with Electron's own PrefService in ElectronBrowserContext. It also removes
usage of BrowserList and Browser as we subclass related methods and use our
WindowList.
diff --git a/chrome/browser/ui/webui/accessibility/accessibility_ui.cc b/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
index 45b085ebb5096b2cdd083337371539a249c7a0a8..404a0a8d99eb68a35c0c06fe1b1dbfa3086e8794 100644
index 45b085ebb5096b2cdd083337371539a249c7a0a8..9a0a6cb8b37c60641c2c51aa489fbf22cdb123cb 100644
--- a/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
+++ b/chrome/browser/ui/webui/accessibility/accessibility_ui.cc
@@ -23,7 +23,10 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#if 0
#include "chrome/browser/profiles/profile.h"
+#endif
+#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/accessibility_resources.h"
@@ -33,6 +36,7 @@
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/ax_inspect_factory.h"
#include "content/public/browser/browser_accessibility_state.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
@@ -52,9 +56,11 @@
#include "ui/views/accessibility/view_accessibility.h"
#if !BUILDFLAG(IS_ANDROID)
+#if 0
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
+#endif
#include "ui/views/accessibility/widget_ax_tree_id_map.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -169,7 +175,7 @@ base::Value::Dict BuildTargetDescriptor(content::RenderViewHost* rvh) {
@@ -44,6 +44,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "electron/shell/browser/electron_browser_context.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -169,7 +170,7 @@ base::Value::Dict BuildTargetDescriptor(content::RenderViewHost* rvh) {
accessibility_mode);
}
@ -50,27 +30,25 @@ index 45b085ebb5096b2cdd083337371539a249c7a0a8..404a0a8d99eb68a35c0c06fe1b1dbfa3
base::Value::Dict BuildTargetDescriptor(Browser* browser) {
base::Value::Dict target_data;
target_data.Set(kSessionIdField, browser->session_id().id());
@@ -203,7 +209,9 @@ void HandleAccessibilityRequestCallback(
@@ -203,7 +204,7 @@ void HandleAccessibilityRequestCallback(
DCHECK(ShouldHandleAccessibilityRequestCallback(path));
base::Value::Dict data;
+#if 0
PrefService* pref = Profile::FromBrowserContext(current_context)->GetPrefs();
+#endif
- PrefService* pref = Profile::FromBrowserContext(current_context)->GetPrefs();
+ PrefService* pref = static_cast<electron::ElectronBrowserContext*>(current_context)->prefs();
ui::AXMode mode =
content::BrowserAccessibilityState::GetInstance()->GetAccessibilityMode();
bool is_native_enabled = content::BrowserAccessibilityState::GetInstance()
@@ -235,8 +243,7 @@ void HandleAccessibilityRequestCallback(
// enabled.
@@ -236,7 +237,7 @@ void HandleAccessibilityRequestCallback(
data.Set(kViewsAccessibility, features::IsAccessibilityTreeForViewsEnabled());
- std::string pref_api_type =
std::string pref_api_type =
- pref->GetString(prefs::kShownAccessibilityApiType);
+ std::string pref_api_type = "blink";
+ std::string(pref->GetString(prefs::kShownAccessibilityApiType));
bool pref_api_type_supported = false;
std::vector<ui::AXApiType::Type> supported_api_types =
@@ -303,11 +310,11 @@ void HandleAccessibilityRequestCallback(
@@ -303,11 +304,11 @@ void HandleAccessibilityRequestCallback(
data.Set(kPagesField, std::move(page_list));
base::Value::List browser_list;
@ -80,36 +58,31 @@ index 45b085ebb5096b2cdd083337371539a249c7a0a8..404a0a8d99eb68a35c0c06fe1b1dbfa3
browser_list.Append(BuildTargetDescriptor(browser));
}
-#endif // !BUILDFLAG(IS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
+#endif
data.Set(kBrowsersField, std::move(browser_list));
base::Value::List widgets_list;
@@ -647,8 +654,10 @@ void AccessibilityUIMessageHandler::SetGlobalString(
@@ -647,7 +648,8 @@ void AccessibilityUIMessageHandler::SetGlobalString(
const std::string value = CheckJSValue(data.FindString(kValueField));
if (string_name == kApiTypeField) {
+#if 0
PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
- PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
+ PrefService* pref = static_cast<electron::ElectronBrowserContext*>(
+ web_ui()->GetWebContents()->GetBrowserContext())->prefs();
pref->SetString(prefs::kShownAccessibilityApiType, value);
+#endif
}
}
@@ -700,9 +709,13 @@ void AccessibilityUIMessageHandler::RequestWebContentsTree(
@@ -700,7 +702,8 @@ void AccessibilityUIMessageHandler::RequestWebContentsTree(
AXPropertyFilter::ALLOW_EMPTY);
AddPropertyFilters(property_filters, deny, AXPropertyFilter::DENY);
+#if 0
PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
- PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
+ PrefService* pref = static_cast<electron::ElectronBrowserContext*>(
+ web_contents->GetBrowserContext())->prefs();
ui::AXApiType::Type api_type =
ui::AXApiType::From(pref->GetString(prefs::kShownAccessibilityApiType));
+#else
+ ui::AXApiType::Type api_type = ui::AXApiType::kBlink;
+#endif
std::string accessibility_contents =
web_contents->DumpAccessibilityTree(api_type, property_filters);
result.Set(kTreeField, accessibility_contents);
@@ -727,6 +740,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
@@ -727,6 +730,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
AXPropertyFilter::ALLOW_EMPTY);
AddPropertyFilters(property_filters, deny, AXPropertyFilter::DENY);
@ -117,7 +90,7 @@ index 45b085ebb5096b2cdd083337371539a249c7a0a8..404a0a8d99eb68a35c0c06fe1b1dbfa3
for (Browser* browser : *BrowserList::GetInstance()) {
if (browser->session_id().id() == session_id) {
base::Value::Dict result = BuildTargetDescriptor(browser);
@@ -739,6 +753,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
@@ -739,6 +743,7 @@ void AccessibilityUIMessageHandler::RequestNativeUITree(
return;
}
}
@ -125,25 +98,24 @@ index 45b085ebb5096b2cdd083337371539a249c7a0a8..404a0a8d99eb68a35c0c06fe1b1dbfa3
#endif // !BUILDFLAG(IS_ANDROID)
// No browser with the specified |session_id| was found.
base::Value::Dict result;
@@ -807,11 +822,15 @@ void AccessibilityUIMessageHandler::StopRecording(
@@ -807,11 +812,13 @@ void AccessibilityUIMessageHandler::StopRecording(
}
ui::AXApiType::Type AccessibilityUIMessageHandler::GetRecordingApiType() {
+#if 0
PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
- PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
- const std::vector<ui::AXApiType::Type> supported_types =
- content::AXInspectFactory::SupportedApis();
+ PrefService* pref = static_cast<electron::ElectronBrowserContext*>(
+ web_ui()->GetWebContents()->GetBrowserContext())->prefs();
ui::AXApiType::Type api_type =
ui::AXApiType::From(pref->GetString(prefs::kShownAccessibilityApiType));
+#else
+ ui::AXApiType::Type api_type = ui::AXApiType::kBlink;
+#endif
+
+ const std::vector<ui::AXApiType::Type> supported_types =
+ content::AXInspectFactory::SupportedApis();
// Check to see if it is in the supported types list.
if (std::find(supported_types.begin(), supported_types.end(), api_type) ==
supported_types.end()) {
@@ -881,8 +900,11 @@ void AccessibilityUIMessageHandler::RequestAccessibilityEvents(
@@ -881,8 +888,11 @@ void AccessibilityUIMessageHandler::RequestAccessibilityEvents(
// static
void AccessibilityUIMessageHandler::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {

View file

@ -50,6 +50,7 @@
#include "shell/browser/protocol_registry.h"
#include "shell/browser/special_storage_policy.h"
#include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/webui/accessibility_ui.h"
#include "shell/browser/web_contents_permission_helper.h"
#include "shell/browser/web_view_manager.h"
#include "shell/browser/zoom_level_delegate.h"
@ -352,6 +353,7 @@ void ElectronBrowserContext::InitPrefs() {
MediaDeviceIDSalt::RegisterPrefs(registry.get());
ZoomLevelDelegate::RegisterPrefs(registry.get());
PrefProxyConfigTrackerImpl::RegisterPrefs(registry.get());
ElectronAccessibilityUIMessageHandler::RegisterPrefs(registry.get());
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
if (!in_memory_)
extensions::ExtensionPrefs::RegisterProfilePrefs(registry.get());

View file

@ -20,11 +20,11 @@
#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/resource_context.h"
#include "electron/buildflags/buildflags.h"
#include "electron/shell/browser/media/media_device_id_salt.h"
#include "gin/arguments.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "shell/browser/media/media_device_id_salt.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
class PrefService;

View file

@ -19,7 +19,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/accessibility_resources.h" // nogncheck
@ -40,11 +39,17 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_ui_data_source.h"
#include "shell/browser/electron_browser_context.h"
#include "shell/browser/native_window.h"
#include "shell/browser/window_list.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/accessibility/widget_ax_tree_id_map.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace {
@ -57,26 +62,34 @@ static const char kFaviconUrlField[] = "faviconUrl";
static const char kNameField[] = "name";
static const char kPagesField[] = "pages";
static const char kPidField[] = "pid";
static const char kSessionIdField[] = "sessionId";
static const char kProcessIdField[] = "processId";
static const char kRequestTypeField[] = "requestType";
static const char kRoutingIdField[] = "routingId";
static const char kSessionIdField[] = "sessionId";
static const char kSupportedApiTypesField[] = "supportedApiTypes";
static const char kTreeField[] = "tree";
static const char kTypeField[] = "type";
static const char kUrlField[] = "url";
static const char kTreeField[] = "tree";
static const char kWidgetsField[] = "widgets";
static const char kApiTypeField[] = "apiType";
#if defined(USE_AURA)
static const char kWidgetIdField[] = "widgetId";
static const char kWidget[] = "widget";
#endif
// Global flags
static const char kBrowser[] = "browser";
static const char kCopyTree[] = "copyTree";
static const char kHTML[] = "html";
static const char kInternal[] = "internal";
static const char kLabelImages[] = "labelImages";
static const char kLocked[] = "locked";
static const char kNative[] = "native";
static const char kPage[] = "page";
static const char kPDF[] = "pdf";
static const char kPDFPrinting[] = "pdfPrinting";
static const char kScreenReader[] = "screenreader";
static const char kShowOrRefreshTree[] = "showOrRefreshTree";
static const char kText[] = "text";
static const char kViewsAccessibility[] = "viewsAccessibility";
static const char kWeb[] = "web";
// Possible global flag values
@ -141,75 +154,23 @@ base::Value::Dict BuildTargetDescriptor(electron::NativeWindow* window) {
return target_data;
}
#if defined(USE_AURA)
base::Value::Dict BuildTargetDescriptor(views::Widget* widget) {
base::Value::Dict widget_data;
widget_data.Set(kNameField, widget->widget_delegate()->GetWindowTitle());
widget_data.Set(kTypeField, kWidget);
// Use the Widget's root view ViewAccessibility's unique ID for lookup.
int id = widget->GetRootView()->GetViewAccessibility().GetUniqueId().Get();
widget_data.Set(kWidgetIdField, id);
return widget_data;
}
#endif // defined(USE_AURA)
bool ShouldHandleAccessibilityRequestCallback(const std::string& path) {
return path == kTargetsDataFile;
}
// Add property filters to the property_filters vector for the given property
// filter type. The attributes are passed in as a string with each attribute
// separated by a space.
void AddPropertyFilters(std::vector<ui::AXPropertyFilter>* property_filters,
const std::string& attributes,
ui::AXPropertyFilter::Type type) {
for (const std::string& attribute : base::SplitString(
attributes, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
property_filters->emplace_back(attribute, type);
}
}
bool MatchesPropertyFilters(
const std::vector<ui::AXPropertyFilter>& property_filters,
const std::string& text) {
bool allow = false;
for (const auto& filter : property_filters) {
if (base::MatchPattern(text, filter.match_str)) {
switch (filter.type) {
case ui::AXPropertyFilter::ALLOW_EMPTY:
case ui::AXPropertyFilter::SCRIPT:
allow = true;
break;
case ui::AXPropertyFilter::ALLOW:
allow = (!base::MatchPattern(text, "*=''"));
break;
case ui::AXPropertyFilter::DENY:
allow = false;
break;
}
}
}
return allow;
}
std::string RecursiveDumpAXPlatformNodeAsString(
const ui::AXPlatformNode* node,
int indent,
const std::vector<ui::AXPropertyFilter>& property_filters) {
if (!node)
return "";
std::string str(2 * indent, '+');
const std::string line = node->GetDelegate()->GetData().ToString();
const std::vector<std::string> attributes = base::SplitString(
line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (const std::string& attribute : attributes) {
if (MatchesPropertyFilters(property_filters, attribute)) {
str += attribute + " ";
}
}
str += "\n";
for (size_t i = 0; i < node->GetDelegate()->GetChildCount(); i++) {
gfx::NativeViewAccessible child = node->GetDelegate()->ChildAtIndex(i);
const ui::AXPlatformNode* child_node =
ui::AXPlatformNode::FromNativeViewAccessible(child);
str += RecursiveDumpAXPlatformNodeAsString(child_node, indent + 1,
property_filters);
}
return str;
}
bool IsValidJSValue(const std::string* str) {
return str && str->length() < 5000U;
}
void HandleAccessibilityRequestCallback(
content::BrowserContext* current_context,
const std::string& path,
@ -217,6 +178,8 @@ void HandleAccessibilityRequestCallback(
DCHECK(ShouldHandleAccessibilityRequestCallback(path));
base::Value::Dict data;
PrefService* pref =
static_cast<electron::ElectronBrowserContext*>(current_context)->prefs();
ui::AXMode mode =
content::BrowserAccessibilityState::GetInstance()->GetAccessibilityMode();
bool is_native_enabled = content::BrowserAccessibilityState::GetInstance()
@ -226,7 +189,7 @@ void HandleAccessibilityRequestCallback(
bool text = mode.has_mode(ui::AXMode::kInlineTextBoxes);
bool screenreader = mode.has_mode(ui::AXMode::kScreenReader);
bool html = mode.has_mode(ui::AXMode::kHTML);
bool pdf = mode.has_mode(ui::AXMode::kPDFPrinting);
bool pdf_printing = mode.has_mode(ui::AXMode::kPDFPrinting);
// The "native" and "web" flags are disabled if
// --disable-renderer-accessibility is set.
@ -241,73 +204,161 @@ void HandleAccessibilityRequestCallback(
is_web_enabled ? (screenreader ? kOn : kOff) : kDisabled);
data.Set(kHTML, is_web_enabled ? (html ? kOn : kOff) : kDisabled);
// TODO(codebytere): enable use of this flag.
//
// The "labelImages" flag works only if "web" is enabled, the current profile
// has the kAccessibilityImageLabelsEnabled preference set and the appropriate
// command line switch has been used. Since this is so closely tied into user
// prefs and causes bugs, we're disabling it for now.
bool are_accessibility_image_labels_enabled = is_web_enabled;
data.Set(kLabelImages, kDisabled);
// The "pdfPrinting" flag is independent of the others.
data.Set(kPDFPrinting, pdf_printing ? kOn : kOff);
// The "pdf" flag is independent of the others.
data.Set(kPDF, pdf ? kOn : kOff);
// The "Top Level Widgets" section is only relevant if views accessibility is
// enabled.
data.Set(kViewsAccessibility, features::IsAccessibilityTreeForViewsEnabled());
// Always dump the Accessibility tree.
data.Set(kInternal, kOn);
std::string pref_api_type =
std::string(pref->GetString(prefs::kShownAccessibilityApiType));
bool pref_api_type_supported = false;
base::Value::List rvh_list;
std::unique_ptr<content::RenderWidgetHostIterator> widgets(
std::vector<ui::AXApiType::Type> supported_api_types =
content::AXInspectFactory::SupportedApis();
base::Value::List supported_api_list;
supported_api_list.reserve(supported_api_types.size());
for (ui::AXApiType::Type type : supported_api_types) {
supported_api_list.Append(std::string_view(type));
if (type == ui::AXApiType::From(pref_api_type)) {
pref_api_type_supported = true;
}
}
data.Set(kSupportedApiTypesField, std::move(supported_api_list));
// If the saved API type is not supported, use the default platform formatter
// API type.
if (!pref_api_type_supported) {
pref_api_type = std::string_view(
content::AXInspectFactory::DefaultPlatformFormatterType());
}
data.Set(kApiTypeField, pref_api_type);
bool is_mode_locked = !content::BrowserAccessibilityState::GetInstance()
->IsAXModeChangeAllowed();
data.Set(kLocked, is_mode_locked ? kOn : kOff);
base::Value::List page_list;
std::unique_ptr<content::RenderWidgetHostIterator> widget_iter(
content::RenderWidgetHost::GetRenderWidgetHosts());
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
while (content::RenderWidgetHost* widget = widget_iter->GetNextHost()) {
// Ignore processes that don't have a connection, such as crashed tabs.
if (!widget->GetProcess()->IsInitializedAndNotDead())
if (!widget->GetProcess()->IsInitializedAndNotDead()) {
continue;
}
content::RenderViewHost* rvh = content::RenderViewHost::From(widget);
if (!rvh)
if (!rvh) {
continue;
}
content::WebContents* web_contents =
content::WebContents::FromRenderViewHost(rvh);
content::WebContentsDelegate* delegate = web_contents->GetDelegate();
if (!delegate)
if (!delegate) {
continue;
}
if (web_contents->GetPrimaryMainFrame()->GetRenderViewHost() != rvh) {
continue;
}
// Ignore views that are never user-visible, like background pages.
if (delegate->IsNeverComposited(web_contents))
if (delegate->IsNeverComposited(web_contents)) {
continue;
}
content::BrowserContext* context = rvh->GetProcess()->GetBrowserContext();
if (context != current_context)
if (context != current_context) {
continue;
}
base::Value::Dict descriptor = BuildTargetDescriptor(rvh);
descriptor.Set(kNative, is_native_enabled);
descriptor.Set(kScreenReader, is_web_enabled && screenreader);
descriptor.Set(kWeb, is_web_enabled);
descriptor.Set(kLabelImages, are_accessibility_image_labels_enabled);
rvh_list.Append(std::move(descriptor));
page_list.Append(std::move(descriptor));
}
data.Set(kPagesField, std::move(rvh_list));
data.Set(kPagesField, std::move(page_list));
base::Value::List window_list;
for (auto* window : electron::WindowList::GetWindows()) {
window_list.Append(BuildTargetDescriptor(window));
}
data.Set(kBrowsersField, std::move(window_list));
base::Value::List widgets_list;
#if defined(USE_AURA)
if (features::IsAccessibilityTreeForViewsEnabled()) {
views::WidgetAXTreeIDMap& manager_map =
views::WidgetAXTreeIDMap::GetInstance();
const std::vector<views::Widget*> widgets = manager_map.GetWidgets();
for (views::Widget* widget : widgets) {
widgets_list.Append(BuildTargetDescriptor(widget));
}
}
#endif // defined(USE_AURA)
data.Set(kWidgetsField, std::move(widgets_list));
std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>(
base::WriteJson(data).value_or("")));
}
std::string RecursiveDumpAXPlatformNodeAsString(
ui::AXPlatformNode* node,
int indent,
const std::vector<ui::AXPropertyFilter>& property_filters) {
if (!node) {
return "";
}
std::string str(2 * indent, '+');
std::string line = node->GetDelegate()->GetData().ToString();
std::vector<std::string> attributes = base::SplitString(
line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (std::string attribute : attributes) {
if (ui::AXTreeFormatter::MatchesPropertyFilters(property_filters, attribute,
false)) {
str += attribute + " ";
}
}
str += "\n";
for (size_t i = 0; i < node->GetDelegate()->GetChildCount(); i++) {
gfx::NativeViewAccessible child = node->GetDelegate()->ChildAtIndex(i);
ui::AXPlatformNode* child_node =
ui::AXPlatformNode::FromNativeViewAccessible(child);
str += RecursiveDumpAXPlatformNodeAsString(child_node, indent + 1,
property_filters);
}
return str;
}
// Add property filters to the property_filters vector for the given property
// filter type. The attributes are passed in as a string with each attribute
// separated by a space.
void AddPropertyFilters(std::vector<ui::AXPropertyFilter>& property_filters,
const std::string& attributes,
ui::AXPropertyFilter::Type type) {
for (const std::string& attribute : base::SplitString(
attributes, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
property_filters.emplace_back(attribute, type);
}
}
bool IsValidJSValue(const std::string* str) {
return str && str->length() < 5000U;
}
const std::string& CheckJSValue(const std::string* str) {
CHECK(IsValidJSValue(str));
return *str;
}
} // namespace
ElectronAccessibilityUI::ElectronAccessibilityUI(content::WebUI* web_ui)
: content::WebUIController(web_ui) {
auto* const browser_context = web_ui->GetWebContents()->GetBrowserContext();
// Set up the chrome://accessibility source.
content::WebUIDataSource* html_source =
content::WebUIDataSource::CreateAndAdd(
web_ui->GetWebContents()->GetBrowserContext(),
chrome::kChromeUIAccessibilityHost);
browser_context, chrome::kChromeUIAccessibilityHost);
// Add required resources.
html_source->UseStringsJs();
@ -317,8 +368,7 @@ ElectronAccessibilityUI::ElectronAccessibilityUI(content::WebUI* web_ui)
html_source->SetRequestFilter(
base::BindRepeating(&ShouldHandleAccessibilityRequestCallback),
base::BindRepeating(&HandleAccessibilityRequestCallback,
web_ui->GetWebContents()->GetBrowserContext()));
browser_context));
html_source->OverrideContentSecurityPolicy(
network::mojom::CSPDirectiveName::TrustedTypes,
"trusted-types parse-html-subset sanitize-inner-html;");
@ -332,33 +382,35 @@ ElectronAccessibilityUI::~ElectronAccessibilityUI() = default;
ElectronAccessibilityUIMessageHandler::ElectronAccessibilityUIMessageHandler() =
default;
void ElectronAccessibilityUIMessageHandler::GetRequestTypeAndFilters(
const base::Value::Dict& data,
std::string& request_type,
std::string& allow,
std::string& allow_empty,
std::string& deny) {
request_type = CheckJSValue(data.FindString(kRequestTypeField));
CHECK(request_type == kShowOrRefreshTree || request_type == kCopyTree);
allow = CheckJSValue(data.FindStringByDottedPath("filters.allow"));
allow_empty = CheckJSValue(data.FindStringByDottedPath("filters.allowEmpty"));
deny = CheckJSValue(data.FindStringByDottedPath("filters.deny"));
}
void ElectronAccessibilityUIMessageHandler::RequestNativeUITree(
const base::Value::List& args) {
const base::Value::Dict& data = args.front().GetDict();
const int window_id = *data.FindInt(kSessionIdField);
const std::string* const request_type_p = data.FindString(kRequestTypeField);
CHECK(IsValidJSValue(request_type_p));
std::string request_type = *request_type_p;
CHECK(request_type == kShowOrRefreshTree || request_type == kCopyTree);
request_type = "accessibility." + request_type;
std::string request_type, allow, allow_empty, deny;
GetRequestTypeAndFilters(data, request_type, allow, allow_empty, deny);
const std::string* const allow_p =
data.FindStringByDottedPath("filters.allow");
CHECK(IsValidJSValue(allow_p));
const std::string* const allow_empty_p =
data.FindStringByDottedPath("filters.allowEmpty");
CHECK(IsValidJSValue(allow_empty_p));
const std::string* const deny_p = data.FindStringByDottedPath("filters.deny");
CHECK(IsValidJSValue(deny_p));
int window_id = *data.FindInt(kSessionIdField);
AllowJavascript();
std::vector<ui::AXPropertyFilter> property_filters;
AddPropertyFilters(&property_filters, *allow_p, ui::AXPropertyFilter::ALLOW);
AddPropertyFilters(&property_filters, *allow_empty_p,
AddPropertyFilters(property_filters, allow, ui::AXPropertyFilter::ALLOW);
AddPropertyFilters(property_filters, allow_empty,
ui::AXPropertyFilter::ALLOW_EMPTY);
AddPropertyFilters(&property_filters, *deny_p, ui::AXPropertyFilter::DENY);
AddPropertyFilters(property_filters, deny, ui::AXPropertyFilter::DENY);
for (auto* window : electron::WindowList::GetWindows()) {
if (window->window_id() == window_id) {
@ -366,9 +418,9 @@ void ElectronAccessibilityUIMessageHandler::RequestNativeUITree(
gfx::NativeWindow native_window = window->GetNativeWindow();
ui::AXPlatformNode* node =
ui::AXPlatformNode::FromNativeWindow(native_window);
result.Set(kTreeField, base::Value(RecursiveDumpAXPlatformNodeAsString(
node, 0, property_filters)));
CallJavascriptFunction(request_type, base::Value(std::move(result)));
result.Set(kTreeField, RecursiveDumpAXPlatformNodeAsString(
node, 0, property_filters));
FireWebUIListener(request_type, result);
return;
}
}
@ -378,7 +430,7 @@ void ElectronAccessibilityUIMessageHandler::RequestNativeUITree(
result.Set(kSessionIdField, window_id);
result.Set(kTypeField, kBrowser);
result.Set(kErrorField, "Window no longer exists.");
CallJavascriptFunction(request_type, base::Value(std::move(result)));
FireWebUIListener(request_type, result);
}
void ElectronAccessibilityUIMessageHandler::RegisterMessages() {
@ -393,6 +445,10 @@ void ElectronAccessibilityUIMessageHandler::RegisterMessages() {
"setGlobalFlag",
base::BindRepeating(&AccessibilityUIMessageHandler::SetGlobalFlag,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"setGlobalString",
base::BindRepeating(&AccessibilityUIMessageHandler::SetGlobalString,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"requestWebContentsTree",
base::BindRepeating(
@ -403,9 +459,24 @@ void ElectronAccessibilityUIMessageHandler::RegisterMessages() {
base::BindRepeating(
&ElectronAccessibilityUIMessageHandler::RequestNativeUITree,
base::Unretained(this)));
#if defined(USE_AURA)
web_ui()->RegisterMessageCallback(
"requestWidgetsTree",
base::BindRepeating(&AccessibilityUIMessageHandler::RequestWidgetsTree,
base::Unretained(this)));
#endif
web_ui()->RegisterMessageCallback(
"requestAccessibilityEvents",
base::BindRepeating(
&AccessibilityUIMessageHandler::RequestAccessibilityEvents,
base::Unretained(this)));
}
// static
void ElectronAccessibilityUIMessageHandler::RegisterPrefs(
user_prefs::PrefRegistrySyncable* registry) {
const std::string_view default_api_type =
std::string_view(ui::AXApiType::Type(ui::AXApiType::kBlink));
registry->RegisterStringPref(prefs::kShownAccessibilityApiType,
std::string(default_api_type));
}

View file

@ -31,7 +31,14 @@ class ElectronAccessibilityUIMessageHandler
void RegisterMessages() final;
static void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry);
private:
void GetRequestTypeAndFilters(const base::Value::Dict& data,
std::string& request_type,
std::string& allow,
std::string& allow_empty,
std::string& deny);
void RequestNativeUITree(const base::Value::List& args);
};