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