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<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<OHOS::Notification::NotificationRequest> & notificationRequestList)80 void JsObjToNotificationRequestList(const napi_env& env, const napi_value& object,
81     std::vector<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<OHOS::Notification::NotificationRequest> & notificationRequestList)87 void GetNotificationRequestArray(const napi_env& env, const napi_value& notificationRequestValue,
88     std::vector<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         OHOS::Notification::NotificationRequest notificationRequest;
112         GenNotificationRequest(env, elementValue, notificationRequest);
113         notificationRequestList.push_back(notificationRequest);
114     }
115 }
116 
GenNotificationRequest(const napi_env & env,const napi_value & elementValue,OHOS::Notification::NotificationRequest & notificationRequest)117 void GenNotificationRequest(const napi_env& env, const napi_value& elementValue,
118     OHOS::Notification::NotificationRequest& notificationRequest)
119 {
120     napi_valuetype elementValueType;
121     NAPI_CALL_RETURN_VOID(env, napi_typeof(env, elementValue, &elementValueType));
122     if (elementValueType != napi_object) {
123         LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
124         return;
125     }
126     // argv[0] : NotificationRequest
127     NotificationNapi::GetNotificationRequest(env, elementValue, notificationRequest);
128 }
129 #endif
130 
JsObjToGeofenceTransitionEventList(const napi_env & env,const napi_value & object,std::vector<GeofenceTransitionEvent> & geofenceTransitionStatusList)131 void JsObjToGeofenceTransitionEventList(const napi_env& env, const napi_value& object,
132     std::vector<GeofenceTransitionEvent>& geofenceTransitionStatusList)
133 {
134     napi_value monitorTransitionEvents = GetArrayProperty(env, object, "monitorTransitionEvents");
135     GetGeofenceTransitionEventArray(env, monitorTransitionEvents, geofenceTransitionStatusList);
136 }
137 
GetGeofenceTransitionEventArray(const napi_env & env,const napi_value & monitorTransitionEvents,std::vector<GeofenceTransitionEvent> & geofenceTransitionStatusList)138 void GetGeofenceTransitionEventArray(const napi_env& env, const napi_value& monitorTransitionEvents,
139     std::vector<GeofenceTransitionEvent>& geofenceTransitionStatusList)
140 {
141     napi_valuetype valueType;
142     NAPI_CALL_RETURN_VOID(env, napi_typeof(env, monitorTransitionEvents, &valueType));
143     if (valueType != napi_object) {
144         LBSLOGE(NAPI_UTILS, "Wrong argument type, value should be object");
145         return;
146     }
147     uint32_t arrayLength = 0;
148     NAPI_CALL_RETURN_VOID(env, napi_get_array_length(env, monitorTransitionEvents, &arrayLength));
149     if (arrayLength == 0 || arrayLength > MAX_TRANSITION_ARRAY_SIZE) {
150         LBSLOGE(NAPI_UTILS, "The array is empty or out of range.");
151         return;
152     }
153     for (uint32_t i = 0; i < arrayLength; i++) {
154         napi_value elementValue = nullptr;
155         NAPI_CALL_RETURN_VOID(env, napi_get_element(env, monitorTransitionEvents, i, &elementValue));
156         napi_valuetype napiType;
157         NAPI_CALL_RETURN_VOID(env, napi_typeof(env, elementValue, &napiType));
158         if (napiType != napi_number) {
159             LBSLOGE(NAPI_UTILS, "Wrong argument type.");
160             break;
161         }
162         int geofenceTransitionStatus = -1;
163         NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, elementValue, &geofenceTransitionStatus));
164         geofenceTransitionStatusList.push_back(static_cast<GeofenceTransitionEvent>(geofenceTransitionStatus));
165     }
166 }
167 
CheckGeofenceParameter(const GeoFence & fenceInfo)168 static bool CheckGeofenceParameter(const GeoFence& fenceInfo)
169 {
170     if (fenceInfo.latitude > MAX_LATITUDE || fenceInfo.latitude < MIN_LATITUDE) {
171         LBSLOGE(LOCATOR_STANDARD, "latitude error.");
172         return false;
173     }
174     if (fenceInfo.longitude > MAX_LONGITUDE || fenceInfo.longitude < MIN_LONGITUDE) {
175         LBSLOGE(LOCATOR_STANDARD, "longitude error.");
176         return false;
177     }
178     if (!(fenceInfo.radius > 0)) {
179         LBSLOGE(LOCATOR_STANDARD, "radius error.");
180         return false;
181     }
182     if (!(fenceInfo.expiration > 0)) {
183         LBSLOGE(LOCATOR_STANDARD, "expiration error.");
184         return false;
185     }
186     return true;
187 }
188 
JsObjToGeoFenceRequest(const napi_env & env,const napi_value & object,const std::shared_ptr<GeofenceRequest> & request)189 bool JsObjToGeoFenceRequest(const napi_env& env, const napi_value& object,
190     const std::shared_ptr<GeofenceRequest>& request)
191 {
192     int value = 0;
193     if (JsObjectToInt(env, object, "scenario", value) == SUCCESS) {
194         request->SetScenario(value);
195     }
196     napi_value geofenceValue = GetNapiValueByKey(env, "geofence", object);
197     if (geofenceValue == nullptr) {
198         LBSLOGE(LOCATOR_STANDARD, "parse geofence failed");
199         return false;
200     }
201     GeoFence geofence = {0};
202     if (JsObjectToDouble(env, geofenceValue, "latitude", geofence.latitude) != SUCCESS) {
203         LBSLOGE(LOCATOR_STANDARD, "parse latitude failed");
204         return false;
205     }
206     if (JsObjectToDouble(env, geofenceValue, "longitude", geofence.longitude) != SUCCESS) {
207         LBSLOGE(LOCATOR_STANDARD, "parse longitude failed");
208         return false;
209     }
210     if (JsObjectToInt(env, geofenceValue, "coordinateSystemType", value) == SUCCESS) {
211         geofence.coordinateSystemType = static_cast<CoordinateSystemType>(value);
212     } else {
213         geofence.coordinateSystemType = CoordinateSystemType::WGS84;
214     }
215     if (JsObjectToDouble(env, geofenceValue, "radius", geofence.radius) != SUCCESS) {
216         LBSLOGE(LOCATOR_STANDARD, "parse radius failed");
217         return false;
218     }
219     if (JsObjectToDouble(env, geofenceValue, "expiration", geofence.expiration) != SUCCESS) {
220         LBSLOGE(LOCATOR_STANDARD, "parse expiration failed");
221         return false;
222     }
223     bool isValidParameter = CheckGeofenceParameter(geofence);
224     if (!isValidParameter) {
225         return false;
226     }
227     request->SetGeofence(geofence);
228     return true;
229 }
230 
GeofenceTransitionToJs(const napi_env & env,const GeofenceTransition geofenceTransition,napi_value & result)231 void GeofenceTransitionToJs(const napi_env& env,
232     const GeofenceTransition geofenceTransition, napi_value& result)
233 {
234     SetValueInt32(env, "geofenceId", geofenceTransition.fenceId, result);
235     SetValueInt32(env, "transitionEvent", static_cast<int>(geofenceTransition.event), result);
236 }
237 }  // namespace Location
238 }  // namespace OHOS
239