1 /*
2  * Copyright (C) 2022 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 "napi_accessibility_system_ability_client.h"
17 
18 #include <uv.h>
19 #include "accessibility_state_event.h"
20 #include "hilog_wrapper.h"
21 #include "accessibility_utils.h"
22 
23 using namespace OHOS;
24 using namespace OHOS::Accessibility;
25 using namespace OHOS::AccessibilityNapi;
26 
27 namespace OHOS {
28 namespace Accessibility {
TmpOpenScope(napi_env env)29 napi_handle_scope TmpOpenScope(napi_env env)
30 {
31     napi_handle_scope scope = nullptr;
32     NAPI_CALL(env, napi_open_handle_scope(env, &scope));
33     return scope;
34 }
35 } // namespace Accessibility
36 } // namespace OHOS
37 
38 std::shared_ptr<StateListenerImpl> NAccessibilityClient::accessibilityStateListeners_ =
39     std::make_shared<StateListenerImpl>(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED);
40 std::shared_ptr<StateListenerImpl> NAccessibilityClient::touchGuideStateListeners_ =
41     std::make_shared<StateListenerImpl>(AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED);
42 std::shared_ptr<NAccessibilityConfigObserverImpl> NAccessibilityClient::captionListeners_ =
43     std::make_shared<NAccessibilityConfigObserverImpl>();
44 
45 napi_ref NAccessibilityClient::aaConsRef_;
46 napi_ref NAccessibilityClient::aaStyleConsRef_;
47 
48 #define ACCESSIBILITY_NAPI_ASSERT(env, cond, errCode) \
49 do { \
50     if (!(cond)) { \
51         napi_value err = CreateBusinessError(env, errCode); \
52         napi_throw(env, err); \
53         napi_value res = nullptr; \
54         napi_get_undefined(env, &res); \
55         return res; \
56     } \
57 } while (0)
58 
IsOpenAccessibilitySync(napi_env env, napi_callback_info info)59 napi_value NAccessibilityClient::IsOpenAccessibilitySync(napi_env env, napi_callback_info info)
60 {
61     HILOG_INFO();
62     size_t argc = ARGS_SIZE_ONE;
63     napi_value argv = nullptr;
64     napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
65     ACCESSIBILITY_NAPI_ASSERT(env, argc == ARGS_SIZE_ZERO, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
66 
67     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
68     ACCESSIBILITY_NAPI_ASSERT(env, asaClient != nullptr, OHOS::Accessibility::RET_ERR_NULLPTR);
69     bool status = false;
70     auto ret = asaClient->IsEnabled(status);
71     ACCESSIBILITY_NAPI_ASSERT(env, ret == RET_OK, OHOS::Accessibility::RET_ERR_FAILED);
72     napi_value result = nullptr;
73     napi_get_boolean(env, status, &result);
74     return result;
75 }
76 
IsOpenAccessibility(napi_env env, napi_callback_info info)77 napi_value NAccessibilityClient::IsOpenAccessibility(napi_env env, napi_callback_info info)
78 {
79     HILOG_INFO();
80     size_t argc = ARGS_SIZE_ONE;
81     napi_value argv = nullptr;
82     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
83     if (callbackInfo == nullptr) {
84         HILOG_ERROR("Failed to create callbackInfo.");
85         return nullptr;
86     }
87     napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
88 
89     napi_value promise = nullptr;
90     if (argc > 0 && CheckJsFunction(env, argv)) {
91         HILOG_DEBUG("IsOpenAccessibility callback mode");
92         napi_create_reference(env, argv, 1, &callbackInfo->callback_);
93         napi_get_undefined(env, &promise);
94     } else {
95         HILOG_DEBUG("IsOpenAccessibility promise mode");
96         napi_create_promise(env, &callbackInfo->deferred_, &promise);
97     }
98     napi_value resource = nullptr;
99     napi_create_string_utf8(env, "IsOpenAccessibility", NAPI_AUTO_LENGTH, &resource);
100 
101     auto ret = napi_create_async_work(env, nullptr, resource,
102         // Execute async to call c++ function
103         [](napi_env env, void* data) {
104             NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
105             auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
106             if (asaClient) {
107                 callbackInfo->ret_ = asaClient->IsEnabled(callbackInfo->enabled_);
108                 HILOG_INFO("IsOpenAccessibility Executing enabled[%{public}d]", callbackInfo->enabled_);
109             }
110         },
111         // Execute the complete function
112         [](napi_env env, napi_status status, void* data) {
113             Completefunction(env, "IsOpenAccessibility", data);
114         },
115         reinterpret_cast<void*>(callbackInfo), &callbackInfo->work_);
116     if (ret != napi_ok) {
117         delete callbackInfo;
118         callbackInfo = nullptr;
119         HILOG_ERROR("failed to create async work.");
120         return nullptr;
121     }
122     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
123     return promise;
124 }
125 
IsOpenTouchExplorationSync(napi_env env, napi_callback_info info)126 napi_value NAccessibilityClient::IsOpenTouchExplorationSync(napi_env env, napi_callback_info info)
127 {
128     HILOG_INFO();
129     size_t argc = ARGS_SIZE_ONE;
130     napi_value argv = nullptr;
131     napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
132     ACCESSIBILITY_NAPI_ASSERT(env, argc == ARGS_SIZE_ZERO, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
133 
134     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
135     ACCESSIBILITY_NAPI_ASSERT(env, asaClient != nullptr, OHOS::Accessibility::RET_ERR_NULLPTR);
136     bool status = false;
137     auto ret = asaClient->IsTouchExplorationEnabled(status);
138     ACCESSIBILITY_NAPI_ASSERT(env, ret == RET_OK, OHOS::Accessibility::RET_ERR_FAILED);
139     napi_value result = nullptr;
140     napi_get_boolean(env, status, &result);
141     return result;
142 }
143 
IsOpenTouchExploration(napi_env env, napi_callback_info info)144 napi_value NAccessibilityClient::IsOpenTouchExploration(napi_env env, napi_callback_info info)
145 {
146     HILOG_INFO();
147     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
148     if (callbackInfo == nullptr) {
149         HILOG_ERROR("Failed to create callbackInfo.");
150         return nullptr;
151     }
152     size_t argc = ARGS_SIZE_ONE;
153     napi_value argv = nullptr;
154     napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
155 
156     napi_value promise = nullptr;
157     if (argc > 0 && CheckJsFunction(env, argv)) {
158         HILOG_DEBUG("IsOpenTouchExploration callback mode");
159         napi_create_reference(env, argv, 1, &callbackInfo->callback_);
160         napi_get_undefined(env, &promise);
161     } else {
162         HILOG_DEBUG("IsOpenTouchExploration promise mode");
163         napi_create_promise(env, &callbackInfo->deferred_, &promise);
164     }
165     napi_value resource = nullptr;
166     napi_create_string_utf8(env, "IsOpenTouchExploration", NAPI_AUTO_LENGTH, &resource);
167 
168     auto ret = napi_create_async_work(env, nullptr, resource,
169         // Execute async to call c++ function
170         [](napi_env env, void* data) {
171             NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
172             auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
173             if (asaClient) {
174                 callbackInfo->ret_ = asaClient->IsTouchExplorationEnabled(callbackInfo->touchEnabled_);
175                 HILOG_INFO("IsOpenTouchExploration Executing touchEnabled[%{public}d]", callbackInfo->touchEnabled_);
176             }
177         },
178         // Execute the complete function
179         [](napi_env env, napi_status status, void* data) {
180             Completefunction(env, "IsOpenTouchExploration", data);
181         },
182         reinterpret_cast<void*>(callbackInfo), &callbackInfo->work_);
183     if (ret != napi_ok) {
184         delete callbackInfo;
185         callbackInfo = nullptr;
186         HILOG_ERROR("failed to create async work.");
187         return nullptr;
188     }
189     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
190     return promise;
191 }
192 
Completefunction(napi_env env, std::string type, void* data)193 void NAccessibilityClient::Completefunction(napi_env env, std::string type, void* data)
194 {
195     NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
196     napi_value result[ARGS_SIZE_TWO] = {0};
197     napi_value callback = 0;
198     napi_value undefined = 0;
199     napi_get_undefined(env, &undefined);
200 
201     if (type == "IsOpenAccessibility") {
202         NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, callbackInfo->enabled_, &result[PARAM1]));
203         HILOG_INFO("IsOpenAccessibility completed enabled[%{public}d]", callbackInfo->enabled_);
204     } else if (type == "IsOpenTouchExploration") {
205         NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, callbackInfo->touchEnabled_, &result[PARAM1]));
206         HILOG_INFO("IsOpenTouchExploration completed touchEnabled_[%{public}d]", callbackInfo->touchEnabled_);
207     } else {
208         napi_delete_async_work(env, callbackInfo->work_);
209         delete callbackInfo;
210         callbackInfo = nullptr;
211         return;
212     }
213     result[PARAM0] = CreateBusinessError(env, callbackInfo->ret_);
214     if (callbackInfo->callback_) {
215         napi_get_reference_value(env, callbackInfo->callback_, &callback);
216         napi_value returnVal = nullptr;
217         napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &returnVal);
218         napi_delete_reference(env, callbackInfo->callback_);
219     } else {
220         if (callbackInfo->ret_ == OHOS::Accessibility::RET_OK) {
221             HILOG_DEBUG("Completefunction callbackInfo->ret_ is RET_OK");
222             napi_resolve_deferred(env, callbackInfo->deferred_, result[PARAM1]);
223         } else {
224             HILOG_DEBUG("Completefunction callbackInfo->ret_ is not RET_OK");
225             napi_reject_deferred(env, callbackInfo->deferred_, result[PARAM0]);
226         }
227     }
228     napi_delete_async_work(env, callbackInfo->work_);
229     delete callbackInfo;
230     callbackInfo = nullptr;
231 }
232 
GetAbilityListExecute(napi_env env, void* data)233 void NAccessibilityClient::GetAbilityListExecute(napi_env env, void* data)
234 {
235     NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
236     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
237     if (asaClient) {
238         callbackInfo->ret_ = asaClient->GetAbilityList(callbackInfo->abilityTypes_,
239             callbackInfo->stateTypes_, callbackInfo->abilityList_);
240     }
241 }
242 
GetAbilityListComplete(napi_env env, napi_status status, void* data)243 void NAccessibilityClient::GetAbilityListComplete(napi_env env, napi_status status, void* data)
244 {
245     NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
246     napi_value result[ARGS_SIZE_TWO] = {0};
247     napi_value callback = 0;
248     napi_value undefined = 0;
249     napi_get_undefined(env, &undefined);
250     napi_create_array(env, &result[PARAM1]);
251     ConvertAccessibleAbilityInfosToJS(env, result[PARAM1], callbackInfo->abilityList_);
252     result[PARAM0] = CreateBusinessError(env, callbackInfo->ret_);
253     if (callbackInfo->callback_) {
254         napi_get_reference_value(env, callbackInfo->callback_, &callback);
255         napi_value returnVal = nullptr;
256         napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &returnVal);
257         napi_delete_reference(env, callbackInfo->callback_);
258     } else {
259         if (callbackInfo->ret_ == OHOS::Accessibility::RET_OK) {
260             HILOG_DEBUG("GetAbilityListComplete callbackInfo->ret_ is RET_OK");
261             napi_resolve_deferred(env, callbackInfo->deferred_, result[PARAM1]);
262         } else {
263             HILOG_DEBUG("GetAbilityListComplete callbackInfo->ret_ is not RET_OK");
264             napi_reject_deferred(env, callbackInfo->deferred_, result[PARAM0]);
265         }
266     }
267     napi_delete_async_work(env, callbackInfo->work_);
268     delete callbackInfo;
269     callbackInfo = nullptr;
270 }
271 
GetAbilityList(napi_env env, napi_callback_info info)272 napi_value NAccessibilityClient::GetAbilityList(napi_env env, napi_callback_info info)
273 {
274     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
275     if (callbackInfo == nullptr) {
276         HILOG_ERROR("Failed to create callbackInfo.");
277         return nullptr;
278     }
279 
280     size_t argc = 3;
281     napi_value parameters[3] = {0};
282     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
283 
284     std::string abilityTypes = GetStringFromNAPI(env, parameters[0]);
285     std::string stateTypes = GetStringFromNAPI(env, parameters[1]);
286     HILOG_INFO("abilityTypes[%{public}s] stateTypes[%{public}s]", abilityTypes.c_str(), stateTypes.c_str());
287 
288     callbackInfo->abilityTypes_ = ConvertStringToAccessibilityAbilityTypes(abilityTypes);
289     callbackInfo->stateTypes_ = ConvertStringToAbilityStateType(stateTypes);
290 
291     napi_value promise = nullptr;
292 
293     if (argc > ARGS_SIZE_TWO && CheckJsFunction(env, parameters[ARGS_SIZE_TWO])) {
294         napi_create_reference(env, parameters[ARGS_SIZE_TWO], 1, &callbackInfo->callback_);
295         napi_get_undefined(env, &promise);
296     } else {
297         napi_create_promise(env, &callbackInfo->deferred_, &promise);
298     }
299     napi_value resource = nullptr;
300     napi_create_string_utf8(env, "GetAbilityList", NAPI_AUTO_LENGTH, &resource);
301 
302     auto ret = napi_create_async_work(env, nullptr, resource,
303         // Execute async to call c++ function
304         NAccessibilityClient::GetAbilityListExecute,
305         // Execute the complete function
306         NAccessibilityClient::GetAbilityListComplete,
307         reinterpret_cast<void*>(callbackInfo),
308         &callbackInfo->work_);
309     if (ret != napi_ok) {
310         delete callbackInfo;
311         callbackInfo = nullptr;
312         HILOG_ERROR("failed to create async work.");
313         return nullptr;
314     }
315     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
316     return promise;
317 }
318 
GetAccessibilityExtensionList(napi_env env, napi_callback_info info)319 napi_value NAccessibilityClient::GetAccessibilityExtensionList(napi_env env, napi_callback_info info)
320 {
321     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
322     if (callbackInfo == nullptr) {
323         HILOG_ERROR("Failed to create callbackInfo.");
324         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_NULLPTR);
325         napi_throw(env, err);
326         return nullptr;
327     }
328 
329     size_t argc = ARGS_SIZE_THREE;
330     napi_value parameters[ARGS_SIZE_THREE] = {0};
331     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
332 
333     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
334     do {
335         if (argc < ARGS_SIZE_THREE - 1) {
336             HILOG_ERROR("argc is invalid: %{public}zu", argc);
337             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
338             break;
339         }
340 
341         // parse ability type
342         std::string abilityTypes = "";
343         std::string stateTypes = "";
344         if (!ParseString(env, abilityTypes, parameters[PARAM0]) ||
345             !ParseString(env, stateTypes, parameters[PARAM1])) {
346             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
347             break;
348         }
349 
350         HILOG_INFO("abilityTypes = %{private}s", abilityTypes.c_str());
351         if (CheckAbilityType(abilityTypes)) {
352             callbackInfo->abilityTypes_ = ConvertStringToAccessibilityAbilityTypes(abilityTypes);
353         } else {
354             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
355             break;
356         }
357         // parse ability state
358         HILOG_INFO("stateTypes = %{private}s", stateTypes.c_str());
359         if (CheckStateType(stateTypes)) {
360             callbackInfo->stateTypes_ = ConvertStringToAbilityStateType(stateTypes);
361         } else {
362             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
363         }
364     } while (0);
365 
366     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
367         delete callbackInfo;
368         callbackInfo = nullptr;
369         napi_value err = CreateBusinessError(env, errCode);
370         HILOG_ERROR("invalid param");
371         napi_throw(env, err);
372         return nullptr;
373     }
374 
375     return GetAccessibilityExtensionListAsync(env, argc, parameters, callbackInfo);
376 }
377 
GetAccessibilityExtensionListAsync( napi_env env, size_t argc, napi_value* parameters, NAccessibilitySystemAbilityClient* callbackInfo)378 napi_value NAccessibilityClient::GetAccessibilityExtensionListAsync(
379     napi_env env, size_t argc, napi_value* parameters, NAccessibilitySystemAbilityClient* callbackInfo)
380 {
381     napi_value promise = nullptr;
382     if (argc > ARGS_SIZE_THREE - 1 && CheckJsFunction(env, parameters[PARAM2])) {
383         napi_create_reference(env, parameters[PARAM2], 1, &callbackInfo->callback_);
384         napi_get_undefined(env, &promise);
385     } else {
386         napi_create_promise(env, &callbackInfo->deferred_, &promise);
387     }
388     napi_value resource = nullptr;
389     napi_create_string_utf8(env, "GetAccessibilityExtensionList", NAPI_AUTO_LENGTH, &resource);
390 
391     auto ret = napi_create_async_work(env, nullptr, resource,
392         // Execute async to call c++ function
393         NAccessibilityClient::GetAbilityListExecute,
394         // Execute the complete function
395         NAccessibilityClient::GetAbilityListComplete,
396         reinterpret_cast<void*>(callbackInfo),
397         &callbackInfo->work_);
398     if (ret != napi_ok) {
399         delete callbackInfo;
400         callbackInfo = nullptr;
401         HILOG_ERROR("failed to create async work.");
402         return nullptr;
403     }
404     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
405     return promise;
406 }
407 
GetAccessibilityExtensionListSync(napi_env env, napi_callback_info info)408 napi_value NAccessibilityClient::GetAccessibilityExtensionListSync(napi_env env, napi_callback_info info)
409 {
410     size_t argc = ARGS_SIZE_THREE;
411     napi_value parameters[ARGS_SIZE_THREE] = {0};
412     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
413 
414     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
415     OHOS::Accessibility::AbilityStateType stateTypes = OHOS::Accessibility::ABILITY_STATE_INVALID;
416     uint32_t abilityTypes = 0;
417 
418     do {
419         if (argc < ARGS_SIZE_THREE - 1) {
420             HILOG_ERROR("argc is invalid: %{public}zu", argc);
421             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
422             break;
423         }
424 
425         // parse ability type
426         std::string abilityTypeStr = "";
427         std::string stateTypeStr = "";
428         if (!ParseString(env, abilityTypeStr, parameters[PARAM0]) ||
429             !ParseString(env, stateTypeStr, parameters[PARAM1])) {
430             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
431             break;
432         }
433 
434         HILOG_DEBUG("abilityTypeStr = %{private}s", abilityTypeStr.c_str());
435         if (CheckAbilityType(abilityTypeStr)) {
436             abilityTypes = ConvertStringToAccessibilityAbilityTypes(abilityTypeStr);
437         } else {
438             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
439             break;
440         }
441 
442         // parse ability state
443         HILOG_DEBUG("stateTypeStr = %{private}s", stateTypeStr.c_str());
444         if (CheckStateType(stateTypeStr)) {
445             stateTypes = ConvertStringToAbilityStateType(stateTypeStr);
446         } else {
447             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
448         }
449     } while (0);
450 
451     std::vector<OHOS::Accessibility::AccessibilityAbilityInfo> abilityList {};
452     if (errCode == OHOS::Accessibility::RET_OK) {
453         auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
454         if (asaClient) {
455             errCode = asaClient->GetAbilityList(abilityTypes, stateTypes, abilityList);
456         }
457     }
458 
459     ACCESSIBILITY_NAPI_ASSERT(env, errCode == OHOS::Accessibility::RET_OK,
460         OHOS::Accessibility::RET_ERR_INVALID_PARAM);
461 
462     napi_value resultAbilityList = nullptr;
463     napi_create_array(env, &resultAbilityList);
464     ConvertAccessibleAbilityInfosToJS(env, resultAbilityList, abilityList);
465     return resultAbilityList;
466 }
467 
CheckAbilityType(const std::string& abilityType)468 bool NAccessibilityClient::CheckAbilityType(const std::string& abilityType)
469 {
470     if (std::strcmp(abilityType.c_str(), "audible") == 0 ||
471         std::strcmp(abilityType.c_str(), "generic") == 0 ||
472         std::strcmp(abilityType.c_str(), "haptic") == 0 ||
473         std::strcmp(abilityType.c_str(), "spoken") == 0 ||
474         std::strcmp(abilityType.c_str(), "visual") == 0 ||
475         std::strcmp(abilityType.c_str(), "all") == 0) {
476         return true;
477     } else {
478         return false;
479     }
480 }
481 
CheckStateType(const std::string& stateType)482 bool NAccessibilityClient::CheckStateType(const std::string& stateType)
483 {
484     if (std::strcmp(stateType.c_str(), "enable") == 0 ||
485         std::strcmp(stateType.c_str(), "disable") == 0 ||
486         std::strcmp(stateType.c_str(), "install") == 0) {
487         return true;
488     } else {
489         return false;
490     }
491 }
492 
SendEventExecute(napi_env env, void* data)493 void NAccessibilityClient::SendEventExecute(napi_env env, void* data)
494 {
495     NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
496     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
497     if (callbackInfo->result_ && asaClient) {
498         callbackInfo->ret_ = asaClient->SendEvent(callbackInfo->eventInfo_);
499     }
500     HILOG_INFO("SendEvent result[%{public}d]", callbackInfo->ret_);
501 }
502 
SendEventComplete(napi_env env, napi_status status, void* data)503 void NAccessibilityClient::SendEventComplete(napi_env env, napi_status status, void* data)
504 {
505     NAccessibilitySystemAbilityClient* callbackInfo = static_cast<NAccessibilitySystemAbilityClient*>(data);
506     napi_value result[ARGS_SIZE_TWO] = {0};
507     napi_value callback = 0;
508     napi_value undefined = 0;
509     napi_value ret = 0;
510     napi_get_undefined(env, &undefined);
511     napi_get_undefined(env, &ret);
512     result[PARAM0] = CreateBusinessError(env, callbackInfo->ret_);
513     result[PARAM1] = ret;
514     if (callbackInfo->callback_) {
515         napi_get_reference_value(env, callbackInfo->callback_, &callback);
516         napi_value returnVal = nullptr;
517         napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &returnVal);
518         napi_delete_reference(env, callbackInfo->callback_);
519     } else {
520         if (callbackInfo->ret_ == OHOS::Accessibility::RET_OK) {
521             HILOG_DEBUG("SendEventComplete callbackInfo->ret_ is RET_OK");
522             napi_resolve_deferred(env, callbackInfo->deferred_, result[PARAM1]);
523         } else {
524             HILOG_DEBUG("SendEventComplete callbackInfo->ret_ is not RET_OK");
525             napi_reject_deferred(env, callbackInfo->deferred_, result[PARAM0]);
526         }
527     }
528     napi_delete_async_work(env, callbackInfo->work_);
529     delete callbackInfo;
530     callbackInfo = nullptr;
531 }
532 
SendEvent(napi_env env, napi_callback_info info)533 napi_value NAccessibilityClient::SendEvent(napi_env env, napi_callback_info info)
534 {
535     HILOG_INFO();
536     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
537     if (callbackInfo == nullptr) {
538         HILOG_ERROR("Failed to create callbackInfo.");
539         return nullptr;
540     }
541 
542     size_t argc = ARGS_SIZE_TWO;
543     napi_value parameters[ARGS_SIZE_TWO] = {0};
544     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
545     callbackInfo->result_ = ConvertEventInfoJSToNAPI(env, parameters[0], callbackInfo->eventInfo_);
546 
547     napi_value promise = nullptr;
548 
549     if (argc > ARGS_SIZE_ONE && CheckJsFunction(env, parameters[1])) {
550         HILOG_DEBUG("SendEvent callback mode");
551         napi_create_reference(env, parameters[1], 1, &callbackInfo->callback_);
552     } else {
553         HILOG_DEBUG("SendEvent promise mode");
554         napi_create_promise(env, &callbackInfo->deferred_, &promise);
555     }
556     napi_value resource = nullptr;
557     napi_create_string_utf8(env, "SendEvent", NAPI_AUTO_LENGTH, &resource);
558 
559     auto ret = napi_create_async_work(env, nullptr, resource,
560         NAccessibilityClient::SendEventExecute,
561         NAccessibilityClient::SendEventComplete,
562         reinterpret_cast<void*>(callbackInfo),
563         &callbackInfo->work_);
564     if (ret != napi_ok) {
565         delete callbackInfo;
566         callbackInfo = nullptr;
567         HILOG_ERROR("failed to create async work.");
568         return nullptr;
569     }
570     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
571 
572     return promise;
573 }
574 
SendAccessibilityEvent(napi_env env, napi_callback_info info)575 napi_value NAccessibilityClient::SendAccessibilityEvent(napi_env env, napi_callback_info info)
576 {
577     HILOG_INFO();
578     NAccessibilitySystemAbilityClient* callbackInfo = new(std::nothrow) NAccessibilitySystemAbilityClient();
579     if (callbackInfo == nullptr) {
580         HILOG_ERROR("Failed to create callbackInfo.");
581         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_NULLPTR);
582         napi_throw(env, err);
583         return nullptr;
584     }
585 
586     size_t argc = ARGS_SIZE_TWO;
587     napi_value parameters[ARGS_SIZE_TWO] = {0};
588     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
589 
590     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
591     if (argc < ARGS_SIZE_TWO - 1) {
592         HILOG_ERROR("argc is invalid: %{public}zu", argc);
593         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
594     }
595 
596     if (errCode == OHOS::Accessibility::RET_OK) {
597         callbackInfo->result_ = ConvertEventInfoJSToNAPI(env, parameters[0], callbackInfo->eventInfo_);
598         if (!callbackInfo->result_) {
599             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
600         }
601     }
602 
603     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
604         delete callbackInfo;
605         callbackInfo = nullptr;
606         napi_value err = CreateBusinessError(env, errCode);
607         HILOG_ERROR("SendAccessibilityEvent invalid param");
608         napi_throw(env, err);
609         return nullptr;
610     }
611 
612     napi_value promise = nullptr;
613     if (argc > ARGS_SIZE_TWO - 1 && CheckJsFunction(env, parameters[PARAM1])) {
614         napi_create_reference(env, parameters[PARAM1], 1, &callbackInfo->callback_);
615         napi_get_undefined(env, &promise);
616     } else {
617         HILOG_DEBUG("SendEvent promise mode");
618         napi_create_promise(env, &callbackInfo->deferred_, &promise);
619     }
620     napi_value resource = nullptr;
621     napi_create_string_utf8(env, "SendAccessibilityEvent", NAPI_AUTO_LENGTH, &resource);
622 
623     napi_create_async_work(env, nullptr, resource,
624         NAccessibilityClient::SendEventExecute,
625         NAccessibilityClient::SendEventComplete,
626         reinterpret_cast<void*>(callbackInfo),
627         &callbackInfo->work_);
628     napi_queue_async_work_with_qos(env, callbackInfo->work_, napi_qos_user_initiated);
629 
630     return promise;
631 }
632 
SubscribeState(napi_env env, napi_callback_info info)633 napi_value NAccessibilityClient::SubscribeState(napi_env env, napi_callback_info info)
634 {
635     HILOG_INFO();
636     size_t argc = ARGS_SIZE_TWO;
637     napi_value args[ARGS_SIZE_TWO] = {0};
638     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
639     if (status != napi_ok) {
640         HILOG_ERROR("SubscribeState Failed to get event type");
641         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_FAILED);
642         napi_throw(env, err);
643         return nullptr;
644     }
645 
646     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
647     if (argc < ARGS_SIZE_TWO) {
648         HILOG_ERROR("SubscribeState argc is invalid: %{public}zu", argc);
649         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
650     }
651     uint32_t type = AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED;
652     GetAccessibilityStateEventType(env, args, errCode, type);
653     if (errCode == OHOS::Accessibility::RET_OK) {
654         napi_valuetype valueType = napi_null;
655         napi_typeof(env, args[PARAM1], &valueType);
656         if (valueType != napi_function) {
657             HILOG_ERROR("args[PARAM1] format is wrong");
658             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
659         }
660     }
661 
662     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
663         napi_value err = CreateBusinessError(env, errCode);
664         HILOG_ERROR("SubscribeState invalid param");
665         napi_throw(env, err);
666         return nullptr;
667     }
668 
669     switch (type) {
670         case AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED:
671             accessibilityStateListeners_->SubscribeObserver(env, args[PARAM1]);
672             break;
673         case AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED:
674             touchGuideStateListeners_->SubscribeObserver(env, args[PARAM1]);
675             break;
676         default:
677             break;
678     }
679     return nullptr;
680 }
681 
GetAccessibilityStateEventType( napi_env env, napi_value* args, OHOS::Accessibility::RetError& errCode, uint32_t& type)682 void NAccessibilityClient::GetAccessibilityStateEventType(
683     napi_env env, napi_value* args, OHOS::Accessibility::RetError& errCode, uint32_t& type)
684 {
685     if (errCode == OHOS::Accessibility::RET_OK) {
686         std::string eventType = "";
687         if (!ParseString(env, eventType, args[PARAM0])) {
688             HILOG_ERROR("eventType type parse failed");
689             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
690         } else {
691             if (std::strcmp(eventType.c_str(), "accessibilityStateChange") == 0) {
692                 type = AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED;
693             } else if (std::strcmp(eventType.c_str(), "touchGuideStateChange") == 0) {
694                 type = AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED;
695             } else {
696                 HILOG_ERROR("SubscribeState eventType[%{public}s] is error", eventType.c_str());
697                 errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
698             }
699         }
700     }
701 }
702 
UnsubscribeState(napi_env env, napi_callback_info info)703 napi_value NAccessibilityClient::UnsubscribeState(napi_env env, napi_callback_info info)
704 {
705     HILOG_INFO();
706     size_t argc = ARGS_SIZE_TWO;
707     napi_value args[ARGS_SIZE_TWO] = {0};
708     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
709 
710     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
711     if (argc < ARGS_SIZE_TWO - 1) {
712         HILOG_ERROR("UnsubscribeState argc is invalid: %{public}zu", argc);
713         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
714     }
715 
716     uint32_t type = AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED;
717     GetAccessibilityStateEventType(env, args, errCode, type);
718 
719     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
720         napi_value err = CreateBusinessError(env, errCode);
721         HILOG_ERROR("invalid param");
722         napi_throw(env, err);
723         return nullptr;
724     }
725     switch (type) {
726         case AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED:
727             if (argc >= ARGS_SIZE_TWO && CheckJsFunction(env, args[PARAM1])) {
728                 accessibilityStateListeners_->UnsubscribeObserver(env, args[PARAM1]);
729             } else {
730                 accessibilityStateListeners_->UnsubscribeObservers();
731             }
732             break;
733         case AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED:
734             if (argc >= ARGS_SIZE_TWO && CheckJsFunction(env, args[PARAM1])) {
735                 touchGuideStateListeners_->UnsubscribeObserver(env, args[PARAM1]);
736             } else {
737                 touchGuideStateListeners_->UnsubscribeObservers();
738             }
739             break;
740         default:
741             break;
742     }
743 
744     return nullptr;
745 }
746 
NotifyJS(napi_env env, bool state, napi_ref handlerRef)747 void StateListener::NotifyJS(napi_env env, bool state, napi_ref handlerRef)
748 {
749     HILOG_INFO("state = [%{public}s]", state ? "true" : "false");
750 
751     StateCallbackInfo *callbackInfo = new(std::nothrow) StateCallbackInfo();
752     if (callbackInfo == nullptr) {
753         HILOG_ERROR("Failed to create callbackInfo.");
754         return;
755     }
756     callbackInfo->state_ = state;
757     callbackInfo->env_ = env;
758     callbackInfo->ref_ = handlerRef;
759     uv_work_t *work = new(std::nothrow) uv_work_t;
760     if (!work) {
761         HILOG_ERROR("Failed to create work.");
762         delete callbackInfo;
763         callbackInfo = nullptr;
764         return;
765     }
766     work->data = static_cast<void*>(callbackInfo);
767 
768     int ret = NotifyJSWork(env, work);
769     if (ret != 0) {
770         HILOG_ERROR("Failed to execute NotifyJS work queue");
771         delete callbackInfo;
772         callbackInfo = nullptr;
773         delete work;
774         work = nullptr;
775     }
776 }
777 
NotifyJSWork(napi_env env, uv_work_t *work)778 int StateListener::NotifyJSWork(napi_env env, uv_work_t *work)
779 {
780     uv_loop_s *loop = nullptr;
781     napi_get_uv_event_loop(env, &loop);
782     if (loop == nullptr || work == nullptr) {
783         HILOG_ERROR("loop or work is nullptr.");
784         return RET_ERR_FAILED;
785     }
786     int ret = uv_queue_work_with_qos(
787         loop,
788         work,
789         [](uv_work_t *work) {},
790         [](uv_work_t *work, int status) {
791             StateCallbackInfo *callbackInfo = static_cast<StateCallbackInfo*>(work->data);
792             napi_env tmpEnv = callbackInfo->env_;
793             auto closeScope = [tmpEnv](napi_handle_scope scope) {
794                 napi_close_handle_scope(tmpEnv, scope);
795             };
796             std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(
797                 OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope);
798             napi_value handler = nullptr;
799             napi_value callResult = nullptr;
800             napi_value jsEvent = nullptr;
801             napi_get_boolean(callbackInfo->env_, callbackInfo->state_, &jsEvent);
802 
803             napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
804             napi_value undefined = nullptr;
805             napi_get_undefined(callbackInfo->env_, &undefined);
806             napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
807             delete callbackInfo;
808             callbackInfo = nullptr;
809             delete work;
810             work = nullptr;
811         },
812         uv_qos_default);
813     return ret;
814 }
815 
OnStateChanged(const bool state)816 void StateListener::OnStateChanged(const bool state)
817 {
818     NotifyJS(env_, state, handlerRef_);
819 }
820 
DefineJSCaptionsManager(napi_env env)821 void NAccessibilityClient::DefineJSCaptionsManager(napi_env env)
822 {
823     napi_property_descriptor captionsManagerDesc[] = {
824         DECLARE_NAPI_GETTER_SETTER("enabled",
825             NAccessibilityClient::GetCaptionStateEnabled, NAccessibilityClient::SetCaptionStateEnabled),
826         DECLARE_NAPI_GETTER_SETTER("style",
827             NAccessibilityClient::GetCaptionStyle, NAccessibilityClient::SetCaptionStyle),
828         DECLARE_NAPI_FUNCTION("on", NAccessibilityClient::RegisterCaptionStateCallback),
829         DECLARE_NAPI_FUNCTION("off", NAccessibilityClient::DeregisterCaptionStateCallback),
830     };
831 
832     napi_value aaCons = nullptr;
833     NAPI_CALL_RETURN_VOID(env,
834         napi_define_class(env,
835             "CaptionsManager",
836             NAPI_AUTO_LENGTH,
837             NAccessibilityClient::AccessibleAbilityConstructor,
838             nullptr,
839             sizeof(captionsManagerDesc) / sizeof(captionsManagerDesc[0]),
840             captionsManagerDesc,
841             &aaCons));
842 
843     napi_create_reference(env, aaCons, 1, &NAccessibilityClient::aaConsRef_);
844 }
845 
AccessibleAbilityConstructor(napi_env env, napi_callback_info info)846 napi_value NAccessibilityClient::AccessibleAbilityConstructor(napi_env env, napi_callback_info info)
847 {
848     napi_value jsthis = nullptr;
849     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr));
850     return jsthis;
851 }
852 
853 
GetCaptionsManager(napi_env env, napi_callback_info info)854 napi_value NAccessibilityClient::GetCaptionsManager(napi_env env, napi_callback_info info)
855 {
856     HILOG_INFO();
857     napi_value result = 0;
858     napi_value aaCons = nullptr;
859     napi_get_reference_value(env, NAccessibilityClient::aaConsRef_, &aaCons);
860     napi_new_instance(env, aaCons, 0, nullptr, &result);
861     return result;
862 }
863 
SetCaptionStateEnabled(napi_env env, napi_callback_info info)864 napi_value NAccessibilityClient::SetCaptionStateEnabled(napi_env env, napi_callback_info info)
865 {
866     HILOG_INFO();
867     size_t argc = ARGS_SIZE_ONE;
868     napi_value parameters[ARGS_SIZE_ONE] = {0};
869     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
870     if (argc >= ARGS_SIZE_ONE) {
871         bool captionState = false;
872         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
873         if (!ParseBool(env, captionState, parameters[PARAM0])) {
874             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
875         } else {
876             HILOG_INFO("captionState = %{public}s", captionState ? "True" : "False");
877 
878             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
879             ret = instance.SetCaptionsState(captionState);
880         }
881         if (ret != OHOS::Accessibility::RET_OK) {
882             napi_value err = CreateBusinessError(env, ret);
883             napi_throw(env, err);
884         }
885     } else {
886         HILOG_ERROR("SetCaptionStateEnabled argc size Error");
887         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
888         napi_throw(env, err);
889     }
890 
891     napi_value undefined = nullptr;
892     napi_get_undefined(env, &undefined);
893     return undefined;
894 }
895 
GetCaptionStateEnabled(napi_env env, napi_callback_info info)896 napi_value NAccessibilityClient::GetCaptionStateEnabled(napi_env env, napi_callback_info info)
897 {
898     HILOG_INFO();
899     napi_value captionStateEnabled = nullptr;
900 
901     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
902     bool captionState = false;
903     instance.GetCaptionsState(captionState);
904     napi_get_boolean(env, captionState, &captionStateEnabled);
905 
906     HILOG_INFO("captionState = %{public}s", captionState ? "True" : "False");
907 
908     return captionStateEnabled;
909 }
910 
SetCaptionStyle(napi_env env, napi_callback_info info)911 napi_value NAccessibilityClient::SetCaptionStyle(napi_env env, napi_callback_info info)
912 {
913     HILOG_INFO();
914     size_t argc = ARGS_SIZE_ONE;
915     napi_value parameters[ARGS_SIZE_ONE] = {0};
916     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
917     if (argc >= ARGS_SIZE_ONE) {
918         OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
919         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
920         if (!ConvertObjToCaptionProperty(env, parameters[PARAM0], &captionProperty)) {
921             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
922         } else {
923             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
924             ret = instance.SetCaptionsProperty(captionProperty);
925         }
926         if (ret != OHOS::Accessibility::RET_OK) {
927             napi_value err = CreateBusinessError(env, ret);
928             napi_throw(env, err);
929         }
930     } else {
931         HILOG_ERROR("SetCaptionStyle argc size Error");
932         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
933         napi_throw(env, err);
934     }
935 
936     napi_value undefined = nullptr;
937     napi_get_undefined(env, &undefined);
938     return undefined;
939 }
940 
GetCaptionStyle(napi_env env, napi_callback_info info)941 napi_value NAccessibilityClient::GetCaptionStyle(napi_env env, napi_callback_info info)
942 {
943     HILOG_INFO();
944     napi_value captionStyle = nullptr;
945     napi_get_reference_value(env, NAccessibilityClient::aaStyleConsRef_, &captionStyle);
946 
947     return captionStyle;
948 }
949 
RegisterCaptionStateCallback(napi_env env, napi_callback_info info)950 napi_value NAccessibilityClient::RegisterCaptionStateCallback(napi_env env, napi_callback_info info)
951 {
952     HILOG_INFO();
953 
954     size_t argc = ARGS_SIZE_TWO;
955     napi_value args[ARGS_SIZE_TWO] = {0};
956     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
957     if (status != napi_ok) {
958         HILOG_ERROR("RegisterCaptionStateCallback Failed to get event type");
959         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_FAILED);
960         napi_throw(env, err);
961         return nullptr;
962     }
963 
964     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
965     if (argc < ARGS_SIZE_TWO) {
966         HILOG_ERROR("RegisterCaptionStateCallback argc is invalid: %{public}zu", argc);
967         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
968     }
969 
970     OHOS::AccessibilityConfig::CONFIG_ID type = OHOS::AccessibilityConfig::CONFIG_ID_MAX;
971     if (errCode == OHOS::Accessibility::RET_OK) {
972         std::string eventType = "";
973         if (!ParseString(env, eventType, args[PARAM0])) {
974             HILOG_ERROR("eventType type parse failed");
975             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
976         } else {
977             if (std::strcmp(eventType.c_str(), "enableChange") == 0) {
978                 type = OHOS::AccessibilityConfig::CONFIG_CAPTION_STATE;
979             } else if (std::strcmp(eventType.c_str(), "styleChange") == 0) {
980                 type =  OHOS::AccessibilityConfig::CONFIG_CAPTION_STYLE;
981             } else {
982                 HILOG_ERROR("SubscribeState eventType[%{public}s] is error", eventType.c_str());
983                 errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
984             }
985         }
986     }
987 
988     if (errCode == OHOS::Accessibility::RET_OK) {
989         napi_valuetype valueType = napi_null;
990         napi_typeof(env, args[PARAM1], &valueType);
991         if (valueType != napi_function) {
992             HILOG_ERROR("RegisterCaptionStateCallback args[PARAM1] format is wrong");
993             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
994         }
995     }
996 
997     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
998         napi_value err = CreateBusinessError(env, errCode);
999         HILOG_ERROR("invalid param");
1000         napi_throw(env, err);
1001         return nullptr;
1002     }
1003 
1004     captionListeners_->SubscribeObserver(env, type, args[PARAM1]);
1005 
1006     return nullptr;
1007 }
1008 
DeregisterCaptionStateCallback(napi_env env, napi_callback_info info)1009 napi_value NAccessibilityClient::DeregisterCaptionStateCallback(napi_env env, napi_callback_info info)
1010 {
1011     HILOG_INFO();
1012     size_t argc = ARGS_SIZE_TWO;
1013     napi_value args[ARGS_SIZE_TWO] = {0};
1014     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
1015 
1016     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
1017     if (argc < ARGS_SIZE_TWO - 1) {
1018         HILOG_ERROR("DeregisterCaptionStateCallback argc is invalid: %{public}zu", argc);
1019         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1020     }
1021 
1022     OHOS::AccessibilityConfig::CONFIG_ID type = OHOS::AccessibilityConfig::CONFIG_ID_MAX;
1023     if (errCode == OHOS::Accessibility::RET_OK) {
1024         std::string eventType = "";
1025         if (!ParseString(env, eventType, args[PARAM0])) {
1026             HILOG_ERROR("eventType type parse failed");
1027             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1028         } else {
1029             if (std::strcmp(eventType.c_str(), "enableChange") == 0) {
1030                 type = OHOS::AccessibilityConfig::CONFIG_CAPTION_STATE;
1031             } else if (std::strcmp(eventType.c_str(), "styleChange") == 0) {
1032                 type =  OHOS::AccessibilityConfig::CONFIG_CAPTION_STYLE;
1033             } else {
1034                 HILOG_ERROR("SubscribeState eventType[%{public}s] is error", eventType.c_str());
1035                 errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1036             }
1037         }
1038     }
1039 
1040     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
1041         napi_value err = CreateBusinessError(env, errCode);
1042         HILOG_ERROR("DeregisterCaptionStateCallback invalid param");
1043         napi_throw(env, err);
1044         return nullptr;
1045     }
1046 
1047     if (argc >= ARGS_SIZE_TWO && CheckJsFunction(env, args[PARAM1])) {
1048         captionListeners_->UnsubscribeObserver(env, type, args[PARAM1]);
1049     } else {
1050         captionListeners_->UnsubscribeObservers(type);
1051     }
1052 
1053     return nullptr;
1054 }
1055 
DefineJSCaptionsStyle(napi_env env)1056 void NAccessibilityClient::DefineJSCaptionsStyle(napi_env env)
1057 {
1058     napi_property_descriptor captionsStyleDesc[] = {
1059         DECLARE_NAPI_GETTER_SETTER("fontFamily",
1060             NAccessibilityClient::GetCaptionsFontFamily, NAccessibilityClient::SetCaptionsFontFamily),
1061         DECLARE_NAPI_GETTER_SETTER("fontScale",
1062             NAccessibilityClient::GetCaptionsFontScale, NAccessibilityClient::SetCaptionsFontScale),
1063         DECLARE_NAPI_GETTER_SETTER("fontColor",
1064             NAccessibilityClient::GetCaptionFrontColor, NAccessibilityClient::SetCaptionFrontColor),
1065         DECLARE_NAPI_GETTER_SETTER("fontEdgeType",
1066             NAccessibilityClient::GetCaptionFontEdgeType, NAccessibilityClient::SetCaptionFontEdgeType),
1067         DECLARE_NAPI_GETTER_SETTER("backgroundColor",
1068             NAccessibilityClient::GetCaptionBackgroundColor, NAccessibilityClient::SetCaptionBackgroundColor),
1069         DECLARE_NAPI_GETTER_SETTER("windowColor",
1070             NAccessibilityClient::GetCaptionWindowColor, NAccessibilityClient::SetCaptionWindowColor),
1071     };
1072 
1073     napi_value aaStyleCons = nullptr;
1074     napi_value captionStyle = nullptr;
1075 
1076     NAPI_CALL_RETURN_VOID(env,
1077         napi_define_class(env,
1078             "CaptionsStyle",
1079             NAPI_AUTO_LENGTH,
1080             NAccessibilityClient::AccessibleAbilityConstructorStyle,
1081             nullptr,
1082             sizeof(captionsStyleDesc) / sizeof(captionsStyleDesc[0]),
1083             captionsStyleDesc,
1084             &aaStyleCons));
1085 
1086     napi_new_instance(env, aaStyleCons, 0, nullptr, &captionStyle);
1087     napi_create_reference(env, captionStyle, 1, &NAccessibilityClient::aaStyleConsRef_);
1088 }
1089 
AccessibleAbilityConstructorStyle(napi_env env, napi_callback_info info)1090 napi_value NAccessibilityClient::AccessibleAbilityConstructorStyle(napi_env env, napi_callback_info info)
1091 {
1092     HILOG_INFO();
1093     napi_value jsthis = nullptr;
1094     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr));
1095     return jsthis;
1096 }
1097 
GetCaptionsFontFamily(napi_env env, napi_callback_info info)1098 napi_value NAccessibilityClient::GetCaptionsFontFamily(napi_env env, napi_callback_info info)
1099 {
1100     HILOG_INFO();
1101     napi_value returnValue = nullptr;
1102     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1103     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1104     instance.GetCaptionsProperty(captionProperty);
1105     napi_create_string_utf8(env, captionProperty.GetFontFamily().c_str(), NAPI_AUTO_LENGTH, &returnValue);
1106     return returnValue;
1107 }
1108 
SetCaptionsFontFamily(napi_env env, napi_callback_info info)1109 napi_value NAccessibilityClient::SetCaptionsFontFamily(napi_env env, napi_callback_info info)
1110 {
1111     HILOG_INFO();
1112     size_t argc = ARGS_SIZE_ONE;
1113     napi_value parameters[ARGS_SIZE_ONE] = {0};
1114     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1115     if (argc >= ARGS_SIZE_ONE) {
1116         // Get input FontFamily
1117         std::string fontFamily = "";
1118         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1119         if (ParseString(env, fontFamily, parameters[PARAM0]) && fontFamily.length() > 0) {
1120             HILOG_INFO("FontFamily = %{public}s", fontFamily.c_str());
1121             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1122             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1123             instance.GetCaptionsProperty(captionProperty);
1124             // Change the input info and then set the CaptionProperty
1125             captionProperty.SetFontFamily(std::string(fontFamily));
1126             ret = instance.SetCaptionsProperty(captionProperty);
1127         } else {
1128             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1129         }
1130         if (ret != OHOS::Accessibility::RET_OK) {
1131             napi_value err = CreateBusinessError(env, ret);
1132             napi_throw(env, err);
1133         }
1134     } else {
1135         HILOG_ERROR("SetCaptionsFontFamily argc size Error");
1136         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1137         napi_throw(env, err);
1138     }
1139     napi_value undefined = nullptr;
1140     napi_get_undefined(env, &undefined);
1141     return undefined;
1142 }
1143 
GetCaptionsFontScale(napi_env env, napi_callback_info info)1144 napi_value NAccessibilityClient::GetCaptionsFontScale(napi_env env, napi_callback_info info)
1145 {
1146     HILOG_INFO();
1147     napi_value returnValue = nullptr;
1148     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1149     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1150     instance.GetCaptionsProperty(captionProperty);
1151     napi_create_int32(env, captionProperty.GetFontScale(), &returnValue);
1152     return returnValue;
1153 }
1154 
SetCaptionsFontScale(napi_env env, napi_callback_info info)1155 napi_value NAccessibilityClient::SetCaptionsFontScale(napi_env env, napi_callback_info info)
1156 {
1157     HILOG_INFO();
1158     size_t argc = ARGS_SIZE_ONE;
1159     napi_value parameters[ARGS_SIZE_ONE] = {0};
1160     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1161     if (argc >= ARGS_SIZE_ONE) {
1162         // Get input FontScale
1163         int32_t num = 100;
1164         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1165         if (ParseInt32(env, num, parameters[PARAM0])) {
1166             HILOG_INFO("FontScale = %{public}d", num);
1167             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1168             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1169             instance.GetCaptionsProperty(captionProperty);
1170             // Change the input info and then set the CaptionProperty
1171             captionProperty.SetFontScale(num);
1172             ret = instance.SetCaptionsProperty(captionProperty);
1173         } else {
1174             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1175         }
1176         if (ret != OHOS::Accessibility::RET_OK) {
1177             napi_value err = CreateBusinessError(env, ret);
1178             napi_throw(env, err);
1179         }
1180     } else {
1181         HILOG_ERROR("SetCaptionsFontScale argc size Error");
1182         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1183         napi_throw(env, err);
1184     }
1185     napi_value undefined = nullptr;
1186     napi_get_undefined(env, &undefined);
1187     return undefined;
1188 }
1189 
GetCaptionFrontColor(napi_env env, napi_callback_info info)1190 napi_value NAccessibilityClient::GetCaptionFrontColor(napi_env env, napi_callback_info info)
1191 {
1192     HILOG_INFO();
1193     napi_value returnValue = nullptr;
1194     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1195     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1196     instance.GetCaptionsProperty(captionProperty);
1197     uint32_t color = captionProperty.GetFontColor();
1198     std::string colorStr = ConvertColorToString(color);
1199     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1200     return returnValue;
1201 }
1202 
SetCaptionFrontColor(napi_env env, napi_callback_info info)1203 napi_value NAccessibilityClient::SetCaptionFrontColor(napi_env env, napi_callback_info info)
1204 {
1205     HILOG_INFO();
1206     size_t argc = ARGS_SIZE_ONE;
1207     napi_value parameters[ARGS_SIZE_ONE] = {0};
1208     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1209     if (argc >= ARGS_SIZE_ONE) {
1210         HILOG_DEBUG("SetCaptionFrontColor argc > 1");
1211         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1212         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1213         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1214         instance.GetCaptionsProperty(captionProperty);
1215         // Change the input info and then set the CaptionProperty
1216         captionProperty.SetFontColor(color);
1217         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1218         if (ret != OHOS::Accessibility::RET_OK) {
1219             napi_value err = CreateBusinessError(env, ret);
1220             napi_throw(env, err);
1221         }
1222     } else {
1223         HILOG_ERROR("SetCaptionFrontColor argc size Error");
1224         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1225         napi_throw(env, err);
1226     }
1227     napi_value undefined = nullptr;
1228     napi_get_undefined(env, &undefined);
1229     return undefined;
1230 }
1231 
GetCaptionFontEdgeType(napi_env env, napi_callback_info info)1232 napi_value NAccessibilityClient::GetCaptionFontEdgeType(napi_env env, napi_callback_info info)
1233 {
1234     HILOG_INFO();
1235     napi_value returnValue = nullptr;
1236     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1237     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1238     instance.GetCaptionsProperty(captionProperty);
1239     napi_create_string_utf8(env, captionProperty.GetFontEdgeType().c_str(), NAPI_AUTO_LENGTH, &returnValue);
1240     return returnValue;
1241 }
1242 
SetCaptionFontEdgeType(napi_env env, napi_callback_info info)1243 napi_value NAccessibilityClient::SetCaptionFontEdgeType(napi_env env, napi_callback_info info)
1244 {
1245     HILOG_INFO();
1246     size_t argc = ARGS_SIZE_ONE;
1247     napi_value parameters[ARGS_SIZE_ONE] = {0};
1248 
1249     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1250     if (argc >= ARGS_SIZE_ONE) {
1251         // Get input FontEdgeType
1252         std::string fontEdgeType = "";
1253         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1254         if (ParseString(env, fontEdgeType, parameters[PARAM0]) && fontEdgeType.length() > 0) {
1255             HILOG_INFO("fontEdgeType = %{public}s", fontEdgeType.c_str());
1256             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1257             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1258             instance.GetCaptionsProperty(captionProperty);
1259             // Change the input info and then set the CaptionProperty
1260             captionProperty.SetFontEdgeType(std::string(fontEdgeType));
1261             ret = instance.SetCaptionsProperty(captionProperty);
1262         } else {
1263             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1264         }
1265         if (ret != OHOS::Accessibility::RET_OK) {
1266             napi_value err = CreateBusinessError(env, ret);
1267             napi_throw(env, err);
1268         }
1269     } else {
1270         HILOG_ERROR("SetCaptionFontEdgeType argc size Error");
1271         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1272         napi_throw(env, err);
1273     }
1274     napi_value undefined = nullptr;
1275     napi_get_undefined(env, &undefined);
1276     return undefined;
1277 }
1278 
GetCaptionBackgroundColor(napi_env env, napi_callback_info info)1279 napi_value NAccessibilityClient::GetCaptionBackgroundColor(napi_env env, napi_callback_info info)
1280 {
1281     HILOG_INFO();
1282     napi_value returnValue = nullptr;
1283     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1284     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1285     instance.GetCaptionsProperty(captionProperty);
1286     uint32_t color = captionProperty.GetBackgroundColor();
1287     std::string colorStr = ConvertColorToString(color);
1288     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1289     return returnValue;
1290 }
1291 
SetCaptionBackgroundColor(napi_env env, napi_callback_info info)1292 napi_value NAccessibilityClient::SetCaptionBackgroundColor(napi_env env, napi_callback_info info)
1293 {
1294     HILOG_INFO();
1295     size_t argc = ARGS_SIZE_ONE;
1296     napi_value parameters[ARGS_SIZE_ONE] = {0};
1297     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1298     if (argc >= ARGS_SIZE_ONE) {
1299         HILOG_DEBUG("SetCaptionBackgroundColor argc > 1");
1300         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1301         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1302         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1303         instance.GetCaptionsProperty(captionProperty);
1304         // Change the input info and then set the CaptionProperty
1305         captionProperty.SetBackgroundColor(color);
1306         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1307         if (ret != OHOS::Accessibility::RET_OK) {
1308             napi_value err = CreateBusinessError(env, ret);
1309             napi_throw(env, err);
1310         }
1311     } else {
1312         HILOG_ERROR("SetCaptionBackgroundColor argc size Error");
1313         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1314         napi_throw(env, err);
1315     }
1316     napi_value undefined = nullptr;
1317     napi_get_undefined(env, &undefined);
1318     return undefined;
1319 }
1320 
GetCaptionWindowColor(napi_env env, napi_callback_info info)1321 napi_value NAccessibilityClient::GetCaptionWindowColor(napi_env env, napi_callback_info info)
1322 {
1323     HILOG_INFO();
1324     napi_value returnValue = nullptr;
1325     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1326     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1327     instance.GetCaptionsProperty(captionProperty);
1328     uint32_t color = captionProperty.GetWindowColor();
1329     std::string colorStr = ConvertColorToString(color);
1330     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1331     return returnValue;
1332 }
1333 
SetCaptionWindowColor(napi_env env, napi_callback_info info)1334 napi_value NAccessibilityClient::SetCaptionWindowColor(napi_env env, napi_callback_info info)
1335 {
1336     HILOG_INFO();
1337     size_t argc = ARGS_SIZE_ONE;
1338     napi_value parameters[ARGS_SIZE_ONE] = {0};
1339     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1340     if (argc >= ARGS_SIZE_ONE) {
1341         HILOG_DEBUG("SetCaptionWindowColor argc > 1");
1342         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1343         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1344         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1345         instance.GetCaptionsProperty(captionProperty);
1346         // Change the input info and then set the CaptionProperty
1347         captionProperty.SetWindowColor(color);
1348         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1349         if (ret != OHOS::Accessibility::RET_OK) {
1350             napi_value err = CreateBusinessError(env, ret);
1351             napi_throw(env, err);
1352         }
1353     } else {
1354         HILOG_ERROR("SetCaptionWindowColor argc size Error");
1355         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1356         napi_throw(env, err);
1357     }
1358     napi_value undefined = nullptr;
1359     napi_get_undefined(env, &undefined);
1360     return undefined;
1361 }
1362 
SubscribeToFramework()1363 void StateListenerImpl::SubscribeToFramework()
1364 {
1365     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
1366     if (asaClient) {
1367         asaClient->SubscribeStateObserver(shared_from_this(), type_);
1368     }
1369 }
1370 
UnsubscribeFromFramework()1371 void StateListenerImpl::UnsubscribeFromFramework()
1372 {
1373     HILOG_INFO("UnsubscribeFromFramework");
1374     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
1375     if (asaClient) {
1376         asaClient->UnsubscribeStateObserver(shared_from_this(), type_);
1377     }
1378 }
1379 
OnStateChanged(const bool state)1380 void StateListenerImpl::OnStateChanged(const bool state)
1381 {
1382     HILOG_INFO();
1383     std::lock_guard<ffrt::mutex> lock(mutex_);
1384     for (auto &observer : observers_) {
1385         observer->OnStateChanged(state);
1386     }
1387 }
1388 
SubscribeObserver(napi_env env, napi_value observer)1389 void StateListenerImpl::SubscribeObserver(napi_env env, napi_value observer)
1390 {
1391     HILOG_INFO();
1392     std::lock_guard<ffrt::mutex> lock(mutex_);
1393     for (auto iter = observers_.begin(); iter != observers_.end();) {
1394         if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
1395             HILOG_DEBUG("SubscribeObserver Observer exist");
1396             return;
1397         } else {
1398             iter++;
1399         }
1400     }
1401 
1402     napi_ref ref;
1403     napi_create_reference(env, observer, 1, &ref);
1404     std::shared_ptr<StateListener> stateListener = std::make_shared<StateListener>(env, ref);
1405 
1406     observers_.emplace_back(stateListener);
1407     HILOG_INFO("observer size%{public}zu", observers_.size());
1408 }
1409 
UnsubscribeObserver(napi_env env, napi_value observer)1410 void StateListenerImpl::UnsubscribeObserver(napi_env env, napi_value observer)
1411 {
1412     HILOG_INFO();
1413     std::lock_guard<ffrt::mutex> lock(mutex_);
1414     for (auto iter = observers_.begin(); iter != observers_.end();) {
1415         if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
1416             observers_.erase(iter);
1417             return;
1418         } else {
1419             iter++;
1420         }
1421     }
1422 }
1423 
UnsubscribeObservers()1424 void StateListenerImpl::UnsubscribeObservers()
1425 {
1426     HILOG_INFO();
1427     std::lock_guard<ffrt::mutex> lock(mutex_);
1428     observers_.clear();
1429 }