• 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.h"
17 
18 #include <uv.h>
19 #include "accessible_ability_client.h"
20 #include "ability_info.h"
21 #include "hilog_wrapper.h"
22 #include "js_runtime.h"
23 #include "js_runtime_utils.h"
24 #include "napi_accessibility_event_info.h"
25 #include "napi_accessibility_extension_context.h"
26 #include "accessibility_utils.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "napi_accessibility_element.h"
30 
31 using namespace OHOS::AbilityRuntime;
32 using namespace OHOS::AccessibilityNapi;
33 
34 namespace OHOS {
35 namespace Accessibility {
36 namespace {
37     constexpr int32_t VIRTUAL_COMPONENT_ID = -1;
38 }
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)39 NAccessibilityExtension* NAccessibilityExtension::Create(const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
40 {
41     HILOG_INFO();
42     return new(std::nothrow) NAccessibilityExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
43 }
44 
NAccessibilityExtension(AbilityRuntime::JsRuntime & jsRuntime)45 NAccessibilityExtension::NAccessibilityExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime)
46 {
47     listener_ = std::make_shared<AbilityListener>(*this);
48 
49     HandleScope handleScope(jsRuntime_);
50     engine_ = &jsRuntime_.GetNativeEngine();
51 }
52 
53 NAccessibilityExtension::~NAccessibilityExtension() = default;
54 
OpenScope(napi_env env)55 napi_handle_scope OpenScope(napi_env env)
56 {
57     napi_handle_scope scope = nullptr;
58     NAPI_CALL(env, napi_open_handle_scope(env, &scope));
59     return scope;
60 }
61 
Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord> & record,const std::shared_ptr<AppExecFwk::OHOSApplication> & application,std::shared_ptr<AppExecFwk::AbilityHandler> & handler,const sptr<IRemoteObject> & token)62 void NAccessibilityExtension::Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord> &record,
63     const std::shared_ptr<AppExecFwk::OHOSApplication> &application,
64     std::shared_ptr<AppExecFwk::AbilityHandler> &handler, const sptr<IRemoteObject> &token)
65 {
66     HILOG_INFO();
67     AccessibilityExtension::Init(record, application, handler, token);
68     std::string srcPath = "";
69     std::string moduleName = "";
70     if (!GetSrcPathAndModuleName(srcPath, moduleName)) {
71         return;
72     }
73     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
74         abilityInfo_->compileMode == CompileMode::ES_MODULE);
75     if (!jsObj_) {
76         HILOG_ERROR("Failed to get jsObj_");
77         return;
78     }
79     NativeObject* obj = ConvertNativeValueTo<NativeObject>(jsObj_->Get());
80     if (!obj) {
81         HILOG_ERROR("Failed to get NAccessibilityExtension object");
82         return;
83     }
84 
85     auto context = GetContext();
86     if (!context) {
87         HILOG_ERROR("Failed to get context");
88         return;
89     }
90     NativeValue* contextObj = CreateJsAccessibilityExtensionContext(*engine_, context);
91     auto shellContextRef = jsRuntime_.LoadSystemModule("application.AccessibilityExtensionContext", &contextObj, 1);
92     if (!shellContextRef) {
93         HILOG_ERROR("shellContextRef is nullptr.");
94         return;
95     }
96     contextObj = shellContextRef->Get();
97     context->Bind(jsRuntime_, shellContextRef.release());
98     obj->SetProperty("context", contextObj);
99 
100     auto nativeObj = ConvertNativeValueTo<NativeObject>(contextObj);
101     if (!nativeObj) {
102         HILOG_ERROR("Failed to get accessibility extension native object");
103         return;
104     }
105     nativeObj->SetNativePointer(new std::weak_ptr<AbilityRuntime::Context>(context),
106         [](NativeEngine*, void* data, void*) {
107             delete static_cast<std::weak_ptr<AbilityRuntime::Context>*>(data);
108         }, nullptr);
109     NAccessibilityElement::DefineJSAccessibilityElement(reinterpret_cast<napi_env>(engine_));
110 }
111 
GetSrcPathAndModuleName(std::string & srcPath,std::string & moduleName)112 bool NAccessibilityExtension::GetSrcPathAndModuleName(std::string& srcPath, std::string& moduleName)
113 {
114     if (!Extension::abilityInfo_) {
115         HILOG_ERROR("abilityInfo_ is nullptr");
116         return false;
117     }
118     if (!Extension::abilityInfo_->isModuleJson) {
119         srcPath.append(Extension::abilityInfo_->package);
120         srcPath.append("/assets/js/");
121         if (!Extension::abilityInfo_->srcPath.empty()) {
122             srcPath.append(Extension::abilityInfo_->srcPath);
123         }
124         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
125     } else if (!Extension::abilityInfo_->srcEntrance.empty()) {
126         srcPath.append(Extension::abilityInfo_->moduleName + "/");
127         srcPath.append(Extension::abilityInfo_->srcEntrance);
128         srcPath.erase(srcPath.rfind('.'));
129         srcPath.append(".abc");
130     } else {
131         HILOG_ERROR("Failed to get srcPath");
132         return false;
133     }
134     moduleName = Extension::abilityInfo_->moduleName;
135     moduleName.append("::").append(abilityInfo_->name);
136     HILOG_INFO("moduleName:%{public}s, srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
137     return true;
138 }
139 
OnConnect(const AAFwk::Want & want)140 sptr<IRemoteObject> NAccessibilityExtension::OnConnect(const AAFwk::Want &want)
141 {
142     HILOG_INFO();
143     Extension::OnConnect(want);
144     sptr<AccessibleAbilityClient> aaClient = AccessibleAbilityClient::GetInstance();
145     if (!aaClient) {
146         HILOG_ERROR("aaClient is nullptr");
147         return nullptr;
148     }
149     aaClient->RegisterAbilityListener(listener_);
150     return aaClient->GetRemoteObject();
151 }
152 
OnAbilityConnected()153 void NAccessibilityExtension::OnAbilityConnected()
154 {
155     HILOG_INFO();
156     uv_loop_t *loop = engine_->GetUVLoop();
157     ExtensionCallbackInfo *callbackInfo = new(std::nothrow) ExtensionCallbackInfo();
158     if (!callbackInfo) {
159         HILOG_ERROR("Failed to create callbackInfo.");
160         return;
161     }
162     callbackInfo->extension_ = this;
163     uv_work_t *work = new(std::nothrow) uv_work_t;
164     if (!work) {
165         HILOG_ERROR("Failed to create data.");
166         delete callbackInfo;
167         callbackInfo = nullptr;
168         return;
169     }
170     work->data = static_cast<void*>(callbackInfo);
171 
172     int ret = uv_queue_work_with_qos(
173         loop,
174         work,
175         [](uv_work_t *work) {},
176         [](uv_work_t *work, int status) {
177             ExtensionCallbackInfo *data = static_cast<ExtensionCallbackInfo*>(work->data);
178             data->extension_->CallObjectMethod("onConnect");
179             delete data;
180             data = nullptr;
181             delete work;
182             work = nullptr;
183         },
184         uv_qos_user_initiated);
185     if (ret) {
186         HILOG_ERROR("Failed to execute OnAbilityConnected work queue");
187         delete callbackInfo;
188         callbackInfo = nullptr;
189         delete work;
190         work = nullptr;
191     }
192     HILOG_INFO("end.");
193 }
194 
OnAbilityDisconnected()195 void NAccessibilityExtension::OnAbilityDisconnected()
196 {
197     HILOG_INFO();
198     uv_loop_t *loop = engine_->GetUVLoop();
199     ExtensionCallbackInfo *callbackInfo = new(std::nothrow) ExtensionCallbackInfo();
200     if (!callbackInfo) {
201         HILOG_ERROR("Failed to create callbackInfo.");
202         return;
203     }
204     callbackInfo->extension_ = this;
205     uv_work_t *work = new(std::nothrow) uv_work_t;
206     if (!work) {
207         HILOG_ERROR("Failed to create data.");
208         delete callbackInfo;
209         callbackInfo = nullptr;
210         return;
211     }
212     work->data = static_cast<void*>(callbackInfo);
213     std::future syncFuture = callbackInfo->syncPromise_.get_future();
214 
215     int ret = uv_queue_work_with_qos(
216         loop,
217         work,
218         [](uv_work_t *work) {},
219         [](uv_work_t *work, int status) {
220             ExtensionCallbackInfo *data = static_cast<ExtensionCallbackInfo*>(work->data);
221             data->extension_->CallObjectMethod("onDisconnect");
222             data->syncPromise_.set_value();
223             delete data;
224             data = nullptr;
225             delete work;
226             work = nullptr;
227         },
228         uv_qos_user_initiated);
229     if (ret) {
230         HILOG_ERROR("Failed to execute OnAbilityDisconnected work queue");
231         callbackInfo->syncPromise_.set_value();
232         delete callbackInfo;
233         callbackInfo = nullptr;
234         delete work;
235         work = nullptr;
236     }
237     syncFuture.get();
238     HILOG_INFO("end.");
239 }
240 
GetElement(const AccessibilityEventInfo & eventInfo)241 std::shared_ptr<AccessibilityElement> NAccessibilityExtension::GetElement(const AccessibilityEventInfo& eventInfo)
242 {
243     HILOG_DEBUG();
244 
245     sptr<AccessibleAbilityClient> aaClient = AccessibleAbilityClient::GetInstance();
246     if (!aaClient) {
247         return nullptr;
248     }
249     int32_t componentId = eventInfo.GetAccessibilityId();
250     int32_t windowId = eventInfo.GetWindowId();
251     std::shared_ptr<AccessibilityElement> element = nullptr;
252     if (componentId > 0) {
253         std::shared_ptr<AccessibilityElementInfo> elementInfo = std::make_shared<AccessibilityElementInfo>();
254         if (aaClient->GetSource(eventInfo, *elementInfo) == RET_OK) {
255             element = std::make_shared<AccessibilityElement>(elementInfo);
256         }
257     } else if (windowId > 0) {
258         std::shared_ptr<AccessibilityWindowInfo> windowInfo = std::make_shared<AccessibilityWindowInfo>();
259         if (aaClient->GetWindow(windowId, *windowInfo) == RET_OK) {
260             element = std::make_shared<AccessibilityElement>(windowInfo);
261         }
262     } else {
263         std::shared_ptr<AccessibilityElementInfo> elementInfo = std::make_shared<AccessibilityElementInfo>();
264         CreateElementInfoByEventInfo(eventInfo, elementInfo);
265         element = std::make_shared<AccessibilityElement>(elementInfo);
266     }
267     return element;
268 }
269 
CreateElementInfoByEventInfo(const AccessibilityEventInfo & eventInfo,const std::shared_ptr<AccessibilityElementInfo> & elementInfo)270 void NAccessibilityExtension::CreateElementInfoByEventInfo(const AccessibilityEventInfo& eventInfo,
271     const std::shared_ptr<AccessibilityElementInfo> &elementInfo)
272 {
273     HILOG_DEBUG();
274     if (!elementInfo) {
275         return;
276     }
277     elementInfo->SetComponentId(VIRTUAL_COMPONENT_ID);
278     elementInfo->SetBundleName(eventInfo.GetBundleName());
279     elementInfo->SetComponentType(eventInfo.GetComponentType());
280     elementInfo->SetPageId(eventInfo.GetPageId());
281     elementInfo->SetDescriptionInfo(eventInfo.GetDescription());
282     elementInfo->SetTriggerAction(eventInfo.GetTriggerAction());
283     elementInfo->SetTextMovementStep(eventInfo.GetTextMovementStep());
284     elementInfo->SetContentList(eventInfo.GetContentList());
285     elementInfo->SetLatestContent(eventInfo.GetLatestContent());
286     elementInfo->SetBeginIndex(eventInfo.GetBeginIndex());
287     elementInfo->SetCurrentIndex(eventInfo.GetCurrentIndex());
288     elementInfo->SetEndIndex(eventInfo.GetEndIndex());
289     elementInfo->SetItemCounts(eventInfo.GetItemCounts());
290 }
291 
ConvertAccessibilityElementToJS(napi_env env,napi_value objEventInfo,const std::shared_ptr<AccessibilityElement> & element)292 void ConvertAccessibilityElementToJS(napi_env env, napi_value objEventInfo,
293     const std::shared_ptr<AccessibilityElement>& element)
294 {
295     HILOG_DEBUG();
296     if (!element) {
297         HILOG_DEBUG("No element information.");
298         return;
299     }
300     AccessibilityElement* pAccessibilityElement = new(std::nothrow) AccessibilityElement(*element);
301     if (!pAccessibilityElement) {
302         HILOG_ERROR("Failed to create AccessibilityElement.");
303         return;
304     }
305     auto closeScope = [env](napi_handle_scope scope) { napi_close_handle_scope(env, scope); };
306     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(OpenScope(env), closeScope);
307     napi_value nTargetObject = nullptr;
308     napi_value constructor = nullptr;
309     napi_get_reference_value(env, NAccessibilityElement::consRef_, &constructor);
310     napi_new_instance(env, constructor, 0, nullptr, &nTargetObject);
311     // Bind js object to a Native object
312     napi_status sts = napi_wrap(
313         env,
314         nTargetObject,
315         pAccessibilityElement,
316         [](napi_env env, void* data, void* hint) {
317             AccessibilityElement* info = static_cast<AccessibilityElement*>(data);
318             delete info;
319             info = nullptr;
320         },
321         nullptr,
322         nullptr);
323     HILOG_DEBUG("napi_wrap status: %{public}d", (int)sts);
324     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objEventInfo, "target", nTargetObject));
325 }
326 
OnAccessibilityEventExec(uv_work_t * work,uv_loop_t * loop)327 int NAccessibilityExtension::OnAccessibilityEventExec(uv_work_t *work, uv_loop_t *loop)
328 {
329     int ret = uv_queue_work_with_qos(
330         loop,
331         work,
332         [](uv_work_t *work) {},
333         [](uv_work_t *work, int status) {
334             AccessibilityEventInfoCallbackInfo *data = static_cast<AccessibilityEventInfoCallbackInfo*>(work->data);
335             auto closeScope = [data](napi_handle_scope scope) {
336                 napi_close_handle_scope(reinterpret_cast<napi_env>(data->engine_), scope);
337             };
338             std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(
339                 OpenScope(reinterpret_cast<napi_env>(data->engine_)), closeScope);
340             napi_value napiEventInfo = nullptr;
341             napi_create_object(reinterpret_cast<napi_env>(data->engine_), &napiEventInfo);
342 
343             napi_value nType;
344             NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
345                 napi_create_string_utf8(reinterpret_cast<napi_env>(data->engine_), data->eventType_.c_str(),
346                 NAPI_AUTO_LENGTH, &nType));
347             NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
348                 napi_set_named_property(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, "eventType", nType));
349             HILOG_DEBUG("eventType[%{public}s]", data->eventType_.c_str());
350 
351             napi_value nTimeStamp;
352             NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
353                 napi_create_int64(reinterpret_cast<napi_env>(data->engine_), data->timeStamp_, &nTimeStamp));
354             NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
355                 napi_set_named_property(reinterpret_cast<napi_env>(data->engine_),
356                 napiEventInfo, "timeStamp", nTimeStamp));
357 
358             ConvertAccessibilityElementToJS(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, data->element_);
359             NativeValue* nativeEventInfo = reinterpret_cast<NativeValue*>(napiEventInfo);
360             NativeValue* argv[] = {nativeEventInfo};
361             data->extension_->CallObjectMethod("onAccessibilityEvent", argv, 1);
362             delete data;
363             data = nullptr;
364             delete work;
365             work = nullptr;
366         },
367         uv_qos_user_initiated);
368     return ret;
369 }
370 
OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)371 void NAccessibilityExtension::OnAccessibilityEvent(const AccessibilityEventInfo& eventInfo)
372 {
373     HILOG_INFO();
374     std::string strType = "";
375     ConvertEventTypeToString(eventInfo, strType);
376     if (strType.empty()) {
377         HILOG_DEBUG("eventType is invalid.");
378         return;
379     }
380     uv_loop_t *loop = engine_->GetUVLoop();
381     AccessibilityEventInfoCallbackInfo *callbackInfo = new(std::nothrow) AccessibilityEventInfoCallbackInfo();
382     if (!callbackInfo) {
383         HILOG_ERROR("Failed to create callbackInfo.");
384         return;
385     }
386     callbackInfo->engine_ = engine_;
387     callbackInfo->extension_ = this;
388     callbackInfo->eventType_ = strType;
389     callbackInfo->timeStamp_ = eventInfo.GetTimeStamp();
390     callbackInfo->element_ = GetElement(eventInfo);
391     uv_work_t *work = new(std::nothrow) uv_work_t;
392     if (!work) {
393         HILOG_ERROR("Failed to create data.");
394         delete callbackInfo;
395         callbackInfo = nullptr;
396         return;
397     }
398     work->data = static_cast<void*>(callbackInfo);
399 
400     if (OnAccessibilityEventExec(work, loop)) {
401         HILOG_ERROR("Failed to execute OnAccessibilityEvent work queue");
402         delete callbackInfo;
403         callbackInfo = nullptr;
404         delete work;
405         work = nullptr;
406     }
407 }
408 
OnAccessibilityEventCompleteCallback(uv_work_t * work,int status)409 void NAccessibilityExtension::OnAccessibilityEventCompleteCallback(uv_work_t* work, int status)
410 {
411     AccessibilityEventInfoCallbackInfo *data = static_cast<AccessibilityEventInfoCallbackInfo*>(work->data);
412     auto closeScope = [data](napi_handle_scope scope) {
413         napi_close_handle_scope(reinterpret_cast<napi_env>(data->engine_), scope);
414     };
415     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(
416         OpenScope(reinterpret_cast<napi_env>(data->engine_)), closeScope);
417     napi_value napiEventInfo = nullptr;
418     napi_create_object(reinterpret_cast<napi_env>(data->engine_), &napiEventInfo);
419 
420     napi_value nType;
421     NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
422         napi_create_string_utf8(reinterpret_cast<napi_env>(data->engine_), data->eventType_.c_str(),
423         NAPI_AUTO_LENGTH, &nType));
424     NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
425         napi_set_named_property(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, "eventType", nType));
426     HILOG_DEBUG("eventType[%{public}s]", data->eventType_.c_str());
427 
428     napi_value nTimeStamp;
429     NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
430         napi_create_int64(reinterpret_cast<napi_env>(data->engine_), data->timeStamp_, &nTimeStamp));
431     NAPI_CALL_RETURN_VOID(reinterpret_cast<napi_env>(data->engine_),
432         napi_set_named_property(reinterpret_cast<napi_env>(data->engine_),
433         napiEventInfo, "timeStamp", nTimeStamp));
434 
435     ConvertAccessibilityElementToJS(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, data->element_);
436     NativeValue* nativeEventInfo = reinterpret_cast<NativeValue*>(napiEventInfo);
437     NativeValue* argv[] = {nativeEventInfo};
438     data->extension_->CallObjectMethod("onAccessibilityEvent", argv, 1);
439     delete data;
440     data = nullptr;
441     delete work;
442     work = nullptr;
443 }
444 
OnKeyPressEventExec(uv_work_t * work,uv_loop_t * loop)445 int NAccessibilityExtension::OnKeyPressEventExec(uv_work_t *work, uv_loop_t *loop)
446 {
447     int ret = uv_queue_work_with_qos(
448         loop,
449         work,
450         [](uv_work_t *work) {},
451         [](uv_work_t *work, int status) {
452             KeyEventCallbackInfo *data = static_cast<KeyEventCallbackInfo*>(work->data);
453             auto closeScope = [data](napi_handle_scope scope) {
454                 napi_close_handle_scope(reinterpret_cast<napi_env>(data->engine_), scope);
455             };
456             std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(
457                 OpenScope(reinterpret_cast<napi_env>(data->engine_)), closeScope);
458             napi_value napiEventInfo = nullptr;
459             if (napi_create_object(reinterpret_cast<napi_env>(data->engine_), &napiEventInfo) != napi_ok) {
460                 HILOG_ERROR("Create keyEvent object failed.");
461                 data->syncPromise_.set_value(false);
462                 delete data;
463                 data = nullptr;
464                 delete work;
465                 work = nullptr;
466                 return;
467             }
468             ConvertKeyEventToJS(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, data->keyEvent_);
469             NativeValue* nativeEventInfo = reinterpret_cast<NativeValue*>(napiEventInfo);
470             NativeValue* argv[] = {nativeEventInfo};
471             NativeValue* nativeResult = data->extension_->CallObjectMethod("onKeyEvent", argv, 1);
472 
473             // Unwrap result
474             bool result = false;
475             if (!ConvertFromJsValue(*data->engine_, nativeResult, result)) {
476                 HILOG_ERROR("ConvertFromJsValue failed");
477                 data->syncPromise_.set_value(false);
478                 delete data;
479                 data = nullptr;
480                 delete work;
481                 work = nullptr;
482                 return;
483             }
484             HILOG_INFO("OnKeyPressEvent result = %{public}d", result);
485             data->syncPromise_.set_value(result);
486             delete data;
487             data = nullptr;
488             delete work;
489             work = nullptr;
490         },
491         uv_qos_user_initiated);
492     return ret;
493 }
494 
OnKeyPressEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)495 bool NAccessibilityExtension::OnKeyPressEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
496 {
497     HILOG_INFO();
498     uv_loop_t *loop = engine_->GetUVLoop();
499     KeyEventCallbackInfo *callbackInfo = new(std::nothrow) KeyEventCallbackInfo();
500     if (!callbackInfo) {
501         HILOG_ERROR("Failed to create callbackInfo.");
502         return false;
503     }
504     callbackInfo->engine_ = engine_;
505     callbackInfo->keyEvent_ = MMI::KeyEvent::Clone(keyEvent);
506     callbackInfo->extension_ = this;
507     uv_work_t *work = new(std::nothrow) uv_work_t;
508     if (!work) {
509         HILOG_ERROR("Failed to create data.");
510         delete callbackInfo;
511         callbackInfo = nullptr;
512         return false;
513     }
514     work->data = static_cast<void*>(callbackInfo);
515     std::future syncFuture = callbackInfo->syncPromise_.get_future();
516 
517     if (OnKeyPressEventExec(work, loop)) {
518         HILOG_ERROR("Failed to execute OnKeyPressEvent work queue");
519         callbackInfo->syncPromise_.set_value(false);
520         delete callbackInfo;
521         callbackInfo = nullptr;
522         delete work;
523         work = nullptr;
524     }
525     bool callbackResult = syncFuture.get();
526     HILOG_INFO("OnKeyPressEvent callbackResult = %{public}d", callbackResult);
527     return callbackResult;
528 }
529 
OnKeyPressEventCompleteCallback(uv_work_t * work,int status)530 void NAccessibilityExtension::OnKeyPressEventCompleteCallback(uv_work_t* work, int status)
531 {
532     KeyEventCallbackInfo *data = static_cast<KeyEventCallbackInfo*>(work->data);
533     auto closeScope = [data](napi_handle_scope scope) {
534         napi_close_handle_scope(reinterpret_cast<napi_env>(data->engine_), scope);
535     };
536     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scopes(
537         OpenScope(reinterpret_cast<napi_env>(data->engine_)), closeScope);
538     napi_value napiEventInfo = nullptr;
539     if (napi_create_object(reinterpret_cast<napi_env>(data->engine_), &napiEventInfo) != napi_ok) {
540         HILOG_ERROR("Create keyEvent object failed.");
541         data->syncPromise_.set_value(false);
542         delete data;
543         data = nullptr;
544         delete work;
545         work = nullptr;
546         return;
547     }
548     ConvertKeyEventToJS(reinterpret_cast<napi_env>(data->engine_), napiEventInfo, data->keyEvent_);
549     NativeValue* nativeEventInfo = reinterpret_cast<NativeValue*>(napiEventInfo);
550     NativeValue* argv[] = {nativeEventInfo};
551     NativeValue* nativeResult = data->extension_->CallObjectMethod("onKeyEvent", argv, 1);
552 
553     // Unwrap result
554     bool result = false;
555     if (!ConvertFromJsValue(*data->engine_, nativeResult, result)) {
556         HILOG_ERROR("ConvertFromJsValue failed");
557         data->syncPromise_.set_value(false);
558         delete data;
559         data = nullptr;
560         delete work;
561         work = nullptr;
562         return;
563     }
564     HILOG_INFO("OnKeyPressEvent result = %{public}d", result);
565     data->syncPromise_.set_value(result);
566     delete data;
567     data = nullptr;
568     delete work;
569     work = nullptr;
570 }
571 
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc)572 NativeValue* NAccessibilityExtension::CallObjectMethod(const char* name, NativeValue* const* argv, size_t argc)
573 {
574     HILOG_INFO("name:%{public}s", name);
575     if (!jsObj_) {
576         HILOG_ERROR("jsObj_ is nullptr");
577         return nullptr;
578     }
579 
580     NativeValue* value = jsObj_->Get();
581     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
582     if (!obj) {
583         HILOG_ERROR("Failed to get AccessibilityExtension object");
584         return nullptr;
585     }
586 
587     NativeValue* method = obj->GetProperty(name);
588     if (!method) {
589         HILOG_ERROR("Failed to get '%{public}s' from AccessibilityExtension object", name);
590         return nullptr;
591     }
592     HILOG_INFO("CallFunction(%{public}s), success", name);
593     return engine_->CallFunction(value, method, argv, argc);
594 }
595 } // namespace Accessibility
596 } // namespace OHOS
597