1 /*
2 * Copyright (C) 2024 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_util.h"
17 #include "securec.h"
18 #include "string_ex.h"
19 #include "common_utils.h"
20 #include "location_log.h"
21 #ifdef NOTIFICATION_ENABLE
22 #include "notification_request.h"
23 #include "notification.h"
24 #include "notification_napi.h"
25 #endif
26 #include "geofence_definition.h"
27 #include "geofence_napi.h"
28
29 namespace OHOS {
30 namespace Location {
31 const int MAX_TRANSITION_ARRAY_SIZE = 3;
32
ParseGnssGeofenceRequest(const napi_env & env,const napi_value & value,std::shared_ptr<GeofenceRequest> & request)33 bool ParseGnssGeofenceRequest(
34 const napi_env& env, const napi_value& value, std::shared_ptr<GeofenceRequest>& request)
35 {
36 napi_valuetype valueType;
37 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
38 if (valueType != napi_object) {
39 LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
40 return false;
41 }
42 return GenGnssGeofenceRequest(env, value, request);
43 }
44
GenGnssGeofenceRequest(const napi_env & env,const napi_value & value,std::shared_ptr<GeofenceRequest> & geofenceRequest)45 bool GenGnssGeofenceRequest(
46 const napi_env& env, const napi_value& value, std::shared_ptr<GeofenceRequest>& geofenceRequest)
47 {
48 if (geofenceRequest == nullptr) {
49 LBSLOGE(NAPI_UTILS, "geofenceRequest == nullptr");
50 return false;
51 }
52 bool isValidParameter = JsObjToGeoFenceRequest(env, value, geofenceRequest);
53 if (!isValidParameter) {
54 return false;
55 }
56 std::vector<GeofenceTransitionEvent> geofenceTransitionStatusList;
57 JsObjToGeofenceTransitionEventList(env, value, geofenceTransitionStatusList);
58 geofenceRequest->SetGeofenceTransitionEventList(geofenceTransitionStatusList);
59 #ifdef NOTIFICATION_ENABLE
60 std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>> notificationRequestList;
61 JsObjToNotificationRequestList(env, value, notificationRequestList);
62 geofenceRequest->SetNotificationRequestList(notificationRequestList);
63 #endif
64 return true;
65 }
66
JsObjToGeofenceTransitionCallback(const napi_env & env,const napi_value & object,sptr<LocationGnssGeofenceCallbackNapi> callbackHost)67 void JsObjToGeofenceTransitionCallback(const napi_env& env, const napi_value& object,
68 sptr<LocationGnssGeofenceCallbackNapi> callbackHost)
69 {
70 napi_ref handlerRef = nullptr;
71 napi_value callbackNapiValue = nullptr;
72 NAPI_CALL_RETURN_VOID(env,
73 napi_get_named_property(env, object, "geofenceTransitionCallback", &callbackNapiValue));
74 NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, callbackNapiValue, 1, &handlerRef));
75 callbackHost->SetEnv(env);
76 callbackHost->SetHandleCb(handlerRef);
77 }
78
79 #ifdef NOTIFICATION_ENABLE
JsObjToNotificationRequestList(const napi_env & env,const napi_value & object,std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>> & notificationRequestList)80 void JsObjToNotificationRequestList(const napi_env& env, const napi_value& object,
81 std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>>& notificationRequestList)
82 {
83 napi_value notificationRequest = GetArrayProperty(env, object, "notifications");
84 GetNotificationRequestArray(env, notificationRequest, notificationRequestList);
85 }
86
GetNotificationRequestArray(const napi_env & env,const napi_value & notificationRequestValue,std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>> & notificationRequestList)87 void GetNotificationRequestArray(const napi_env& env, const napi_value& notificationRequestValue,
88 std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>>& notificationRequestList)
89 {
90 napi_valuetype valueType;
91 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, notificationRequestValue, &valueType));
92 if (valueType != napi_object) {
93 LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
94 return;
95 }
96 uint32_t arrayLength = 0;
97 NAPI_CALL_RETURN_VOID(env, napi_get_array_length(env, notificationRequestValue, &arrayLength));
98 if (arrayLength == 0 || arrayLength > MAX_TRANSITION_ARRAY_SIZE) {
99 LBSLOGE(NAPI_UTILS, "The array is empty or out of range.");
100 return;
101 }
102 for (uint32_t i = 0; i < arrayLength; i++) {
103 napi_value elementValue = nullptr;
104 NAPI_CALL_RETURN_VOID(env, napi_get_element(env, notificationRequestValue, i, &elementValue));
105 napi_valuetype napiType;
106 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, elementValue, &napiType));
107 if (napiType != napi_object) {
108 LBSLOGE(NAPI_UTILS, "Wrong argument type.");
109 break;
110 }
111 std::shared_ptr<OHOS::Notification::NotificationRequest> notificationRequest =
112 std::make_shared<OHOS::Notification::NotificationRequest>();
113 GenNotificationRequest(env, elementValue, notificationRequest);
114 notificationRequestList.push_back(notificationRequest);
115 }
116 }
117
GenNotificationRequest(const napi_env & env,const napi_value & elementValue,std::shared_ptr<OHOS::Notification::NotificationRequest> & notificationRequest)118 void GenNotificationRequest(const napi_env& env, const napi_value& elementValue,
119 std::shared_ptr<OHOS::Notification::NotificationRequest>& notificationRequest)
120 {
121 napi_valuetype elementValueType;
122 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, elementValue, &elementValueType));
123 if (elementValueType != napi_object) {
124 LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
125 return;
126 }
127 // argv[0] : NotificationRequest
128 NotificationNapi::GetNotificationRequest(env, elementValue, *notificationRequest);
129 }
130 #endif
131
JsObjToGeofenceTransitionEventList(const napi_env & env,const napi_value & object,std::vector<GeofenceTransitionEvent> & geofenceTransitionStatusList)132 void JsObjToGeofenceTransitionEventList(const napi_env& env, const napi_value& object,
133 std::vector<GeofenceTransitionEvent>& geofenceTransitionStatusList)
134 {
135 napi_value monitorTransitionEvents = GetArrayProperty(env, object, "monitorTransitionEvents");
136 GetGeofenceTransitionEventArray(env, monitorTransitionEvents, geofenceTransitionStatusList);
137 }
138
GetGeofenceTransitionEventArray(const napi_env & env,const napi_value & monitorTransitionEvents,std::vector<GeofenceTransitionEvent> & geofenceTransitionStatusList)139 void GetGeofenceTransitionEventArray(const napi_env& env, const napi_value& monitorTransitionEvents,
140 std::vector<GeofenceTransitionEvent>& geofenceTransitionStatusList)
141 {
142 napi_valuetype valueType;
143 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, monitorTransitionEvents, &valueType));
144 if (valueType != napi_object) {
145 LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
146 return;
147 }
148 uint32_t arrayLength = 0;
149 NAPI_CALL_RETURN_VOID(env, napi_get_array_length(env, monitorTransitionEvents, &arrayLength));
150 if (arrayLength == 0 || arrayLength > MAX_TRANSITION_ARRAY_SIZE) {
151 LBSLOGE(NAPI_UTILS, "The array is empty or out of range.");
152 return;
153 }
154 for (uint32_t i = 0; i < arrayLength; i++) {
155 napi_value elementValue = nullptr;
156 NAPI_CALL_RETURN_VOID(env, napi_get_element(env, monitorTransitionEvents, i, &elementValue));
157 napi_valuetype napiType;
158 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, elementValue, &napiType));
159 if (napiType != napi_number) {
160 LBSLOGE(NAPI_UTILS, "Wrong argument type.");
161 break;
162 }
163 int geofenceTransitionStatus = -1;
164 NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, elementValue, &geofenceTransitionStatus));
165 geofenceTransitionStatusList.push_back(static_cast<GeofenceTransitionEvent>(geofenceTransitionStatus));
166 }
167 }
168
CheckGeofenceParameter(const GeoFence & fenceInfo)169 static bool CheckGeofenceParameter(const GeoFence& fenceInfo)
170 {
171 if (fenceInfo.latitude > MAX_LATITUDE || fenceInfo.latitude < MIN_LATITUDE) {
172 LBSLOGE(LOCATOR_STANDARD, "latitude error.");
173 return false;
174 }
175 if (fenceInfo.longitude > MAX_LONGITUDE || fenceInfo.longitude < MIN_LONGITUDE) {
176 LBSLOGE(LOCATOR_STANDARD, "longitude error.");
177 return false;
178 }
179 if (!(fenceInfo.radius > 0)) {
180 LBSLOGE(LOCATOR_STANDARD, "radius error.");
181 return false;
182 }
183 if (!(fenceInfo.expiration > 0)) {
184 LBSLOGE(LOCATOR_STANDARD, "expiration error.");
185 return false;
186 }
187 return true;
188 }
189
JsObjToGeoFenceRequest(const napi_env & env,const napi_value & object,const std::shared_ptr<GeofenceRequest> & request)190 bool JsObjToGeoFenceRequest(const napi_env& env, const napi_value& object,
191 const std::shared_ptr<GeofenceRequest>& request)
192 {
193 int value = 0;
194 if (JsObjectToInt(env, object, "scenario", value) == SUCCESS) {
195 request->SetScenario(value);
196 }
197 napi_value geofenceValue = GetNapiValueByKey(env, "geofence", object);
198 if (geofenceValue == nullptr) {
199 LBSLOGE(LOCATOR_STANDARD, "parse geofence failed");
200 return false;
201 }
202 GeoFence geofence = {0};
203 if (JsObjectToDouble(env, geofenceValue, "latitude", geofence.latitude) != SUCCESS) {
204 LBSLOGE(LOCATOR_STANDARD, "parse latitude failed");
205 return false;
206 }
207 if (JsObjectToDouble(env, geofenceValue, "longitude", geofence.longitude) != SUCCESS) {
208 LBSLOGE(LOCATOR_STANDARD, "parse longitude failed");
209 return false;
210 }
211 if (JsObjectToInt(env, geofenceValue, "coordinateSystemType", value) == SUCCESS) {
212 geofence.coordinateSystemType = static_cast<CoordinateSystemType>(value);
213 } else {
214 geofence.coordinateSystemType = CoordinateSystemType::WGS84;
215 }
216 if (JsObjectToDouble(env, geofenceValue, "radius", geofence.radius) != SUCCESS) {
217 LBSLOGE(LOCATOR_STANDARD, "parse radius failed");
218 return false;
219 }
220 if (JsObjectToDouble(env, geofenceValue, "expiration", geofence.expiration) != SUCCESS) {
221 LBSLOGE(LOCATOR_STANDARD, "parse expiration failed");
222 return false;
223 }
224 bool isValidParameter = CheckGeofenceParameter(geofence);
225 if (!isValidParameter) {
226 return false;
227 }
228 request->SetGeofence(geofence);
229 return true;
230 }
231
GeofenceTransitionToJs(const napi_env & env,const GeofenceTransition geofenceTransition,napi_value & result)232 void GeofenceTransitionToJs(const napi_env& env,
233 const GeofenceTransition geofenceTransition, napi_value& result)
234 {
235 SetValueInt32(env, "geofenceId", geofenceTransition.fenceId, result);
236 SetValueInt32(env, "transitionEvent", static_cast<int>(geofenceTransition.event), result);
237 if (geofenceTransition.beaconFence != nullptr) {
238 napi_value beaconFenceJsObj = CreateBeaconFenceJsObj(env, geofenceTransition.beaconFence);
239 SetValueBeacon(env, "beaconFence", beaconFenceJsObj, result);
240 }
241 }
242
CreateBeaconFenceJsObj(const napi_env & env,const std::shared_ptr<BeaconFence> & beaconFence)243 napi_value CreateBeaconFenceJsObj(const napi_env& env, const std::shared_ptr<BeaconFence>& beaconFence)
244 {
245 napi_value beaconFenceObject = nullptr;
246 NAPI_CALL(env, napi_create_object(env, &beaconFenceObject));
247 SetValueUtf8String(env, "identifier",
248 beaconFence->GetIdentifier().c_str(), beaconFenceObject);
249 SetValueInt32(env, "beaconFenceInfoType",
250 static_cast<int>(beaconFence->GetBeaconFenceInfoType()), beaconFenceObject);
251
252 napi_value manufactureDataObject = nullptr;
253 NAPI_CALL(env, napi_create_object(env, &manufactureDataObject));
254 SetValueInt32(env, "manufactureId",
255 beaconFence->GetBeaconManufactureData().manufactureId, manufactureDataObject);
256 SetValueArrayBuffer(env, "manufactureData",
257 beaconFence->GetBeaconManufactureData().manufactureData, manufactureDataObject);
258 SetValueArrayBuffer(env, "manufactureDataMask",
259 beaconFence->GetBeaconManufactureData().manufactureDataMask, manufactureDataObject);
260 SetValueBeacon(env, "manufactureData",
261 manufactureDataObject, beaconFenceObject);
262 return beaconFenceObject;
263 }
264
SetValueBeacon(const napi_env & env,const char * fieldStr,napi_value & value,napi_value & result)265 napi_status SetValueBeacon(const napi_env& env, const char* fieldStr, napi_value& value, napi_value& result)
266 {
267 NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
268 return napi_ok;
269 }
270 } // namespace Location
271 } // namespace OHOS
272