File: semantic_provider_impl.h

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 (212 lines) | stat: -rw-r--r-- 8,275 bytes parent folder | download | duplicates (5)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_ACCESSIBILITY_PLATFORM_FUCHSIA_SEMANTIC_PROVIDER_IMPL_H_
#define UI_ACCESSIBILITY_PLATFORM_FUCHSIA_SEMANTIC_PROVIDER_IMPL_H_

#include <fidl/fuchsia.accessibility.semantics/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>

#include <map>
#include <optional>
#include <set>
#include <vector>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "ui/accessibility/platform/fuchsia/semantic_provider.h"

namespace ui {

namespace {

class SemanticTreeEventHandler
    : public fidl::AsyncEventHandler<
          fuchsia_accessibility_semantics::SemanticTree> {
 public:
  explicit SemanticTreeEventHandler(
      base::OnceCallback<void(fidl::UnbindInfo)> on_fidl_error_callback);
  ~SemanticTreeEventHandler() override;

  void on_fidl_error(fidl::UnbindInfo error) override;

 private:
  base::OnceCallback<void(fidl::UnbindInfo)> on_fidl_error_callback_;
};

}  // namespace

// Clients instantiate this class, which connects to the Fuchsia semantics API.
// This object must remain alive across the entire lifespan of the corresponding
// fuchsia view.
class COMPONENT_EXPORT(AX_PLATFORM) AXFuchsiaSemanticProviderImpl
    : public AXFuchsiaSemanticProvider,
      public fidl::Server<fuchsia_accessibility_semantics::SemanticListener> {
 public:
  // Arguments:
  // |view_ref|: identifies the view providing semantics. Please consult
  // |fuchsia.accessibility.semantics| API documentation.
  // |delegate|: Handles semantic requests, please see Delegate class for more
  // documentation. Caller is responsible for ensuring that |delegate| outlives
  // |this|.
  // During construction, this class connects to
  // |fuchsia.accessibility.semantics.SemanticsManager| to register itself as a
  // semantic provider.
  AXFuchsiaSemanticProviderImpl(fuchsia_ui_views::ViewRef view_ref,
                                Delegate* delegate);
  ~AXFuchsiaSemanticProviderImpl() override;

  // Returns true if Fuchsia has enabled semantics.
  bool semantic_updates_enabled() const { return semantic_updates_enabled_; }

  // AXFuchsiaSemanticProvider overrides.
  bool Update(fuchsia_accessibility_semantics::Node node) override;
  bool Delete(uint32_t node_id) override;
  bool Clear() override;
  void SendEvent(fuchsia_accessibility_semantics::SemanticEvent event) override;
  bool HasPendingUpdates() const override;
  float GetPixelScale() const override;
  void SetPixelScale(float pixel_scale) override;

 private:
  // Holds information about a Fuchsia Semantic Node. It contains only the
  // fields needed to check that the resulting tree would be valid.
  struct NodeInfo {
    NodeInfo();
    ~NodeInfo();

    // During a tree update a node may have multiple parents pointing to it,
    // although after all updates are processed only one should be present.
    std::set<uint32_t> parents;
    std::vector<uint32_t> children;
  };

  // Represents a batch of nodes to be sent to Fuchsia.
  // Batches can hold exactly one type: a series of updates or a series of
  // deletions.
  class Batch {
   public:
    enum class Type { kUpdate, kDelete };

    Batch(Type type);
    Batch(Batch&& other);
    ~Batch();
    Batch(const Batch& other) = delete;

    Type type() const { return type_; }

    // Returns true if the batch has reached its size limit.
    bool IsFull() const;

    // Adds an update or deletion to the batch. This fails if the batch is full
    // or if the new item is not the same type of the batch.
    void Append(fuchsia_accessibility_semantics::Node node);
    void AppendDeletion(uint32_t delete_node_id);

    // Sends enqueued operations to SemanticsManager.
    void Apply(fidl::Client<fuchsia_accessibility_semantics::SemanticTree>*
                   semantic_tree);

   private:
    Type type_;
    std::vector<fuchsia_accessibility_semantics::Node> updates_;
    std::vector<uint32_t> delete_node_ids_;
  };

  // Attempts to commit the pending updates to Fuchsia if the resulting updates
  // would leave the final tree in a valid state.
  void TryToCommit();

  // Returns a batch that can receive an update or deletion depending on |type|.
  Batch& GetCurrentUnfilledBatch(Batch::Type type);

  // Invoked whenever Fuchsia responds that a commit was received. This tries to
  // commit again if there are pending upedates or deletions.
  void OnCommitComplete(
      fidl::Result<
          fuchsia_accessibility_semantics::SemanticTree::CommitUpdates>&
          result);

  // Mark all |child_ids| not reachable from |parent_id|, meaning:
  // - If |parent_id| was the only parent, the children are now disconnected
  // from the tree.
  // - If |parent_id| was an additional parent, now the children are connected
  // to a single parent in the tree.
  // - If the children do not exist, remove them from the list of nodes waiting
  // to be updated.
  void MarkChildrenAsNotReachable(const std::vector<uint32_t>& child_ids,
                                  uint32_t parent_id);

  // Mark all |child_ids| reachable from |parent_id|, meaning:
  // - If |parent_id| is the only parent, the children are now connected to the
  // tree and are all reachable.
  // - If |parent_id| is an additional parent, now the children are not
  // connected to the tree as multiple parents point to them.
  // - If the children do not exist, the parent waits for the nodes to be
  // created.
  void MarkChildrenAsReachable(const std::vector<uint32_t>& child_ids,
                               uint32_t parent_id);

  // Returns the ID of the parent of this node if it has one. If it does not
  // have a parent or it has multiple parents, returns std::nullopt.
  std::optional<uint32_t> GetParentForNode(const uint32_t node_id);

  // fuchsia_accessibility_semantics::SemanticListener:
  void OnAccessibilityActionRequested(
      OnAccessibilityActionRequestedRequest& request,
      OnAccessibilityActionRequestedCompleter::Sync& completer) override;

  // fuchsia_accessibility_semantics::SemanticListener:
  void HitTest(HitTestRequest& request,
               HitTestCompleter::Sync& completer) override;

  // fuchsia_accessibility_semantics::SemanticListener:
  void OnSemanticsModeChanged(
      OnSemanticsModeChangedRequest& request,
      OnSemanticsModeChangedCompleter::Sync& completer) override;

  const raw_ptr<Delegate> delegate_;

  std::optional<
      fidl::ServerBinding<fuchsia_accessibility_semantics::SemanticListener>>
      semantic_listener_binding_;

  fidl::Client<fuchsia_accessibility_semantics::SemanticTree> semantic_tree_;

  std::optional<SemanticTreeEventHandler> semantic_tree_event_handler_;

  bool semantic_updates_enabled_ = false;

  // Nodes from this tree. If not empty, to be considered a valid tree, there
  // must be:
  // - A node which node id is equal to kFuchsiaRootNodeId;
  // - Each node except the root has only one parent;
  // - All children pointed by a parent exist in the tree.
  // Only the node ID and the child IDs of the node are stored here because at
  // this point we only check to see if the tree is valid.
  std::map<uint32_t /*node_id*/, NodeInfo> nodes_;

  // Key == the node ID that is not reachable from the root of the tree, value
  // == 0 or more parents that point to this node. Note that nodes can be listed
  // here but still be present in |nodes_|. This may happen, for example, if the
  // parent of the node was deleted and there is no path from the root to it, so
  // the node waits for a parent to connect to it.
  std::map<uint32_t, std::set<uint32_t>> not_reachable_;

  // Stores batches of node updates or deletions to be sent to Fuchsia. Note
  // that a batch contains only updates or deletions, because they are pushed to
  // Fuchsia differently.
  std::vector<Batch> batches_;

  bool commit_inflight_ = false;

  // The scale factor used to convert between the coordinate space chrome
  // allocates for the view and the view's logical size reported by scenic.
  float pixel_scale_ = 1.f;
};

}  // namespace ui
#endif  // UI_ACCESSIBILITY_PLATFORM_FUCHSIA_SEMANTIC_PROVIDER_IMPL_H_