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_util.h"
17 #include <codecvt>
18 #include <cstdio>
19 #include <climits>
20 #include <locale>
21 #include <string>
22
23 #include "hilog_wrapper.h"
24 #include "securec.h"
25 #include "usb_common.h"
26 #include "usb_errors.h"
27 #include "usb_napi_errors.h"
28 namespace OHOS {
29 namespace USB {
30 const int32_t MAX_STR_LENGTH = 1024;
JsValueToString(const napi_env & env,const napi_value & value,const int32_t bufLen,std::string & target)31 void NapiUtil::JsValueToString(const napi_env &env, const napi_value &value, const int32_t bufLen, std::string &target)
32 {
33 if (bufLen <= 0 || bufLen > MAX_STR_LENGTH) {
34 USB_HILOGE(MODULE_JS_NAPI, "string too long malloc failed");
35 return;
36 }
37 // 1 represent '\0'
38 int32_t actBufLen = bufLen + 1;
39 std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
40
41 errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
42 RETURN_IF_WITH_LOG(ret != EOK, "JsValueToString memset_s failed.");
43
44 size_t result = 0;
45 napi_get_value_string_utf8(env, value, buf.get(), actBufLen, &result);
46 target = buf.get();
47 }
48
JsObjectToString(const napi_env & env,const napi_value & object,std::string fieldStr,const int32_t bufLen,std::string & fieldRef)49 void NapiUtil::JsObjectToString(
50 const napi_env &env, const napi_value &object, std::string fieldStr, const int32_t bufLen, std::string &fieldRef)
51 {
52 if (bufLen <= 0) {
53 USB_HILOGE(MODULE_JS_NAPI, "invalid bufLen=%{public}d", bufLen);
54 return;
55 }
56
57 bool hasProperty = false;
58 napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
59 if (hasProperty) {
60 napi_value field;
61 napi_valuetype valueType;
62
63 napi_get_named_property(env, object, fieldStr.c_str(), &field);
64 napi_typeof(env, field, &valueType);
65 USB_ASSERT_RETURN_VOID(
66 env, valueType == napi_string, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be string.");
67 // 1 represent '\0'
68 int32_t actBufLen = bufLen + 1;
69 std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
70
71 errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
72 RETURN_IF_WITH_LOG(ret != EOK, "JsObjectToString memset_s failed.");
73
74 size_t result = 0;
75 napi_get_value_string_utf8(env, field, buf.get(), actBufLen, &result);
76 fieldRef = buf.get();
77 } else {
78 USB_HILOGW(MODULE_JS_NAPI, "js to str no property: %{public}s", fieldStr.c_str());
79 }
80 }
81
JsObjectGetProperty(const napi_env & env,const napi_value & object,std::string fieldStr,napi_value & value)82 bool NapiUtil::JsObjectGetProperty(
83 const napi_env &env, const napi_value &object, std::string fieldStr, napi_value &value)
84 {
85 bool hasProperty = false;
86 napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
87 if (hasProperty) {
88 napi_get_named_property(env, object, fieldStr.c_str(), &value);
89 } else {
90 USB_HILOGW(MODULE_JS_NAPI, "js object has no property: %{public}s", fieldStr.c_str());
91 }
92 return hasProperty;
93 }
94
JsObjectToBool(const napi_env & env,const napi_value & object,std::string fieldStr,bool & fieldRef)95 void NapiUtil::JsObjectToBool(const napi_env &env, const napi_value &object, std::string fieldStr, bool &fieldRef)
96 {
97 bool hasProperty = false;
98 napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
99 if (hasProperty) {
100 napi_value field;
101 napi_valuetype valueType;
102
103 napi_get_named_property(env, object, fieldStr.c_str(), &field);
104 napi_typeof(env, field, &valueType);
105 USB_ASSERT_RETURN_VOID(
106 env, valueType == napi_boolean, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be boolean.");
107 napi_get_value_bool(env, field, &fieldRef);
108 } else {
109 USB_HILOGW(MODULE_JS_NAPI, "js to boolean no property: %{public}s", fieldStr.c_str());
110 }
111 }
112
JsObjectToInt(const napi_env & env,const napi_value & object,std::string fieldStr,int32_t & fieldRef)113 void NapiUtil::JsObjectToInt(const napi_env &env, const napi_value &object, std::string fieldStr, int32_t &fieldRef)
114 {
115 bool hasProperty = false;
116 napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
117 if (hasProperty) {
118 napi_value field;
119 napi_valuetype valueType;
120
121 napi_get_named_property(env, object, fieldStr.c_str(), &field);
122 napi_typeof(env, field, &valueType);
123 USB_ASSERT_RETURN_VOID(
124 env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
125 napi_get_value_int32(env, field, &fieldRef);
126 } else {
127 USB_HILOGW(MODULE_JS_NAPI, "js to int32_t no property: %{public}s", fieldStr.c_str());
128 }
129 }
130
JsObjectToUint(const napi_env & env,const napi_value & object,const std::string & fieldStr,uint32_t & fieldRef)131 void NapiUtil::JsObjectToUint(
132 const napi_env &env, const napi_value &object, const std::string &fieldStr, uint32_t &fieldRef)
133 {
134 bool hasProperty = false;
135 napi_status status = napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
136 if (status != napi_ok || !hasProperty) {
137 USB_HILOGE(MODULE_JS_NAPI, "js to uint32_t no property: %{public}s", fieldStr.c_str());
138 return;
139 }
140
141 napi_value field = nullptr;
142 napi_valuetype valueType;
143
144 status = napi_get_named_property(env, object, fieldStr.c_str(), &field);
145 if (status != napi_ok) {
146 USB_HILOGE(MODULE_JS_NAPI, "get property failed: %{public}s", fieldStr.c_str());
147 return;
148 }
149
150 status = napi_typeof(env, field, &valueType);
151 if (status != napi_ok) {
152 USB_HILOGE(MODULE_JS_NAPI, "type error failed: %{public}s", fieldStr.c_str());
153 return;
154 }
155
156 USB_ASSERT_RETURN_VOID(
157 env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
158 status = napi_get_value_uint32(env, field, &fieldRef);
159 if (status != napi_ok) {
160 USB_HILOGE(MODULE_JS_NAPI, "get value failed: %{public}s", fieldStr.c_str());
161 }
162 }
163
JsObjectToUint(const napi_env & env,const napi_value & object,const std::string & fieldStr,uint8_t & fieldRef)164 void NapiUtil::JsObjectToUint(
165 const napi_env &env, const napi_value &object, const std::string &fieldStr, uint8_t &fieldRef)
166 {
167 uint32_t tmpValue = UINT_MAX;
168 JsObjectToUint(env, object, fieldStr, tmpValue);
169 if (tmpValue > SCHAR_MAX) {
170 USB_HILOGE(MODULE_JS_NAPI, "type error failed: uint32_t to uint8_t");
171 } else {
172 fieldRef = tmpValue;
173 }
174 }
175
JsUint8ArrayParse(const napi_env & env,const napi_value & object,uint8_t ** uint8Buffer,size_t & bufferSize,size_t & offset)176 bool NapiUtil::JsUint8ArrayParse(
177 const napi_env &env, const napi_value &object, uint8_t **uint8Buffer, size_t &bufferSize, size_t &offset)
178 {
179 bool isTypedArray = false;
180 if (napi_is_typedarray(env, object, &isTypedArray) != napi_ok || !isTypedArray) {
181 USB_ASSERT_RETURN_FALSE(env, isTypedArray, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be TypedArray.");
182 USB_HILOGW(MODULE_JS_NAPI, "invalid type");
183 return false;
184 }
185
186 napi_typedarray_type type;
187 napi_value buffer;
188
189 napi_status infoStatus = napi_get_typedarray_info(
190 env, object, &type, &bufferSize, reinterpret_cast<void **>(uint8Buffer), &buffer, &offset);
191 if (infoStatus != napi_ok) {
192 USB_HILOGW(MODULE_JS_NAPI, "get typedarray info failed, status: %{public}d", infoStatus);
193 return false;
194 }
195 USB_ASSERT_RETURN_FALSE(
196 env, type == napi_uint8_array, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be Uint8Array.");
197 USB_ASSERT_RETURN_FALSE(
198 env, bufferSize != 0, OHEC_COMMON_PARAM_ERROR, "The size of buffer must be a positive number.");
199 return true;
200 }
201
Uint8ArrayToJsValue(const napi_env & env,std::vector<uint8_t> & uint8Buffer,size_t bufferSize,napi_value & result)202 void NapiUtil::Uint8ArrayToJsValue(
203 const napi_env &env, std::vector<uint8_t> &uint8Buffer, size_t bufferSize, napi_value &result)
204 {
205 uint8_t *nativeArraybuffer = nullptr;
206 napi_value nativeValue = nullptr;
207 napi_create_arraybuffer(env, bufferSize, reinterpret_cast<void **>(&nativeArraybuffer), &nativeValue);
208
209 errno_t ret = memcpy_s(nativeArraybuffer, bufferSize, uint8Buffer.data(), bufferSize);
210 if (ret != EOK) {
211 USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed");
212 return;
213 }
214
215 napi_create_typedarray(env, napi_uint8_array, bufferSize, nativeValue, 0, &result);
216 }
217
SetValueUtf8String(const napi_env & env,std::string fieldStr,std::string str,napi_value & result)218 void NapiUtil::SetValueUtf8String(const napi_env &env, std::string fieldStr, std::string str, napi_value &result)
219 {
220 napi_value value;
221 napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &value);
222 napi_set_named_property(env, result, fieldStr.c_str(), value);
223 }
224
SetValueInt32(const napi_env & env,std::string fieldStr,const int32_t intValue,napi_value & result)225 void NapiUtil::SetValueInt32(const napi_env &env, std::string fieldStr, const int32_t intValue, napi_value &result)
226 {
227 napi_value value;
228 napi_create_int32(env, intValue, &value);
229 napi_set_named_property(env, result, fieldStr.c_str(), value);
230 }
231
SetValueUint32(const napi_env & env,const std::string & fieldStr,const uint32_t uintValue,napi_value & result)232 void NapiUtil::SetValueUint32(
233 const napi_env &env, const std::string &fieldStr, const uint32_t uintValue, napi_value &result)
234 {
235 napi_value value = nullptr;
236 napi_status status = napi_create_uint32(env, uintValue, &value);
237 if (status != napi_ok) {
238 USB_HILOGE(MODULE_JS_NAPI, "create uint32 failed:%{public}s", fieldStr.c_str());
239 return;
240 }
241
242 status = napi_set_named_property(env, result, fieldStr.c_str(), value);
243 if (status != napi_ok) {
244 USB_HILOGE(MODULE_JS_NAPI, "set property failed:%{public}s", fieldStr.c_str());
245 }
246 }
247
SetValueBool(const napi_env & env,std::string fieldStr,const bool boolValue,napi_value & result)248 void NapiUtil::SetValueBool(const napi_env &env, std::string fieldStr, const bool boolValue, napi_value &result)
249 {
250 napi_value value;
251 napi_get_boolean(env, boolValue, &value);
252 napi_set_named_property(env, result, fieldStr.c_str(), value);
253 }
254
255 } // namespace USB
256 } // namespace OHOS
257