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