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
172
173
174
175
176
177
178
179
180
|
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FUCHSIA_ENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_
#define FUCHSIA_ENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_
#include <fuchsia/accessibility/semantics/cpp/fidl.h>
#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <base/containers/flat_map.h>
#include "base/callback.h"
#include "base/macros.h"
#include "base/optional.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "fuchsia/engine/browser/ax_tree_converter.h"
#include "fuchsia/engine/web_engine_export.h"
#include "ui/accessibility/ax_serializable_tree.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/ax_tree_observer.h"
namespace content {
class WebContents;
} // namespace content
// This class is the intermediate for accessibility between Chrome and Fuchsia.
// It handles registration to the Fuchsia Semantics Manager, translating events
// and data structures between the two services, and forwarding actions and
// events.
// The lifetime of an instance of AccessibilityBridge is the same as that of a
// View created by FrameImpl. This class refers to the View via the
// caller-supplied ViewRef.
// If |semantic_tree_| gets disconnected, it will cause the FrameImpl that owns
// |this| to close, which will also destroy |this|.
class WEB_ENGINE_EXPORT AccessibilityBridge
: public content::WebContentsObserver,
public fuchsia::accessibility::semantics::SemanticListener,
public ui::AXTreeObserver {
public:
// |semantics_manager| is used during construction to register the instance.
// |web_contents| is required to exist for the duration of |this|.
AccessibilityBridge(
fuchsia::accessibility::semantics::SemanticsManager* semantics_manager,
fuchsia::ui::views::ViewRef view_ref,
content::WebContents* web_contents,
base::OnceCallback<void(zx_status_t)> on_error_callback);
~AccessibilityBridge() final;
AccessibilityBridge(const AccessibilityBridge&) = delete;
AccessibilityBridge& operator=(const AccessibilityBridge&) = delete;
const ui::AXSerializableTree* ax_tree_for_test();
void set_event_received_callback_for_test(base::OnceClosure callback) {
event_received_callback_for_test_ = std::move(callback);
}
void set_device_scale_factor_for_test(float device_scale_factor) {
device_scale_factor_override_for_test_ = device_scale_factor;
}
private:
FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest, OnSemanticsModeChanged);
FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest,
TreeModificationsAreForwarded);
// Represents a connection between two AXTrees that are in different frames.
struct TreeConnection {
// ID of the node in the parent tree that points to this tree.
int32_t parent_node_id = 0;
// ID of the parent tree.
ui::AXTreeID parent_tree_id = ui::AXTreeIDUnknown();
// Whether the trees are connected.
bool is_connected = false;
};
// Processes pending data and commits it to the Semantic Tree.
void TryCommit();
// Connects trees if they are present or deletes the connection if both are
// gone.
void UpdateTreeConnections();
// Returns true if the main frame AXTree is not present or if trees are not
// connected.
bool ShouldHoldCommit();
// The AXTreeID of a tree can change. Updates all internal references of an
// AXTreeID by fetching the RenderFrameHost associated with |tree_id| and
// updates the value if it is different from the previously used AXTreeID.
// Returns false if the frame does not exist anymore, true otherwise.
bool UpdateAXTreeID(const ui::AXTreeID& tree_id);
// If |tree| is connected to another tree as its child, mark them as
// disconnected.
void MaybeDisconnectTreeFromParentTree(ui::AXTree* tree);
// Callback for SemanticTree::CommitUpdates.
void OnCommitComplete();
// Interrupts actions that are waiting for a response. This is invoked during
// destruction time or when semantic updates have been disabled.
void InterruptPendingActions();
// Accessor for the device scale factor that allows for overriding the value
// in tests.
float GetDeviceScaleFactor();
// content::WebContentsObserver implementation.
void AccessibilityEventReceived(
const content::AXEventNotificationDetails& details) override;
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
// fuchsia::accessibility::semantics::SemanticListener implementation.
void OnAccessibilityActionRequested(
uint32_t node_id,
fuchsia::accessibility::semantics::Action action,
OnAccessibilityActionRequestedCallback callback) final;
void HitTest(fuchsia::math::PointF local_point,
HitTestCallback callback) final;
void OnSemanticsModeChanged(bool updates_enabled,
OnSemanticsModeChangedCallback callback) final;
// ui::AXTreeObserver implementation.
void OnNodeDeleted(ui::AXTree* tree, int32_t node_id) override;
void OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
const std::vector<ui::AXTreeObserver::Change>& changes) override;
fuchsia::accessibility::semantics::SemanticTreePtr semantic_tree_;
fidl::Binding<fuchsia::accessibility::semantics::SemanticListener> binding_;
content::WebContents* web_contents_;
// Holds one semantic tree per iframe.
base::flat_map<ui::AXTreeID, std::unique_ptr<ui::AXSerializableTree>>
ax_trees_;
// Maps frames to AXTrees.
base::flat_map<content::GlobalFrameRoutingId, ui::AXTreeID>
frame_id_to_tree_id_;
// Keeps track of semantic trees connections.
// The key is the AXTreeID of the semantic tree that is connected to another
// tree.
base::flat_map<ui::AXTreeID, TreeConnection> tree_connections_;
// Whether semantic updates are enabled.
bool enable_semantic_updates_ = false;
// Cache for pending data to be sent to the Semantic Tree between commits.
std::vector<uint32_t> to_delete_;
std::vector<fuchsia::accessibility::semantics::Node> to_update_;
bool commit_inflight_ = false;
// Maintain a map of callbacks as multiple hit test events can happen at
// once. These are keyed by the request_id field of ui::AXActionData.
base::flat_map<int, HitTestCallback> pending_hit_test_callbacks_;
// Run in the case of an internal error that cannot be recovered from. This
// will cause the frame |this| is owned by to be torn down.
base::OnceCallback<void(zx_status_t)> on_error_callback_;
// The root id of the AXTree of the main frame.
int32_t root_id_ = 0;
// Maps node IDs from one platform to another.
std::unique_ptr<NodeIDMapper> id_mapper_;
base::OnceClosure event_received_callback_for_test_;
// If set, the scale factor for this device for use in tests.
base::Optional<float> device_scale_factor_override_for_test_;
};
#endif // FUCHSIA_ENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_
|