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