• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "feature_ability.h"
16 
17 #include <cstring>
18 #include <uv.h>
19 #include <vector>
20 
21 #include "napi_common_ability.h"
22 #include "js_napi_common_ability.h"
23 #include "ability_process.h"
24 #include "element_name.h"
25 #include "hilog_wrapper.h"
26 #include "hitrace_meter.h"
27 #include "js_runtime_utils.h"
28 #ifdef SUPPORT_GRAPHICS
29 #include "js_window.h"
30 #endif
31 #include "napi_common_util.h"
32 #include "napi_context.h"
33 #include "napi_data_ability_helper.h"
34 #include "napi/native_api.h"
35 #include "napi/native_node_api.h"
36 #include "securec.h"
37 
38 using namespace OHOS::AAFwk;
39 using namespace OHOS::AppExecFwk;
40 
41 namespace OHOS {
42 namespace AppExecFwk {
43 using namespace OHOS::AbilityRuntime;
44 static int64_t dummyRequestCode_ = 0;
45 CallbackInfo g_aceCallbackInfo;
46 
47 const int PARA_SIZE_IS_ONE = 1;
48 const int PARA_SIZE_IS_TWO = 2;
49 
50 /**
51  * @brief FeatureAbility NAPI module registration.
52  *
53  * @param env The environment that the Node-API call is invoked under.
54  * @param exports An empty object via the exports parameter as a convenience.
55  *
56  * @return The return value from Init is treated as the exports object for the module.
57  */
FeatureAbilityInit(napi_env env,napi_value exports)58 napi_value FeatureAbilityInit(napi_env env, napi_value exports)
59 {
60     HILOG_DEBUG("called");
61     napi_property_descriptor properties[] = {
62         DECLARE_NAPI_FUNCTION("finishWithResult", NAPI_SetResult),
63         DECLARE_NAPI_FUNCTION("getAppType", NAPI_GetAppType),
64         DECLARE_NAPI_FUNCTION("getAbilityName", NAPI_GetAbilityName),
65         DECLARE_NAPI_FUNCTION("getAbilityInfo", NAPI_GetAbilityInfo),
66         DECLARE_NAPI_FUNCTION("getHapModuleInfo", NAPI_GetHapModuleInfo),
67         DECLARE_NAPI_FUNCTION("getDataAbilityHelper", NAPI_GetDataAbilityHelper),
68         DECLARE_NAPI_FUNCTION("acquireDataAbilityHelper", NAPI_AcquireDataAbilityHelper),
69         DECLARE_NAPI_FUNCTION("continueAbility", NAPI_FAContinueAbility),
70         DECLARE_NAPI_FUNCTION("getWantSync", NAPI_GetWantSync),
71     };
72     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
73 
74     return JsFeatureAbilityInit(env, exports);
75 }
76 
77 class JsFeatureAbility : public JsNapiCommon {
78 public:
79     JsFeatureAbility() = default;
80     virtual ~JsFeatureAbility() override = default;
81 
82     Ability* GetAbility(napi_env env);
83     static void Finalizer(napi_env env, void *data, void *hint);
84     static napi_value StartAbility(napi_env env, napi_callback_info info);
85     static napi_value HasWindowFocus(napi_env env, napi_callback_info info);
86     static napi_value ConnectAbility(napi_env env, napi_callback_info info);
87     static napi_value DisconnectAbility(napi_env env, napi_callback_info info);
88     static napi_value GetWant(napi_env env, napi_callback_info info);
89     static napi_value StartAbilityForResult(napi_env env, napi_callback_info info);
90     static napi_value GetContext(napi_env env, napi_callback_info info);
91     static napi_value FinishWithResult(napi_env env, napi_callback_info info);
92     static napi_value TerminateAbility(napi_env env, napi_callback_info info);
93     static napi_value GetWindow(napi_env env, napi_callback_info info);
94     std::shared_ptr<NativeReference> GetFAContext();
95     void SetFAContext(std::shared_ptr<NativeReference> context);
96 private:
97     napi_value OnStartAbilityForResult(napi_env env, NapiCallbackInfo& info);
98     napi_value OnFinishWithResult(napi_env env, NapiCallbackInfo& info);
99     napi_value OnGetWindow(napi_env env, napi_callback_info info);
100 #ifdef SUPPORT_GRAPHICS
101     napi_value OnHasWindowFocus(napi_env env, const NapiCallbackInfo& info);
102 #endif
103     std::shared_ptr<NativeReference> context_;
104 };
105 
Finalizer(napi_env env,void * data,void * hint)106 void JsFeatureAbility::Finalizer(napi_env env, void *data, void *hint)
107 {
108     HILOG_DEBUG("called");
109     std::unique_ptr<JsFeatureAbility>(static_cast<JsFeatureAbility*>(data));
110 }
111 
JsFeatureAbilityInit(napi_env env,napi_value exports)112 napi_value JsFeatureAbilityInit(napi_env env, napi_value exports)
113 {
114     HILOG_DEBUG("JsFeatureAbilityInit is called");
115     if (env == nullptr || exports == nullptr) {
116         HILOG_ERROR("Invalid input parameters");
117         return exports;
118     }
119 
120     if (!AppExecFwk::CheckTypeForNapiValue(env, exports, napi_object)) {
121         HILOG_ERROR("object is nullptr");
122         return exports;
123     }
124 
125     std::unique_ptr<JsFeatureAbility> jsFeatureAbility = std::make_unique<JsFeatureAbility>();
126     jsFeatureAbility->ability_ = jsFeatureAbility->GetAbility(env);
127     napi_value contextValue = CreateNapiJSContext(env);
128     if (contextValue != nullptr) {
129         napi_ref contextRef = nullptr;
130         napi_create_reference(env, contextValue, 1, &contextRef);
131         jsFeatureAbility->SetFAContext(
132             std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(contextRef)));
133     }
134     napi_wrap(env, exports, jsFeatureAbility.release(), JsFeatureAbility::Finalizer, nullptr, nullptr);
135 
136     const char *moduleName = "JsFeatureAbility";
137     BindNativeFunction(env, exports, "startAbility", moduleName, JsFeatureAbility::StartAbility);
138     BindNativeFunction(env, exports, "getWant", moduleName, JsFeatureAbility::GetWant);
139     BindNativeFunction(env, exports, "hasWindowFocus", moduleName, JsFeatureAbility::HasWindowFocus);
140     BindNativeFunction(env, exports, "connectAbility", moduleName, JsFeatureAbility::ConnectAbility);
141     BindNativeFunction(env, exports, "disconnectAbility", moduleName, JsFeatureAbility::DisconnectAbility);
142     BindNativeFunction(env, exports, "startAbilityForResult", moduleName, JsFeatureAbility::StartAbilityForResult);
143     BindNativeFunction(env, exports, "getContext", moduleName, JsFeatureAbility::GetContext);
144     BindNativeFunction(env, exports, "getWindow", moduleName, JsFeatureAbility::GetWindow);
145     BindNativeFunction(env, exports, "terminateSelfWithResult", moduleName, JsFeatureAbility::FinishWithResult);
146     BindNativeFunction(env, exports, "terminateSelf", moduleName, JsFeatureAbility::TerminateAbility);
147     return exports;
148 }
149 
SetFAContext(std::shared_ptr<NativeReference> context)150 void JsFeatureAbility::SetFAContext(std::shared_ptr<NativeReference> context)
151 {
152     context_ = context;
153 }
154 
GetFAContext()155 std::shared_ptr<NativeReference> JsFeatureAbility::GetFAContext()
156 {
157     return context_;
158 }
159 
StartAbility(napi_env env,napi_callback_info info)160 napi_value JsFeatureAbility::StartAbility(napi_env env, napi_callback_info info)
161 {
162     JsFeatureAbility *me = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
163     return (me != nullptr) ? me->JsStartAbility(env, info, AbilityType::PAGE) : nullptr;
164 }
165 
GetWant(napi_env env,napi_callback_info info)166 napi_value JsFeatureAbility::GetWant(napi_env env, napi_callback_info info)
167 {
168     JsFeatureAbility *me = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
169     return (me != nullptr) ? me->JsGetWant(env, info, AbilityType::PAGE) : nullptr;
170 }
171 
HasWindowFocus(napi_env env,napi_callback_info info)172 napi_value JsFeatureAbility::HasWindowFocus(napi_env env, napi_callback_info info)
173 {
174 #ifdef SUPPORT_GRAPHICS
175     GET_NAPI_INFO_AND_CALL(env, info, JsFeatureAbility, OnHasWindowFocus);
176 #else
177     return nullptr;
178 #endif
179 }
180 
ConnectAbility(napi_env env,napi_callback_info info)181 napi_value JsFeatureAbility::ConnectAbility(napi_env env, napi_callback_info info)
182 {
183     JsFeatureAbility *me = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
184     return (me != nullptr) ? me->JsConnectAbility(env, info, AbilityType::PAGE) : nullptr;
185 }
186 
DisconnectAbility(napi_env env,napi_callback_info info)187 napi_value JsFeatureAbility::DisconnectAbility(napi_env env, napi_callback_info info)
188 {
189     JsFeatureAbility *me = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
190     return (me != nullptr) ? me->JsDisConnectAbility(env, info, AbilityType::PAGE) : nullptr;
191 }
192 
StartAbilityForResult(napi_env env,napi_callback_info info)193 napi_value JsFeatureAbility::StartAbilityForResult(napi_env env, napi_callback_info info)
194 {
195     GET_NAPI_INFO_AND_CALL(env, info, JsFeatureAbility, OnStartAbilityForResult);
196 }
197 
GetContext(napi_env env,napi_callback_info info)198 napi_value JsFeatureAbility::GetContext(napi_env env, napi_callback_info info)
199 {
200     JsFeatureAbility *me = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
201     if (me != nullptr) {
202         std::shared_ptr<NativeReference> contextObj = me->GetFAContext();
203         if (contextObj != nullptr) {
204             return contextObj->GetNapiValue();
205         }
206         napi_value contextValue = me->JsGetContext(env, info, AbilityType::PAGE);
207         if (contextValue != nullptr) {
208             napi_ref contextRef = nullptr;
209             napi_create_reference(env, contextValue, 1, &contextRef);
210             me->SetFAContext(std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(contextRef)));
211             return contextValue;
212         }
213     }
214     return nullptr;
215 }
216 
FinishWithResult(napi_env env,napi_callback_info info)217 napi_value JsFeatureAbility::FinishWithResult(napi_env env, napi_callback_info info)
218 {
219     GET_NAPI_INFO_AND_CALL(env, info, JsFeatureAbility, OnFinishWithResult);
220 }
221 
TerminateAbility(napi_env env,napi_callback_info info)222 napi_value JsFeatureAbility::TerminateAbility(napi_env env, napi_callback_info info)
223 {
224     GET_NAPI_INFO_AND_CALL(env, info, JsFeatureAbility, JsTerminateAbility);
225 }
226 
227 #ifdef SUPPORT_GRAPHICS
OnHasWindowFocus(napi_env env,const NapiCallbackInfo & info)228 napi_value JsFeatureAbility::OnHasWindowFocus(napi_env env, const NapiCallbackInfo& info)
229 {
230     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
231     if (info.argc > ARGS_ONE || info.argc < ARGS_ZERO) {
232         HILOG_ERROR(" wrong number of arguments.");
233         return CreateJsUndefined(env);
234     }
235     NapiAsyncTask::CompleteCallback complete =
236         [obj = this](napi_env env, NapiAsyncTask &task, int32_t status) {
237             if (obj->ability_ == nullptr) {
238                 HILOG_ERROR("HasWindowFocus execute error, the ability is nullptr");
239                 task.Reject(env, CreateJsError(env, NAPI_ERR_ACE_ABILITY, "HasWindowFocus failed"));
240                 return;
241             }
242             auto ret = obj->ability_->HasWindowFocus();
243             task.Resolve(env, CreateJsValue(env, ret));
244         };
245     napi_value result = nullptr;
246     napi_value lastParam = (info.argc == ARGS_ZERO) ? nullptr : info.argv[PARAM0];
247     NapiAsyncTask::ScheduleHighQos("JSFeatureAbility::OnHasWindowFocus",
248         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
249     HILOG_DEBUG("OnHasWindowFocus is called end");
250     return result;
251 }
252 #endif
253 
GetAbility(napi_env env)254 Ability* JsFeatureAbility::GetAbility(napi_env env)
255 {
256     napi_status ret;
257     napi_value global = nullptr;
258     const napi_extended_error_info *errorInfo = nullptr;
259     ret = napi_get_global(env, &global);
260     if (ret != napi_ok) {
261         napi_get_last_error_info(env, &errorInfo);
262         HILOG_ERROR("get_global=%{public}d err:%{public}s", ret, errorInfo->error_message);
263         return nullptr;
264     }
265 
266     napi_value abilityObj = nullptr;
267     ret = napi_get_named_property(env, global, "ability", &abilityObj);
268     if (ret != napi_ok) {
269         napi_get_last_error_info(env, &errorInfo);
270         HILOG_ERROR("get_named_property=%{public}d err:%{public}s", ret, errorInfo->error_message);
271         return nullptr;
272     }
273 
274     Ability *ability = nullptr;
275     ret = napi_get_value_external(env, abilityObj, reinterpret_cast<void **>(&ability));
276     if (ret != napi_ok) {
277         napi_get_last_error_info(env, &errorInfo);
278         HILOG_ERROR("get_value_external=%{public}d err:%{public}s", ret, errorInfo->error_message);
279         return nullptr;
280     }
281 
282     return ability;
283 }
284 
OnStartAbilityForResult(napi_env env,NapiCallbackInfo & info)285 napi_value JsFeatureAbility::OnStartAbilityForResult(napi_env env, NapiCallbackInfo& info)
286 {
287     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
288     if (info.argc < ARGS_ONE || info.argc > ARGS_TWO) {
289         HILOG_ERROR("wrong number of arguments.");
290         return CreateJsUndefined(env);
291     }
292 
293     if (ability_ == nullptr) {
294         HILOG_ERROR("ability is nullptr");
295         return CreateJsUndefined(env);
296     }
297 
298     std::shared_ptr<CallAbilityParam> abilityParam = std::make_shared<CallAbilityParam>();
299     std::shared_ptr<CallbackInfo> startAbilityCallback = std::make_shared<CallbackInfo>();
300     startAbilityCallback->env = env;
301 
302     if (UnwrapForResultParam(*abilityParam, env, info.argv[0]) == nullptr) {
303         HILOG_ERROR("OnStartAbilityForResult UnwrapForResultParam failed.");
304         startAbilityCallback->errCode = NAPI_ERR_PARAM_INVALID;
305     }
306 
307     napi_value result = nullptr;
308     napi_value lastParam = (info.argc == ARGS_TWO) ? info.argv[ARGS_ONE] : nullptr;
309     startAbilityCallback->napiAsyncTask =
310         AbilityRuntime::CreateAsyncTaskWithLastParam(env, lastParam, nullptr, nullptr, &result).release();
311 
312     AbilityProcess::GetInstance()->AddAbilityResultCallback(ability_,
313         *abilityParam, startAbilityCallback->errCode, *startAbilityCallback);
314 
315     if (startAbilityCallback->errCode == NAPI_ERR_NO_ERROR) {
316         startAbilityCallback->errCode = AbilityProcess::GetInstance()->StartAbility(ability_,
317             *abilityParam, *startAbilityCallback);
318     }
319 
320     if (startAbilityCallback->errCode != NAPI_ERR_NO_ERROR) {
321         // Callback the errcode when StartAbilityForResult failed.
322         Want resultData;
323         AbilityProcess::GetInstance()->OnAbilityResult(ability_, abilityParam->requestCode, 0, resultData);
324     }
325 
326     return result;
327 }
328 
OnFinishWithResult(napi_env env,NapiCallbackInfo & info)329 napi_value JsFeatureAbility::OnFinishWithResult(napi_env env, NapiCallbackInfo& info)
330 {
331     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
332     if (info.argc > ARGS_TWO || info.argc < ARGS_ONE) {
333         HILOG_ERROR("wrong number of arguments.");
334         return CreateJsUndefined(env);
335     }
336 
337     if (!AppExecFwk::IsTypeForNapiValue(env, info.argv[0], napi_object)) {
338         HILOG_ERROR("OnFinishWithResult param is not object.");
339         return CreateJsUndefined(env);
340     }
341 
342     CallAbilityParam param;
343     napi_value jsRequestCode = nullptr;
344     napi_get_named_property(env, info.argv[0], "resultCode", &jsRequestCode);
345     if (!AppExecFwk::IsTypeForNapiValue(env, jsRequestCode, napi_number)) {
346         HILOG_ERROR("OnFinishWithResult resultCode type failed.");
347         return CreateJsUndefined(env);
348     }
349     if (!ConvertFromJsValue(env, jsRequestCode, param.requestCode)) {
350         HILOG_ERROR("OnFinishWithResult convert resultCode failed.");
351         return CreateJsUndefined(env);
352     }
353     bool hasWant = false;
354     napi_has_named_property(env, info.argv[0], "want", &hasWant);
355     if (hasWant) {
356         napi_value jsWant = nullptr;
357         napi_get_named_property(env, info.argv[0], "want", &jsWant);
358         if (!AppExecFwk::IsTypeForNapiValue(env, jsWant, napi_object)) {
359             HILOG_ERROR("OnFinishWithResult want type failed.");
360             return CreateJsUndefined(env);
361         }
362         if (!UnwrapWant(env, jsWant, param.want)) {
363             HILOG_ERROR("OnFinishWithResult UnwrapWant failed.");
364             return CreateJsUndefined(env);
365         }
366     }
367 
368     NapiAsyncTask::CompleteCallback complete = [obj = this, param](napi_env env, NapiAsyncTask &task, int32_t status) {
369         if (obj->ability_ != nullptr) {
370             obj->ability_->SetResult(param.requestCode, param.want);
371             obj->ability_->TerminateAbility();
372         } else {
373             HILOG_ERROR("OnFinishWithResult ability is nullptr");
374         }
375         task.Resolve(env, CreateJsNull(env));
376     };
377     napi_value result = nullptr;
378     napi_value lastParam = (info.argc >= ARGS_TWO) ? info.argv[ARGS_ONE] : nullptr;
379     NapiAsyncTask::ScheduleHighQos("JSFeatureAbility::OnFinishWithResult",
380         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
381     return result;
382 }
383 
384 #ifdef SUPPORT_GRAPHICS
GetWindow(napi_env env,napi_callback_info info)385 napi_value JsFeatureAbility::GetWindow(napi_env env, napi_callback_info info)
386 {
387     if (env == nullptr || info == nullptr) {
388         HILOG_ERROR("JsFeatureAbility::%{public}s is called, but input parameters %{public}s is nullptr",
389             __func__, ((env == nullptr) ? "env" : "info"));
390         return nullptr;
391     }
392 
393     auto object = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
394     if (object == nullptr) {
395         HILOG_ERROR("CheckParamsAndGetThis return nullptr");
396         return nullptr;
397     }
398 
399     return object->OnGetWindow(env, info);
400 }
401 
OnGetWindow(napi_env env,napi_callback_info info)402 napi_value JsFeatureAbility::OnGetWindow(napi_env env, napi_callback_info info)
403 {
404     HILOG_DEBUG("%{public}s called", __func__);
405     size_t argc = ARGS_MAX_COUNT;
406     napi_value argv[ARGS_MAX_COUNT] = { nullptr };
407     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
408     if (argc > ARGS_ONE) {
409         HILOG_ERROR("input params count error, argc=%{public}zu", argc);
410         return CreateJsUndefined(env);
411     }
412 
413     auto complete = [obj = this] (napi_env env, NapiAsyncTask& task, int32_t status) {
414         if (obj->ability_ == nullptr) {
415             HILOG_ERROR("OnGetWindow task execute error, the ability is nullptr");
416             task.Resolve(env, CreateJsNull(env));
417             return;
418         }
419         auto window = obj->ability_->GetWindow();
420         task.Resolve(env, OHOS::Rosen::CreateJsWindowObject(env, window));
421     };
422 
423     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
424     napi_value result = nullptr;
425     NapiAsyncTask::ScheduleHighQos("JsFeatureAbility::OnGetWindow",
426         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
427 
428     return result;
429 }
430 #else
431 
GetWindow(napi_env env,napi_callback_info info)432 napi_value JsFeatureAbility::GetWindow(napi_env env, napi_callback_info info)
433 {
434     return nullptr;
435 }
436 
OnGetWindow(napi_env env,napi_callback_info info)437 napi_value JsFeatureAbility::OnGetWindow(napi_env env, napi_callback_info info)
438 {
439     return nullptr;
440 }
441 #endif
442 
443 /**
444  * @brief FeatureAbility NAPI method : setResult.
445  *
446  * @param env The environment that the Node-API call is invoked under.
447  * @param info The callback info passed into the callback function.
448  *
449  * @return The return value from NAPI C++ to JS for the module.
450  */
NAPI_SetResult(napi_env env,napi_callback_info info)451 napi_value NAPI_SetResult(napi_env env, napi_callback_info info)
452 {
453     HILOG_INFO("%{public}s,called", __func__);
454     AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
455     if (asyncCallbackInfo == nullptr) {
456         HILOG_ERROR("%{public}s,asyncCallbackInfo == nullptr", __func__);
457         return WrapVoidToJS(env);
458     }
459 
460     napi_value ret = SetResultWrap(env, info, asyncCallbackInfo);
461     if (ret == nullptr) {
462         HILOG_ERROR("%{public}s,ret == nullptr", __func__);
463         if (asyncCallbackInfo != nullptr) {
464             delete asyncCallbackInfo;
465             asyncCallbackInfo = nullptr;
466         }
467         ret = WrapVoidToJS(env);
468     }
469     HILOG_INFO("%{public}s,end", __func__);
470     return ret;
471 }
472 
473 /**
474  * @brief SetResult processing function.
475  *
476  * @param env The environment that the Node-API call is invoked under.
477  * @param asyncCallbackInfo Process data asynchronously.
478  *
479  * @return Return JS data successfully, otherwise return nullptr.
480  */
SetResultWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)481 napi_value SetResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
482 {
483     HILOG_INFO("%{public}s,called", __func__);
484     size_t argcAsync = 2;
485     const size_t argcPromise = 1;
486     const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT;
487     napi_value args[ARGS_MAX_COUNT] = {nullptr};
488     napi_value ret = nullptr;
489 
490     NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
491     if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) {
492         HILOG_ERROR("%{public}s, Fail argument count.", __func__);
493         return nullptr;
494     }
495 
496     CallAbilityParam param;
497     if (UnwrapAbilityResult(param, env, args[0]) == nullptr) {
498         HILOG_ERROR("%{public}s, call unwrapWant failed.", __func__);
499         return nullptr;
500     }
501     asyncCallbackInfo->param = param;
502 
503     if (argcAsync > argcPromise) {
504         ret = SetResultAsync(env, args, 1, asyncCallbackInfo);
505     } else {
506         ret = SetResultPromise(env, asyncCallbackInfo);
507     }
508     HILOG_INFO("%{public}s,end", __func__);
509     return ret;
510 }
511 
SetResultAsync(napi_env env,napi_value * args,const size_t argCallback,AsyncCallbackInfo * asyncCallbackInfo)512 napi_value SetResultAsync(
513     napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo)
514 {
515     HILOG_INFO("%{public}s, asyncCallback.", __func__);
516     if (args == nullptr || asyncCallbackInfo == nullptr) {
517         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
518         return nullptr;
519     }
520     napi_value resourceName = nullptr;
521     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
522 
523     napi_valuetype valuetype = napi_undefined;
524     NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype));
525     if (valuetype == napi_function) {
526         napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback);
527     }
528 
529     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
530         [](napi_env env, void *data) {
531             HILOG_INFO("NAPI_SetResult, worker pool thread enter.");
532             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
533             if (asyncCallbackInfo == nullptr) {
534                 HILOG_ERROR("NAPI_SetResult, execute asyncCallbackInfo is nullptr");
535                 return;
536             }
537 
538             if (asyncCallbackInfo->ability != nullptr) {
539                 asyncCallbackInfo->ability->SetResult(
540                     asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want);
541                 asyncCallbackInfo->ability->TerminateAbility();
542             } else {
543                 HILOG_ERROR("NAPI_SetResult, ability == null");
544             }
545             HILOG_INFO("NAPI_SetResult, worker pool thread execute exit.");
546         },
547         [](napi_env env, napi_status status, void *data) {
548             HILOG_INFO("NAPI_SetResult, main event thread complete.");
549             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
550             if (asyncCallbackInfo == nullptr) {
551                 HILOG_ERROR("NAPI_SetResult, complete asyncCallbackInfo is nullptr");
552                 return;
553             }
554             napi_value result[ARGS_TWO] = {nullptr};
555             napi_value callback = nullptr;
556             napi_value undefined = nullptr;
557             napi_value callResult = nullptr;
558             napi_get_undefined(env, &undefined);
559             result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
560             napi_get_null(env, &result[PARAM1]);
561             napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
562             napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
563 
564             if (asyncCallbackInfo->cbInfo.callback != nullptr) {
565                 HILOG_DEBUG("napi_delete_reference");
566                 napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
567             }
568             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
569             delete asyncCallbackInfo;
570             HILOG_INFO("NAPI_SetResult, main event thread complete end.");
571         },
572         static_cast<void *>(asyncCallbackInfo),
573         &asyncCallbackInfo->asyncWork));
574     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
575     napi_value result = nullptr;
576     NAPI_CALL(env, napi_get_null(env, &result));
577     HILOG_INFO("%{public}s, asyncCallback end", __func__);
578     return result;
579 }
580 
SetResultPromise(napi_env env,AsyncCallbackInfo * asyncCallbackInfo)581 napi_value SetResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo)
582 {
583     HILOG_INFO("%{public}s, promise.", __func__);
584     if (asyncCallbackInfo == nullptr) {
585         HILOG_ERROR("SetResultPromise, param == nullptr.");
586         return nullptr;
587     }
588     napi_value resourceName = nullptr;
589     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
590     napi_deferred deferred;
591     napi_value promise = nullptr;
592     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
593     asyncCallbackInfo->deferred = deferred;
594 
595     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
596         [](napi_env env, void *data) {
597             HILOG_INFO("NAPI_SetResult, worker pool thread execute.");
598             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
599             if (asyncCallbackInfo == nullptr) {
600                 HILOG_ERROR("NAPI_SetResult promise, execute asyncCallbackInfo is nullptr");
601                 return;
602             }
603 
604             if (asyncCallbackInfo->ability != nullptr) {
605                 asyncCallbackInfo->ability->SetResult(
606                     asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want);
607                 asyncCallbackInfo->ability->TerminateAbility();
608             } else {
609                 HILOG_ERROR("NAPI_SetResult, ability == nullptr");
610             }
611             HILOG_INFO("NAPI_SetResult, worker pool thread execute end.");
612         },
613         [](napi_env env, napi_status status, void *data) {
614             HILOG_INFO("NAPI_SetResult,  main event thread complete.");
615             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
616             if (asyncCallbackInfo == nullptr) {
617                 HILOG_ERROR("NAPI_SetResult promise, execute asyncCallbackInfo is nullptr");
618                 return;
619             }
620             napi_value result = nullptr;
621             napi_get_null(env, &result);
622             napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
623             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
624             delete asyncCallbackInfo;
625             HILOG_INFO("NAPI_SetResult,  main event thread complete end.");
626         },
627         static_cast<void *>(asyncCallbackInfo),
628         &asyncCallbackInfo->asyncWork));
629     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
630     HILOG_INFO("%{public}s, promise end", __func__);
631     return promise;
632 }
633 
634 EXTERN_C_START
635 /**
636  * @brief The interface of onAbilityResult provided for ACE to call back to JS.
637  *
638  * @param requestCode Indicates the request code returned after the ability is started.
639  * @param resultCode Indicates the result code returned after the ability is started.
640  * @param resultData Indicates the data returned after the ability is started.
641  * @param cb The environment and call back info that the Node-API call is invoked under.
642  *
643  * @return The return value from NAPI C++ to JS for the module.
644  */
CallOnAbilityResult(int requestCode,int resultCode,const Want & resultData,CallbackInfo callbackInfo)645 void CallOnAbilityResult(int requestCode, int resultCode, const Want &resultData, CallbackInfo callbackInfo)
646 {
647     HILOG_INFO("%{public}s,called", __func__);
648     if (callbackInfo.env == nullptr) {
649         HILOG_ERROR("CallOnAbilityResult cb.env is nullptr.");
650         return;
651     }
652 
653     if (callbackInfo.napiAsyncTask == nullptr) {
654         HILOG_ERROR("CallOnAbilityResult cb.asyncTask is nullptr.");
655         return;
656     }
657 
658     uv_loop_t *loop = nullptr;
659     napi_get_uv_event_loop(callbackInfo.env, &loop);
660     if (loop == nullptr) {
661         HILOG_ERROR("loop instance is nullptr");
662         return;
663     }
664 
665     auto work = new uv_work_t;
666     auto onAbilityCB = new (std::nothrow) OnAbilityCallback;
667     onAbilityCB->requestCode = requestCode;
668     onAbilityCB->resultCode = resultCode;
669     onAbilityCB->resultData = resultData;
670     onAbilityCB->cb = callbackInfo;
671 
672     work->data = static_cast<void *>(onAbilityCB);
673 
674     int rev = uv_queue_work(
675         loop,
676         work,
677         [](uv_work_t *work) {},
678         [](uv_work_t *work, int status) {
679             HILOG_INFO("CallOnAbilityResult, uv_queue_work");
680             // JS Thread
681             if (work == nullptr) {
682                 HILOG_ERROR("%{public}s, uv_queue_work work == nullptr.", __func__);
683                 return;
684             }
685             auto onAbilityCB = static_cast<OnAbilityCallback *>(work->data);
686             if (onAbilityCB == nullptr) {
687                 HILOG_ERROR("%{public}s, uv_queue_work onAbilityCB == nullptr.", __func__);
688                 delete work;
689                 work = nullptr;
690                 return;
691             }
692 
693             if (onAbilityCB->cb.errCode != ERR_OK) {
694                 int32_t errCode = GetStartAbilityErrorCode(onAbilityCB->cb.errCode);
695                 onAbilityCB->cb.napiAsyncTask->Reject(onAbilityCB->cb.env,
696                     CreateJsError(onAbilityCB->cb.env, errCode, "StartAbilityForResult Error"));
697                 delete onAbilityCB->cb.napiAsyncTask;
698                 onAbilityCB->cb.napiAsyncTask = nullptr;
699                 delete onAbilityCB;
700                 onAbilityCB = nullptr;
701                 delete work;
702                 work = nullptr;
703                 return;
704             }
705 
706             napi_value objValue = nullptr;
707             napi_create_object(onAbilityCB->cb.env, &objValue);
708 
709             napi_set_named_property(onAbilityCB->cb.env,
710                 objValue, "resultCode", CreateJsValue(onAbilityCB->cb.env, onAbilityCB->resultCode));
711             napi_set_named_property(onAbilityCB->cb.env,
712                 objValue, "want", CreateJsWant(onAbilityCB->cb.env, onAbilityCB->resultData));
713 
714             onAbilityCB->cb.napiAsyncTask->Resolve(onAbilityCB->cb.env, objValue);
715             delete onAbilityCB->cb.napiAsyncTask;
716             onAbilityCB->cb.napiAsyncTask = nullptr;
717             delete onAbilityCB;
718             onAbilityCB = nullptr;
719             delete work;
720             work = nullptr;
721             HILOG_INFO("CallOnAbilityResult, uv_queue_work end");
722         });
723     if (rev != 0) {
724         if (onAbilityCB != nullptr) {
725             delete onAbilityCB;
726             onAbilityCB = nullptr;
727         }
728         if (work != nullptr) {
729             delete work;
730             work = nullptr;
731         }
732     }
733     HILOG_INFO("%{public}s,end", __func__);
734 }
735 EXTERN_C_END
736 
InnerUnwrapWant(napi_env env,napi_value args,Want & want)737 bool InnerUnwrapWant(napi_env env, napi_value args, Want &want)
738 {
739     HILOG_INFO("%{public}s called", __func__);
740     napi_valuetype valueType = napi_undefined;
741     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
742     if (valueType != napi_object) {
743         HILOG_ERROR("%{public}s wrong argument type", __func__);
744         return false;
745     }
746 
747     napi_value jsWant = GetPropertyValueByPropertyName(env, args, "want", napi_object);
748     if (jsWant == nullptr) {
749         HILOG_ERROR("%{public}s jsWant == nullptr", __func__);
750         return false;
751     }
752 
753     return UnwrapWant(env, jsWant, want);
754 }
755 
756 /**
757  * @brief Parse the parameters.
758  *
759  * @param param Indicates the parameters saved the parse result.
760  * @param env The environment that the Node-API call is invoked under.
761  * @param args Indicates the arguments passed into the callback.
762  *
763  * @return The return value from NAPI C++ to JS for the module.
764  */
UnwrapForResultParam(CallAbilityParam & param,napi_env env,napi_value args)765 napi_value UnwrapForResultParam(CallAbilityParam &param, napi_env env, napi_value args)
766 {
767     HILOG_INFO("%{public}s,called", __func__);
768     // dummy requestCode for NativeC++ interface and onabilityresult callback
769     param.requestCode = dummyRequestCode_;
770     param.forResultOption = true;
771     dummyRequestCode_ = (dummyRequestCode_ < INT32_MAX) ? (dummyRequestCode_ + 1) : 0;
772     HILOG_INFO("%{public}s, reqCode=%{public}d forResultOption=%{public}d.",
773         __func__,
774         param.requestCode,
775         param.forResultOption);
776 
777     // unwrap the param : want object
778     if (!InnerUnwrapWant(env, args, param.want)) {
779         HILOG_ERROR("Failed to InnerUnwrapWant");
780         return nullptr;
781     }
782 
783     // unwrap the param : abilityStartSetting (optional)
784     napi_value jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSettings", napi_object);
785     if (jsSettingObj == nullptr) {
786         jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSetting", napi_object);
787     }
788     if (jsSettingObj != nullptr) {
789         param.setting = AbilityStartSetting::GetEmptySetting();
790         if (!UnwrapAbilityStartSetting(env, jsSettingObj, *(param.setting))) {
791             HILOG_ERROR("%{public}s, unwrap abilityStartSetting failed.", __func__);
792         }
793         HILOG_INFO("%{public}s abilityStartSetting", __func__);
794     }
795 
796     napi_value result;
797     NAPI_CALL(env, napi_create_int32(env, 1, &result));
798     HILOG_INFO("%{public}s,end", __func__);
799     return result;
800 }
801 
802 /**
803  * @brief Parse the abilityResult parameters.
804  *
805  * @param param Indicates the want parameters saved the parse result.
806  * @param env The environment that the Node-API call is invoked under.
807  * @param args Indicates the arguments passed into the callback.
808  *
809  * @return The return value from NAPI C++ to JS for the module.
810  */
UnwrapAbilityResult(CallAbilityParam & param,napi_env env,napi_value args)811 napi_value UnwrapAbilityResult(CallAbilityParam &param, napi_env env, napi_value args)
812 {
813     HILOG_INFO("%{public}s,called", __func__);
814     // unwrap the param
815     napi_valuetype valueType = napi_undefined;
816     NAPI_CALL(env, napi_typeof(env, args, &valueType));
817     NAPI_ASSERT(env, valueType == napi_object, "param type mismatch!");
818     // get resultCode property
819     napi_value property = nullptr;
820     NAPI_CALL(env, napi_get_named_property(env, args, "resultCode", &property));
821     NAPI_CALL(env, napi_typeof(env, property, &valueType));
822     NAPI_ASSERT(env, valueType == napi_number, "property type mismatch!");
823     NAPI_CALL(env, napi_get_value_int32(env, property, &param.requestCode));
824     HILOG_INFO("%{public}s, requestCode=%{public}d.", __func__, param.requestCode);
825 
826     // unwrap the param : want object
827     InnerUnwrapWant(env, args, param.want);
828 
829     napi_value result;
830     NAPI_CALL(env, napi_create_int32(env, 1, &result));
831     HILOG_INFO("%{public}s,end", __func__);
832     return result;
833 }
834 
835 /**
836  * @brief GetWantSyncWrap processing function.
837  *
838  * @param env The environment that the Node-API call is invoked under.
839  * @param CallingBundleCB Process data asynchronously.
840  *
841  * @return Return JS data successfully, otherwise return nullptr.
842  */
GetWantSyncWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)843 napi_value GetWantSyncWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
844 {
845     HILOG_INFO("%{public}s, called.", __func__);
846     if (asyncCallbackInfo == nullptr) {
847         HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__);
848         return nullptr;
849     }
850 
851     asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR;
852     if (asyncCallbackInfo->ability == nullptr) {
853         HILOG_ERROR("%{public}s, ability == nullptr", __func__);
854         asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY;
855         return nullptr;
856     }
857 
858     std::shared_ptr<AAFwk::Want> ptrWant = asyncCallbackInfo->ability->GetWant();
859     if (ptrWant != nullptr) {
860         asyncCallbackInfo->param.want = *ptrWant;
861     } else {
862         asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_CALL_INVALID;
863     }
864 
865     napi_value result = nullptr;
866     if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) {
867         result = WrapWant(env, asyncCallbackInfo->param.want);
868     } else {
869         result = WrapVoidToJS(env);
870     }
871     HILOG_INFO("%{public}s, end.", __func__);
872     return result;
873 }
874 
875 /**
876  * @brief Get want(Sync).
877  *
878  * @param env The environment that the Node-API call is invoked under.
879  * @param info The callback info passed into the callback function.
880  *
881  * @return The return value from NAPI C++ to JS for the module.
882  */
NAPI_GetWantSync(napi_env env,napi_callback_info info)883 napi_value NAPI_GetWantSync(napi_env env, napi_callback_info info)
884 {
885     HILOG_INFO("%{public}s called.", __func__);
886     AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
887     if (asyncCallbackInfo == nullptr) {
888         return WrapVoidToJS(env);
889     }
890 
891     asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR;
892     napi_value ret = GetWantSyncWrap(env, info, asyncCallbackInfo);
893 
894     delete asyncCallbackInfo;
895     asyncCallbackInfo = nullptr;
896 
897     if (ret == nullptr) {
898         ret = WrapVoidToJS(env);
899         HILOG_ERROR("%{public}s ret == null", __func__);
900     } else {
901         HILOG_INFO("%{public}s, exit.", __func__);
902     }
903     return ret;
904 }
905 
906 /**
907  * @brief Obtains the type of this application.
908  *
909  * @param env The environment that the Node-API call is invoked under.
910  * @param info The callback info passed into the callback function.
911  *
912  * @return The return value from NAPI C++ to JS for the module.
913  */
NAPI_GetAppType(napi_env env,napi_callback_info info)914 napi_value NAPI_GetAppType(napi_env env, napi_callback_info info)
915 {
916     HILOG_INFO("%{public}s called.", __func__);
917     return NAPI_GetAppTypeCommon(env, info, AbilityType::PAGE);
918 }
919 
920 /**
921  * @brief Obtains the class name in this ability name, without the prefixed bundle name.
922  *
923  * @param env The environment that the Node-API call is invoked under.
924  * @param info The callback info passed into the callback function.
925  *
926  * @return The return value from NAPI C++ to JS for the module.
927  */
NAPI_GetAbilityName(napi_env env,napi_callback_info info)928 napi_value NAPI_GetAbilityName(napi_env env, napi_callback_info info)
929 {
930     HILOG_INFO("%{public}s called.", __func__);
931     return NAPI_GetAbilityNameCommon(env, info, AbilityType::PAGE);
932 }
933 
934 /**
935  * @brief Obtains information about the current ability.
936  *
937  * @param env The environment that the Node-API call is invoked under.
938  * @param info The callback info passed into the callback function.
939  *
940  * @return The return value from NAPI C++ to JS for the module.
941  */
NAPI_GetAbilityInfo(napi_env env,napi_callback_info info)942 napi_value NAPI_GetAbilityInfo(napi_env env, napi_callback_info info)
943 {
944     HILOG_INFO("%{public}s called.", __func__);
945     return NAPI_GetAbilityInfoCommon(env, info, AbilityType::PAGE);
946 }
947 
948 /**
949  * @brief Obtains the HapModuleInfo object of the application.
950  *
951  * @param env The environment that the Node-API call is invoked under.
952  * @param info The callback info passed into the callback function.
953  *
954  * @return The return value from NAPI C++ to JS for the module.
955  */
NAPI_GetHapModuleInfo(napi_env env,napi_callback_info info)956 napi_value NAPI_GetHapModuleInfo(napi_env env, napi_callback_info info)
957 {
958     HILOG_INFO("%{public}s called.", __func__);
959     return NAPI_GetHapModuleInfoCommon(env, info, AbilityType::PAGE);
960 }
961 
962 /**
963  * @brief FeatureAbility NAPI method : getDataAbilityHelper.
964  *
965  * @param env The environment that the Node-API call is invoked under.
966  * @param info The callback info passed into the callback function.
967  *
968  * @return The return value from NAPI C++ to JS for the module.
969  */
NAPI_GetDataAbilityHelper(napi_env env,napi_callback_info info)970 napi_value NAPI_GetDataAbilityHelper(napi_env env, napi_callback_info info)
971 {
972     HILOG_INFO("%{public}s,called", __func__);
973     DataAbilityHelperCB *dataAbilityHelperCB = new (std::nothrow) DataAbilityHelperCB;
974     if (dataAbilityHelperCB == nullptr) {
975         HILOG_ERROR("%{public}s, dataAbilityHelperCB == nullptr", __func__);
976         return WrapVoidToJS(env);
977     }
978     dataAbilityHelperCB->cbBase.cbInfo.env = env;
979     napi_value ret = GetDataAbilityHelperWrap(env, info, dataAbilityHelperCB);
980     if (ret == nullptr) {
981         HILOG_ERROR("%{public}s, ret == nullptr", __func__);
982         if (dataAbilityHelperCB != nullptr) {
983             delete dataAbilityHelperCB;
984             dataAbilityHelperCB = nullptr;
985         }
986         ret = WrapVoidToJS(env);
987     }
988     HILOG_INFO("%{public}s,end", __func__);
989     return ret;
990 }
991 
992 /**
993  * @brief getDataAbilityHelper processing function.
994  *
995  * @param env The environment that the Node-API call is invoked under.
996  * @param dataAbilityHelperCB Process data asynchronously.
997  *
998  * @return Return JS data successfully, otherwise return nullptr.
999  */
GetDataAbilityHelperWrap(napi_env env,napi_callback_info info,DataAbilityHelperCB * dataAbilityHelperCB)1000 napi_value GetDataAbilityHelperWrap(napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB)
1001 {
1002     HILOG_INFO("%{public}s,called", __func__);
1003     if (dataAbilityHelperCB == nullptr) {
1004         HILOG_ERROR("%{public}s,dataAbilityHelperCB == nullptr", __func__);
1005         return nullptr;
1006     }
1007 
1008     size_t argcAsync = 2;
1009     const size_t argcPromise = 1;
1010     const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT;
1011     napi_value args[ARGS_MAX_COUNT] = {nullptr};
1012     napi_value ret = nullptr;
1013 
1014     NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
1015     if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) {
1016         HILOG_ERROR("%{public}s, Wrong argument count.", __func__);
1017         return nullptr;
1018     }
1019 
1020     napi_valuetype valuetype = napi_undefined;
1021     NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype));
1022     if (valuetype == napi_string) {
1023         NAPI_CALL(env, napi_create_reference(env, args[PARAM0], 1, &dataAbilityHelperCB->uri));
1024     }
1025 
1026     if (argcAsync > argcPromise) {
1027         ret = GetDataAbilityHelperAsync(env, args, 1, dataAbilityHelperCB);
1028     } else {
1029         ret = GetDataAbilityHelperPromise(env, dataAbilityHelperCB);
1030     }
1031     HILOG_INFO("%{public}s,end", __func__);
1032     return ret;
1033 }
1034 
GetDataAbilityHelperAsync(napi_env env,napi_value * args,const size_t argCallback,DataAbilityHelperCB * dataAbilityHelperCB)1035 napi_value GetDataAbilityHelperAsync(
1036     napi_env env, napi_value *args, const size_t argCallback, DataAbilityHelperCB *dataAbilityHelperCB)
1037 {
1038     HILOG_INFO("%{public}s, asyncCallback.", __func__);
1039     if (args == nullptr || dataAbilityHelperCB == nullptr) {
1040         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
1041         return nullptr;
1042     }
1043     napi_value resourceName = nullptr;
1044     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1045 
1046     napi_valuetype valuetype = napi_undefined;
1047     NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype));
1048     if (valuetype == napi_function) {
1049         NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &dataAbilityHelperCB->cbBase.cbInfo.callback));
1050     }
1051 
1052     NAPI_CALL(env,
1053         napi_create_async_work(env, nullptr, resourceName,
1054             [](napi_env env, void *data) { HILOG_INFO("NAPI_GetDataAbilityHelper, worker pool thread execute."); },
1055             GetDataAbilityHelperAsyncCompleteCB,
1056             static_cast<void *>(dataAbilityHelperCB),
1057             &dataAbilityHelperCB->cbBase.asyncWork));
1058     NAPI_CALL(env, napi_queue_async_work_with_qos(env, dataAbilityHelperCB->cbBase.asyncWork,
1059         napi_qos_user_initiated));
1060     napi_value result = nullptr;
1061     NAPI_CALL(env, napi_get_null(env, &result));
1062     HILOG_INFO("%{public}s, asyncCallback end", __func__);
1063     return result;
1064 }
1065 
GetDataAbilityHelperPromise(napi_env env,DataAbilityHelperCB * dataAbilityHelperCB)1066 napi_value GetDataAbilityHelperPromise(napi_env env, DataAbilityHelperCB *dataAbilityHelperCB)
1067 {
1068     HILOG_INFO("%{public}s, promise.", __func__);
1069     if (dataAbilityHelperCB == nullptr) {
1070         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
1071         return nullptr;
1072     }
1073     napi_value resourceName;
1074     NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1075     napi_deferred deferred;
1076     napi_value promise = nullptr;
1077     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1078     dataAbilityHelperCB->cbBase.deferred = deferred;
1079 
1080     NAPI_CALL(env,
1081         napi_create_async_work(env, nullptr, resourceName,
1082             [](napi_env env, void *data) { HILOG_INFO("NAPI_GetDataAbilityHelper, worker pool thread execute."); },
1083             GetDataAbilityHelperPromiseCompleteCB,
1084             static_cast<void *>(dataAbilityHelperCB),
1085             &dataAbilityHelperCB->cbBase.asyncWork));
1086     NAPI_CALL(env, napi_queue_async_work_with_qos(env, dataAbilityHelperCB->cbBase.asyncWork,
1087         napi_qos_user_initiated));
1088     HILOG_INFO("%{public}s, promise end.", __func__);
1089     return promise;
1090 }
1091 
GetDataAbilityHelperAsyncCompleteCB(napi_env env,napi_status status,void * data)1092 void GetDataAbilityHelperAsyncCompleteCB(napi_env env, napi_status status, void *data)
1093 {
1094     HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete.");
1095     DataAbilityHelperCB *dataAbilityHelperCB = static_cast<DataAbilityHelperCB *>(data);
1096     if (dataAbilityHelperCB == nullptr) {
1097         HILOG_ERROR("GetDataAbilityHelperAsyncCompleteCB, dataAbilityHelperCB is nullptr");
1098         return;
1099     }
1100 
1101     std::unique_ptr<DataAbilityHelperCB> callbackPtr {dataAbilityHelperCB};
1102     napi_value uri = nullptr;
1103     napi_value callback = nullptr;
1104     napi_value undefined = nullptr;
1105     napi_value result[ARGS_TWO] = {nullptr};
1106     napi_value callResult = nullptr;
1107     napi_get_undefined(env, &undefined);
1108     napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri);
1109     napi_get_reference_value(env, dataAbilityHelperCB->cbBase.cbInfo.callback, &callback);
1110     napi_new_instance(env, GetGlobalDataAbilityHelper(env), 1, &uri, &dataAbilityHelperCB->result);
1111     if (IsTypeForNapiValue(env, dataAbilityHelperCB->result, napi_object)) {
1112         result[PARAM1] = dataAbilityHelperCB->result;
1113     } else {
1114         HILOG_INFO("NAPI_GetDataAbilityHelper, helper is nullptr.");
1115         result[PARAM1] = WrapVoidToJS(env);
1116     }
1117     result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
1118     napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
1119     if (dataAbilityHelperCB->cbBase.cbInfo.callback != nullptr) {
1120         napi_delete_reference(env, dataAbilityHelperCB->cbBase.cbInfo.callback);
1121     }
1122     if (dataAbilityHelperCB->uri != nullptr) {
1123         napi_delete_reference(env, dataAbilityHelperCB->uri);
1124     }
1125     napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork);
1126     HILOG_INFO("NAPI_GetDataAbilityHelper, main event thread complete end.");
1127 }
1128 
GetDataAbilityHelperPromiseCompleteCB(napi_env env,napi_status status,void * data)1129 void GetDataAbilityHelperPromiseCompleteCB(napi_env env, napi_status status, void *data)
1130 {
1131     HILOG_INFO("NAPI_GetDataAbilityHelper,  main event thread complete.");
1132     DataAbilityHelperCB *dataAbilityHelperCB = static_cast<DataAbilityHelperCB *>(data);
1133     if (dataAbilityHelperCB == nullptr) {
1134         HILOG_INFO("GetDataAbilityHelperPromiseCompleteCB, dataAbilityHelperCB is nullptr.");
1135         return;
1136     }
1137 
1138     napi_value uri = nullptr;
1139     napi_value result = nullptr;
1140     napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri);
1141     napi_new_instance(env, GetGlobalDataAbilityHelper(env), 1, &uri, &dataAbilityHelperCB->result);
1142     if (IsTypeForNapiValue(env, dataAbilityHelperCB->result, napi_object)) {
1143         result = dataAbilityHelperCB->result;
1144         napi_resolve_deferred(env, dataAbilityHelperCB->cbBase.deferred, result);
1145     } else {
1146         result = GetCallbackErrorValue(env, dataAbilityHelperCB->cbBase.errCode);
1147         napi_reject_deferred(env, dataAbilityHelperCB->cbBase.deferred, result);
1148         HILOG_INFO("NAPI_GetDataAbilityHelper, helper is nullptr.");
1149     }
1150 
1151     if (dataAbilityHelperCB->uri != nullptr) {
1152         napi_delete_reference(env, dataAbilityHelperCB->uri);
1153     }
1154     napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork);
1155     HILOG_INFO("NAPI_GetDataAbilityHelper,  main event thread complete end.");
1156 }
1157 
1158 /**
1159  * @brief FeatureAbility NAPI method : acquireDataAbilityHelper.
1160  *
1161  * @param env The environment that the Node-API call is invoked under.
1162  * @param info The callback info passed into the callback function.
1163  *
1164  * @return The return value from NAPI C++ to JS for the module.
1165  */
NAPI_AcquireDataAbilityHelper(napi_env env,napi_callback_info info)1166 napi_value NAPI_AcquireDataAbilityHelper(napi_env env, napi_callback_info info)
1167 {
1168     return NAPI_AcquireDataAbilityHelperCommon(env, info, AbilityType::PAGE);
1169 }
1170 
1171 /**
1172  * @brief FeatureAbility NAPI method : continueAbility.
1173  *
1174  * @param env The environment that the Node-API call is invoked under.
1175  * @param info The callback info passed into the callback function.
1176  *
1177  * @return The return value from NAPI C++ to JS for the module.
1178  */
NAPI_FAContinueAbility(napi_env env,napi_callback_info info)1179 napi_value NAPI_FAContinueAbility(napi_env env, napi_callback_info info)
1180 {
1181     HILOG_INFO("%{public}s,called", __func__);
1182     AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
1183     if (asyncCallbackInfo == nullptr) {
1184         HILOG_ERROR("%{public}s, asyncCallbackInfo == nullptr.", __func__);
1185         return WrapVoidToJS(env);
1186     }
1187 
1188     napi_value ret = ContinueAbilityWrap(env, info, asyncCallbackInfo);
1189     if (ret == nullptr) {
1190         if (asyncCallbackInfo != nullptr) {
1191             delete asyncCallbackInfo;
1192             asyncCallbackInfo = nullptr;
1193         }
1194         ret = WrapVoidToJS(env);
1195     }
1196     HILOG_INFO("%{public}s,end.", __func__);
1197     return ret;
1198 }
1199 
1200 /**
1201  * @brief ContinueAbilityWrap processing function.
1202  *
1203  * @param env The environment that the Node-API call is invoked under.
1204  * @param asyncCallbackInfo Process data asynchronously.
1205  *
1206  * @return Return JS data successfully, otherwise return nullptr.
1207  */
ContinueAbilityWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)1208 napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
1209 {
1210     HILOG_INFO("%{public}s, called.", __func__);
1211     size_t argc = 2;
1212     napi_value args[ARGS_MAX_COUNT] = {nullptr};
1213     napi_value ret = nullptr;
1214     napi_valuetype valueType = napi_undefined;
1215 
1216     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
1217     NAPI_CALL(env, napi_typeof(env, args[0], &valueType));
1218     if (valueType != napi_object && valueType != napi_function) {
1219         HILOG_ERROR("%{public}s, Wrong argument type. Object or function expected.", __func__);
1220         return nullptr;
1221     }
1222     if (argc == 0) {
1223         ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc);
1224     } else if (PARA_SIZE_IS_ONE == argc) {
1225         if (valueType == napi_function) {
1226             ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc);
1227         } else {
1228             ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc);
1229         }
1230     } else if (PARA_SIZE_IS_TWO == argc) {
1231         napi_valuetype value = napi_undefined;
1232         NAPI_CALL(env, napi_typeof(env, args[1], &value));
1233         if (value != napi_function) {
1234             HILOG_ERROR("%{public}s, Wrong argument type. function expected.", __func__);
1235             return nullptr;
1236         }
1237         ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc);
1238     } else {
1239         HILOG_ERROR("%{public}s, Wrong argument count.", __func__);
1240     }
1241     HILOG_INFO("%{public}s,end.", __func__);
1242     return ret;
1243 }
1244 
ContinueAbilityAsync(napi_env env,napi_value * args,AsyncCallbackInfo * asyncCallbackInfo,size_t argc)1245 napi_value ContinueAbilityAsync(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc)
1246 {
1247     HILOG_INFO("%{public}s, asyncCallback.", __func__);
1248     if (args == nullptr || asyncCallbackInfo == nullptr) {
1249         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
1250         return nullptr;
1251     }
1252     napi_value resourceName = nullptr;
1253     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1254 
1255     if (PARA_SIZE_IS_TWO == argc) {
1256         // args[0] : ContinueAbilityOptions
1257         napi_valuetype valueTypeOptions = napi_undefined;
1258         NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions));
1259         if (valueTypeOptions != napi_object) {
1260             HILOG_ERROR("%{public}s, Wrong argument type. Object expected.", __func__);
1261             return nullptr;
1262         }
1263         if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) {
1264             HILOG_ERROR("%{public}s, GetContinueAbilityOptionsInfoCommonFail", __func__);
1265             return nullptr;
1266         }
1267 
1268         // args[1] : callback
1269         napi_valuetype valueTypeCallBack = napi_undefined;
1270         napi_typeof(env, args[1], &valueTypeCallBack);
1271         if (valueTypeCallBack == napi_function) {
1272             napi_create_reference(env, args[1], 1, &asyncCallbackInfo->cbInfo.callback);
1273         }
1274     } else {
1275         // args[0] : callback
1276         napi_valuetype valueTypeCallBack = napi_undefined;
1277         napi_typeof(env, args[1], &valueTypeCallBack);
1278         if (valueTypeCallBack == napi_function) {
1279             napi_create_reference(env, args[0], 1, &asyncCallbackInfo->cbInfo.callback);
1280         }
1281     }
1282 
1283     napi_create_async_work(env, nullptr, resourceName,
1284         [](napi_env env, void *data) {
1285             HILOG_INFO("NAPI_ContinueAbility, worker pool thread execute.");
1286             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
1287             if (asyncCallbackInfo == nullptr) {
1288                 HILOG_ERROR("NAPI_ContinueAbility, asyncCallbackInfo is nullptr.");
1289                 return;
1290             }
1291 
1292             if (asyncCallbackInfo->ability != nullptr) {
1293                 asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId);
1294             } else {
1295                 HILOG_ERROR("NAPI_ContinueAbilityForResult, asyncCallbackInfo == nullptr.");
1296             }
1297             HILOG_INFO("NAPI_ContinueAbilityForResult, worker pool thread execute exit.");
1298         },
1299         [](napi_env env, napi_status status, void *data) {
1300             HILOG_INFO("NAPI_ContinueAbility, main event thread end.");
1301             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
1302             if (asyncCallbackInfo == nullptr) {
1303                 HILOG_ERROR("NAPI_ContinueAbility complete, asyncCallbackInfo is nullptr.");
1304                 return;
1305             }
1306             napi_value callback = nullptr;
1307             napi_value undefined = nullptr;
1308             napi_value result[ARGS_TWO] = {nullptr};
1309             napi_value callResult = nullptr;
1310             napi_get_undefined(env, &undefined);
1311             result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
1312             napi_get_null(env, &result[PARAM1]);
1313             napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
1314             napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
1315 
1316             if (asyncCallbackInfo->cbInfo.callback != nullptr) {
1317                 napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
1318             }
1319             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1320             delete asyncCallbackInfo;
1321             HILOG_INFO("NAPI_ContinueAbilityForResult, main event thread complete end.");
1322         },
1323         static_cast<void *>(asyncCallbackInfo),
1324         &asyncCallbackInfo->asyncWork);
1325     napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
1326     napi_value result = nullptr;
1327     napi_get_null(env, &result);
1328     HILOG_INFO("%{public}s, asyncCallback end.", __func__);
1329     return result;
1330 }
1331 
ContinueAbilityPromise(napi_env env,napi_value * args,AsyncCallbackInfo * asyncCallbackInfo,size_t argc)1332 napi_value ContinueAbilityPromise(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc)
1333 {
1334     HILOG_INFO("%{public}s, promise.", __func__);
1335     if (asyncCallbackInfo == nullptr) {
1336         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
1337         return nullptr;
1338     }
1339 
1340     if (argc == PARA_SIZE_IS_ONE) {
1341         // args[0] : ContinueAbilityOptions
1342         napi_valuetype valueTypeOptions = napi_undefined;
1343         NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions));
1344         if (valueTypeOptions != napi_object) {
1345             HILOG_ERROR("%{public}s, Wrong argument type. Object expected.", __func__);
1346             return nullptr;
1347         }
1348         if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) {
1349             return nullptr;
1350         }
1351     }
1352 
1353     napi_value resourceName = nullptr;
1354     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1355     napi_deferred deferred;
1356     napi_value promise = nullptr;
1357     napi_create_promise(env, &deferred, &promise);
1358 
1359     asyncCallbackInfo->deferred = deferred;
1360 
1361     napi_create_async_work(env, nullptr, resourceName,
1362         [](napi_env env, void *data) {
1363             HILOG_INFO("NAPI_ContinueAbility, worker pool thread execute.");
1364             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
1365             if (asyncCallbackInfo == nullptr) {
1366                 HILOG_ERROR("NAPI_ContinueAbility, worker pool thread execute asyncCallbackInfo is nullptr.");
1367                 return;
1368             }
1369             if (asyncCallbackInfo->ability != nullptr) {
1370                 asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId);
1371             } else {
1372                 HILOG_ERROR("NAPI_ContinueAbilityForResult, asyncCallbackInfo == nullptr");
1373             }
1374             HILOG_INFO("NAPI_ContinueAbilityForResult, worker pool thread execute end.");
1375         },
1376         [](napi_env env, napi_status status, void *data) {
1377             HILOG_INFO("NAPI_ContinueAbility,  main event thread complete.");
1378             AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
1379             if (asyncCallbackInfo == nullptr) {
1380                 HILOG_ERROR("NAPI_ContinueAbility, main event thread complete asyncCallbackInfo is nullptr.");
1381                 return;
1382             }
1383             napi_value result = nullptr;
1384             napi_get_null(env, &result);
1385             napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
1386             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1387             delete asyncCallbackInfo;
1388             HILOG_INFO("NAPI_ContinueAbilityForResult,  main event thread complete end.");
1389         },
1390         static_cast<void *>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork);
1391     napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
1392     HILOG_INFO("%{public}s, promise end.", __func__);
1393     return promise;
1394 }
1395 }  // namespace AppExecFwk
1396 }  // namespace OHOS
1397