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 
16 #include "napi_form_util.h"
17 
18 #include <cinttypes>
19 #include <regex>
20 #include <uv.h>
21 #include <vector>
22 
23 #include "fms_log_wrapper.h"
24 #include "form_mgr.h"
25 #include "form_mgr_errors.h"
26 #include "napi/native_api.h"
27 #include "napi/native_node_api.h"
28 #include "running_form_info.h"
29 #include "runtime.h"
30 
31 using namespace OHOS;
32 using namespace OHOS::AAFwk;
33 using namespace OHOS::AppExecFwk;
34 
35 namespace OHOS {
36 namespace AbilityRuntime {
37 namespace {
38 constexpr size_t ARGS_SIZE_TWO = 2;
39 constexpr int INT_64_LENGTH = 19;
40 constexpr int ZERO_VALUE = 0;
41 constexpr int REF_COUNT = 1;
42 constexpr int BASE_NUMBER = 9;
43 constexpr int CALLBACK_FLG = 1;
44 constexpr int64_t HEAD_BIT_NUM = 9000000000000000000;
45 const std::map<int32_t, int32_t> ERROR_CODE_MAP = {
46     { ERR_OK,                                             ERR_OK },
47     { ERR_APPEXECFWK_FORM_COMMON_CODE,                    ERR_COMMON },
48     { ERR_APPEXECFWK_FORM_PERMISSION_DENY,                ERR_PERMISSION_DENY },
49     { ERR_APPEXECFWK_FORM_PERMISSION_DENY_BUNDLE,         ERR_PERMISSION_DENY },
50     { ERR_APPEXECFWK_FORM_PERMISSION_DENY_SYS,            ERR_PERMISSION_DENY },
51     { ERR_APPEXECFWK_FORM_GET_INFO_FAILED,                ERR_GET_INFO_FAILED },
52     { ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED,              ERR_GET_BUNDLE_FAILED },
53     { ERR_APPEXECFWK_FORM_INVALID_PARAM,                  ERR_ADD_INVALID_PARAM },
54     { ERR_APPEXECFWK_FORM_INVALID_FORM_ID,                ERR_ADD_INVALID_PARAM },
55     { ERR_APPEXECFWK_FORM_FORM_ID_NUM_ERR,                ERR_ADD_INVALID_PARAM },
56     { ERR_APPEXECFWK_FORM_FORM_ARRAY_ERR,                 ERR_ADD_INVALID_PARAM },
57     { ERR_APPEXECFWK_FORM_RELEASE_FLG_ERR,                ERR_COMMON },
58     { ERR_APPEXECFWK_FORM_REFRESH_TIME_NUM_ERR,           ERR_COMMON },
59     { ERR_APPEXECFWK_FORM_INVALID_BUNDLENAME,             ERR_ADD_INVALID_PARAM },
60     { ERR_APPEXECFWK_FORM_INVALID_MODULENAME,             ERR_ADD_INVALID_PARAM },
61     { ERR_APPEXECFWK_FORM_INVALID_PROVIDER_DATA,          ERR_ADD_INVALID_PARAM },
62     { ERR_APPEXECFWK_FORM_INVALID_REFRESH_TIME,           ERR_ADD_INVALID_PARAM },
63     { ERR_APPEXECFWK_FORM_FORM_ID_ARRAY_ERR,              ERR_ADD_INVALID_PARAM },
64     { ERR_APPEXECFWK_FORM_SERVER_STATUS_ERR,              ERR_COMMON },
65     { ERR_APPEXECFWK_FORM_CFG_NOT_MATCH_ID,               ERR_CFG_NOT_MATCH_ID },
66     { ERR_APPEXECFWK_FORM_NOT_EXIST_ID,                   ERR_NOT_EXIST_ID },
67     { ERR_APPEXECFWK_FORM_PROVIDER_DATA_EMPTY,            ERR_ADD_INVALID_PARAM },
68     { ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED,           ERR_BIND_PROVIDER_FAILED },
69     { ERR_APPEXECFWK_FORM_MAX_SYSTEM_FORMS,               ERR_MAX_SYSTEM_FORMS },
70     { ERR_APPEXECFWK_FORM_EXCEED_INSTANCES_PER_FORM,      ERR_MAX_INSTANCES_PER_FORM },
71     { ERR_APPEXECFWK_FORM_OPERATION_NOT_SELF,             ERR_OPERATION_FORM_NOT_SELF },
72     { ERR_APPEXECFWK_FORM_PROVIDER_DEL_FAIL,              ERR_PROVIDER_DEL_FAIL },
73     { ERR_APPEXECFWK_FORM_MAX_FORMS_PER_CLIENT,           ERR_MAX_FORMS_PER_CLIENT },
74     { ERR_APPEXECFWK_FORM_MAX_SYSTEM_TEMP_FORMS,          ERR_MAX_SYSTEM_TEMP_FORMS },
75     { ERR_APPEXECFWK_FORM_NO_SUCH_MODULE,                 ERR_FORM_NO_SUCH_MODULE },
76     { ERR_APPEXECFWK_FORM_NO_SUCH_ABILITY,                ERR_FORM_NO_SUCH_ABILITY },
77     { ERR_APPEXECFWK_FORM_NO_SUCH_DIMENSION,              ERR_FORM_NO_SUCH_DIMENSION },
78     { ERR_APPEXECFWK_FORM_FA_NOT_INSTALLED,               ERR_FORM_FA_NOT_INSTALLED },
79     { ERR_APPEXECFWK_FORM_MAX_REQUEST,                    ERR_MAX_SYSTEM_FORMS },
80     { ERR_APPEXECFWK_FORM_MAX_REFRESH,                    ERR_MAX_SYSTEM_FORMS },
81     { ERR_APPEXECFWK_FORM_GET_BMS_FAILED,                 ERR_COMMON },
82     { ERR_APPEXECFWK_FORM_GET_HOST_FAILED,                ERR_COMMON },
83     { ERR_APPEXECFWK_FORM_GET_FMS_FAILED,                 ERR_COMMON },
84     { ERR_APPEXECFWK_FORM_SEND_FMS_MSG,                   ERR_COMMON },
85     { ERR_APPEXECFWK_FORM_FORM_DUPLICATE_ADDED,           ERR_FORM_DUPLICATE_ADDED },
86     { ERR_APPEXECFWK_FORM_IN_RECOVER,                     ERR_IN_RECOVERY },
87     { ERR_APPEXECFWK_FORM_DISTRIBUTED_SCHEDULE_FAILED,    ERR_DISTRIBUTED_SCHEDULE_FAILED },
88     { ERR_APPEXECFWK_FORM_GET_SYSMGR_FAILED,              ERR_SYSTEM_RESPONSES_FAILED }
89 };
90 const std::map<int32_t, std::string> CODE_MSG_MAP = {
91     { ERR_OK, "success" },
92     { ERR_COMMON, "internal error" },
93     { ERR_PERMISSION_DENY, "does not have permission to use forms" },
94     { ERR_GET_INFO_FAILED, "failed to obtain the configuration information" },
95     { ERR_GET_BUNDLE_FAILED, "failed to obtain the bundle information" },
96     { ERR_GET_LAYOUT_FAILED, "failed to initialize the form layout" },
97     { ERR_ADD_INVALID_PARAM, "invalid input parameter during form operation" },
98     { ERR_CFG_NOT_MATCH_ID, "the form id is different from that obtained for the first time" },
99     { ERR_NOT_EXIST_ID, "the ID of the form to be operated does not exist" },
100     { ERR_BIND_PROVIDER_FAILED, "failed to bind the Form Manager Service to the provider service" },
101     { ERR_MAX_SYSTEM_FORMS, "the total number of added forms exceeds the maximum allowed by the system" },
102     { ERR_MAX_INSTANCES_PER_FORM, "the number of form instances exceeds the maximum allowed by the system" },
103     { ERR_OPERATION_FORM_NOT_SELF, "can not be operated by the current application" },
104     { ERR_PROVIDER_DEL_FAIL, "failed to instruct the form provider to delete the form" },
105     { ERR_MAX_FORMS_PER_CLIENT, "the total number of added forms exceeds the maximum per client" },
106     { ERR_MAX_SYSTEM_TEMP_FORMS, "the total number of added temp forms exceeds the maximum in system" },
107     { ERR_FORM_NO_SUCH_MODULE, "the module can not be find in system" },
108     { ERR_FORM_NO_SUCH_ABILITY, "the ability can not be find in system" },
109     { ERR_FORM_NO_SUCH_DIMENSION, "the dimension is not exist in the form" },
110     { ERR_FORM_FA_NOT_INSTALLED, "the ability is not installed" },
111     { ERR_SYSTEM_RESPONSES_FAILED, "failed to obtain the RPC object" },
112     { ERR_FORM_DUPLICATE_ADDED, "failed to obtain the form requested by the client" },
113     { ERR_DISTRIBUTED_SCHEDULE_FAILED, "failed to distributed schedule" },
114     { ERR_IN_RECOVERY, "the form is being restored" }
115 };
116 }
117 
Throw(napi_env env,int32_t errCode,const std::string & errMessage)118 bool NapiFormUtil::Throw(napi_env env, int32_t errCode, const std::string &errMessage)
119 {
120     napi_value error = CreateJsError(env, errCode, errMessage);
121     napi_throw(env, error);
122     return true;
123 }
124 
ThrowByInternalErrorCode(napi_env env,int32_t internalErrorCode)125 bool NapiFormUtil::ThrowByInternalErrorCode(napi_env env, int32_t internalErrorCode)
126 {
127     int32_t externalErrorCode = 0;
128     std::string externalErrorMessage;
129     FormMgr::GetInstance().GetExternalError(internalErrorCode, externalErrorCode, externalErrorMessage);
130     return Throw(env, externalErrorCode, externalErrorMessage);
131 }
132 
ThrowByExternalErrorCode(napi_env env,int32_t externalErrorCode)133 bool NapiFormUtil::ThrowByExternalErrorCode(napi_env env, int32_t externalErrorCode)
134 {
135     std::string externalErrorMessage = FormMgr::GetInstance().GetErrorMsgByExternalErrorCode(externalErrorCode);
136     return Throw(env, externalErrorCode, externalErrorMessage);
137 }
138 
CreateErrorByInternalErrorCode(napi_env env,int32_t internalErrorCode)139 napi_value NapiFormUtil::CreateErrorByInternalErrorCode(napi_env env, int32_t internalErrorCode)
140 {
141     int32_t externalErrorCode = 0;
142     std::string externalErrorMessage;
143     FormMgr::GetInstance().GetExternalError(internalErrorCode, externalErrorCode, externalErrorMessage);
144     return CreateJsError(env, externalErrorCode, externalErrorMessage);
145 }
146 
CreateErrorByExternalErrorCode(napi_env env,int32_t externalErrorCode)147 napi_value NapiFormUtil::CreateErrorByExternalErrorCode(napi_env env, int32_t externalErrorCode)
148 {
149     std::string externalErrorMessage = FormMgr::GetInstance().GetErrorMsgByExternalErrorCode(externalErrorCode);
150     return CreateJsError(env, externalErrorCode, externalErrorMessage);
151 }
152 
ThrowParamTypeError(napi_env env,const std::string & paramName,const std::string & type)153 bool NapiFormUtil::ThrowParamTypeError(napi_env env, const std::string &paramName, const std::string &type)
154 {
155     return Throw(env, ERR_FORM_EXTERNAL_PARAM_INVALID, CreateParamTypeErrorMessage(paramName, type));
156 }
157 
ThrowParamNumError(napi_env env,const std::string & gotNum,const std::string & expectedNum)158 bool NapiFormUtil::ThrowParamNumError(napi_env env, const std::string &gotNum, const std::string &expectedNum)
159 {
160     std::string errorMessage = "Parameter error. Got " + gotNum + ", expected " + expectedNum;
161     return Throw(env, ERR_FORM_EXTERNAL_PARAM_INVALID, errorMessage);
162 }
163 
ThrowParamError(napi_env env,const std::string & extraMessage)164 bool NapiFormUtil::ThrowParamError(napi_env env, const std::string &extraMessage)
165 {
166     std::string errorMessage = "Parameter error. " + extraMessage;
167     return Throw(env, ERR_FORM_EXTERNAL_PARAM_INVALID, errorMessage);
168 }
169 
CreateParamTypeErrorMessage(const std::string & paramName,const std::string & type)170 std::string NapiFormUtil::CreateParamTypeErrorMessage(const std::string &paramName, const std::string &type)
171 {
172     std::string errorMessage = "Parameter error.";
173     if (paramName.empty()) {
174         // Parameter error.
175         return errorMessage;
176     }
177     errorMessage += " The type of \"" + paramName + "\"";
178     if (type.empty()) {
179         errorMessage += " is invalid.";
180         // Parameter error. The type of "paramName" is invalid.
181         return errorMessage;
182     }
183     errorMessage += " must be " + type + ".";
184     // Parameter error. The type of "${paramName}" must be ${type}.
185     return errorMessage;
186 }
187 
188 /**
189  * @brief query the error message by error code
190  *
191  * @param[in] errorCode the error code return by form JS API.
192  *
193  * @return the error detail message
194  */
QueryRetMsg(int32_t errorCode)195 std::string QueryRetMsg(int32_t errorCode)
196 {
197     auto iter = CODE_MSG_MAP.find(errorCode);
198     if (iter != CODE_MSG_MAP.end()) {
199         return iter->second;
200     } else {
201         return CODE_MSG_MAP.at(ERR_COMMON);
202     }
203 }
204 
205 /**
206  * @brief query the error code by FMS errcode
207  *
208  * @param[in] innerErrorCode the error code return by form native API.
209  *
210  * @return the error detail message
211  */
QueryRetCode(int32_t innerErrorCode)212 int32_t QueryRetCode(int32_t innerErrorCode)
213 {
214     auto iter = ERROR_CODE_MAP.find(innerErrorCode);
215     if (iter != ERROR_CODE_MAP.end()) {
216         return iter->second;
217     } else {
218         return ERR_COMMON;
219     }
220 }
221 
222 /**
223  * @brief NapiGetResult
224  *
225  * @param[in] env The environment that the Node-API call is invoked under
226  *
227  * @return napi_value
228  */
NapiGetResult(napi_env env,int iResult)229 napi_value NapiGetResult(napi_env env, int iResult)
230 {
231     napi_value result;
232     NAPI_CALL(env, napi_create_int32(env, iResult, &result));
233     return result;
234 }
235 
236 /**
237  * @brief Convert string to int64_t
238  *
239  * @param[in] strInfo The string information
240  * @param[out] int64Value Convert string to int64_t
241  *
242  * @return Return the convert result
243  */
ConvertStringToInt64(const std::string & strInfo,int64_t & int64Value)244 bool ConvertStringToInt64(const std::string &strInfo, int64_t &int64Value)
245 {
246     size_t strLength = strInfo.size();
247     if (strLength == ZERO_VALUE) {
248         int64Value = ZERO_VALUE;
249         return true;
250     }
251     std::regex pattern("^0|-?[1-9][0-9]{0,18}$"); // "^-?[0-9]{1,19}$"
252     std::smatch match;
253     if (regex_match(strInfo, match, pattern)) {
254         HILOG_DEBUG("regex_match successed");
255         if (strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1) != "-") { // maximum: 9223372036854775807
256             if (strLength < INT_64_LENGTH) {
257                 int64Value = std::stoll(strInfo);
258                 return true;
259             }
260             int maxSubValue = std::stoi(strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1));
261             if (strLength == INT_64_LENGTH && maxSubValue < BASE_NUMBER) {
262                 int64Value = std::stoll(strInfo);
263                 return true;
264             }
265             // Means 0x7FFFFFFFFFFFFFFF remove the first number:(2^63 - 1 - 9 * 10 ^ 19)
266             int64_t subValue = std::stoll(strInfo.substr(ZERO_VALUE + 1, INT_64_LENGTH - 1));
267             if (strLength == INT_64_LENGTH && subValue <= (INT64_MAX - HEAD_BIT_NUM)) {
268                 int64Value = std::stoll(strInfo);
269                 return true;
270             }
271             return false;
272         }
273         if (strLength < INT_64_LENGTH + 1) { // The minimum value: -9223372036854775808
274             int64Value = std::stoll(strInfo);
275             return true;
276         }
277         if (strLength == INT_64_LENGTH + 1) {
278             int minSubValue = std::stoi(strInfo.substr(1, 1));
279             if (minSubValue < BASE_NUMBER) {
280                 int64Value = std::stoll(strInfo);
281                 return true;
282             }
283 
284             // Means 0x8000000000000000 remove the first number:-(2^63 - 9 * 10 ^ 19)
285             int64_t subValue = std::stoll(strInfo.substr(ZERO_VALUE + 2, INT_64_LENGTH - 1));
286             if (subValue <= (INT64_MAX - HEAD_BIT_NUM + 1)) {
287                 int64Value = std::stoll(strInfo);
288                 return true;
289             }
290         }
291     }
292     HILOG_DEBUG("regex_match failed");
293     return false;
294 }
295 
296 /**
297  * @brief Create return message(callback)
298  *
299  * @param[in] env The environment that the Node-API call is invoked under
300  * @param[in] code result code
301  * @param[out] result result message
302  *
303  * @return void
304  */
InnerCreateCallbackRetMsg(napi_env env,int32_t code,napi_value (& result)[CALLBACK_RETURN_MSG_SIZE])305 void InnerCreateCallbackRetMsg(napi_env env, int32_t code, napi_value (&result)[CALLBACK_RETURN_MSG_SIZE])
306 {
307     HILOG_DEBUG("code:%{public}d", code);
308     napi_value error = nullptr;
309     napi_create_object(env, &error);
310 
311     auto retCode = QueryRetCode(code);
312     auto retMsg = QueryRetMsg(retCode);
313 
314     // create error code
315     napi_value errCode = nullptr;
316     napi_create_int32(env, retCode, &errCode);
317     napi_set_named_property(env, error, "code", errCode);
318 
319     // create error message
320     napi_value errMsg = nullptr;
321     napi_create_string_utf8(env, retMsg.c_str(), NAPI_AUTO_LENGTH, &errMsg);
322     napi_set_named_property(env, error, "message", errMsg);
323 
324     result[0] = error;
325     napi_get_undefined(env, &result[1]);
326     HILOG_DEBUG("end");
327 }
328 
329 /**
330  * @brief Create return message(promise)
331  *
332  * @param[in] env The environment that the Node-API call is invoked under
333  * @param[in] code result code
334  * @param[out] result result message
335  *
336  * @return void
337  */
InnerCreatePromiseRetMsg(napi_env env,int32_t code,napi_value * result)338 void InnerCreatePromiseRetMsg(napi_env env, int32_t code, napi_value* result)
339 {
340     HILOG_DEBUG("code:%{public}d", code);
341     if (code == ERR_OK) {
342         napi_get_undefined(env, result);
343         return;
344     }
345     napi_value errInfo = nullptr;
346     napi_create_object(env, &errInfo);
347 
348     auto retCode = QueryRetCode(code);
349     auto retMsg = QueryRetMsg(retCode);
350 
351     // create error code
352     napi_value errCode = nullptr;
353     napi_create_int32(env, retCode, &errCode);
354     napi_set_named_property(env, errInfo, "code", errCode);
355 
356     // create error message
357     napi_value errMsg = nullptr;
358     napi_create_string_utf8(env, retMsg.c_str(), NAPI_AUTO_LENGTH, &errMsg);
359     napi_set_named_property(env, errInfo, "message", errMsg);
360 
361     *result = errInfo;
362     HILOG_DEBUG("end");
363 }
364 
RetErrMsgForCallback(AsyncErrMsgCallbackInfo * asyncCallbackInfo)365 napi_value RetErrMsgForCallback(AsyncErrMsgCallbackInfo* asyncCallbackInfo)
366 {
367     HILOG_INFO("call");
368 
369     napi_env env = asyncCallbackInfo->env;
370     napi_value value = asyncCallbackInfo->callbackValue;
371 
372     // Check the value type of the arguments
373     napi_valuetype valueType = napi_undefined;
374     NAPI_CALL(env, napi_typeof(env, value, &valueType));
375     NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of deleteForm is incorrect,\
376         expected type is function.");
377 
378     napi_create_reference(env, value, REF_COUNT, &asyncCallbackInfo->callback);
379 
380     napi_value resourceName;
381     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
382     napi_create_async_work(
383         env,
384         nullptr,
385         resourceName,
386         [](napi_env env, void *data) {},
387         [](napi_env env, napi_status status, void *data) {
388             AsyncErrMsgCallbackInfo *asyncCallbackInfo = (AsyncErrMsgCallbackInfo *)data;
389             HILOG_INFO("complete");
390             if (asyncCallbackInfo->callback != nullptr) {
391                 napi_value callback;
392                 napi_value undefined;
393                 napi_value result[ARGS_SIZE_TWO] = {0};
394                 InnerCreateCallbackRetMsg(env, asyncCallbackInfo->code, result);
395                 napi_get_undefined(env, &undefined);
396                 napi_get_reference_value(env, asyncCallbackInfo->callback, &callback);
397                 napi_value callResult;
398                 napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &callResult);
399                 napi_delete_reference(env, asyncCallbackInfo->callback);
400             }
401             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
402             delete asyncCallbackInfo;
403         },
404         (void *)asyncCallbackInfo,
405         &asyncCallbackInfo->asyncWork);
406     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default));
407     return NapiGetResult(env, 1);
408 }
409 
RetErrMsgForPromise(AsyncErrMsgCallbackInfo * asyncCallbackInfo)410 napi_value RetErrMsgForPromise(AsyncErrMsgCallbackInfo* asyncCallbackInfo)
411 {
412     HILOG_INFO("call");
413 
414     napi_env env = asyncCallbackInfo->env;
415     napi_deferred deferred;
416     napi_value promise;
417     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
418     asyncCallbackInfo->deferred = deferred;
419 
420     napi_value resourceName;
421     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
422     napi_create_async_work(
423         env,
424         nullptr,
425         resourceName,
426         [](napi_env env, void *data) {},
427         [](napi_env env, napi_status status, void *data) {
428             HILOG_INFO("promise complete");
429             AsyncErrMsgCallbackInfo *asyncCallbackInfo = (AsyncErrMsgCallbackInfo *)data;
430             napi_value result;
431             InnerCreatePromiseRetMsg(env, asyncCallbackInfo->code, &result);
432             napi_reject_deferred(env, asyncCallbackInfo->deferred, result);
433             napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
434             delete asyncCallbackInfo;
435         },
436         (void *)asyncCallbackInfo,
437         &asyncCallbackInfo->asyncWork);
438     napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default);
439     return promise;
440 }
441 
442 /**
443  * @brief Send error message.
444  *
445  * @param[in] env The environment that the Node-API call is invoked under
446  * @param[in] asyncCallbackInfo Reference, callback info via Node-API
447  * @param[out] result result message
448  *
449  * @return void
450  */
RetErrMsg(AsyncErrMsgCallbackInfo * asyncCallbackInfo)451 napi_value RetErrMsg(AsyncErrMsgCallbackInfo* asyncCallbackInfo)
452 {
453     HILOG_INFO("call");
454     if (asyncCallbackInfo == nullptr) {
455         HILOG_ERROR("null asyncCallback");
456         return nullptr;
457     }
458     if (asyncCallbackInfo->type == CALLBACK_FLG) {
459         return RetErrMsgForCallback(asyncCallbackInfo);
460     }
461     return RetErrMsgForPromise(asyncCallbackInfo);
462 }
463 
InitErrMsg(napi_env env,int32_t code,int32_t type,napi_value callbackValue)464 AsyncErrMsgCallbackInfo *InitErrMsg(napi_env env, int32_t code, int32_t type, napi_value callbackValue)
465 {
466     auto *asyncErrorInfo = new (std::nothrow) AsyncErrMsgCallbackInfo {
467         .env = env,
468         .asyncWork = nullptr,
469         .deferred = nullptr,
470         .callback = nullptr,
471         .callbackValue = callbackValue,
472         .code = code,
473         .type = type
474     };
475     return asyncErrorInfo;
476 }
477 
ParseRunningFormInfoIntoNapi(napi_env env,const RunningFormInfo & runningFormInfo,napi_value & result)478 void ParseRunningFormInfoIntoNapi(napi_env env, const RunningFormInfo &runningFormInfo, napi_value &result)
479 {
480     napi_create_object(env, &result);
481 
482     napi_set_named_property(env, result, "formId", CreateJsValue(env, std::to_string(runningFormInfo.formId)));
483     napi_set_named_property(env, result, "bundleName", CreateJsValue(env, runningFormInfo.bundleName));
484     napi_set_named_property(env, result, "hostBundleName", CreateJsValue(env, runningFormInfo.hostBundleName));
485     napi_set_named_property(env, result, "visibilityType", CreateJsValue(env, (int32_t)runningFormInfo.formVisiblity));
486     napi_set_named_property(env, result, "moduleName", CreateJsValue(env, runningFormInfo.moduleName));
487     napi_set_named_property(env, result, "abilityName", CreateJsValue(env, runningFormInfo.abilityName));
488     napi_set_named_property(env, result, "bundleName", CreateJsValue(env, runningFormInfo.bundleName));
489     napi_set_named_property(env, result, "formName", CreateJsValue(env, runningFormInfo.formName));
490     napi_set_named_property(env, result, "dimension", CreateJsValue(env, runningFormInfo.dimension));
491     napi_set_named_property(env, result, "formUsageState", CreateJsValue(env, runningFormInfo.formUsageState));
492     napi_set_named_property(env, result, "formDescription", CreateJsValue(env, runningFormInfo.description));
493     napi_set_named_property(env, result, "formLocation", CreateJsValue(env, (int32_t)runningFormInfo.formLocation));
494 }
495 
GetFormType(const FormInfo & formInfo)496 inline FormType GetFormType(const FormInfo &formInfo)
497 {
498     if (formInfo.uiSyntax == FormType::ETS) {
499         return FormType::ETS;
500     }
501     return formInfo.type;
502 }
503 
CreateFormInfos(napi_env env,const std::vector<FormInfo> & formInfos)504 napi_value CreateFormInfos(napi_env env, const std::vector<FormInfo> &formInfos)
505 {
506     napi_value arrayValue = nullptr;
507     napi_create_array_with_length(env, formInfos.size(), &arrayValue);
508     uint32_t index = 0;
509     for (const auto &formInfo : formInfos) {
510         napi_set_element(env, arrayValue, index++, CreateFormInfo(env, formInfo));
511     }
512     return arrayValue;
513 }
514 
CreateFormInfo(napi_env env,const FormInfo & formInfo)515 napi_value CreateFormInfo(napi_env env, const FormInfo &formInfo)
516 {
517     HILOG_DEBUG("call");
518 
519     napi_value objContext = nullptr;
520     napi_create_object(env, &objContext);
521 
522     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, formInfo.bundleName));
523     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, formInfo.moduleName));
524     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, formInfo.abilityName));
525     napi_set_named_property(env, objContext, "name", CreateJsValue(env, formInfo.name));
526     napi_set_named_property(env, objContext, "displayName", CreateJsValue(env, formInfo.displayName));
527     napi_set_named_property(env, objContext, "displayNameId", CreateJsValue(env, formInfo.displayNameId));
528     napi_set_named_property(env, objContext, "description", CreateJsValue(env, formInfo.description));
529     napi_set_named_property(env, objContext, "descriptionId", CreateJsValue(env, formInfo.descriptionId));
530     napi_set_named_property(env, objContext, "type", CreateJsValue(env, GetFormType(formInfo)));
531     napi_set_named_property(env, objContext, "jsComponentName", CreateJsValue(env, formInfo.jsComponentName));
532     napi_set_named_property(env, objContext, "colorMode", CreateJsValue(env, formInfo.colorMode));
533     napi_set_named_property(env, objContext, "isDefault", CreateJsValue(env, formInfo.defaultFlag));
534     napi_set_named_property(env, objContext, "updateEnabled", CreateJsValue(env, formInfo.updateEnabled));
535     napi_set_named_property(env, objContext, "formVisibleNotify", CreateJsValue(env, formInfo.formVisibleNotify));
536     napi_set_named_property(env, objContext, "formConfigAbility", CreateJsValue(env, formInfo.formConfigAbility));
537     napi_set_named_property(env, objContext, "updateDuration", CreateJsValue(env, formInfo.updateDuration));
538     napi_set_named_property(env, objContext, "scheduledUpdateTime", CreateJsValue(env, formInfo.scheduledUpdateTime));
539     napi_set_named_property(env, objContext, "defaultDimension", CreateJsValue(env, formInfo.defaultDimension));
540     napi_set_named_property(env, objContext, "relatedBundleName", CreateJsValue(env, formInfo.relatedBundleName));
541     napi_set_named_property(env, objContext, "supportDimensions", CreateNativeArray(env, formInfo.supportDimensions));
542     napi_set_named_property(env, objContext, "customizeData", CreateFormCustomizeDatas(env, formInfo.customizeDatas));
543     napi_set_named_property(env, objContext, "isDynamic", CreateJsValue(env, formInfo.isDynamic));
544     napi_set_named_property(env, objContext, "transparencyEnabled", CreateJsValue(env, formInfo.transparencyEnabled));
545     napi_set_named_property(env, objContext, "fontScaleFollowSystem",
546         CreateJsValue(env, formInfo.fontScaleFollowSystem));
547     napi_set_named_property(env, objContext, "supportedShapes", CreateNativeArray(env, formInfo.supportShapes));
548 
549     return objContext;
550 }
551 
CreateRunningFormInfos(napi_env env,const std::vector<RunningFormInfo> & runningFormInfos)552 napi_value CreateRunningFormInfos(napi_env env, const std::vector<RunningFormInfo> &runningFormInfos)
553 {
554     napi_value arrayValue = nullptr;
555     napi_create_array_with_length(env, runningFormInfos.size(), &arrayValue);
556     uint32_t index = 0;
557     for (const auto &runningFormInfo : runningFormInfos) {
558         napi_set_element(env, arrayValue, index++, CreateRunningFormInfo(env, runningFormInfo));
559     }
560     return arrayValue;
561 }
562 
CreateRunningFormInfo(napi_env env,const RunningFormInfo & runningFormInfo)563 napi_value CreateRunningFormInfo(napi_env env, const RunningFormInfo &runningFormInfo)
564 {
565     HILOG_DEBUG("call");
566 
567     napi_value objContext = nullptr;
568     napi_create_object(env, &objContext);
569 
570     std::string formStr = std::to_string(runningFormInfo.formId);
571     napi_set_named_property(env, objContext, "formId", CreateJsValue(env, formStr));
572     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, runningFormInfo.bundleName));
573     napi_set_named_property(env, objContext, "hostBundleName", CreateJsValue(env, runningFormInfo.hostBundleName));
574     napi_set_named_property(env, objContext, "visibilityType", CreateJsValue(env, runningFormInfo.formVisiblity));
575     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, runningFormInfo.moduleName));
576     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, runningFormInfo.abilityName));
577     napi_set_named_property(env, objContext, "formName", CreateJsValue(env, runningFormInfo.formName));
578     napi_set_named_property(env, objContext, "dimension", CreateJsValue(env, runningFormInfo.dimension));
579     napi_set_named_property(env, objContext, "formUsageState", CreateJsValue(env, runningFormInfo.formUsageState));
580     napi_set_named_property(env, objContext, "formDescription", CreateJsValue(env, runningFormInfo.description));
581     napi_set_named_property(env, objContext, "formLocation", CreateJsValue(env, (int32_t)runningFormInfo.formLocation));
582 
583     return objContext;
584 }
585 
CreateFormCustomizeDatas(napi_env env,const std::vector<FormCustomizeData> & customizeDatas)586 napi_value CreateFormCustomizeDatas(napi_env env, const std::vector<FormCustomizeData> &customizeDatas)
587 {
588     napi_value objContext = nullptr;
589     napi_create_object(env, &objContext);
590 
591     for (const auto& data : customizeDatas) {
592         napi_set_named_property(env, objContext, data.name.c_str(), CreateJsValue(env, data.value));
593     }
594 
595     return objContext;
596 }
597 
ParseParam(napi_env env,napi_value args,FormInstancesFilter & filter)598 bool ParseParam(napi_env env, napi_value args, FormInstancesFilter &filter)
599 {
600     napi_valuetype valueType;
601     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
602     if (valueType != napi_object) {
603         HILOG_ERROR("args not object type");
604         return false;
605     }
606     napi_value prop = nullptr;
607     napi_get_named_property(env, args, "bundleName", &prop);
608     napi_typeof(env, prop, &valueType);
609     if (valueType != napi_string) {
610         HILOG_ERROR("input bundleName not string");
611         return false;
612     }
613     filter.bundleName = GetStringFromNapi(env, prop);
614     if (filter.bundleName.empty()) {
615         HILOG_ERROR("empty inputBundleName");
616         return false;
617     }
618     prop = nullptr;
619     napi_get_named_property(env, args, "formName", &prop);
620     filter.formName = GetStringFromNapi(env, prop);
621     prop = nullptr;
622     napi_get_named_property(env, args, "moduleName", &prop);
623     filter.moduleName = GetStringFromNapi(env, prop);
624     prop = nullptr;
625     napi_get_named_property(env, args, "abilityName", &prop);
626     filter.abilityName = GetStringFromNapi(env, prop);
627     bool hasIsUnusedIncluded = false;
628     napi_has_named_property(env, args, "isUnusedIncluded", &hasIsUnusedIncluded);
629     if (hasIsUnusedIncluded) {
630         prop = nullptr;
631         napi_get_named_property(env, args, "isUnusedIncluded", &prop);
632         if (napi_get_value_bool(env, prop, &filter.isUnusedIncluded) != napi_ok) {
633             return false;
634         }
635     }
636     return true;
637 }
638 
GetStringFromNapi(napi_env env,napi_value value)639 std::string GetStringFromNapi(napi_env env, napi_value value)
640 {
641     std::string result;
642     size_t size = 0;
643 
644     if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) {
645         HILOG_ERROR("can't get stringSize");
646         return "";
647     }
648     result.reserve(size + 1);
649     result.resize(size);
650     if (napi_get_value_string_utf8(env, value, result.data(), (size + 1), &size) != napi_ok) {
651         HILOG_ERROR("can't get string value");
652         return "";
653     }
654     return result;
655 }
656 
CreateFormInstances(napi_env env,const std::vector<FormInstance> & formInstances)657 napi_value CreateFormInstances(napi_env env, const std::vector<FormInstance> &formInstances)
658 {
659     napi_value arrayValue = nullptr;
660     napi_create_array_with_length(env, formInstances.size(), &arrayValue);
661     uint32_t index = 0;
662     for (const auto &formInstance : formInstances) {
663         napi_set_element(env, arrayValue, index++, CreateFormInstance(env, formInstance));
664     }
665     return arrayValue;
666 }
667 
CreateFormInstance(napi_env env,const FormInstance & formInstance)668 napi_value CreateFormInstance(napi_env env, const FormInstance &formInstance)
669 {
670     HILOG_DEBUG("call");
671 
672     napi_value objContext = nullptr;
673     napi_create_object(env, &objContext);
674 
675     std::string formStr = std::to_string(formInstance.formId);
676     napi_set_named_property(env, objContext, "formId", CreateJsValue(env, formStr));
677     napi_set_named_property(env, objContext, "hostBundleName", CreateJsValue(env, formInstance.formHostName));
678     napi_set_named_property(env, objContext, "visibilityType", CreateJsValue(env, formInstance.formVisiblity));
679     napi_set_named_property(env, objContext, "dimension", CreateJsValue(env, formInstance.specification));
680     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, formInstance.bundleName));
681     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, formInstance.moduleName));
682     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, formInstance.abilityName));
683     napi_set_named_property(env, objContext, "formName", CreateJsValue(env, formInstance.formName));
684     napi_set_named_property(env, objContext, "formUsageState", CreateJsValue(env, formInstance.formUsageState));
685     napi_set_named_property(env, objContext, "formDescription", CreateJsValue(env, formInstance.description));
686     return objContext;
687 }
688 
ConvertFormInfoFilter(napi_env env,napi_value value,AppExecFwk::FormInfoFilter & formInfoFilter)689 bool ConvertFormInfoFilter(napi_env env, napi_value value, AppExecFwk::FormInfoFilter &formInfoFilter)
690 {
691     napi_valuetype type = napi_undefined;
692     napi_typeof(env, value, &type);
693     if (type != napi_object) {
694         HILOG_ERROR("type not napi_object");
695         return false;
696     }
697 
698     napi_value nativeDataValue = nullptr;
699     napi_get_named_property(env, value, "moduleName", &nativeDataValue);
700     napi_valuetype nativeDataValueType = napi_undefined;
701     napi_typeof(env, nativeDataValue, &nativeDataValueType);
702     if (nativeDataValue == nullptr || (nativeDataValueType != napi_undefined &&
703         !ConvertFromJsValue(env, nativeDataValue, formInfoFilter.moduleName))) {
704         HILOG_ERROR("convert nativeDataValue failed");
705         return false;
706     }
707     HILOG_INFO("module:%{public}s", formInfoFilter.moduleName.c_str());
708 
709     return true;
710 }
711 }  // namespace AbilityRuntime
712 }  // namespace OHOS
713