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