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 "napi_util.h"
17 
18 #include "securec.h"
19 #include "string_ex.h"
20 
21 #include "country_code.h"
22 #include "common_utils.h"
23 #include "geo_address.h"
24 #include "location_log.h"
25 #include "locator_proxy.h"
26 #include "request_config.h"
27 
28 namespace OHOS {
29 namespace Location {
30 static constexpr int MAX_BUF_LEN = 100;
31 static constexpr int MIN_WIFI_SCAN_TIME = 5000;
32 const uint32_t MAX_ADDITION_SIZE = 100;
33 
UndefinedNapiValue(const napi_env & env)34 napi_value UndefinedNapiValue(const napi_env& env)
35 {
36     napi_value result;
37     NAPI_CALL(env, napi_get_undefined(env, &result));
38     return result;
39 }
40 
SatelliteStatusToJs(const napi_env & env,const std::shared_ptr<SatelliteStatus> & statusInfo,napi_value & result)41 void SatelliteStatusToJs(const napi_env& env,
42     const std::shared_ptr<SatelliteStatus>& statusInfo, napi_value& result)
43 {
44     napi_value satelliteIdsArray;
45     napi_value cn0Array;
46     napi_value altitudesArray;
47     napi_value azimuthsArray;
48     napi_value carrierFrequenciesArray;
49     napi_value additionalInfoArray;
50     napi_value satelliteConstellationArray;
51     int svNum = statusInfo->GetSatellitesNumber();
52     SetValueDouble(env, "satellitesNumber", svNum, result);
53     if (svNum >= 0) {
54         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &satelliteIdsArray));
55         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &cn0Array));
56         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &altitudesArray));
57         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &azimuthsArray));
58         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &carrierFrequenciesArray));
59         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &satelliteConstellationArray));
60         NAPI_CALL_RETURN_VOID(env, napi_create_array_with_length(env, svNum, &additionalInfoArray));
61         uint32_t idx1 = 0;
62         for (int index = 0; index < svNum; index++) {
63             napi_value value = nullptr;
64             NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, statusInfo->GetSatelliteIds()[index], &value));
65             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, satelliteIdsArray, idx1, value));
66             NAPI_CALL_RETURN_VOID(env,
67                 napi_create_double(env, statusInfo->GetCarrierToNoiseDensitys()[index], &value));
68             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, cn0Array, idx1, value));
69             NAPI_CALL_RETURN_VOID(env, napi_create_double(env, statusInfo->GetAltitudes()[index], &value));
70             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, altitudesArray, idx1, value));
71             NAPI_CALL_RETURN_VOID(env, napi_create_double(env, statusInfo->GetAzimuths()[index], &value));
72             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, azimuthsArray, idx1, value));
73             NAPI_CALL_RETURN_VOID(env, napi_create_double(env, statusInfo->GetCarrierFrequencies()[index], &value));
74             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, carrierFrequenciesArray, idx1, value));
75             NAPI_CALL_RETURN_VOID(env,
76                 napi_create_int32(env, statusInfo->GetSatelliteAdditionalInfoList()[index], &value));
77             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, additionalInfoArray, idx1, value));
78             NAPI_CALL_RETURN_VOID(env,
79                 napi_create_int32(env, statusInfo->GetConstellationTypes()[index], &value));
80             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, satelliteConstellationArray, idx1, value));
81             idx1++;
82         }
83         SetValueStringArray(env, "satelliteIds", satelliteIdsArray, result);
84         SetValueStringArray(env, "carrierToNoiseDensitys", cn0Array, result);
85         SetValueStringArray(env, "altitudes", altitudesArray, result);
86         SetValueStringArray(env, "azimuths", azimuthsArray, result);
87         SetValueStringArray(env, "carrierFrequencies", carrierFrequenciesArray, result);
88         SetValueStringArray(env, "satelliteConstellation", satelliteConstellationArray, result);
89         SetValueStringArray(env, "satelliteAdditionalInfo", additionalInfoArray, result);
90     }
91 }
92 
LocationsToJs(const napi_env & env,const std::vector<std::unique_ptr<Location>> & locations,napi_value & result)93 void LocationsToJs(const napi_env& env, const std::vector<std::unique_ptr<Location>>& locations, napi_value& result)
94 {
95     if (locations.size() > 0) {
96         for (unsigned int index = 0; index < locations.size(); index++) {
97             napi_value value;
98             LocationToJs(env, locations[index], value);
99             NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index, value));
100         }
101     }
102 }
103 
LocationToJs(const napi_env & env,const std::unique_ptr<Location> & locationInfo,napi_value & result)104 void LocationToJs(const napi_env& env, const std::unique_ptr<Location>& locationInfo, napi_value& result)
105 {
106     SetValueDouble(env, "latitude", locationInfo->GetLatitude(), result);
107     SetValueDouble(env, "longitude", locationInfo->GetLongitude(), result);
108     SetValueDouble(env, "altitude", locationInfo->GetAltitude(), result);
109     SetValueDouble(env, "accuracy", locationInfo->GetAccuracy(), result);
110     SetValueDouble(env, "speed", locationInfo->GetSpeed(), result);
111     SetValueInt64(env, "timeStamp", locationInfo->GetTimeStamp(), result);
112     SetValueDouble(env, "direction", locationInfo->GetDirection(), result);
113     SetValueInt64(env, "timeSinceBoot", locationInfo->GetTimeSinceBoot(), result);
114     napi_value additionArray;
115     uint32_t additionSize = static_cast<uint32_t>(locationInfo->GetAdditionSize());
116     additionSize = additionSize > MAX_ADDITION_SIZE ? MAX_ADDITION_SIZE : additionSize;
117     std::vector<std::string> additions = locationInfo->GetAdditions();
118     SetValueInt64(env, "additionSize", additionSize, result);
119     NAPI_CALL_RETURN_VOID(env,
120         napi_create_array_with_length(env, additionSize, &additionArray));
121     for (uint32_t index = 0; index < additionSize; index++) {
122         napi_value value;
123         NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, additions[index].c_str(),
124             NAPI_AUTO_LENGTH, &value));
125         NAPI_CALL_RETURN_VOID(env, napi_set_element(env, additionArray, index, value));
126     }
127     SetValueStringArray(env, "additions", additionArray, result);
128     if (locationInfo->GetIsSystemApp() != 0) {
129         SetValueBool(env, "isFromMock", locationInfo->GetIsFromMock(), result);
130     }
131     napi_value additionMap = CreateJsMap(env, locationInfo->GetAdditionsMap());
132     SetValueStringMap(env, "additionsMap", additionMap, result);
133     SetValueDouble(env, "altitudeAccuracy", locationInfo->GetAltitudeAccuracy(), result);
134     SetValueDouble(env, "speedAccuracy", locationInfo->GetSpeedAccuracy(), result);
135     SetValueDouble(env, "directionAccuracy", locationInfo->GetDirectionAccuracy(), result);
136     SetValueInt64(env, "uncertaintyOfTimeSinceBoot", locationInfo->GetUncertaintyOfTimeSinceBoot(), result);
137     SetValueInt32(env, "sourceType", locationInfo->GetLocationSourceType(), result);
138 }
139 
CreateJsMap(napi_env env,const std::map<std::string,std::string> & additionsMap)140 napi_value CreateJsMap(napi_env env, const std::map<std::string, std::string>& additionsMap)
141 {
142     napi_value global = nullptr;
143     napi_value mapFunc = nullptr;
144     napi_value map = nullptr;
145     NAPI_CALL(env, napi_get_global(env, &global));
146     NAPI_CALL(env, napi_get_named_property(env, global, "Map", &mapFunc));
147     NAPI_CALL(env, napi_new_instance(env, mapFunc, 0, nullptr, &map));
148     napi_value setFunc = nullptr;
149     NAPI_CALL(env, napi_get_named_property(env, map, "set", &setFunc));
150     for (auto iter : additionsMap) {
151         napi_value key = nullptr;
152         napi_value value = nullptr;
153         NAPI_CALL(env, napi_create_string_utf8(env, iter.first.c_str(), NAPI_AUTO_LENGTH, &key));
154         NAPI_CALL(env, napi_create_string_utf8(env, iter.second.c_str(), NAPI_AUTO_LENGTH, &value));
155         napi_value setArgs[] = { key, value };
156         NAPI_CALL(env, napi_call_function(env, map, setFunc, sizeof(setArgs) / sizeof(setArgs[0]), setArgs, nullptr));
157     }
158     return map;
159 }
160 
CountryCodeToJs(const napi_env & env,const std::shared_ptr<CountryCode> & country,napi_value & result)161 void CountryCodeToJs(const napi_env& env, const std::shared_ptr<CountryCode>& country, napi_value& result)
162 {
163     SetValueUtf8String(env, "country", country->GetCountryCodeStr().c_str(), result);
164     SetValueInt64(env, "type", country->GetCountryCodeType(), result);
165 }
166 
SystemLocationToJs(const napi_env & env,const std::unique_ptr<Location> & locationInfo,napi_value & result)167 void SystemLocationToJs(const napi_env& env, const std::unique_ptr<Location>& locationInfo, napi_value& result)
168 {
169     SetValueDouble(env, "longitude", locationInfo->GetLongitude(), result);
170     SetValueDouble(env, "latitude", locationInfo->GetLatitude(), result);
171     SetValueDouble(env, "altitude", locationInfo->GetAltitude(), result);
172     SetValueDouble(env, "accuracy", locationInfo->GetAccuracy(), result);
173     SetValueInt64(env, "time", locationInfo->GetTimeStamp(), result);
174 }
175 
GeoAddressesToJsObj(const napi_env & env,std::list<std::shared_ptr<GeoAddress>> & replyList,napi_value & arrayResult)176 bool GeoAddressesToJsObj(const napi_env& env,
177     std::list<std::shared_ptr<GeoAddress>>& replyList, napi_value& arrayResult)
178 {
179     uint32_t idx = 0;
180     for (auto iter = replyList.begin(); iter != replyList.end(); ++iter) {
181         auto geoAddress = *iter;
182         napi_value eachObj;
183         NAPI_CALL_BASE(env, napi_create_object(env, &eachObj), false);
184         SetValueDouble(env, "latitude", geoAddress->GetLatitude(), eachObj);
185         SetValueDouble(env, "longitude", geoAddress->GetLongitude(), eachObj);
186         SetValueUtf8String(env, "locale", geoAddress->locale_.c_str(), eachObj);
187         SetValueUtf8String(env, "placeName", geoAddress->placeName_.c_str(), eachObj);
188         SetValueUtf8String(env, "countryCode", geoAddress->countryCode_.c_str(), eachObj);
189         SetValueUtf8String(env, "countryName", geoAddress->countryName_.c_str(), eachObj);
190         SetValueUtf8String(env, "administrativeArea", geoAddress->administrativeArea_.c_str(), eachObj);
191         SetValueUtf8String(env, "subAdministrativeArea", geoAddress->subAdministrativeArea_.c_str(), eachObj);
192         SetValueUtf8String(env, "locality", geoAddress->locality_.c_str(), eachObj);
193         SetValueUtf8String(env, "subLocality", geoAddress->subLocality_.c_str(), eachObj);
194         SetValueUtf8String(env, "roadName", geoAddress->roadName_.c_str(), eachObj);
195         SetValueUtf8String(env, "subRoadName", geoAddress->subRoadName_.c_str(), eachObj);
196         SetValueUtf8String(env, "premises", geoAddress->premises_.c_str(), eachObj);
197         SetValueUtf8String(env, "postalCode", geoAddress->postalCode_.c_str(), eachObj);
198         SetValueUtf8String(env, "phoneNumber", geoAddress->phoneNumber_.c_str(), eachObj);
199         SetValueUtf8String(env, "addressUrl", geoAddress->addressUrl_.c_str(), eachObj);
200         napi_value descriptionArray;
201         if (geoAddress->descriptionsSize_ > 0) {
202             NAPI_CALL_BASE(env,
203                 napi_create_array_with_length(env, geoAddress->descriptionsSize_, &descriptionArray), false);
204             uint32_t idx1 = 0;
205             for (int index = 0; index < geoAddress->descriptionsSize_; index++) {
206                 napi_value value;
207                 NAPI_CALL_BASE(env, napi_create_string_utf8(env, geoAddress->GetDescriptions(index).c_str(),
208                     NAPI_AUTO_LENGTH, &value), false);
209                 NAPI_CALL_BASE(env, napi_set_element(env, descriptionArray, idx1++, value), false);
210             }
211             SetValueStringArray(env, "descriptions", descriptionArray, eachObj);
212         }
213         SetValueInt32(env, "descriptionsSize", geoAddress->descriptionsSize_, eachObj);
214         if (geoAddress->GetIsSystemApp()) {
215             SetValueBool(env, "isFromMock", geoAddress->isFromMock_, eachObj);
216         }
217         NAPI_CALL_BASE(env, napi_set_element(env, arrayResult, idx++, eachObj), false);
218     }
219     return true;
220 }
221 
LocatingRequiredDataToJsObj(const napi_env & env,std::vector<std::shared_ptr<LocatingRequiredData>> & replyList,napi_value & arrayResult)222 bool LocatingRequiredDataToJsObj(const napi_env& env,
223     std::vector<std::shared_ptr<LocatingRequiredData>>& replyList, napi_value& arrayResult)
224 {
225     uint32_t idx = 0;
226     for (size_t i = 0; i < replyList.size(); i++) {
227         napi_value eachObj;
228         NAPI_CALL_BASE(env, napi_create_object(env, &eachObj), false);
229         napi_value wifiObj;
230         NAPI_CALL_BASE(env, napi_create_object(env, &wifiObj), false);
231         SetValueUtf8String(env, "ssid", replyList[i]->GetWifiScanInfo()->GetSsid().c_str(), wifiObj);
232         SetValueUtf8String(env, "bssid", replyList[i]->GetWifiScanInfo()->GetBssid().c_str(), wifiObj);
233         SetValueInt32(env, "rssi", replyList[i]->GetWifiScanInfo()->GetRssi(), wifiObj);
234         SetValueInt32(env, "frequency", replyList[i]->GetWifiScanInfo()->GetFrequency(), wifiObj);
235         SetValueInt64(env, "timestamp", replyList[i]->GetWifiScanInfo()->GetTimestamp(), wifiObj);
236 
237         napi_value blueToothObj;
238         NAPI_CALL_BASE(env, napi_create_object(env, &blueToothObj), false);
239         SetValueUtf8String(env, "deviceName",
240             replyList[i]->GetBluetoothScanInfo()->GetDeviceName().c_str(), blueToothObj);
241         SetValueUtf8String(env, "macAddress", replyList[i]->GetBluetoothScanInfo()->GetMac().c_str(), blueToothObj);
242         SetValueInt64(env, "rssi", replyList[i]->GetBluetoothScanInfo()->GetRssi(), blueToothObj);
243         SetValueInt64(env, "timestamp", replyList[i]->GetBluetoothScanInfo()->GetTimeStamp(), blueToothObj);
244 
245         NAPI_CALL_BASE(env, napi_set_named_property(env, eachObj, "wifiData", wifiObj), napi_generic_failure);
246         NAPI_CALL_BASE(env, napi_set_named_property(env, eachObj, "bluetoothData", blueToothObj), napi_generic_failure);
247         napi_status status = napi_set_element(env, arrayResult, idx++, eachObj);
248         if (status != napi_ok) {
249             LBSLOGE(LOCATING_DATA_CALLBACK, "set element error: %{public}d, idx: %{public}d", status, idx - 1);
250             return false;
251         }
252     }
253     return true;
254 }
255 
JsObjToCachedLocationRequest(const napi_env & env,const napi_value & object,std::unique_ptr<CachedGnssLocationsRequest> & request)256 void JsObjToCachedLocationRequest(const napi_env& env, const napi_value& object,
257     std::unique_ptr<CachedGnssLocationsRequest>& request)
258 {
259     JsObjectToInt(env, object, "reportingPeriodSec", request->reportingPeriodSec);
260     JsObjectToBool(env, object, "wakeUpCacheQueueFull", request->wakeUpCacheQueueFull);
261 }
262 
JsObjToLocationRequest(const napi_env & env,const napi_value & object,std::unique_ptr<RequestConfig> & requestConfig)263 void JsObjToLocationRequest(const napi_env& env, const napi_value& object,
264     std::unique_ptr<RequestConfig>& requestConfig)
265 {
266     int value = 0;
267     double valueDouble = 0.0;
268     if (JsObjectToInt(env, object, "priority", value) == SUCCESS) {
269         requestConfig->SetPriority(value);
270     }
271     if (JsObjectToInt(env, object, "scenario", value) == SUCCESS ||
272         JsObjectToInt(env, object, "locationScenario", value) == SUCCESS) {
273         requestConfig->SetScenario(value);
274     }
275     if (JsObjectToInt(env, object, "timeInterval", value) == SUCCESS ||
276         JsObjectToInt(env, object, "interval", value) == SUCCESS) {
277         if (value >= 0 && value < 1) {
278             requestConfig->SetTimeInterval(1);
279         } else {
280             requestConfig->SetTimeInterval(value);
281         }
282     }
283     if (JsObjectToDouble(env, object, "maxAccuracy", valueDouble) == SUCCESS) {
284         requestConfig->SetMaxAccuracy(valueDouble);
285     }
286     if (JsObjectToDouble(env, object, "distanceInterval", valueDouble) == SUCCESS) {
287         requestConfig->SetDistanceInterval(valueDouble);
288     }
289 }
290 
JsObjToLocatingRequiredDataConfig(const napi_env & env,const napi_value & object,std::unique_ptr<LocatingRequiredDataConfig> & config)291 void JsObjToLocatingRequiredDataConfig(const napi_env& env, const napi_value& object,
292     std::unique_ptr<LocatingRequiredDataConfig>& config)
293 {
294     int valueInt = 0;
295     bool valueBool = false;
296     if (JsObjectToInt(env, object, "type", valueInt) == SUCCESS) {
297         config->SetType(valueInt);
298     }
299     if (JsObjectToBool(env, object, "needStartScan", valueBool) == SUCCESS) {
300         config->SetNeedStartScan(valueBool);
301     }
302     if (JsObjectToInt(env, object, "scanInterval", valueInt) == SUCCESS) {
303         config->SetScanIntervalMs(valueInt < MIN_WIFI_SCAN_TIME ? MIN_WIFI_SCAN_TIME : valueInt);
304     }
305     if (JsObjectToInt(env, object, "scanTimeout", valueInt) == SUCCESS) {
306         config->SetScanTimeoutMs(valueInt < MIN_WIFI_SCAN_TIME ? MIN_WIFI_SCAN_TIME : valueInt);
307     }
308 }
309 
JsObjToCurrentLocationRequest(const napi_env & env,const napi_value & object,std::unique_ptr<RequestConfig> & requestConfig)310 void JsObjToCurrentLocationRequest(const napi_env& env, const napi_value& object,
311     std::unique_ptr<RequestConfig>& requestConfig)
312 {
313     int value = 0;
314     double valueDouble = 0.0;
315     if (JsObjectToInt(env, object, "priority", value) == SUCCESS ||
316         JsObjectToInt(env, object, "locatingPriority", value) == SUCCESS) {
317         requestConfig->SetPriority(value);
318     }
319     if (JsObjectToInt(env, object, "scenario", value) == SUCCESS) {
320         requestConfig->SetScenario(value);
321     }
322     if (JsObjectToDouble(env, object, "maxAccuracy", valueDouble) == SUCCESS) {
323         requestConfig->SetMaxAccuracy(valueDouble);
324     }
325     if (JsObjectToInt(env, object, "timeoutMs", value) == SUCCESS ||
326         JsObjectToInt(env, object, "locatingTimeoutMs", value) == SUCCESS) {
327         requestConfig->SetTimeOut(value);
328     }
329 }
330 
JsObjToCommand(const napi_env & env,const napi_value & object,std::unique_ptr<LocationCommand> & commandConfig)331 int JsObjToCommand(const napi_env& env, const napi_value& object,
332     std::unique_ptr<LocationCommand>& commandConfig)
333 {
334     if (commandConfig == nullptr) {
335         return COMMON_ERROR;
336     }
337     CHK_ERROR_CODE("scenario", JsObjectToInt(env, object, "scenario", commandConfig->scenario), true);
338     CHK_ERROR_CODE("command", JsObjectToString(env, object, "command", MAX_BUF_LEN, commandConfig->command), true);
339     return SUCCESS;
340 }
341 
JsObjToGeoCodeRequest(const napi_env & env,const napi_value & object,MessageParcel & dataParcel)342 int JsObjToGeoCodeRequest(const napi_env& env, const napi_value& object, MessageParcel& dataParcel)
343 {
344     std::string description = "";
345     int maxItems = 1;
346     double minLatitude = 0.0;
347     double minLongitude = 0.0;
348     double maxLatitude = 0.0;
349     double maxLongitude = 0.0;
350     std::string locale = "";
351     int bufLen = MAX_BUF_LEN;
352     std::string country = "";
353     CHK_ERROR_CODE("locale", JsObjectToString(env, object, "locale", bufLen, locale), false);
354     CHK_ERROR_CODE("description", JsObjectToString(env, object, "description", bufLen, description), true);
355     if (description == "") {
356         LBSLOGE(LOCATOR_STANDARD, "The required description field should not be empty.");
357         return INPUT_PARAMS_ERROR;
358     }
359     CHK_ERROR_CODE("maxItems", JsObjectToInt(env, object, "maxItems", maxItems), false);
360     CHK_ERROR_CODE("minLatitude", JsObjectToDouble(env, object, "minLatitude", minLatitude), false);
361     CHK_ERROR_CODE("minLongitude", JsObjectToDouble(env, object, "minLongitude", minLongitude), false);
362     CHK_ERROR_CODE("maxLatitude", JsObjectToDouble(env, object, "maxLatitude", maxLatitude), false);
363     CHK_ERROR_CODE("maxLongitude", JsObjectToDouble(env, object, "maxLongitude", maxLongitude), false);
364     CHK_ERROR_CODE("country", JsObjectToString(env, object, "country", MAX_BUF_LEN, country), false);
365     if (minLatitude < MIN_LATITUDE || minLatitude > MAX_LATITUDE) {
366         return INPUT_PARAMS_ERROR;
367     }
368     if (minLongitude < MIN_LONGITUDE || minLongitude > MAX_LONGITUDE) {
369         return INPUT_PARAMS_ERROR;
370     }
371     if (maxLatitude < MIN_LATITUDE || maxLatitude > MAX_LATITUDE) {
372         return INPUT_PARAMS_ERROR;
373     }
374     if (maxLongitude < MIN_LONGITUDE || maxLongitude > MAX_LONGITUDE) {
375         return INPUT_PARAMS_ERROR;
376     }
377     if (!dataParcel.WriteInterfaceToken(LocatorProxy::GetDescriptor())) {
378         LBSLOGE(LOCATOR_STANDARD, "write interfaceToken fail!");
379         return COMMON_ERROR;
380     }
381     dataParcel.WriteString16(Str8ToStr16(locale)); // locale
382     dataParcel.WriteString16(Str8ToStr16(description)); // description
383     dataParcel.WriteInt32(maxItems); // maxItems
384     dataParcel.WriteDouble(minLatitude); // latitude
385     dataParcel.WriteDouble(minLongitude); // longitude
386     dataParcel.WriteDouble(maxLatitude); // latitude
387     dataParcel.WriteDouble(maxLongitude); // longitude
388     dataParcel.WriteString16(Str8ToStr16(CommonUtils::GenerateUuid())); // transId
389     dataParcel.WriteString16(Str8ToStr16(country)); // country
390     return SUCCESS;
391 }
392 
JsObjToReverseGeoCodeRequest(const napi_env & env,const napi_value & object,MessageParcel & dataParcel)393 bool JsObjToReverseGeoCodeRequest(const napi_env& env, const napi_value& object, MessageParcel& dataParcel)
394 {
395     double latitude = 0;
396     double longitude = 0;
397     int maxItems = 1;
398     std::string locale = "";
399     std::string country = "";
400 
401     CHK_ERROR_CODE("latitude", JsObjectToDouble(env, object, "latitude", latitude), true);
402     CHK_ERROR_CODE("longitude", JsObjectToDouble(env, object, "longitude", longitude), true);
403     CHK_ERROR_CODE("maxItems", JsObjectToInt(env, object, "maxItems", maxItems), false);
404     CHK_ERROR_CODE("locale", JsObjectToString(env, object, "locale", MAX_BUF_LEN, locale), false); // max bufLen
405     CHK_ERROR_CODE("country", JsObjectToString(env, object, "country", MAX_BUF_LEN, country), false);
406 
407     if (latitude < MIN_LATITUDE || latitude > MAX_LATITUDE) {
408         return false;
409     }
410     if (longitude < MIN_LONGITUDE || longitude > MAX_LONGITUDE) {
411         return false;
412     }
413     if (!dataParcel.WriteInterfaceToken(LocatorProxy::GetDescriptor())) {
414         return false;
415     }
416     dataParcel.WriteString16(Str8ToStr16(locale)); // locale
417     dataParcel.WriteDouble(latitude); // latitude
418     dataParcel.WriteDouble(longitude); // longitude
419     dataParcel.WriteInt32(maxItems); // maxItems
420     dataParcel.WriteString16(Str8ToStr16(CommonUtils::GenerateUuid())); // transId
421     dataParcel.WriteString16(Str8ToStr16(country)); // country
422     return true;
423 }
424 
GetArrayProperty(const napi_env & env,const napi_value & object,const std::string propertyName)425 napi_value GetArrayProperty(const napi_env& env, const napi_value& object, const std::string propertyName)
426 {
427     if (object == nullptr) {
428         LBSLOGE(NAPI_UTILS, "object is nullptr.");
429         return UndefinedNapiValue(env);
430     }
431     bool hasProperty = false;
432     NAPI_CALL_BASE(env,
433         napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), UndefinedNapiValue(env));
434     if (!hasProperty) {
435         LBSLOGE(NAPI_UTILS, "propertyName is not exist");
436         return UndefinedNapiValue(env);
437     }
438     napi_value property = nullptr;
439     NAPI_CALL_BASE(env,
440         napi_get_named_property(env, object, propertyName.c_str(), &property), UndefinedNapiValue(env));
441     bool isArray = false;
442     NAPI_CALL_BASE(env, napi_is_array(env, property, &isArray), UndefinedNapiValue(env));
443     if (!isArray) {
444         LBSLOGE(NAPI_UTILS, "propertyName is not an array!");
445         return UndefinedNapiValue(env);
446     }
447     return property;
448 }
449 
GetLocationInfo(const napi_env & env,const napi_value & object,const char * fieldStr,std::shared_ptr<ReverseGeocodeRequest> & request)450 bool GetLocationInfo(const napi_env& env, const napi_value& object,
451     const char* fieldStr, std::shared_ptr<ReverseGeocodeRequest>& request)
452 {
453     bool result = false;
454     napi_value value = nullptr;
455 
456     if (object == nullptr) {
457         LBSLOGE(LOCATOR_STANDARD, "object is nullptr.");
458         return false;
459     }
460 
461     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &result), false);
462     if (result) {
463         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &value), false);
464         JsObjectToString(env, value, "locale", MAX_BUF_LEN, request->locale);
465         JsObjectToInt(env, value, "maxItems", request->maxItems);
466         JsObjectToDouble(env, value, "latitude", request->latitude);
467         JsObjectToDouble(env, value, "longitude", request->longitude);
468         return true;
469     }
470     return false;
471 }
472 
GetNapiValueByKey(napi_env env,const std::string & keyChar,napi_value object)473 napi_value GetNapiValueByKey(napi_env env, const std::string& keyChar, napi_value object)
474 {
475     if (object == nullptr) {
476         LBSLOGE(LOCATOR_STANDARD, "GetNapiValueByKey object is nullptr.");
477         return nullptr;
478     }
479     bool result = false;
480     NAPI_CALL(env, napi_has_named_property(env, object, keyChar.c_str(), &result));
481     if (result) {
482         napi_value value = nullptr;
483         NAPI_CALL(env, napi_get_named_property(env, object, keyChar.c_str(), &value));
484         return value;
485     }
486     return nullptr;
487 }
488 
GetStringArrayFromJsObj(napi_env env,napi_value value,std::vector<std::string> & outArray)489 bool GetStringArrayFromJsObj(napi_env env, napi_value value, std::vector<std::string>& outArray)
490 {
491     uint32_t arrayLength = 0;
492     NAPI_CALL_BASE(env, napi_get_array_length(env, value, &arrayLength), false);
493     if (arrayLength == 0) {
494         LBSLOGE(LOCATOR_STANDARD, "The array is empty.");
495         return false;
496     }
497     for (size_t i = 0; i < arrayLength; i++) {
498         napi_value napiElement = nullptr;
499         NAPI_CALL_BASE(env, napi_get_element(env, value, i, &napiElement), false);
500         napi_valuetype napiValueType = napi_undefined;
501         NAPI_CALL_BASE(env, napi_typeof(env, napiElement, &napiValueType), false);
502         if (napiValueType != napi_string) {
503             LBSLOGE(LOCATOR_STANDARD, "wrong argument type.");
504             return false;
505         }
506         char type[64] = {0}; // max length
507         size_t typeLen = 0;
508         NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, napiElement, type, sizeof(type), &typeLen), false);
509         std::string event = type;
510         outArray.push_back(event);
511     }
512     return true;
513 }
514 
GetStringArrayValueByKey(napi_env env,napi_value jsObject,const std::string & key,std::vector<std::string> & outArray)515 bool GetStringArrayValueByKey(
516     napi_env env, napi_value jsObject, const std::string& key, std::vector<std::string>& outArray)
517 {
518     napi_value array = GetNapiValueByKey(env, key, jsObject);
519     if (array == nullptr) {
520         return false;
521     }
522     bool isArray = false;
523     NAPI_CALL_BASE(env, napi_is_array(env, array, &isArray), false);
524     if (!isArray) {
525         LBSLOGE(LOCATOR_STANDARD, "not an array!");
526         return false;
527     }
528     return GetStringArrayFromJsObj(env, array, outArray);
529 }
530 
GetGeoAddressInfo(const napi_env & env,const napi_value & object,const std::string & fieldStr,std::shared_ptr<GeoAddress> address)531 bool GetGeoAddressInfo(const napi_env& env, const napi_value& object,
532     const std::string& fieldStr, std::shared_ptr<GeoAddress> address)
533 {
534     napi_value value = GetNapiValueByKey(env, fieldStr, object);
535     if (value == nullptr) {
536         LBSLOGE(LOCATOR_STANDARD, "GetNapiValueByKey is nullptr.");
537         return false;
538     }
539     int bufLen = MAX_BUF_LEN;
540     JsObjectToDouble(env, value, "latitude", address->latitude_);
541     JsObjectToDouble(env, value, "longitude", address->longitude_);
542     JsObjectToString(env, value, "locale", bufLen, address->locale_);
543     JsObjectToString(env, value, "placeName", bufLen, address->placeName_);
544     JsObjectToString(env, value, "countryCode", bufLen, address->countryCode_);
545     JsObjectToString(env, value, "countryName", bufLen, address->countryName_);
546     JsObjectToString(env, value, "administrativeArea", bufLen, address->administrativeArea_);
547     JsObjectToString(env, value, "subAdministrativeArea", bufLen, address->subAdministrativeArea_);
548     JsObjectToString(env, value, "locality", bufLen, address->locality_);
549     JsObjectToString(env, value, "subLocality", bufLen, address->subLocality_);
550     JsObjectToString(env, value, "roadName", bufLen, address->roadName_);
551     JsObjectToString(env, value, "subRoadName", bufLen, address->subRoadName_);
552     JsObjectToString(env, value, "premises", bufLen, address->premises_);
553     JsObjectToString(env, value, "postalCode", bufLen, address->postalCode_);
554     JsObjectToString(env, value, "phoneNumber", bufLen, address->phoneNumber_);
555     JsObjectToString(env, value, "addressUrl", bufLen, address->addressUrl_);
556     JsObjectToInt(env, value, "descriptionsSize", address->descriptionsSize_);
557     JsObjectToBool(env, value, "isFromMock", address->isFromMock_);
558     std::vector<std::string> descriptions;
559     GetStringArrayValueByKey(env, value, "descriptions", descriptions);
560     size_t size = static_cast<size_t>(address->descriptionsSize_) > descriptions.size() ?
561         descriptions.size() : static_cast<size_t>(address->descriptionsSize_);
562     for (size_t i = 0; i < size; i++) {
563         address->descriptions_.insert(std::make_pair(i, descriptions[i]));
564     }
565     return true;
566 }
567 
JsObjToRevGeocodeMock(const napi_env & env,const napi_value & object,std::vector<std::shared_ptr<GeocodingMockInfo>> & mockInfo)568 bool JsObjToRevGeocodeMock(const napi_env& env, const napi_value& object,
569     std::vector<std::shared_ptr<GeocodingMockInfo>>& mockInfo)
570 {
571     bool isArray = false;
572     NAPI_CALL_BASE(env, napi_is_array(env, object, &isArray), false);
573     if (!isArray) {
574         LBSLOGE(LOCATOR_STANDARD, "JsObjToRevGeocodeMock:not an array!");
575         return false;
576     }
577     uint32_t arrayLength = 0;
578     NAPI_CALL_BASE(env, napi_get_array_length(env, object, &arrayLength), false);
579     if (arrayLength == 0) {
580         LBSLOGE(LOCATOR_STANDARD, "JsObjToRevGeocodeMock:The array is empty.");
581         return false;
582     }
583     for (size_t i = 0; i < arrayLength; i++) {
584         napi_value napiElement = nullptr;
585         NAPI_CALL_BASE(env, napi_get_element(env, object, i, &napiElement), false);
586         std::shared_ptr<GeocodingMockInfo> info = std::make_shared<GeocodingMockInfo>();
587         std::shared_ptr<ReverseGeocodeRequest> request = std::make_shared<ReverseGeocodeRequest>();
588         std::shared_ptr<GeoAddress> geoAddress = std::make_shared<GeoAddress>();
589         GetLocationInfo(env, napiElement, "location", request);
590         GetGeoAddressInfo(env, napiElement, "geoAddress", geoAddress);
591         info->SetLocation(request);
592         info->SetGeoAddressInfo(geoAddress);
593         mockInfo.push_back(info);
594     }
595     return true;
596 }
597 
GetLocationArray(const napi_env & env,LocationMockAsyncContext * asyncContext,const napi_value & object)598 void GetLocationArray(const napi_env& env, LocationMockAsyncContext *asyncContext, const napi_value& object)
599 {
600     uint32_t arrayLength = 0;
601     NAPI_CALL_RETURN_VOID(env, napi_get_array_length(env, object, &arrayLength));
602     if (arrayLength == 0) {
603         LBSLOGE(LOCATOR_STANDARD, "The array is empty.");
604         return;
605     }
606     for (uint32_t i = 0; i < arrayLength; i++) {
607         napi_value elementValue = nullptr;
608         std::shared_ptr<Location> locationAdapter = std::make_shared<Location>();
609         NAPI_CALL_RETURN_VOID(env, napi_get_element(env, object, i, &elementValue));
610         double latitude = 0.0;
611         JsObjectToDouble(env, elementValue, "latitude", latitude);
612         locationAdapter->SetLatitude(latitude);
613         double longitude = 0.0;
614         JsObjectToDouble(env, elementValue, "longitude", longitude);
615         locationAdapter->SetLongitude(longitude);
616         double altitude = 0.0;
617         JsObjectToDouble(env, elementValue, "altitude", altitude);
618         locationAdapter->SetAltitude(altitude);
619         double accuracy = 0.0;
620         JsObjectToDouble(env, elementValue, "accuracy", accuracy);
621         locationAdapter->SetAccuracy(accuracy);
622         double speed = 0.0;
623         JsObjectToDouble(env, elementValue, "speed", speed);
624         locationAdapter->SetSpeed(speed);
625         double direction = 0.0;
626         JsObjectToDouble(env, elementValue, "direction", direction);
627         locationAdapter->SetDirection(direction);
628         int64_t timeStamp = 0;
629         JsObjectToInt64(env, elementValue, "timeStamp", timeStamp);
630         locationAdapter->SetTimeStamp(timeStamp);
631         int64_t timeSinceBoot = 0;
632         JsObjectToInt64(env, elementValue, "timeSinceBoot", timeSinceBoot);
633         locationAdapter->SetTimeSinceBoot(timeSinceBoot);
634         int32_t additionSize = 0;
635         JsObjectToInt(env, elementValue, "additionSize", additionSize);
636         locationAdapter->SetAdditionSize(static_cast<int64_t>(additionSize));
637         bool isFromMock = false;
638         JsObjectToBool(env, elementValue, "isFromMock", isFromMock);
639         locationAdapter->SetIsFromMock(isFromMock ? 1 : 0);
640         std::vector<std::string> additions;
641         GetStringArrayValueByKey(env, elementValue, "additions", additions);
642         locationAdapter->SetAdditions(additions, false);
643         asyncContext->LocationNapi.push_back(locationAdapter);
644     }
645 }
646 
JsObjectToString(const napi_env & env,const napi_value & object,const char * fieldStr,const int bufLen,std::string & fieldRef)647 int JsObjectToString(const napi_env& env, const napi_value& object,
648     const char* fieldStr, const int bufLen, std::string& fieldRef)
649 {
650     bool hasProperty = false;
651     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), COMMON_ERROR);
652     if (hasProperty) {
653         napi_value field;
654         napi_valuetype valueType;
655 
656         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &field), COMMON_ERROR);
657         NAPI_CALL_BASE(env, napi_typeof(env, field, &valueType), COMMON_ERROR);
658         if (valueType != napi_string) {
659             LBSLOGE(LOCATOR_STANDARD, "JsObjectToString, valueType != napi_string.");
660             return INPUT_PARAMS_ERROR;
661         }
662         if (bufLen <= 0) {
663             LBSLOGE(LOCATOR_STANDARD, "The length of buf should be greater than 0.");
664             return COMMON_ERROR;
665         }
666         int32_t actBuflen = bufLen + 1;
667         std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBuflen);
668         (void)memset_s(buf.get(), actBuflen, 0, actBuflen);
669         size_t result = 0;
670         NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, field, buf.get(), actBuflen, &result), COMMON_ERROR);
671         fieldRef = buf.get();
672         return SUCCESS;
673     }
674     LBSLOGD(LOCATOR_STANDARD, "Js obj to str no property: %{public}s", fieldStr);
675     return PARAM_IS_EMPTY;
676 }
677 
JsObjectToDouble(const napi_env & env,const napi_value & object,const char * fieldStr,double & fieldRef)678 int JsObjectToDouble(const napi_env& env, const napi_value& object, const char* fieldStr, double& fieldRef)
679 {
680     bool hasProperty = false;
681     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), COMMON_ERROR);
682     if (hasProperty) {
683         napi_value field;
684         napi_valuetype valueType;
685 
686         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &field), COMMON_ERROR);
687         NAPI_CALL_BASE(env, napi_typeof(env, field, &valueType), COMMON_ERROR);
688         NAPI_ASSERT_BASE(env, valueType == napi_number, "Wrong argument type.", INPUT_PARAMS_ERROR);
689         NAPI_CALL_BASE(env, napi_get_value_double(env, field, &fieldRef), COMMON_ERROR);
690         return SUCCESS;
691     }
692     LBSLOGD(LOCATOR_STANDARD, "Js to int no property: %{public}s", fieldStr);
693     return PARAM_IS_EMPTY;
694 }
695 
JsObjectToInt(const napi_env & env,const napi_value & object,const char * fieldStr,int & fieldRef)696 int JsObjectToInt(const napi_env& env, const napi_value& object, const char* fieldStr, int& fieldRef)
697 {
698     bool hasProperty = false;
699     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), COMMON_ERROR);
700     if (hasProperty) {
701         napi_value field;
702         napi_valuetype valueType;
703 
704         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &field), COMMON_ERROR);
705         NAPI_CALL_BASE(env, napi_typeof(env, field, &valueType), COMMON_ERROR);
706         NAPI_ASSERT_BASE(env, valueType == napi_number, "Wrong argument type.", INPUT_PARAMS_ERROR);
707         NAPI_CALL_BASE(env, napi_get_value_int32(env, field, &fieldRef), COMMON_ERROR);
708         return SUCCESS;
709     }
710     LBSLOGD(LOCATOR_STANDARD, "Js to int no property: %{public}s", fieldStr);
711     return PARAM_IS_EMPTY;
712 }
713 
JsObjectToInt64(const napi_env & env,const napi_value & object,const char * fieldStr,int64_t & fieldRef)714 int JsObjectToInt64(const napi_env& env, const napi_value& object, const char* fieldStr, int64_t& fieldRef)
715 {
716     bool hasProperty = false;
717     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), COMMON_ERROR);
718     if (hasProperty) {
719         napi_value field;
720         napi_valuetype valueType;
721 
722         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &field), COMMON_ERROR);
723         NAPI_CALL_BASE(env, napi_typeof(env, field, &valueType), COMMON_ERROR);
724         NAPI_ASSERT_BASE(env, valueType == napi_number, "Wrong argument type.", INPUT_PARAMS_ERROR);
725         NAPI_CALL_BASE(env, napi_get_value_int64(env, field, &fieldRef), COMMON_ERROR);
726         return SUCCESS;
727     }
728     LBSLOGD(LOCATOR_STANDARD, "Js to int no property: %{public}s", fieldStr);
729     return PARAM_IS_EMPTY;
730 }
731 
JsObjectToBool(const napi_env & env,const napi_value & object,const char * fieldStr,bool & fieldRef)732 int JsObjectToBool(const napi_env& env, const napi_value& object, const char* fieldStr, bool& fieldRef)
733 {
734     bool hasProperty = false;
735     NAPI_CALL_BASE(env, napi_has_named_property(env, object, fieldStr, &hasProperty), COMMON_ERROR);
736     if (hasProperty) {
737         napi_value field;
738         napi_valuetype valueType;
739 
740         NAPI_CALL_BASE(env, napi_get_named_property(env, object, fieldStr, &field), COMMON_ERROR);
741         NAPI_CALL_BASE(env, napi_typeof(env, field, &valueType), COMMON_ERROR);
742         NAPI_ASSERT_BASE(env, valueType == napi_boolean, "Wrong argument type.", INPUT_PARAMS_ERROR);
743         NAPI_CALL_BASE(env, napi_get_value_bool(env, field, &fieldRef), COMMON_ERROR);
744         return SUCCESS;
745     }
746     LBSLOGD(LOCATOR_STANDARD, "Js to bool no property: %{public}s", fieldStr);
747     return PARAM_IS_EMPTY;
748 }
749 
SetValueUtf8String(const napi_env & env,const char * fieldStr,const char * str,napi_value & result)750 napi_status SetValueUtf8String(const napi_env& env, const char* fieldStr, const char* str, napi_value& result)
751 {
752     napi_value value = nullptr;
753     NAPI_CALL_BASE(env, napi_create_string_utf8(env, str, NAPI_AUTO_LENGTH, &value), napi_generic_failure);
754     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
755     return napi_ok;
756 }
757 
SetValueStringArray(const napi_env & env,const char * fieldStr,napi_value & value,napi_value & result)758 napi_status SetValueStringArray(const napi_env& env, const char* fieldStr, napi_value& value, napi_value& result)
759 {
760     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
761     return napi_ok;
762 }
763 
SetValueStringMap(const napi_env & env,const char * fieldStr,napi_value & value,napi_value & result)764 napi_status SetValueStringMap(const napi_env& env, const char* fieldStr, napi_value& value, napi_value& result)
765 {
766     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
767     return napi_ok;
768 }
769 
SetValueInt32(const napi_env & env,const char * fieldStr,const int intValue,napi_value & result)770 napi_status SetValueInt32(const napi_env& env, const char* fieldStr, const int intValue, napi_value& result)
771 {
772     napi_value value = nullptr;
773     NAPI_CALL_BASE(env, napi_create_int32(env, intValue, &value), napi_generic_failure);
774     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
775     return napi_ok;
776 }
777 
SetValueInt64(const napi_env & env,const char * fieldStr,const int64_t intValue,napi_value & result)778 napi_status SetValueInt64(const napi_env& env, const char* fieldStr, const int64_t intValue, napi_value& result)
779 {
780     napi_value value = nullptr;
781     NAPI_CALL_BASE(env, napi_create_int64(env, intValue, &value), napi_generic_failure);
782     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
783     return napi_ok;
784 }
785 
SetValueDouble(const napi_env & env,const char * fieldStr,const double doubleValue,napi_value & result)786 napi_status SetValueDouble(const napi_env& env, const char* fieldStr, const double doubleValue, napi_value& result)
787 {
788     napi_value value = nullptr;
789     NAPI_CALL_BASE(env, napi_create_double(env, doubleValue, &value), napi_generic_failure);
790     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
791     return napi_ok;
792 }
793 
SetValueBool(const napi_env & env,const char * fieldStr,const bool boolvalue,napi_value & result)794 napi_status SetValueBool(const napi_env& env, const char* fieldStr, const bool boolvalue, napi_value& result)
795 {
796     napi_value value = nullptr;
797     NAPI_CALL_BASE(env, napi_get_boolean(env, boolvalue, &value), napi_generic_failure);
798     NAPI_CALL_BASE(env, napi_set_named_property(env, result, fieldStr, value), napi_generic_failure);
799     return napi_ok;
800 }
801 
InitAsyncCallBackEnv(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t objectArgsNum)802 static bool InitAsyncCallBackEnv(const napi_env& env, AsyncContext* asyncContext,
803     const size_t argc, const napi_value* argv, const size_t objectArgsNum)
804 {
805     if (asyncContext == nullptr || argv == nullptr ||
806         argc > MAXIMUM_JS_PARAMS || objectArgsNum > MAXIMUM_JS_PARAMS) {
807         return false;
808     }
809     size_t startLoop = objectArgsNum;
810     size_t endLoop = argc;
811     for (size_t i = startLoop; i < endLoop; ++i) {
812         napi_valuetype valuetype;
813         NAPI_CALL_BASE(env, napi_typeof(env, argv[i], &valuetype), false);
814         NAPI_ASSERT_BASE(env, valuetype == napi_function,  "Wrong argument type.", false);
815         size_t index = i - startLoop;
816         if (index >= MAX_CALLBACK_NUM) {
817             break;
818         }
819         NAPI_CALL_BASE(env, napi_create_reference(env, argv[i], 1, &asyncContext->callback[index]), false);
820     }
821     return true;
822 }
823 
InitAsyncPromiseEnv(const napi_env & env,AsyncContext * asyncContext,napi_value & promise)824 static bool InitAsyncPromiseEnv(const napi_env& env, AsyncContext *asyncContext, napi_value& promise)
825 {
826     napi_deferred deferred;
827     if (asyncContext == nullptr) {
828         return false;
829     }
830     NAPI_CALL_BASE(env, napi_create_promise(env, &deferred, &promise), false);
831     asyncContext->deferred = deferred;
832     return true;
833 }
834 
CreateFailCallBackParams(AsyncContext & context,const std::string & msg,int32_t errorCode)835 void CreateFailCallBackParams(AsyncContext& context, const std::string& msg, int32_t errorCode)
836 {
837     SetValueUtf8String(context.env, "data", msg.c_str(), context.result[PARAM0]);
838     SetValueInt32(context.env, "code", errorCode, context.result[PARAM1]);
839 }
840 
GetErrorMsgByCode(int code)841 std::string GetErrorMsgByCode(int code)
842 {
843     static std::map<int, std::string> errorCodeMap = {
844         {SUCCESS, "SUCCESS"},
845         {NOT_SUPPORTED, "NOT_SUPPORTED"},
846         {INPUT_PARAMS_ERROR, "INPUT_PARAMS_ERROR"},
847         {REVERSE_GEOCODE_ERROR, "REVERSE_GEOCODE_ERROR"},
848         {GEOCODE_ERROR, "GEOCODE_ERROR"},
849         {LOCATOR_ERROR, "LOCATOR_ERROR"},
850         {LOCATION_SWITCH_ERROR, "LOCATION_SWITCH_ERROR"},
851         {LAST_KNOWN_LOCATION_ERROR, "LAST_KNOWN_LOCATION_ERROR"},
852         {LOCATION_REQUEST_TIMEOUT_ERROR, "LOCATION_REQUEST_TIMEOUT_ERROR"},
853         {QUERY_COUNTRY_CODE_ERROR, "QUERY_COUNTRY_CODE_ERROR"},
854         {LocationErrCode::ERRCODE_SUCCESS, "SUCCESS."},
855         {LocationErrCode::ERRCODE_PERMISSION_DENIED,
856             "Permission verification failed. The application does not have the permission required to call the API."},
857         {LocationErrCode::ERRCODE_SYSTEM_PERMISSION_DENIED,
858             "Permission verification failed. A non-system application calls a system API."},
859         {LocationErrCode::ERRCODE_INVALID_PARAM,
860             "Parameter error. Possible causes:1.Mandatory parameters are left unspecified;" \
861             "2.Incorrect parameter types;3. Parameter verification failed."},
862         {LocationErrCode::ERRCODE_NOT_SUPPORTED,
863             "Capability not supported." \
864             "Failed to call function due to limited device capabilities."},
865         {LocationErrCode::ERRCODE_SERVICE_UNAVAILABLE, "The location service is unavailable."},
866         {LocationErrCode::ERRCODE_SWITCH_OFF, "The location switch is off."},
867         {LocationErrCode::ERRCODE_LOCATING_FAIL, "Failed to obtain the geographical location."},
868         {LocationErrCode::ERRCODE_REVERSE_GEOCODING_FAIL, "Reverse geocoding query failed."},
869         {LocationErrCode::ERRCODE_GEOCODING_FAIL, "Geocoding query failed."},
870         {LocationErrCode::ERRCODE_COUNTRYCODE_FAIL, "Failed to query the area information."},
871         {LocationErrCode::ERRCODE_GEOFENCE_FAIL, "Failed to operate the geofence."},
872         {LocationErrCode::ERRCODE_NO_RESPONSE, "No response to the request."},
873         {LocationErrCode::ERRCODE_WIFI_IS_NOT_CONNECTED,
874             "Failed to obtain the hotpot MAC address because the Wi-Fi is not connected."},
875         {LocationErrCode::ERRCODE_GEOFENCE_EXCEED_MAXIMUM, "The number of geofences exceeds the maximum."},
876         {LocationErrCode::ERRCODE_GEOFENCE_INCORRECT_ID, "Failed to delete a geofence due to an incorrect ID."},
877     };
878 
879     auto iter = errorCodeMap.find(code);
880     if (iter != errorCodeMap.end()) {
881         std::string errMessage = "BussinessError ";
882         errMessage.append(std::to_string(code)).append(": ").append(iter->second);
883         return errMessage;
884     }
885     return "undefined error.";
886 }
887 
GetErrorObject(napi_env env,const int32_t errCode,const std::string & errMsg)888 napi_value GetErrorObject(napi_env env, const int32_t errCode, const std::string& errMsg)
889 {
890     napi_value businessError = nullptr;
891     napi_value eCode = nullptr;
892     napi_value eMsg = nullptr;
893     NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
894     NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(), errMsg.length(), &eMsg));
895     NAPI_CALL(env, napi_create_object(env, &businessError));
896     NAPI_CALL(env, napi_set_named_property(env, businessError, "code", eCode));
897     NAPI_CALL(env, napi_set_named_property(env, businessError, "message", eMsg));
898     return businessError;
899 }
900 
CreateResultObject(const napi_env & env,AsyncContext * context)901 void CreateResultObject(const napi_env& env, AsyncContext* context)
902 {
903     if (context == nullptr || env == nullptr) {
904         LBSLOGE(LOCATOR_STANDARD, "CreateResultObject input para error");
905         return;
906     }
907     if (context->errCode != SUCCESS) {
908         std::string errMsg = GetErrorMsgByCode(context->errCode);
909         context->result[PARAM0] = GetErrorObject(env, context->errCode, errMsg);
910         NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &context->result[PARAM1]));
911     } else {
912         NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &context->result[PARAM0]));
913     }
914 }
915 
SendResultToJs(const napi_env & env,AsyncContext * context)916 void SendResultToJs(const napi_env& env, AsyncContext* context)
917 {
918     if (context == nullptr || env == nullptr) {
919         LBSLOGE(LOCATOR_STANDARD, "SendResultToJs input para error");
920         return;
921     }
922 
923     bool isPromise = context->deferred != nullptr;
924     if (isPromise) {
925         if (context->errCode != SUCCESS) {
926             NAPI_CALL_RETURN_VOID(env,
927                 napi_reject_deferred(env, context->deferred, context->result[PARAM0]));
928         } else {
929             NAPI_CALL_RETURN_VOID(env,
930                 napi_resolve_deferred(env, context->deferred, context->result[PARAM1]));
931         }
932     } else {
933         napi_value undefine;
934         NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefine));
935         napi_value callback;
936         NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context->callback[0], &callback));
937         NAPI_CALL_RETURN_VOID(env,
938             napi_call_function(env, nullptr, callback, RESULT_SIZE, context->result, &undefine));
939     }
940 }
941 
MemoryReclamation(const napi_env & env,AsyncContext * context)942 void MemoryReclamation(const napi_env& env, AsyncContext* context)
943 {
944     if (context == nullptr || env == nullptr) {
945         LBSLOGE(LOCATOR_STANDARD, "MemoryReclamation input para error");
946         return;
947     }
948 
949     if (context->callback[SUCCESS_CALLBACK] != nullptr) {
950         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callback[SUCCESS_CALLBACK]));
951     }
952     if (context->callback[FAIL_CALLBACK] != nullptr) {
953         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callback[FAIL_CALLBACK]));
954     }
955     if (context->callback[COMPLETE_CALLBACK] != nullptr) {
956         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callback[COMPLETE_CALLBACK]));
957     }
958     NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, context->work));
959     delete context;
960 }
961 
CreateAsyncWork(const napi_env & env,AsyncContext * asyncContext)962 static napi_value CreateAsyncWork(const napi_env& env, AsyncContext* asyncContext)
963 {
964     if (asyncContext == nullptr) {
965         return UndefinedNapiValue(env);
966     }
967     NAPI_CALL(env, napi_create_async_work(
968         env, nullptr, asyncContext->resourceName,
969         [](napi_env env, void* data) {
970             if (data == nullptr) {
971                 LBSLOGE(LOCATOR_STANDARD, "Async data parameter is null");
972                 return;
973             }
974             AsyncContext* context = static_cast<AsyncContext *>(data);
975             context->executeFunc(context);
976         },
977         [](napi_env env, napi_status status, void* data) {
978             if (data == nullptr) {
979                 LBSLOGE(LOCATOR_STANDARD, "Async data parameter is null");
980                 return;
981             }
982             AsyncContext* context = static_cast<AsyncContext *>(data);
983             context->completeFunc(data);
984             CreateResultObject(env, context);
985             SendResultToJs(env, context);
986             MemoryReclamation(env, context);
987         }, static_cast<void*>(asyncContext), &asyncContext->work));
988     NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
989     return UndefinedNapiValue(env);
990 }
991 
DoAsyncWork(const napi_env & env,AsyncContext * asyncContext,const size_t argc,const napi_value * argv,const size_t objectArgsNum)992 napi_value DoAsyncWork(const napi_env& env, AsyncContext* asyncContext,
993     const size_t argc, const napi_value* argv, const size_t objectArgsNum)
994 {
995     if (asyncContext == nullptr || argv == nullptr) {
996         return UndefinedNapiValue(env);
997     }
998     if (argc > objectArgsNum) {
999         InitAsyncCallBackEnv(env, asyncContext, argc, argv, objectArgsNum);
1000         return CreateAsyncWork(env, asyncContext);
1001     } else {
1002         napi_value promise;
1003         InitAsyncPromiseEnv(env, asyncContext, promise);
1004         CreateAsyncWork(env, asyncContext);
1005         return promise;
1006     }
1007 }
1008 
DeleteQueueWork(AsyncContext * context)1009 void DeleteQueueWork(AsyncContext* context)
1010 {
1011     uv_loop_s *loop = nullptr;
1012     if (context->env == nullptr) {
1013         LBSLOGE(LOCATOR_STANDARD, "env is nullptr.");
1014         delete context;
1015         return;
1016     }
1017     NAPI_CALL_RETURN_VOID(context->env, napi_get_uv_event_loop(context->env, &loop));
1018     if (loop == nullptr) {
1019         LBSLOGE(LOCATOR_STANDARD, "loop == nullptr.");
1020         delete context;
1021         return;
1022     }
1023     uv_work_t *work = new (std::nothrow) uv_work_t;
1024     if (work == nullptr) {
1025         LBSLOGE(LOCATOR_STANDARD, "work == nullptr.");
1026         delete context;
1027         return;
1028     }
1029     work->data = context;
1030     DeleteCallbackHandler(loop, work);
1031 }
1032 
DeleteCallbackHandler(uv_loop_s * & loop,uv_work_t * & work)1033 void DeleteCallbackHandler(uv_loop_s *&loop, uv_work_t *&work)
1034 {
1035     uv_queue_work(loop, work, [](uv_work_t *work) {},
1036         [](uv_work_t *work, int status) {
1037             AsyncContext *context = nullptr;
1038             napi_handle_scope scope = nullptr;
1039             if (work == nullptr) {
1040                 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr");
1041                 return;
1042             }
1043             context = static_cast<AsyncContext *>(work->data);
1044             if (context == nullptr || context->env == nullptr) {
1045                 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr");
1046                 delete work;
1047                 return;
1048             }
1049             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
1050             if (scope == nullptr) {
1051                 LBSLOGE(LOCATOR_CALLBACK, "scope is nullptr");
1052                 delete context;
1053                 delete work;
1054                 return;
1055             }
1056             if (context->callback[SUCCESS_CALLBACK] != nullptr) {
1057                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
1058                     napi_delete_reference(context->env, context->callback[SUCCESS_CALLBACK]),
1059                     scope, context, work);
1060             }
1061             if (context->callback[FAIL_CALLBACK] != nullptr) {
1062                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
1063                     napi_delete_reference(context->env, context->callback[FAIL_CALLBACK]),
1064                     scope, context, work);
1065             }
1066             if (context->callback[COMPLETE_CALLBACK] != nullptr) {
1067                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
1068                     napi_delete_reference(context->env, context->callback[COMPLETE_CALLBACK]),
1069                     scope, context, work);
1070             }
1071             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
1072             delete context;
1073             delete work;
1074     });
1075 }
1076 
CheckIfParamIsFunctionType(napi_env env,napi_value param)1077 bool CheckIfParamIsFunctionType(napi_env env, napi_value param)
1078 {
1079     napi_valuetype valueType;
1080     NAPI_CALL_BASE(env, napi_typeof(env, param, &valueType), false);
1081     if (valueType != napi_function) {
1082         return false;
1083     }
1084     return true;
1085 }
1086 
SetEnumPropertyByInteger(napi_env env,napi_value dstObj,int32_t enumValue,const char * enumName)1087 napi_value SetEnumPropertyByInteger(napi_env env, napi_value dstObj, int32_t enumValue, const char *enumName)
1088 {
1089     napi_value enumProp = nullptr;
1090     NAPI_CALL(env, napi_create_int32(env, enumValue, &enumProp));
1091     NAPI_CALL(env, napi_set_named_property(env, dstObj, enumName, enumProp));
1092     return enumProp;
1093 }
1094 
CheckIfParamIsObjectType(napi_env env,napi_value param)1095 bool CheckIfParamIsObjectType(napi_env env, napi_value param)
1096 {
1097     napi_valuetype valueType;
1098     NAPI_CALL_BASE(env, napi_typeof(env, param, &valueType), false);
1099     if (valueType != napi_object) {
1100         return false;
1101     }
1102     return true;
1103 }
1104 }  // namespace Location
1105 }  // namespace OHOS
1106