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 ¶mName, 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 ¶mName, 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