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 "country_code_callback_napi.h"
17
18 #include "common_utils.h"
19 #include "ipc_skeleton.h"
20 #include "location_log.h"
21 #include "napi/native_api.h"
22 #include "country_code.h"
23 #include "napi_util.h"
24
25 namespace OHOS {
26 namespace Location {
CountryCodeCallbackNapi()27 CountryCodeCallbackNapi::CountryCodeCallbackNapi()
28 {
29 env_ = nullptr;
30 handlerCb_ = nullptr;
31 }
32
~CountryCodeCallbackNapi()33 CountryCodeCallbackNapi::~CountryCodeCallbackNapi()
34 {
35 }
36
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)37 int CountryCodeCallbackNapi::OnRemoteRequest(
38 uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
39 {
40 LBSLOGD(COUNTRY_CODE_CALLBACK, "CountryCodeCallbackNapi::OnRemoteRequest!");
41 if (data.ReadInterfaceToken() != GetDescriptor()) {
42 LBSLOGE(COUNTRY_CODE_CALLBACK, "invalid token.");
43 return -1;
44 }
45
46 switch (code) {
47 case COUNTRY_CODE_CHANGE_EVENT: {
48 auto countryCodePtr = CountryCode::Unmarshalling(data);
49 OnCountryCodeChange(countryCodePtr);
50 break;
51 }
52 default: {
53 IPCObjectStub::OnRemoteRequest(code, data, reply, option);
54 break;
55 }
56 }
57 return 0;
58 }
59
Send(const std::shared_ptr<CountryCode> & country)60 bool CountryCodeCallbackNapi::Send(const std::shared_ptr<CountryCode>& country)
61 {
62 std::unique_lock<std::mutex> guard(mutex_);
63 uv_loop_s *loop = nullptr;
64 if (env_ == nullptr) {
65 LBSLOGE(COUNTRY_CODE_CALLBACK, "env_ == nullptr.");
66 return false;
67 }
68 if (handlerCb_ == nullptr) {
69 LBSLOGE(COUNTRY_CODE_CALLBACK, "handler is nullptr.");
70 return false;
71 }
72 if (country == nullptr) {
73 LBSLOGE(COUNTRY_CODE_CALLBACK, "country == nullptr.");
74 return false;
75 }
76 NAPI_CALL_BASE(env_, napi_get_uv_event_loop(env_, &loop), false);
77 if (loop == nullptr) {
78 LBSLOGE(COUNTRY_CODE_CALLBACK, "loop == nullptr.");
79 return false;
80 }
81 uv_work_t *work = new (std::nothrow) uv_work_t;
82 if (work == nullptr) {
83 LBSLOGE(COUNTRY_CODE_CALLBACK, "work == nullptr.");
84 return false;
85 }
86 auto context = new (std::nothrow) CountryCodeContext(env_);
87 if (context == nullptr) {
88 LBSLOGE(COUNTRY_CODE_CALLBACK, "context == nullptr.");
89 delete work;
90 return false;
91 }
92 if (!InitContext(context)) {
93 LBSLOGE(COUNTRY_CODE_CALLBACK, "InitContext fail");
94 return false;
95 }
96 context->country = country;
97 work->data = context;
98 UvQueueWork(loop, work);
99 return true;
100 }
101
UvQueueWork(uv_loop_s * loop,uv_work_t * work)102 void CountryCodeCallbackNapi::UvQueueWork(uv_loop_s* loop, uv_work_t* work)
103 {
104 uv_queue_work(
105 loop,
106 work,
107 [](uv_work_t *work) {},
108 [](uv_work_t *work, int status) {
109 CountryCodeContext *context = nullptr;
110 napi_handle_scope scope = nullptr;
111 if (work == nullptr) {
112 LBSLOGE(LOCATOR_CALLBACK, "work is nullptr!");
113 return;
114 }
115 context = static_cast<CountryCodeContext *>(work->data);
116 if (context == nullptr || context->env == nullptr) {
117 LBSLOGE(LOCATOR_CALLBACK, "context is nullptr!");
118 delete work;
119 return;
120 }
121 NAPI_CALL_RETURN_VOID(context->env, napi_open_handle_scope(context->env, &scope));
122 if (scope == nullptr) {
123 LBSLOGE(COUNTRY_CODE_CALLBACK, "scope is nullptr");
124 delete context;
125 delete work;
126 return;
127 }
128 napi_value jsEvent;
129 CHK_NAPI_ERR_CLOSE_SCOPE(context->env, napi_create_object(context->env, &jsEvent),
130 scope, context, work);
131 if (context->country) {
132 CountryCodeToJs(context->env, context->country, jsEvent);
133 } else {
134 LBSLOGE(LOCATOR_STANDARD, "country is nullptr!");
135 }
136 if (context->callback[0] != nullptr) {
137 napi_value undefine;
138 napi_value handler = nullptr;
139 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
140 napi_get_undefined(context->env, &undefine), scope, context, work);
141 CHK_NAPI_ERR_CLOSE_SCOPE(context->env,
142 napi_get_reference_value(context->env, context->callback[SUCCESS_CALLBACK], &handler),
143 scope, context, work);
144 if (napi_call_function(context->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
145 LBSLOGE(COUNTRY_CODE_CALLBACK, "Report event failed");
146 }
147 }
148 NAPI_CALL_RETURN_VOID(context->env, napi_close_handle_scope(context->env, scope));
149 delete context;
150 delete work;
151 });
152 }
153
OnCountryCodeChange(const std::shared_ptr<CountryCode> & country)154 void CountryCodeCallbackNapi::OnCountryCodeChange(const std::shared_ptr<CountryCode>& country)
155 {
156 LBSLOGD(COUNTRY_CODE_CALLBACK, "CountryCodeCallbackNapi::OnCountryCodeChange");
157 Send(country);
158 }
159
SetEnv(napi_env env)160 void CountryCodeCallbackNapi::SetEnv(napi_env env)
161 {
162 std::unique_lock<std::mutex> guard(mutex_);
163 env_ = env;
164 }
165
SetCallback(napi_ref cb)166 void CountryCodeCallbackNapi::SetCallback(napi_ref cb)
167 {
168 std::unique_lock<std::mutex> guard(mutex_);
169 handlerCb_ = cb;
170 }
171
DeleteHandler()172 void CountryCodeCallbackNapi::DeleteHandler()
173 {
174 std::unique_lock<std::mutex> guard(mutex_);
175 if (handlerCb_ == nullptr || env_ == nullptr) {
176 LBSLOGE(COUNTRY_CODE_CALLBACK, "handler or env is nullptr.");
177 return;
178 }
179 NAPI_CALL_RETURN_VOID(env_, napi_delete_reference(env_, handlerCb_));
180 handlerCb_ = nullptr;
181 }
182 } // namespace Location
183 } // namespace OHOS
184