• 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(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("%{public}s, regex_match successed.", __func__);
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             int subValue = std::stoll(strInfo.substr(ZERO_VALUE + 1, INT_64_LENGTH - 1));
267             if (strLength == INT_64_LENGTH && subValue <= INT64_MAX - BASE_NUMBER *
268                 pow(DECIMAL_VALUE, INT_64_LENGTH - 1)) {
269                 int64Value = std::stoll(strInfo);
270                 return true;
271             }
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             if (std::stoll(strInfo.substr(ZERO_VALUE + 2, INT_64_LENGTH - 1)) <=
286                 (INT64_MAX - BASE_NUMBER * pow(DECIMAL_VALUE, INT_64_LENGTH) + 1)) {
287                 int64Value = std::stoll(strInfo);
288                 return true;
289             }
290         }
291     }
292     HILOG_DEBUG("%{public}s, regex_match failed.", __func__);
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("%{public}s called. code:%{public}d", __func__, 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("%{public}s, end.", __func__);
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("%{public}s called. code:%{public}d", __func__, 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("%{public}s, end.", __func__);
363 }
364 
RetErrMsgForCallback(AsyncErrMsgCallbackInfo * asyncCallbackInfo)365 napi_value RetErrMsgForCallback(AsyncErrMsgCallbackInfo* asyncCallbackInfo)
366 {
367     HILOG_INFO("called.");
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("napi_create_async_work 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("called.");
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("called.");
454     if (asyncCallbackInfo == nullptr) {
455         HILOG_ERROR("asyncCallback == nullptr");
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 
SetFormInfoPropertyString(napi_env env,const char * inValue,napi_value & result,const char * outName)478 void SetFormInfoPropertyString(napi_env env, const char *inValue, napi_value &result, const char *outName)
479 {
480     napi_value temp;
481     napi_create_string_utf8(env, inValue, NAPI_AUTO_LENGTH, &temp);
482     HILOG_DEBUG("%{public}s, %{public}s=%{public}s.", __func__, outName, inValue);
483     napi_set_named_property(env, result, outName, temp);
484 }
485 
SetFormInfoPropertyInt32(napi_env env,int32_t inValue,napi_value & result,const char * outName)486 void SetFormInfoPropertyInt32(napi_env env, int32_t inValue, napi_value &result, const char *outName)
487 {
488     napi_value temp;
489     napi_create_int32(env, inValue, &temp);
490     HILOG_DEBUG("%{public}s, %{public}s=%{public}d.", __func__, outName, inValue);
491     napi_set_named_property(env, result, outName, temp);
492 }
493 
SetFormInfoPropertyBoolean(napi_env env,bool inValue,napi_value & result,const char * outName)494 void SetFormInfoPropertyBoolean(napi_env env, bool inValue, napi_value &result, const char *outName)
495 {
496     napi_value temp;
497     napi_get_boolean(env, inValue, &temp);
498     HILOG_DEBUG("%{public}s, %{public}s=%{public}d.", __func__, outName, inValue);
499     napi_set_named_property(env, result, outName, temp);
500 }
501 
502 /**
503  * @brief Parse form info into Node-API
504  *
505  * @param[in] env The environment that the Node-API call is invoked under
506  * @param[in] formInfo it is used for return forminfo to JavaScript
507  * @param[out] result This is an opaque pointer that is used to represent a JavaScript value
508  *
509  * @return void
510  */
ParseFormInfoIntoNapi(napi_env env,const FormInfo & formInfo,napi_value & result)511 void ParseFormInfoIntoNapi(napi_env env, const FormInfo &formInfo, napi_value &result)
512 {
513     SetFormInfoPropertyString(env, formInfo.bundleName.c_str(), result, "bundleName");
514     SetFormInfoPropertyString(env, formInfo.moduleName.c_str(), result, "moduleName");
515     SetFormInfoPropertyString(env, formInfo.abilityName.c_str(), result, "abilityName");
516     SetFormInfoPropertyString(env, formInfo.name.c_str(), result, "name");
517     SetFormInfoPropertyString(env, formInfo.displayName.c_str(), result, "displayName");
518     SetFormInfoPropertyInt32(env, formInfo.displayNameId, result, "displayNameId");
519     SetFormInfoPropertyString(env, formInfo.description.c_str(), result, "description");
520     SetFormInfoPropertyInt32(env, formInfo.descriptionId, result, "descriptionId");
521     FormType formType = formInfo.type;
522     SetFormInfoPropertyInt32(env, (int32_t)formType, result, "type");
523     SetFormInfoPropertyString(env, formInfo.jsComponentName.c_str(), result, "jsComponentName");
524     FormsColorMode formsColorMode = formInfo.colorMode;
525     SetFormInfoPropertyInt32(env, (int32_t)formsColorMode, result, "colorMode");
526     SetFormInfoPropertyBoolean(env, formInfo.defaultFlag, result, "isDefault");
527     SetFormInfoPropertyBoolean(env, formInfo.updateEnabled, result, "updateEnabled");
528     SetFormInfoPropertyBoolean(env, formInfo.formVisibleNotify, result, "formVisibleNotify");
529     SetFormInfoPropertyString(env, formInfo.formConfigAbility.c_str(), result, "formConfigAbility");
530     SetFormInfoPropertyInt32(env, formInfo.updateDuration, result, "updateDuration");
531     SetFormInfoPropertyString(env, formInfo.scheduledUpdateTime.c_str(), result, "scheduledUpdateTime");
532     SetFormInfoPropertyInt32(env, formInfo.defaultDimension, result, "defaultDimension");
533     SetFormInfoPropertyString(env, formInfo.relatedBundleName.c_str(), result, "relatedBundleName");
534 
535     // supportDimensions
536     napi_value supportDimensions;
537     napi_create_array(env, &supportDimensions);
538     int32_t iDimensionsCount = 0;
539     for (auto dimension : formInfo.supportDimensions) {
540         HILOG_DEBUG("%{public}s, dimension=%{public}d.", __func__, dimension);
541         napi_value dimensionInfo;
542         napi_create_int32(env, (int32_t)dimension, &dimensionInfo);
543         napi_set_element(env, supportDimensions, iDimensionsCount, dimensionInfo);
544         ++iDimensionsCount;
545     }
546     HILOG_DEBUG("%{public}s, supportDimensions size=%{public}zu.", __func__, formInfo.supportDimensions.size());
547     napi_set_named_property(env, result, "supportDimensions", supportDimensions);
548 
549     // customizeData
550     napi_value customizeData;
551     napi_create_object(env, &customizeData);
552     for (const auto& data : formInfo.customizeDatas) {
553         SetFormInfoPropertyString(env, data.value.c_str(), customizeData, data.name.c_str());
554     }
555     HILOG_DEBUG("%{public}s, customizeData size=%{public}zu.", __func__, formInfo.customizeDatas.size());
556     napi_set_named_property(env, result, "customizeData", customizeData);
557 }
558 
ParseRunningFormInfoIntoNapi(napi_env env,const RunningFormInfo & runningFormInfo,napi_value & result)559 void ParseRunningFormInfoIntoNapi(napi_env env, const RunningFormInfo &runningFormInfo, napi_value &result)
560 {
561     std::string formIdString = std::to_string(runningFormInfo.formId);
562     SetFormInfoPropertyString(env, formIdString.c_str(), result, "formId");
563     SetFormInfoPropertyString(env, runningFormInfo.bundleName.c_str(), result, "bundleName");
564     SetFormInfoPropertyString(env, runningFormInfo.hostBundleName.c_str(), result, "hostBundleName");
565     FormVisibilityType formVisiblity = runningFormInfo.formVisiblity;
566     SetFormInfoPropertyInt32(env, (int32_t)formVisiblity, result, "visibilityType");
567     SetFormInfoPropertyString(env, runningFormInfo.moduleName.c_str(), result, "moduleName");
568     SetFormInfoPropertyString(env, runningFormInfo.abilityName.c_str(), result, "abilityName");
569     SetFormInfoPropertyString(env, runningFormInfo.formName.c_str(), result, "formName");
570     SetFormInfoPropertyInt32(env, runningFormInfo.dimension, result, "dimension");
571     FormUsageState formUsageState = runningFormInfo.formUsageState;
572     SetFormInfoPropertyInt32(env, (int32_t)formUsageState, result, "formUsageState");
573     SetFormInfoPropertyString(env, runningFormInfo.description.c_str(), result, "formDescription");
574 }
575 
GetFormType(const FormInfo & formInfo)576 inline FormType GetFormType(const FormInfo &formInfo)
577 {
578     if (formInfo.uiSyntax == FormType::ETS) {
579         return FormType::ETS;
580     }
581     return formInfo.type;
582 }
583 
CreateFormInfos(napi_env env,const std::vector<FormInfo> & formInfos)584 napi_value CreateFormInfos(napi_env env, const std::vector<FormInfo> &formInfos)
585 {
586     napi_value arrayValue = nullptr;
587     napi_create_array_with_length(env, formInfos.size(), &arrayValue);
588     uint32_t index = 0;
589     for (const auto &formInfo : formInfos) {
590         napi_set_element(env, arrayValue, index++, CreateFormInfo(env, formInfo));
591     }
592     return arrayValue;
593 }
594 
CreateFormInfo(napi_env env,const FormInfo & formInfo)595 napi_value CreateFormInfo(napi_env env, const FormInfo &formInfo)
596 {
597     HILOG_DEBUG("called");
598 
599     napi_value objContext = nullptr;
600     napi_create_object(env, &objContext);
601 
602     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, formInfo.bundleName));
603     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, formInfo.moduleName));
604     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, formInfo.abilityName));
605     napi_set_named_property(env, objContext, "name", CreateJsValue(env, formInfo.name));
606     napi_set_named_property(env, objContext, "displayName", CreateJsValue(env, formInfo.displayName));
607     napi_set_named_property(env, objContext, "displayNameId", CreateJsValue(env, formInfo.displayNameId));
608     napi_set_named_property(env, objContext, "description", CreateJsValue(env, formInfo.description));
609     napi_set_named_property(env, objContext, "descriptionId", CreateJsValue(env, formInfo.descriptionId));
610     napi_set_named_property(env, objContext, "type", CreateJsValue(env, GetFormType(formInfo)));
611     napi_set_named_property(env, objContext, "jsComponentName", CreateJsValue(env, formInfo.jsComponentName));
612     napi_set_named_property(env, objContext, "colorMode", CreateJsValue(env, formInfo.colorMode));
613     napi_set_named_property(env, objContext, "isDefault", CreateJsValue(env, formInfo.defaultFlag));
614     napi_set_named_property(env, objContext, "updateEnabled", CreateJsValue(env, formInfo.updateEnabled));
615     napi_set_named_property(env, objContext, "formVisibleNotify", CreateJsValue(env, formInfo.formVisibleNotify));
616     napi_set_named_property(env, objContext, "formConfigAbility", CreateJsValue(env, formInfo.formConfigAbility));
617     napi_set_named_property(env, objContext, "updateDuration", CreateJsValue(env, formInfo.updateDuration));
618     napi_set_named_property(env, objContext, "scheduledUpdateTime", CreateJsValue(env, formInfo.scheduledUpdateTime));
619     napi_set_named_property(env, objContext, "defaultDimension", CreateJsValue(env, formInfo.defaultDimension));
620     napi_set_named_property(env, objContext, "relatedBundleName", CreateJsValue(env, formInfo.relatedBundleName));
621     napi_set_named_property(env, objContext, "supportDimensions", CreateNativeArray(env, formInfo.supportDimensions));
622     napi_set_named_property(env, objContext, "customizeData", CreateFormCustomizeDatas(env, formInfo.customizeDatas));
623     napi_set_named_property(env, objContext, "isDynamic", CreateJsValue(env, formInfo.isDynamic));
624     napi_set_named_property(env, objContext, "transparencyEnabled", CreateJsValue(env, formInfo.transparencyEnabled));
625 
626     return objContext;
627 }
628 
CreateRunningFormInfos(napi_env env,const std::vector<RunningFormInfo> & runningFormInfos)629 napi_value CreateRunningFormInfos(napi_env env, const std::vector<RunningFormInfo> &runningFormInfos)
630 {
631     napi_value arrayValue = nullptr;
632     napi_create_array_with_length(env, runningFormInfos.size(), &arrayValue);
633     uint32_t index = 0;
634     for (const auto &runningFormInfo : runningFormInfos) {
635         napi_set_element(env, arrayValue, index++, CreateRunningFormInfo(env, runningFormInfo));
636     }
637     return arrayValue;
638 }
639 
CreateRunningFormInfo(napi_env env,const RunningFormInfo & runningFormInfo)640 napi_value CreateRunningFormInfo(napi_env env, const RunningFormInfo &runningFormInfo)
641 {
642     HILOG_DEBUG("called");
643 
644     napi_value objContext = nullptr;
645     napi_create_object(env, &objContext);
646 
647     std::string formStr = std::to_string(runningFormInfo.formId);
648     napi_set_named_property(env, objContext, "formId", CreateJsValue(env, formStr));
649     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, runningFormInfo.bundleName));
650     napi_set_named_property(env, objContext, "hostBundleName", CreateJsValue(env, runningFormInfo.hostBundleName));
651     napi_set_named_property(env, objContext, "visibilityType", CreateJsValue(env, runningFormInfo.formVisiblity));
652     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, runningFormInfo.moduleName));
653     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, runningFormInfo.abilityName));
654     napi_set_named_property(env, objContext, "formName", CreateJsValue(env, runningFormInfo.formName));
655     napi_set_named_property(env, objContext, "dimension", CreateJsValue(env, runningFormInfo.dimension));
656     napi_set_named_property(env, objContext, "formUsageState", CreateJsValue(env, runningFormInfo.formUsageState));
657     napi_set_named_property(env, objContext, "formDescription", CreateJsValue(env, runningFormInfo.description));
658 
659     return objContext;
660 }
661 
CreateFormCustomizeDatas(napi_env env,const std::vector<FormCustomizeData> & customizeDatas)662 napi_value CreateFormCustomizeDatas(napi_env env, const std::vector<FormCustomizeData> &customizeDatas)
663 {
664     napi_value objContext = nullptr;
665     napi_create_object(env, &objContext);
666 
667     for (const auto& data : customizeDatas) {
668         napi_set_named_property(env, objContext, data.name.c_str(), CreateJsValue(env, data.value));
669     }
670 
671     return objContext;
672 }
673 
ParseParam(napi_env env,napi_value args,FormInstancesFilter & filter)674 bool ParseParam(napi_env env, napi_value args, FormInstancesFilter &filter)
675 {
676     napi_valuetype valueType;
677     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
678     if (valueType != napi_object) {
679         HILOG_ERROR("args not object type");
680         return false;
681     }
682     napi_value prop = nullptr;
683     napi_get_named_property(env, args, "bundleName", &prop);
684     napi_typeof(env, prop, &valueType);
685     if (valueType != napi_string) {
686         HILOG_ERROR("The input bundleName is not a string.");
687         return false;
688     }
689     filter.bundleName = GetStringFromNapi(env, prop);
690     if (filter.bundleName.empty()) {
691         HILOG_ERROR("The input bundleName is empty");
692         return false;
693     }
694     prop = nullptr;
695     napi_get_named_property(env, args, "formName", &prop);
696     filter.formName = GetStringFromNapi(env, prop);
697     prop = nullptr;
698     napi_get_named_property(env, args, "moduleName", &prop);
699     filter.moduleName = GetStringFromNapi(env, prop);
700     prop = nullptr;
701     napi_get_named_property(env, args, "abilityName", &prop);
702     filter.abilityName = GetStringFromNapi(env, prop);
703     bool hasIsUnusedIncluded = false;
704     napi_has_named_property(env, args, "isUnusedIncluded", &hasIsUnusedIncluded);
705     if (hasIsUnusedIncluded) {
706         prop = nullptr;
707         napi_get_named_property(env, args, "isUnusedIncluded", &prop);
708         if (napi_get_value_bool(env, prop, &filter.isUnusedIncluded) != napi_ok) {
709             return false;
710         }
711     }
712     return true;
713 }
714 
GetStringFromNapi(napi_env env,napi_value value)715 std::string GetStringFromNapi(napi_env env, napi_value value)
716 {
717     std::string result;
718     size_t size = 0;
719 
720     if (napi_get_value_string_utf8(env, value, nullptr, 0, &size) != napi_ok) {
721         HILOG_ERROR("can not get string size");
722         return "";
723     }
724     result.reserve(size + 1);
725     result.resize(size);
726     if (napi_get_value_string_utf8(env, value, result.data(), (size + 1), &size) != napi_ok) {
727         HILOG_ERROR("can not get string value");
728         return "";
729     }
730     return result;
731 }
732 
CreateFormInstances(napi_env env,const std::vector<FormInstance> & formInstances)733 napi_value CreateFormInstances(napi_env env, const std::vector<FormInstance> &formInstances)
734 {
735     napi_value arrayValue = nullptr;
736     napi_create_array_with_length(env, formInstances.size(), &arrayValue);
737     uint32_t index = 0;
738     for (const auto &formInstance : formInstances) {
739         napi_set_element(env, arrayValue, index++, CreateFormInstance(env, formInstance));
740     }
741     return arrayValue;
742 }
743 
CreateFormInstance(napi_env env,const FormInstance & formInstance)744 napi_value CreateFormInstance(napi_env env, const FormInstance &formInstance)
745 {
746     HILOG_DEBUG("called");
747 
748     napi_value objContext = nullptr;
749     napi_create_object(env, &objContext);
750 
751     std::string formStr = std::to_string(formInstance.formId);
752     napi_set_named_property(env, objContext, "formId", CreateJsValue(env, formStr));
753     napi_set_named_property(env, objContext, "hostBundleName", CreateJsValue(env, formInstance.formHostName));
754     napi_set_named_property(env, objContext, "visibilityType", CreateJsValue(env, formInstance.formVisiblity));
755     napi_set_named_property(env, objContext, "dimension", CreateJsValue(env, formInstance.specification));
756     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, formInstance.bundleName));
757     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, formInstance.moduleName));
758     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, formInstance.abilityName));
759     napi_set_named_property(env, objContext, "formName", CreateJsValue(env, formInstance.formName));
760     napi_set_named_property(env, objContext, "formUsageState", CreateJsValue(env, formInstance.formUsageState));
761     return objContext;
762 }
763 }  // namespace AbilityRuntime
764 }  // namespace OHOS
765