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     std::shared_ptr<StateCallbackInfo> callbackInfo = std::make_shared<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     auto task = [callbackInfo]() {
760         if (callbackInfo == nullptr) {
761             return;
762         }
763 
764         napi_env tmpEnv = callbackInfo->env_;
765         auto closeScope = [tmpEnv](napi_handle_scope scope) {
766             napi_close_handle_scope(tmpEnv, scope);
767         };
768         std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(
769             OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope);
770         napi_value handler = nullptr;
771         napi_value callResult = nullptr;
772         napi_value jsEvent = nullptr;
773         napi_get_boolean(callbackInfo->env_, callbackInfo->state_, &jsEvent);
774         napi_get_reference_value(callbackInfo->env_, callbackInfo->ref_, &handler);
775         napi_value undefined = nullptr;
776         napi_get_undefined(callbackInfo->env_, &undefined);
777         napi_call_function(callbackInfo->env_, undefined, handler, 1, &jsEvent, &callResult);
778     };
779     if (napi_send_event(env, task, napi_eprio_high) != napi_status::napi_ok) {
780         HILOG_ERROR("failed to send event");
781     }
782 }
783 
OnStateChanged(const bool state)784 void StateListener::OnStateChanged(const bool state)
785 {
786     NotifyJS(env_, state, handlerRef_);
787 }
788 
DefineJSCaptionsManager(napi_env env)789 void NAccessibilityClient::DefineJSCaptionsManager(napi_env env)
790 {
791     napi_property_descriptor captionsManagerDesc[] = {
792         DECLARE_NAPI_GETTER_SETTER("enabled",
793             NAccessibilityClient::GetCaptionStateEnabled, NAccessibilityClient::SetCaptionStateEnabled),
794         DECLARE_NAPI_GETTER_SETTER("style",
795             NAccessibilityClient::GetCaptionStyle, NAccessibilityClient::SetCaptionStyle),
796         DECLARE_NAPI_FUNCTION("on", NAccessibilityClient::RegisterCaptionStateCallback),
797         DECLARE_NAPI_FUNCTION("off", NAccessibilityClient::DeregisterCaptionStateCallback),
798     };
799 
800     napi_value aaCons = nullptr;
801     NAPI_CALL_RETURN_VOID(env,
802         napi_define_class(env,
803             "CaptionsManager",
804             NAPI_AUTO_LENGTH,
805             NAccessibilityClient::AccessibleAbilityConstructor,
806             nullptr,
807             sizeof(captionsManagerDesc) / sizeof(captionsManagerDesc[0]),
808             captionsManagerDesc,
809             &aaCons));
810 
811     napi_create_reference(env, aaCons, 1, &NAccessibilityClient::aaConsRef_);
812 }
813 
AccessibleAbilityConstructor(napi_env env,napi_callback_info info)814 napi_value NAccessibilityClient::AccessibleAbilityConstructor(napi_env env, napi_callback_info info)
815 {
816     napi_value jsthis = nullptr;
817     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr));
818     return jsthis;
819 }
820 
821 
GetCaptionsManager(napi_env env,napi_callback_info info)822 napi_value NAccessibilityClient::GetCaptionsManager(napi_env env, napi_callback_info info)
823 {
824     HILOG_INFO();
825     napi_value result = 0;
826     napi_value aaCons = nullptr;
827     napi_get_reference_value(env, NAccessibilityClient::aaConsRef_, &aaCons);
828     napi_new_instance(env, aaCons, 0, nullptr, &result);
829     return result;
830 }
831 
SetCaptionStateEnabled(napi_env env,napi_callback_info info)832 napi_value NAccessibilityClient::SetCaptionStateEnabled(napi_env env, napi_callback_info info)
833 {
834     HILOG_INFO();
835     size_t argc = ARGS_SIZE_ONE;
836     napi_value parameters[ARGS_SIZE_ONE] = {0};
837     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
838     if (argc >= ARGS_SIZE_ONE) {
839         bool captionState = false;
840         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
841         if (!ParseBool(env, captionState, parameters[PARAM0])) {
842             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
843         } else {
844             HILOG_INFO("captionState = %{public}s", captionState ? "True" : "False");
845 
846             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
847             ret = instance.SetCaptionsState(captionState);
848         }
849         if (ret != OHOS::Accessibility::RET_OK) {
850             napi_value err = CreateBusinessError(env, ret);
851             napi_throw(env, err);
852         }
853     } else {
854         HILOG_ERROR("SetCaptionStateEnabled argc size Error");
855         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
856         napi_throw(env, err);
857     }
858 
859     napi_value undefined = nullptr;
860     napi_get_undefined(env, &undefined);
861     return undefined;
862 }
863 
GetCaptionStateEnabled(napi_env env,napi_callback_info info)864 napi_value NAccessibilityClient::GetCaptionStateEnabled(napi_env env, napi_callback_info info)
865 {
866     HILOG_INFO();
867     napi_value captionStateEnabled = nullptr;
868 
869     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
870     bool captionState = false;
871     instance.GetCaptionsState(captionState);
872     napi_get_boolean(env, captionState, &captionStateEnabled);
873 
874     HILOG_INFO("captionState = %{public}s", captionState ? "True" : "False");
875 
876     return captionStateEnabled;
877 }
878 
SetCaptionStyle(napi_env env,napi_callback_info info)879 napi_value NAccessibilityClient::SetCaptionStyle(napi_env env, napi_callback_info info)
880 {
881     HILOG_INFO();
882     size_t argc = ARGS_SIZE_ONE;
883     napi_value parameters[ARGS_SIZE_ONE] = {0};
884     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
885     if (argc >= ARGS_SIZE_ONE) {
886         OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
887         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
888         if (!ConvertObjToCaptionProperty(env, parameters[PARAM0], &captionProperty)) {
889             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
890         } else {
891             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
892             ret = instance.SetCaptionsProperty(captionProperty);
893         }
894         if (ret != OHOS::Accessibility::RET_OK) {
895             napi_value err = CreateBusinessError(env, ret);
896             napi_throw(env, err);
897         }
898     } else {
899         HILOG_ERROR("SetCaptionStyle argc size Error");
900         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
901         napi_throw(env, err);
902     }
903 
904     napi_value undefined = nullptr;
905     napi_get_undefined(env, &undefined);
906     return undefined;
907 }
908 
GetCaptionStyle(napi_env env,napi_callback_info info)909 napi_value NAccessibilityClient::GetCaptionStyle(napi_env env, napi_callback_info info)
910 {
911     HILOG_INFO();
912     napi_value captionStyle = nullptr;
913     napi_get_reference_value(env, NAccessibilityClient::aaStyleConsRef_, &captionStyle);
914 
915     return captionStyle;
916 }
917 
RegisterCaptionStateCallback(napi_env env,napi_callback_info info)918 napi_value NAccessibilityClient::RegisterCaptionStateCallback(napi_env env, napi_callback_info info)
919 {
920     HILOG_INFO();
921 
922     size_t argc = ARGS_SIZE_TWO;
923     napi_value args[ARGS_SIZE_TWO] = {0};
924     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
925     if (status != napi_ok) {
926         HILOG_ERROR("RegisterCaptionStateCallback Failed to get event type");
927         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_FAILED);
928         napi_throw(env, err);
929         return nullptr;
930     }
931 
932     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
933     if (argc < ARGS_SIZE_TWO) {
934         HILOG_ERROR("RegisterCaptionStateCallback argc is invalid: %{public}zu", argc);
935         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
936     }
937 
938     OHOS::AccessibilityConfig::CONFIG_ID type = OHOS::AccessibilityConfig::CONFIG_ID_MAX;
939     if (errCode == OHOS::Accessibility::RET_OK) {
940         std::string eventType = "";
941         if (!ParseString(env, eventType, args[PARAM0])) {
942             HILOG_ERROR("eventType type parse failed");
943             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
944         } else {
945             if (std::strcmp(eventType.c_str(), "enableChange") == 0) {
946                 type = OHOS::AccessibilityConfig::CONFIG_CAPTION_STATE;
947             } else if (std::strcmp(eventType.c_str(), "styleChange") == 0) {
948                 type =  OHOS::AccessibilityConfig::CONFIG_CAPTION_STYLE;
949             } else {
950                 HILOG_ERROR("SubscribeState eventType[%{public}s] is error", eventType.c_str());
951                 errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
952             }
953         }
954     }
955 
956     if (errCode == OHOS::Accessibility::RET_OK) {
957         napi_valuetype valueType = napi_null;
958         napi_typeof(env, args[PARAM1], &valueType);
959         if (valueType != napi_function) {
960             HILOG_ERROR("RegisterCaptionStateCallback args[PARAM1] format is wrong");
961             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
962         }
963     }
964 
965     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
966         napi_value err = CreateBusinessError(env, errCode);
967         HILOG_ERROR("invalid param");
968         napi_throw(env, err);
969         return nullptr;
970     }
971 
972     captionListeners_->SubscribeObserver(env, type, args[PARAM1]);
973 
974     return nullptr;
975 }
976 
DeregisterCaptionStateCallback(napi_env env,napi_callback_info info)977 napi_value NAccessibilityClient::DeregisterCaptionStateCallback(napi_env env, napi_callback_info info)
978 {
979     HILOG_INFO();
980     size_t argc = ARGS_SIZE_TWO;
981     napi_value args[ARGS_SIZE_TWO] = {0};
982     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
983 
984     OHOS::Accessibility::RetError errCode = OHOS::Accessibility::RET_OK;
985     if (argc < ARGS_SIZE_TWO - 1) {
986         HILOG_ERROR("DeregisterCaptionStateCallback argc is invalid: %{public}zu", argc);
987         errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
988     }
989 
990     OHOS::AccessibilityConfig::CONFIG_ID type = OHOS::AccessibilityConfig::CONFIG_ID_MAX;
991     if (errCode == OHOS::Accessibility::RET_OK) {
992         std::string eventType = "";
993         if (!ParseString(env, eventType, args[PARAM0])) {
994             HILOG_ERROR("eventType type parse failed");
995             errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
996         } else {
997             if (std::strcmp(eventType.c_str(), "enableChange") == 0) {
998                 type = OHOS::AccessibilityConfig::CONFIG_CAPTION_STATE;
999             } else if (std::strcmp(eventType.c_str(), "styleChange") == 0) {
1000                 type =  OHOS::AccessibilityConfig::CONFIG_CAPTION_STYLE;
1001             } else {
1002                 HILOG_ERROR("SubscribeState eventType[%{public}s] is error", eventType.c_str());
1003                 errCode = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1004             }
1005         }
1006     }
1007 
1008     if (errCode == OHOS::Accessibility::RET_ERR_INVALID_PARAM) {
1009         napi_value err = CreateBusinessError(env, errCode);
1010         HILOG_ERROR("DeregisterCaptionStateCallback invalid param");
1011         napi_throw(env, err);
1012         return nullptr;
1013     }
1014 
1015     if (argc >= ARGS_SIZE_TWO && CheckJsFunction(env, args[PARAM1])) {
1016         captionListeners_->UnsubscribeObserver(env, type, args[PARAM1]);
1017     } else {
1018         captionListeners_->UnsubscribeObservers(type);
1019     }
1020 
1021     return nullptr;
1022 }
1023 
DefineJSCaptionsStyle(napi_env env)1024 void NAccessibilityClient::DefineJSCaptionsStyle(napi_env env)
1025 {
1026     napi_property_descriptor captionsStyleDesc[] = {
1027         DECLARE_NAPI_GETTER_SETTER("fontFamily",
1028             NAccessibilityClient::GetCaptionsFontFamily, NAccessibilityClient::SetCaptionsFontFamily),
1029         DECLARE_NAPI_GETTER_SETTER("fontScale",
1030             NAccessibilityClient::GetCaptionsFontScale, NAccessibilityClient::SetCaptionsFontScale),
1031         DECLARE_NAPI_GETTER_SETTER("fontColor",
1032             NAccessibilityClient::GetCaptionFrontColor, NAccessibilityClient::SetCaptionFrontColor),
1033         DECLARE_NAPI_GETTER_SETTER("fontEdgeType",
1034             NAccessibilityClient::GetCaptionFontEdgeType, NAccessibilityClient::SetCaptionFontEdgeType),
1035         DECLARE_NAPI_GETTER_SETTER("backgroundColor",
1036             NAccessibilityClient::GetCaptionBackgroundColor, NAccessibilityClient::SetCaptionBackgroundColor),
1037         DECLARE_NAPI_GETTER_SETTER("windowColor",
1038             NAccessibilityClient::GetCaptionWindowColor, NAccessibilityClient::SetCaptionWindowColor),
1039     };
1040 
1041     napi_value aaStyleCons = nullptr;
1042     napi_value captionStyle = nullptr;
1043 
1044     NAPI_CALL_RETURN_VOID(env,
1045         napi_define_class(env,
1046             "CaptionsStyle",
1047             NAPI_AUTO_LENGTH,
1048             NAccessibilityClient::AccessibleAbilityConstructorStyle,
1049             nullptr,
1050             sizeof(captionsStyleDesc) / sizeof(captionsStyleDesc[0]),
1051             captionsStyleDesc,
1052             &aaStyleCons));
1053 
1054     napi_new_instance(env, aaStyleCons, 0, nullptr, &captionStyle);
1055     napi_create_reference(env, captionStyle, 1, &NAccessibilityClient::aaStyleConsRef_);
1056 }
1057 
AccessibleAbilityConstructorStyle(napi_env env,napi_callback_info info)1058 napi_value NAccessibilityClient::AccessibleAbilityConstructorStyle(napi_env env, napi_callback_info info)
1059 {
1060     HILOG_INFO();
1061     napi_value jsthis = nullptr;
1062     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr));
1063     return jsthis;
1064 }
1065 
GetCaptionsFontFamily(napi_env env,napi_callback_info info)1066 napi_value NAccessibilityClient::GetCaptionsFontFamily(napi_env env, napi_callback_info info)
1067 {
1068     HILOG_INFO();
1069     napi_value returnValue = nullptr;
1070     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1071     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1072     instance.GetCaptionsProperty(captionProperty);
1073     napi_create_string_utf8(env, captionProperty.GetFontFamily().c_str(), NAPI_AUTO_LENGTH, &returnValue);
1074     return returnValue;
1075 }
1076 
SetCaptionsFontFamily(napi_env env,napi_callback_info info)1077 napi_value NAccessibilityClient::SetCaptionsFontFamily(napi_env env, napi_callback_info info)
1078 {
1079     HILOG_INFO();
1080     size_t argc = ARGS_SIZE_ONE;
1081     napi_value parameters[ARGS_SIZE_ONE] = {0};
1082     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1083     if (argc >= ARGS_SIZE_ONE) {
1084         // Get input FontFamily
1085         std::string fontFamily = "";
1086         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1087         if (ParseString(env, fontFamily, parameters[PARAM0]) && fontFamily.length() > 0) {
1088             HILOG_INFO("FontFamily = %{public}s", fontFamily.c_str());
1089             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1090             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1091             instance.GetCaptionsProperty(captionProperty);
1092             // Change the input info and then set the CaptionProperty
1093             captionProperty.SetFontFamily(std::string(fontFamily));
1094             ret = instance.SetCaptionsProperty(captionProperty);
1095         } else {
1096             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1097         }
1098         if (ret != OHOS::Accessibility::RET_OK) {
1099             napi_value err = CreateBusinessError(env, ret);
1100             napi_throw(env, err);
1101         }
1102     } else {
1103         HILOG_ERROR("SetCaptionsFontFamily argc size Error");
1104         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1105         napi_throw(env, err);
1106     }
1107     napi_value undefined = nullptr;
1108     napi_get_undefined(env, &undefined);
1109     return undefined;
1110 }
1111 
GetCaptionsFontScale(napi_env env,napi_callback_info info)1112 napi_value NAccessibilityClient::GetCaptionsFontScale(napi_env env, napi_callback_info info)
1113 {
1114     HILOG_INFO();
1115     napi_value returnValue = nullptr;
1116     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1117     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1118     instance.GetCaptionsProperty(captionProperty);
1119     napi_create_int32(env, captionProperty.GetFontScale(), &returnValue);
1120     return returnValue;
1121 }
1122 
SetCaptionsFontScale(napi_env env,napi_callback_info info)1123 napi_value NAccessibilityClient::SetCaptionsFontScale(napi_env env, napi_callback_info info)
1124 {
1125     HILOG_INFO();
1126     size_t argc = ARGS_SIZE_ONE;
1127     napi_value parameters[ARGS_SIZE_ONE] = {0};
1128     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1129     if (argc >= ARGS_SIZE_ONE) {
1130         // Get input FontScale
1131         int32_t num = 100;
1132         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1133         if (ParseInt32(env, num, parameters[PARAM0])) {
1134             HILOG_INFO("FontScale = %{public}d", num);
1135             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1136             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1137             instance.GetCaptionsProperty(captionProperty);
1138             // Change the input info and then set the CaptionProperty
1139             captionProperty.SetFontScale(num);
1140             ret = instance.SetCaptionsProperty(captionProperty);
1141         } else {
1142             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1143         }
1144         if (ret != OHOS::Accessibility::RET_OK) {
1145             napi_value err = CreateBusinessError(env, ret);
1146             napi_throw(env, err);
1147         }
1148     } else {
1149         HILOG_ERROR("SetCaptionsFontScale argc size Error");
1150         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1151         napi_throw(env, err);
1152     }
1153     napi_value undefined = nullptr;
1154     napi_get_undefined(env, &undefined);
1155     return undefined;
1156 }
1157 
GetCaptionFrontColor(napi_env env,napi_callback_info info)1158 napi_value NAccessibilityClient::GetCaptionFrontColor(napi_env env, napi_callback_info info)
1159 {
1160     HILOG_INFO();
1161     napi_value returnValue = nullptr;
1162     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1163     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1164     instance.GetCaptionsProperty(captionProperty);
1165     uint32_t color = captionProperty.GetFontColor();
1166     std::string colorStr = ConvertColorToString(color);
1167     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1168     return returnValue;
1169 }
1170 
SetCaptionFrontColor(napi_env env,napi_callback_info info)1171 napi_value NAccessibilityClient::SetCaptionFrontColor(napi_env env, napi_callback_info info)
1172 {
1173     HILOG_INFO();
1174     size_t argc = ARGS_SIZE_ONE;
1175     napi_value parameters[ARGS_SIZE_ONE] = {0};
1176     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1177     if (argc >= ARGS_SIZE_ONE) {
1178         HILOG_DEBUG("SetCaptionFrontColor argc > 1");
1179         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1180         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1181         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1182         instance.GetCaptionsProperty(captionProperty);
1183         // Change the input info and then set the CaptionProperty
1184         captionProperty.SetFontColor(color);
1185         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1186         if (ret != OHOS::Accessibility::RET_OK) {
1187             napi_value err = CreateBusinessError(env, ret);
1188             napi_throw(env, err);
1189         }
1190     } else {
1191         HILOG_ERROR("SetCaptionFrontColor argc size Error");
1192         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1193         napi_throw(env, err);
1194     }
1195     napi_value undefined = nullptr;
1196     napi_get_undefined(env, &undefined);
1197     return undefined;
1198 }
1199 
GetCaptionFontEdgeType(napi_env env,napi_callback_info info)1200 napi_value NAccessibilityClient::GetCaptionFontEdgeType(napi_env env, napi_callback_info info)
1201 {
1202     HILOG_INFO();
1203     napi_value returnValue = nullptr;
1204     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1205     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1206     instance.GetCaptionsProperty(captionProperty);
1207     napi_create_string_utf8(env, captionProperty.GetFontEdgeType().c_str(), NAPI_AUTO_LENGTH, &returnValue);
1208     return returnValue;
1209 }
1210 
SetCaptionFontEdgeType(napi_env env,napi_callback_info info)1211 napi_value NAccessibilityClient::SetCaptionFontEdgeType(napi_env env, napi_callback_info info)
1212 {
1213     HILOG_INFO();
1214     size_t argc = ARGS_SIZE_ONE;
1215     napi_value parameters[ARGS_SIZE_ONE] = {0};
1216 
1217     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1218     if (argc >= ARGS_SIZE_ONE) {
1219         // Get input FontEdgeType
1220         std::string fontEdgeType = "";
1221         OHOS::Accessibility::RetError ret = OHOS::Accessibility::RET_OK;
1222         if (ParseString(env, fontEdgeType, parameters[PARAM0]) && fontEdgeType.length() > 0) {
1223             HILOG_INFO("fontEdgeType = %{public}s", fontEdgeType.c_str());
1224             auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1225             OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1226             instance.GetCaptionsProperty(captionProperty);
1227             // Change the input info and then set the CaptionProperty
1228             captionProperty.SetFontEdgeType(std::string(fontEdgeType));
1229             ret = instance.SetCaptionsProperty(captionProperty);
1230         } else {
1231             ret = OHOS::Accessibility::RET_ERR_INVALID_PARAM;
1232         }
1233         if (ret != OHOS::Accessibility::RET_OK) {
1234             napi_value err = CreateBusinessError(env, ret);
1235             napi_throw(env, err);
1236         }
1237     } else {
1238         HILOG_ERROR("SetCaptionFontEdgeType argc size Error");
1239         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1240         napi_throw(env, err);
1241     }
1242     napi_value undefined = nullptr;
1243     napi_get_undefined(env, &undefined);
1244     return undefined;
1245 }
1246 
GetCaptionBackgroundColor(napi_env env,napi_callback_info info)1247 napi_value NAccessibilityClient::GetCaptionBackgroundColor(napi_env env, napi_callback_info info)
1248 {
1249     HILOG_INFO();
1250     napi_value returnValue = nullptr;
1251     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1252     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1253     instance.GetCaptionsProperty(captionProperty);
1254     uint32_t color = captionProperty.GetBackgroundColor();
1255     std::string colorStr = ConvertColorToString(color);
1256     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1257     return returnValue;
1258 }
1259 
SetCaptionBackgroundColor(napi_env env,napi_callback_info info)1260 napi_value NAccessibilityClient::SetCaptionBackgroundColor(napi_env env, napi_callback_info info)
1261 {
1262     HILOG_INFO();
1263     size_t argc = ARGS_SIZE_ONE;
1264     napi_value parameters[ARGS_SIZE_ONE] = {0};
1265     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1266     if (argc >= ARGS_SIZE_ONE) {
1267         HILOG_DEBUG("SetCaptionBackgroundColor argc > 1");
1268         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1269         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1270         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1271         instance.GetCaptionsProperty(captionProperty);
1272         // Change the input info and then set the CaptionProperty
1273         captionProperty.SetBackgroundColor(color);
1274         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1275         if (ret != OHOS::Accessibility::RET_OK) {
1276             napi_value err = CreateBusinessError(env, ret);
1277             napi_throw(env, err);
1278         }
1279     } else {
1280         HILOG_ERROR("SetCaptionBackgroundColor argc size Error");
1281         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1282         napi_throw(env, err);
1283     }
1284     napi_value undefined = nullptr;
1285     napi_get_undefined(env, &undefined);
1286     return undefined;
1287 }
1288 
GetCaptionWindowColor(napi_env env,napi_callback_info info)1289 napi_value NAccessibilityClient::GetCaptionWindowColor(napi_env env, napi_callback_info info)
1290 {
1291     HILOG_INFO();
1292     napi_value returnValue = nullptr;
1293     auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1294     OHOS::AccessibilityConfig::CaptionProperty captionProperty = {};
1295     instance.GetCaptionsProperty(captionProperty);
1296     uint32_t color = captionProperty.GetWindowColor();
1297     std::string colorStr = ConvertColorToString(color);
1298     napi_create_string_utf8(env, colorStr.c_str(), NAPI_AUTO_LENGTH, &returnValue);
1299     return returnValue;
1300 }
1301 
SetCaptionWindowColor(napi_env env,napi_callback_info info)1302 napi_value NAccessibilityClient::SetCaptionWindowColor(napi_env env, napi_callback_info info)
1303 {
1304     HILOG_INFO();
1305     size_t argc = ARGS_SIZE_ONE;
1306     napi_value parameters[ARGS_SIZE_ONE] = {0};
1307     napi_get_cb_info(env, info, &argc, parameters, nullptr, nullptr);
1308     if (argc >= ARGS_SIZE_ONE) {
1309         HILOG_DEBUG("SetCaptionWindowColor argc > 1");
1310         uint32_t color = GetColorValue(env, parameters[PARAM0]);
1311         auto &instance = OHOS::AccessibilityConfig::AccessibilityConfig::GetInstance();
1312         OHOS::AccessibilityConfig::CaptionProperty captionProperty {};
1313         instance.GetCaptionsProperty(captionProperty);
1314         // Change the input info and then set the CaptionProperty
1315         captionProperty.SetWindowColor(color);
1316         OHOS::Accessibility::RetError ret = instance.SetCaptionsProperty(captionProperty);
1317         if (ret != OHOS::Accessibility::RET_OK) {
1318             napi_value err = CreateBusinessError(env, ret);
1319             napi_throw(env, err);
1320         }
1321     } else {
1322         HILOG_ERROR("SetCaptionWindowColor argc size Error");
1323         napi_value err = CreateBusinessError(env, OHOS::Accessibility::RET_ERR_INVALID_PARAM);
1324         napi_throw(env, err);
1325     }
1326     napi_value undefined = nullptr;
1327     napi_get_undefined(env, &undefined);
1328     return undefined;
1329 }
1330 
SubscribeToFramework()1331 void StateListenerImpl::SubscribeToFramework()
1332 {
1333     auto asaClient = AccessibilitySystemAbilityClient::GetInstance();
1334     if (asaClient) {
1335         asaClient->SubscribeStateObserver(shared_from_this(), type_);
1336     }
1337 }
1338 
OnStateChanged(const bool state)1339 void StateListenerImpl::OnStateChanged(const bool state)
1340 {
1341     HILOG_INFO();
1342     std::lock_guard<ffrt::mutex> lock(mutex_);
1343     for (auto &observer : observers_) {
1344         observer->OnStateChanged(state);
1345     }
1346 }
1347 
DeleteObserverReference(napi_env env,std::shared_ptr<StateListener> observer)1348 void StateListenerImpl::DeleteObserverReference(napi_env env, std::shared_ptr<StateListener> observer)
1349 {
1350     if (observer == nullptr) {
1351         return;
1352     }
1353     std::shared_ptr<AccessibilityCallbackInfo> callbackInfo =
1354         std::make_shared<AccessibilityCallbackInfo>();
1355     if (callbackInfo == nullptr) {
1356         HILOG_ERROR("failed to create callbackInfo");
1357         return;
1358     }
1359     callbackInfo->env_ = observer->env_;
1360     callbackInfo->ref_ = observer->handlerRef_;
1361     auto task = [callbackInfo]() {
1362         if (callbackInfo == nullptr) {
1363             return;
1364         }
1365         napi_env tmpEnv = callbackInfo->env_;
1366         auto closeScope = [tmpEnv](napi_handle_scope scope) {
1367             napi_close_handle_scope(tmpEnv, scope);
1368         };
1369         std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(
1370             OHOS::Accessibility::TmpOpenScope(callbackInfo->env_), closeScope);
1371         napi_delete_reference(tmpEnv, callbackInfo->ref_);
1372     };
1373     if (napi_send_event(env, task, napi_eprio_high) != napi_status::napi_ok) {
1374         HILOG_ERROR("failed to send event");
1375     }
1376 }
1377 
SubscribeObserver(napi_env env,napi_value observer)1378 void StateListenerImpl::SubscribeObserver(napi_env env, napi_value observer)
1379 {
1380     HILOG_INFO();
1381     std::lock_guard<ffrt::mutex> lock(mutex_);
1382     for (auto iter = observers_.begin(); iter != observers_.end();) {
1383         if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
1384             HILOG_DEBUG("SubscribeObserver Observer exist");
1385             return;
1386         } else {
1387             iter++;
1388         }
1389     }
1390 
1391     napi_ref ref;
1392     napi_create_reference(env, observer, 1, &ref);
1393     std::shared_ptr<StateListener> stateListener = std::make_shared<StateListener>(env, ref);
1394 
1395     observers_.emplace_back(stateListener);
1396     HILOG_INFO("observer size%{public}zu", observers_.size());
1397 }
1398 
UnsubscribeObserver(napi_env env,napi_value observer)1399 void StateListenerImpl::UnsubscribeObserver(napi_env env, napi_value observer)
1400 {
1401     HILOG_INFO();
1402     std::lock_guard<ffrt::mutex> lock(mutex_);
1403     for (auto iter = observers_.begin(); iter != observers_.end();) {
1404         if (CheckObserverEqual(env, observer, (*iter)->env_, (*iter)->handlerRef_)) {
1405             DeleteObserverReference(env, *iter);
1406             observers_.erase(iter);
1407             return;
1408         } else {
1409             iter++;
1410         }
1411     }
1412 }
1413 
UnsubscribeObservers()1414 void StateListenerImpl::UnsubscribeObservers()
1415 {
1416     HILOG_INFO();
1417     std::lock_guard<ffrt::mutex> lock(mutex_);
1418     for (auto iter = observers_.begin(); iter != observers_.end();) {
1419         DeleteObserverReference((*iter)->env_, *iter);
1420         observers_.erase(iter);
1421     }
1422     observers_.clear();
1423 }