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_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 TAG_LOGD(AAFwkTag::FA, "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 TAG_LOGD(AAFwkTag::FA, "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 TAG_LOGD(AAFwkTag::FA, "called");
115 if (env == nullptr || exports == nullptr) {
116 TAG_LOGE(AAFwkTag::FA, "Invalid input parameters");
117 return exports;
118 }
119
120 if (!AppExecFwk::CheckTypeForNapiValue(env, exports, napi_object)) {
121 TAG_LOGE(AAFwkTag::FA, "null object");
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 TAG_LOGD(AAFwkTag::FA, "called");
231 if (info.argc > ARGS_ONE || info.argc < ARGS_ZERO) {
232 TAG_LOGE(AAFwkTag::FA, "invalid argc");
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 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGD(AAFwkTag::FA, "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 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGD(AAFwkTag::FA, "called");
288 if (info.argc < ARGS_ONE || info.argc > ARGS_TWO) {
289 TAG_LOGE(AAFwkTag::FA, "invalid argc");
290 return CreateJsUndefined(env);
291 }
292
293 if (ability_ == nullptr) {
294 TAG_LOGE(AAFwkTag::FA, "null ability");
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 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGD(AAFwkTag::FA, "called");
332 if (info.argc > ARGS_TWO || info.argc < ARGS_ONE) {
333 TAG_LOGE(AAFwkTag::FA, "invalid argc");
334 return CreateJsUndefined(env);
335 }
336
337 if (!AppExecFwk::IsTypeForNapiValue(env, info.argv[0], napi_object)) {
338 TAG_LOGE(AAFwkTag::FA, "param 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 TAG_LOGE(AAFwkTag::FA, "resultCode type failed");
347 return CreateJsUndefined(env);
348 }
349 if (!ConvertFromJsValue(env, jsRequestCode, param.requestCode)) {
350 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGE(AAFwkTag::FA, "want type failed");
360 return CreateJsUndefined(env);
361 }
362 if (!UnwrapWant(env, jsWant, param.want)) {
363 TAG_LOGE(AAFwkTag::FA, "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 TAG_LOGE(AAFwkTag::FA, "null ability");
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 TAG_LOGE(AAFwkTag::FA, "null %{public}s", ((env == nullptr) ? "env" : "info"));
389 return nullptr;
390 }
391
392 auto object = CheckParamsAndGetThis<JsFeatureAbility>(env, info);
393 if (object == nullptr) {
394 TAG_LOGE(AAFwkTag::FA, "null obj");
395 return nullptr;
396 }
397
398 return object->OnGetWindow(env, info);
399 }
400
OnGetWindow(napi_env env,napi_callback_info info)401 napi_value JsFeatureAbility::OnGetWindow(napi_env env, napi_callback_info info)
402 {
403 TAG_LOGD(AAFwkTag::FA, "called");
404 size_t argc = ARGS_MAX_COUNT;
405 napi_value argv[ARGS_MAX_COUNT] = { nullptr };
406 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
407 if (argc > ARGS_ONE) {
408 TAG_LOGE(AAFwkTag::FA, "input params count error, argc=%{public}zu", argc);
409 return CreateJsUndefined(env);
410 }
411
412 auto complete = [obj = this] (napi_env env, NapiAsyncTask& task, int32_t status) {
413 if (obj->ability_ == nullptr) {
414 TAG_LOGE(AAFwkTag::FA, "null ability");
415 task.Resolve(env, CreateJsNull(env));
416 return;
417 }
418 auto window = obj->ability_->GetWindow();
419 task.Resolve(env, OHOS::Rosen::CreateJsWindowObject(env, window));
420 };
421
422 auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
423 napi_value result = nullptr;
424 NapiAsyncTask::ScheduleHighQos("JsFeatureAbility::OnGetWindow",
425 env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
426
427 return result;
428 }
429 #else
430
GetWindow(napi_env env,napi_callback_info info)431 napi_value JsFeatureAbility::GetWindow(napi_env env, napi_callback_info info)
432 {
433 return nullptr;
434 }
435
OnGetWindow(napi_env env,napi_callback_info info)436 napi_value JsFeatureAbility::OnGetWindow(napi_env env, napi_callback_info info)
437 {
438 return nullptr;
439 }
440 #endif
441
442 /**
443 * @brief FeatureAbility NAPI method : setResult.
444 *
445 * @param env The environment that the Node-API call is invoked under.
446 * @param info The callback info passed into the callback function.
447 *
448 * @return The return value from NAPI C++ to JS for the module.
449 */
NAPI_SetResult(napi_env env,napi_callback_info info)450 napi_value NAPI_SetResult(napi_env env, napi_callback_info info)
451 {
452 TAG_LOGI(AAFwkTag::FA, "called");
453 AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
454 if (asyncCallbackInfo == nullptr) {
455 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
456 return WrapVoidToJS(env);
457 }
458
459 napi_value ret = SetResultWrap(env, info, asyncCallbackInfo);
460 if (ret == nullptr) {
461 TAG_LOGE(AAFwkTag::FA, "null ret");
462 if (asyncCallbackInfo != nullptr) {
463 delete asyncCallbackInfo;
464 asyncCallbackInfo = nullptr;
465 }
466 ret = WrapVoidToJS(env);
467 }
468 TAG_LOGI(AAFwkTag::FA, "end");
469 return ret;
470 }
471
472 /**
473 * @brief SetResult processing function.
474 *
475 * @param env The environment that the Node-API call is invoked under.
476 * @param asyncCallbackInfo Process data asynchronously.
477 *
478 * @return Return JS data successfully, otherwise return nullptr.
479 */
SetResultWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)480 napi_value SetResultWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
481 {
482 TAG_LOGI(AAFwkTag::FA, "called");
483 size_t argcAsync = 2;
484 const size_t argcPromise = 1;
485 const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT;
486 napi_value args[ARGS_MAX_COUNT] = {nullptr};
487 napi_value ret = nullptr;
488
489 NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
490 if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) {
491 TAG_LOGE(AAFwkTag::FA, "invalid argc");
492 return nullptr;
493 }
494
495 CallAbilityParam param;
496 if (UnwrapAbilityResult(param, env, args[0]) == nullptr) {
497 TAG_LOGE(AAFwkTag::FA, "call unwrapWant failed");
498 return nullptr;
499 }
500 asyncCallbackInfo->param = param;
501
502 if (argcAsync > argcPromise) {
503 ret = SetResultAsync(env, args, 1, asyncCallbackInfo);
504 } else {
505 ret = SetResultPromise(env, asyncCallbackInfo);
506 }
507 TAG_LOGI(AAFwkTag::FA, "end");
508 return ret;
509 }
510
CreateAsyncWork(napi_env env,napi_value & resourceName,AsyncCallbackInfo * asyncCallbackInfo)511 napi_value CreateAsyncWork(napi_env env, napi_value &resourceName, AsyncCallbackInfo *asyncCallbackInfo)
512 {
513 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
514 [](napi_env env, void *data) {
515 TAG_LOGI(AAFwkTag::FA, "worker pool thread");
516 AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
517 if (asyncCallbackInfo == nullptr) {
518 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
519 return;
520 }
521
522 if (asyncCallbackInfo->ability != nullptr) {
523 asyncCallbackInfo->ability->SetResult(
524 asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want);
525 asyncCallbackInfo->ability->TerminateAbility();
526 } else {
527 TAG_LOGE(AAFwkTag::FA, "null ability");
528 }
529 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute exit");
530 },
531 [](napi_env env, napi_status status, void *data) {
532 TAG_LOGI(AAFwkTag::FA, "complete");
533 AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
534 if (asyncCallbackInfo == nullptr) {
535 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
536 return;
537 }
538 napi_value result[ARGS_TWO] = {nullptr};
539 napi_value callback = nullptr;
540 napi_value undefined = nullptr;
541 napi_value callResult = nullptr;
542 napi_get_undefined(env, &undefined);
543 result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
544 napi_get_null(env, &result[PARAM1]);
545 napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
546 napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
547
548 if (asyncCallbackInfo->cbInfo.callback != nullptr) {
549 TAG_LOGD(AAFwkTag::FA, "napi_delete_reference");
550 napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
551 }
552 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
553 delete asyncCallbackInfo;
554 TAG_LOGI(AAFwkTag::FA, "complete end");
555 },
556 static_cast<void *>(asyncCallbackInfo),
557 &asyncCallbackInfo->asyncWork));
558 NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
559 napi_value result = nullptr;
560 NAPI_CALL(env, napi_get_null(env, &result));
561 TAG_LOGI(AAFwkTag::FA, "end");
562 return result;
563 }
564
SetResultAsync(napi_env env,napi_value * args,const size_t argCallback,AsyncCallbackInfo * asyncCallbackInfo)565 napi_value SetResultAsync(
566 napi_env env, napi_value *args, const size_t argCallback, AsyncCallbackInfo *asyncCallbackInfo)
567 {
568 TAG_LOGI(AAFwkTag::FA, "called");
569 if (args == nullptr || asyncCallbackInfo == nullptr) {
570 TAG_LOGE(AAFwkTag::FA, "null param");
571 return nullptr;
572 }
573 napi_value resourceName = nullptr;
574 NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
575
576 napi_valuetype valuetype = napi_undefined;
577 NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype));
578 if (valuetype == napi_function) {
579 napi_create_reference(env, args[argCallback], 1, &asyncCallbackInfo->cbInfo.callback);
580 }
581
582 return CreateAsyncWork(env, resourceName, asyncCallbackInfo);
583 }
584
SetResultPromise(napi_env env,AsyncCallbackInfo * asyncCallbackInfo)585 napi_value SetResultPromise(napi_env env, AsyncCallbackInfo *asyncCallbackInfo)
586 {
587 TAG_LOGI(AAFwkTag::FA, "promise");
588 if (asyncCallbackInfo == nullptr) {
589 TAG_LOGE(AAFwkTag::FA, "null param");
590 return nullptr;
591 }
592 napi_value resourceName = nullptr;
593 NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
594 napi_deferred deferred;
595 napi_value promise = nullptr;
596 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
597 asyncCallbackInfo->deferred = deferred;
598
599 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
600 [](napi_env env, void *data) {
601 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute");
602 AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
603 if (asyncCallbackInfo->ability != nullptr) {
604 asyncCallbackInfo->ability->SetResult(
605 asyncCallbackInfo->param.requestCode, asyncCallbackInfo->param.want);
606 asyncCallbackInfo->ability->TerminateAbility();
607 } else {
608 TAG_LOGE(AAFwkTag::FA, "ability == nullptr");
609 }
610 TAG_LOGI(AAFwkTag::FA, "execute end");
611 },
612 [](napi_env env, napi_status status, void *data) {
613 TAG_LOGI(AAFwkTag::FA, "complete called");
614 AsyncCallbackInfo *asyncCallbackInfo = static_cast<AsyncCallbackInfo *>(data);
615 napi_value result = nullptr;
616 napi_get_null(env, &result);
617 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
618 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
619 delete asyncCallbackInfo;
620 TAG_LOGI(AAFwkTag::FA, "complete end");
621 },
622 static_cast<void *>(asyncCallbackInfo),
623 &asyncCallbackInfo->asyncWork));
624 NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
625 TAG_LOGI(AAFwkTag::FA, "end");
626 return promise;
627 }
628
629 EXTERN_C_START
CreateUVQueueWork(uv_loop_t * loop,uv_work_t * work)630 int CreateUVQueueWork(uv_loop_t *loop, uv_work_t *work)
631 {
632 int rev = uv_queue_work(
633 loop,
634 work,
635 [](uv_work_t *work) {},
636 [](uv_work_t *work, int status) {
637 // JS Thread
638 if (work == nullptr) {
639 TAG_LOGE(AAFwkTag::FA, "null work");
640 return;
641 }
642 auto onAbilityCB = static_cast<OnAbilityCallback *>(work->data);
643 if (onAbilityCB == nullptr) {
644 TAG_LOGE(AAFwkTag::FA, "null onAbilityCB");
645 delete work;
646 work = nullptr;
647 return;
648 }
649
650 if (onAbilityCB->cb.errCode != ERR_OK) {
651 int32_t errCode = GetStartAbilityErrorCode(onAbilityCB->cb.errCode);
652 onAbilityCB->cb.napiAsyncTask->Reject(onAbilityCB->cb.env,
653 CreateJsError(onAbilityCB->cb.env, errCode, "StartAbilityForResult Error"));
654 delete onAbilityCB->cb.napiAsyncTask;
655 onAbilityCB->cb.napiAsyncTask = nullptr;
656 delete onAbilityCB;
657 onAbilityCB = nullptr;
658 delete work;
659 work = nullptr;
660 return;
661 }
662
663 napi_value objValue = nullptr;
664 napi_create_object(onAbilityCB->cb.env, &objValue);
665
666 napi_set_named_property(onAbilityCB->cb.env,
667 objValue, "resultCode", CreateJsValue(onAbilityCB->cb.env, onAbilityCB->resultCode));
668 napi_set_named_property(onAbilityCB->cb.env,
669 objValue, "want", CreateJsWant(onAbilityCB->cb.env, onAbilityCB->resultData));
670
671 onAbilityCB->cb.napiAsyncTask->Resolve(onAbilityCB->cb.env, objValue);
672 delete onAbilityCB->cb.napiAsyncTask;
673 onAbilityCB->cb.napiAsyncTask = nullptr;
674 delete onAbilityCB;
675 onAbilityCB = nullptr;
676 delete work;
677 work = nullptr;
678 TAG_LOGI(AAFwkTag::FA, "uv_queue_work end");
679 });
680 return rev;
681 }
682
CallOnAbilityResult(int requestCode,int resultCode,const Want & resultData,CallbackInfo callbackInfo)683 void CallOnAbilityResult(int requestCode, int resultCode, const Want &resultData, CallbackInfo callbackInfo)
684 {
685 TAG_LOGI(AAFwkTag::FA, "called");
686 if (callbackInfo.env == nullptr) {
687 TAG_LOGE(AAFwkTag::FA, "null cb.env");
688 return;
689 }
690
691 if (callbackInfo.napiAsyncTask == nullptr) {
692 TAG_LOGE(AAFwkTag::FA, "null cb.asyncTask");
693 return;
694 }
695
696 uv_loop_t *loop = nullptr;
697 napi_get_uv_event_loop(callbackInfo.env, &loop);
698 if (loop == nullptr) {
699 TAG_LOGE(AAFwkTag::FA, "null loop");
700 return;
701 }
702
703 auto work = new uv_work_t;
704 auto onAbilityCB = new (std::nothrow) OnAbilityCallback;
705 if (onAbilityCB == nullptr) {
706 TAG_LOGE(AAFwkTag::FA, "Failed to allocate OnAbilityCallback");
707 delete work;
708 return;
709 }
710
711 onAbilityCB->requestCode = requestCode;
712 onAbilityCB->resultCode = resultCode;
713 onAbilityCB->resultData = resultData;
714 onAbilityCB->cb = callbackInfo;
715
716 if (work == nullptr) {
717 TAG_LOGE(AAFwkTag::FA, "null work");
718 return;
719 }
720 work->data = static_cast<void *>(onAbilityCB);
721
722 int rev = CreateUVQueueWork(loop, work);
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 TAG_LOGI(AAFwkTag::FA, "end");
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 TAG_LOGI(AAFwkTag::FA, "called");
740 napi_valuetype valueType = napi_undefined;
741 NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
742 if (valueType != napi_object) {
743 TAG_LOGE(AAFwkTag::FA, "wrong argument type");
744 return false;
745 }
746
747 napi_value jsWant = GetPropertyValueByPropertyName(env, args, "want", napi_object);
748 if (jsWant == nullptr) {
749 TAG_LOGE(AAFwkTag::FA, "null jsWant");
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 ¶m, napi_env env, napi_value args)
766 {
767 TAG_LOGI(AAFwkTag::FA, "called");
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 TAG_LOGI(AAFwkTag::FA, "reqCode=%{public}d forResultOption=%{public}d",
773 param.requestCode,
774 param.forResultOption);
775
776 // unwrap the param : want object
777 if (!InnerUnwrapWant(env, args, param.want)) {
778 TAG_LOGE(AAFwkTag::FA, "Failed to InnerUnwrapWant");
779 return nullptr;
780 }
781
782 // unwrap the param : abilityStartSetting (optional)
783 napi_value jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSettings", napi_object);
784 if (jsSettingObj == nullptr) {
785 jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSetting", napi_object);
786 }
787 if (jsSettingObj != nullptr) {
788 param.setting = AbilityStartSetting::GetEmptySetting();
789 if (!UnwrapAbilityStartSetting(env, jsSettingObj, *(param.setting))) {
790 TAG_LOGE(AAFwkTag::FA, "unwrap abilityStartSetting failed");
791 }
792 TAG_LOGI(AAFwkTag::FA, "abilityStartSetting");
793 }
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 Parse the abilityResult parameters.
803 *
804 * @param param Indicates the want parameters saved the parse result.
805 * @param env The environment that the Node-API call is invoked under.
806 * @param args Indicates the arguments passed into the callback.
807 *
808 * @return The return value from NAPI C++ to JS for the module.
809 */
UnwrapAbilityResult(CallAbilityParam & param,napi_env env,napi_value args)810 napi_value UnwrapAbilityResult(CallAbilityParam ¶m, napi_env env, napi_value args)
811 {
812 TAG_LOGI(AAFwkTag::FA, "called");
813 // unwrap the param
814 napi_valuetype valueType = napi_undefined;
815 NAPI_CALL(env, napi_typeof(env, args, &valueType));
816 NAPI_ASSERT(env, valueType == napi_object, "param type mismatch!");
817 // get resultCode property
818 napi_value property = nullptr;
819 NAPI_CALL(env, napi_get_named_property(env, args, "resultCode", &property));
820 NAPI_CALL(env, napi_typeof(env, property, &valueType));
821 NAPI_ASSERT(env, valueType == napi_number, "property type mismatch!");
822 NAPI_CALL(env, napi_get_value_int32(env, property, ¶m.requestCode));
823 TAG_LOGI(AAFwkTag::FA, "requestCode=%{public}d", param.requestCode);
824
825 // unwrap the param : want object
826 InnerUnwrapWant(env, args, param.want);
827
828 napi_value result;
829 NAPI_CALL(env, napi_create_int32(env, 1, &result));
830 TAG_LOGI(AAFwkTag::FA, "end");
831 return result;
832 }
833
834 /**
835 * @brief GetWantSyncWrap processing function.
836 *
837 * @param env The environment that the Node-API call is invoked under.
838 * @param CallingBundleCB Process data asynchronously.
839 *
840 * @return Return JS data successfully, otherwise return nullptr.
841 */
GetWantSyncWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)842 napi_value GetWantSyncWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
843 {
844 TAG_LOGI(AAFwkTag::FA, "called");
845 if (asyncCallbackInfo == nullptr) {
846 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
847 return nullptr;
848 }
849
850 asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR;
851 if (asyncCallbackInfo->ability == nullptr) {
852 TAG_LOGE(AAFwkTag::FA, "null ability");
853 asyncCallbackInfo->errCode = NAPI_ERR_ACE_ABILITY;
854 return nullptr;
855 }
856
857 std::shared_ptr<AAFwk::Want> ptrWant = asyncCallbackInfo->ability->GetWant();
858 if (ptrWant != nullptr) {
859 asyncCallbackInfo->param.want = *ptrWant;
860 } else {
861 asyncCallbackInfo->errCode = NAPI_ERR_ABILITY_CALL_INVALID;
862 }
863
864 napi_value result = nullptr;
865 if (asyncCallbackInfo->errCode == NAPI_ERR_NO_ERROR) {
866 result = WrapWant(env, asyncCallbackInfo->param.want);
867 } else {
868 result = WrapVoidToJS(env);
869 }
870 TAG_LOGI(AAFwkTag::FA, "end");
871 return result;
872 }
873
874 /**
875 * @brief Get want(Sync).
876 *
877 * @param env The environment that the Node-API call is invoked under.
878 * @param info The callback info passed into the callback function.
879 *
880 * @return The return value from NAPI C++ to JS for the module.
881 */
NAPI_GetWantSync(napi_env env,napi_callback_info info)882 napi_value NAPI_GetWantSync(napi_env env, napi_callback_info info)
883 {
884 TAG_LOGI(AAFwkTag::FA, "called");
885 AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
886 if (asyncCallbackInfo == nullptr) {
887 return WrapVoidToJS(env);
888 }
889
890 asyncCallbackInfo->errCode = NAPI_ERR_NO_ERROR;
891 napi_value ret = GetWantSyncWrap(env, info, asyncCallbackInfo);
892
893 delete asyncCallbackInfo;
894 asyncCallbackInfo = nullptr;
895
896 if (ret == nullptr) {
897 ret = WrapVoidToJS(env);
898 TAG_LOGE(AAFwkTag::FA, "null ret");
899 } else {
900 TAG_LOGI(AAFwkTag::FA, "exit");
901 }
902 return ret;
903 }
904
905 /**
906 * @brief Obtains the type of this application.
907 *
908 * @param env The environment that the Node-API call is invoked under.
909 * @param info The callback info passed into the callback function.
910 *
911 * @return The return value from NAPI C++ to JS for the module.
912 */
NAPI_GetAppType(napi_env env,napi_callback_info info)913 napi_value NAPI_GetAppType(napi_env env, napi_callback_info info)
914 {
915 TAG_LOGI(AAFwkTag::FA, "called");
916 return NAPI_GetAppTypeCommon(env, info, AbilityType::PAGE);
917 }
918
919 /**
920 * @brief Obtains the class name in this ability name, without the prefixed bundle name.
921 *
922 * @param env The environment that the Node-API call is invoked under.
923 * @param info The callback info passed into the callback function.
924 *
925 * @return The return value from NAPI C++ to JS for the module.
926 */
NAPI_GetAbilityName(napi_env env,napi_callback_info info)927 napi_value NAPI_GetAbilityName(napi_env env, napi_callback_info info)
928 {
929 TAG_LOGI(AAFwkTag::FA, "called");
930 return NAPI_GetAbilityNameCommon(env, info, AbilityType::PAGE);
931 }
932
933 /**
934 * @brief Obtains information about the current ability.
935 *
936 * @param env The environment that the Node-API call is invoked under.
937 * @param info The callback info passed into the callback function.
938 *
939 * @return The return value from NAPI C++ to JS for the module.
940 */
NAPI_GetAbilityInfo(napi_env env,napi_callback_info info)941 napi_value NAPI_GetAbilityInfo(napi_env env, napi_callback_info info)
942 {
943 TAG_LOGI(AAFwkTag::FA, "called");
944 return NAPI_GetAbilityInfoCommon(env, info, AbilityType::PAGE);
945 }
946
947 /**
948 * @brief Obtains the HapModuleInfo object of the application.
949 *
950 * @param env The environment that the Node-API call is invoked under.
951 * @param info The callback info passed into the callback function.
952 *
953 * @return The return value from NAPI C++ to JS for the module.
954 */
NAPI_GetHapModuleInfo(napi_env env,napi_callback_info info)955 napi_value NAPI_GetHapModuleInfo(napi_env env, napi_callback_info info)
956 {
957 TAG_LOGI(AAFwkTag::FA, "called");
958 return NAPI_GetHapModuleInfoCommon(env, info, AbilityType::PAGE);
959 }
960
961 /**
962 * @brief FeatureAbility NAPI method : getDataAbilityHelper.
963 *
964 * @param env The environment that the Node-API call is invoked under.
965 * @param info The callback info passed into the callback function.
966 *
967 * @return The return value from NAPI C++ to JS for the module.
968 */
NAPI_GetDataAbilityHelper(napi_env env,napi_callback_info info)969 napi_value NAPI_GetDataAbilityHelper(napi_env env, napi_callback_info info)
970 {
971 TAG_LOGI(AAFwkTag::FA, "called");
972 DataAbilityHelperCB *dataAbilityHelperCB = new (std::nothrow) DataAbilityHelperCB;
973 if (dataAbilityHelperCB == nullptr) {
974 TAG_LOGE(AAFwkTag::FA, "null dataAbilityHelperCB");
975 return WrapVoidToJS(env);
976 }
977 dataAbilityHelperCB->cbBase.cbInfo.env = env;
978 napi_value ret = GetDataAbilityHelperWrap(env, info, dataAbilityHelperCB);
979 if (ret == nullptr) {
980 TAG_LOGE(AAFwkTag::FA, "null ret");
981 if (dataAbilityHelperCB != nullptr) {
982 delete dataAbilityHelperCB;
983 dataAbilityHelperCB = nullptr;
984 }
985 ret = WrapVoidToJS(env);
986 }
987 TAG_LOGI(AAFwkTag::FA, "end");
988 return ret;
989 }
990
991 /**
992 * @brief getDataAbilityHelper processing function.
993 *
994 * @param env The environment that the Node-API call is invoked under.
995 * @param dataAbilityHelperCB Process data asynchronously.
996 *
997 * @return Return JS data successfully, otherwise return nullptr.
998 */
GetDataAbilityHelperWrap(napi_env env,napi_callback_info info,DataAbilityHelperCB * dataAbilityHelperCB)999 napi_value GetDataAbilityHelperWrap(napi_env env, napi_callback_info info, DataAbilityHelperCB *dataAbilityHelperCB)
1000 {
1001 TAG_LOGI(AAFwkTag::FA, "called");
1002 if (dataAbilityHelperCB == nullptr) {
1003 TAG_LOGE(AAFwkTag::FA, "null dataAbilityHelperCB");
1004 return nullptr;
1005 }
1006
1007 size_t argcAsync = 2;
1008 const size_t argcPromise = 1;
1009 const size_t argCountWithAsync = argcPromise + ARGS_ASYNC_COUNT;
1010 napi_value args[ARGS_MAX_COUNT] = {nullptr};
1011 napi_value ret = nullptr;
1012
1013 NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
1014 if (argcAsync > argCountWithAsync || argcAsync > ARGS_MAX_COUNT) {
1015 TAG_LOGE(AAFwkTag::FA, "invalid argc");
1016 return nullptr;
1017 }
1018
1019 napi_valuetype valuetype = napi_undefined;
1020 NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valuetype));
1021 if (valuetype == napi_string) {
1022 NAPI_CALL(env, napi_create_reference(env, args[PARAM0], 1, &dataAbilityHelperCB->uri));
1023 }
1024
1025 if (argcAsync > argcPromise) {
1026 ret = GetDataAbilityHelperAsync(env, args, 1, dataAbilityHelperCB);
1027 } else {
1028 ret = GetDataAbilityHelperPromise(env, dataAbilityHelperCB);
1029 }
1030 TAG_LOGI(AAFwkTag::FA, "end");
1031 return ret;
1032 }
1033
GetDataAbilityHelperAsync(napi_env env,napi_value * args,const size_t argCallback,DataAbilityHelperCB * dataAbilityHelperCB)1034 napi_value GetDataAbilityHelperAsync(
1035 napi_env env, napi_value *args, const size_t argCallback, DataAbilityHelperCB *dataAbilityHelperCB)
1036 {
1037 TAG_LOGI(AAFwkTag::FA, "asyncCallback");
1038 if (args == nullptr || dataAbilityHelperCB == nullptr) {
1039 TAG_LOGE(AAFwkTag::FA, "null param");
1040 return nullptr;
1041 }
1042 napi_value resourceName = nullptr;
1043 NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1044
1045 napi_valuetype valuetype = napi_undefined;
1046 NAPI_CALL(env, napi_typeof(env, args[argCallback], &valuetype));
1047 if (valuetype == napi_function) {
1048 NAPI_CALL(env, napi_create_reference(env, args[argCallback], 1, &dataAbilityHelperCB->cbBase.cbInfo.callback));
1049 }
1050
1051 NAPI_CALL(env,
1052 napi_create_async_work(env, nullptr, resourceName,
1053 [](napi_env env, void *data) {
1054 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute");
1055 },
1056 GetDataAbilityHelperAsyncCompleteCB,
1057 static_cast<void *>(dataAbilityHelperCB),
1058 &dataAbilityHelperCB->cbBase.asyncWork));
1059 NAPI_CALL(env, napi_queue_async_work_with_qos(env, dataAbilityHelperCB->cbBase.asyncWork,
1060 napi_qos_user_initiated));
1061 napi_value result = nullptr;
1062 NAPI_CALL(env, napi_get_null(env, &result));
1063 TAG_LOGI(AAFwkTag::FA, "end");
1064 return result;
1065 }
1066
GetDataAbilityHelperPromise(napi_env env,DataAbilityHelperCB * dataAbilityHelperCB)1067 napi_value GetDataAbilityHelperPromise(napi_env env, DataAbilityHelperCB *dataAbilityHelperCB)
1068 {
1069 TAG_LOGI(AAFwkTag::FA, "promise");
1070 if (dataAbilityHelperCB == nullptr) {
1071 TAG_LOGE(AAFwkTag::FA, "null param");
1072 return nullptr;
1073 }
1074 napi_value resourceName;
1075 NAPI_CALL(env, napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1076 napi_deferred deferred;
1077 napi_value promise = nullptr;
1078 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1079 dataAbilityHelperCB->cbBase.deferred = deferred;
1080
1081 NAPI_CALL(env,
1082 napi_create_async_work(env, nullptr, resourceName,
1083 [](napi_env env, void *data) {
1084 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute");
1085 },
1086 GetDataAbilityHelperPromiseCompleteCB,
1087 static_cast<void *>(dataAbilityHelperCB),
1088 &dataAbilityHelperCB->cbBase.asyncWork));
1089 NAPI_CALL(env, napi_queue_async_work_with_qos(env, dataAbilityHelperCB->cbBase.asyncWork,
1090 napi_qos_user_initiated));
1091 TAG_LOGI(AAFwkTag::FA, "end");
1092 return promise;
1093 }
1094
GetDataAbilityHelperAsyncCompleteCB(napi_env env,napi_status status,void * data)1095 void GetDataAbilityHelperAsyncCompleteCB(napi_env env, napi_status status, void *data)
1096 {
1097 TAG_LOGI(AAFwkTag::FA, "called");
1098 DataAbilityHelperCB *dataAbilityHelperCB = static_cast<DataAbilityHelperCB *>(data);
1099 std::unique_ptr<DataAbilityHelperCB> callbackPtr {dataAbilityHelperCB};
1100 napi_value uri = nullptr;
1101 napi_value callback = nullptr;
1102 napi_value undefined = nullptr;
1103 napi_value result[ARGS_TWO] = {nullptr};
1104 napi_value callResult = nullptr;
1105 napi_get_undefined(env, &undefined);
1106 napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri);
1107 napi_get_reference_value(env, dataAbilityHelperCB->cbBase.cbInfo.callback, &callback);
1108 napi_new_instance(env, GetGlobalDataAbilityHelper(env), 1, &uri, &dataAbilityHelperCB->result);
1109 if (IsTypeForNapiValue(env, dataAbilityHelperCB->result, napi_object)) {
1110 result[PARAM1] = dataAbilityHelperCB->result;
1111 } else {
1112 TAG_LOGI(AAFwkTag::FA, "helper is nullptr");
1113 result[PARAM1] = WrapVoidToJS(env);
1114 }
1115 result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
1116 napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
1117 if (dataAbilityHelperCB->cbBase.cbInfo.callback != nullptr) {
1118 napi_delete_reference(env, dataAbilityHelperCB->cbBase.cbInfo.callback);
1119 }
1120 if (dataAbilityHelperCB->uri != nullptr) {
1121 napi_delete_reference(env, dataAbilityHelperCB->uri);
1122 }
1123 napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork);
1124 TAG_LOGI(AAFwkTag::FA, "end");
1125 }
1126
GetDataAbilityHelperPromiseCompleteCB(napi_env env,napi_status status,void * data)1127 void GetDataAbilityHelperPromiseCompleteCB(napi_env env, napi_status status, void *data)
1128 {
1129 TAG_LOGI(AAFwkTag::FA, "called");
1130 DataAbilityHelperCB *dataAbilityHelperCB = static_cast<DataAbilityHelperCB *>(data);
1131 napi_value uri = nullptr;
1132 napi_value result = nullptr;
1133 napi_get_reference_value(env, dataAbilityHelperCB->uri, &uri);
1134 napi_new_instance(env, GetGlobalDataAbilityHelper(env), 1, &uri, &dataAbilityHelperCB->result);
1135 if (IsTypeForNapiValue(env, dataAbilityHelperCB->result, napi_object)) {
1136 result = dataAbilityHelperCB->result;
1137 napi_resolve_deferred(env, dataAbilityHelperCB->cbBase.deferred, result);
1138 } else {
1139 result = GetCallbackErrorValue(env, dataAbilityHelperCB->cbBase.errCode);
1140 napi_reject_deferred(env, dataAbilityHelperCB->cbBase.deferred, result);
1141 TAG_LOGI(AAFwkTag::FA, "null helper");
1142 }
1143
1144 if (dataAbilityHelperCB->uri != nullptr) {
1145 napi_delete_reference(env, dataAbilityHelperCB->uri);
1146 }
1147 napi_delete_async_work(env, dataAbilityHelperCB->cbBase.asyncWork);
1148 TAG_LOGI(AAFwkTag::FA, "end");
1149 }
1150
1151 /**
1152 * @brief FeatureAbility NAPI method : acquireDataAbilityHelper.
1153 *
1154 * @param env The environment that the Node-API call is invoked under.
1155 * @param info The callback info passed into the callback function.
1156 *
1157 * @return The return value from NAPI C++ to JS for the module.
1158 */
NAPI_AcquireDataAbilityHelper(napi_env env,napi_callback_info info)1159 napi_value NAPI_AcquireDataAbilityHelper(napi_env env, napi_callback_info info)
1160 {
1161 return NAPI_AcquireDataAbilityHelperCommon(env, info, AbilityType::PAGE);
1162 }
1163
1164 /**
1165 * @brief FeatureAbility NAPI method : continueAbility.
1166 *
1167 * @param env The environment that the Node-API call is invoked under.
1168 * @param info The callback info passed into the callback function.
1169 *
1170 * @return The return value from NAPI C++ to JS for the module.
1171 */
NAPI_FAContinueAbility(napi_env env,napi_callback_info info)1172 napi_value NAPI_FAContinueAbility(napi_env env, napi_callback_info info)
1173 {
1174 TAG_LOGI(AAFwkTag::FA, "called");
1175 AsyncCallbackInfo *asyncCallbackInfo = CreateAsyncCallbackInfo(env);
1176 if (asyncCallbackInfo == nullptr) {
1177 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
1178 return WrapVoidToJS(env);
1179 }
1180
1181 napi_value ret = ContinueAbilityWrap(env, info, asyncCallbackInfo);
1182 if (ret == nullptr) {
1183 if (asyncCallbackInfo != nullptr) {
1184 delete asyncCallbackInfo;
1185 asyncCallbackInfo = nullptr;
1186 }
1187 ret = WrapVoidToJS(env);
1188 }
1189 TAG_LOGI(AAFwkTag::FA, "end");
1190 return ret;
1191 }
1192
1193 /**
1194 * @brief ContinueAbilityWrap processing function.
1195 *
1196 * @param env The environment that the Node-API call is invoked under.
1197 * @param asyncCallbackInfo Process data asynchronously.
1198 *
1199 * @return Return JS data successfully, otherwise return nullptr.
1200 */
ContinueAbilityWrap(napi_env env,napi_callback_info info,AsyncCallbackInfo * asyncCallbackInfo)1201 napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info, AsyncCallbackInfo *asyncCallbackInfo)
1202 {
1203 TAG_LOGI(AAFwkTag::FA, "called");
1204 size_t argc = 2;
1205 napi_value args[ARGS_MAX_COUNT] = {nullptr};
1206 napi_value ret = nullptr;
1207 napi_valuetype valueType = napi_undefined;
1208
1209 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
1210 NAPI_CALL(env, napi_typeof(env, args[0], &valueType));
1211 if (valueType != napi_object && valueType != napi_function) {
1212 TAG_LOGE(AAFwkTag::FA, "wrong argument type. Object or function expected");
1213 return nullptr;
1214 }
1215 if (argc == 0) {
1216 ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc);
1217 } else if (PARA_SIZE_IS_ONE == argc) {
1218 if (valueType == napi_function) {
1219 ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc);
1220 } else {
1221 ret = ContinueAbilityPromise(env, args, asyncCallbackInfo, argc);
1222 }
1223 } else if (PARA_SIZE_IS_TWO == argc) {
1224 napi_valuetype value = napi_undefined;
1225 NAPI_CALL(env, napi_typeof(env, args[1], &value));
1226 if (value != napi_function) {
1227 TAG_LOGE(AAFwkTag::FA, "function expected");
1228 return nullptr;
1229 }
1230 ret = ContinueAbilityAsync(env, args, asyncCallbackInfo, argc);
1231 } else {
1232 TAG_LOGE(AAFwkTag::FA, "invalid argc");
1233 }
1234 TAG_LOGI(AAFwkTag::FA, "end");
1235 return ret;
1236 }
1237
CreateContinueAsyncWork(napi_env env,napi_value & resourceName,AsyncCallbackInfo * asyncCallbackInfo)1238 void CreateContinueAsyncWork(napi_env env, napi_value &resourceName, AsyncCallbackInfo *asyncCallbackInfo)
1239 {
1240 napi_create_async_work(env, nullptr, resourceName,
1241 [](napi_env env, void *data) {
1242 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute");
1243 AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data;
1244 if (asyncCallbackInfo->ability != nullptr) {
1245 asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId);
1246 } else {
1247 TAG_LOGE(AAFwkTag::FA, "null asyncCallbackInfo");
1248 }
1249 TAG_LOGI(AAFwkTag::FA, "worker pool thread execute exit");
1250 },
1251 [](napi_env env, napi_status status, void *data) {
1252 TAG_LOGI(AAFwkTag::FA, "main event thread end");
1253 AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data;
1254 napi_value callback = nullptr;
1255 napi_value undefined = nullptr;
1256 napi_value result[ARGS_TWO] = {nullptr};
1257 napi_value callResult = nullptr;
1258 napi_get_undefined(env, &undefined);
1259 result[PARAM0] = GetCallbackErrorValue(env, NO_ERROR);
1260 napi_get_null(env, &result[PARAM1]);
1261 napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
1262 napi_call_function(env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
1263
1264 if (asyncCallbackInfo->cbInfo.callback != nullptr) {
1265 napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
1266 }
1267 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1268 delete asyncCallbackInfo;
1269 TAG_LOGI(AAFwkTag::FA, "end");
1270 },
1271 static_cast<void *>(asyncCallbackInfo),
1272 &asyncCallbackInfo->asyncWork);
1273 }
1274
ContinueAbilityAsync(napi_env env,napi_value * args,AsyncCallbackInfo * asyncCallbackInfo,size_t argc)1275 napi_value ContinueAbilityAsync(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc)
1276 {
1277 TAG_LOGI(AAFwkTag::FA, "asyncCallback");
1278 if (args == nullptr || asyncCallbackInfo == nullptr) {
1279 TAG_LOGE(AAFwkTag::FA, "null param");
1280 return nullptr;
1281 }
1282 napi_value resourceName = nullptr;
1283 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1284
1285 if (PARA_SIZE_IS_TWO == argc) {
1286 // args[0] : ContinueAbilityOptions
1287 napi_valuetype valueTypeOptions = napi_undefined;
1288 NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions));
1289 if (valueTypeOptions != napi_object) {
1290 TAG_LOGE(AAFwkTag::FA, "object expected");
1291 return nullptr;
1292 }
1293 if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) {
1294 TAG_LOGE(AAFwkTag::FA, "getContinueAbilityOptionsInfoCommon fail");
1295 return nullptr;
1296 }
1297
1298 // args[1] : callback
1299 napi_valuetype valueTypeCallBack = napi_undefined;
1300 napi_typeof(env, args[1], &valueTypeCallBack);
1301 if (valueTypeCallBack == napi_function) {
1302 napi_create_reference(env, args[1], 1, &asyncCallbackInfo->cbInfo.callback);
1303 }
1304 } else {
1305 // args[0] : callback
1306 napi_valuetype valueTypeCallBack = napi_undefined;
1307 napi_typeof(env, args[1], &valueTypeCallBack);
1308 if (valueTypeCallBack == napi_function) {
1309 napi_create_reference(env, args[0], 1, &asyncCallbackInfo->cbInfo.callback);
1310 }
1311 }
1312
1313 CreateContinueAsyncWork(env, resourceName, asyncCallbackInfo);
1314
1315 napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
1316 napi_value result = nullptr;
1317 napi_get_null(env, &result);
1318 TAG_LOGI(AAFwkTag::FA, "end");
1319 return result;
1320 }
1321
ContinueAbilityPromise(napi_env env,napi_value * args,AsyncCallbackInfo * asyncCallbackInfo,size_t argc)1322 napi_value ContinueAbilityPromise(napi_env env, napi_value *args, AsyncCallbackInfo *asyncCallbackInfo, size_t argc)
1323 {
1324 TAG_LOGI(AAFwkTag::FA, "called");
1325 if (asyncCallbackInfo == nullptr) {
1326 TAG_LOGE(AAFwkTag::FA, "null param");
1327 return nullptr;
1328 }
1329
1330 if (argc == PARA_SIZE_IS_ONE) {
1331 // args[0] : ContinueAbilityOptions
1332 napi_valuetype valueTypeOptions = napi_undefined;
1333 NAPI_CALL(env, napi_typeof(env, args[0], &valueTypeOptions));
1334 if (valueTypeOptions != napi_object) {
1335 TAG_LOGE(AAFwkTag::FA, "object expected");
1336 return nullptr;
1337 }
1338 if (GetContinueAbilityOptionsInfoCommon(env, args[0], asyncCallbackInfo->optionInfo) == nullptr) {
1339 return nullptr;
1340 }
1341 }
1342
1343 napi_value resourceName = nullptr;
1344 napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
1345 napi_deferred deferred;
1346 napi_value promise = nullptr;
1347 napi_create_promise(env, &deferred, &promise);
1348
1349 asyncCallbackInfo->deferred = deferred;
1350
1351 napi_create_async_work(env, nullptr, resourceName,
1352 [](napi_env env, void *data) {
1353 TAG_LOGI(AAFwkTag::FA, "execute called");
1354 AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data;
1355 if (asyncCallbackInfo->ability != nullptr) {
1356 asyncCallbackInfo->ability->ContinueAbility(asyncCallbackInfo->optionInfo.deviceId);
1357 } else {
1358 TAG_LOGE(AAFwkTag::FA, "null ability");
1359 }
1360 TAG_LOGI(AAFwkTag::FA, "execute end");
1361 },
1362 [](napi_env env, napi_status status, void *data) {
1363 TAG_LOGI(AAFwkTag::FA, "complete called");
1364 AsyncCallbackInfo *asyncCallbackInfo = (AsyncCallbackInfo *)data;
1365 napi_value result = nullptr;
1366 napi_get_null(env, &result);
1367 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
1368 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1369 delete asyncCallbackInfo;
1370 TAG_LOGI(AAFwkTag::FA, "complete end");
1371 },
1372 static_cast<void *>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork);
1373 napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
1374 TAG_LOGI(AAFwkTag::FA, "end");
1375 return promise;
1376 }
1377 } // namespace AppExecFwk
1378 } // namespace OHOS
1379