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