• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>> &paramInfos)
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