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