• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "location_error_callback_napi.h"
17 #include "common_utils.h"
18 #include "ipc_skeleton.h"
19 #include "location_log.h"
20 #include "napi/native_common.h"
21 #include "napi_util.h"
22 #include "location_async_context.h"
23 
24 namespace OHOS {
25 namespace Location {
26 static std::mutex g_regCallbackMutex;
27 static std::vector<napi_ref> g_registerCallbacks;
LocationErrorCallbackNapi()28 LocationErrorCallbackNapi::LocationErrorCallbackNapi()
29 {
30     env_ = nullptr;
31     handlerCb_ = nullptr;
32 }
33 
~LocationErrorCallbackNapi()34 LocationErrorCallbackNapi::~LocationErrorCallbackNapi()
35 {
36     LBSLOGW(LOCATION_ERR_CALLBACK, "~LocationErrorCallbackNapi()");
37 }
38 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)39 int LocationErrorCallbackNapi::OnRemoteRequest(
40     uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
41 {
42     LBSLOGD(LOCATION_ERR_CALLBACK, "LocatorCallbackHost::OnRemoteRequest! code = %{public}d", code);
43     if (data.ReadInterfaceToken() != GetDescriptor()) {
44         LBSLOGE(LOCATION_ERR_CALLBACK, "invalid token.");
45         return -1;
46     }
47 
48     switch (code) {
49         case RECEIVE_ERROR_INFO_EVENT: {
50             OnErrorReport(data.ReadInt32());
51             break;
52         }
53         default: {
54             IPCObjectStub::OnRemoteRequest(code, data, reply, option);
55             break;
56         }
57     }
58     return 0;
59 }
60 
GetEnv()61 napi_env LocationErrorCallbackNapi::GetEnv()
62 {
63     std::unique_lock<std::mutex> guard(mutex_);
64     return env_;
65 }
66 
SetEnv(const napi_env & env)67 void LocationErrorCallbackNapi::SetEnv(const napi_env& env)
68 {
69     std::unique_lock<std::mutex> guard(mutex_);
70     env_ = env;
71 }
72 
GetHandleCb()73 napi_ref LocationErrorCallbackNapi::GetHandleCb()
74 {
75     std::unique_lock<std::mutex> guard(mutex_);
76     return handlerCb_;
77 }
78 
SetHandleCb(const napi_ref & handlerCb)79 void LocationErrorCallbackNapi::SetHandleCb(const napi_ref& handlerCb)
80 {
81     {
82         std::unique_lock<std::mutex> guard(mutex_);
83         handlerCb_ = handlerCb;
84     }
85     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
86     g_registerCallbacks.emplace_back(handlerCb);
87 }
88 
FindErrorCallback(napi_ref cb)89 bool FindErrorCallback(napi_ref cb)
90 {
91     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
92     auto iter = std::find(g_registerCallbacks.begin(), g_registerCallbacks.end(), cb);
93     if (iter == g_registerCallbacks.end()) {
94         return false;
95     }
96     return true;
97 }
98 
DeleteErrorCallback(napi_ref cb)99 void DeleteErrorCallback(napi_ref cb)
100 {
101     std::unique_lock<std::mutex> guard(g_regCallbackMutex);
102     for (auto iter = g_registerCallbacks.begin(); iter != g_registerCallbacks.end(); iter++) {
103         if (*iter == cb) {
104             iter = g_registerCallbacks.erase(iter);
105             break;
106         }
107     }
108     LBSLOGW(LOCATION_ERR_CALLBACK, "after DeleteErrorCallback, callback size %{public}s",
109         std::to_string(g_registerCallbacks.size()).c_str());
110 }
111 
Send(int32_t errorCode)112 bool LocationErrorCallbackNapi::Send(int32_t errorCode)
113 {
114     LBSLOGD(LOCATION_ERR_CALLBACK, "LocatorCallbackNapi::OnRemoteRequest! errorCode = %{public}d", errorCode);
115     std::unique_lock<std::mutex> guard(mutex_);
116     uv_loop_s *loop = nullptr;
117     NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
118     if (loop == nullptr) {
119         LBSLOGE(LOCATION_ERR_CALLBACK, "loop == nullptr.");
120         return false;
121     }
122     if (handlerCb_ == nullptr) {
123         LBSLOGE(LOCATION_ERR_CALLBACK, "handler is nullptr.");
124         return false;
125     }
126     uv_work_t *work = new (std::nothrow) uv_work_t;
127     if (work == nullptr) {
128         LBSLOGE(LOCATION_ERR_CALLBACK, "work == nullptr.");
129         return false;
130     }
131     LocationErrorAsyncContext *context = new (std::nothrow) LocationErrorAsyncContext(env_);
132     if (context == nullptr) {
133         LBSLOGE(LOCATION_ERR_CALLBACK, "context == nullptr.");
134         delete work;
135         return false;
136     }
137     if (!InitContext(context)) {
138         LBSLOGE(LOCATION_ERR_CALLBACK, "InitContext fail");
139         delete work;
140         delete context;
141         return false;
142     }
143     context->errCode = errorCode;
144     work->data = context;
145     UvQueueWork(loop, work);
146     return true;
147 }
148 
UvQueueWork(uv_loop_s * loop,uv_work_t * work)149 void LocationErrorCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
150 {
151     uv_queue_work(
152         loop,
153         work,
154         [](uv_work_t *work) {},
155         [](uv_work_t *work, int status) {
156             LocationErrorAsyncContext *context = nullptr;
157             napi_handle_scope scope = nullptr;
158             if (work == nullptr) {
159                 LBSLOGE(LOCATION_ERR_CALLBACK, "work is nullptr!");
160                 return;
161             }
162             context = static_cast<LocationErrorAsyncContext *>(work->data);
163             if (context == nullptr || context->env == nullptr) {
164                 LBSLOGE(LOCATION_ERR_CALLBACK, "context is nullptr!");
165                 delete work;
166                 return;
167             }
168             NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
169             napi_value jsEvent;
170             CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_int32(context->env, context->errCode, &jsEvent),
171                 scope, context, work);
172             if (scope == nullptr) {
173                 LBSLOGE(LOCATION_ERR_CALLBACK, "scope is nullptr");
174                 delete context;
175                 delete work;
176                 return;
177             }
178             if (context->callback[0] != nullptr) {
179                 napi_value undefine;
180                 napi_value handler = nullptr;
181                 napi_status ret = napi_ok;
182                 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_get_undefined(context->env, &undefine),
183                     scope, context, work);
184                 if (FindErrorCallback(context->callback[0])) {
185                     CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
186                         napi_get_reference_value(context->env, context->callback[0], &handler), scope, context, work);
187                     ret = napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine);
188                 } else {
189                     LBSLOGE(LOCATION_ERR_CALLBACK, "no valid callback");
190                 }
191                 if (ret != napi_ok) {
192                     LBSLOGE(LOCATION_ERR_CALLBACK, "Report event failed");
193                 }
194             }
195             NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
196             delete context;
197             delete work;
198     });
199 }
200 
OnLocationReport(const std::unique_ptr<Location> & location)201 void LocationErrorCallbackNapi::OnLocationReport(const std::unique_ptr<Location>& location)
202 {
203 }
204 
OnLocatingStatusChange(const int status)205 void LocationErrorCallbackNapi::OnLocatingStatusChange(const int status)
206 {
207 }
208 
OnErrorReport(const int errorCode)209 void LocationErrorCallbackNapi::OnErrorReport(const int errorCode)
210 {
211     Send(errorCode);
212 }
213 
DeleteHandler()214 void LocationErrorCallbackNapi::DeleteHandler()
215 {
216     std::unique_lock<std::mutex> guard(mutex_);
217     if (handlerCb_ == nullptr || env_ == nullptr) {
218         LBSLOGE(LOCATION_ERR_CALLBACK, "handler or env is nullptr.");
219         return;
220     }
221     DeleteErrorCallback(handlerCb_);
222     NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
223     handlerCb_ = nullptr;
224 }
225 }  // namespace Location
226 }  // namespace OHOS
227