1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_form_host.h"
17 
18 #include <cinttypes>
19 #include <regex>
20 #include <typeinfo>
21 #include <uv.h>
22 #include <vector>
23 #include <iostream>
24 #include <string>
25 
26 #include "fms_log_wrapper.h"
27 #include "form_info.h"
28 #include "form_callback_interface.h"
29 #include "form_host_client.h"
30 #include "form_mgr.h"
31 #include "form_mgr_errors.h"
32 #include "napi_form_util.h"
33 #include "napi/native_api.h"
34 #include "napi/native_node_api.h"
35 #include "napi_common_util.h"
36 #include "napi_common_want.h"
37 #include "runtime.h"
38 
39 namespace OHOS {
40 namespace AbilityRuntime {
41 using namespace OHOS;
42 using namespace OHOS::AAFwk;
43 using namespace OHOS::AppExecFwk;
44 
45 namespace {
46     constexpr size_t ARGS_SIZE_ONE = 1;
47     constexpr size_t ARGS_SIZE_TWO = 2;
48     constexpr size_t ARGS_SIZE_THREE = 3;
49     constexpr int REF_COUNT = 1;
50     constexpr int CALLBACK_FLG = 1;
51     constexpr int PROMISE_FLG = 2;
52     // NANOSECONDS mean 10^9 nano second
53     constexpr int64_t NANOSECONDS = 1000000000;
54     // MICROSECONDS mean 10^6 millias second
55     constexpr int64_t MICROSECONDS = 1000000;
56 
57     struct OnDeleteInvalidFormsS {
58         int result;
59         int32_t numFormsDeleted = 0;
60         std::vector<int64_t> iFormIds;
61     };
62 }
63 
64 /**
65  * @brief Get a C++ string value from Node-API
66  *
67  * @param[in] env The environment that the Node-API call is invoked under
68  * @param[in] value This is an opaque pointer that is used to represent a JavaScript value
69  *
70  * @return Return a C++ string
71  */
GetStringFromNAPI(napi_env env,napi_value value)72 static std::string GetStringFromNAPI(napi_env env, napi_value value)
73 {
74     std::string result;
75     size_t size = 0;
76 
77     if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) {
78         HILOG_ERROR("%{public}s, can not get string size", __func__);
79         return "";
80     }
81     result.reserve(size + 1);
82     result.resize(size);
83     if (napi_get_value_string_utf8(env, value, result.data(), (size + 1), &size) != napi_ok) {
84         HILOG_ERROR("%{public}s, can not get string value", __func__);
85         return "";
86     }
87     return result;
88 }
89 
GetFormIds(napi_env env,napi_value value,ErrCode & errCode,std::vector<int64_t> & formIds)90 static napi_value GetFormIds(napi_env env, napi_value value, ErrCode &errCode, std::vector<int64_t> &formIds)
91 {
92     errCode = ERR_INVALID_VALUE;
93 
94     bool isArray;
95     NAPI_CALL(env, napi_is_array(env, value, &isArray));
96     if (!isArray) {
97         errCode = ERR_APPEXECFWK_FORM_FORM_ARRAY_ERR;
98         return nullptr;
99     }
100 
101     uint32_t arrayLength = 0;
102     NAPI_CALL(env, napi_get_array_length(env, value, &arrayLength));
103 
104     for (size_t i = 0; i < arrayLength; i++) {
105         napi_value napiFormId;
106         napi_get_element(env, value, i, &napiFormId);
107 
108         // Check the value type of the arguments
109         napi_valuetype valueType = napi_undefined;
110         NAPI_CALL(env, napi_typeof(env, napiFormId, &valueType));
111         if (valueType != napi_string) {
112             errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
113             return nullptr;
114         }
115 
116         std::string strFormId = GetStringFromNAPI(env, napiFormId);
117         int64_t formIdValue;
118         if (!ConvertStringToInt64(strFormId, formIdValue)) {
119             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
120             return nullptr;
121         }
122 
123         formIds.push_back(formIdValue);
124     }
125 
126     errCode = ERR_OK;
127     return nullptr;
128 }
129 
ParseFormStateInfo(napi_env env,FormStateInfo & stateInfo)130 napi_value ParseFormStateInfo(napi_env env, FormStateInfo &stateInfo)
131 {
132     napi_value formStateInfoObject = nullptr;
133     napi_create_object(env, &formStateInfoObject);
134     napi_value jsValue = WrapWant(env, stateInfo.want);
135     SetPropertyValueByPropertyName(env, formStateInfoObject, "want", jsValue);
136     napi_value formState = nullptr;
137     napi_create_int32(env, (int32_t) stateInfo.state, &formState);
138     SetPropertyValueByPropertyName(env, formStateInfoObject, "formState", formState);
139 
140     return formStateInfoObject;
141 }
142 
AcquireFormStateCallbackComplete(uv_work_t * work,int32_t status)143 void AcquireFormStateCallbackComplete(uv_work_t *work, int32_t status)
144 {
145     HILOG_INFO("call");
146     if (work == nullptr) {
147         HILOG_ERROR("work == nullptr.");
148         return;
149     }
150     auto *asyncCallbackInfo = static_cast<AsyncAcquireFormStateCallbackInfo *>(work->data);
151     if (asyncCallbackInfo == nullptr) {
152         HILOG_ERROR("asyncCallbackInfo == nullptr.");
153         delete work;
154         return;
155     }
156     napi_env env = asyncCallbackInfo->env;
157 
158     if (asyncCallbackInfo->callback != nullptr) {
159         napi_value callback;
160         napi_value callbackValues[ARGS_SIZE_TWO] = {nullptr, nullptr};
161         InnerCreateCallbackRetMsg(env, asyncCallbackInfo->result, callbackValues);
162         if (asyncCallbackInfo->result == ERR_OK) {
163             callbackValues[1] = ParseFormStateInfo(env, asyncCallbackInfo->stateInfo);
164         }
165 
166         napi_get_reference_value(env, asyncCallbackInfo->callback, &callback);
167         napi_value callResult;
168         napi_call_function(env, nullptr, callback, ARGS_SIZE_TWO, callbackValues, &callResult);
169         napi_delete_reference(env, asyncCallbackInfo->callback);
170     }
171 
172     delete asyncCallbackInfo;
173     asyncCallbackInfo = nullptr;
174     delete work;
175     work = nullptr;
176     HILOG_INFO("end");
177 }
178 
AcquireFormStatePromiseComplete(uv_work_t * work,int32_t status)179 void AcquireFormStatePromiseComplete(uv_work_t *work, int32_t status)
180 {
181     HILOG_INFO("onAcquireFormState back");
182     if (work == nullptr) {
183         HILOG_ERROR("%{public}s, work == nullptr.", __func__);
184         return;
185     }
186     auto *asyncCallbackInfo = static_cast<AsyncAcquireFormStateCallbackInfo *>(work->data);
187     if (asyncCallbackInfo == nullptr) {
188         HILOG_ERROR("asyncCallbackInfo == nullptr.");
189         delete work;
190         return;
191     }
192     napi_env env = asyncCallbackInfo->env;
193 
194     if (asyncCallbackInfo->result != ERR_OK) {
195         napi_value result;
196         InnerCreatePromiseRetMsg(env, asyncCallbackInfo->result, &result);
197         napi_reject_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
198     } else {
199         napi_value result = ParseFormStateInfo(env, asyncCallbackInfo->stateInfo);
200         napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
201     }
202 
203     delete asyncCallbackInfo;
204     asyncCallbackInfo = nullptr;
205     delete work;
206     work = nullptr;
207     HILOG_INFO("onAcquireFormState done");
208 }
209 
210 namespace {
211 class FormStateCallbackClient : public FormStateCallbackInterface {
212 public:
FormStateCallbackClient(AsyncAcquireFormStateCallbackInfo * const asyncCallbackInfo)213     explicit FormStateCallbackClient(AsyncAcquireFormStateCallbackInfo *const asyncCallbackInfo)
214     {
215         asyncCallbackInfo_ = asyncCallbackInfo;
216     }
217 
218     virtual ~FormStateCallbackClient() = default;
219 
ProcessAcquireState(FormState state)220     void ProcessAcquireState(FormState state) override
221     {
222         if (asyncCallbackInfo_ == nullptr) {
223             return;
224         }
225         asyncCallbackInfo_->stateInfo.state = state;
226 
227         uv_loop_s *loop = nullptr;
228         napi_get_uv_event_loop(asyncCallbackInfo_->env, &loop);
229         if (loop == nullptr) {
230             HILOG_ERROR("%{public}s, loop == nullptr.", __func__);
231             return;
232         }
233 
234         auto *work = new (std::nothrow) uv_work_t;
235         if (work == nullptr) {
236             HILOG_ERROR("%{public}s, work == nullptr.", __func__);
237             return;
238         }
239         work->data = asyncCallbackInfo_;
240 
241         int32_t result = 0;
242         if (asyncCallbackInfo_->callbackType == CALLBACK_FLG) {
243             result = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {},
244                 AcquireFormStateCallbackComplete, uv_qos_default);
245         } else {
246             result = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {},
247                 AcquireFormStatePromiseComplete, uv_qos_default);
248         }
249         // When uv_queue_work_with_qos returns 0, asyncCallbackInfo_ and work will be freed in the callback function.
250         if (result != 0) {
251             delete asyncCallbackInfo_;
252             asyncCallbackInfo_ = nullptr;
253             delete work;
254             work = nullptr;
255         }
256     }
257 
258 private:
259     AsyncAcquireFormStateCallbackInfo *asyncCallbackInfo_ = nullptr;
260 };
261 
262 class FormUninstallCallbackClient : public std::enable_shared_from_this<FormUninstallCallbackClient> {
263 public:
FormUninstallCallbackClient(napi_env env,napi_ref callbackRef)264     FormUninstallCallbackClient(napi_env env, napi_ref callbackRef) : callbackRef_(callbackRef), env_(env)
265     {
266         handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
267     }
268 
~FormUninstallCallbackClient()269     virtual ~FormUninstallCallbackClient()
270     {
271         napi_delete_reference(env_, callbackRef_);
272     }
273 
ProcessFormUninstall(const int64_t formId)274     void ProcessFormUninstall(const int64_t formId)
275     {
276         if (handler_ == nullptr) {
277             HILOG_INFO("handler is null");
278             return;
279         }
280         handler_->PostSyncTask([thisWeakPtr = weak_from_this(), formId]() {
281             auto sharedThis = thisWeakPtr.lock();
282             if (sharedThis == nullptr) {
283                 HILOG_ERROR("sharedThis is null.");
284                 return;
285             }
286             HILOG_DEBUG("task end formId: form: %{public}" PRId64 ".", formId);
287             std::string formIdString = std::to_string(formId);
288             napi_value callbackValues;
289             napi_create_string_utf8(sharedThis->env_, formIdString.c_str(), NAPI_AUTO_LENGTH, &callbackValues);
290             napi_value callResult;
291             napi_value myCallback = nullptr;
292             napi_get_reference_value(sharedThis->env_, sharedThis->callbackRef_, &myCallback);
293             if (myCallback != nullptr) {
294                 napi_call_function(sharedThis->env_, nullptr, myCallback, ARGS_SIZE_ONE, &callbackValues, &callResult);
295             }
296         });
297     }
298 
IsStrictEqual(napi_value callback)299     bool IsStrictEqual(napi_value callback)
300     {
301         bool isEqual = false;
302         napi_value myCallback = nullptr;
303         napi_get_reference_value(env_, callbackRef_, &myCallback);
304         napi_strict_equals(env_, myCallback, callback, &isEqual);
305         HILOG_INFO("isStrictEqual:%{public}d", isEqual);
306         return isEqual;
307     }
308 
309 private:
310     std::shared_ptr<AppExecFwk::EventHandler> handler_ = nullptr;
311     napi_ref callbackRef_ {};
312     napi_env env_;
313 };
314 
315 std::map<napi_ref, std::shared_ptr<FormUninstallCallbackClient>> g_formUninstallCallbackMap {};
316 std::mutex formUninstallCallbackMapMutex_;
317 
FormUninstallCallback(const std::vector<int64_t> & formIds)318 void FormUninstallCallback(const std::vector<int64_t> &formIds)
319 {
320     std::lock_guard<std::mutex> lock(formUninstallCallbackMapMutex_);
321     for (auto &iter : g_formUninstallCallbackMap) {
322         for (int64_t formId : formIds) {
323             iter.second->ProcessFormUninstall(formId);
324         }
325     }
326 }
327 
AddFormUninstallCallback(napi_env env,napi_value callback)328 bool AddFormUninstallCallback(napi_env env, napi_value callback)
329 {
330     std::lock_guard<std::mutex> lock(formUninstallCallbackMapMutex_);
331     for (auto &iter : g_formUninstallCallbackMap) {
332         if (iter.second->IsStrictEqual(callback)) {
333             HILOG_ERROR("found equal callback");
334             return false;
335         }
336     }
337 
338     napi_ref callbackRef;
339     napi_create_reference(env, callback, REF_COUNT, &callbackRef);
340     std::shared_ptr<FormUninstallCallbackClient> callbackClient = std::make_shared<FormUninstallCallbackClient>(env,
341         callbackRef);
342 
343     auto ret = g_formUninstallCallbackMap.emplace(callbackRef, callbackClient);
344     if (!ret.second) {
345         HILOG_ERROR("failed to emplace callback");
346         return false;
347     }
348     return true;
349 }
350 
DelFormUninstallCallback(napi_value callback)351 bool DelFormUninstallCallback(napi_value callback)
352 {
353     int32_t count = 0;
354     std::lock_guard<std::mutex> lock(formUninstallCallbackMapMutex_);
355     for (auto iter = g_formUninstallCallbackMap.begin(); iter != g_formUninstallCallbackMap.end();) {
356         if (iter->second->IsStrictEqual(callback)) {
357             HILOG_INFO("equal callback");
358             iter = g_formUninstallCallbackMap.erase(iter);
359             count++;
360         } else {
361             iter++;
362         }
363     }
364     HILOG_INFO("%{public}d form uninstall callback deleted.", count);
365     return true;
366 }
367 
ClearFormUninstallCallback()368 bool ClearFormUninstallCallback()
369 {
370     std::lock_guard<std::mutex> lock(formUninstallCallbackMapMutex_);
371     g_formUninstallCallbackMap.clear();
372     return true;
373 }
374 }
375 
InnerAcquireFormState(napi_env env,AsyncAcquireFormStateCallbackInfo * const asyncCallbackInfo)376 static void InnerAcquireFormState(napi_env env, AsyncAcquireFormStateCallbackInfo *const asyncCallbackInfo)
377 {
378     HILOG_DEBUG("%{public}s called.", __func__);
379     std::shared_ptr<FormStateCallbackInterface> formStateCallback = std::make_shared<FormStateCallbackClient>(
380         asyncCallbackInfo);
381     FormHostClient::GetInstance()->AddFormState(formStateCallback, asyncCallbackInfo->want);
382 
383     asyncCallbackInfo->result = FormMgr::GetInstance().AcquireFormState(asyncCallbackInfo->want,
384         FormHostClient::GetInstance(), asyncCallbackInfo->stateInfo);
385     HILOG_DEBUG("%{public}s, end", __func__);
386 }
387 
AcquireFormStateCallback(napi_env env,AsyncAcquireFormStateCallbackInfo * const asyncCallbackInfo)388 napi_value AcquireFormStateCallback(napi_env env, AsyncAcquireFormStateCallbackInfo *const asyncCallbackInfo)
389 {
390     HILOG_INFO("asyncCallback.");
391     napi_value resourceName;
392     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
393     napi_create_async_work(
394         env,
395         nullptr,
396         resourceName,
397         [](napi_env env, void *data) {
398             HILOG_INFO("napi_create_async_work running");
399             auto *asyncCallbackInfo = (AsyncAcquireFormStateCallbackInfo *) data;
400             InnerAcquireFormState(env, asyncCallbackInfo);
401         },
402         [](napi_env env, napi_status status, void *data) {
403             HILOG_INFO("napi_create_async_work complete");
404             auto *asyncCallbackInfo = (AsyncAcquireFormStateCallbackInfo *) data;
405             // asyncCallbackInfo will be freed in OnAcquireState, so save the member variable asyncWork.
406             napi_async_work asyncWork = asyncCallbackInfo->asyncWork;
407             // When the result is not ERR_OK, OnAcquireState will be called here,
408             // else OnAcquireState will be called after the form state is acquired.
409             if (asyncCallbackInfo->result != ERR_OK) {
410                 FormHostClient::GetInstance()->OnAcquireState(FormState::UNKNOWN, asyncCallbackInfo->want);
411             }
412             napi_delete_async_work(env, asyncWork);
413         },
414         (void *) asyncCallbackInfo,
415         &asyncCallbackInfo->asyncWork);
416     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default));
417     return NapiGetResult(env, 1);
418 }
419 
AcquireFormStatePromise(napi_env env,AsyncAcquireFormStateCallbackInfo * const asyncCallbackInfo)420 napi_value AcquireFormStatePromise(napi_env env, AsyncAcquireFormStateCallbackInfo *const asyncCallbackInfo)
421 {
422     HILOG_INFO("promise.");
423     napi_deferred deferred;
424     napi_value promise;
425     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
426     asyncCallbackInfo->deferred = deferred;
427 
428     napi_value resourceName;
429     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
430     napi_create_async_work(
431         env,
432         nullptr,
433         resourceName,
434         [](napi_env env, void *data) {
435             HILOG_INFO("runnning");
436             auto *asyncCallbackInfo = (AsyncAcquireFormStateCallbackInfo *) data;
437             InnerAcquireFormState(env, asyncCallbackInfo);
438         },
439         [](napi_env env, napi_status status, void *data) {
440             HILOG_INFO("complete");
441             auto *asyncCallbackInfo = (AsyncAcquireFormStateCallbackInfo *) data;
442             // asyncCallbackInfo will be freed in OnAcquireState, so save the member variable asyncWork.
443             napi_async_work asyncWork = asyncCallbackInfo->asyncWork;
444             // When the result is not ERR_OK, OnAcquireState will be called here,
445             // else OnAcquireState will be called after the form state is acquired.
446             if (asyncCallbackInfo->result != ERR_OK) {
447                 FormHostClient::GetInstance()->OnAcquireState(FormState::UNKNOWN, asyncCallbackInfo->want);
448             }
449             napi_delete_async_work(env, asyncWork);
450         },
451         (void *) asyncCallbackInfo,
452         &asyncCallbackInfo->asyncWork);
453     napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default);
454     return promise;
455 }
456 
457 /**
458  * @brief  The implementation of Node-API interface: acquireFormState
459  *
460  * @param[in] env The environment that the Node-API call is invoked under
461  * @param[out] info An opaque datatype that is passed to a callback function
462  *
463  * @return This is an opaque pointer that is used to represent a JavaScript value
464  */
NAPI_AcquireFormState(napi_env env,napi_callback_info info)465 napi_value NAPI_AcquireFormState(napi_env env, napi_callback_info info)
466 {
467     HILOG_INFO("call");
468 
469     // Check the number of the arguments
470     size_t argc = ARGS_SIZE_TWO;
471     napi_value argv[ARGS_SIZE_TWO] = {nullptr, nullptr};
472     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
473     if (argc > ARGS_SIZE_TWO) {
474         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
475         return nullptr;
476     }
477     HILOG_INFO("argc:[%{public}zu]", argc);
478 
479     int32_t callbackType = (argc == ARGS_SIZE_TWO) ? CALLBACK_FLG : PROMISE_FLG;
480     napi_valuetype valueType = napi_undefined;
481     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
482     if (valueType != napi_object) {
483         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_INVALID_PARAM, callbackType, argv[1]));
484     }
485 
486     auto *asyncCallbackInfo = new (std::nothrow) AsyncAcquireFormStateCallbackInfo {
487         .env = env,
488         .asyncWork = nullptr,
489         .deferred = nullptr,
490         .callback = nullptr,
491         .want = {},
492         .stateInfo = {},
493         .callbackType = callbackType,
494         .result = ERR_OK,
495     };
496     if (asyncCallbackInfo == nullptr) {
497         HILOG_ERROR("asyncCallbackInfo == nullptr.");
498         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_COMMON_CODE, callbackType, argv[1]));
499     }
500     std::unique_ptr<AsyncAcquireFormStateCallbackInfo> callbackPtr {asyncCallbackInfo};
501 
502     bool parseResult = UnwrapWant(env, argv[0], asyncCallbackInfo->want);
503     if (!parseResult) {
504         HILOG_ERROR("%{public}s, failed to parse want.", __func__);
505         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_INVALID_PARAM, callbackType, argv[1]));
506     }
507 
508     napi_value result;
509     if (argc == ARGS_SIZE_TWO) {
510         // Check the value type of the arguments
511         valueType = napi_undefined;
512         NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
513         NAPI_ASSERT(env, valueType == napi_function,
514             "The arguments[1] type of acquireFormState is incorrect, expected type is function.");
515         napi_create_reference(env, argv[1], REF_COUNT, &asyncCallbackInfo->callback);
516         result = AcquireFormStateCallback(env, asyncCallbackInfo);
517     } else {
518         result = AcquireFormStatePromise(env, asyncCallbackInfo);
519     }
520     callbackPtr.release();
521     return result;
522 }
523 
524 /**
525  * @brief  The implementation of Node-API interface: on
526  *
527  * @param[in] env The environment that the Node-API call is invoked under
528  * @param[out] info An opaque datatype that is passed to a callback function
529  *
530  * @return This is an opaque pointer that is used to represent a JavaScript value
531  */
NAPI_RegisterFormUninstallObserver(napi_env env,napi_callback_info info)532 napi_value NAPI_RegisterFormUninstallObserver(napi_env env, napi_callback_info info)
533 {
534     HILOG_INFO("call");
535 
536     // Check the number of the arguments
537     size_t argc = ARGS_SIZE_TWO;
538     napi_value argv[ARGS_SIZE_TWO] = {nullptr, nullptr};
539     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
540     if (argc != ARGS_SIZE_TWO) {
541         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
542         return nullptr;
543     }
544     HILOG_INFO("argc:[%{public}zu]", argc);
545 
546     napi_valuetype valueType = napi_undefined;
547     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
548     if (valueType != napi_string) {
549         HILOG_ERROR("The type of args[0] is incorrect, expected type is string.");
550         return nullptr;
551     }
552     std::string type;
553     if (!UnwrapStringFromJS2(env, argv[0], type)) {
554         HILOG_ERROR("failed to get args[0].");
555         return nullptr;
556     }
557 
558     if (type != "formUninstall") {
559         HILOG_ERROR("args[0] should be formUninstall.");
560         return nullptr;
561     }
562 
563     valueType = napi_undefined;
564     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
565     if (valueType != napi_function) {
566         HILOG_ERROR("The type of args[1] is incorrect, expected type is function.");
567         return nullptr;
568     }
569 
570     FormHostClient::GetInstance()->RegisterUninstallCallback(FormUninstallCallback);
571     AddFormUninstallCallback(env, argv[1]);
572     return nullptr;
573 }
574 
575 /**
576  * @brief  The implementation of Node-API interface: off
577  *
578  * @param[in] env The environment that the Node-API call is invoked under
579  * @param[out] info An opaque datatype that is passed to a callback function
580  *
581  * @return This is an opaque pointer that is used to represent a JavaScript value
582  */
NAPI_UnregisterFormUninstallObserver(napi_env env,napi_callback_info info)583 napi_value NAPI_UnregisterFormUninstallObserver(napi_env env, napi_callback_info info)
584 {
585     HILOG_INFO("call");
586 
587     // Check the number of the arguments
588     size_t argc = ARGS_SIZE_TWO;
589     napi_value argv[ARGS_SIZE_TWO] = {nullptr, nullptr};
590     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
591     if (argc > ARGS_SIZE_TWO) {
592         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
593         return nullptr;
594     }
595     HILOG_INFO("argc:[%{public}zu]", argc);
596 
597     napi_valuetype valueType = napi_undefined;
598     NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
599     if (valueType != napi_string) {
600         HILOG_ERROR("The type of args[0] is incorrect, expected type is string.");
601         return nullptr;
602     }
603     std::string type;
604     if (!UnwrapStringFromJS2(env, argv[0], type)) {
605         HILOG_ERROR("failed to get args[0].");
606         return nullptr;
607     }
608 
609     if (type != "formUninstall") {
610         HILOG_ERROR("args[0] should be formUninstall.");
611         return nullptr;
612     }
613 
614     if (argc == ARGS_SIZE_TWO) {
615         valueType = napi_undefined;
616         NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
617         if (valueType != napi_function) {
618             HILOG_ERROR("The type of args[1] is incorrect, expected type is function.");
619             return nullptr;
620         }
621         DelFormUninstallCallback(argv[1]);
622         return nullptr;
623     } else {
624         ClearFormUninstallCallback();
625         return nullptr;
626     }
627 }
628 
InnerNotifyFormsVisible(napi_env env,AsyncNotifyFormsVisibleCallbackInfo * const asyncCallbackInfo)629 static void InnerNotifyFormsVisible(napi_env env, AsyncNotifyFormsVisibleCallbackInfo *const asyncCallbackInfo)
630 {
631     HILOG_DEBUG("%{public}s called.", __func__);
632 
633     asyncCallbackInfo->result = FormMgr::GetInstance().NotifyFormsVisible(asyncCallbackInfo->formIds,
634         asyncCallbackInfo->isVisible, FormHostClient::GetInstance());
635     HILOG_DEBUG("%{public}s, end", __func__);
636 }
637 
NotifyFormsVisibleCallback(napi_env env,AsyncNotifyFormsVisibleCallbackInfo * const asyncCallbackInfo)638 napi_value NotifyFormsVisibleCallback(napi_env env, AsyncNotifyFormsVisibleCallbackInfo *const asyncCallbackInfo)
639 {
640     HILOG_INFO("start");
641     napi_value resourceName;
642     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
643     napi_create_async_work(
644         env,
645         nullptr,
646         resourceName,
647         [](napi_env env, void *data) {
648             HILOG_INFO("running");
649             auto *asyncCallbackInfo = (AsyncNotifyFormsVisibleCallbackInfo *) data;
650             InnerNotifyFormsVisible(env, asyncCallbackInfo);
651         },
652         [](napi_env env, napi_status status, void *data) {
653             HILOG_INFO("complete");
654             auto *asyncCallbackInfo = (AsyncNotifyFormsVisibleCallbackInfo *) data;
655 
656             if (asyncCallbackInfo->callback != nullptr) {
657                 napi_value callback;
658                 napi_value callbackValues[ARGS_SIZE_TWO] = {nullptr, nullptr};
659                 InnerCreateCallbackRetMsg(env, asyncCallbackInfo->result, callbackValues);
660 
661                 napi_get_reference_value(env, asyncCallbackInfo->callback, &callback);
662                 napi_value callResult;
663                 napi_call_function(env, nullptr, callback, ARGS_SIZE_TWO, callbackValues, &callResult);
664                 napi_delete_reference(env, asyncCallbackInfo->callback);
665             }
666             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
667             delete asyncCallbackInfo;
668         },
669         (void *) asyncCallbackInfo,
670         &asyncCallbackInfo->asyncWork);
671     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default));
672     return NapiGetResult(env, 1);
673 }
674 
NotifyFormsVisiblePromise(napi_env env,AsyncNotifyFormsVisibleCallbackInfo * const asyncCallbackInfo)675 napi_value NotifyFormsVisiblePromise(napi_env env, AsyncNotifyFormsVisibleCallbackInfo *const asyncCallbackInfo)
676 {
677     HILOG_INFO("NotifyFormsVisiblePromise start");
678     napi_deferred deferred;
679     napi_value promise;
680     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
681     asyncCallbackInfo->deferred = deferred;
682 
683     napi_value resourceName;
684     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
685     napi_create_async_work(
686         env,
687         nullptr,
688         resourceName,
689         [](napi_env env, void *data) {
690             HILOG_INFO("promise runnning");
691             auto *asyncCallbackInfo = (AsyncNotifyFormsVisibleCallbackInfo *) data;
692             InnerNotifyFormsVisible(env, asyncCallbackInfo);
693         },
694         [](napi_env env, napi_status status, void *data) {
695             HILOG_INFO("promise complete");
696             auto *asyncCallbackInfo = (AsyncNotifyFormsVisibleCallbackInfo *) data;
697             napi_value result;
698             InnerCreatePromiseRetMsg(env, asyncCallbackInfo->result, &result);
699             if (asyncCallbackInfo->result == ERR_OK) {
700                 napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
701             } else {
702                 napi_reject_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
703             }
704             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
705             delete asyncCallbackInfo;
706         },
707         (void *) asyncCallbackInfo,
708         &asyncCallbackInfo->asyncWork);
709     napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default);
710     return promise;
711 }
712 
713 /**
714  * @brief  The implementation of Node-API interface: notifyFormsVisible
715  *
716  * @param[in] env The environment that the Node-API call is invoked under
717  * @param[out] info An opaque datatype that is passed to a callback function
718  *
719  * @return This is an opaque pointer that is used to represent a JavaScript value
720  */
NAPI_NotifyFormsVisible(napi_env env,napi_callback_info info)721 napi_value NAPI_NotifyFormsVisible(napi_env env, napi_callback_info info)
722 {
723     HILOG_INFO("call");
724 
725     // Check the number of the arguments
726     size_t argc = ARGS_SIZE_THREE;
727     napi_value argv[ARGS_SIZE_THREE] = {nullptr, nullptr, nullptr};
728     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
729     if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) {
730         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
731         return nullptr;
732     }
733 
734     int32_t callbackType = (argc == ARGS_SIZE_THREE) ? CALLBACK_FLG : PROMISE_FLG;
735 
736     ErrCode errCode;
737     std::vector<int64_t> formIds {};
738     GetFormIds(env, argv[0], errCode, formIds);
739     if (errCode != ERR_OK) {
740         return RetErrMsg(InitErrMsg(env, errCode, callbackType, argv[ARGS_SIZE_TWO]));
741     }
742 
743     napi_valuetype valueType = napi_undefined;
744     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
745     if (valueType != napi_boolean) {
746         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_INVALID_PARAM, callbackType, argv[ARGS_SIZE_TWO]));
747     }
748 
749     auto *asyncCallbackInfo = new (std::nothrow) AsyncNotifyFormsVisibleCallbackInfo {
750         .env = env,
751         .asyncWork = nullptr,
752         .deferred = nullptr,
753         .callback = nullptr,
754         .formIds = formIds,
755         .isVisible = false,
756     };
757     if (asyncCallbackInfo == nullptr) {
758         HILOG_ERROR("asyncCallbackInfo == nullptr.");
759         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_COMMON_CODE, callbackType, argv[1]));
760     }
761     std::unique_ptr<AsyncNotifyFormsVisibleCallbackInfo> callbackPtr {asyncCallbackInfo};
762 
763     napi_get_value_bool(env, argv[1], &asyncCallbackInfo->isVisible);
764 
765     napi_value result;
766     if (argc == ARGS_SIZE_THREE) {
767         // Check the value type of the arguments
768         valueType = napi_undefined;
769         NAPI_CALL(env, napi_typeof(env, argv[ARGS_SIZE_TWO], &valueType));
770         NAPI_ASSERT(env, valueType == napi_function, "The type of arg 2 is incorrect, expected type is function.");
771         napi_create_reference(env, argv[ARGS_SIZE_TWO], REF_COUNT, &asyncCallbackInfo->callback);
772         result = NotifyFormsVisibleCallback(env, asyncCallbackInfo);
773     } else {
774         result = NotifyFormsVisiblePromise(env, asyncCallbackInfo);
775     }
776 
777     callbackPtr.release();
778     return result;
779 }
780 
InnerNotifyFormsEnableUpdate(napi_env env,AsyncNotifyFormsEnableUpdateCallbackInfo * const asyncCallbackInfo)781 static void InnerNotifyFormsEnableUpdate(napi_env env,
782                                          AsyncNotifyFormsEnableUpdateCallbackInfo *const asyncCallbackInfo)
783 {
784     HILOG_DEBUG("%{public}s called.", __func__);
785 
786     asyncCallbackInfo->result = FormMgr::GetInstance().NotifyFormsEnableUpdate(asyncCallbackInfo->formIds,
787         asyncCallbackInfo->isEnableUpdate, FormHostClient::GetInstance());
788     HILOG_DEBUG("%{public}s, end", __func__);
789 }
790 
NotifyFormsEnableUpdateCallback(napi_env env,AsyncNotifyFormsEnableUpdateCallbackInfo * const asyncCallbackInfo)791 napi_value NotifyFormsEnableUpdateCallback(napi_env env,
792                                            AsyncNotifyFormsEnableUpdateCallbackInfo *const asyncCallbackInfo)
793 {
794     HILOG_INFO("enter");
795     napi_value resourceName;
796     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
797     napi_create_async_work(
798         env,
799         nullptr,
800         resourceName,
801         [](napi_env env, void *data) {
802             HILOG_INFO("running");
803             auto *asyncCallbackInfo = (AsyncNotifyFormsEnableUpdateCallbackInfo *) data;
804             InnerNotifyFormsEnableUpdate(env, asyncCallbackInfo);
805         },
806         [](napi_env env, napi_status status, void *data) {
807             HILOG_INFO("complete");
808             auto *asyncCallbackInfo = (AsyncNotifyFormsEnableUpdateCallbackInfo *) data;
809 
810             if (asyncCallbackInfo->callback != nullptr) {
811                 napi_value callback;
812                 napi_value callbackValues[ARGS_SIZE_TWO] = {nullptr, nullptr};
813                 InnerCreateCallbackRetMsg(env, asyncCallbackInfo->result, callbackValues);
814 
815                 napi_get_reference_value(env, asyncCallbackInfo->callback, &callback);
816                 napi_value callResult;
817                 napi_call_function(env, nullptr, callback, ARGS_SIZE_TWO, callbackValues, &callResult);
818                 napi_delete_reference(env, asyncCallbackInfo->callback);
819             }
820             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
821             delete asyncCallbackInfo;
822         },
823         (void *) asyncCallbackInfo,
824         &asyncCallbackInfo->asyncWork);
825     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default));
826     return NapiGetResult(env, 1);
827 }
828 
NotifyFormsEnableUpdatePromise(napi_env env,AsyncNotifyFormsEnableUpdateCallbackInfo * const asyncCallbackInfo)829 napi_value NotifyFormsEnableUpdatePromise(napi_env env,
830                                           AsyncNotifyFormsEnableUpdateCallbackInfo *const asyncCallbackInfo)
831 {
832     HILOG_INFO("enter");
833     napi_deferred deferred;
834     napi_value promise;
835     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
836     asyncCallbackInfo->deferred = deferred;
837 
838     napi_value resourceName;
839     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
840     napi_create_async_work(
841         env,
842         nullptr,
843         resourceName,
844         [](napi_env env, void *data) {
845             HILOG_INFO("runnning");
846             auto *asyncCallbackInfo = (AsyncNotifyFormsEnableUpdateCallbackInfo *) data;
847             InnerNotifyFormsEnableUpdate(env, asyncCallbackInfo);
848         },
849         [](napi_env env, napi_status status, void *data) {
850             HILOG_INFO("complete");
851             auto *asyncCallbackInfo = (AsyncNotifyFormsEnableUpdateCallbackInfo *) data;
852             napi_value result;
853             InnerCreatePromiseRetMsg(env, asyncCallbackInfo->result, &result);
854             if (asyncCallbackInfo->result == ERR_OK) {
855                 napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
856             } else {
857                 napi_reject_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
858             }
859             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
860             delete asyncCallbackInfo;
861         },
862         (void *) asyncCallbackInfo,
863         &asyncCallbackInfo->asyncWork);
864     napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default);
865     return promise;
866 }
867 
868 /**
869  * @brief  The implementation of Node-API interface: notifyFormsEnableUpdate
870  *
871  * @param[in] env The environment that the Node-API call is invoked under
872  * @param[out] info An opaque datatype that is passed to a callback function
873  *
874  * @return This is an opaque pointer that is used to represent a JavaScript value
875  */
NAPI_NotifyFormsEnableUpdate(napi_env env,napi_callback_info info)876 napi_value NAPI_NotifyFormsEnableUpdate(napi_env env, napi_callback_info info)
877 {
878     HILOG_INFO("call");
879 
880     // Check the number of the arguments
881     size_t argc = ARGS_SIZE_THREE;
882     napi_value argv[ARGS_SIZE_THREE] = {nullptr, nullptr, nullptr};
883     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
884     if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) {
885         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
886         return nullptr;
887     }
888 
889     int32_t callbackType = (argc == ARGS_SIZE_THREE) ? CALLBACK_FLG : PROMISE_FLG;
890 
891     ErrCode errCode;
892     std::vector<int64_t> formIds {};
893     GetFormIds(env, argv[0], errCode, formIds);
894     if (errCode != ERR_OK) {
895         return RetErrMsg(InitErrMsg(env, errCode, callbackType, argv[ARGS_SIZE_TWO]));
896     }
897 
898     napi_valuetype valueType = napi_undefined;
899     NAPI_CALL(env, napi_typeof(env, argv[1], &valueType));
900     if (valueType != napi_boolean) {
901         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_INVALID_PARAM, callbackType, argv[ARGS_SIZE_TWO]));
902     }
903 
904     auto *asyncCallbackInfo = new (std::nothrow) AsyncNotifyFormsEnableUpdateCallbackInfo {
905         .env = env,
906         .asyncWork = nullptr,
907         .deferred = nullptr,
908         .callback = nullptr,
909         .formIds = formIds,
910         .isEnableUpdate = false,
911     };
912     if (asyncCallbackInfo == nullptr) {
913         HILOG_ERROR("asyncCallbackInfo == nullptr.");
914         return RetErrMsg(InitErrMsg(env, ERR_APPEXECFWK_FORM_COMMON_CODE, callbackType, argv[1]));
915     }
916     std::unique_ptr<AsyncNotifyFormsEnableUpdateCallbackInfo> callbackPtr {asyncCallbackInfo};
917 
918     napi_get_value_bool(env, argv[1], &asyncCallbackInfo->isEnableUpdate);
919 
920     napi_value result;
921     if (argc == ARGS_SIZE_THREE) {
922         // Check the value type of the arguments
923         valueType = napi_undefined;
924         NAPI_CALL(env, napi_typeof(env, argv[ARGS_SIZE_TWO], &valueType));
925         NAPI_ASSERT(env, valueType == napi_function, "The type of arg 2 is incorrect, expected type is function.");
926         napi_create_reference(env, argv[ARGS_SIZE_TWO], REF_COUNT, &asyncCallbackInfo->callback);
927         result = NotifyFormsEnableUpdateCallback(env, asyncCallbackInfo);
928     } else {
929         result = NotifyFormsEnableUpdatePromise(env, asyncCallbackInfo);
930     }
931     callbackPtr.release();
932     return result;
933 }
934 
SystemTimeMillis()935 int64_t SystemTimeMillis() noexcept
936 {
937     struct timespec t;
938     t.tv_sec = 0;
939     t.tv_nsec = 0;
940     clock_gettime(CLOCK_MONOTONIC, &t);
941     return static_cast<int64_t>(((t.tv_sec) * NANOSECONDS + t.tv_nsec) / MICROSECONDS);
942 }
943 
944 class ShareFormCallBackClient : public ShareFormCallBack,
945                                 public std::enable_shared_from_this<ShareFormCallBackClient> {
946 public:
ShareFormCallBackClient(ShareFormTask && task)947     explicit ShareFormCallBackClient(ShareFormTask &&task) : task_(std::move(task))
948     {
949         handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
950     }
951 
952     virtual ~ShareFormCallBackClient() = default;
953 
ProcessShareFormResponse(int32_t result)954     void ProcessShareFormResponse(int32_t result) override
955     {
956         if (handler_) {
957             handler_->PostSyncTask([client = shared_from_this(), result] () {
958                 client->task_(result);
959             });
960         }
961     }
962 
963 private:
964     ShareFormTask task_;
965     std::shared_ptr<AppExecFwk::EventHandler> handler_;
966 };
967 
Finalizer(napi_env env,void * data,void * hint)968 void NapiFormHost::Finalizer(napi_env env, void *data, void *hint)
969 {
970     HILOG_DEBUG("NapiFormHost::Finalizer is called");
971     std::unique_ptr<NapiFormHost>(static_cast<NapiFormHost*>(data));
972 }
973 
ShareForm(napi_env env,napi_callback_info info)974 napi_value NapiFormHost::ShareForm(napi_env env, napi_callback_info info)
975 {
976     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnShareForm);
977 }
978 
DisableFormsUpdate(napi_env env,napi_callback_info info)979 napi_value NapiFormHost::DisableFormsUpdate(napi_env env, napi_callback_info info)
980 {
981     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnDisableFormsUpdate);
982 }
983 
IsSystemReady(napi_env env,napi_callback_info info)984 napi_value NapiFormHost::IsSystemReady(napi_env env, napi_callback_info info)
985 {
986     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnIsSystemReady);
987 }
988 
GetAllFormsInfo(napi_env env,napi_callback_info info)989 napi_value NapiFormHost::GetAllFormsInfo(napi_env env, napi_callback_info info)
990 {
991     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnGetAllFormsInfo);
992 }
993 
GetFormsInfo(napi_env env,napi_callback_info info)994 napi_value NapiFormHost::GetFormsInfo(napi_env env, napi_callback_info info)
995 {
996     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnGetFormsInfo);
997 }
998 
DeleteForm(napi_env env,napi_callback_info info)999 napi_value NapiFormHost::DeleteForm(napi_env env, napi_callback_info info)
1000 {
1001     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnDeleteForm);
1002 }
1003 
ReleaseForm(napi_env env,napi_callback_info info)1004 napi_value NapiFormHost::ReleaseForm(napi_env env, napi_callback_info info)
1005 {
1006     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnReleaseForm);
1007 }
1008 
RequestForm(napi_env env,napi_callback_info info)1009 napi_value NapiFormHost::RequestForm(napi_env env, napi_callback_info info)
1010 {
1011     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnRequestForm);
1012 }
1013 
CastTempForm(napi_env env,napi_callback_info info)1014 napi_value NapiFormHost::CastTempForm(napi_env env, napi_callback_info info)
1015 {
1016     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnCastTempForm);
1017 }
1018 
EnableFormsUpdate(napi_env env,napi_callback_info info)1019 napi_value NapiFormHost::EnableFormsUpdate(napi_env env, napi_callback_info info)
1020 {
1021     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnEnableFormsUpdate);
1022 }
1023 
DeleteInvalidForms(napi_env env,napi_callback_info info)1024 napi_value NapiFormHost::DeleteInvalidForms(napi_env env, napi_callback_info info)
1025 {
1026     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnDeleteInvalidForms);
1027 }
1028 
NotifyVisibleForms(napi_env env,napi_callback_info info)1029 napi_value NapiFormHost::NotifyVisibleForms(napi_env env, napi_callback_info info)
1030 {
1031     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnNotifyVisibleForms);
1032 }
1033 
NotifyInVisibleForms(napi_env env,napi_callback_info info)1034 napi_value NapiFormHost::NotifyInVisibleForms(napi_env env, napi_callback_info info)
1035 {
1036     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnNotifyInVisibleForms);
1037 }
1038 
OnShareForm(napi_env env,size_t argc,napi_value * argv)1039 napi_value NapiFormHost::OnShareForm(napi_env env, size_t argc, napi_value* argv)
1040 {
1041     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1042     int32_t errCode = ERR_OK;
1043     if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) {
1044         HILOG_ERROR("wrong number of arguments.");
1045         errCode = ERR_ADD_INVALID_PARAM;
1046     }
1047 
1048     std::string strFormId =
1049         GetStringFromNAPI(env, argv[0]);
1050     std::string remoteDeviceId =
1051         GetStringFromNAPI(env, argv[1]);
1052     // The promise form has only two parameters
1053     decltype(argc) unwrapArgc = 2;
1054 
1055     int64_t formId = 0;
1056     if (!ConvertStringToInt64(strFormId, formId)) {
1057         HILOG_ERROR("convert string formId to int64 failed.");
1058         errCode = ERR_COMMON;
1059     }
1060     if (formId == 0 || remoteDeviceId.empty()) {
1061         errCode = ERR_COMMON;
1062     }
1063 
1064     napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
1065     napi_value result = nullptr;
1066 
1067     std::unique_ptr<AbilityRuntime::NapiAsyncTask> uasyncTask =
1068         AbilityRuntime::CreateAsyncTaskWithLastParam(env, lastParam, nullptr, nullptr, &result);
1069     std::shared_ptr<AbilityRuntime::NapiAsyncTask> asyncTask = std::move(uasyncTask);
1070 
1071     ShareFormTask task = [env, asyncTask](int32_t code) {
1072         HILOG_DEBUG("task complete code: %{public}d", code);
1073         if (code == ERR_OK) {
1074             asyncTask->Resolve(env, CreateJsUndefined(env));
1075         } else {
1076             auto retCode = QueryRetCode(code);
1077             auto retMsg = QueryRetMsg(retCode);
1078             asyncTask->Reject(env, AbilityRuntime::CreateJsError(env, retCode, retMsg));
1079         }
1080     };
1081 
1082     if (errCode != ERR_OK) {
1083         asyncTask->Reject(env, AbilityRuntime::CreateJsError(env, errCode, "Invalidate params."));
1084     } else {
1085         InnerShareForm(env, asyncTask, std::move(task), formId, remoteDeviceId);
1086     }
1087 
1088     return result;
1089 }
1090 
OnDisableFormsUpdate(napi_env env,size_t argc,napi_value * argv)1091 napi_value NapiFormHost::OnDisableFormsUpdate(napi_env env, size_t argc, napi_value* argv)
1092 {
1093     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1094     int32_t errCode = ERR_OK;
1095     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1096         HILOG_ERROR("wrong number of arguments!");
1097         return CreateJsUndefined(env);
1098     }
1099 
1100     std::vector<string> strFormIdList;
1101     if (!GetStringsValue(env, argv[PARAM0], strFormIdList)) {
1102         HILOG_ERROR("conversion string failed!");
1103         errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1104     }
1105     if (strFormIdList.empty()) {
1106         HILOG_ERROR("formId list is empty!");
1107         errCode = ERR_APPEXECFWK_FORM_FORM_ID_ARRAY_ERR;
1108     }
1109     std::vector<int64_t> iFormIds;
1110     for (size_t i = 0; i < strFormIdList.size(); i++) {
1111         int64_t formIdValue;
1112         if (!ConvertStringToInt64(strFormIdList[i], formIdValue)) {
1113             HILOG_ERROR("conversion int failed!");
1114             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1115         } else {
1116             iFormIds.push_back(formIdValue);
1117         }
1118     }
1119 
1120     auto complete = [formIds = iFormIds, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1121         if (errCode != ERR_OK) {
1122             auto code = QueryRetCode(errCode);
1123             task.Reject(env, CreateJsError(env, code, QueryRetMsg(code)));
1124             return;
1125         }
1126         auto ret = FormMgr::GetInstance().LifecycleUpdate(formIds, FormHostClient::GetInstance(), false);
1127         if (ret != ERR_OK) {
1128             auto retCode = QueryRetCode(ret);
1129             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1130             return;
1131         }
1132         task.Resolve(env, CreateJsValue(env, ret));
1133     };
1134 
1135     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1136     napi_value result = nullptr;
1137     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnDisableFormsUpdate",
1138         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1139     return result;
1140 }
1141 
OnIsSystemReady(napi_env env,size_t argc,napi_value * argv)1142 napi_value NapiFormHost::OnIsSystemReady(napi_env env, size_t argc, napi_value* argv)
1143 {
1144     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1145     if (argc > ARGS_ONE || argc < ARGS_ZERO) {
1146         HILOG_ERROR("wrong number of arguments.");
1147         return CreateJsUndefined(env);
1148     }
1149 
1150     auto complete = [](napi_env env, NapiAsyncTask &task, int32_t status) {
1151         // Use original logic.
1152         // Use the error code to return whether the function executed successfully.
1153         auto ret = FormMgr::GetInstance().CheckFMSReady() ? 0 : 1;
1154         if (ret == ERR_OK) {
1155             task.Resolve(env, CreateJsUndefined(env));
1156         } else {
1157             auto retCode = QueryRetCode(ret);
1158             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1159         }
1160     };
1161 
1162     auto callback = (argc == ARGS_ZERO) ? nullptr : argv[PARAM0];
1163     napi_value result = nullptr;
1164     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnIsSystemReady",
1165         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1166     return result;
1167 }
1168 
OnGetAllFormsInfo(napi_env env,size_t argc,napi_value * argv)1169 napi_value NapiFormHost::OnGetAllFormsInfo(napi_env env, size_t argc, napi_value* argv)
1170 {
1171     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1172     if (argc > ARGS_ONE || argc < ARGS_ZERO) {
1173         HILOG_ERROR("wrong number of arguments!");
1174         return CreateJsUndefined(env);
1175     }
1176 
1177     auto complete = [](napi_env env, NapiAsyncTask &task, int32_t status) {
1178         std::vector<FormInfo> formInfos;
1179         auto ret = FormMgr::GetInstance().GetAllFormsInfo(formInfos);
1180         if (ret != ERR_OK) {
1181             auto retCode = QueryRetCode(ret);
1182             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1183             return;
1184         }
1185         task.Resolve(env, CreateFormInfos(env, formInfos));
1186     };
1187 
1188     auto callback = (argc == ARGS_ZERO) ? nullptr : argv[PARAM0];
1189     napi_value result = nullptr;
1190     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnGetAllFormsInfo",
1191         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1192     return result;
1193 }
1194 
OnGetFormsInfo(napi_env env,size_t argc,napi_value * argv)1195 napi_value NapiFormHost::OnGetFormsInfo(napi_env env, size_t argc, napi_value* argv)
1196 {
1197     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1198     int32_t errCode = ERR_OK;
1199     if (argc > ARGS_THREE || argc < ARGS_ONE) {
1200         HILOG_ERROR("wrong number of arguments!");
1201         return CreateJsUndefined(env);
1202     }
1203 
1204     std::string bName("");
1205     if (!ConvertFromJsValue(env, argv[PARAM0], bName)) {
1206         HILOG_ERROR("conversion failed!");
1207         errCode = ERR_APPEXECFWK_FORM_INVALID_BUNDLENAME;
1208     }
1209 
1210     std::string mName("");
1211     bool bParam = false;
1212     bool flagCall = UnwrapGetFormsInfoParams(env, argc, argv, mName, bParam);
1213     auto complete = [bName, mName, bParam, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1214         std::string bundleName(bName);
1215         std::string moduleName(mName);
1216         std::vector<FormInfo> formInfos;
1217         if (errCode != ERR_OK) {
1218             auto retCode = QueryRetCode(errCode);
1219             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1220             return;
1221         }
1222         int ret = ERR_OK;
1223         if (!bParam) {
1224             ret = FormMgr::GetInstance().GetFormsInfoByApp(bundleName, formInfos);
1225         } else {
1226             ret = FormMgr::GetInstance().GetFormsInfoByModule(bundleName, moduleName, formInfos);
1227         }
1228 
1229         if (ret != ERR_OK) {
1230             auto retCode = QueryRetCode(ret);
1231             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1232             return;
1233         }
1234         task.Resolve(env, CreateFormInfos(env, formInfos));
1235     };
1236 
1237     napi_value result = nullptr;
1238     auto callback = flagCall ? ((argc == ARGS_TWO) ? argv[PARAM1] : argv[PARAM2]) : nullptr;
1239     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnGetFormsInfo",
1240         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1241     return result;
1242 }
1243 
OnDeleteForm(napi_env env,size_t argc,napi_value * argv)1244 napi_value NapiFormHost::OnDeleteForm(napi_env env, size_t argc, napi_value* argv)
1245 {
1246     HILOG_DEBUG("%{public}s called.", __func__);
1247 
1248     int32_t errCode = ERR_OK;
1249     int64_t formId = 0;
1250     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1251         HILOG_ERROR("OnDeleteForm wrong number of arguments.");
1252         return CreateJsUndefined(env);
1253     }
1254     if (!IsTypeForNapiValue(env, argv[PARAM0], napi_string)) {
1255         HILOG_ERROR("input arguments is not string!");
1256         errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
1257     } else {
1258         std::string strFormId;
1259         if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
1260             HILOG_ERROR("conversion failed!");
1261             return CreateJsUndefined(env);
1262         }
1263         if (!ConvertStringToInt64(strFormId, formId)) {
1264             HILOG_ERROR("OnDeleteForm convert string formId to int64 failed.");
1265             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1266         }
1267     }
1268     NapiAsyncTask::CompleteCallback complete = [formId, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1269         if (errCode != ERR_OK) {
1270             auto retCode = QueryRetCode(errCode);
1271             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1272             return;
1273         }
1274         auto ret = FormMgr::GetInstance().DeleteForm(formId, FormHostClient::GetInstance());
1275         if (ret == ERR_OK) {
1276             auto result = QueryRetCode(ret);
1277             task.Resolve(env, CreateJsValue(env, result));
1278         } else {
1279             auto retCode = QueryRetCode(ret);
1280             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1281         }
1282     };
1283 
1284     napi_value lastParam = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1285     napi_value result = nullptr;
1286     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnDeleteForm",
1287         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1288     return result;
1289 }
1290 
OnReleaseForm(napi_env env,size_t argc,napi_value * argv)1291 napi_value NapiFormHost::OnReleaseForm(napi_env env,
1292     size_t argc, napi_value* argv)
1293 {
1294     HILOG_DEBUG("%{public}s called.", __func__);
1295 
1296     int32_t errCode = ERR_OK;
1297     int64_t formId = 0;
1298     bool isReleaseCache = false;
1299     if (argc > ARGS_THREE || argc < ARGS_ONE) {
1300         HILOG_ERROR("OnReleaseForm wrong number of arguments.");
1301         return CreateJsUndefined(env);
1302     }
1303     if (!IsTypeForNapiValue(env, argv[PARAM0], napi_string)) {
1304         HILOG_ERROR("input params is not string!");
1305         errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
1306     } else {
1307         std::string strFormId;
1308         if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
1309             HILOG_ERROR("conversion error!");
1310             return CreateJsUndefined(env);
1311         }
1312         if (!ConvertStringToInt64(strFormId, formId)) {
1313             HILOG_ERROR("OnReleaseForm convert string formId to int64 failed.");
1314             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1315         } else if ((argc == ARGS_TWO || argc == ARGS_THREE) &&
1316             !IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
1317             if (IsTypeForNapiValue(env, argv[PARAM1], napi_boolean)) {
1318                 if (!ConvertFromJsValue(env, argv[PARAM1], isReleaseCache)) {
1319                     HILOG_ERROR("conversion bool failed!");
1320                     return CreateJsUndefined(env);
1321                 }
1322             } else {
1323                 HILOG_ERROR("promise second param type is illegal");
1324                 errCode = ERR_APPEXECFWK_FORM_RELEASE_FLG_ERR;
1325             }
1326         }
1327     }
1328 
1329     NapiAsyncTask::CompleteCallback complete = [formId, errCode, isReleaseCache]
1330         (napi_env env, NapiAsyncTask &task, int32_t status) {
1331             auto ret = ERR_COMMON;
1332             if (errCode != ERR_OK) {
1333                 auto retCode = QueryRetCode(errCode);
1334                 task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1335                 return ;
1336             }
1337             ret = FormMgr::GetInstance().ReleaseForm(formId, FormHostClient::GetInstance(), isReleaseCache);
1338             if (ret == ERR_OK) {
1339                 auto result = QueryRetCode(ret);
1340                 task.Resolve(env, CreateJsValue(env, result));
1341             } else {
1342                 auto retCode = QueryRetCode(ret);
1343                 task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1344                 return;
1345             }
1346     };
1347 
1348     napi_value lastParam = (argc == ARGS_ONE) ? nullptr :
1349         (argc == ARGS_TWO && !IsTypeForNapiValue(env, argv[PARAM1], napi_function)) ? nullptr :
1350         (argc == ARGS_THREE) ? argv[PARAM2] : argv[PARAM1];
1351     napi_value result = nullptr;
1352     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnReleaseForm",
1353         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1354     return result;
1355 }
1356 
OnRequestForm(napi_env env,size_t argc,napi_value * argv)1357 napi_value NapiFormHost::OnRequestForm(napi_env env, size_t argc, napi_value* argv)
1358 {
1359     HILOG_DEBUG("%{public}s called.", __func__);
1360 
1361     int32_t errCode = ERR_OK;
1362     int64_t formId = 0;
1363     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1364         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
1365         return CreateJsUndefined(env);
1366     }
1367     if (!IsTypeForNapiValue(env, argv[PARAM0], napi_string)) {
1368         HILOG_ERROR("input params is not string!");
1369         errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
1370     } else {
1371         std::string strFormId;
1372         if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
1373             HILOG_ERROR("transform failed!");
1374             return CreateJsUndefined(env);
1375         }
1376         if (!ConvertStringToInt64(strFormId, formId)) {
1377             HILOG_ERROR("%{public}s, convert string formId to int64 failed.", __func__);
1378             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1379         }
1380     }
1381     NapiAsyncTask::CompleteCallback complete = [formId, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1382         if (errCode != ERR_OK) {
1383             auto retCode = QueryRetCode(errCode);
1384             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1385             return;
1386         }
1387         Want want;
1388         auto ret = FormMgr::GetInstance().RequestForm(formId, FormHostClient::GetInstance(), want);
1389         if (ret == ERR_OK) {
1390             auto result = QueryRetCode(ret);
1391             task.Resolve(env, CreateJsValue(env, result));
1392         } else {
1393             auto retCode = QueryRetCode(ret);
1394             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1395         }
1396     };
1397 
1398     napi_value lastParam = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1399     napi_value result = nullptr;
1400     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnRequestForm",
1401         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1402     return result;
1403 }
1404 
OnCastTempForm(napi_env env,size_t argc,napi_value * argv)1405 napi_value NapiFormHost::OnCastTempForm(napi_env env, size_t argc, napi_value* argv)
1406 {
1407     HILOG_DEBUG("%{public}s called.", __func__);
1408 
1409     int32_t errCode = ERR_OK;
1410     int64_t formId = 0;
1411     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1412         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
1413         return CreateJsUndefined(env);
1414     }
1415     if (!IsTypeForNapiValue(env, argv[PARAM0], napi_string)) {
1416         HILOG_ERROR("input arguments is not string!");
1417         errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
1418     } else {
1419         std::string strFormId;
1420         if (!ConvertFromJsValue(env, argv[PARAM0], strFormId)) {
1421             HILOG_ERROR("transform failed!");
1422             return CreateJsUndefined(env);
1423         }
1424         if (!ConvertStringToInt64(strFormId, formId)) {
1425             HILOG_ERROR("%{public}s, convert string formId to int64 failed.", __func__);
1426             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1427         }
1428     }
1429     NapiAsyncTask::CompleteCallback complete = [formId, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1430         if (errCode != ERR_OK) {
1431             auto retCode = QueryRetCode(errCode);
1432             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1433             return;
1434         }
1435         auto ret = FormMgr::GetInstance().CastTempForm(formId, FormHostClient::GetInstance());
1436         if (ret == ERR_OK) {
1437             auto result = QueryRetCode(ret);
1438             task.Resolve(env, CreateJsValue(env, result));
1439         } else {
1440             auto retCode = QueryRetCode(ret);
1441             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1442         }
1443     };
1444 
1445     napi_value lastParam = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1446     napi_value result = nullptr;
1447     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnCastTempForm",
1448         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1449     return result;
1450 }
1451 
OnEnableFormsUpdate(napi_env env,size_t argc,napi_value * argv)1452 napi_value NapiFormHost::OnEnableFormsUpdate(napi_env env, size_t argc, napi_value* argv)
1453 {
1454     HILOG_DEBUG("%{public}s is called", __FUNCTION__);
1455 
1456     int32_t errCode = ERR_OK;
1457     std::vector<int64_t> iFormIds;
1458     if (argc > ARGS_TWO|| argc < ARGS_ONE) {
1459         HILOG_ERROR("wrong number of arguments!");
1460         return CreateJsUndefined(env);
1461     }
1462     std::vector<string> strFormIdList;
1463     if (!GetStringsValue(env, argv[PARAM0], strFormIdList)) {
1464         HILOG_ERROR("conversion string failed!");
1465         errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1466     }
1467     for (size_t i = 0; i < strFormIdList.size(); i++) {
1468         int64_t formIdValue;
1469         if (!ConvertStringToInt64(strFormIdList[i], formIdValue)) {
1470             HILOG_ERROR("conversion int failed!");
1471             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1472         } else {
1473             iFormIds.push_back(formIdValue);
1474         }
1475     }
1476     auto complete = [iFormIds, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1477         if (errCode != ERR_OK) {
1478             auto code = QueryRetCode(errCode);
1479             task.Reject(env, CreateJsError(env, code, QueryRetMsg(code)));
1480             return;
1481         }
1482         auto ret = FormMgr::GetInstance().LifecycleUpdate(iFormIds, FormHostClient::GetInstance(), true);
1483         if (ret == ERR_OK) {
1484             auto result = QueryRetCode(ret);
1485             task.Resolve(env, CreateJsValue(env, result));
1486         } else {
1487             auto retCode = QueryRetCode(ret);
1488             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1489         }
1490     };
1491 
1492     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1493     napi_value result = nullptr;
1494     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnEnableFormsUpdate",
1495         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1496     return result;
1497 }
1498 
GetStringsValue(napi_env env,napi_value array,std::vector<std::string> & strList)1499 bool NapiFormHost::GetStringsValue(napi_env env, napi_value array, std::vector<std::string> &strList)
1500 {
1501     uint32_t nativeArrayLen = 0;
1502     napi_get_array_length(env, array, &nativeArrayLen);
1503     napi_value element = nullptr;
1504 
1505     for (uint32_t i = 0; i < nativeArrayLen; i++) {
1506         std::string itemStr("");
1507         napi_get_element(env, array, i, &element);
1508         if (!ConvertFromJsValue(env, element, itemStr)) {
1509             HILOG_ERROR("GetElement from to array [%{public}u] error", i);
1510             return false;
1511         }
1512         strList.push_back(itemStr);
1513     }
1514 
1515     return true;
1516 }
1517 
UnwrapGetFormsInfoParams(napi_env env,size_t argc,napi_value * argv,std::string & moduleName,bool & bParam)1518 bool NapiFormHost::UnwrapGetFormsInfoParams(
1519     napi_env env, size_t argc, napi_value* argv, std::string &moduleName, bool &bParam)
1520 {
1521     bool flagCall = true;
1522     if (argc == ARGS_ONE) {
1523         flagCall = false;
1524         bParam = false;
1525     } else if (argc == ARGS_TWO && !IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
1526         if (!ConvertFromJsValue(env, argv[PARAM1], moduleName)) {
1527             HILOG_WARN("input params string error");
1528         }
1529         flagCall = false;
1530         bParam = true;
1531     } else if (argc == ARGS_TWO && IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
1532         bParam = false;
1533     } else if (argc == ARGS_THREE) {
1534         if (!ConvertFromJsValue(env, argv[PARAM1], moduleName)) {
1535             HILOG_WARN("input params string error");
1536         }
1537         bParam = true;
1538     }
1539 
1540     return flagCall;
1541 }
1542 
InnerShareForm(napi_env env,const std::shared_ptr<AbilityRuntime::NapiAsyncTask> & asyncTask,ShareFormTask && task,int64_t formId,const std::string & remoteDeviceId)1543 void NapiFormHost::InnerShareForm(
1544     napi_env env,
1545     const std::shared_ptr<AbilityRuntime::NapiAsyncTask> &asyncTask,
1546     ShareFormTask &&task,
1547     int64_t formId,
1548     const std::string &remoteDeviceId)
1549 {
1550     auto shareFormCallback = std::make_shared<ShareFormCallBackClient>(std::move(task));
1551     int64_t requestCode = SystemTimeMillis();
1552     FormHostClient::GetInstance()->AddShareFormCallback(shareFormCallback, requestCode);
1553 
1554     ErrCode ret = FormMgr::GetInstance().ShareForm(
1555         formId, remoteDeviceId, FormHostClient::GetInstance(), requestCode);
1556     if (ret != ERR_OK) {
1557         HILOG_INFO("share form fail");
1558         auto retCode = QueryRetCode(ret);
1559         auto retMsg = QueryRetMsg(retCode);
1560         asyncTask->Reject(env, AbilityRuntime::CreateJsError(env, retCode, retMsg));
1561         FormHostClient::GetInstance()->RemoveShareFormCallback(requestCode);
1562     }
1563 }
1564 
NotifyFormsPrivacyProtected(napi_env env,napi_callback_info info)1565 napi_value NapiFormHost::NotifyFormsPrivacyProtected(napi_env env, napi_callback_info info)
1566 {
1567     GET_CB_INFO_AND_CALL(env, info, NapiFormHost, OnNotifyFormsPrivacyProtected);
1568 }
1569 
OnNotifyFormsPrivacyProtected(napi_env env,size_t argc,napi_value * argv)1570 napi_value NapiFormHost::OnNotifyFormsPrivacyProtected(napi_env env, size_t argc, napi_value* argv)
1571 {
1572     HILOG_INFO("call");
1573     if (argc > ARGS_SIZE_THREE || argc < ARGS_SIZE_TWO) {
1574         HILOG_ERROR("%{public}s, wrong number of arguments.", __func__);
1575         return nullptr;
1576     }
1577 
1578     ErrCode errCode = ERR_OK;
1579     std::vector<int64_t> formIds {};
1580     GetFormIds(env, argv[0], errCode, formIds);
1581     if (errCode != ERR_OK) {
1582         HILOG_ERROR("get formIds faild, code is %{public}d", errCode);
1583         return nullptr;
1584     }
1585 
1586     // The promise form has only two parameters
1587     decltype(argc) unwrapArgc = 2;
1588     bool isProtected = false;
1589 
1590     if (!ConvertFromJsValue(env, argv[1], isProtected)) {
1591         HILOG_ERROR("convert from Js value failed!");
1592         return nullptr;
1593     }
1594 
1595     NapiAsyncTask::CompleteCallback complete =
1596         [formIds, isProtected, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1597             if (errCode != ERR_OK) {
1598                 HILOG_ERROR("task reject, code is %{public}d", errCode);
1599                 task.Reject(env, CreateJsError(env, errCode, QueryRetMsg(errCode)));
1600                 return;
1601             }
1602 
1603             auto ret = FormMgr::GetInstance().NotifyFormsPrivacyProtected(formIds,
1604                 isProtected, FormHostClient::GetInstance());
1605             if (ret == ERR_OK) {
1606                 task.Resolve(env, CreateJsUndefined(env));
1607             } else {
1608                 HILOG_ERROR("task reject, result code is %{public}d", ret);
1609                 auto retCode = QueryRetCode(ret);
1610                 task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1611             }
1612         };
1613 
1614     napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
1615     napi_value result = nullptr;
1616     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnNotifyFormsPrivacyProtected",
1617         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
1618     return result;
1619 }
1620 
OnDeleteInvalidFormsParseParam(napi_env env,size_t argc,napi_value * argv,int32_t & errCode,std::vector<std::string> & strFormIdList)1621 bool NapiFormHost::OnDeleteInvalidFormsParseParam(napi_env env, size_t argc, napi_value* argv,
1622     int32_t &errCode, std::vector<std::string> &strFormIdList)
1623 {
1624     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1625         HILOG_ERROR("wrong number of arguments.");
1626         return false;
1627     }
1628     if (!GetStringsValue(env, argv[PARAM0], strFormIdList)) {
1629         HILOG_ERROR("conversion string failed!");
1630         errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1631     }
1632     if (strFormIdList.empty()) {
1633         HILOG_ERROR("formId list is empty!");
1634         errCode = ERR_APPEXECFWK_FORM_FORM_ID_ARRAY_ERR;
1635     }
1636     return true;
1637 }
1638 
OnDeleteInvalidForms(napi_env env,size_t argc,napi_value * argv)1639 napi_value NapiFormHost::OnDeleteInvalidForms(napi_env env, size_t argc, napi_value* argv)
1640 {
1641     HILOG_DEBUG("called");
1642 
1643     int32_t errCode = ERR_OK;
1644     std::vector<std::string> strFormIdList;
1645     if (!OnDeleteInvalidFormsParseParam(env, argc, argv, errCode, strFormIdList)) {
1646         HILOG_ERROR("parse param failed");
1647         return CreateJsNull(env);
1648     }
1649 
1650     std::shared_ptr<OnDeleteInvalidFormsS> onDeleteInvalidForms = std::make_shared<OnDeleteInvalidFormsS>();
1651     for (size_t i = 0; i < strFormIdList.size(); i++) {
1652         int64_t formIdValue;
1653         if (!ConvertStringToInt64(strFormIdList[i], formIdValue)) {
1654             HILOG_ERROR("conversion int failed!");
1655             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1656         } else {
1657             onDeleteInvalidForms->iFormIds.push_back(formIdValue);
1658         }
1659     }
1660     auto execute = [data = onDeleteInvalidForms] {
1661         if (data == nullptr) {
1662             HILOG_ERROR("onDeleteInvalidForms is nullptr.");
1663             return;
1664         }
1665         data->result = FormMgr::GetInstance().DeleteInvalidForms(
1666             data->iFormIds, FormHostClient::GetInstance(), data->numFormsDeleted);
1667     };
1668     auto complete = [data = onDeleteInvalidForms, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1669         if (errCode != ERR_OK) {
1670             auto retCode = QueryRetCode(errCode);
1671             auto retMsg = QueryRetMsg(retCode);
1672             task.Reject(env, CreateJsError(env, retCode, retMsg));
1673             return;
1674         }
1675         auto retCode = QueryRetCode(data->result);
1676         auto retMsg = QueryRetMsg(retCode);
1677         if (data->result == ERR_OK) {
1678             task.ResolveWithCustomize(env, CreateJsError(env, retCode, retMsg),
1679             CreateJsValue(env, data->numFormsDeleted));
1680         } else {
1681             task.Reject(env, CreateJsError(env, retCode, retMsg));
1682         }
1683     };
1684 
1685     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1686     napi_value result = nullptr;
1687     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnDeleteInvalidForms",
1688         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
1689     return result;
1690 }
1691 
OnNotifyVisibleForms(napi_env env,size_t argc,napi_value * argv)1692 napi_value NapiFormHost::OnNotifyVisibleForms(napi_env env, size_t argc, napi_value* argv)
1693 {
1694     HILOG_DEBUG("called");
1695 
1696     int32_t errCode = ERR_OK;
1697     std::vector<int64_t> iFormIds;
1698     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1699         HILOG_ERROR("wrong number of arguments!");
1700         return CreateJsUndefined(env);
1701     }
1702     bool isArray = false;
1703     napi_is_array(env, argv[PARAM0], &isArray);
1704     if (!isArray) {
1705         HILOG_ERROR("input params0 is not array!");
1706         errCode = ERR_APPEXECFWK_FORM_FORM_ARRAY_ERR;
1707     } else {
1708         std::vector<string> strFormIdList;
1709         if (!GetStringsValue(env, argv[PARAM0], strFormIdList)) {
1710             HILOG_ERROR("conversion string failed!");
1711             errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1712         }
1713         for (size_t i = 0; i < strFormIdList.size(); i++) {
1714             int64_t formIdValue;
1715             if (!ConvertStringToInt64(strFormIdList[i], formIdValue)) {
1716                 HILOG_ERROR("conversion int error!");
1717                 errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1718             } else {
1719                 iFormIds.push_back(formIdValue);
1720             }
1721         }
1722     }
1723     auto complete = [iFormIds, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1724         if (errCode != ERR_OK) {
1725             auto code = QueryRetCode(errCode);
1726             task.Reject(env, CreateJsError(env, code, QueryRetMsg(code)));
1727             return;
1728         }
1729         auto ret = FormMgr::GetInstance().NotifyWhetherVisibleForms(iFormIds, FormHostClient::GetInstance(),
1730             Constants::FORM_VISIBLE);
1731         auto retCode = QueryRetCode(ret);
1732         if (ret == ERR_OK) {
1733             task.ResolveWithCustomize(env, CreateJsError(env, retCode, QueryRetMsg(retCode)), CreateJsUndefined(env));
1734         } else {
1735             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1736         }
1737     };
1738     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1739     napi_value result = nullptr;
1740     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnNotifyVisibleForms",
1741         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1742     return result;
1743 }
1744 
OnNotifyInVisibleFormsParseParam(napi_env env,size_t argc,napi_value * argv,std::vector<int64_t> & formIds)1745 int32_t NapiFormHost::OnNotifyInVisibleFormsParseParam(napi_env env, size_t argc, napi_value* argv,
1746     std::vector<int64_t> &formIds)
1747 {
1748     if (argc > ARGS_TWO || argc < ARGS_ONE) {
1749         HILOG_ERROR("wrong number of arguments. argc is %{public}zu", argc);
1750         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
1751     }
1752 
1753     bool isArray = false;
1754     int32_t errCode = ERR_OK;
1755     napi_is_array(env, argv[PARAM0], &isArray);
1756     if (!isArray) {
1757         HILOG_ERROR("input params is not array!");
1758         errCode = ERR_APPEXECFWK_FORM_FORM_ARRAY_ERR;
1759     } else {
1760         std::vector<string> strFormIdList;
1761         if (!GetStringsValue(env, argv[PARAM0], strFormIdList)) {
1762             HILOG_ERROR("conversion string failed!");
1763             errCode = ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
1764         } else {
1765             if (strFormIdList.size() == 0) {
1766                 HILOG_ERROR("input params is null!");
1767                 errCode = ERR_APPEXECFWK_FORM_FORM_ARRAY_ERR;
1768             }
1769         }
1770         for (size_t i = 0; i < strFormIdList.size(); i++) {
1771             int64_t formIdValue;
1772             if (!ConvertStringToInt64(strFormIdList[i], formIdValue)) {
1773                 HILOG_ERROR("transform  int failed!");
1774                 errCode = ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR;
1775             } else {
1776                 formIds.push_back(formIdValue);
1777             }
1778         }
1779     }
1780     return errCode;
1781 }
1782 
OnNotifyInVisibleForms(napi_env env,size_t argc,napi_value * argv)1783 napi_value NapiFormHost::OnNotifyInVisibleForms(napi_env env, size_t argc, napi_value* argv)
1784 {
1785     HILOG_DEBUG("called");
1786 
1787     int32_t errCode;
1788     std::vector<int64_t> formIds;
1789 
1790     errCode = OnNotifyInVisibleFormsParseParam(env, argc, argv, formIds);
1791     if (errCode == ERR_APPEXECFWK_FORM_INVALID_PARAM) {
1792         return CreateJsUndefined(env);
1793     }
1794 
1795     auto complete = [formIds = formIds, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
1796         if (errCode != ERR_OK) {
1797             auto code = QueryRetCode(errCode);
1798             task.Reject(env, CreateJsError(env, code, QueryRetMsg(code)));
1799             return;
1800         }
1801         auto ret = FormMgr::GetInstance().NotifyWhetherVisibleForms(formIds,
1802             FormHostClient::GetInstance(), Constants::FORM_INVISIBLE);
1803         if (ret == ERR_OK) {
1804             auto resultCode = QueryRetCode(ret);
1805             task.ResolveWithCustomize(
1806                 env, CreateJsError(env, resultCode, QueryRetMsg(resultCode)), CreateJsUndefined(env));
1807         } else {
1808             auto retCode = QueryRetCode(ret);
1809             task.Reject(env, CreateJsError(env, retCode, QueryRetMsg(retCode)));
1810         }
1811     };
1812 
1813     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1814     napi_value result = nullptr;
1815     NapiAsyncTask::ScheduleWithDefaultQos("NapiFormHost::OnNotifyInVisibleForms",
1816         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1817     return result;
1818 }
1819 }  // namespace AbilityRuntime
1820 }  // namespace OHOS
1821