1 /*
2 * Copyright (C) 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 "bluetooth_opp.h"
17 #include "bluetooth_log.h"
18 #include "napi_bluetooth_opp_observer.h"
19 #include "napi_bluetooth_utils.h"
20 #include "napi_bluetooth_profile.h"
21 #include "napi_bluetooth_opp.h"
22
23 namespace OHOS {
24 namespace Bluetooth {
25 using namespace std;
26 std::shared_ptr<NapiBluetoothOppObserver> NapiBluetoothOpp::observer_ = std::make_shared<NapiBluetoothOppObserver>();
27 bool NapiBluetoothOpp::isRegistered_ = false;
28
DefineOppJSClass(napi_env env)29 void NapiBluetoothOpp::DefineOppJSClass(napi_env env)
30 {
31 napi_value constructor;
32 napi_property_descriptor properties[] = {
33 DECLARE_NAPI_FUNCTION("on", NapiBluetoothOpp::On),
34 DECLARE_NAPI_FUNCTION("off", NapiBluetoothOpp::Off),
35 DECLARE_NAPI_FUNCTION("sendFile", NapiBluetoothOpp::SendFile),
36 DECLARE_NAPI_FUNCTION("setIncomingFileConfirmation", NapiBluetoothOpp::SetIncomingFileConfirmation),
37 DECLARE_NAPI_FUNCTION("getCurrentTransferInformation", NapiBluetoothOpp::GetCurrentTransferInformation),
38 DECLARE_NAPI_FUNCTION("cancelTransfer", NapiBluetoothOpp::CancelTransfer),
39 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
40 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
41 };
42
43 napi_define_class(env, "NapiBluetoothOpp", NAPI_AUTO_LENGTH, NapiBluetoothOpp::OppConstructor, nullptr,
44 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
45
46 napi_value napiProfile;
47 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
48 NapiProfile::SetProfile(env, ProfileId::PROFILE_OPP, napiProfile);
49 Opp *profile = Opp::GetProfile();
50 profile->RegisterObserver(observer_);
51 }
52
OppConstructor(napi_env env,napi_callback_info info)53 napi_value NapiBluetoothOpp::OppConstructor(napi_env env, napi_callback_info info)
54 {
55 napi_value thisVar = nullptr;
56 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
57 return thisVar;
58 }
59
On(napi_env env,napi_callback_info info)60 napi_value NapiBluetoothOpp::On(napi_env env, napi_callback_info info)
61 {
62 HILOGI("On called");
63 size_t expectedArgsCount = ARGS_SIZE_TWO;
64 size_t argc = expectedArgsCount;
65 napi_value argv[ARGS_SIZE_TWO] = {0};
66 napi_value thisVar = nullptr;
67
68 napi_value ret = nullptr;
69 napi_get_undefined(env, &ret);
70
71 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
72 if (argc != expectedArgsCount) {
73 HILOGE("Requires 2 argument.");
74 return ret;
75 }
76 string type;
77 if (!ParseString(env, type, argv[PARAM0])) {
78 HILOGE("string expected.");
79 return ret;
80 }
81 std::shared_ptr<TransforInformationCallbackInfo> callbackInfo = std::make_shared<TransforInformationCallbackInfo>();
82 callbackInfo->env_ = env;
83
84 napi_valuetype valueType = napi_undefined;
85 napi_typeof(env, argv[PARAM1], &valueType);
86 if (valueType != napi_function) {
87 HILOGE("Wrong argument type. Function expected.");
88 return ret;
89 }
90 napi_create_reference(env, argv[PARAM1], 1, &callbackInfo->callback_);
91 observer_->callbackInfos_[type] = callbackInfo;
92 HILOGI("%{public}s is registered", type.c_str());
93 return ret;
94 }
95
Off(napi_env env,napi_callback_info info)96 napi_value NapiBluetoothOpp::Off(napi_env env, napi_callback_info info)
97 {
98 HILOGI("Off called");
99 size_t expectedArgsCount = ARGS_SIZE_ONE;
100 size_t argc = expectedArgsCount;
101 napi_value argv[ARGS_SIZE_ONE] = {0};
102 napi_value thisVar = nullptr;
103
104 napi_value ret = nullptr;
105 napi_get_undefined(env, &ret);
106
107 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
108 if (argc != expectedArgsCount) {
109 HILOGE("Requires 1 argument.");
110 return ret;
111 }
112 string type;
113 if (!ParseString(env, type, argv[PARAM0])) {
114 HILOGE("string expected.");
115 return ret;
116 }
117
118 if (observer_->callbackInfos_[type] != nullptr) {
119 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = observer_->callbackInfos_[type];
120 napi_delete_reference(env, callbackInfo->callback_);
121 }
122 observer_->callbackInfos_[type] = nullptr;
123 HILOGI("%{public}s is unregistered", type.c_str());
124 return ret;
125 }
126
ParseStringArrayParameters(const napi_env & env,napi_value & args,std::vector<std::string> & params)127 static bool ParseStringArrayParameters(const napi_env &env, napi_value &args, std::vector<std::string> ¶ms)
128 {
129 HILOGI("%{public}s, enter", __func__);
130 if (args == nullptr) {
131 return NapiGetNull(env);
132 }
133
134 bool isArray = false;
135 std::string fileParam;
136 napi_is_array(env, args, &isArray);
137 if (isArray) {
138 uint32_t length = 0;
139 napi_get_array_length(env, args, &length);
140 for (size_t i = 0; i < length; i++) {
141 napi_value result;
142 napi_get_element(env, args, i, &result);
143 if (!ParseString(env, fileParam, result)) {
144 return false;
145 }
146 params.push_back(fileParam);
147 }
148 } else {
149 return false;
150 }
151 return true;
152 }
153
SendFile(napi_env env,napi_callback_info info)154 napi_value NapiBluetoothOpp::SendFile(napi_env env, napi_callback_info info)
155 {
156 HILOGI("SendFile called");
157
158 size_t expectedArgsCount = ARGS_SIZE_THREE;
159 size_t argc = expectedArgsCount;
160 napi_value argv[ARGS_SIZE_THREE] = {};
161 napi_value thisVar = nullptr;
162
163 napi_value ret = nullptr;
164 napi_get_undefined(env, &ret);
165
166 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
167 if (argc != expectedArgsCount) {
168 HILOGE("Requires 3 argument.");
169 return ret;
170 }
171 std::string device;
172 if (!ParseString(env, device, argv[PARAM0])) {
173 HILOGE("string expected.");
174 return ret;
175 }
176 std::vector<std::string> filePaths;
177 if (argv[PARAM1] != nullptr) {
178 if (!ParseStringArrayParameters(env, argv[PARAM1], filePaths)) {
179 return ret;
180 }
181 }
182 std::vector<std::string> mimeTypes;
183 if (argv[PARAM2] != nullptr) {
184 if (!ParseStringArrayParameters(env, argv[PARAM2], mimeTypes)) {
185 return ret;
186 }
187 }
188 Opp *profile = Opp::GetProfile();
189 bool isOK = profile->SendFile(device, filePaths, mimeTypes);
190 napi_value result = nullptr;
191 napi_get_boolean(env, isOK, &result);
192 return result;
193 }
194
SetIncomingFileConfirmation(napi_env env,napi_callback_info info)195 napi_value NapiBluetoothOpp::SetIncomingFileConfirmation(napi_env env, napi_callback_info info)
196 {
197 HILOGI("SetIncomingFileConfirmation called");
198
199 size_t expectedArgsCount = ARGS_SIZE_ONE;
200 size_t argc = expectedArgsCount;
201 napi_value argv[ARGS_SIZE_ONE] = {};
202 napi_value thisVar = nullptr;
203
204 napi_value ret = nullptr;
205 napi_get_undefined(env, &ret);
206
207 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
208 if (argc != expectedArgsCount) {
209 HILOGE("Requires 1 argument.");
210 return ret;
211 }
212 bool accept;
213 if (!ParseBool(env, accept, argv[PARAM0])) {
214 HILOGE("Bool expected.");
215 return ret;
216 }
217 Opp *profile = Opp::GetProfile();
218 bool isOk = profile->SetIncomingFileConfirmation(accept);
219 napi_value result = nullptr;
220 napi_get_boolean(env, isOk, &result);
221 return result;
222 }
223
GetCurrentTransferInformation(napi_env env,napi_callback_info info)224 napi_value NapiBluetoothOpp::GetCurrentTransferInformation(napi_env env, napi_callback_info info)
225 {
226 HILOGI("GetCurrentTransferInformation called");
227
228 size_t expectedArgsCount = ARGS_SIZE_ZERO;
229 size_t argc = expectedArgsCount;
230 napi_value argv[ARGS_SIZE_ZERO] = {};
231 napi_value thisVar = nullptr;
232
233 napi_value ret = nullptr;
234 napi_get_undefined(env, &ret);
235
236 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
237 if (argc != expectedArgsCount) {
238 HILOGE("No Requires argument.");
239 return ret;
240 }
241 Opp *profile = Opp::GetProfile();
242 BluetoothOppTransferInformation information = profile->GetCurrentTransferInformation();
243 napi_value obj = nullptr;
244 napi_create_object(env, &obj);
245 ConvertOppTransferInformationToJS(env, obj, information);
246 return obj;
247 }
248
CancelTransfer(napi_env env,napi_callback_info info)249 napi_value NapiBluetoothOpp::CancelTransfer(napi_env env, napi_callback_info info)
250 {
251 HILOGI("CancelTransfer called");
252
253 size_t expectedArgsCount = ARGS_SIZE_ZERO;
254 size_t argc = expectedArgsCount;
255 napi_value argv[ARGS_SIZE_ZERO] = {};
256 napi_value thisVar = nullptr;
257
258 napi_value ret = nullptr;
259 napi_get_undefined(env, &ret);
260
261 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
262 if (argc != expectedArgsCount) {
263 HILOGE("No Requires argument.");
264 return ret;
265 }
266 Opp *profile = Opp::GetProfile();
267 bool isOk = profile->CancelTransfer();
268 napi_value result = nullptr;
269 napi_get_boolean(env, isOk, &result);
270 return result;
271 }
272
GetConnectionDevices(napi_env env,napi_callback_info info)273 napi_value NapiBluetoothOpp::GetConnectionDevices(napi_env env, napi_callback_info info)
274 {
275 HILOGI("GetConnectionDevices called");
276
277 size_t expectedArgsCount = ARGS_SIZE_ZERO;
278 size_t argc = expectedArgsCount;
279 napi_value argv[ARGS_SIZE_ZERO] = {};
280 napi_value thisVar = nullptr;
281
282 napi_value ret = nullptr;
283 napi_get_undefined(env, &ret);
284
285 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
286 if (argc != expectedArgsCount) {
287 HILOGE("No Requires argument.");
288 return ret;
289 }
290 napi_create_array(env, &ret);
291 Opp *profile = Opp::GetProfile();
292 vector<int> states = { static_cast<int>(BTConnectState::CONNECTED) };
293 vector<BluetoothRemoteDevice> devices = profile->GetDevicesByStates(states);
294 vector<string> deviceVector;
295 for (auto &device : devices) {
296 deviceVector.push_back(device.GetDeviceAddr());
297 }
298 ConvertStringVectorToJS(env, ret, deviceVector);
299 return ret;
300 }
301
GetDeviceState(napi_env env,napi_callback_info info)302 napi_value NapiBluetoothOpp::GetDeviceState(napi_env env, napi_callback_info info)
303 {
304 HILOGI("GetDeviceState called");
305 size_t expectedArgsCount = ARGS_SIZE_ONE;
306 size_t argc = expectedArgsCount;
307 napi_value argv[ARGS_SIZE_ONE] = {0};
308 napi_value thisVar = nullptr;
309
310 napi_value ret = nullptr;
311 napi_get_undefined(env, &ret);
312
313 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
314 if (argc != expectedArgsCount) {
315 HILOGE("Requires 1 argument.");
316 return ret;
317 }
318 string deviceId;
319 if (!ParseString(env, deviceId, argv[PARAM0])) {
320 HILOGE("string expected.");
321 return ret;
322 }
323
324 Opp *profile = Opp::GetProfile();
325 BluetoothRemoteDevice device(deviceId, 1);
326 int state = profile->GetDeviceState(device);
327 int profileState = GetProfileConnectionState(state);
328 napi_value result = nullptr;
329 napi_create_int32(env, profileState, &result);
330 return result;
331 }
332 } // namespace Bluetooth
333 } // namespace OHOS