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 "wifi_napi_utils.h"
17 #include "securec.h"
18 #include "wifi_logger.h"
19 #include "context.h"
20 #include "wifi_napi_errcode.h"
21
22 namespace OHOS {
23 namespace Wifi {
24 DEFINE_WIFILOG_LABEL("WifiNAPIUtils");
25
TraceFuncCall(std::string funcName)26 TraceFuncCall::TraceFuncCall(std::string funcName): m_funcName(funcName)
27 {
28 if (m_isTrace) {
29 m_startTime = std::chrono::steady_clock::now();
30 WIFI_LOGI("Call wifi func: %{public}s (start)", m_funcName.c_str());
31 }
32 }
33
~TraceFuncCall()34 TraceFuncCall::~TraceFuncCall()
35 {
36 if (m_isTrace) {
37 auto us = std::chrono::duration_cast<std::chrono::microseconds>
38 (std::chrono::steady_clock::now() - m_startTime).count();
39 constexpr int usForPerMs = 1000;
40 WIFI_LOGI("Call wifi func: %{public}s (end), time cost:%{public}lldus, %{public}lldms",
41 m_funcName.c_str(), us, us / usForPerMs);
42 }
43 }
44
UndefinedNapiValue(const napi_env & env)45 napi_value UndefinedNapiValue(const napi_env& env)
46 {
47 napi_value result;
48 napi_get_undefined(env, &result);
49 return result;
50 }
51
CreateInt32(const napi_env & env)52 napi_value CreateInt32(const napi_env& env)
53 {
54 int32_t value = 1;
55 napi_value result = nullptr;
56 napi_create_int32(env, value, &result);
57 return result;
58 }
59
JsObjectToString(const napi_env & env,const napi_value & object,const char * fieldStr,const int bufLen,std::string & fieldRef)60 napi_value JsObjectToString(const napi_env& env, const napi_value& object,
61 const char* fieldStr, const int bufLen, std::string& fieldRef)
62 {
63 bool hasProperty = false;
64 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
65 if (hasProperty) {
66 napi_value field;
67 napi_valuetype valueType;
68
69 napi_get_named_property(env, object, fieldStr, &field);
70 NAPI_CALL(env, napi_typeof(env, field, &valueType));
71 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument type. String expected.");
72 if (bufLen <= 0) {
73 goto error;
74 }
75 char *buf = (char *)malloc(bufLen);
76 if (buf == nullptr) {
77 WIFI_LOGE("Js object to str malloc failed");
78 goto error;
79 }
80 (void)memset_s(buf, bufLen, 0, bufLen);
81 size_t result = 0;
82 NAPI_CALL(env, napi_get_value_string_utf8(env, field, buf, bufLen, &result));
83 fieldRef = buf;
84 free(buf);
85 buf = nullptr;
86 } else {
87 WIFI_LOGW("Js obj to str no property: %{public}s", fieldStr);
88 }
89
90 error:
91 return UndefinedNapiValue(env);
92 }
93
JsObjectToInt(const napi_env & env,const napi_value & object,const char * fieldStr,int & fieldRef)94 napi_value JsObjectToInt(const napi_env& env, const napi_value& object, const char* fieldStr, int& fieldRef)
95 {
96 bool hasProperty = false;
97 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
98 if (hasProperty) {
99 napi_value field;
100 napi_valuetype valueType;
101
102 napi_get_named_property(env, object, fieldStr, &field);
103 NAPI_CALL(env, napi_typeof(env, field, &valueType));
104 NAPI_ASSERT(env, valueType == napi_number, "Wrong argument type. Number expected.");
105 napi_get_value_int32(env, field, &fieldRef);
106 } else {
107 WIFI_LOGW("Js to int no property: %{public}s", fieldStr);
108 }
109 return UndefinedNapiValue(env);
110 }
111
JsObjectToUint(const napi_env & env,const napi_value & object,const char * fieldStr,uint32_t & fieldRef)112 napi_value JsObjectToUint(const napi_env& env, const napi_value& object, const char* fieldStr, uint32_t& fieldRef)
113 {
114 bool hasProperty = false;
115 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
116 if (hasProperty) {
117 napi_value field;
118 napi_valuetype valueType;
119
120 napi_get_named_property(env, object, fieldStr, &field);
121 NAPI_CALL(env, napi_typeof(env, field, &valueType));
122 NAPI_ASSERT(env, valueType == napi_number, "Wrong argument type. Number expected.");
123 napi_get_value_uint32(env, field, &fieldRef);
124 } else {
125 WIFI_LOGW("Js to int no property: %{public}s", fieldStr);
126 }
127 return UndefinedNapiValue(env);
128 }
129
JsObjectToBool(const napi_env & env,const napi_value & object,const char * fieldStr,bool & fieldRef)130 napi_value JsObjectToBool(const napi_env& env, const napi_value& object, const char* fieldStr, bool& fieldRef)
131 {
132 bool hasProperty = false;
133 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
134 if (hasProperty) {
135 napi_value field;
136 napi_valuetype valueType;
137
138 napi_get_named_property(env, object, fieldStr, &field);
139 NAPI_CALL(env, napi_typeof(env, field, &valueType));
140 NAPI_ASSERT(env, valueType == napi_boolean, "Wrong argument type. Bool expected.");
141 napi_get_value_bool(env, field, &fieldRef);
142 } else {
143 WIFI_LOGW("Js to bool no property: %{public}s", fieldStr);
144 }
145 return UndefinedNapiValue(env);
146 }
147
JsObjectToU8Vector(const napi_env & env,const napi_value & object,const char * fieldStr)148 std::vector<uint8_t> JsObjectToU8Vector(const napi_env& env, const napi_value& object, const char* fieldStr)
149 {
150 bool hasProperty = false;
151 NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), {});
152 if (!hasProperty) {
153 WIFI_LOGW("JsObjectToU8Vector, Js to U8Vector no property: %{public}s", fieldStr);
154 return {};
155 }
156
157 bool isTypedArray = false;
158 if (napi_is_typedarray(env, object, &isTypedArray) != napi_ok || !isTypedArray) {
159 WIFI_LOGW("JsObjectToU8Vector, property is not typedarray: %{public}s", fieldStr);
160 return {};
161 }
162
163 size_t length = 0;
164 size_t offset = 0;
165 napi_typedarray_type type;
166 napi_value buffer = nullptr;
167 NAPI_CALL_BASE(env, napi_get_typedarray_info(env, object, &type, &length, nullptr, &buffer, &offset), {});
168 if (type != napi_uint8_array || buffer == nullptr) {
169 WIFI_LOGW("JsObjectToU8Vector, %{public}s, buffer is nullptr: %{public}d",
170 fieldStr, (int)(buffer == nullptr));
171 return {};
172 }
173
174 size_t total = 0;
175 uint8_t *data = nullptr;
176 NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
177 length = std::min<size_t>(length, total - offset);
178 std::vector<uint8_t> result(length);
179 int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
180 if (retCode != 0) {
181 WIFI_LOGW("JsObjectToU8Vector, memcpy_s return fail: %{public}d", retCode);
182 return {};
183 }
184 return result;
185 }
186
SetValueUtf8String(const napi_env & env,const char * fieldStr,const char * str,napi_value & result,size_t strLen)187 napi_status SetValueUtf8String(const napi_env& env, const char* fieldStr, const char* str,
188 napi_value& result, size_t strLen)
189 {
190 napi_value value;
191 size_t len = strLen;
192 napi_status status = napi_create_string_utf8(env, str, len, &value);
193 if (status != napi_ok) {
194 WIFI_LOGE("Set value create utf8 string error! field: %{public}s", fieldStr);
195 return status;
196 }
197 status = napi_set_named_property(env, result, fieldStr, value);
198 if (status != napi_ok) {
199 WIFI_LOGE("Set utf8 string named property error! field: %{public}s", fieldStr);
200 }
201 return status;
202 }
203
SetValueUtf8String(const napi_env & env,const std::string & fieldStr,const std::string & valueStr,napi_value & result)204 napi_status SetValueUtf8String(const napi_env& env, const std::string &fieldStr, const std::string &valueStr,
205 napi_value& result)
206 {
207 WIFI_LOGD("SetValueUtf8String, fieldStr: %{public}s, valueStr: %{public}s",
208 fieldStr.c_str(), valueStr.c_str());
209 napi_value value;
210 size_t len = valueStr.length();
211 napi_status status = napi_create_string_utf8(env, valueStr.c_str(), len, &value);
212 if (status != napi_ok) {
213 WIFI_LOGE("Set value create utf8 string error! field: %{public}s", fieldStr.c_str());
214 return status;
215 }
216 status = napi_set_named_property(env, result, fieldStr.c_str(), value);
217 if (status != napi_ok) {
218 WIFI_LOGE("Set utf8 string named property error! field: %{public}s", fieldStr.c_str());
219 }
220 return status;
221 }
222
SetValueInt32(const napi_env & env,const char * fieldStr,const int intValue,napi_value & result)223 napi_status SetValueInt32(const napi_env& env, const char* fieldStr, const int intValue, napi_value& result)
224 {
225 napi_value value;
226 napi_status status = napi_create_int32(env, intValue, &value);
227 if (status != napi_ok) {
228 WIFI_LOGE("Set value create int32 error! field: %{public}s", fieldStr);
229 return status;
230 }
231 status = napi_set_named_property(env, result, fieldStr, value);
232 if (status != napi_ok) {
233 WIFI_LOGE("Set int32 named property error! field: %{public}s", fieldStr);
234 }
235 return status;
236 }
237
SetValueUnsignedInt32(const napi_env & env,const char * fieldStr,const int intValue,napi_value & result)238 napi_status SetValueUnsignedInt32(const napi_env& env, const char* fieldStr, const int intValue, napi_value& result)
239 {
240 napi_value value;
241 napi_status status = napi_create_uint32(env, intValue, &value);
242 if (status != napi_ok) {
243 WIFI_LOGE("Set value create unsigned int32 error! field: %{public}s", fieldStr);
244 return status;
245 }
246 status = napi_set_named_property(env, result, fieldStr, value);
247 if (status != napi_ok) {
248 WIFI_LOGE("Set unsigned int32 named property error! field: %{public}s", fieldStr);
249 }
250 return status;
251 }
252
SetValueInt64(const napi_env & env,const char * fieldStr,const int64_t intValue,napi_value & result)253 napi_status SetValueInt64(const napi_env& env, const char* fieldStr, const int64_t intValue, napi_value& result)
254 {
255 napi_value value;
256 napi_status status = napi_create_int64(env, intValue, &value);
257 if (status != napi_ok) {
258 WIFI_LOGE("Set value create int64 error! field: %{public}s", fieldStr);
259 return status;
260 }
261 status = napi_set_named_property(env, result, fieldStr, value);
262 if (status != napi_ok) {
263 WIFI_LOGE("Set int64 named property error! field: %{public}s", fieldStr);
264 }
265 return status;
266 }
267
SetValueBool(const napi_env & env,const char * fieldStr,const bool boolvalue,napi_value & result)268 napi_status SetValueBool(const napi_env& env, const char* fieldStr, const bool boolvalue, napi_value& result)
269 {
270 napi_value value;
271 napi_status status = napi_get_boolean(env, boolvalue, &value);
272 if (status != napi_ok) {
273 WIFI_LOGE("Set value create boolean error! field: %{public}s", fieldStr);
274 return status;
275 }
276 status = napi_set_named_property(env, result, fieldStr, value);
277 if (status != napi_ok) {
278 WIFI_LOGE("Set boolean named property error! field: %{public}s", fieldStr);
279 }
280 return status;
281 }
282
InitAsyncCallBackEnv(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t nonCallbackArgNum)283 static napi_value InitAsyncCallBackEnv(const napi_env& env, AsyncContext *asyncContext,
284 const size_t argc, const napi_value *argv, const size_t nonCallbackArgNum)
285 {
286 for (size_t i = nonCallbackArgNum; i != argc; ++i) {
287 napi_valuetype valuetype;
288 NAPI_CALL(env, napi_typeof(env, argv[i], &valuetype));
289 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
290 napi_create_reference(env, argv[i], 1, &asyncContext->callback[i - nonCallbackArgNum]);
291 }
292 return nullptr;
293 }
294
InitAsyncPromiseEnv(const napi_env & env,AsyncContext * asyncContext,napi_value & promise)295 static napi_value InitAsyncPromiseEnv(const napi_env& env, AsyncContext *asyncContext, napi_value& promise)
296 {
297 napi_deferred deferred;
298 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
299 asyncContext->deferred = deferred;
300 return nullptr;
301 }
302
DoCallBackAsyncWork(const napi_env & env,AsyncContext * asyncContext)303 static napi_value DoCallBackAsyncWork(const napi_env& env, AsyncContext *asyncContext)
304 {
305 napi_create_async_work(
306 env,
307 nullptr,
308 asyncContext->resourceName,
309 [](napi_env env, void* data) {
310 if (data == nullptr) {
311 WIFI_LOGE("Async data parameter is null");
312 return;
313 }
314 AsyncContext *context = (AsyncContext *)data;
315 context->executeFunc(context);
316 },
317 [](napi_env env, napi_status status, void* data) {
318 if (data == nullptr) {
319 WIFI_LOGE("Async data parameter is null");
320 return;
321 }
322 AsyncContext *context = (AsyncContext *)data;
323 context->completeFunc(data);
324 HandleCallbackErrCode(env, *context);
325 if (context->callback[0] != nullptr) {
326 napi_delete_reference(env, context->callback[0]);
327 }
328 if (context->callback[1] != nullptr) {
329 napi_delete_reference(env, context->callback[1]);
330 }
331 napi_delete_async_work(env, context->work);
332 delete context;
333 },
334 (void *)asyncContext,
335 &asyncContext->work);
336 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
337 return UndefinedNapiValue(env);
338 }
339
DoPromiseAsyncWork(const napi_env & env,AsyncContext * asyncContext)340 static napi_value DoPromiseAsyncWork(const napi_env& env, AsyncContext *asyncContext)
341 {
342 napi_create_async_work(
343 env,
344 nullptr,
345 asyncContext->resourceName,
346 [](napi_env env, void *data) {
347 if (data == nullptr) {
348 WIFI_LOGE("Async data parameter is null");
349 return;
350 }
351 AsyncContext *context = (AsyncContext *)data;
352 context->executeFunc(context);
353 },
354 [](napi_env env, napi_status status, void *data) {
355 if (data == nullptr) {
356 WIFI_LOGE("Async data parameter is null");
357 return;
358 }
359 AsyncContext *context = (AsyncContext *)data;
360 context->completeFunc(data);
361 HandlePromiseErrCode(env, *context);
362 napi_delete_async_work(env, context->work);
363 delete context;
364 },
365 (void *)asyncContext,
366 &asyncContext->work);
367 napi_queue_async_work(env, asyncContext->work);
368 return UndefinedNapiValue(env);
369 }
370
DoAsyncWork(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t nonCallbackArgNum)371 napi_value DoAsyncWork(const napi_env& env, AsyncContext *asyncContext,
372 const size_t argc, const napi_value *argv, const size_t nonCallbackArgNum)
373 {
374 if (argc > nonCallbackArgNum) {
375 InitAsyncCallBackEnv(env, asyncContext, argc, argv, nonCallbackArgNum);
376 return DoCallBackAsyncWork(env, asyncContext);
377 } else {
378 napi_value promise;
379 InitAsyncPromiseEnv(env, asyncContext, promise);
380 DoPromiseAsyncWork(env, asyncContext);
381 return promise;
382 }
383 }
384
SetNamedPropertyByInteger(napi_env env,napi_value dstObj,int32_t objName,const char * propName)385 void SetNamedPropertyByInteger(napi_env env, napi_value dstObj, int32_t objName, const char *propName)
386 {
387 napi_value prop = nullptr;
388 if (napi_create_int32(env, objName, &prop) == napi_ok) {
389 napi_set_named_property(env, dstObj, propName, prop);
390 }
391 }
392 } // namespace Wifi
393 } // namespace OHOS
394