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