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 "location_napi_system.h"
17
18#include "locator_callback_napi.h"
19#include "location_log.h"
20#include "locator.h"
21#include "napi_util.h"
22
23namespace OHOS {
24namespace Location {
25sptr<LocatorCallbackNapi> g_systemSingleLocatorCallbackHost =
26    sptr<LocatorCallbackNapi>(new (std::nothrow)LocatorCallbackNapi());
27sptr<LocatorCallbackNapi> g_systemSubcribeCallbackHost =
28    sptr<LocatorCallbackNapi>(new (std::nothrow)LocatorCallbackNapi());
29auto g_locatorImpl = Locator::GetInstance();
30
31napi_value GetLocationOnce(const napi_env& env,
32                           const napi_ref& successHandlerRef,
33                           const napi_ref& failHandlerRef,
34                           const napi_ref& completeHandlerRef,
35                           int fixNumber)
36{
37    NAPI_ASSERT(env, g_locatorImpl != nullptr, "get locator SA failed");
38    auto requestConfig = std::make_unique<RequestConfig>();
39    auto locatorCallback = sptr<ILocatorCallback>(g_systemSingleLocatorCallbackHost);
40    requestConfig->SetPriority(PRIORITY_FAST_FIRST_FIX);
41    requestConfig->SetFixNumber(fixNumber);
42    if (g_systemSingleLocatorCallbackHost->GetSuccHandleCb() != nullptr ||
43        g_systemSingleLocatorCallbackHost->GetFailHandleCb() != nullptr ||
44        g_systemSingleLocatorCallbackHost->GetCompleteHandleCb() != nullptr) {
45        LBSLOGI(LOCATION_NAPI, "handlers is not nullptr, stop locating first");
46        g_locatorImpl->StopLocating(locatorCallback);
47        if (env == g_systemSingleLocatorCallbackHost->GetEnv()) {
48            g_systemSingleLocatorCallbackHost->DeleteAllCallbacks();
49        }
50    }
51    g_systemSingleLocatorCallbackHost->SetEnv(env);
52    g_systemSingleLocatorCallbackHost->SetFixNumber(fixNumber);
53    g_systemSingleLocatorCallbackHost->SetSuccHandleCb(successHandlerRef);
54    g_systemSingleLocatorCallbackHost->SetFailHandleCb(failHandlerRef);
55    g_systemSingleLocatorCallbackHost->SetCompleteHandleCb(completeHandlerRef);
56    g_locatorImpl->StartLocating(requestConfig, locatorCallback);
57    return UndefinedNapiValue(env);
58}
59
60void GetAllCallback(const napi_env &env, const napi_value &argv, napi_ref &successHandlerRef,
61    napi_ref &failHandlerRef, napi_ref &completeHandlerRef)
62{
63    bool hasProperty = false;
64    napi_value nVsuccessCallback = nullptr;
65    napi_value nVfailCallback = nullptr;
66    napi_value nVcompleteCallback = nullptr;
67    NAPI_CALL_RETURN_VOID(env, napi_has_named_property(env, argv, "success", &hasProperty));
68    if (hasProperty) {
69        NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "success", &nVsuccessCallback));
70        NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, nVsuccessCallback, 1, &successHandlerRef));
71    }
72    hasProperty = false;
73    NAPI_CALL_RETURN_VOID(env, napi_has_named_property(env, argv, "fail", &hasProperty));
74    if (hasProperty) {
75        NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "fail", &nVfailCallback));
76        NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, nVfailCallback, 1, &failHandlerRef));
77    }
78    hasProperty = false;
79    NAPI_CALL_RETURN_VOID(env, napi_has_named_property(env, argv, "complete", &hasProperty));
80    if (hasProperty) {
81        NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "complete", &nVcompleteCallback));
82        NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, nVcompleteCallback, 1, &completeHandlerRef));
83    }
84}
85
86napi_value GetLocation(napi_env env, napi_callback_info cbinfo)
87{
88    size_t argc = MAXIMUM_JS_PARAMS;
89    napi_value argv[MAXIMUM_JS_PARAMS] = {0};
90    napi_value thisVar = nullptr;
91    napi_value result = nullptr;
92    NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
93    napi_valuetype valueType = napi_undefined;
94    NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
95    NAPI_ASSERT(env, argc == 1, "number of parameters is error");
96    NAPI_ASSERT(env, valueType == napi_object, "type of parameters is error");
97    NAPI_ASSERT(env, g_locatorImpl != nullptr, "get locator SA failed");
98    napi_value nVtimeout;
99    napi_value nVcoordType;
100    int32_t timeout = 0;
101    napi_ref successHandlerRef = nullptr;
102    napi_ref failHandlerRef = nullptr;
103    napi_ref completeHandlerRef = nullptr;
104    bool hasProperty = false;
105    NAPI_CALL(env, napi_has_named_property(env, argv[0], "timeout", &hasProperty));
106    if (hasProperty) {
107        NAPI_CALL(env, napi_get_named_property(env, argv[0], "timeout", &nVtimeout));
108        NAPI_CALL(env, napi_get_value_int32(env, nVtimeout, &timeout));
109    }
110    hasProperty = false;
111    NAPI_CALL(env, napi_has_named_property(env, argv[0], "coordType", &hasProperty));
112    if (hasProperty) {
113        NAPI_CALL(env, napi_get_named_property(env, argv[0], "coordType", &nVcoordType));
114        char type[64] = {0};
115        size_t typeLen = 0;
116        NAPI_CALL(env, napi_get_value_string_utf8(env, nVcoordType, type, sizeof(type), &typeLen));
117        std::string coordType = type;
118        if (coordType != "wgs84") {
119            NAPI_CALL(env, napi_get_undefined(env, &result));
120            return result;
121        }
122    }
123    GetAllCallback(env, argv[0], successHandlerRef, failHandlerRef, completeHandlerRef);
124    int fixnumber = 1;
125    GetLocationOnce(env, successHandlerRef, failHandlerRef, completeHandlerRef, fixnumber);
126    NAPI_CALL(env, napi_get_undefined(env, &result));
127    return result;
128}
129
130bool EmitSyncCallbackWork(const napi_env& env,
131                          const napi_value& successHandler,
132                          const napi_value& failHandler,
133                          const napi_value& completeHandler)
134{
135    napi_value jsEvent = nullptr;
136    napi_value arrString = nullptr;
137    napi_value value;
138    int arrIndex = 0;
139    NAPI_CALL_BASE(env, napi_create_array(env, &arrString), false);
140    NAPI_CALL_BASE(env, napi_create_string_utf8(env, "gps", NAPI_AUTO_LENGTH, &value), false);
141    NAPI_CALL_BASE(env, napi_set_element(env, arrString, arrIndex, value), false);
142    arrIndex++;
143    NAPI_CALL_BASE(env, napi_create_string_utf8(env, "network", NAPI_AUTO_LENGTH, &value), false);
144    NAPI_CALL_BASE(env, napi_set_element(env, arrString, arrIndex, value), false);
145    NAPI_CALL_BASE(env, napi_create_object(env, &jsEvent), false);
146    NAPI_CALL_BASE(env, napi_set_named_property(env, jsEvent, "types", arrString), false);
147    napi_value undefine;
148    NAPI_CALL_BASE(env, napi_get_undefined(env, &undefine), false);
149    NAPI_CALL_BASE(env, napi_call_function(env, nullptr, successHandler, 1, &jsEvent, &undefine), false);
150    return true;
151}
152
153napi_value GetLocationType(napi_env env, napi_callback_info cbinfo)
154{
155    size_t argc = MAXIMUM_JS_PARAMS;
156    napi_value argv[MAXIMUM_JS_PARAMS] = {0};
157    napi_value thisVar = nullptr;
158    napi_value result = nullptr;
159    napi_valuetype valueType = napi_undefined;
160    NAPI_CALL(env,  napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
161    NAPI_ASSERT(env, argc == 1, "number of parameters is error");
162    NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
163    NAPI_ASSERT(env, valueType == napi_object, "type of parameters is error");
164    napi_value nVsuccessCallback;
165    napi_value nVfailCallback;
166    napi_value nVcompleteCallback;
167    bool hasProperty = false;
168    NAPI_CALL(env, napi_has_named_property(env, argv[0], "success", &hasProperty));
169    if (hasProperty) {
170        NAPI_CALL(env, napi_get_named_property(env, argv[0], "success", &nVsuccessCallback));
171    }
172    hasProperty = false;
173    NAPI_CALL(env, napi_has_named_property(env, argv[0], "fail", &hasProperty));
174    if (hasProperty) {
175        NAPI_CALL(env, napi_get_named_property(env, argv[0], "fail", &nVfailCallback));
176    }
177    hasProperty = false;
178    NAPI_CALL(env, napi_has_named_property(env, argv[0], "complete", &hasProperty));
179    if (hasProperty) {
180        NAPI_CALL(env, napi_get_named_property(env, argv[0], "complete", &nVcompleteCallback));
181    }
182    EmitSyncCallbackWork(env, nVsuccessCallback, nVfailCallback, nVcompleteCallback);
183    NAPI_CALL(env, napi_get_undefined(env, &result));
184    return result;
185}
186
187void SubscribeSystemLocationChange(napi_env env,
188                                   napi_ref& successHandlerRef,
189                                   napi_ref& failHandlerRef,
190                                   int fixNumber,
191                                   sptr<LocatorCallbackNapi>& locatorCallbackHost)
192{
193    auto locatorCallback = sptr<ILocatorCallback>(locatorCallbackHost);
194    if (locatorCallbackHost->GetSuccHandleCb() != nullptr ||
195        locatorCallbackHost->GetFailHandleCb() != nullptr) {
196        LBSLOGI(LOCATION_NAPI, "GetHandlerCb() != nullptr, UnSubscribeLocationChange");
197        g_locatorImpl->StopLocating(locatorCallback);
198        if (env == locatorCallbackHost->GetEnv()) {
199            locatorCallbackHost->DeleteAllCallbacks();
200        }
201    }
202    locatorCallbackHost->SetEnv(env);
203    locatorCallbackHost->SetFixNumber(fixNumber);
204    locatorCallbackHost->SetSuccHandleCb(successHandlerRef);
205    locatorCallbackHost->SetFailHandleCb(failHandlerRef);
206    std::unique_ptr<RequestConfig> requestConfig = std::make_unique<RequestConfig>();
207    requestConfig->SetPriority(PRIORITY_FAST_FIRST_FIX);
208    requestConfig->SetFixNumber(fixNumber);
209    g_locatorImpl->StartLocating(requestConfig, locatorCallback);
210}
211
212napi_value Subscribe(napi_env env, napi_callback_info cbinfo)
213{
214    size_t argc = MAXIMUM_JS_PARAMS;
215    napi_value argv[MAXIMUM_JS_PARAMS] = {0};
216    napi_value thisVar = nullptr;
217    napi_value result = nullptr;
218    napi_value nVcoordType;
219    NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
220    napi_valuetype valueType = napi_undefined;
221    NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
222    NAPI_ASSERT(env, argc == 1, "number of parameters is error");
223    NAPI_ASSERT(env, valueType == napi_object, "type of parameters is error");
224    NAPI_ASSERT(env, g_locatorImpl != nullptr, "get locator SA failed");
225    napi_ref successHandlerRef = nullptr;
226    napi_ref failHandlerRef = nullptr;
227    napi_ref completeHandlerRef = nullptr;
228    bool hasProperty = false;
229    NAPI_CALL(env, napi_has_named_property(env, argv[0], "coordType", &hasProperty));
230    if (hasProperty) {
231        NAPI_CALL(env, napi_get_named_property(env, argv[0], "coordType", &nVcoordType));
232        char type[64] = {0};
233        size_t typeLen = 0;
234        NAPI_CALL(env, napi_get_value_string_utf8(env, nVcoordType, type, sizeof(type), &typeLen));
235        std::string coordType = type;
236        if (coordType != "wgs84") {
237            NAPI_CALL(env, napi_get_undefined(env, &result));
238            return result;
239        }
240    }
241    GetAllCallback(env, argv[0], successHandlerRef, failHandlerRef, completeHandlerRef);
242    SubscribeSystemLocationChange(env, successHandlerRef, failHandlerRef, 0, g_systemSubcribeCallbackHost);
243    NAPI_CALL(env, napi_get_undefined(env, &result));
244    return result;
245}
246
247napi_value Unsubscribe(napi_env env, napi_callback_info cbinfo)
248{
249    NAPI_ASSERT(env, g_locatorImpl != nullptr, "get locator SA failed");
250    napi_value result = nullptr;
251    auto locatorCallback = sptr<ILocatorCallback>(g_systemSubcribeCallbackHost);
252    g_locatorImpl->StopLocating(locatorCallback);
253    if (env == g_systemSubcribeCallbackHost->GetEnv()) {
254        g_systemSubcribeCallbackHost->DeleteAllCallbacks();
255    }
256    NAPI_CALL(env, napi_get_undefined(env, &result));
257    return result;
258}
259
260napi_value GetSupportedCoordTypes(napi_env env, napi_callback_info cbinfo)
261{
262    size_t argc = MAXIMUM_JS_PARAMS;
263    napi_value argv[MAXIMUM_JS_PARAMS] = {0};
264    napi_value thisVar = nullptr;
265    NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
266    NAPI_ASSERT(env, argc == 0, "number of parameters is error");
267    napi_value arrString = nullptr;
268    napi_value value;
269    int arrIndex = 0;
270    NAPI_CALL(env, napi_create_array(env, &arrString));
271    NAPI_CALL(env, napi_create_string_utf8(env, "wgs84", NAPI_AUTO_LENGTH, &value));
272    NAPI_CALL(env, napi_set_element(env, arrString, arrIndex, value));
273    return arrString;
274}
275}  // namespace Location
276}  // namespace OHOS
277