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