1 /*
2 * Copyright (c) 2024 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_common_utils.h"
17
18 #include "napi/native_common.h"
19 #include "node_api.h"
20
21 #include "update_define.h"
22
23 namespace OHOS::UpdateEngine {
24 constexpr int32_t STRING_MAX_LENGTH = 400;
25
GetInt32(napi_env env,napi_value arg,const std::string & attrName,int32_t & intValue)26 int32_t NapiCommonUtils::GetInt32(napi_env env, napi_value arg, const std::string &attrName, int32_t &intValue)
27 {
28 bool result = false;
29 napi_status status = napi_has_named_property(env, arg, attrName.c_str(), &result);
30 if (result && (status == napi_ok)) {
31 napi_value value = nullptr;
32 napi_get_named_property(env, arg, attrName.c_str(), &value);
33 napi_get_value_int32(env, value, &intValue);
34 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
35 }
36 return CAST_INT(ClientStatus::CLIENT_FAIL);
37 }
38
GetBool(napi_env env,napi_value arg,const std::string & attrName,bool & value)39 int32_t NapiCommonUtils::GetBool(napi_env env, napi_value arg, const std::string &attrName, bool &value)
40 {
41 bool result = false;
42 napi_status status = napi_has_named_property(env, arg, attrName.c_str(), &result);
43 if (result && (status == napi_ok)) {
44 napi_value obj = nullptr;
45 napi_get_named_property(env, arg, attrName.c_str(), &obj);
46 napi_get_value_bool(env, obj, &value);
47 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
48 }
49 return CAST_INT(ClientStatus::CLIENT_FAIL);
50 }
51
GetString(napi_env env,napi_value arg,const std::string & attrName,std::string & strValue)52 int32_t NapiCommonUtils::GetString(napi_env env, napi_value arg, const std::string &attrName, std::string &strValue)
53 {
54 bool result = false;
55 napi_status status = napi_has_named_property(env, arg, attrName.c_str(), &result);
56 if (result && (status == napi_ok)) {
57 napi_value value = nullptr;
58 napi_get_named_property(env, arg, attrName.c_str(), &value);
59 return GetString(env, value, strValue);
60 }
61 return CAST_INT(ClientStatus::CLIENT_FAIL);
62 }
63
GetString(napi_env env,napi_value arg,std::string & strValue)64 int32_t NapiCommonUtils::GetString(napi_env env, napi_value arg, std::string &strValue)
65 {
66 napi_valuetype valuetype;
67 napi_status status = napi_typeof(env, arg, &valuetype);
68 PARAM_CHECK(status == napi_ok, return CAST_INT(ClientStatus::CLIENT_FAIL), "Failed to napi_typeof");
69 PARAM_CHECK(valuetype == napi_string, return CAST_INT(ClientStatus::CLIENT_INVALID_TYPE), "Invalid type");
70
71 std::vector<char> buff(STRING_MAX_LENGTH);
72 size_t copied;
73 status = napi_get_value_string_utf8(env, arg, static_cast<char*>(buff.data()), STRING_MAX_LENGTH, &copied);
74 PARAM_CHECK(status == napi_ok, return CAST_INT(ClientStatus::CLIENT_INVALID_TYPE), "Error get string");
75 strValue.assign(buff.data(), copied);
76 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
77 }
78
SetString(napi_env env,napi_value arg,const std::string & attrName,const std::string & string)79 int32_t NapiCommonUtils::SetString(napi_env env, napi_value arg, const std::string &attrName, const std::string &string)
80 {
81 napi_value value = nullptr;
82 napi_create_string_utf8(env, string.c_str(), string.length(), &value);
83 napi_set_named_property(env, arg, attrName.c_str(), value);
84 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
85 }
86
SetUint32(napi_env env,napi_value arg,const std::string & attrName,uint32_t intValue)87 int32_t NapiCommonUtils::SetUint32(napi_env env, napi_value arg, const std::string &attrName, uint32_t intValue)
88 {
89 napi_value infoStatus = nullptr;
90 napi_create_uint32(env, intValue, &infoStatus);
91 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
92 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
93 }
94
SetInt32(napi_env env,napi_value arg,const std::string & attrName,int32_t intValue)95 int32_t NapiCommonUtils::SetInt32(napi_env env, napi_value arg, const std::string &attrName, int32_t intValue)
96 {
97 napi_value infoStatus = nullptr;
98 napi_create_int32(env, intValue, &infoStatus);
99 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
100 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
101 }
102
SetInt64(napi_env env,napi_value arg,const std::string & attrName,int64_t intValue)103 int32_t NapiCommonUtils::SetInt64(napi_env env, napi_value arg, const std::string &attrName, int64_t intValue)
104 {
105 napi_value infoStatus = nullptr;
106 napi_create_int64(env, intValue, &infoStatus);
107 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
108 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
109 }
110
SetBool(napi_env env,napi_value arg,const std::string & attrName,bool value)111 int32_t NapiCommonUtils::SetBool(napi_env env, napi_value arg, const std::string &attrName, bool value)
112 {
113 napi_value infoStatus = nullptr;
114 napi_get_boolean(env, value, &infoStatus);
115 napi_set_named_property(env, arg, attrName.c_str(), infoStatus);
116 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
117 }
118
IsTypeOf(napi_env env,napi_value arg,napi_valuetype type)119 ClientStatus NapiCommonUtils::IsTypeOf(napi_env env, napi_value arg, napi_valuetype type)
120 {
121 napi_valuetype valueType;
122 napi_status status = napi_typeof(env, arg, &valueType);
123 PARAM_CHECK(status == napi_ok, return ClientStatus::CLIENT_FAIL, "Failed to napi_typeof");
124 PARAM_CHECK(valueType == type, return ClientStatus::CLIENT_INVALID_TYPE, "Not same napi type");
125 return ClientStatus::CLIENT_SUCCESS;
126 }
127
CreateReference(napi_env env,napi_value arg,uint32_t refcount,napi_ref & reference)128 ClientStatus NapiCommonUtils::CreateReference(napi_env env, napi_value arg, uint32_t refcount, napi_ref &reference)
129 {
130 napi_status status = napi_create_reference(env, arg, refcount, &reference);
131 PARAM_CHECK(status == napi_ok, return ClientStatus::CLIENT_FAIL, "Failed to create reference");
132 return ClientStatus::CLIENT_SUCCESS;
133 }
134
CreateUint32(napi_env env,uint32_t code)135 napi_value NapiCommonUtils::CreateUint32(napi_env env, uint32_t code)
136 {
137 napi_value value = nullptr;
138 if (napi_create_uint32(env, code, &value) != napi_ok) {
139 return nullptr;
140 }
141 return value;
142 }
143
CreateStringUtf8(napi_env env,const std::string & str)144 napi_value NapiCommonUtils::CreateStringUtf8(napi_env env, const std::string &str)
145 {
146 napi_value value = nullptr;
147 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
148 return nullptr;
149 }
150 return value;
151 }
152
CreateProperty(napi_env env,napi_value exports,const std::string & name,const std::vector<std::pair<std::string,napi_value>> & properties)153 void NapiCommonUtils::CreateProperty(napi_env env, napi_value exports, const std::string &name,
154 const std::vector<std::pair<std::string, napi_value>> &properties)
155 {
156 napi_value object = nullptr;
157 napi_status status = napi_create_object(env, &object);
158 if (status != napi_ok) {
159 ENGINE_LOGE("CreateObject, napi_create_object fail");
160 }
161 if (object == nullptr) {
162 return;
163 }
164 size_t size = properties.size();
165 napi_property_descriptor descriptors[size];
166 for (size_t pos = 0; pos < size; pos++) {
167 if (properties[pos].first.empty()) {
168 continue;
169 }
170 descriptors[pos] = DECLARE_NAPI_STATIC_PROPERTY(properties[pos].first.c_str(), properties[pos].second);
171 }
172 status = napi_define_properties(env, object, size, descriptors);
173 if (status != napi_ok) {
174 ENGINE_LOGE("DefineProperties, napi_define_properties fail");
175 }
176
177 status = napi_set_named_property(env, exports, name.c_str(), object);
178 if (status != napi_ok) {
179 ENGINE_LOGE("CreateProperty, napi_set_named_property fail");
180 }
181 }
182
NapiThrowParamError(napi_env env,std::vector<std::pair<std::string,std::string>> & paramInfos)183 void NapiCommonUtils::NapiThrowParamError(
184 napi_env env, std::vector<std::pair<std::string, std::string>> ¶mInfos)
185 {
186 BusinessError businessError;
187 CallResult errCode = CallResult::PARAM_ERR;
188 std::string errMsg = "BusinessError " + std::to_string(CAST_INT(errCode))
189 .append(": Parameter error. The type of { ").append(GetParamNames(paramInfos)).append(" }")
190 .append("must be { ").append(GetParamTypes(paramInfos)).append(" }.");
191 businessError.Build(errCode, errMsg);
192 napi_value msg = BuildThrowError(env, businessError);
193 napi_status status = napi_throw(env, msg);
194 PARAM_CHECK(status == napi_ok, return, "Failed to napi_throw %d", CAST_INT(status));
195 }
196
GetParamNames(std::vector<std::pair<std::string,std::string>> & strVector)197 std::string NapiCommonUtils::GetParamNames(std::vector<std::pair<std::string, std::string>> &strVector)
198 {
199 return ConvertVectorToStr(strVector, true);
200 }
201
GetParamTypes(std::vector<std::pair<std::string,std::string>> & strVector)202 std::string NapiCommonUtils::GetParamTypes(std::vector<std::pair<std::string, std::string>> &strVector)
203 {
204 return ConvertVectorToStr(strVector, false);
205 }
206
ConvertVectorToStr(std::vector<std::pair<std::string,std::string>> & strVector,bool isFirst)207 std::string NapiCommonUtils::ConvertVectorToStr(std::vector<std::pair<std::string, std::string>> &strVector,
208 bool isFirst)
209 {
210 std::string strValue;
211 for (auto &str : strVector) {
212 if (!strValue.empty()) {
213 strValue.append(", ");
214 }
215 if (isFirst) {
216 strValue.append(str.first);
217 } else {
218 strValue.append(str.second);
219 }
220 }
221 return strValue;
222 }
223
BuildThrowError(napi_env env,const BusinessError & businessError)224 napi_value NapiCommonUtils::BuildThrowError(napi_env env, const BusinessError &businessError)
225 {
226 napi_value message = nullptr;
227 napi_create_string_utf8(env, businessError.message.c_str(), NAPI_AUTO_LENGTH, &message);
228 napi_value error = nullptr;
229 napi_status status = napi_create_error(env, nullptr, message, &error);
230 PARAM_CHECK(status == napi_ok, return nullptr, "Failed to create napi_create_object %d",
231 CAST_INT(status));
232
233 SetInt32(env, error, "code", ConvertToErrorCode(businessError.errorNum));
234 SetString(env, error, "message", businessError.message);
235 BuildErrorMessages(env, error, "data", businessError.data);
236 return error;
237 }
238
BuildBusinessError(napi_env env,napi_value & obj,const BusinessError & businessError)239 int32_t NapiCommonUtils::BuildBusinessError(napi_env env, napi_value &obj, const BusinessError &businessError)
240 {
241 if (businessError.errorNum == CallResult::SUCCESS) {
242 // success, no need to set businessError
243 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
244 }
245 napi_status status = napi_create_object(env, &obj);
246 PARAM_CHECK(status == napi_ok, return CAST_INT(ClientStatus::CLIENT_INVALID_TYPE),
247 "Failed to create napi_create_object %d", CAST_INT(status));
248
249 SetString(env, obj, "message", businessError.message);
250 SetInt32(env, obj, "code", ConvertToErrorCode(businessError.errorNum));
251 BuildErrorMessages(env, obj, "data", businessError.data);
252 return CAST_INT(ClientStatus::CLIENT_SUCCESS);
253 }
254
ConvertToErrorCode(CallResult callResult)255 int32_t NapiCommonUtils::ConvertToErrorCode(CallResult callResult)
256 {
257 if (IsCommonError(callResult) || callResult == CallResult::SUCCESS) {
258 return CAST_INT(callResult);
259 } else {
260 return COMPONENT_ERR + CAST_INT(callResult);
261 }
262 }
263
IsCommonError(CallResult callResult)264 bool NapiCommonUtils::IsCommonError(CallResult callResult)
265 {
266 return callResult == CallResult::UN_SUPPORT || callResult == CallResult::NOT_SYSTEM_APP ||
267 callResult == CallResult::APP_NOT_GRANTED || callResult == CallResult::PARAM_ERR;
268 }
269
BuildErrorMessages(napi_env env,napi_value & obj,const std::string & name,const std::vector<ErrorMessage> & errorMessages)270 void NapiCommonUtils::BuildErrorMessages(napi_env env, napi_value &obj, const std::string &name,
271 const std::vector<ErrorMessage> &errorMessages)
272 {
273 size_t validErrorMsgCount = GetValidDataCount(errorMessages);
274 if (validErrorMsgCount == 0) {
275 return;
276 }
277
278 napi_value napiErrorMessages;
279 napi_create_array_with_length(env, validErrorMsgCount, &napiErrorMessages);
280 size_t index = 0;
281 for (size_t i = 0; (i < errorMessages.size()) && (index < validErrorMsgCount); i++) {
282 if (errorMessages[i].errorCode != 0) {
283 napi_value napiErrorMessage;
284 napi_create_object(env, &napiErrorMessage);
285 SetInt32(env, napiErrorMessage, "errorCode", errorMessages[i].errorCode);
286 SetString(env, napiErrorMessage, "errorMessage", errorMessages[i].errorMessage);
287 napi_set_element(env, napiErrorMessages, index, napiErrorMessage);
288 index++;
289 }
290 }
291 napi_set_named_property(env, obj, name.c_str(), napiErrorMessages);
292 }
293
GetValidDataCount(const std::vector<ErrorMessage> & list)294 size_t NapiCommonUtils::GetValidDataCount(const std::vector<ErrorMessage> &list)
295 {
296 size_t validDataCount = 0;
297 for (const auto &errorMessage : list) {
298 if (errorMessage.errorCode != 0) {
299 validDataCount++;
300 }
301 }
302 return validDataCount;
303 }
304
CheckNapiObjectType(napi_env env,const napi_value & arg)305 ClientStatus NapiCommonUtils::CheckNapiObjectType(napi_env env, const napi_value &arg)
306 {
307 napi_valuetype type = napi_undefined;
308 napi_status status = napi_typeof(env, arg, &type);
309 PARAM_CHECK(status == napi_ok, return ClientStatus::CLIENT_INVALID_TYPE, "Invalid argc %d",
310 static_cast<int32_t>(status));
311 PARAM_CHECK(type == napi_object, return ClientStatus::CLIENT_INVALID_TYPE, "Invalid argc %d",
312 static_cast<int32_t>(type))
313 return ClientStatus::CLIENT_SUCCESS;
314 }
315 } // namespace OHOS::UpdateEngine