• 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         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