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