// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/accessibility/service/automation_client_impl.h"
#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
#include "extensions/browser/api/automation_internal/automation_event_router.h"
#include "extensions/browser/api/automation_internal/automation_internal_api.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
namespace ash {
AutomationClientImpl::AutomationClientImpl() = default;
AutomationClientImpl::~AutomationClientImpl() {
if (!bound_)
return;
extensions::AutomationEventRouter::GetInstance()->RegisterRemoteRouter(
nullptr);
}
void AutomationClientImpl::BindAutomation(
mojo::PendingAssociatedRemote<ax::mojom::Automation> automation) {
// Launches the service if it wasn't running yet.
// Development note (crbug.com/1355633): Using the remote router means
// extensions don't get a11y events when AutomationClientImpl is bound, so
// accessibility features built as component extensions are broken when the
// service is running.
if (!bound_) {
bound_ = true;
extensions::AutomationEventRouter::GetInstance()->RegisterRemoteRouter(
this);
}
automation_remotes_.Add(std::move(automation));
}
void AutomationClientImpl::BindAutomationClient(
mojo::PendingReceiver<ax::mojom::AutomationClient> automation_client) {
automation_client_receivers_.Add(this, std::move(automation_client));
}
void AutomationClientImpl::DispatchAccessibilityEvents(
const ui::AXTreeID& tree_id,
const std::vector<ui::AXTreeUpdate>& updates,
const gfx::Point& mouse_location,
const std::vector<ui::AXEvent>& events) {
DCHECK(tree_id != ui::AXTreeIDUnknown());
if (tree_id == ui::AXTreeIDUnknown())
return;
for (auto& remote : automation_remotes_) {
remote->DispatchAccessibilityEvents(tree_id, updates, mouse_location,
events);
}
}
void AutomationClientImpl::DispatchAccessibilityLocationChange(
const ui::AXLocationChanges& details) {
ui::AXTreeID tree_id = details.ax_tree_id;
if (tree_id == ui::AXTreeIDUnknown())
return;
for (auto& remote : automation_remotes_) {
remote->DispatchAccessibilityLocationChange(tree_id, details.id,
details.new_location);
}
}
void AutomationClientImpl::DispatchTreeDestroyedEvent(ui::AXTreeID tree_id) {
if (tree_id == ui::AXTreeIDUnknown())
return;
// TODO(crbug.com/1355633): Send to AccessibilityService.
// for (auto& remote : automation_remotes_) {
// remote->DispatchTreeDestroyedEvent(tree_id);
// }
}
void AutomationClientImpl::DispatchActionResult(
const ui::AXActionData& data,
bool result,
content::BrowserContext* browser_context) {
// TODO(crbug.com/1355633): Send to AccessibilityService.
// for (auto& remote : automation_remotes_) {
// remote->DispatchActionResult(data, result);
// }
}
void AutomationClientImpl::DispatchGetTextLocationDataResult(
const ui::AXActionData& data,
const std::optional<gfx::Rect>& rect) {
// TODO(crbug.com/1355633): Send to AccessibilityService.
// for (auto& remote : automation_remotes_) {
// remote->DispatchGetTextLocationDataResult(data, rect);
// }
}
void AutomationClientImpl::Enable(EnableCallback callback) {
// Enable automation for all of Desktop.
AutomationManagerAura::GetInstance()->Enable();
std::move(callback).Run(AutomationManagerAura::GetInstance()->ax_tree_id());
}
void AutomationClientImpl::Disable() {
// Disable automation.
AutomationManagerAura::GetInstance()->Disable();
}
void AutomationClientImpl::EnableChildTree(const ui::AXTreeID& tree_id) {
// TODO(crbug.com/1355633): Refactor logic from extensions namespace to a
// common location.
extensions::AutomationInternalEnableTreeFunction::EnableTree(
tree_id, /*extension_id=*/"");
}
void AutomationClientImpl::PerformAction(const ui::AXActionData& data) {
// TODO(crbug.com/1355633): Refactor logic from extensions namespace to a
// common location.
extensions::AutomationInternalPerformActionFunction::PerformAction(
data, /*extension=*/nullptr, /*automation_info=*/nullptr);
}
} // namespace ash