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