• 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 "native_engine/native_value.h"
26 
27 using namespace OHOS::AbilityRuntime;
28 using namespace OHOS::AccessibilityNapi;
29 
30 namespace OHOS {
31 namespace Accessibility {
32 namespace {
ConvertAccessibilityWindowInfoToJS(napi_env env,napi_value result,const AccessibilityWindowInfo & accessibilityWindowInfo)33 static void ConvertAccessibilityWindowInfoToJS(
34     napi_env env, napi_value result, const AccessibilityWindowInfo& accessibilityWindowInfo)
35 {
36     // Bind js object to a Native object
37     std::shared_ptr<AccessibilityWindowInfo> windowInfo =
38         std::make_shared<AccessibilityWindowInfo>(accessibilityWindowInfo);
39     AccessibilityElement* pAccessibilityElement = new(std::nothrow) AccessibilityElement(windowInfo);
40     if (!pAccessibilityElement) {
41         HILOG_ERROR("Failed to create work.");
42         return;
43     }
44 
45     napi_status sts = napi_wrap(
46         env,
47         result,
48         pAccessibilityElement,
49         [](napi_env env, void* data, void* hint) {
50             AccessibilityElement* info = static_cast<AccessibilityElement*>(data);
51             delete info;
52             info = nullptr;
53         },
54         nullptr,
55         nullptr);
56     HILOG_DEBUG("napi_wrap status: %{public}d", (int)sts);
57 }
58 
ConvertAccessibilityWindowInfosToJS(napi_env env,napi_value result,const std::vector<AccessibilityWindowInfo> & accessibilityWindowInfos)59 static void ConvertAccessibilityWindowInfosToJS(
60     napi_env env, napi_value result, const std::vector<AccessibilityWindowInfo>& accessibilityWindowInfos)
61 {
62     HILOG_DEBUG();
63     size_t idx = 0;
64 
65     if (accessibilityWindowInfos.empty()) {
66         return;
67     }
68     napi_value constructor = nullptr;
69     napi_get_reference_value(env, NAccessibilityElement::consRef_, &constructor);
70 
71     for (const auto& windowInfo : accessibilityWindowInfos) {
72         napi_value obj = nullptr;
73         napi_new_instance(env, constructor, 0, nullptr, &obj);
74         ConvertAccessibilityWindowInfoToJS(env, obj, windowInfo);
75         napi_set_element(env, result, idx, obj);
76         idx++;
77     }
78 }
79 
GetLastParamForTwo(NativeEngine & engine,NativeCallbackInfo & info,NativeValue * & lastParam,bool & isAccessibilityFocus)80 static void GetLastParamForTwo(
81     NativeEngine& engine, NativeCallbackInfo& info, NativeValue*& lastParam, bool& isAccessibilityFocus)
82 {
83     if (info.argv[PARAM0] != nullptr && info.argv[PARAM1] != nullptr &&
84         info.argv[PARAM0]->TypeOf() == NATIVE_BOOLEAN && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) {
85         lastParam = ConvertFromJsValue(engine, info.argv[PARAM0], isAccessibilityFocus) ?
86             info.argv[PARAM1] : nullptr;
87     } else if (info.argv[PARAM1] != nullptr && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) {
88         HILOG_INFO("argc is more than two, use callback: situation 1");
89         lastParam = info.argv[PARAM1];
90     } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
91         HILOG_INFO("argc is more than two, use callback: situation 2");
92         lastParam = info.argv[PARAM0];
93     } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_BOOLEAN) {
94         HILOG_INFO("argc is more than two, use promise: situation 3");
95         lastParam = nullptr;
96         ConvertFromJsValue(engine, info.argv[PARAM0], isAccessibilityFocus);
97     } else {
98         lastParam = nullptr;
99         HILOG_INFO("argc is more than two, use promise");
100     }
101 }
102 
103 class NAccessibilityExtensionContext final {
104 public:
NAccessibilityExtensionContext(const std::shared_ptr<AccessibilityExtensionContext> & context)105     explicit NAccessibilityExtensionContext(
106         const std::shared_ptr<AccessibilityExtensionContext>& context) : context_(context) {}
107     ~NAccessibilityExtensionContext() = default;
108 
Finalizer(NativeEngine * engine,void * data,void * hint)109     static void Finalizer(NativeEngine* engine, void* data, void* hint)
110     {
111         HILOG_INFO();
112         std::unique_ptr<NAccessibilityExtensionContext>(static_cast<NAccessibilityExtensionContext*>(data));
113     }
114 
SetTargetBundleName(NativeEngine * engine,NativeCallbackInfo * info)115     static NativeValue* SetTargetBundleName(NativeEngine* engine, NativeCallbackInfo* info)
116     {
117         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
118         return (me != nullptr) ? me->OnSetTargetBundleName(*engine, *info) : nullptr;
119     }
120 
GetFocusElement(NativeEngine * engine,NativeCallbackInfo * info)121     static NativeValue* GetFocusElement(NativeEngine* engine, NativeCallbackInfo* info)
122     {
123         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
124         return (me != nullptr) ? me->OnGetFocusElement(*engine, *info) : nullptr;
125     }
126 
GetWindowRootElement(NativeEngine * engine,NativeCallbackInfo * info)127     static NativeValue* GetWindowRootElement(NativeEngine* engine, NativeCallbackInfo* info)
128     {
129         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
130         return (me != nullptr) ? me->OnGetWindowRootElement(*engine, *info) : nullptr;
131     }
132 
GetWindows(NativeEngine * engine,NativeCallbackInfo * info)133     static NativeValue* GetWindows(NativeEngine* engine, NativeCallbackInfo* info)
134     {
135         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
136         return (me != nullptr) ? me->OnGetWindows(*engine, *info) : nullptr;
137     }
138 
InjectGesture(NativeEngine * engine,NativeCallbackInfo * info)139     static NativeValue* InjectGesture(NativeEngine* engine, NativeCallbackInfo* info)
140     {
141         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
142         return (me != nullptr) ? me->OnGestureInject(*engine, *info) : nullptr;
143     }
144 
InjectGestureSync(NativeEngine * engine,NativeCallbackInfo * info)145     static NativeValue* InjectGestureSync(NativeEngine* engine, NativeCallbackInfo* info)
146     {
147         NAccessibilityExtensionContext* me = CheckParamsAndGetThis<NAccessibilityExtensionContext>(engine, info);
148         return (me != nullptr) ? me->OnGestureInjectSync(*engine, *info) : nullptr;
149     }
150 
151 private:
152     std::weak_ptr<AccessibilityExtensionContext> context_;
153 
OnSetTargetBundleName(NativeEngine & engine,NativeCallbackInfo & info)154     NativeValue* OnSetTargetBundleName(NativeEngine& engine, NativeCallbackInfo& info)
155     {
156         HILOG_INFO();
157         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
158         if (info.argc < ARGS_SIZE_ONE) {
159             HILOG_ERROR("Not enough params");
160             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
161         }
162 
163         std::vector<std::string> targetBundleNames;
164         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
165             if (ConvertJSToStringVec(reinterpret_cast<napi_env>(&engine),
166                 reinterpret_cast<napi_value>(info.argv[PARAM0]), targetBundleNames)) {
167                 HILOG_INFO("targetBundleNames's size = %{public}zu", targetBundleNames.size());
168             } else {
169                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
170             }
171         }
172 
173         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
174             HILOG_ERROR("invalid param");
175             engine.Throw(CreateJsError(engine,
176                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
177                 ERROR_MESSAGE_PARAMETER_ERROR));
178             return engine.CreateUndefined();
179         }
180 
181         return SetTargetBundleNameCompleteTask(engine, targetBundleNames, info);
182     }
183 
SetTargetBundleNameCompleteTask(NativeEngine & engine,std::vector<std::string> targetBundleNames,NativeCallbackInfo & info)184     NativeValue* SetTargetBundleNameCompleteTask(
185         NativeEngine& engine, std::vector<std::string> targetBundleNames, NativeCallbackInfo& info)
186     {
187         AsyncTask::CompleteCallback complete =
188             [weak = context_, targetBundleNames](NativeEngine& engine, AsyncTask& task, int32_t status) {
189                 HILOG_INFO("SetTargetBundleName begin");
190                 auto context = weak.lock();
191                 if (!context) {
192                     HILOG_ERROR("context is released");
193                     task.Reject(engine, CreateJsError(engine,
194                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
195                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
196                     return;
197                 }
198 
199                 RetError ret = context->SetTargetBundleName(targetBundleNames);
200                 if (ret == RET_OK) {
201                     task.Resolve(engine, engine.CreateUndefined());
202                 } else {
203                     HILOG_ERROR("set target bundle name failed. ret: %{public}d.", ret);
204                     task.Reject(engine, CreateJsError(engine,
205                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
206                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
207                 }
208             };
209 
210         NativeValue* lastParam = (info.argc == ARGS_SIZE_ONE) ? nullptr :
211             ((info.argv[PARAM1] != nullptr && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) ?
212             info.argv[PARAM1] : nullptr);
213         NativeValue* result = nullptr;
214         AsyncTask::Schedule("NAccessibilityExtensionContext::OnSetTargetBundleName",
215             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
216         return result;
217     }
218 
OnGetFocusElement(NativeEngine & engine,NativeCallbackInfo & info)219     NativeValue* OnGetFocusElement(NativeEngine& engine, NativeCallbackInfo& info)
220     {
221         HILOG_INFO();
222         bool isAccessibilityFocus = false;
223         NativeValue* lastParam = nullptr;
224         if (info.argc >= ARGS_SIZE_TWO) {
225             GetLastParamForTwo(engine, info, lastParam, isAccessibilityFocus);
226         } else if (info.argc == ARGS_SIZE_ONE) {
227             if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
228                 lastParam = info.argv[PARAM0];
229             } else {
230                 if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_BOOLEAN) {
231                     ConvertFromJsValue(engine, info.argv[PARAM0], isAccessibilityFocus);
232                 }
233                 lastParam = nullptr;
234                 HILOG_INFO("argc is one, use promise");
235             }
236         } else {
237             lastParam = nullptr;
238             HILOG_INFO("argc is others, use promise");
239         }
240 
241         int32_t focus = isAccessibilityFocus ? FOCUS_TYPE_ACCESSIBILITY : FOCUS_TYPE_INPUT;
242         HILOG_DEBUG("focus type is [%{public}d]", focus);
243         return GetFoucusElementCompleteTask(engine, focus, lastParam);
244     }
245 
GetFoucusElementCompleteTask(NativeEngine & engine,int32_t focus,NativeValue * lastParam)246     NativeValue* GetFoucusElementCompleteTask(NativeEngine& engine, int32_t focus, NativeValue* lastParam)
247     {
248         AsyncTask::CompleteCallback complete =
249             [weak = context_, focus](NativeEngine& engine, AsyncTask& task, int32_t status) {
250                 HILOG_INFO("GetFocusElement begin");
251                 auto context = weak.lock();
252                 if (!context) {
253                     HILOG_ERROR("context is released");
254                     task.Reject(engine, CreateJsError(engine,
255                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
256                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
257                     return;
258                 }
259 
260                 OHOS::Accessibility::AccessibilityElementInfo elementInfo;
261                 RetError ret = context->GetFocus(focus, elementInfo);
262                 if (ret == RET_OK) {
263                     napi_value constructor = nullptr;
264                     napi_get_reference_value(reinterpret_cast<napi_env>(&engine), NAccessibilityElement::consRef_,
265                         &constructor);
266                     napi_value napiElementInfo = nullptr;
267                     napi_new_instance(reinterpret_cast<napi_env>(&engine), constructor, 0, nullptr, &napiElementInfo);
268                     NAccessibilityElement::ConvertElementInfoToJS(reinterpret_cast<napi_env>(&engine),
269                         napiElementInfo, elementInfo);
270                     NativeValue* nativeElementInfo = reinterpret_cast<NativeValue*>(napiElementInfo);
271                     task.Resolve(engine, nativeElementInfo);
272                 } else {
273                     HILOG_ERROR("Get focus elementInfo failed. ret: %{public}d", ret);
274                     task.Reject(engine, CreateJsError(engine,
275                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).errCode),
276                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).message));
277                 }
278             };
279 
280         NativeValue* result = nullptr;
281         AsyncTask::Schedule("NAccessibilityExtensionContext::OnGetFocusElement",
282             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
283         return result;
284     }
285 
OnGetWindowRootElement(NativeEngine & engine,NativeCallbackInfo & info)286     NativeValue* OnGetWindowRootElement(NativeEngine& engine, NativeCallbackInfo& info)
287     {
288         HILOG_INFO();
289         int32_t windowId = INVALID_WINDOW_ID;
290         bool isActiveWindow = true;
291         NativeValue* lastParam = nullptr;
292         if (info.argc >= ARGS_SIZE_TWO) {
293             if (info.argv[PARAM1] != nullptr && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) {
294                 HILOG_INFO("argc is more than two, use callback: situation 1");
295                 lastParam = info.argv[PARAM1];
296             } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
297                 HILOG_INFO("argc is more than two, use callback: situation 2");
298                 lastParam = info.argv[PARAM0];
299             } else {
300                 lastParam = nullptr;
301                 HILOG_INFO("argc is two, use promise");
302             }
303             if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_NUMBER) {
304                 HILOG_INFO("argc is more than two, use promise: situation 3");
305                 isActiveWindow = !ConvertFromJsValue(engine, info.argv[PARAM0], windowId);
306             }
307         } else if (info.argc == ARGS_SIZE_ONE) {
308             if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
309                 lastParam = info.argv[PARAM0];
310             } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_NUMBER) {
311                 isActiveWindow = !ConvertFromJsValue(engine, info.argv[PARAM0], windowId);
312                 lastParam = nullptr;
313                 HILOG_INFO("argc is one, use promise");
314             }
315         } else {
316             lastParam = nullptr;
317             HILOG_INFO("argc is others, use promise");
318         }
319         return GetWindowRootElementCompleteTask(engine, windowId, isActiveWindow, lastParam);
320     }
321 
GetWindowRootElementCompleteTask(NativeEngine & engine,int32_t windowId,bool isActiveWindow,NativeValue * lastParam)322     NativeValue* GetWindowRootElementCompleteTask(
323         NativeEngine& engine, int32_t windowId, bool isActiveWindow, NativeValue* lastParam)
324     {
325         AsyncTask::CompleteCallback complete =
326             [weak = context_, windowId, isActiveWindow](NativeEngine& engine, AsyncTask& task, int32_t status) {
327                 HILOG_INFO("GetWindowRootElement begin");
328                 auto context = weak.lock();
329                 if (!context) {
330                     HILOG_ERROR("context is released");
331                     task.Reject(engine, CreateJsError(engine,
332                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
333                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
334                     return;
335                 }
336 
337                 HILOG_DEBUG("isActiveWindow[%{public}d] windowId[%{public}d]", isActiveWindow, windowId);
338                 OHOS::Accessibility::AccessibilityElementInfo elementInfo;
339                 RetError ret = RET_OK;
340                 if (isActiveWindow) {
341                     ret = context->GetRoot(elementInfo);
342                 } else {
343                     AccessibilityWindowInfo windowInfo;
344                     windowInfo.SetWindowId(windowId);
345                     ret = context->GetRootByWindow(windowInfo, elementInfo);
346                 }
347                 if (ret == RET_OK) {
348                     napi_value constructor = nullptr;
349                     napi_get_reference_value(reinterpret_cast<napi_env>(&engine), NAccessibilityElement::consRef_,
350                         &constructor);
351                     napi_value napiElementInfo = nullptr;
352                     napi_status result = napi_new_instance(reinterpret_cast<napi_env>(&engine), constructor, 0, nullptr,
353                         &napiElementInfo);
354                     HILOG_DEBUG("napi_new_instance result is %{public}d", result);
355                     NAccessibilityElement::ConvertElementInfoToJS(reinterpret_cast<napi_env>(&engine),
356                         napiElementInfo, elementInfo);
357                     NativeValue* nativeElementInfo = reinterpret_cast<NativeValue*>(napiElementInfo);
358                     task.Resolve(engine, nativeElementInfo);
359                 } else {
360                     HILOG_ERROR("Get root elementInfo failed. ret : %{public}d", ret);
361                     task.Reject(engine, CreateJsError(engine,
362                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).errCode),
363                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).message));
364                 }
365             };
366 
367         NativeValue* result = nullptr;
368         AsyncTask::Schedule("NAccessibilityExtensionContext::OnGetWindowRootElement",
369             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
370         return result;
371     }
372 
OnGetWindows(NativeEngine & engine,NativeCallbackInfo & info)373     NativeValue* OnGetWindows(NativeEngine& engine, NativeCallbackInfo& info)
374     {
375         HILOG_INFO();
376 
377         int64_t displayId = 0;
378         bool hasDisplayId = false;
379         NativeValue* lastParam = nullptr;
380         if (info.argc >= ARGS_SIZE_TWO) {
381             if (info.argv[PARAM1] != nullptr && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) {
382                 HILOG_INFO("argc is more than two, use callback: situation 1");
383                 lastParam = info.argv[PARAM1];
384             } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
385                 HILOG_INFO("argc is more than two, use callback: situation 2");
386                 lastParam = info.argv[PARAM0];
387             } else {
388                 lastParam = nullptr;
389             }
390             if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_NUMBER) {
391                 hasDisplayId = ConvertFromJsValue(engine, info.argv[PARAM0], displayId);
392                 HILOG_INFO("argc is more than two, use promise: situation 3");
393             }
394         } else if (info.argc == ARGS_SIZE_ONE) {
395             if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_FUNCTION) {
396                 lastParam = info.argv[PARAM0];
397             } else if (info.argv[PARAM0] != nullptr && info.argv[PARAM0]->TypeOf() == NATIVE_NUMBER) {
398                 hasDisplayId = ConvertFromJsValue(engine, info.argv[PARAM0], displayId);
399                 lastParam = nullptr;
400                 HILOG_INFO("argc is one, use promise");
401             }
402         } else {
403             lastParam = nullptr;
404             HILOG_INFO("argc is others, use promise");
405         }
406 
407         return hasDisplayId ? GetWindowsByDisplayIdAsync(engine, lastParam, displayId) :
408             GetWindowsAsync(engine, lastParam);
409     }
410 
GetWindowsAsync(NativeEngine & engine,NativeValue * lastParam)411     NativeValue* GetWindowsAsync(NativeEngine& engine, NativeValue* lastParam)
412     {
413         HILOG_INFO();
414         AsyncTask::CompleteCallback complete =
415             [weak = context_](NativeEngine& engine, AsyncTask& task, int32_t status) {
416                 HILOG_INFO("GetWindows begin");
417                 auto context = weak.lock();
418                 if (!context) {
419                     HILOG_ERROR("context is released");
420                     task.Reject(engine, CreateJsError(engine,
421                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
422                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
423                     return;
424                 }
425 
426                 std::vector<OHOS::Accessibility::AccessibilityWindowInfo> accessibilityWindows;
427                 RetError ret = context->GetWindows(accessibilityWindows);
428                 if (ret == RET_OK) {
429                     napi_value napiWindowInfos = nullptr;
430                     napi_create_array(reinterpret_cast<napi_env>(&engine), &napiWindowInfos);
431                     ConvertAccessibilityWindowInfosToJS(
432                         reinterpret_cast<napi_env>(&engine), napiWindowInfos, accessibilityWindows);
433                     NativeValue* nativeWindowInfos = reinterpret_cast<NativeValue*>(napiWindowInfos);
434                     task.Resolve(engine, nativeWindowInfos);
435                 } else {
436                     HILOG_ERROR("Get windowInfos failed.");
437                     task.Reject(engine, CreateJsError(engine,
438                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).errCode),
439                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).message));
440                 }
441             };
442 
443         NativeValue* result = nullptr;
444         AsyncTask::Schedule("NAccessibilityExtensionContext::GetWindowsAsync",
445             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
446         return result;
447     }
448 
GetWindowsByDisplayIdAsync(NativeEngine & engine,NativeValue * lastParam,int64_t displayId)449     NativeValue* GetWindowsByDisplayIdAsync(NativeEngine& engine, NativeValue* lastParam, int64_t displayId)
450     {
451         HILOG_INFO();
452         AsyncTask::CompleteCallback complete =
453             [weak = context_, displayId](NativeEngine& engine, AsyncTask& task, int32_t status) {
454                 HILOG_INFO("GetWindows begin");
455                 auto context = weak.lock();
456                 if (!context) {
457                     HILOG_ERROR("context is released");
458                     task.Reject(engine, CreateJsError(engine,
459                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
460                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
461                     return;
462                 }
463 
464                 if (displayId < 0) {
465                     HILOG_ERROR("displayId is error: %{public}" PRId64 "", displayId);
466                     task.Reject(engine, CreateJsError(engine,
467                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
468                         ERROR_MESSAGE_PARAMETER_ERROR));
469                     return;
470                 }
471 
472                 std::vector<OHOS::Accessibility::AccessibilityWindowInfo> accessibilityWindows;
473                 RetError ret = context->GetWindows(static_cast<uint64_t>(displayId), accessibilityWindows);
474                 if (ret == RET_OK) {
475                     napi_value napiWindowInfos = nullptr;
476                     napi_create_array(reinterpret_cast<napi_env>(&engine), &napiWindowInfos);
477                     ConvertAccessibilityWindowInfosToJS(
478                         reinterpret_cast<napi_env>(&engine), napiWindowInfos, accessibilityWindows);
479                     NativeValue* nativeWindowInfos = reinterpret_cast<NativeValue*>(napiWindowInfos);
480                     task.Resolve(engine, nativeWindowInfos);
481                 } else {
482                     HILOG_ERROR("Get windowInfos failed.");
483                     task.Reject(engine, CreateJsError(engine,
484                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).errCode),
485                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).message));
486                 }
487             };
488 
489         NativeValue* result = nullptr;
490         AsyncTask::Schedule("NAccessibilityExtensionContext::GetWindowsByDisplayIdAsync",
491             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
492         return result;
493     }
494 
OnGestureInjectSync(NativeEngine & engine,NativeCallbackInfo & info)495     NativeValue* OnGestureInjectSync(NativeEngine& engine, NativeCallbackInfo& info)
496     {
497         HILOG_INFO();
498         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
499         if (info.argc != ARGS_SIZE_TWO) {
500             HILOG_ERROR("invalid param");
501             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
502         }
503 
504         napi_value nGesturePaths = reinterpret_cast<napi_value>(info.argv[PARAM0]);
505         std::shared_ptr<AccessibilityGestureInjectPath> gesturePath =
506             std::make_shared<AccessibilityGestureInjectPath>();
507         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
508             if (!ConvertGesturePathJSToNAPI(reinterpret_cast<napi_env>(&engine), nGesturePaths, gesturePath)) {
509                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
510                 HILOG_ERROR("invalid param");
511             }
512         }
513 
514         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
515             engine.Throw(CreateJsError(engine,
516                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
517                 ERROR_MESSAGE_PARAMETER_ERROR));
518             return engine.CreateUndefined();
519         }
520 
521         auto context = context_.lock();
522         RetError ret = context->InjectGesture(gesturePath);
523         if (ret != RET_OK) {
524             HILOG_ERROR("result error, ret %{public}d", ret);
525             engine.Throw(CreateJsError(engine,
526                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
527                 ERROR_MESSAGE_PARAMETER_ERROR));
528             return engine.CreateUndefined();
529         }
530 
531         HILOG_DEBUG("OnGestureInjectSync success");
532         return engine.CreateUndefined();
533     }
534 
OnGestureInject(NativeEngine & engine,NativeCallbackInfo & info)535     NativeValue* OnGestureInject(NativeEngine& engine, NativeCallbackInfo& info)
536     {
537         HILOG_INFO();
538         NAccessibilityErrorCode errCode = NAccessibilityErrorCode::ACCESSIBILITY_OK;
539         if (info.argc < ARGS_SIZE_ONE) {
540             HILOG_ERROR("Not enough params");
541             errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
542         }
543 
544         napi_value nGesturePaths = reinterpret_cast<napi_value>(info.argv[PARAM0]);
545         std::shared_ptr<AccessibilityGestureInjectPath> gesturePath =
546             std::make_shared<AccessibilityGestureInjectPath>();
547         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_OK) {
548             if (!ConvertGesturePathJSToNAPI(reinterpret_cast<napi_env>(&engine), nGesturePaths, gesturePath)) {
549                 errCode = NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM;
550             }
551         }
552 
553         if (errCode == NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM) {
554             HILOG_ERROR("invalid param");
555             engine.Throw(CreateJsError(engine,
556                 static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM),
557                 ERROR_MESSAGE_PARAMETER_ERROR));
558             return engine.CreateUndefined();
559         }
560         return GestureInjectCompleteTask(engine, info, gesturePath);
561     }
562 
GestureInjectCompleteTask(NativeEngine & engine,NativeCallbackInfo & info,std::shared_ptr<AccessibilityGestureInjectPath> gesturePath)563     NativeValue* GestureInjectCompleteTask(
564         NativeEngine& engine, NativeCallbackInfo& info, std::shared_ptr<AccessibilityGestureInjectPath> gesturePath)
565     {
566         AsyncTask::CompleteCallback complete =
567             [weak = context_, gesturePath](
568             NativeEngine& engine, AsyncTask& task, int32_t status) {
569                 auto context = weak.lock();
570                 if (!context) {
571                     HILOG_ERROR("context is released");
572                     task.Reject(engine, CreateJsError(engine,
573                         static_cast<int32_t>(NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY),
574                         ERROR_MESSAGE_SYSTEM_ABNORMALITY));
575                     return;
576                 }
577                 RetError ret = context->InjectGesture(gesturePath);
578                 if (ret == RET_OK) {
579                     task.Resolve(engine, engine.CreateUndefined());
580                 } else {
581                     HILOG_ERROR("Gesture inject failed. ret: %{public}d.", ret);
582                     task.Reject(engine, CreateJsError(engine,
583                         static_cast<int32_t>(ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).errCode),
584                         ACCESSIBILITY_JS_TO_ERROR_CODE_MAP.at(ret).message));
585                 }
586             };
587 
588         NativeValue* lastParam = (info.argc == ARGS_SIZE_ONE) ? nullptr :
589             ((info.argv[PARAM1] != nullptr && info.argv[PARAM1]->TypeOf() == NATIVE_FUNCTION) ?
590             info.argv[PARAM1] : nullptr);
591         NativeValue* result = nullptr;
592         AsyncTask::Schedule("NAccessibilityExtensionContext::OnGestureInject",
593             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
594         return result;
595     }
596 };
597 } // namespace
598 
CreateJsAccessibilityExtensionContext(NativeEngine & engine,std::shared_ptr<AccessibilityExtensionContext> context)599 NativeValue* CreateJsAccessibilityExtensionContext(
600     NativeEngine& engine, std::shared_ptr<AccessibilityExtensionContext> context)
601 {
602     HILOG_INFO();
603     NativeValue* objValue = CreateJsExtensionContext(engine, context);
604     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
605 
606     std::unique_ptr<NAccessibilityExtensionContext> jsContext =
607         std::make_unique<NAccessibilityExtensionContext>(context);
608     if (!object) {
609         HILOG_ERROR("object is nullptr.");
610         return nullptr;
611     }
612     object->SetNativePointer(jsContext.release(), NAccessibilityExtensionContext::Finalizer, nullptr);
613 
614     const char *moduleName = "NAccessibilityExtensionContext";
615     BindNativeFunction(engine, *object, "setTargetBundleName", moduleName,
616         NAccessibilityExtensionContext::SetTargetBundleName);
617     BindNativeFunction(engine, *object, "getFocusElement", moduleName,
618         NAccessibilityExtensionContext::GetFocusElement);
619     BindNativeFunction(engine, *object, "getWindowRootElement", moduleName,
620         NAccessibilityExtensionContext::GetWindowRootElement);
621     BindNativeFunction(engine, *object, "getWindows", moduleName, NAccessibilityExtensionContext::GetWindows);
622     BindNativeFunction(engine, *object, "injectGesture", moduleName, NAccessibilityExtensionContext::InjectGesture);
623     BindNativeFunction(engine, *object, "injectGestureSync", moduleName,
624         NAccessibilityExtensionContext::InjectGestureSync);
625 
626     return objValue;
627 }
628 } // namespace Accessibility
629 } // namespace OHOS