1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/accessibility/native_interface_accessibility_provider.h"
17
18 #include "base/log/log.h"
19
20 using namespace OHOS::Ace;
21 namespace {
22 constexpr int32_t SEND_EVENT_FAILED = -1;
23 constexpr int32_t SEND_EVENT_SUCCESS = 0;
24
CheckProviderCallback(ArkUI_AccessibilityProviderCallbacks * callbacks)25 bool CheckProviderCallback(ArkUI_AccessibilityProviderCallbacks* callbacks)
26 {
27 if (callbacks == nullptr) {
28 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "callbacks is null");
29 return false;
30 }
31
32 bool result = true;
33 if (callbacks->findAccessibilityNodeInfosById == nullptr) {
34 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosById is null");
35 result = false;
36 }
37
38 if (callbacks->findAccessibilityNodeInfosByText == nullptr) {
39 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosByText is null");
40 result = false;
41 }
42
43 if (callbacks->findFocusedAccessibilityNode == nullptr) {
44 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findFocusedAccessibilityNode is null");
45 result = false;
46 }
47
48 if (callbacks->findNextFocusAccessibilityNode == nullptr) {
49 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findNextFocusAccessibilityNode is null");
50 result = false;
51 }
52
53 if (callbacks->executeAccessibilityAction == nullptr) {
54 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "executeAccessibilityAction is null");
55 result = false;
56 }
57
58 if (callbacks->clearFocusedFocusAccessibilityNode == nullptr) {
59 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "clearFocusedFocusAccessibilityNode is null");
60 result = false;
61 }
62
63 if (callbacks->getAccessibilityNodeCursorPosition == nullptr) {
64 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "getAccessibilityNodeCursorPosition is null");
65 result = false;
66 }
67
68 return result;
69 }
CheckProviderCallbackWithInstance(ArkUI_AccessibilityProviderCallbacksWithInstance * callbacks)70 bool CheckProviderCallbackWithInstance(ArkUI_AccessibilityProviderCallbacksWithInstance* callbacks)
71 {
72 if (callbacks == nullptr) {
73 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "callbacks is null");
74 return false;
75 }
76
77 if (callbacks->findAccessibilityNodeInfosById == nullptr) {
78 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosById is null");
79 return false;
80 }
81
82 if (callbacks->findAccessibilityNodeInfosByText == nullptr) {
83 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosByText is null");
84 return false;
85 }
86
87 if (callbacks->findFocusedAccessibilityNode == nullptr) {
88 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findFocusedAccessibilityNode is null");
89 return false;
90 }
91
92 if (callbacks->findNextFocusAccessibilityNode == nullptr) {
93 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findNextFocusAccessibilityNode is null");
94 return false;
95 }
96
97 if (callbacks->executeAccessibilityAction == nullptr) {
98 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "executeAccessibilityAction is null");
99 return false;
100 }
101
102 if (callbacks->clearFocusedFocusAccessibilityNode == nullptr) {
103 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "clearFocusedFocusAccessibilityNode is null");
104 return false;
105 }
106
107 if (callbacks->getAccessibilityNodeCursorPosition == nullptr) {
108 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "getAccessibilityNodeCursorPosition is null");
109 return false;
110 }
111
112 return true;
113 }
114 }
AccessibilityProviderRegisterCallback(ArkUI_AccessibilityProviderCallbacks * callbacks)115 int32_t ArkUI_AccessibilityProvider::AccessibilityProviderRegisterCallback(
116 ArkUI_AccessibilityProviderCallbacks* callbacks)
117 {
118 if (!CheckProviderCallback(callbacks)) {
119 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "CheckProviderCallback failed.");
120 if (registerCallback_) {
121 registerCallback_(false);
122 }
123 return ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER;
124 }
125
126 accessibilityProviderCallbacks_ = *callbacks;
127 if (registerCallback_) {
128 registerCallback_(true);
129 }
130 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "AccessibilityProviderRegisterCallback success");
131 return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL;
132 }
133
AccessibilityProviderRegisterCallbackWithInstance(const char * instanceId,ArkUI_AccessibilityProviderCallbacksWithInstance * callbacks)134 int32_t ArkUI_AccessibilityProvider::AccessibilityProviderRegisterCallbackWithInstance(const char* instanceId,
135 ArkUI_AccessibilityProviderCallbacksWithInstance* callbacks)
136 {
137 if (!CheckProviderCallbackWithInstance(callbacks)) {
138 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "CheckProviderCallbackWithInstance failed.");
139 if (registerCallback_) {
140 registerCallback_(false);
141 }
142 return ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER;
143 }
144 accessibilityProviderCallbacksWithInstance_ = *callbacks;
145 if (registerCallback_) {
146 registerCallback_(true);
147 }
148 instanceId_ = instanceId;
149 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "AccessibilityProviderRegisterCallbackWithInstance success");
150 return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL;
151 }
152
FindAccessibilityNodeInfosById(const int64_t elementId,const int32_t mode,const int32_t requestId,std::vector<ArkUI_AccessibilityElementInfo> & infos)153 int32_t ArkUI_AccessibilityProvider::FindAccessibilityNodeInfosById(
154 const int64_t elementId, const int32_t mode, const int32_t requestId,
155 std::vector<ArkUI_AccessibilityElementInfo>& infos)
156 {
157 ArkUI_AccessibilityElementInfoList* accessibilityElementInfoList
158 = new (std::nothrow) ArkUI_AccessibilityElementInfoList();
159 if (accessibilityElementInfoList == nullptr) {
160 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "info list is null");
161 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
162 }
163 int32_t ret = 0;
164 if (accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById) {
165 ret = accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById(instanceId_.c_str(),
166 elementId, static_cast<ArkUI_AccessibilitySearchMode>(mode),
167 requestId, accessibilityElementInfoList);
168 } else if (accessibilityProviderCallbacks_.findAccessibilityNodeInfosById) {
169 ret = accessibilityProviderCallbacks_.findAccessibilityNodeInfosById(
170 elementId, static_cast<ArkUI_AccessibilitySearchMode>(mode),
171 requestId, accessibilityElementInfoList);
172 } else {
173 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosById is null");
174 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
175 }
176
177 if (!accessibilityElementInfoList->CopyAccessibilityElementInfo(infos)) {
178 ret = AccessibilityProviderOperatorErrorCode::COPY_FAILED;
179 }
180
181 delete accessibilityElementInfoList;
182 accessibilityElementInfoList = nullptr;
183 return ret;
184 }
185
FindAccessibilityNodeInfosByText(const int64_t elementId,std::string text,const int32_t requestId,std::vector<ArkUI_AccessibilityElementInfo> & infos)186 int32_t ArkUI_AccessibilityProvider::FindAccessibilityNodeInfosByText(
187 const int64_t elementId, std::string text, const int32_t requestId,
188 std::vector<ArkUI_AccessibilityElementInfo>& infos)
189 {
190 ArkUI_AccessibilityElementInfoList* accessibilityElementInfoList
191 = new (std::nothrow) ArkUI_AccessibilityElementInfoList();
192 if (accessibilityElementInfoList == nullptr) {
193 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "info list is null");
194 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
195 }
196 int32_t ret = 0;
197 if (accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosByText) {
198 ret = accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosByText(instanceId_.c_str(),
199 elementId, text.c_str(), requestId, accessibilityElementInfoList);
200 } else if (accessibilityProviderCallbacks_.findAccessibilityNodeInfosByText) {
201 ret = accessibilityProviderCallbacks_.findAccessibilityNodeInfosByText(
202 elementId, text.c_str(), requestId, accessibilityElementInfoList);
203 } else {
204 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findAccessibilityNodeInfosByText is null");
205 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
206 }
207
208 if (!accessibilityElementInfoList->CopyAccessibilityElementInfo(infos)) {
209 ret = AccessibilityProviderOperatorErrorCode::COPY_FAILED;
210 }
211
212 delete accessibilityElementInfoList;
213 accessibilityElementInfoList = nullptr;
214 return ret;
215 }
216
FindFocusedAccessibilityNode(const int64_t elementId,int32_t focusType,const int32_t requestId,ArkUI_AccessibilityElementInfo & elementInfo)217 int32_t ArkUI_AccessibilityProvider::FindFocusedAccessibilityNode(
218 const int64_t elementId, int32_t focusType, const int32_t requestId,
219 ArkUI_AccessibilityElementInfo& elementInfo)
220 {
221 if (accessibilityProviderCallbacksWithInstance_.findFocusedAccessibilityNode) {
222 return accessibilityProviderCallbacksWithInstance_.findFocusedAccessibilityNode(instanceId_.c_str(),
223 elementId, static_cast<ArkUI_AccessibilityFocusType>(focusType), requestId, &elementInfo);
224 } else if (accessibilityProviderCallbacks_.findFocusedAccessibilityNode) {
225 return accessibilityProviderCallbacks_.findFocusedAccessibilityNode(elementId,
226 static_cast<ArkUI_AccessibilityFocusType>(focusType), requestId, &elementInfo);
227 } else {
228 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findFocusedAccessibilityNode is null");
229 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
230 }
231 }
232
FindNextFocusAccessibilityNode(const int64_t elementId,int32_t direction,const int32_t requestId,ArkUI_AccessibilityElementInfo & elementInfo)233 int32_t ArkUI_AccessibilityProvider::FindNextFocusAccessibilityNode(
234 const int64_t elementId, int32_t direction, const int32_t requestId,
235 ArkUI_AccessibilityElementInfo& elementInfo)
236 {
237 if (accessibilityProviderCallbacksWithInstance_.findNextFocusAccessibilityNode) {
238 return accessibilityProviderCallbacksWithInstance_.findNextFocusAccessibilityNode(instanceId_.c_str(),
239 elementId, static_cast<ArkUI_AccessibilityFocusMoveDirection>(direction), requestId, &elementInfo);
240 } else if (accessibilityProviderCallbacks_.findNextFocusAccessibilityNode) {
241 return accessibilityProviderCallbacks_.findNextFocusAccessibilityNode(elementId,
242 static_cast<ArkUI_AccessibilityFocusMoveDirection>(direction), requestId, &elementInfo);
243 } else {
244 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "findNextFocusAccessibilityNode is null");
245 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
246 }
247 }
248
ExecuteAccessibilityAction(const int64_t elementId,int32_t action,const int32_t requestId,const std::map<std::string,std::string> & actionArguments)249 int32_t ArkUI_AccessibilityProvider::ExecuteAccessibilityAction(
250 const int64_t elementId, int32_t action, const int32_t requestId,
251 const std::map<std::string, std::string>& actionArguments)
252 {
253 if (accessibilityProviderCallbacksWithInstance_.executeAccessibilityAction) {
254 return accessibilityProviderCallbacksWithInstance_.executeAccessibilityAction(instanceId_.c_str(), elementId,
255 static_cast<ArkUI_Accessibility_ActionType>(action),
256 new ArkUI_AccessibilityActionArguments(actionArguments),
257 requestId);
258 } else if (accessibilityProviderCallbacks_.executeAccessibilityAction) {
259 return accessibilityProviderCallbacks_.executeAccessibilityAction(
260 elementId, static_cast<ArkUI_Accessibility_ActionType>(action),
261 new ArkUI_AccessibilityActionArguments(actionArguments), requestId);
262 } else {
263 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "executeAccessibilityAction is null");
264 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
265 }
266 }
267
ClearFocusedAccessibilityNode()268 int32_t ArkUI_AccessibilityProvider::ClearFocusedAccessibilityNode()
269 {
270 if (accessibilityProviderCallbacksWithInstance_.clearFocusedFocusAccessibilityNode) {
271 return accessibilityProviderCallbacksWithInstance_.clearFocusedFocusAccessibilityNode(instanceId_.c_str());
272 } else if (accessibilityProviderCallbacks_.clearFocusedFocusAccessibilityNode) {
273 return accessibilityProviderCallbacks_.clearFocusedFocusAccessibilityNode();
274 } else {
275 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "clearFocusedFocusAccessibilityNode is null");
276 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
277 }
278 }
279
GetAccessibilityNodeCursorPosition(const int64_t elementId,const int32_t requestId,int32_t & cursorPosition)280 int32_t ArkUI_AccessibilityProvider::GetAccessibilityNodeCursorPosition(
281 const int64_t elementId, const int32_t requestId, int32_t &cursorPosition)
282 {
283 if (accessibilityProviderCallbacksWithInstance_.getAccessibilityNodeCursorPosition) {
284 return accessibilityProviderCallbacksWithInstance_.getAccessibilityNodeCursorPosition(instanceId_.c_str(),
285 elementId, requestId, &cursorPosition);
286 } else if (accessibilityProviderCallbacks_.getAccessibilityNodeCursorPosition) {
287 return accessibilityProviderCallbacks_.getAccessibilityNodeCursorPosition(
288 elementId, requestId, &cursorPosition);
289 } else {
290 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "getAccessibilityNodeCursorPosition is null");
291 return AccessibilityProviderOperatorErrorCode::NOT_REGISTERED;
292 }
293 }
294
SendAccessibilityAsyncEvent(ArkUI_AccessibilityEventInfo * accessibilityEvent,void (* callback)(int32_t errorCode))295 int32_t ArkUI_AccessibilityProvider::SendAccessibilityAsyncEvent(
296 ArkUI_AccessibilityEventInfo* accessibilityEvent,
297 void (*callback)(int32_t errorCode))
298 {
299 if (accessibilityEvent == nullptr) {
300 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "accessibilityEvent is null");
301 if (callback) {
302 callback(SEND_EVENT_FAILED);
303 }
304 return SEND_EVENT_FAILED;
305 }
306
307 auto accessibilityProvider = accessibilityProvider_.Upgrade();
308 if (accessibilityProvider == nullptr) {
309 TAG_LOGW(AceLogTag::ACE_ACCESSIBILITY, "accessibilityProvider is null");
310 if (callback) {
311 callback(SEND_EVENT_FAILED);
312 }
313 return SEND_EVENT_FAILED;
314 }
315
316 accessibilityProvider->SendAccessibilityAsyncEvent(*accessibilityEvent, callback);
317 return SEND_EVENT_SUCCESS;
318 }
319
SetInnerAccessibilityProvider(const OHOS::Ace::WeakPtr<OHOS::Ace::AccessibilityProvider> & accessibilityProvider)320 void ArkUI_AccessibilityProvider::SetInnerAccessibilityProvider(
321 const OHOS::Ace::WeakPtr<OHOS::Ace::AccessibilityProvider>& accessibilityProvider)
322 {
323 accessibilityProvider_ = accessibilityProvider;
324 }
325
IsRegister()326 bool ArkUI_AccessibilityProvider::IsRegister()
327 {
328 return accessibilityProviderCallbacks_.findAccessibilityNodeInfosById != nullptr ||
329 accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById != nullptr;
330 }
331
SetRegisterCallback(RegisterCallback callback)332 void ArkUI_AccessibilityProvider::SetRegisterCallback(RegisterCallback callback)
333 {
334 registerCallback_ = callback;
335 }
336