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