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
21 namespace OHOS {
22 namespace Wifi {
23 DEFINE_WIFILOG_LABEL("WifiNAPIUtils");
24
TraceFuncCall(std::string funcName)25 TraceFuncCall::TraceFuncCall(std::string funcName): m_funcName(funcName)
26 {
27 if (m_isTrace) {
28 m_startTime = std::chrono::steady_clock::now();
29 WIFI_LOGD("Call wifi func: %{public}s (start)", m_funcName.c_str());
30 }
31 }
32
~TraceFuncCall()33 TraceFuncCall::~TraceFuncCall()
34 {
35 if (m_isTrace) {
36 auto us = std::chrono::duration_cast<std::chrono::microseconds>
37 (std::chrono::steady_clock::now() - m_startTime).count();
38 constexpr int usForPerMs = 1000;
39 WIFI_LOGD("Call wifi func: %{public}s (end), time cost:%{public}lldus, %{public}lldms",
40 m_funcName.c_str(), us, us / usForPerMs);
41 }
42 }
43
UndefinedNapiValue(const napi_env & env)44 napi_value UndefinedNapiValue(const napi_env& env)
45 {
46 napi_value result;
47 napi_get_undefined(env, &result);
48 return result;
49 }
50
JsObjectToString(const napi_env & env,const napi_value & object,const char * fieldStr,const int bufLen,std::string & fieldRef)51 napi_value JsObjectToString(const napi_env& env, const napi_value& object,
52 const char* fieldStr, const int bufLen, std::string& fieldRef)
53 {
54 bool hasProperty = false;
55 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
56 if (hasProperty) {
57 napi_value field;
58 napi_valuetype valueType;
59
60 napi_get_named_property(env, object, fieldStr, &field);
61 NAPI_CALL(env, napi_typeof(env, field, &valueType));
62 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument type. String expected.");
63 if (bufLen <= 0) {
64 goto error;
65 }
66 char *buf = (char *)malloc(bufLen);
67 if (buf == nullptr) {
68 WIFI_LOGE("Js object to str malloc failed");
69 goto error;
70 }
71 (void)memset_s(buf, bufLen, 0, bufLen);
72 size_t result = 0;
73 NAPI_CALL(env, napi_get_value_string_utf8(env, field, buf, bufLen, &result));
74 fieldRef = buf;
75 free(buf);
76 buf = nullptr;
77 } else {
78 WIFI_LOGW("Js obj to str no property: %{public}s", fieldStr);
79 }
80
81 error:
82 return UndefinedNapiValue(env);
83 }
84
JsObjectToInt(const napi_env & env,const napi_value & object,const char * fieldStr,int & fieldRef)85 napi_value JsObjectToInt(const napi_env& env, const napi_value& object, const char* fieldStr, int& fieldRef)
86 {
87 bool hasProperty = false;
88 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
89 if (hasProperty) {
90 napi_value field;
91 napi_valuetype valueType;
92
93 napi_get_named_property(env, object, fieldStr, &field);
94 NAPI_CALL(env, napi_typeof(env, field, &valueType));
95 NAPI_ASSERT(env, valueType == napi_number, "Wrong argument type. Number expected.");
96 napi_get_value_int32(env, field, &fieldRef);
97 } else {
98 WIFI_LOGW("Js to int no property: %{public}s", fieldStr);
99 }
100 return UndefinedNapiValue(env);
101 }
102
JsObjectToBool(const napi_env & env,const napi_value & object,const char * fieldStr,bool & fieldRef)103 napi_value JsObjectToBool(const napi_env& env, const napi_value& object, const char* fieldStr, bool& fieldRef)
104 {
105 bool hasProperty = false;
106 NAPI_CALL(env, napi_has_named_property(env, object, fieldStr, &hasProperty));
107 if (hasProperty) {
108 napi_value field;
109 napi_valuetype valueType;
110
111 napi_get_named_property(env, object, fieldStr, &field);
112 NAPI_CALL(env, napi_typeof(env, field, &valueType));
113 NAPI_ASSERT(env, valueType == napi_boolean, "Wrong argument type. Bool expected.");
114 napi_get_value_bool(env, field, &fieldRef);
115 } else {
116 WIFI_LOGW("Js to bool no property: %{public}s", fieldStr);
117 }
118 return UndefinedNapiValue(env);
119 }
120
SetValueUtf8String(const napi_env & env,const char * fieldStr,const char * str,napi_value & result)121 napi_status SetValueUtf8String(const napi_env& env, const char* fieldStr, const char* str, napi_value& result)
122 {
123 napi_value value;
124 napi_status status = napi_create_string_utf8(env, str, NAPI_AUTO_LENGTH, &value);
125 if (status != napi_ok) {
126 WIFI_LOGE("Set value create utf8 string error! field: %{public}s", fieldStr);
127 return status;
128 }
129 status = napi_set_named_property(env, result, fieldStr, value);
130 if (status != napi_ok) {
131 WIFI_LOGE("Set utf8 string named property error! field: %{public}s", fieldStr);
132 }
133 return status;
134 }
135
SetValueInt32(const napi_env & env,const char * fieldStr,const int intValue,napi_value & result)136 napi_status SetValueInt32(const napi_env& env, const char* fieldStr, const int intValue, napi_value& result)
137 {
138 napi_value value;
139 napi_status status = napi_create_int32(env, intValue, &value);
140 if (status != napi_ok) {
141 WIFI_LOGE("Set value create int32 error! field: %{public}s", fieldStr);
142 return status;
143 }
144 status = napi_set_named_property(env, result, fieldStr, value);
145 if (status != napi_ok) {
146 WIFI_LOGE("Set int32 named property error! field: %{public}s", fieldStr);
147 }
148 return status;
149 }
150
SetValueUnsignedInt32(const napi_env & env,const char * fieldStr,const int intValue,napi_value & result)151 napi_status SetValueUnsignedInt32(const napi_env& env, const char* fieldStr, const int intValue, napi_value& result)
152 {
153 napi_value value;
154 napi_status status = napi_create_uint32(env, intValue, &value);
155 if (status != napi_ok) {
156 WIFI_LOGE("Set value create unsigned int32 error! field: %{public}s", fieldStr);
157 return status;
158 }
159 status = napi_set_named_property(env, result, fieldStr, value);
160 if (status != napi_ok) {
161 WIFI_LOGE("Set unsigned int32 named property error! field: %{public}s", fieldStr);
162 }
163 return status;
164 }
165
SetValueInt64(const napi_env & env,const char * fieldStr,const int64_t intValue,napi_value & result)166 napi_status SetValueInt64(const napi_env& env, const char* fieldStr, const int64_t intValue, napi_value& result)
167 {
168 napi_value value;
169 napi_status status = napi_create_int64(env, intValue, &value);
170 if (status != napi_ok) {
171 WIFI_LOGE("Set value create int64 error! field: %{public}s", fieldStr);
172 return status;
173 }
174 status = napi_set_named_property(env, result, fieldStr, value);
175 if (status != napi_ok) {
176 WIFI_LOGE("Set int64 named property error! field: %{public}s", fieldStr);
177 }
178 return status;
179 }
180
SetValueBool(const napi_env & env,const char * fieldStr,const bool boolvalue,napi_value & result)181 napi_status SetValueBool(const napi_env& env, const char* fieldStr, const bool boolvalue, napi_value& result)
182 {
183 napi_value value;
184 napi_status status = napi_get_boolean(env, boolvalue, &value);
185 if (status != napi_ok) {
186 WIFI_LOGE("Set value create boolean error! field: %{public}s", fieldStr);
187 return status;
188 }
189 status = napi_set_named_property(env, result, fieldStr, value);
190 if (status != napi_ok) {
191 WIFI_LOGE("Set boolean named property error! field: %{public}s", fieldStr);
192 }
193 return status;
194 }
195
InitAsyncCallBackEnv(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t nonCallbackArgNum)196 static napi_value InitAsyncCallBackEnv(const napi_env& env, AsyncContext *asyncContext,
197 const size_t argc, const napi_value *argv, const size_t nonCallbackArgNum)
198 {
199 for (size_t i = nonCallbackArgNum; i != argc; ++i) {
200 napi_valuetype valuetype;
201 NAPI_CALL(env, napi_typeof(env, argv[i], &valuetype));
202 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
203 napi_create_reference(env, argv[i], 1, &asyncContext->callback[i - nonCallbackArgNum]);
204 }
205 return nullptr;
206 }
207
InitAsyncPromiseEnv(const napi_env & env,AsyncContext * asyncContext,napi_value & promise)208 static napi_value InitAsyncPromiseEnv(const napi_env& env, AsyncContext *asyncContext, napi_value& promise)
209 {
210 napi_deferred deferred;
211 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
212 asyncContext->deferred = deferred;
213 return nullptr;
214 }
215
DoCallBackAsyncWork(const napi_env & env,AsyncContext * asyncContext)216 static napi_value DoCallBackAsyncWork(const napi_env& env, AsyncContext *asyncContext)
217 {
218 napi_create_async_work(
219 env,
220 nullptr,
221 asyncContext->resourceName,
222 [](napi_env env, void* data) {
223 if (data == nullptr) {
224 WIFI_LOGE("Async data parameter is null");
225 return;
226 }
227 AsyncContext *context = (AsyncContext *)data;
228 context->executeFunc(context);
229 },
230 [](napi_env env, napi_status status, void* data) {
231 if (data == nullptr) {
232 WIFI_LOGE("Async data parameter is null");
233 return;
234 }
235 AsyncContext *context = (AsyncContext *)data;
236 napi_value undefine;
237 napi_get_undefined(env, &undefine);
238 napi_value callback;
239 context->completeFunc(data);
240 constexpr int ARGS_TWO = 2;
241 napi_value result[ARGS_TWO] = {nullptr};
242 napi_create_uint32(env, context->errorCode, &result[0]);
243 result[1] = context->result;
244 if (context->errorCode == ERR_CODE_SUCCESS) {
245 napi_get_reference_value(env, context->callback[0], &callback);
246 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &undefine);
247 } else {
248 if (context->callback[1]) {
249 napi_get_reference_value(env, context->callback[1], &callback);
250 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &undefine);
251 } else {
252 WIFI_LOGE("Get callback func[1] is null");
253 }
254 }
255 if (context->callback[0] != nullptr) {
256 napi_delete_reference(env, context->callback[0]);
257 }
258 if (context->callback[1] != nullptr) {
259 napi_delete_reference(env, context->callback[1]);
260 }
261 napi_delete_async_work(env, context->work);
262 delete context;
263 },
264 (void *)asyncContext,
265 &asyncContext->work);
266 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
267 return UndefinedNapiValue(env);
268 }
269
DoPromiseAsyncWork(const napi_env & env,AsyncContext * asyncContext)270 static napi_value DoPromiseAsyncWork(const napi_env& env, AsyncContext *asyncContext)
271 {
272 napi_create_async_work(
273 env,
274 nullptr,
275 asyncContext->resourceName,
276 [](napi_env env, void *data) {
277 if (data == nullptr) {
278 WIFI_LOGE("Async data parameter is null");
279 return;
280 }
281 AsyncContext *context = (AsyncContext *)data;
282 context->executeFunc(context);
283 },
284 [](napi_env env, napi_status status, void *data) {
285 if (data == nullptr) {
286 WIFI_LOGE("Async data parameter is null");
287 return;
288 }
289 AsyncContext *context = (AsyncContext *)data;
290 context->completeFunc(data);
291 if (context->errorCode == ERR_CODE_SUCCESS) {
292 napi_resolve_deferred(context->env, context->deferred, context->result);
293 } else {
294 napi_reject_deferred(context->env, context->deferred, context->result);
295 }
296 napi_delete_async_work(env, context->work);
297 delete context;
298 },
299 (void *)asyncContext,
300 &asyncContext->work);
301 napi_queue_async_work(env, asyncContext->work);
302 return UndefinedNapiValue(env);
303 }
304
DoAsyncWork(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t nonCallbackArgNum)305 napi_value DoAsyncWork(const napi_env& env, AsyncContext *asyncContext,
306 const size_t argc, const napi_value *argv, const size_t nonCallbackArgNum)
307 {
308 if (argc > nonCallbackArgNum) {
309 InitAsyncCallBackEnv(env, asyncContext, argc, argv, nonCallbackArgNum);
310 return DoCallBackAsyncWork(env, asyncContext);
311 } else {
312 napi_value promise;
313 InitAsyncPromiseEnv(env, asyncContext, promise);
314 DoPromiseAsyncWork(env, asyncContext);
315 return promise;
316 }
317 }
318
JsAbilityGetBundleName()319 std::string JsAbilityGetBundleName()
320 {
321 std::shared_ptr<AbilityRuntime::Context> appContext = AbilityRuntime::Context::GetApplicationContext();
322 if (appContext == nullptr) {
323 WIFI_LOGE("Get boundle name context is null");
324 return "";
325 }
326 return appContext->GetBundleName();
327 }
328 } // namespace Wifi
329 } // namespace OHOS
330