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_extension_context.h"
17 
18 #include <uv.h>
19 #include "display_manager.h"
20 #include "js_extension_context.h"
21 #include "js_runtime_utils.h"
22 #include "hilog_wrapper.h"
23 #include "napi_accessibility_element.h"
24 #include "accessibility_utils.h"
25 #include "napi_common_want.h"
26 #include "napi_common_start_options.h"
27 
28 using namespace OHOS::AbilityRuntime;
29 using namespace OHOS::AccessibilityNapi;
30 
31 namespace OHOS {
32 namespace Accessibility {
33 namespace {
ConvertAccessibilityWindowInfoToJS(napi_env env,napi_value result,const AccessibilityWindowInfo & accessibilityWindowInfo)34 static void ConvertAccessibilityWindowInfoToJS(
35     napi_env env, napi_value result, const AccessibilityWindowInfo& accessibilityWindowInfo)
36 {
37     // Bind js object to a Native object
38     std::shared_ptr<AccessibilityWindowInfo> windowInfo =
39         std::make_shared<AccessibilityWindowInfo>(accessibilityWindowInfo);
40     AccessibilityElement* pAccessibilityElement = new(std::nothrow) AccessibilityElement(windowInfo);
41     if (pAccessibilityElement == nullptr) {
42         HILOG_ERROR("Failed to create work.");
43         return;
44     }
45 
46     napi_status sts = napi_wrap(
47         env,
48         result,
49         pAccessibilityElement,
50         [](napi_env env, void* data, void* hint) {
51             AccessibilityElement* info = static_cast<AccessibilityElement*>(data);
52             delete info;
53             info = nullptr;
54         },
55         nullptr,
56         nullptr);
57     if (sts != napi_ok) {
58         delete pAccessibilityElement;
59         pAccessibilityElement = nullptr;
60         HILOG_ERROR("failed to wrap JS object");
61     }
62     HILOG_DEBUG("napi_wrap status: %{public}d", (int)sts);
63 }
64 
ConvertAccessibilityWindowInfosToJS(napi_env env,napi_value result,const std::vector<AccessibilityWindowInfo> & accessibilityWindowInfos)65 static void ConvertAccessibilityWindowInfosToJS(
66     napi_env env, napi_value result, const std::vector<AccessibilityWindowInfo>& accessibilityWindowInfos)
67 {
68     HILOG_DEBUG();
69     size_t idx = 0;
70 
71     if (accessibilityWindowInfos.empty()) {
72         return;
73     }
74     napi_value constructor = nullptr;
75     napi_get_reference_value(env, NAccessibilityElement::consRef_, &constructor);
76 
77     for (const auto& windowInfo : accessibilityWindowInfos) {
78         napi_value obj = nullptr;
79         napi_new_instance(env, constructor, 0, nullptr, &obj);
80         ConvertAccessibilityWindowInfoToJS(env, obj, windowInfo);
81         napi_set_element(env, result, idx, obj);
82         idx++;
83     }
84 }
85 
IsNapiFunction(napi_env env,napi_value param)86 static bool IsNapiFunction(napi_env env, napi_value param)
87 {
88     napi_valuetype valueType = napi_null;
89     napi_status status = napi_typeof(env, param, &valueType);
90     if (status != napi_ok) {
91         HILOG_ERROR("napi_typeof error and status is %{public}d", status);
92         return false;
93     }
94 
95     if (valueType != napi_function) {
96         HILOG_ERROR("SubscribeState args[PARAM1] format is wrong");
97         return false;
98     }
99     return true;
100 }
101 
IsNapiBool(napi_env env,napi_value param)102 static bool IsNapiBool(napi_env env, napi_value param)
103 {
104     napi_valuetype valuetype = napi_null;
105     napi_status status = napi_typeof(env, param, &valuetype);
106     if (status != napi_ok) {
107         HILOG_ERROR("napi_typeof error and status is %{public}d", status);
108         return false;
109     }
110 
111     if (valuetype != napi_boolean) {
112         HILOG_ERROR("Wrong argument type. Boolean expected.");
113         return false;
114     }
115     return true;
116 }
117 
IsNapiNumber(napi_env env,napi_value param)118 static bool IsNapiNumber(napi_env env, napi_value param)
119 {
120     napi_valuetype valuetype = napi_null;
121     napi_status status = napi_typeof(env, param, &valuetype);
122     if (status != napi_ok) {
123         HILOG_ERROR("napi_typeof error and status is %{public}d", status);
124         return false;
125     }
126 
127     if (valuetype != napi_number) {
128         HILOG_ERROR("Wrong argument type. uint32 expected.");
129         return false;
130     }
131     return true;
132 }
133 
GetLastParamForTwo(napi_env env,NapiCallbackInfo & info,napi_value & lastParam,bool & isAccessibilityFocus)134 static void GetLastParamForTwo(napi_env env, NapiCallbackInfo& info, napi_value& lastParam,
135     bool& isAccessibilityFocus)
136 {
137     if (info.argv[PARAM0] != nullptr && info.argv[PARAM1] != nullptr &&
138         IsNapiBool(env, info.argv[PARAM0]) && IsNapiFunction(env, info.argv[PARAM1])) {
139         lastParam = ConvertFromJsValue(env, info.argv[PARAM0], isAccessibilityFocus) ?
140             info.argv[PARAM1] : nullptr;
141     } else if (info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) {
142         HILOG_INFO("argc is more than two, use callback: situation 1");
143         lastParam = info.argv[PARAM1];
144     } else if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
145         HILOG_INFO("argc is more than two, use callback: situation 2");
146         lastParam = info.argv[PARAM0];
147     } else if (info.argv[PARAM0] != nullptr && IsNapiBool(env, info.argv[PARAM0])) {
148         HILOG_INFO("argc is more than two, use promise: situation 3");
149         lastParam = nullptr;
150         ConvertFromJsValue(env, info.argv[PARAM0], isAccessibilityFocus);
151     } else {
152         lastParam = nullptr;
153         HILOG_INFO("argc is more than two, use promise");
154     }
155 }
156 
CheckStartAbilityInputParam(napi_env env,NapiCallbackInfo & info,AAFwk::Want & want)157 static bool CheckStartAbilityInputParam(napi_env env, NapiCallbackInfo& info,
158     AAFwk::Want& want)
159 {
160     if (info.argc < ARGS_SIZE_ONE) {
161         return false;
162     }
163     if (!AppExecFwk::UnwrapWant(env, info.argv[PARAM0], want)) {
164         return false;
165     }
166     if (!want.HasParameter(Want::PARAM_BACK_TO_OTHER_MISSION_STACK)) {
167         want.SetParam(Want::PARAM_BACK_TO_OTHER_MISSION_STACK, true);
168     }
169     return true;
170 }
171 
172 class NAccessibilityExtensionContext final {
173 public:
NAccessibilityExtensionContext(const std::shared_ptr<AccessibilityExtensionContext> & context)174     explicit NAccessibilityExtensionContext(
175         const std::shared_ptr<AccessibilityExtensionContext>& context) : context_(context) {}
176     ~NAccessibilityExtensionContext() = default;
177 
Finalizer(napi_env env,void * data,void * hint)178     static void Finalizer(napi_env env, void* data, void* hint)
179     {
180         HILOG_INFO();
181         std::unique_ptr<NAccessibilityExtensionContext>(static_cast<NAccessibilityExtensionContext*>(data));
182     }
183 
SetTargetBundleName(napi_env env,napi_callback_info info)184     static napi_value SetTargetBundleName(napi_env env, napi_callback_info info)
185     {
186         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnSetTargetBundleName);
187     }
188 
GetFocusElement(napi_env env,napi_callback_info info)189     static napi_value GetFocusElement(napi_env env, napi_callback_info info)
190     {
191         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnGetFocusElement);
192     }
193 
GetWindowRootElement(napi_env env,napi_callback_info info)194     static napi_value GetWindowRootElement(napi_env env, napi_callback_info info)
195     {
196         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnGetWindowRootElement);
197     }
198 
GetWindows(napi_env env,napi_callback_info info)199     static napi_value GetWindows(napi_env env, napi_callback_info info)
200     {
201         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnGetWindows);
202     }
203 
InjectGesture(napi_env env,napi_callback_info info)204     static napi_value InjectGesture(napi_env env, napi_callback_info info)
205     {
206         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnGestureInject);
207     }
208 
InjectGestureSync(napi_env env,napi_callback_info info)209     static napi_value InjectGestureSync(napi_env env, napi_callback_info info)
210     {
211         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnGestureInjectSync);
212     }
213 
StartAbility(napi_env env,napi_callback_info info)214     static napi_value StartAbility(napi_env env, napi_callback_info info)
215     {
216         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnStartAbility);
217     }
218 
EnableScreenCurtain(napi_env env,napi_callback_info info)219     static napi_value EnableScreenCurtain(napi_env env, napi_callback_info info)
220     {
221         GET_NAPI_INFO_AND_CALL(env, info, NAccessibilityExtensionContext, OnEnableScreenCurtain);
222     }
223 
224 private:
225     std::weak_ptr<AccessibilityExtensionContext> context_;
226 
OnSetTargetBundleName(napi_env env,NapiCallbackInfo & info)227     napi_value OnSetTargetBundleName(napi_env env, NapiCallbackInfo& info)
228     {
229         HILOG_INFO();
230         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
231         if (info.argc < ARGS_SIZE_ONE) {
232             HILOG_ERROR("Not enough params");
233             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
234         }
235 
236         std::vector<std::string> targetBundleNames;
237         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
238             if (ConvertJSToStringVec(env, info.argv[PARAM0], targetBundleNames)) {
239                 HILOG_INFO("targetBundleNames's size = %{public}zu", targetBundleNames.size());
240             } else {
241                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
242             }
243         }
244 
245         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
246             HILOG_ERROR("invalid param");
247             napi_throw(env, CreateJsError(env,
248                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
249                 ERROR_MESSAGE_PARAMETER_ERROR));
250             return CreateJsUndefined(env);
251         }
252 
253         return SetTargetBundleNameCompleteTask(env, targetBundleNames, info);
254     }
255 
SetTargetBundleNameCompleteTask(napi_env env,std::vector<std::string> targetBundleNames,NapiCallbackInfo & info)256     napi_value SetTargetBundleNameCompleteTask(napi_env env, std::vector<std::string> targetBundleNames,
257         NapiCallbackInfo& info)
258         {
259         auto ret = std::make_shared<RetError>(RET_OK);
260         NapiAsyncTask::ExecuteCallback execute = [weak = context_, targetBundleNames, ret] () {
261             HILOG_INFO("SetTargetBundleName begin");
262             auto context = weak.lock();
263             if (!context) {
264                 HILOG_ERROR("context is released");
265                 *ret = RET_ERR_FAILED;
266                 return;
267             }
268 
269             *ret = context->SetTargetBundleName(targetBundleNames);
270         };
271         NapiAsyncTask::CompleteCallback complete =
272             [ret](napi_env env, NapiAsyncTask& task, int32_t status) {
273             if (*ret == RET_OK) {
274                 task.Resolve(env, CreateJsUndefined(env));
275             } else {
276                 HILOG_ERROR("set target bundle name failed. ret: %{public}d.", *ret);
277                 task.Reject(env, CreateJsError(env,
278                     static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
279                     ERROR_MESSAGE_SYSTEM_ABNORMALITY));
280             }
281         };
282 
283         napi_value lastParam = (info.argc == ARGS_SIZE_ONE) ? nullptr :
284             ((info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) ? info.argv[PARAM1] : nullptr);
285         napi_value result = nullptr;
286         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::OnSetTargetBundleName",
287             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
288         return result;
289     }
290 
OnGetFocusElement(napi_env env,NapiCallbackInfo & info)291     napi_value OnGetFocusElement(napi_env env, NapiCallbackInfo& info)
292     {
293         HILOG_INFO();
294         bool isAccessibilityFocus = false;
295         napi_value lastParam = nullptr;
296         if (info.argc >= ARGS_SIZE_TWO) {
297             GetLastParamForTwo(env, info, lastParam, isAccessibilityFocus);
298         } else if (info.argc == ARGS_SIZE_ONE) {
299             if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
300                 lastParam = info.argv[PARAM0];
301             } else {
302                 if (info.argv[PARAM0] != nullptr && IsNapiBool(env, info.argv[PARAM0])) {
303                     ConvertFromJsValue(env, info.argv[PARAM0], isAccessibilityFocus);
304                 }
305                 lastParam = nullptr;
306                 HILOG_INFO("argc is one, use promise");
307             }
308         } else {
309             lastParam = nullptr;
310             HILOG_INFO("argc is others, use promise");
311         }
312 
313         int32_t focus = isAccessibilityFocus ? FOCUS_TYPE_ACCESSIBILITY : FOCUS_TYPE_INPUT;
314         HILOG_DEBUG("focus type is [%{public}d]", focus);
315         return GetFoucusElementCompleteTask(env, focus, lastParam);
316     }
317 
GetFoucusElementCompleteTask(napi_env env,int32_t focus,napi_value lastParam)318     napi_value GetFoucusElementCompleteTask(napi_env env, int32_t focus, napi_value lastParam)
319     {
320         auto elementInfo = std::make_shared<OHOS::Accessibility::AccessibilityElementInfo>();
321         auto ret = std::make_shared<RetError>(RET_OK);
322         NapiAsyncTask::ExecuteCallback execute = [weak = context_, elementInfo, focus, ret] () {
323             HILOG_INFO("GetFoucusElement begin");
324             auto context = weak.lock();
325             if (!context) {
326                 HILOG_ERROR("context is released");
327                 *ret = RET_ERR_FAILED;
328                 return;
329             }
330 
331             *ret = context->GetFocus(focus, *elementInfo);
332         };
333         NapiAsyncTask::CompleteCallback complete =
334             [ret, elementInfo](napi_env env, NapiAsyncTask& task, int32_t status) {
335             if (*ret == RET_OK) {
336                 napi_value constructor = nullptr;
337                 napi_get_reference_value(env, NAccessibilityElement::consRef_, &constructor);
338                 napi_value napiElementInfo = nullptr;
339                 napi_new_instance(env, constructor, 0, nullptr, &napiElementInfo);
340                 NAccessibilityElement::ConvertElementInfoToJS(env, napiElementInfo, *elementInfo);
341                 task.Resolve(env, napiElementInfo);
342             } else {
343                 HILOG_ERROR("Get focus elementInfo failed. ret: %{public}d", *ret);
344                 task.Reject(env, CreateJsError(env,
345                     static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
346                     ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
347             }
348         };
349 
350         napi_value result = nullptr;
351         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::OnGetFocusElement",
352             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
353         return result;
354     }
355 
OnGetWindowRootElement(napi_env env,NapiCallbackInfo & info)356     napi_value OnGetWindowRootElement(napi_env env, NapiCallbackInfo& info)
357     {
358         HILOG_INFO();
359         int32_t windowId = INVALID_WINDOW_ID;
360         bool isActiveWindow = true;
361         napi_value lastParam = nullptr;
362         if (info.argc >= ARGS_SIZE_TWO) {
363             if (info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) {
364                 HILOG_INFO("argc is more than two, use callback: situation 1");
365                 lastParam = info.argv[PARAM1];
366             } else if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
367                 HILOG_INFO("argc is more than two, use callback: situation 2");
368                 lastParam = info.argv[PARAM0];
369             } else {
370                 lastParam = nullptr;
371                 HILOG_INFO("argc is two, use promise");
372             }
373             if (info.argv[PARAM0] != nullptr && IsNapiNumber(env, info.argv[PARAM0])) {
374                 HILOG_INFO("argc is more than two, use promise: situation 3");
375                 isActiveWindow = !ConvertFromJsValue(env, info.argv[PARAM0], windowId);
376             }
377         } else if (info.argc == ARGS_SIZE_ONE) {
378             if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
379                 lastParam = info.argv[PARAM0];
380             } else if (info.argv[PARAM0] != nullptr && IsNapiNumber(env, info.argv[PARAM0])) {
381                 isActiveWindow = !ConvertFromJsValue(env, info.argv[PARAM0], windowId);
382                 lastParam = nullptr;
383                 HILOG_INFO("argc is one, use promise");
384             }
385         } else {
386             lastParam = nullptr;
387             HILOG_INFO("argc is others, use promise");
388         }
389         return GetWindowRootElementCompleteTask(env, windowId, isActiveWindow, lastParam);
390     }
391 
GetWindowRootElementCompleteTask(napi_env env,int32_t windowId,bool isActiveWindow,napi_value lastParam)392     napi_value GetWindowRootElementCompleteTask(
393         napi_env env, int32_t windowId, bool isActiveWindow, napi_value lastParam)
394     {
395         auto elementInfo = std::make_shared<OHOS::Accessibility::AccessibilityElementInfo>();
396         auto ret = std::make_shared<RetError>(RET_OK);
397         NapiAsyncTask::ExecuteCallback execute = [weak = context_, isActiveWindow, windowId, elementInfo, ret] () {
398             HILOG_INFO("GetWindowRootElement begin");
399             auto context = weak.lock();
400             if (!context) {
401                 HILOG_ERROR("context is released");
402                 *ret = RET_ERR_FAILED;
403                 return;
404             }
405             if (isActiveWindow) {
406                 *ret = context->GetRoot(*elementInfo);
407             } else {
408                 AccessibilityWindowInfo windowInfo;
409                 windowInfo.SetWindowId(windowId);
410                 *ret = context->GetRootByWindow(windowInfo, *elementInfo);
411             }
412         };
413 
414         NapiAsyncTask::CompleteCallback complete =
415             [ret, elementInfo](napi_env env, NapiAsyncTask& task, int32_t status) {
416             if (*ret == RET_OK) {
417                 napi_value constructor = nullptr;
418                 napi_get_reference_value(env, NAccessibilityElement::consRef_, &constructor);
419                 napi_value napiElementInfo = nullptr;
420                 napi_status result = napi_new_instance(env, constructor, 0, nullptr, &napiElementInfo);
421                 HILOG_DEBUG("napi_new_instance result is %{public}d", result);
422                 NAccessibilityElement::ConvertElementInfoToJS(env, napiElementInfo, *elementInfo);
423                 task.Resolve(env, napiElementInfo);
424             } else {
425                 HILOG_ERROR("Get root elementInfo failed. ret : %{public}d", *ret);
426                 task.Reject(env, CreateJsError(env,
427                     static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
428                     ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
429             }
430         };
431 
432         napi_value result = nullptr;
433         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::OnGetWindowRootElement",
434             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
435         return result;
436     }
437 
OnGetWindows(napi_env env,NapiCallbackInfo & info)438     napi_value OnGetWindows(napi_env env, NapiCallbackInfo& info)
439     {
440         HILOG_INFO();
441 
442         int64_t displayId = 0;
443         bool hasDisplayId = false;
444         napi_value lastParam = nullptr;
445         if (info.argc >= ARGS_SIZE_TWO) {
446             if (info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) {
447                 HILOG_INFO("argc is more than two, use callback: situation 1");
448                 lastParam = info.argv[PARAM1];
449             } else if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
450                 HILOG_INFO("argc is more than two, use callback: situation 2");
451                 lastParam = info.argv[PARAM0];
452             } else {
453                 lastParam = nullptr;
454             }
455             if (info.argv[PARAM0] != nullptr && IsNapiNumber(env, info.argv[PARAM0])) {
456                 hasDisplayId = ConvertFromJsValue(env, info.argv[PARAM0], displayId);
457                 HILOG_INFO("argc is more than two, use promise: situation 3");
458             }
459         } else if (info.argc == ARGS_SIZE_ONE) {
460             if (info.argv[PARAM0] != nullptr && IsNapiFunction(env, info.argv[PARAM0])) {
461                 lastParam = info.argv[PARAM0];
462             } else if (info.argv[PARAM0] != nullptr && IsNapiNumber(env, info.argv[PARAM0])) {
463                 hasDisplayId = ConvertFromJsValue(env, info.argv[PARAM0], displayId);
464                 lastParam = nullptr;
465                 HILOG_INFO("argc is one, use promise");
466             }
467         } else {
468             lastParam = nullptr;
469             HILOG_INFO("argc is others, use promise");
470         }
471 
472         return hasDisplayId ? GetWindowsByDisplayIdAsync(env, lastParam, displayId) :
473             GetWindowsAsync(env, lastParam);
474     }
475 
GetWindowsAsync(napi_env env,napi_value lastParam)476     napi_value GetWindowsAsync(napi_env env, napi_value lastParam)
477     {
478         HILOG_INFO();
479         auto accessibilityWindows = std::make_shared<std::vector<OHOS::Accessibility::AccessibilityWindowInfo>>();
480         auto ret = std::make_shared<RetError>(RET_OK);
481         NapiAsyncTask::ExecuteCallback execute = [weak = context_, accessibilityWindows, ret] () {
482             HILOG_INFO("Getwindows begin");
483             auto context = weak.lock();
484             if (!context) {
485                 HILOG_ERROR("context is released");
486                 *ret = RET_ERR_FAILED;
487                 return;
488             }
489             *ret = context->GetWindows(*accessibilityWindows);
490         };
491 
492         NapiAsyncTask::CompleteCallback complete =
493             [ret, accessibilityWindows] (napi_env env, NapiAsyncTask& task, int32_t status) {
494                 if (*ret == RET_OK) {
495                     napi_value napiWindowInfos = nullptr;
496                     napi_create_array(env, &napiWindowInfos);
497                     ConvertAccessibilityWindowInfosToJS(env, napiWindowInfos, *accessibilityWindows);
498                     task.Resolve(env, napiWindowInfos);
499                 } else {
500                     HILOG_ERROR("Get windowInfos failed.");
501                     task.Reject(env, CreateJsError(env,
502                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
503                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
504                 }
505         };
506 
507         napi_value result = nullptr;
508         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::GetWindowsAsync",
509             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
510         return result;
511     }
512 
GetWindowsByDisplayIdAsync(napi_env env,napi_value lastParam,int64_t displayId)513     napi_value GetWindowsByDisplayIdAsync(napi_env env, napi_value lastParam, int64_t displayId)
514     {
515         HILOG_INFO();
516         auto accessibilityWindows = std::make_shared<std::vector<OHOS::Accessibility::AccessibilityWindowInfo>>();
517         auto ret = std::make_shared<RetError>(RET_OK);
518         NapiAsyncTask::ExecuteCallback execute = [weak = context_, accessibilityWindows, ret, displayId] () {
519             HILOG_INFO("GetwindowsByDisplayId begin");
520             auto context = weak.lock();
521             if (!context) {
522                 HILOG_ERROR("context is released");
523                 *ret = RET_ERR_FAILED;
524                 return;
525             }
526             if (displayId < 0) {
527                 HILOG_ERROR("displayId is error: %{public}" PRId64 "", displayId);
528                 *ret = RET_ERR_INVALID_PARAM;
529                 return;
530             }
531             *ret = context->GetWindows(static_cast<uint64_t>(displayId), *accessibilityWindows);
532         };
533 
534         NapiAsyncTask::CompleteCallback complete =
535             [ret, accessibilityWindows] (napi_env env, NapiAsyncTask& task, int32_t status) {
536                 if (*ret == RET_OK) {
537                     napi_value napiWindowInfos = nullptr;
538                     napi_create_array(env, &napiWindowInfos);
539                     ConvertAccessibilityWindowInfosToJS(env, napiWindowInfos, *accessibilityWindows);
540                     task.Resolve(env, napiWindowInfos);
541                 } else {
542                     HILOG_ERROR("Get windowInfosByDisplayId failed.");
543                     task.Reject(env, CreateJsError(env,
544                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
545                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
546                 }
547         };
548 
549         napi_value result = nullptr;
550         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::GetWindowsByDisplayIdAsync",
551             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
552         return result;
553     }
554 
OnGestureInjectSync(napi_env env,NapiCallbackInfo & info)555     napi_value OnGestureInjectSync(napi_env env, NapiCallbackInfo& info)
556     {
557         HILOG_INFO();
558         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
559         if (info.argc != ARGS_SIZE_TWO) {
560             HILOG_ERROR("invalid param");
561             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
562         }
563 
564         napi_value nGesturePaths = reinterpret_cast<napi_value>(info.argv[PARAM0]);
565         std::shared_ptr<AccessibilityGestureInjectPath> gesturePath =
566             std::make_shared<AccessibilityGestureInjectPath>();
567         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
568             if (!ConvertGesturePathJSToNAPI(env, nGesturePaths, gesturePath)) {
569                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
570                 HILOG_ERROR("invalid param");
571             }
572         }
573 
574         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
575             napi_throw(env, CreateJsError(env,
576                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
577                 ERROR_MESSAGE_PARAMETER_ERROR));
578             return CreateJsUndefined(env);
579         }
580 
581         auto context = context_.lock();
582         RetError ret = context->InjectGesture(gesturePath);
583         if (ret != RET_OK) {
584             HILOG_ERROR("result error, ret %{public}d", ret);
585             napi_throw(env, CreateJsError(env,
586                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
587                 ERROR_MESSAGE_PARAMETER_ERROR));
588             return CreateJsUndefined(env);
589         }
590 
591         HILOG_DEBUG("OnGestureInjectSync success");
592         return CreateJsUndefined(env);
593     }
594 
OnGestureInject(napi_env env,NapiCallbackInfo & info)595     napi_value OnGestureInject(napi_env env, NapiCallbackInfo& info)
596     {
597         HILOG_INFO();
598         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
599         if (info.argc < ARGS_SIZE_ONE) {
600             HILOG_ERROR("Not enough params");
601             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
602         }
603 
604         napi_value nGesturePaths = info.argv[PARAM0];
605         std::shared_ptr<AccessibilityGestureInjectPath> gesturePath =
606             std::make_shared<AccessibilityGestureInjectPath>();
607         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
608             if (!ConvertGesturePathJSToNAPI(env, nGesturePaths, gesturePath)) {
609                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
610             }
611         }
612 
613         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
614             HILOG_ERROR("invalid param");
615             napi_throw(env, CreateJsError(env,
616                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
617                 ERROR_MESSAGE_PARAMETER_ERROR));
618             return CreateJsUndefined(env);
619         }
620         return GestureInjectCompleteTask(env, info, gesturePath);
621     }
622 
GestureInjectCompleteTask(napi_env env,NapiCallbackInfo & info,std::shared_ptr<AccessibilityGestureInjectPath> gesturePath)623     napi_value GestureInjectCompleteTask(
624         napi_env env, NapiCallbackInfo& info, std::shared_ptr<AccessibilityGestureInjectPath> gesturePath)
625     {
626         auto ret = std::make_shared<RetError>(RET_OK);
627         NapiAsyncTask::ExecuteCallback execute = [weak = context_, gesturePath, ret] () {
628             HILOG_INFO("GestureInject begin");
629             auto context = weak.lock();
630             if (!context) {
631                 HILOG_ERROR("context is released");
632                 *ret = RET_ERR_FAILED;
633                 return;
634             }
635 
636             *ret = context->InjectGesture(gesturePath);
637         };
638         NapiAsyncTask::CompleteCallback complete =
639             [ret, gesturePath](napi_env env, NapiAsyncTask& task, int32_t status) {
640             if (*ret == RET_OK) {
641                 task.Resolve(env, CreateJsUndefined(env));
642             } else {
643                 HILOG_ERROR("Gesture inject failed. ret: %{public}d.", *ret);
644                 task.Reject(env, CreateJsError(env,
645                     static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
646                     ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
647             }
648         };
649 
650         napi_value lastParam = (info.argc == ARGS_SIZE_ONE) ? nullptr :
651             ((info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) ? info.argv[PARAM1] : nullptr);
652         napi_value result = nullptr;
653         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::OnGestureInject",
654             env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
655         return result;
656     }
657 
OnStartAbility(napi_env env,NapiCallbackInfo & info)658     napi_value OnStartAbility(napi_env env, NapiCallbackInfo& info)
659     {
660         if (info.argc < ARGS_SIZE_ONE) {
661             HILOG_ERROR("Start ability failed, not enough params.");
662             napi_throw(env, CreateJsError(env,
663                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM)));
664             return CreateJsUndefined(env);
665         }
666 
667         AAFwk::Want want;
668         if (!CheckStartAbilityInputParam(env, info, want)) {
669             napi_throw(env, CreateJsError(env,
670                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM)));
671             return CreateJsUndefined(env);
672         }
673 
674         NapiAsyncTask::CompleteCallback complete =
675         [weak = context_, want](napi_env env, NapiAsyncTask& task, int32_t status) {
676             HILOG_INFO("startAbility begin");
677             auto context = weak.lock();
678             if (context == nullptr) {
679                 HILOG_ERROR("context is released");
680                 task.Reject(env, CreateJsError(env,
681                     static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
682                     ERROR_MESSAGE_PARAMETER_ERROR));
683                 return;
684             }
685 
686             auto ret = std::make_shared<RetError>(RET_OK);
687             *ret = context->StartAbility(want);
688             if (*ret == RET_OK) {
689                 task.Resolve(env, CreateJsUndefined(env));
690             } else {
691                 HILOG_ERROR("startAbility failed. ret: %{public}d.", *ret);
692                 task.Reject(env, CreateJsError(env,
693                     static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).errCode),
694                     ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(*ret).message));
695             }
696         };
697 
698         napi_value lastParam = (info.argc == ARGS_SIZE_ONE) ? nullptr :
699             ((info.argv[PARAM1] != nullptr && IsNapiFunction(env, info.argv[PARAM1])) ? info.argv[PARAM1] : nullptr);
700         napi_value result = nullptr;
701         NapiAsyncTask::Schedule("NAccessibilityExtensionContext::OnStartAbility",
702             env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
703         return result;
704     }
705 
OnEnableScreenCurtain(napi_env env,NapiCallbackInfo & info)706     napi_value OnEnableScreenCurtain(napi_env env, NapiCallbackInfo& info)
707     {
708         HILOG_INFO();
709         if (info.argc != ARGS_SIZE_ONE) {
710             HILOG_ERROR("Not enough params");
711             napi_throw(env, CreateJsError(env,
712                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
713                 ERROR_MESSAGE_PARAMETER_ERROR));
714             return CreateJsUndefined(env);
715         }
716 
717         bool isEnable = false;
718         napi_get_value_bool(env, info.argv[PARAM0], &isEnable);
719         auto context = context_.lock();
720         RetError ret = context->EnableScreenCurtain(isEnable);
721         if (ret != RET_OK) {
722             HILOG_ERROR("result error, ret %{public}d", ret);
723             napi_throw(env, CreateJsError(env,
724                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
725                 ERROR_MESSAGE_PARAMETER_ERROR));
726             return CreateJsUndefined(env);
727         }
728 
729         HILOG_INFO("OnEnableScreenCurtain success");
730         return CreateJsUndefined(env);
731     }
732 };
733 } // namespace
734 
CreateJsAccessibilityExtensionContext(napi_env env,std::shared_ptr<AccessibilityExtensionContext> context)735 napi_value CreateJsAccessibilityExtensionContext(
736     napi_env env, std::shared_ptr<AccessibilityExtensionContext> context)
737 {
738     HILOG_INFO();
739     napi_value object = CreateJsExtensionContext(env, context);
740     std::unique_ptr<NAccessibilityExtensionContext> jsContext =
741         std::make_unique<NAccessibilityExtensionContext>(context);
742     if (!object) {
743         HILOG_ERROR("object is nullptr.");
744         return nullptr;
745     }
746     napi_wrap(env, object, jsContext.release(), NAccessibilityExtensionContext::Finalizer, nullptr, nullptr);
747     const char *moduleName = "NAccessibilityExtensionContext";
748     BindNativeFunction(env, object, "setTargetBundleName", moduleName,
749         NAccessibilityExtensionContext::SetTargetBundleName);
750     BindNativeFunction(env, object, "getFocusElement", moduleName,
751         NAccessibilityExtensionContext::GetFocusElement);
752     BindNativeFunction(env, object, "getWindowRootElement", moduleName,
753         NAccessibilityExtensionContext::GetWindowRootElement);
754     BindNativeFunction(env, object, "getWindows", moduleName, NAccessibilityExtensionContext::GetWindows);
755     BindNativeFunction(env, object, "injectGesture", moduleName, NAccessibilityExtensionContext::InjectGesture);
756     BindNativeFunction(env, object, "injectGestureSync", moduleName, NAccessibilityExtensionContext::InjectGestureSync);
757     BindNativeFunction(env, object, "startAbility", moduleName, NAccessibilityExtensionContext::StartAbility);
758     BindNativeFunction(env, object, "enableScreenCurtain", moduleName,
759         NAccessibilityExtensionContext::EnableScreenCurtain);
760     return object;
761 }
762 } // namespace Accessibility
763 } // namespace OHOS