1 /*
2  * Copyright (C) 2021-2023 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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_utils"
17 #endif
18 
19 #include "napi_bluetooth_utils.h"
20 #include <algorithm>
21 #include <functional>
22 #include <optional>
23 #include "bluetooth_log.h"
24 #include "bluetooth_utils.h"
25 #include "event_handler.h"  // libeventhandler
26 #include "event_runner.h"  // libeventhandler
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "napi_bluetooth_error.h"
30 #include "napi_bluetooth_spp_client.h"
31 #include "../parser/napi_parser_utils.h"
32 #include "securec.h"
33 
34 namespace OHOS {
35 namespace Bluetooth {
36 using namespace std;
37 
GetCallbackErrorValue(napi_env env,int errCode)38 napi_value GetCallbackErrorValue(napi_env env, int errCode)
39 {
40     HILOGE("errCode: %{public}d", errCode);
41     napi_value result = NapiGetNull(env);
42     napi_value eCode = NapiGetNull(env);
43     if (errCode == BT_NO_ERROR) {
44         return result;
45     }
46     NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
47     NAPI_CALL(env, napi_create_object(env, &result));
48     NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
49 
50     std::string errMsg = GetNapiErrMsg(env, errCode);
51     napi_value message = nullptr;
52     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
53     napi_set_named_property(env, result, "message", message);
54     return result;
55 }
56 
GetCallbackInfoByType(const std::string & type)57 std::shared_ptr<BluetoothCallbackInfo> GetCallbackInfoByType(const std::string &type)
58 {
59     std::lock_guard<std::mutex> lock(g_observerMutex);
60     std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> observers = GetObserver();
61     if (!observers[type]) {
62         return nullptr;
63     }
64     return observers[type];
65 }
66 
ParseString(napi_env env,string & param,napi_value args)67 bool ParseString(napi_env env, string &param, napi_value args)
68 {
69     napi_valuetype valuetype;
70     napi_typeof(env, args, &valuetype);
71 
72     if (valuetype != napi_string) {
73         HILOGE("Wrong argument type(%{public}d). String expected.", valuetype);
74         return false;
75     }
76     size_t size = 0;
77 
78     if (napi_get_value_string_utf8(env, args, nullptr, 0, &size) != napi_ok) {
79         HILOGE("can not get string size");
80         param = "";
81         return false;
82     }
83     param.reserve(size + 1);
84     param.resize(size);
85     if (napi_get_value_string_utf8(env, args, param.data(), (size + 1), &size) != napi_ok) {
86         HILOGE("can not get string value");
87         param = "";
88         return false;
89     }
90     return true;
91 }
92 
ParseInt32(napi_env env,int32_t & param,napi_value args)93 bool ParseInt32(napi_env env, int32_t &param, napi_value args)
94 {
95     napi_valuetype valuetype;
96     napi_typeof(env, args, &valuetype);
97     if (valuetype != napi_number) {
98         HILOGE("Wrong argument type(%{public}d). Int32 expected.", valuetype);
99         return false;
100     }
101     napi_get_value_int32(env, args, &param);
102     return true;
103 }
104 
ParseBool(napi_env env,bool & param,napi_value args)105 bool ParseBool(napi_env env, bool &param, napi_value args)
106 {
107     napi_valuetype valuetype;
108     napi_typeof(env, args, &valuetype);
109 
110     if (valuetype != napi_boolean) {
111         HILOGE("Wrong argument type(%{public}d). bool expected.", valuetype);
112         return false;
113     }
114     napi_get_value_bool(env, args, &param);
115     return true;
116 }
117 
118 
ParseArrayBuffer(napi_env env,uint8_t ** data,size_t & size,napi_value args)119 bool ParseArrayBuffer(napi_env env, uint8_t** data, size_t &size, napi_value args)
120 {
121     napi_status status;
122     napi_valuetype valuetype;
123     napi_typeof(env, args, &valuetype);
124 
125     if (valuetype != napi_object) {
126         HILOGE("Wrong argument type(%{public}d). object expected.", valuetype);
127         return false;
128     }
129 
130     status = napi_get_arraybuffer_info(env, args, reinterpret_cast<void**>(data), &size);
131     if (status != napi_ok) {
132         HILOGE("can not get arraybuffer, error is %{public}d", status);
133         return false;
134     }
135     HILOGI("arraybuffer size is %{public}zu", size);
136     return true;
137 }
138 
ConvertOppTransferInformationToJS(napi_env env,napi_value result,const BluetoothOppTransferInformation & transferInformation)139 napi_status ConvertOppTransferInformationToJS(napi_env env, napi_value result,
140     const BluetoothOppTransferInformation& transferInformation)
141 {
142     HILOGI("ConvertOppTransferInformationToJS called");
143     napi_value id;
144     napi_create_int32(env, transferInformation.GetId(), &id);
145     napi_set_named_property(env, result, "id", id);
146 
147     napi_value fileName;
148     napi_create_string_utf8(env, transferInformation.GetFileName().c_str(), NAPI_AUTO_LENGTH, &fileName);
149     napi_set_named_property(env, result, "fileName", fileName);
150 
151     napi_value filePath;
152     napi_create_string_utf8(env, transferInformation.GetFilePath().c_str(), NAPI_AUTO_LENGTH, &filePath);
153     napi_set_named_property(env, result, "filePath", filePath);
154 
155     napi_value mimeType;
156     napi_create_string_utf8(env, transferInformation.GetMimeType().c_str(), NAPI_AUTO_LENGTH, &mimeType);
157     napi_set_named_property(env, result, "mimeType", mimeType);
158 
159     napi_value deviceName;
160     napi_create_string_utf8(env, transferInformation.GetDeviceName().c_str(), NAPI_AUTO_LENGTH, &deviceName);
161     napi_set_named_property(env, result, "deviceName", deviceName);
162 
163     napi_value deviceAddress;
164     napi_create_string_utf8(env, transferInformation.GetDeviceAddress().c_str(), NAPI_AUTO_LENGTH, &deviceAddress);
165     napi_set_named_property(env, result, "deviceAddress", deviceAddress);
166 
167     napi_value direction;
168     napi_create_int32(env, transferInformation.GetDirection(), &direction);
169     napi_set_named_property(env, result, "direction", direction);
170 
171     napi_value status;
172     napi_create_int32(env, transferInformation.GetStatus(), &status);
173     napi_set_named_property(env, result, "status", status);
174 
175     napi_value failedReason;
176     napi_create_int32(env, transferInformation.GetFailedReason(), &failedReason);
177     napi_set_named_property(env, result, "failedReason", failedReason);
178 
179     napi_value timeStamp;
180     napi_create_int64(env, transferInformation.GetTimeStamp(), &timeStamp);
181     napi_set_named_property(env, result, "timeStamp", timeStamp);
182 
183     napi_value currentBytes;
184     napi_create_int64(env, transferInformation.GetCurrentBytes(), &currentBytes);
185     napi_set_named_property(env, result, "currentBytes", currentBytes);
186 
187     napi_value totalBytes;
188     napi_create_int64(env, transferInformation.GetTotalBytes(), &totalBytes);
189     napi_set_named_property(env, result, "totalBytes", totalBytes);
190 
191     return napi_ok;
192 }
193 
ConvertStringVectorToJS(napi_env env,napi_value result,std::vector<std::string> & stringVector)194 napi_status ConvertStringVectorToJS(napi_env env, napi_value result, std::vector<std::string>& stringVector)
195 {
196     HILOGI("vector size: %{public}zu", stringVector.size());
197     size_t idx = 0;
198 
199     if (stringVector.empty()) {
200         return napi_ok;
201     }
202 
203     for (auto& str : stringVector) {
204         napi_value obj = nullptr;
205         NAPI_BT_CALL_RETURN(napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &obj));
206         NAPI_BT_CALL_RETURN(napi_set_element(env, result, idx, obj));
207         idx++;
208     }
209     return napi_ok;
210 }
211 
ConvertStateChangeParamToJS(napi_env env,napi_value result,const std::string & device,int state,int cause)212 void ConvertStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state, int cause)
213 {
214     napi_value deviceId = nullptr;
215     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
216     napi_set_named_property(env, result, "deviceId", deviceId);
217 
218     napi_value profileState = nullptr;
219     napi_create_int32(env, GetProfileConnectionState(state), &profileState);
220     napi_set_named_property(env, result, "state", profileState);
221 
222     napi_value stateChangeCause = nullptr;
223     napi_create_int32(env, cause, &stateChangeCause);
224     napi_set_named_property(env, result, "cause", stateChangeCause);
225 }
226 
ConvertScoStateChangeParamToJS(napi_env env,napi_value result,const std::string & device,int state)227 void ConvertScoStateChangeParamToJS(napi_env env, napi_value result, const std::string &device, int state)
228 {
229     napi_value deviceId = nullptr;
230     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
231     napi_set_named_property(env, result, "deviceId", deviceId);
232 
233     napi_value profileState = nullptr;
234     napi_create_int32(env, GetScoConnectionState(state), &profileState);
235     napi_set_named_property(env, result, "state", profileState);
236 }
237 
ConvertUuidsVectorToJS(napi_env env,napi_value result,const std::vector<std::string> & uuids)238 void ConvertUuidsVectorToJS(napi_env env, napi_value result, const std::vector<std::string> &uuids)
239 {
240     HILOGD("enter");
241     size_t idx = 0;
242 
243     if (uuids.empty()) {
244         return;
245     }
246     HILOGI("size: %{public}zu", uuids.size());
247     for (auto& uuid : uuids) {
248         napi_value uuidValue = nullptr;
249         napi_create_string_utf8(env, uuid.c_str(), NAPI_AUTO_LENGTH, &uuidValue);
250         napi_set_element(env, result, idx, uuidValue);
251         idx++;
252     }
253 }
254 
SetNamedPropertyByInteger(napi_env env,napi_value dstObj,int32_t objName,const char * propName)255 void SetNamedPropertyByInteger(napi_env env, napi_value dstObj, int32_t objName, const char *propName)
256 {
257     napi_value prop = nullptr;
258     if (napi_create_int32(env, objName, &prop) == napi_ok) {
259         napi_set_named_property(env, dstObj, propName, prop);
260     }
261 }
262 
SetNamedPropertyByString(napi_env env,napi_value dstObj,const std::string & strValue,const char * propName)263 void SetNamedPropertyByString(napi_env env, napi_value dstObj, const std::string &strValue, const char *propName)
264 {
265     napi_value prop = nullptr;
266     if (napi_create_string_utf8(env, strValue.c_str(), NAPI_AUTO_LENGTH, &prop) == napi_ok) {
267         napi_set_named_property(env, dstObj, propName, prop);
268     }
269 }
270 
NapiGetNull(napi_env env)271 napi_value NapiGetNull(napi_env env)
272 {
273     napi_value result = nullptr;
274     napi_get_null(env, &result);
275     return result;
276 }
277 
NapiGetBooleanFalse(napi_env env)278 napi_value NapiGetBooleanFalse(napi_env env)
279 {
280     napi_value result = nullptr;
281     napi_get_boolean(env, false, &result);
282     return result;
283 }
284 
NapiGetBooleanTrue(napi_env env)285 napi_value NapiGetBooleanTrue(napi_env env)
286 {
287     napi_value result = nullptr;
288     napi_get_boolean(env, true, &result);
289     return result;
290 }
291 
NapiGetBooleanRet(napi_env env,bool ret)292 napi_value NapiGetBooleanRet(napi_env env, bool ret)
293 {
294     napi_value result = nullptr;
295     napi_get_boolean(env, ret, &result);
296     return result;
297 }
298 
NapiGetUndefinedRet(napi_env env)299 napi_value NapiGetUndefinedRet(napi_env env)
300 {
301     napi_value ret = nullptr;
302     napi_get_undefined(env, &ret);
303     return ret;
304 }
305 
NapiGetInt32Ret(napi_env env,int32_t res)306 napi_value NapiGetInt32Ret(napi_env env, int32_t res)
307 {
308     napi_value ret = nullptr;
309     napi_create_int32(env, res, &ret);
310     return ret;
311 }
312 
GetObserver()313 std::map<std::string, std::shared_ptr<BluetoothCallbackInfo>> GetObserver()
314 {
315     return g_Observer;
316 }
317 
GetSysBLEObserver()318 const sysBLEMap &GetSysBLEObserver()
319 {
320     return g_sysBLEObserver;
321 }
322 
GetProfileConnectionState(int state)323 int GetProfileConnectionState(int state)
324 {
325     int32_t profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
326     switch (state) {
327         case static_cast<int32_t>(BTConnectState::CONNECTING):
328             HILOGD("STATE_CONNECTING(1)");
329             profileConnectionState = ProfileConnectionState::STATE_CONNECTING;
330             break;
331         case static_cast<int32_t>(BTConnectState::CONNECTED):
332             HILOGD("STATE_CONNECTED(2)");
333             profileConnectionState = ProfileConnectionState::STATE_CONNECTED;
334             break;
335         case static_cast<int32_t>(BTConnectState::DISCONNECTING):
336             HILOGD("STATE_DISCONNECTING(3)");
337             profileConnectionState = ProfileConnectionState::STATE_DISCONNECTING;
338             break;
339         case static_cast<int32_t>(BTConnectState::DISCONNECTED):
340             HILOGD("STATE_DISCONNECTED(0)");
341             profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
342             break;
343         default:
344             break;
345     }
346     return profileConnectionState;
347 }
348 
GetProfileId(int profile)349 uint32_t GetProfileId(int profile)
350 {
351     uint32_t profileId = 0;
352     switch (profile) {
353         case static_cast<int32_t>(ProfileId::PROFILE_A2DP_SINK):
354             HILOGD("PROFILE_ID_A2DP_SINK");
355             profileId = PROFILE_ID_A2DP_SINK;
356             break;
357         case static_cast<int32_t>(ProfileId::PROFILE_A2DP_SOURCE):
358             HILOGD("PROFILE_ID_A2DP_SRC");
359             profileId = PROFILE_ID_A2DP_SRC;
360             break;
361         case static_cast<int32_t>(ProfileId::PROFILE_AVRCP_CT):
362             HILOGD("PROFILE_ID_AVRCP_CT");
363             profileId = PROFILE_ID_AVRCP_CT;
364             break;
365         case static_cast<int32_t>(ProfileId::PROFILE_AVRCP_TG):
366             HILOGD("PROFILE_ID_AVRCP_TG");
367             profileId = PROFILE_ID_AVRCP_TG;
368             break;
369         case static_cast<int32_t>(ProfileId::PROFILE_HANDS_FREE_AUDIO_GATEWAY):
370             HILOGD("PROFILE_ID_HFP_AG");
371             profileId = PROFILE_ID_HFP_AG;
372             break;
373         case static_cast<int32_t>(ProfileId::PROFILE_HANDS_FREE_UNIT):
374             HILOGD("PROFILE_ID_HFP_HF");
375             profileId = PROFILE_ID_HFP_HF;
376             break;
377         case static_cast<int32_t>(ProfileId::PROFILE_PBAP_CLIENT):
378             HILOGD("PROFILE_ID_PBAP_PCE");
379             profileId = PROFILE_ID_PBAP_PCE;
380             break;
381         case static_cast<int32_t>(ProfileId::PROFILE_PBAP_SERVER):
382             HILOGD("PROFILE_ID_PBAP_PSE");
383             profileId = PROFILE_ID_PBAP_PSE;
384             break;
385         case static_cast<int32_t>(ProfileId::PROFILE_HID_HOST):
386             HILOGD("PROFILE_HID_HOST");
387             profileId = PROFILE_ID_HID_HOST;
388             break;
389         default:
390             break;
391     }
392     return profileId;
393 }
394 
GetScoConnectionState(int state)395 int GetScoConnectionState(int state)
396 {
397     int32_t scoState = ScoState::SCO_DISCONNECTED;
398     switch (state) {
399         case static_cast<int32_t>(HfpScoConnectState::SCO_CONNECTING):
400             HILOGD("SCO_CONNECTING(1)");
401             scoState = ScoState::SCO_CONNECTING;
402             break;
403         case static_cast<int32_t>(HfpScoConnectState::SCO_CONNECTED):
404             HILOGD("SCO_CONNECTED(3)");
405             scoState = ScoState::SCO_CONNECTED;
406             break;
407         case static_cast<int32_t>(HfpScoConnectState::SCO_DISCONNECTING):
408             HILOGD("SCO_DISCONNECTING(2)");
409             scoState = ScoState::SCO_DISCONNECTING;
410             break;
411         case static_cast<int32_t>(HfpScoConnectState::SCO_DISCONNECTED):
412             HILOGD("SCO_DISCONNECTED(0)");
413             scoState = ScoState::SCO_DISCONNECTED;
414             break;
415         default:
416             break;
417     }
418     return scoState;
419 }
420 
RegisterSysBLEObserver(const std::shared_ptr<BluetoothCallbackInfo> & info,int32_t callbackIndex,const std::string & type)421 void RegisterSysBLEObserver(
422     const std::shared_ptr<BluetoothCallbackInfo> &info, int32_t callbackIndex, const std::string &type)
423 {
424     if (callbackIndex >= static_cast<int32_t>(ARGS_SIZE_THREE)) {
425         return;
426     }
427     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
428     HILOGI("type: %{public}s, index: %{public}d", type.c_str(), callbackIndex);
429     g_sysBLEObserver[type][callbackIndex] = info;
430 }
431 
UnregisterSysBLEObserver(const std::string & type)432 void UnregisterSysBLEObserver(const std::string &type)
433 {
434     std::lock_guard<std::mutex> lock(g_sysBLEObserverMutex);
435     auto itor = g_sysBLEObserver.find(type);
436     if (itor != g_sysBLEObserver.end()) {
437         g_sysBLEObserver.erase(itor);
438     }
439 }
440 
DoInJsMainThread(napi_env env,std::function<void (void)> func)441 int DoInJsMainThread(napi_env env, std::function<void(void)> func)
442 {
443     if (napi_send_event(env, func, napi_eprio_high) != napi_ok) {
444         HILOGE("Failed to SendEvent");
445         return -1;
446     }
447     return 0;
448 }
449 
IsValidAddress(std::string bdaddr)450 bool IsValidAddress(std::string bdaddr)
451 {
452 #if defined(IOS_PLATFORM)
453     const std::regex deviceIdRegex("^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$");
454     return regex_match(bdaddr, deviceIdRegex);
455 #else
456     const std::regex deviceIdRegex("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$");
457     return regex_match(bdaddr, deviceIdRegex);
458 #endif
459 }
460 
IsValidTransport(int transport)461 bool IsValidTransport(int transport)
462 {
463     return transport == BT_TRANSPORT_BREDR || transport == BT_TRANSPORT_BLE;
464 }
465 
IsValidConnectStrategy(int strategy)466 bool IsValidConnectStrategy(int strategy)
467 {
468     return strategy == static_cast<int>(BTStrategyType::CONNECTION_ALLOWED)
469         || strategy == static_cast<int>(BTStrategyType::CONNECTION_FORBIDDEN);
470 }
471 
NapiIsBoolean(napi_env env,napi_value value)472 napi_status NapiIsBoolean(napi_env env, napi_value value)
473 {
474     napi_valuetype valuetype = napi_undefined;
475     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
476     NAPI_BT_RETURN_IF(valuetype != napi_boolean, "Wrong argument type. Boolean expected.", napi_boolean_expected);
477     return napi_ok;
478 }
479 
NapiIsNumber(napi_env env,napi_value value)480 napi_status NapiIsNumber(napi_env env, napi_value value)
481 {
482     napi_valuetype valuetype = napi_undefined;
483     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
484     NAPI_BT_RETURN_IF(valuetype != napi_number, "Wrong argument type. Number expected.", napi_number_expected);
485     return napi_ok;
486 }
487 
NapiIsString(napi_env env,napi_value value)488 napi_status NapiIsString(napi_env env, napi_value value)
489 {
490     napi_valuetype valuetype = napi_undefined;
491     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
492     NAPI_BT_RETURN_IF(valuetype != napi_string, "Wrong argument type. String expected.", napi_string_expected);
493     return napi_ok;
494 }
495 
NapiIsFunction(napi_env env,napi_value value)496 napi_status NapiIsFunction(napi_env env, napi_value value)
497 {
498     napi_valuetype valuetype = napi_undefined;
499     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
500     if (valuetype != napi_function) {
501         HILOGD("Wrong argument type. Function expected.");
502         return napi_function_expected;
503     }
504     NAPI_BT_RETURN_IF(valuetype != napi_function, "Wrong argument type. Function expected.", napi_function_expected);
505     return napi_ok;
506 }
507 
NapiIsArrayBuffer(napi_env env,napi_value value)508 napi_status NapiIsArrayBuffer(napi_env env, napi_value value)
509 {
510     bool isArrayBuffer = false;
511     NAPI_BT_CALL_RETURN(napi_is_arraybuffer(env, value, &isArrayBuffer));
512     NAPI_BT_RETURN_IF(!isArrayBuffer, "Expected arraybuffer type", napi_arraybuffer_expected);
513     return napi_ok;
514 }
515 
NapiIsArray(napi_env env,napi_value value)516 napi_status NapiIsArray(napi_env env, napi_value value)
517 {
518     bool isArray = false;
519     NAPI_BT_CALL_RETURN(napi_is_array(env, value, &isArray));
520     NAPI_BT_RETURN_IF(!isArray, "Expected array type", napi_array_expected);
521     return napi_ok;
522 }
523 
NapiIsObject(napi_env env,napi_value value)524 napi_status NapiIsObject(napi_env env, napi_value value)
525 {
526     napi_valuetype valuetype = napi_undefined;
527     NAPI_BT_CALL_RETURN(napi_typeof(env, value, &valuetype));
528     NAPI_BT_RETURN_IF(valuetype != napi_object, "Wrong argument type. Object expected.", napi_object_expected);
529     return napi_ok;
530 }
531 
ParseNumberParams(napi_env env,napi_value object,const char * name,bool & outExist,napi_value & outParam)532 napi_status ParseNumberParams(napi_env env, napi_value object, const char *name, bool &outExist,
533     napi_value &outParam)
534 {
535     bool hasProperty = false;
536     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
537     if (hasProperty) {
538         napi_value property;
539         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
540         napi_valuetype valuetype;
541         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
542         NAPI_BT_RETURN_IF(valuetype != napi_number, "Wrong argument type, number expected", napi_number_expected);
543         outParam = property;
544     }
545     outExist = hasProperty;
546     return napi_ok;
547 }
548 
ParseInt32Params(napi_env env,napi_value object,const char * name,bool & outExist,int32_t & outParam)549 napi_status ParseInt32Params(napi_env env, napi_value object, const char *name, bool &outExist,
550     int32_t &outParam)
551 {
552     bool exist = false;
553     napi_value param;
554     NAPI_BT_CALL_RETURN(ParseNumberParams(env, object, name, exist, param));
555     if (exist) {
556         int32_t num = 0;
557         NAPI_BT_CALL_RETURN(napi_get_value_int32(env, param, &num));
558         outParam = num;
559     }
560     outExist = exist;
561     return napi_ok;
562 }
563 
ParseUint32Params(napi_env env,napi_value object,const char * name,bool & outExist,uint32_t & outParam)564 napi_status ParseUint32Params(napi_env env, napi_value object, const char *name, bool &outExist,
565     uint32_t &outParam)
566 {
567     bool exist = false;
568     napi_value param;
569     NAPI_BT_CALL_RETURN(ParseNumberParams(env, object, name, exist, param));
570     if (exist) {
571         uint32_t num = 0;
572         NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, param, &num));
573         outParam = num;
574     }
575     outExist = exist;
576     return napi_ok;
577 }
578 
ParseBooleanParams(napi_env env,napi_value object,const char * name,bool & outExist,bool & outParam)579 napi_status ParseBooleanParams(napi_env env, napi_value object, const char *name, bool &outExist, bool &outParam)
580 {
581     bool hasProperty = false;
582     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
583     if (hasProperty) {
584         napi_value property;
585         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
586         napi_valuetype valuetype;
587         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
588         NAPI_BT_RETURN_IF(valuetype != napi_boolean, "Wrong argument type, boolean expected", napi_boolean_expected);
589 
590         bool param = false;
591         NAPI_BT_CALL_RETURN(napi_get_value_bool(env, property, &param));
592         outParam = param;
593     }
594     outExist = hasProperty;
595     return napi_ok;
596 }
597 
598 // Only used for optional paramters
ParseStringParams(napi_env env,napi_value object,const char * name,bool & outExist,std::string & outParam)599 napi_status ParseStringParams(napi_env env, napi_value object, const char *name, bool &outExist,
600     std::string &outParam)
601 {
602     bool hasProperty = false;
603     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
604     if (hasProperty) {
605         napi_value property;
606         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
607         napi_valuetype valuetype;
608         NAPI_BT_CALL_RETURN(napi_typeof(env, property, &valuetype));
609         NAPI_BT_RETURN_IF(valuetype != napi_string, "Wrong argument type, string expected", napi_string_expected);
610 
611         std::string param {};
612         bool isSuccess = ParseString(env, param, property);
613         if (!isSuccess) {
614             return napi_invalid_arg;
615         }
616         outParam = std::move(param);
617     }
618     outExist = hasProperty;
619     return napi_ok;
620 }
621 
ParseArrayBufferParams(napi_env env,napi_value object,const char * name,bool & outExist,std::vector<uint8_t> & outParam)622 napi_status ParseArrayBufferParams(napi_env env, napi_value object, const char *name, bool &outExist,
623     std::vector<uint8_t> &outParam)
624 {
625     bool hasProperty = false;
626     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &hasProperty));
627     if (hasProperty) {
628         napi_value property;
629         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
630         bool isArrayBuffer = false;
631         NAPI_BT_CALL_RETURN(napi_is_arraybuffer(env, property, &isArrayBuffer));
632         NAPI_BT_RETURN_IF(!isArrayBuffer, "Wrong argument type, arraybuffer expected", napi_arraybuffer_expected);
633 
634         uint8_t *data = nullptr;
635         size_t size = 0;
636         bool isSuccess = ParseArrayBuffer(env, &data, size, property);
637         if (!isSuccess) {
638             HILOGE("ParseArrayBuffer faild.");
639             return napi_invalid_arg;
640         }
641         outParam = std::vector<uint8_t>(data, data + size);
642     }
643     outExist = hasProperty;
644     return napi_ok;
645 }
646 
ParseUuidParams(napi_env env,napi_value object,const char * name,bool & outExist,UUID & outUuid)647 napi_status ParseUuidParams(napi_env env, napi_value object, const char *name, bool &outExist, UUID &outUuid)
648 {
649     bool exist = false;
650     std::string uuid {};
651     NAPI_BT_CALL_RETURN(ParseStringParams(env, object, name, exist, uuid));
652     if (exist) {
653         if (!IsValidUuid(uuid)) {
654             HILOGE("match the UUID faild.");
655             return napi_invalid_arg;
656         }
657         outUuid = ParcelUuid::FromString(uuid);
658     }
659     outExist = exist;
660     return napi_ok;
661 }
662 
663 // This function applies to interfaces with a single address as a parameter.
CheckDeivceIdParam(napi_env env,napi_callback_info info,std::string & addr)664 bool CheckDeivceIdParam(napi_env env, napi_callback_info info, std::string &addr)
665 {
666     size_t argc = ARGS_SIZE_ONE;
667     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
668     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok, "call failed.", false);
669     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
670     NAPI_BT_RETURN_IF(!ParseString(env, addr, argv[PARAM0]), "ParseString failed", false);
671     NAPI_BT_RETURN_IF(!IsValidAddress(addr), "Invalid addr", false);
672     return true;
673 }
674 
CheckProfileIdParam(napi_env env,napi_callback_info info,int & profileId)675 bool CheckProfileIdParam(napi_env env, napi_callback_info info, int &profileId)
676 {
677     size_t argc = ARGS_SIZE_ONE;
678     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
679     napi_value thisVar = nullptr;
680     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
681     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
682     NAPI_BT_RETURN_IF(!ParseInt32(env, profileId, argv[PARAM0]), "ParseInt32 failed", false);
683     return true;
684 }
685 
CheckProfileIdParamEx(napi_env env,napi_callback_info info,int & profileId,size_t & argc)686 bool CheckProfileIdParamEx(napi_env env, napi_callback_info info, int &profileId, size_t &argc)
687 {
688     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
689     napi_value thisVar = nullptr;
690     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
691     NAPI_BT_RETURN_IF(argc > ARGS_SIZE_ONE, "Wrong argument type", false);
692     if (argc == ARGS_SIZE_ONE) {
693         NAPI_BT_RETURN_IF(!ParseInt32(env, profileId, argv[PARAM0]), "ParseInt32 failed", false);
694     }
695     return true;
696 }
697 
CheckSetDevicePairingConfirmationParam(napi_env env,napi_callback_info info,std::string & addr,bool & accept)698 bool CheckSetDevicePairingConfirmationParam(napi_env env, napi_callback_info info, std::string &addr, bool &accept)
699 {
700     size_t argc = ARGS_SIZE_TWO;
701     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
702     napi_value thisVar = nullptr;
703     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
704     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Wrong argument type", false);
705     NAPI_BT_RETURN_IF(!ParseString(env, addr, argv[PARAM0]), "ParseString failed", false);
706     NAPI_BT_RETURN_IF(!IsValidAddress(addr), "Invalid addr", false);
707     NAPI_BT_RETURN_IF(!ParseBool(env, accept, argv[PARAM1]), "ParseBool failed", false);
708     return true;
709 }
710 
CheckLocalNameParam(napi_env env,napi_callback_info info,std::string & name)711 bool CheckLocalNameParam(napi_env env, napi_callback_info info, std::string &name)
712 {
713     size_t argc = ARGS_SIZE_ONE;
714     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
715     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok, "call failed.", false);
716     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE, "Wrong argument type", false);
717     NAPI_BT_RETURN_IF(!ParseString(env, name, argv[PARAM0]), "ParseString failed", false);
718     return true;
719 }
720 
CheckSetBluetoothScanModeParam(napi_env env,napi_callback_info info,int32_t & mode,int32_t & duration)721 bool CheckSetBluetoothScanModeParam(napi_env env, napi_callback_info info, int32_t &mode, int32_t &duration)
722 {
723     size_t argc = ARGS_SIZE_TWO;
724     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
725     napi_value thisVar = nullptr;
726     NAPI_BT_RETURN_IF(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr) != napi_ok, "call failed.", false);
727     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Wrong argument type", false);
728     NAPI_BT_RETURN_IF(!ParseInt32(env, mode, argv[PARAM0]), "ParseInt32 failed", false);
729     NAPI_BT_RETURN_IF(!ParseInt32(env, duration, argv[PARAM1]), "ParseInt32 failed", false);
730     return true;
731 }
732 
CheckEmptyParam(napi_env env,napi_callback_info info)733 napi_status CheckEmptyParam(napi_env env, napi_callback_info info)
734 {
735     size_t argc = ARGS_SIZE_ZERO;
736     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr));
737     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ZERO, "Requires 0 argument.", napi_invalid_arg);
738     return napi_ok;
739 }
740 
NapiCheckObjectPropertiesName(napi_env env,napi_value object,const std::vector<std::string> & names)741 napi_status NapiCheckObjectPropertiesName(napi_env env, napi_value object, const std::vector<std::string> &names)
742 {
743     uint32_t len = 0;
744     napi_value properties;
745     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
746     NAPI_BT_CALL_RETURN(napi_get_property_names(env, object, &properties));
747     NAPI_BT_CALL_RETURN(napi_get_array_length(env, properties, &len));
748     for (uint32_t i = 0; i < len; ++i) {
749         std::string name {};
750         napi_value actualName;
751         NAPI_BT_CALL_RETURN(napi_get_element(env, properties, i, &actualName));
752         NAPI_BT_CALL_RETURN(NapiParseString(env, actualName, name));
753         if (std::find(names.begin(), names.end(), name) == names.end()) {
754             HILOGE("Unexpect object property name: \"%{public}s\"", name.c_str());
755             return napi_invalid_arg;
756         }
757     }
758     return napi_ok;
759 }
760 
CheckSetConnectStrategyParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & strategy)761 napi_status CheckSetConnectStrategyParam(napi_env env, napi_callback_info info, std::string &addr, int32_t &strategy)
762 {
763     size_t argc = ARGS_SIZE_THREE;
764     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
765     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
766     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
767     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
768     NAPI_BT_RETURN_IF(!ParseInt32(env, strategy, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
769     NAPI_BT_RETURN_IF(!IsValidConnectStrategy(strategy), "Invalid strategy", napi_invalid_arg);
770     return napi_ok;
771 }
772 
CheckDeviceAddressParam(napi_env env,napi_callback_info info,std::string & addr)773 napi_status CheckDeviceAddressParam(napi_env env, napi_callback_info info, std::string &addr)
774 {
775     size_t argc = ARGS_SIZE_TWO;
776     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
777     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
778     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments.", napi_invalid_arg);
779     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
780     return napi_ok;
781 }
782 
IsAccessAuthorizationValid(int32_t accessAuthorization)783 bool IsAccessAuthorizationValid(int32_t accessAuthorization)
784 {
785     return accessAuthorization == static_cast<int32_t>(AccessAuthorization::UNKNOWN) ||
786         accessAuthorization == static_cast<int32_t>(AccessAuthorization::ALLOWED) ||
787         accessAuthorization == static_cast<int32_t>(AccessAuthorization::REJECTED);
788 }
789 
CheckAccessAuthorizationParam(napi_env env,napi_callback_info info,std::string & addr,int32_t & accessAuthorization)790 napi_status CheckAccessAuthorizationParam(napi_env env, napi_callback_info info, std::string &addr,
791     int32_t &accessAuthorization)
792 {
793     size_t argc = ARGS_SIZE_THREE;
794     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
795     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
796     NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
797     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
798     NAPI_BT_RETURN_IF(!ParseInt32(env, accessAuthorization, argv[PARAM1]), "ParseInt failed", napi_invalid_arg);
799     NAPI_BT_RETURN_IF(!IsAccessAuthorizationValid(accessAuthorization),
800         "Invalid accessAuthorization", napi_invalid_arg);
801     return napi_ok;
802 }
803 
NapiGetOnOffCallbackName(napi_env env,napi_callback_info info,std::string & name)804 napi_status NapiGetOnOffCallbackName(napi_env env, napi_callback_info info, std::string &name)
805 {
806     size_t argc = ARGS_SIZE_TWO;
807     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
808     napi_value thisVar = nullptr;
809     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
810     NAPI_BT_RETURN_IF(argc == ARGS_SIZE_ZERO, "Requires at least 1 arguments", napi_invalid_arg);
811 
812     std::string type {};
813     NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], type));
814 
815     name = type;
816     return napi_ok;
817 }
818 }  // namespace Bluetooth
819 }  // namespace OHOS
820