• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 DECIMAL_VALUE = 10;
43 constexpr int BASE_NUMBER = 9;
44 constexpr int CALLBACK_FLG = 1;
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(NativeEngine & engine,int32_t errCode,const std::string & errMessage)118 bool NapiFormUtil::Throw(NativeEngine &engine, int32_t errCode, const std::string &errMessage)
119 {
120     NativeValue *error = engine.CreateError(CreateJsValue(engine, errCode), CreateJsValue(engine, errMessage));
121     return engine.Throw(error);
122 }
123 
ThrowByInternalErrorCode(NativeEngine & engine,int32_t internalErrorCode)124 bool NapiFormUtil::ThrowByInternalErrorCode(NativeEngine &engine, int32_t internalErrorCode)
125 {
126     int32_t externalErrorCode = 0;
127     std::string externalErrorMessage;
128     FormMgr::GetInstance().GetExternalError(internalErrorCode, externalErrorCode, externalErrorMessage);
129     return Throw(engine, externalErrorCode, externalErrorMessage);
130 }
131 
ThrowByExternalErrorCode(NativeEngine & engine,int32_t externalErrorCode)132 bool NapiFormUtil::ThrowByExternalErrorCode(NativeEngine &engine, int32_t externalErrorCode)
133 {
134     std::string externalErrorMessage = FormMgr::GetInstance().GetErrorMsgByExternalErrorCode(externalErrorCode);
135     return Throw(engine, externalErrorCode, externalErrorMessage);
136 }
137 
CreateErrorByInternalErrorCode(NativeEngine & engine,int32_t internalErrorCode)138 NativeValue *NapiFormUtil::CreateErrorByInternalErrorCode(NativeEngine &engine, int32_t internalErrorCode)
139 {
140     int32_t externalErrorCode = 0;
141     std::string externalErrorMessage;
142     FormMgr::GetInstance().GetExternalError(internalErrorCode, externalErrorCode, externalErrorMessage);
143     return CreateJsError(engine, externalErrorCode, externalErrorMessage);
144 }
145 
CreateErrorByExternalErrorCode(NativeEngine & engine,int32_t externalErrorCode)146 NativeValue *NapiFormUtil::CreateErrorByExternalErrorCode(NativeEngine &engine, int32_t externalErrorCode)
147 {
148     std::string externalErrorMessage = FormMgr::GetInstance().GetErrorMsgByExternalErrorCode(externalErrorCode);
149     return CreateJsError(engine, externalErrorCode, externalErrorMessage);
150 }
151 
ThrowParamTypeError(NativeEngine & engine,const std::string & paramName,const std::string & type)152 bool NapiFormUtil::ThrowParamTypeError(NativeEngine &engine, const std::string &paramName, const std::string &type)
153 {
154     return Throw(engine, ERR_FORM_EXTERNAL_PARAM_INVALID, CreateParamTypeErrorMessage(paramName, type));
155 }
156 
ThrowParamNumError(NativeEngine & engine,const std::string & gotNum,const std::string & expectedNum)157 bool NapiFormUtil::ThrowParamNumError(NativeEngine &engine, const std::string &gotNum, const std::string &expectedNum)
158 {
159     std::string errorMessage = "Parameter error. Got " + gotNum + ", expected " + expectedNum;
160     return Throw(engine, ERR_FORM_EXTERNAL_PARAM_INVALID, errorMessage);
161 }
162 
ThrowParamError(NativeEngine & engine,const std::string & extraMessage)163 bool NapiFormUtil::ThrowParamError(NativeEngine &engine, const std::string &extraMessage)
164 {
165     std::string errorMessage = "Parameter error. " + extraMessage;
166     return Throw(engine, ERR_FORM_EXTERNAL_PARAM_INVALID, errorMessage);
167 }
168 
CreateParamTypeErrorMessage(const std::string & paramName,const std::string & type)169 std::string NapiFormUtil::CreateParamTypeErrorMessage(const std::string &paramName, const std::string &type)
170 {
171     std::string errorMessage = "Parameter error.";
172     if (paramName.empty()) {
173         // Parameter error.
174         return errorMessage;
175     }
176     errorMessage += " The type of \"" + paramName + "\"";
177     if (type.empty()) {
178         errorMessage += " is invalid.";
179         // Parameter error. The type of "paramName" is invalid.
180         return errorMessage;
181     }
182     errorMessage += " must be " + type + ".";
183     // Parameter error. The type of "${paramName}" must be ${type}.
184     return errorMessage;
185 }
186 
187 /**
188  * @brief query the error message by error code
189  *
190  * @param[in] errorCode the error code return by form JS API.
191  *
192  * @return the error detail message
193  */
QueryRetMsg(int32_t errorCode)194 std::string QueryRetMsg(int32_t errorCode)
195 {
196     auto iter = CODE_MSG_MAP.find(errorCode);
197     if (iter != CODE_MSG_MAP.end()) {
198         return iter->second;
199     } else {
200         return CODE_MSG_MAP.at(ERR_COMMON);
201     }
202 }
203 
204 /**
205  * @brief query the error code by FMS errcode
206  *
207  * @param[in] innerErrorCode the error code return by form native API.
208  *
209  * @return the error detail message
210  */
QueryRetCode(int32_t innerErrorCode)211 int32_t QueryRetCode(int32_t innerErrorCode)
212 {
213     auto iter = ERROR_CODE_MAP.find(innerErrorCode);
214     if (iter != ERROR_CODE_MAP.end()) {
215         return iter->second;
216     } else {
217         return ERR_COMMON;
218     }
219 }
220 
221 /**
222  * @brief NapiGetResult
223  *
224  * @param[in] env The environment that the Node-API call is invoked under
225  *
226  * @return napi_value
227  */
NapiGetResult(napi_env env,int iResult)228 napi_value NapiGetResult(napi_env env, int iResult)
229 {
230     napi_value result;
231     NAPI_CALL(env, napi_create_int32(env, iResult, &result));
232     return result;
233 }
234 
235 /**
236  * @brief Convert string to int64_t
237  *
238  * @param[in] strInfo The string information
239  * @param[out] int64Value Convert string to int64_t
240  *
241  * @return Return the convert result
242  */
ConvertStringToInt64(const std::string & strInfo,int64_t & int64Value)243 bool ConvertStringToInt64(const std::string &strInfo, int64_t &int64Value)
244 {
245     size_t strLength = strInfo.size();
246     if (strLength == ZERO_VALUE) {
247         int64Value = ZERO_VALUE;
248         return true;
249     }
250     std::regex pattern("^0|-?[1-9][0-9]{0,18}$"); // "^-?[0-9]{1,19}$"
251     std::smatch match;
252     if (regex_match(strInfo, match, pattern)) {
253         HILOG_DEBUG("%{public}s, regex_match successed.", __func__);
254         if (strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1) != "-") { // maximum: 9223372036854775807
255             if (strLength < INT_64_LENGTH) {
256                 int64Value = std::stoll(strInfo);
257                 return true;
258             }
259             int maxSubValue = std::stoi(strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1));
260             if (strLength == INT_64_LENGTH && maxSubValue < BASE_NUMBER) {
261                 int64Value = std::stoll(strInfo);
262                 return true;
263             }
264             // Means 0x7FFFFFFFFFFFFFFF remove the first number:(2^63 - 1 - 9 * 10 ^ 19)
265             int subValue = std::stoll(strInfo.substr(ZERO_VALUE + 1, INT_64_LENGTH - 1));
266             if (strLength == INT_64_LENGTH && subValue <= INT64_MAX - BASE_NUMBER *
267                 pow(DECIMAL_VALUE, INT_64_LENGTH - 1)) {
268                 int64Value = std::stoll(strInfo);
269                 return true;
270             }
271         }
272         if (strLength < INT_64_LENGTH + 1) { // The minimum value: -9223372036854775808
273             int64Value = std::stoll(strInfo);
274             return true;
275         }
276         if (strLength == INT_64_LENGTH + 1) {
277             int minSubValue = std::stoi(strInfo.substr(1, 1));
278             if (minSubValue < BASE_NUMBER) {
279                 int64Value = std::stoll(strInfo);
280                 return true;
281             }
282 
283             // Means 0x8000000000000000 remove the first number:-(2^63 - 9 * 10 ^ 19)
284             if (std::stoll(strInfo.substr(ZERO_VALUE + 2, INT_64_LENGTH - 1)) <=
285                 (INT64_MAX - BASE_NUMBER * pow(DECIMAL_VALUE, INT_64_LENGTH) + 1)) {
286                 int64Value = std::stoll(strInfo);
287                 return true;
288             }
289         }
290     }
291     HILOG_DEBUG("%{public}s, regex_match failed.", __func__);
292     return false;
293 }
294 
295 /**
296  * @brief Create return message(callback)
297  *
298  * @param[in] env The environment that the Node-API call is invoked under
299  * @param[in] code result code
300  * @param[out] result result message
301  *
302  * @return void
303  */
InnerCreateCallbackRetMsg(napi_env env,int32_t code,napi_value (& result)[CALLBACK_RETURN_MSG_SIZE])304 void InnerCreateCallbackRetMsg(napi_env env, int32_t code, napi_value (&result)[CALLBACK_RETURN_MSG_SIZE])
305 {
306     HILOG_DEBUG("%{public}s called. code:%{public}d", __func__, code);
307     napi_value error = nullptr;
308     napi_create_object(env, &error);
309 
310     auto retCode = QueryRetCode(code);
311     auto retMsg = QueryRetMsg(retCode);
312 
313     // create error code
314     napi_value errCode = nullptr;
315     napi_create_int32(env, retCode, &errCode);
316     napi_set_named_property(env, error, "code", errCode);
317 
318     // create error message
319     napi_value errMsg = nullptr;
320     napi_create_string_utf8(env, retMsg.c_str(), NAPI_AUTO_LENGTH, &errMsg);
321     napi_set_named_property(env, error, "message", errMsg);
322 
323     result[0] = error;
324     napi_get_undefined(env, &result[1]);
325     HILOG_DEBUG("%{public}s, end.", __func__);
326 }
327 
328 /**
329  * @brief Create return message(promise)
330  *
331  * @param[in] env The environment that the Node-API call is invoked under
332  * @param[in] code result code
333  * @param[out] result result message
334  *
335  * @return void
336  */
InnerCreatePromiseRetMsg(napi_env env,int32_t code,napi_value * result)337 void InnerCreatePromiseRetMsg(napi_env env, int32_t code, napi_value* result)
338 {
339     HILOG_DEBUG("%{public}s called. code:%{public}d", __func__, code);
340     if (code == ERR_OK) {
341         napi_get_undefined(env, result);
342         return;
343     }
344     napi_value errInfo = nullptr;
345     napi_create_object(env, &errInfo);
346 
347     auto retCode = QueryRetCode(code);
348     auto retMsg = QueryRetMsg(retCode);
349 
350     // create error code
351     napi_value errCode = nullptr;
352     napi_create_int32(env, retCode, &errCode);
353     napi_set_named_property(env, errInfo, "code", errCode);
354 
355     // create error message
356     napi_value errMsg = nullptr;
357     napi_create_string_utf8(env, retMsg.c_str(), NAPI_AUTO_LENGTH, &errMsg);
358     napi_set_named_property(env, errInfo, "message", errMsg);
359 
360     *result = errInfo;
361     HILOG_DEBUG("%{public}s, end.", __func__);
362 }
363 
364 /**
365  * @brief Send error message.
366  *
367  * @param[in] env The environment that the Node-API call is invoked under
368  * @param[in] asyncCallbackInfo Reference, callback info via Node-API
369  * @param[out] result result message
370  *
371  * @return void
372  */
RetErrMsg(AsyncErrMsgCallbackInfo * asyncCallbackInfo)373 napi_value RetErrMsg(AsyncErrMsgCallbackInfo* asyncCallbackInfo)
374 {
375     HILOG_INFO("%{public}s called.", __func__);
376     if (asyncCallbackInfo == nullptr) {
377         HILOG_ERROR("asyncCallback == nullptr");
378         return nullptr;
379     }
380 
381     napi_env env = asyncCallbackInfo->env;
382     napi_value value = asyncCallbackInfo->callbackValue;
383 
384     if (asyncCallbackInfo->type == CALLBACK_FLG) {
385         HILOG_INFO("%{public}s, asyncCallback.", __func__);
386 
387         // Check the value type of the arguments
388         napi_valuetype valueType = napi_undefined;
389         NAPI_CALL(env, napi_typeof(env, value, &valueType));
390         NAPI_ASSERT(env, valueType == napi_function, "The arguments[1] type of deleteForm is incorrect,\
391             expected type is function.");
392 
393         napi_create_reference(env, value, REF_COUNT, &asyncCallbackInfo->callback);
394 
395         napi_value resourceName;
396         napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
397         napi_create_async_work(
398             env,
399             nullptr,
400             resourceName,
401             [](napi_env env, void *data) {},
402             [](napi_env env, napi_status status, void *data) {
403                 AsyncErrMsgCallbackInfo *asyncCallbackInfo = (AsyncErrMsgCallbackInfo *)data;
404                 HILOG_INFO("%{public}s, napi_create_async_work complete", __func__);
405                 if (asyncCallbackInfo->callback != nullptr) {
406                     napi_value callback;
407                     napi_value undefined;
408                     napi_value result[ARGS_SIZE_TWO] = {0};
409                     InnerCreateCallbackRetMsg(env, asyncCallbackInfo->code, result);
410                     napi_get_undefined(env, &undefined);
411                     napi_get_reference_value(env, asyncCallbackInfo->callback, &callback);
412                     napi_value callResult;
413                     napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, result, &callResult);
414                     napi_delete_reference(env, asyncCallbackInfo->callback);
415                 }
416                 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
417                 delete asyncCallbackInfo;
418             },
419             (void *)asyncCallbackInfo,
420             &asyncCallbackInfo->asyncWork);
421         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default));
422         return NapiGetResult(env, 1);
423     } else {
424         HILOG_INFO("%{public}s, promise.", __func__);
425         napi_deferred deferred;
426         napi_value promise;
427         NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
428         asyncCallbackInfo->deferred = deferred;
429 
430         napi_value resourceName;
431         napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
432         napi_create_async_work(
433             env,
434             nullptr,
435             resourceName,
436             [](napi_env env, void *data) {},
437             [](napi_env env, napi_status status, void *data) {
438                 HILOG_INFO("%{public}s, promise complete", __func__);
439                 AsyncErrMsgCallbackInfo *asyncCallbackInfo = (AsyncErrMsgCallbackInfo *)data;
440                 napi_value result;
441                 InnerCreatePromiseRetMsg(env, asyncCallbackInfo->code, &result);
442                 napi_reject_deferred(env, asyncCallbackInfo->deferred, result);
443                 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
444                 delete asyncCallbackInfo;
445             },
446             (void *)asyncCallbackInfo,
447             &asyncCallbackInfo->asyncWork);
448         napi_queue_async_work_with_qos(env, asyncCallbackInfo->asyncWork, napi_qos_default);
449         return promise;
450     }
451 }
452 
InitErrMsg(napi_env env,int32_t code,int32_t type,napi_value callbackValue)453 AsyncErrMsgCallbackInfo *InitErrMsg(napi_env env, int32_t code, int32_t type, napi_value callbackValue)
454 {
455     auto *asyncErrorInfo = new (std::nothrow) AsyncErrMsgCallbackInfo {
456         .env = env,
457         .asyncWork = nullptr,
458         .deferred = nullptr,
459         .callback = nullptr,
460         .callbackValue = callbackValue,
461         .code = code,
462         .type = type
463     };
464     return asyncErrorInfo;
465 }
466 
SetFormInfoPropertyString(napi_env env,const char * inValue,napi_value & result,const char * outName)467 void SetFormInfoPropertyString(napi_env env, const char *inValue, napi_value &result, const char *outName)
468 {
469     napi_value temp;
470     napi_create_string_utf8(env, inValue, NAPI_AUTO_LENGTH, &temp);
471     HILOG_DEBUG("%{public}s, %{public}s=%{public}s.", __func__, outName, inValue);
472     napi_set_named_property(env, result, outName, temp);
473 }
474 
SetFormInfoPropertyInt32(napi_env env,int32_t inValue,napi_value & result,const char * outName)475 void SetFormInfoPropertyInt32(napi_env env, int32_t inValue, napi_value &result, const char *outName)
476 {
477     napi_value temp;
478     napi_create_int32(env, inValue, &temp);
479     HILOG_DEBUG("%{public}s, %{public}s=%{public}d.", __func__, outName, inValue);
480     napi_set_named_property(env, result, outName, temp);
481 }
482 
SetFormInfoPropertyBoolean(napi_env env,bool inValue,napi_value & result,const char * outName)483 void SetFormInfoPropertyBoolean(napi_env env, bool inValue, napi_value &result, const char *outName)
484 {
485     napi_value temp;
486     napi_get_boolean(env, inValue, &temp);
487     HILOG_DEBUG("%{public}s, %{public}s=%{public}d.", __func__, outName, inValue);
488     napi_set_named_property(env, result, outName, temp);
489 }
490 
491 /**
492  * @brief Parse form info into Node-API
493  *
494  * @param[in] env The environment that the Node-API call is invoked under
495  * @param[in] formInfo it is used for return forminfo to JavaScript
496  * @param[out] result This is an opaque pointer that is used to represent a JavaScript value
497  *
498  * @return void
499  */
ParseFormInfoIntoNapi(napi_env env,const FormInfo & formInfo,napi_value & result)500 void ParseFormInfoIntoNapi(napi_env env, const FormInfo &formInfo, napi_value &result)
501 {
502     SetFormInfoPropertyString(env, formInfo.bundleName.c_str(), result, "bundleName");
503     SetFormInfoPropertyString(env, formInfo.moduleName.c_str(), result, "moduleName");
504     SetFormInfoPropertyString(env, formInfo.abilityName.c_str(), result, "abilityName");
505     SetFormInfoPropertyString(env, formInfo.name.c_str(), result, "name");
506     SetFormInfoPropertyString(env, formInfo.description.c_str(), result, "description");
507     SetFormInfoPropertyInt32(env, formInfo.descriptionId, result, "descriptionId");
508     FormType formType = formInfo.type;
509     SetFormInfoPropertyInt32(env, (int32_t)formType, result, "type");
510     SetFormInfoPropertyString(env, formInfo.jsComponentName.c_str(), result, "jsComponentName");
511     FormsColorMode formsColorMode = formInfo.colorMode;
512     SetFormInfoPropertyInt32(env, (int32_t)formsColorMode, result, "colorMode");
513     SetFormInfoPropertyBoolean(env, formInfo.defaultFlag, result, "isDefault");
514     SetFormInfoPropertyBoolean(env, formInfo.updateEnabled, result, "updateEnabled");
515     SetFormInfoPropertyBoolean(env, formInfo.formVisibleNotify, result, "formVisibleNotify");
516     SetFormInfoPropertyString(env, formInfo.formConfigAbility.c_str(), result, "formConfigAbility");
517     SetFormInfoPropertyInt32(env, formInfo.updateDuration, result, "updateDuration");
518     SetFormInfoPropertyString(env, formInfo.scheduledUpdateTime.c_str(), result, "scheduledUpdateTime");
519     SetFormInfoPropertyInt32(env, formInfo.defaultDimension, result, "defaultDimension");
520     SetFormInfoPropertyString(env, formInfo.relatedBundleName.c_str(), result, "relatedBundleName");
521 
522     // supportDimensions
523     napi_value supportDimensions;
524     napi_create_array(env, &supportDimensions);
525     int32_t iDimensionsCount = 0;
526     for (auto dimension : formInfo.supportDimensions) {
527         HILOG_DEBUG("%{public}s, dimension=%{public}d.", __func__, dimension);
528         napi_value dimensionInfo;
529         napi_create_int32(env, (int32_t)dimension, &dimensionInfo);
530         napi_set_element(env, supportDimensions, iDimensionsCount, dimensionInfo);
531         ++iDimensionsCount;
532     }
533     HILOG_DEBUG("%{public}s, supportDimensions size=%{public}zu.", __func__, formInfo.supportDimensions.size());
534     napi_set_named_property(env, result, "supportDimensions", supportDimensions);
535 
536     // customizeData
537     napi_value customizeData;
538     napi_create_object(env, &customizeData);
539     for (const auto& data : formInfo.customizeDatas) {
540         SetFormInfoPropertyString(env, data.value.c_str(), customizeData, data.name.c_str());
541     }
542     HILOG_DEBUG("%{public}s, customizeData size=%{public}zu.", __func__, formInfo.customizeDatas.size());
543     napi_set_named_property(env, result, "customizeData", customizeData);
544 }
545 
ParseRunningFormInfoIntoNapi(napi_env env,const RunningFormInfo & runningFormInfo,napi_value & result)546 void ParseRunningFormInfoIntoNapi(napi_env env, const RunningFormInfo &runningFormInfo, napi_value &result)
547 {
548     std::string formIdString = std::to_string(runningFormInfo.formId);
549     SetFormInfoPropertyString(env, formIdString.c_str(), result, "formId");
550     SetFormInfoPropertyString(env, runningFormInfo.bundleName.c_str(), result, "bundleName");
551     SetFormInfoPropertyString(env, runningFormInfo.hostBundleName.c_str(), result, "hostBundleName");
552     FormVisibilityType formVisiblity = runningFormInfo.formVisiblity;
553     SetFormInfoPropertyInt32(env, (int32_t)formVisiblity, result, "visibilityType");
554     SetFormInfoPropertyString(env, runningFormInfo.moduleName.c_str(), result, "moduleName");
555     SetFormInfoPropertyString(env, runningFormInfo.formName.c_str(), result, "formName");
556     SetFormInfoPropertyInt32(env, runningFormInfo.dimension, result, "dimension");
557     SetFormInfoPropertyString(env, runningFormInfo.abilityName.c_str(), result, "abilityName");
558 }
559 
GetFormType(const FormInfo & formInfo)560 inline FormType GetFormType(const FormInfo &formInfo)
561 {
562     if (formInfo.uiSyntax == FormType::ETS) {
563         return FormType::ETS;
564     }
565     return formInfo.type;
566 }
567 
CreateFormInfos(NativeEngine & engine,const std::vector<FormInfo> & formInfos)568 NativeValue* CreateFormInfos(NativeEngine &engine, const std::vector<FormInfo> &formInfos)
569 {
570     NativeValue* arrayValue = engine.CreateArray(formInfos.size());
571     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
572     uint32_t index = 0;
573     for (const auto &formInfo : formInfos) {
574         array->SetElement(index++, CreateFormInfo(engine, formInfo));
575     }
576     return arrayValue;
577 }
578 
CreateFormInfo(NativeEngine & engine,const FormInfo & formInfo)579 NativeValue* CreateFormInfo(NativeEngine &engine, const FormInfo &formInfo)
580 {
581     HILOG_DEBUG("called");
582 
583     auto objContext = engine.CreateObject();
584     if (objContext == nullptr) {
585         HILOG_ERROR("CreateObject failed");
586         return engine.CreateUndefined();
587     }
588 
589     auto object = ConvertNativeValueTo<NativeObject>(objContext);
590     if (object == nullptr) {
591         HILOG_ERROR("ConvertNativeValueTo object failed");
592         return engine.CreateUndefined();
593     }
594 
595     object->SetProperty("bundleName", CreateJsValue(engine, formInfo.bundleName));
596     object->SetProperty("moduleName", CreateJsValue(engine, formInfo.moduleName));
597     object->SetProperty("abilityName", CreateJsValue(engine, formInfo.abilityName));
598     object->SetProperty("name", CreateJsValue(engine, formInfo.name));
599     object->SetProperty("description", CreateJsValue(engine, formInfo.description));
600     object->SetProperty("descriptionId", CreateJsValue(engine, formInfo.descriptionId));
601     object->SetProperty("type", CreateJsValue(engine, GetFormType(formInfo)));
602     object->SetProperty("jsComponentName", CreateJsValue(engine, formInfo.jsComponentName));
603     object->SetProperty("colorMode", CreateJsValue(engine, formInfo.colorMode));
604     object->SetProperty("isDefault", engine.CreateBoolean(formInfo.defaultFlag));
605     object->SetProperty("updateEnabled", engine.CreateBoolean(formInfo.updateEnabled));
606     object->SetProperty("formVisibleNotify", engine.CreateBoolean(formInfo.formVisibleNotify));
607     object->SetProperty("formConfigAbility", CreateJsValue(engine, formInfo.formConfigAbility));
608     object->SetProperty("updateDuration", CreateJsValue(engine, formInfo.updateDuration));
609     object->SetProperty("scheduledUpdateTime", CreateJsValue(engine, formInfo.scheduledUpdateTime));
610     object->SetProperty("defaultDimension", CreateJsValue(engine, formInfo.defaultDimension));
611     object->SetProperty("relatedBundleName", CreateJsValue(engine, formInfo.relatedBundleName));
612     object->SetProperty("supportDimensions", CreateNativeArray(engine, formInfo.supportDimensions));
613     object->SetProperty("customizeData", CreateFormCustomizeDatas(engine, formInfo.customizeDatas));
614     object->SetProperty("isDynamic", engine.CreateBoolean(formInfo.isDynamic));
615 
616     return objContext;
617 }
618 
CreateRunningFormInfos(NativeEngine & engine,const std::vector<RunningFormInfo> & runningFormInfos)619 NativeValue *CreateRunningFormInfos(NativeEngine &engine, const std::vector<RunningFormInfo> &runningFormInfos)
620 {
621     NativeValue *arrayValue = engine.CreateArray(runningFormInfos.size());
622     NativeArray *array = ConvertNativeValueTo<NativeArray>(arrayValue);
623     uint32_t index = 0;
624     for (const auto &runningFormInfo : runningFormInfos) {
625         array->SetElement(index++, CreateRunningFormInfo(engine, runningFormInfo));
626     }
627     return arrayValue;
628 }
629 
CreateRunningFormInfo(NativeEngine & engine,const RunningFormInfo & runningFormInfo)630 NativeValue *CreateRunningFormInfo(NativeEngine &engine, const RunningFormInfo &runningFormInfo)
631 {
632     HILOG_DEBUG("called");
633 
634     auto objContext = engine.CreateObject();
635     if (objContext == nullptr) {
636         HILOG_ERROR("CreateObject failed");
637         return engine.CreateUndefined();
638     }
639 
640     auto object = ConvertNativeValueTo<NativeObject>(objContext);
641     if (object == nullptr) {
642         HILOG_ERROR("ConvertNativeValueTo object failed");
643         return engine.CreateUndefined();
644     }
645 
646     object->SetProperty("formId", CreateJsValue(engine, runningFormInfo.formId));
647     object->SetProperty("bundleName", CreateJsValue(engine, runningFormInfo.bundleName));
648     object->SetProperty("hostBundleName", CreateJsValue(engine, runningFormInfo.hostBundleName));
649     object->SetProperty("visibilityType", CreateJsValue(engine, runningFormInfo.formVisiblity));
650     object->SetProperty("moduleName", CreateJsValue(engine, runningFormInfo.moduleName));
651     object->SetProperty("abilityName", CreateJsValue(engine, runningFormInfo.abilityName));
652     object->SetProperty("formName", CreateJsValue(engine, runningFormInfo.formName));
653     object->SetProperty("dimension", CreateJsValue(engine, runningFormInfo.dimension));
654 
655     return objContext;
656 }
657 
CreateFormCustomizeDatas(NativeEngine & engine,const std::vector<FormCustomizeData> & customizeDatas)658 NativeValue *CreateFormCustomizeDatas(NativeEngine &engine, const std::vector<FormCustomizeData> &customizeDatas)
659 {
660     auto objContext = engine.CreateObject();
661     if (objContext == nullptr) {
662         HILOG_ERROR("CreateObject failed");
663         return engine.CreateUndefined();
664     }
665 
666     auto object = ConvertNativeValueTo<NativeObject>(objContext);
667     if (object == nullptr) {
668         HILOG_ERROR("ConvertNativeValueTo object failed");
669         return engine.CreateUndefined();
670     }
671 
672     for (const auto& data : customizeDatas) {
673         object->SetProperty(data.name.c_str(), CreateJsValue(engine, data.value));
674     }
675 
676     return objContext;
677 }
678 
ParseParam(napi_env env,napi_value args,FormInstancesFilter & filter)679 bool ParseParam(napi_env env, napi_value args, FormInstancesFilter &filter)
680 {
681     napi_valuetype valueType;
682     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
683     if (valueType != napi_object) {
684         HILOG_ERROR("args not object type");
685         return false;
686     }
687     napi_value prop = nullptr;
688     napi_get_named_property(env, args, "bundleName", &prop);
689     napi_typeof(env, prop, &valueType);
690     if (valueType != napi_string) {
691         HILOG_ERROR("The input bundleName is not a string.");
692         return false;
693     }
694     filter.bundleName = GetStringFromNapi(env, prop);
695     if (filter.bundleName.empty()) {
696         HILOG_ERROR("The input bundleName is empty");
697         return false;
698     }
699     prop = nullptr;
700     napi_get_named_property(env, args, "formName", &prop);
701     filter.formName = GetStringFromNapi(env, prop);
702     prop = nullptr;
703     napi_get_named_property(env, args, "moduleName", &prop);
704     filter.moduleName = GetStringFromNapi(env, prop);
705     prop = nullptr;
706     napi_get_named_property(env, args, "abilityName", &prop);
707     filter.abilityName = GetStringFromNapi(env, prop);
708     return true;
709 }
710 
GetStringFromNapi(napi_env env,napi_value value)711 std::string GetStringFromNapi(napi_env env, napi_value value)
712 {
713     std::string result;
714     size_t size = 0;
715 
716     if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) {
717         HILOG_ERROR("can not get string size");
718         return "";
719     }
720     result.reserve(size + 1);
721     result.resize(size);
722     if (napi_get_value_string_utf8(env, value, result.data(), (size + 1), &size) != napi_ok) {
723         HILOG_ERROR("can not get string value");
724         return "";
725     }
726     return result;
727 }
728 
CreateFormInstances(NativeEngine & engine,const std::vector<FormInstance> & formInstances)729 NativeValue *CreateFormInstances(NativeEngine &engine, const std::vector<FormInstance> &formInstances)
730 {
731     NativeValue* arrayValue = engine.CreateArray(formInstances.size());
732     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
733     if (array == nullptr) {
734         return engine.CreateUndefined();
735     }
736     uint32_t index = 0;
737     for (const auto &formInstance : formInstances) {
738         array->SetElement(index++, CreateFormInstance(engine, formInstance));
739     }
740     return arrayValue;
741 }
742 
CreateFormInstance(NativeEngine & engine,const FormInstance & formInstance)743 NativeValue *CreateFormInstance(NativeEngine &engine, const FormInstance &formInstance)
744 {
745     HILOG_DEBUG("called");
746 
747     auto objContext = engine.CreateObject();
748     if (objContext == nullptr) {
749         HILOG_ERROR("create object failed");
750         return engine.CreateUndefined();
751     }
752 
753     auto object = ConvertNativeValueTo<NativeObject>(objContext);
754     if (object == nullptr) {
755         HILOG_ERROR("convert native value to object failed");
756         return engine.CreateUndefined();
757     }
758     std::string formStr = std::to_string(formInstance.formId);
759     object->SetProperty("formId", CreateJsValue(engine, formStr));
760     object->SetProperty("hostBundleName", CreateJsValue(engine, formInstance.formHostName));
761     object->SetProperty("visibilityType", CreateJsValue(engine, formInstance.formVisiblity));
762     object->SetProperty("dimension", CreateJsValue(engine, formInstance.specification));
763     object->SetProperty("bundleName", CreateJsValue(engine, formInstance.bundleName));
764     object->SetProperty("moduleName", CreateJsValue(engine, formInstance.moduleName));
765     object->SetProperty("abilityName", CreateJsValue(engine, formInstance.abilityName));
766     object->SetProperty("formName", CreateJsValue(engine, formInstance.formName));
767     return objContext;
768 }
769 }  // namespace AbilityRuntime
770 }  // namespace OHOS