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