1 /*
2 * Copyright (c) 2022-2023 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 "user_auth_callback_v9.h"
17
18 #include <optional>
19 #include <uv.h>
20
21 #include "iam_logger.h"
22
23 #define LOG_TAG "USER_AUTH_NAPI"
24
25 namespace OHOS {
26 namespace UserIam {
27 namespace UserAuth {
28 namespace {
29 struct ResultCallbackV9Holder {
30 std::shared_ptr<UserAuthCallbackV9> callback {nullptr};
31 int32_t result {0};
32 std::vector<uint8_t> token {};
33 std::optional<int32_t> remainTimes {std::nullopt};
34 std::optional<int32_t> freezingTime {std::nullopt};
35 napi_env env;
36 };
37
38 struct AcquireCallbackV9Holder {
39 std::shared_ptr<UserAuthCallbackV9> callback {nullptr};
40 int32_t module {0};
41 uint32_t acquireInfo {0};
42 napi_env env;
43 };
44
DestoryResultWork(uv_work_t * work)45 void DestoryResultWork(uv_work_t *work)
46 {
47 if (work == nullptr) {
48 return;
49 }
50 if (work->data != nullptr) {
51 delete (reinterpret_cast<ResultCallbackV9Holder *>(work->data));
52 }
53 delete work;
54 }
55
DestoryAcquireWork(uv_work_t * work)56 void DestoryAcquireWork(uv_work_t *work)
57 {
58 if (work == nullptr) {
59 return;
60 }
61 if (work->data != nullptr) {
62 delete (reinterpret_cast<AcquireCallbackV9Holder *>(work->data));
63 }
64 delete work;
65 }
66
OnResultV9Work(uv_work_t * work,int status)67 void OnResultV9Work(uv_work_t *work, int status)
68 {
69 IAM_LOGI("start");
70 if (work == nullptr) {
71 IAM_LOGE("work is null");
72 return;
73 }
74 ResultCallbackV9Holder *resultHolder = reinterpret_cast<ResultCallbackV9Holder *>(work->data);
75 if (resultHolder == nullptr || resultHolder->callback == nullptr) {
76 IAM_LOGE("resultHolder is invalid");
77 DestoryResultWork(work);
78 return;
79 }
80 napi_handle_scope scope = nullptr;
81 napi_open_handle_scope(resultHolder->env, &scope);
82 if (scope == nullptr) {
83 IAM_LOGE("scope is invalid");
84 DestoryResultWork(work);
85 return;
86 }
87 napi_status ret = resultHolder->callback->DoResultCallback(resultHolder->result, resultHolder->token,
88 resultHolder->remainTimes, resultHolder->freezingTime);
89 if (ret != napi_ok) {
90 IAM_LOGE("DoResultCallback fail %{public}d", ret);
91 napi_close_handle_scope(resultHolder->env, scope);
92 DestoryResultWork(work);
93 return;
94 }
95 napi_close_handle_scope(resultHolder->env, scope);
96 DestoryResultWork(work);
97 }
98
OnAcquireV9Work(uv_work_t * work,int status)99 void OnAcquireV9Work(uv_work_t *work, int status)
100 {
101 IAM_LOGI("start");
102 if (work == nullptr) {
103 IAM_LOGE("work is null");
104 return;
105 }
106 AcquireCallbackV9Holder *acquireHolder = reinterpret_cast<AcquireCallbackV9Holder *>(work->data);
107 if (acquireHolder == nullptr || acquireHolder->callback == nullptr) {
108 IAM_LOGE("acquireHolder is invalid");
109 DestoryAcquireWork(work);
110 return;
111 }
112 napi_handle_scope scope = nullptr;
113 napi_open_handle_scope(acquireHolder->env, &scope);
114 if (scope == nullptr) {
115 IAM_LOGE("scope is invalid");
116 DestoryAcquireWork(work);
117 return;
118 }
119 napi_status ret = acquireHolder->callback->DoAcquireCallback(acquireHolder->module, acquireHolder->acquireInfo);
120 if (ret != napi_ok) {
121 IAM_LOGE("DoAcquireCallback fail %{public}d", ret);
122 napi_close_handle_scope(acquireHolder->env, scope);
123 DestoryAcquireWork(work);
124 return;
125 }
126 napi_close_handle_scope(acquireHolder->env, scope);
127 DestoryAcquireWork(work);
128 }
129 }
130
UserAuthCallbackV9(napi_env env)131 UserAuthCallbackV9::UserAuthCallbackV9(napi_env env) : env_(env)
132 {
133 if (env_ == nullptr) {
134 IAM_LOGE("UserAuthCallbackV9 get null env");
135 }
136 }
137
~UserAuthCallbackV9()138 UserAuthCallbackV9::~UserAuthCallbackV9()
139 {
140 }
141
SetResultCallback(const std::shared_ptr<JsRefHolder> & resultCallback)142 void UserAuthCallbackV9::SetResultCallback(const std::shared_ptr<JsRefHolder> &resultCallback)
143 {
144 std::lock_guard<std::mutex> guard(mutex_);
145 resultCallback_ = resultCallback;
146 }
147
ClearResultCallback()148 void UserAuthCallbackV9::ClearResultCallback()
149 {
150 std::lock_guard<std::mutex> guard(mutex_);
151 resultCallback_ = nullptr;
152 }
153
SetAcquireCallback(const std::shared_ptr<JsRefHolder> & acquireCallback)154 void UserAuthCallbackV9::SetAcquireCallback(const std::shared_ptr<JsRefHolder> &acquireCallback)
155 {
156 std::lock_guard<std::mutex> guard(mutex_);
157 acquireCallback_ = acquireCallback;
158 }
159
ClearAcquireCallback()160 void UserAuthCallbackV9::ClearAcquireCallback()
161 {
162 std::lock_guard<std::mutex> guard(mutex_);
163 acquireCallback_ = nullptr;
164 }
165
GetResultCallback()166 std::shared_ptr<JsRefHolder> UserAuthCallbackV9::GetResultCallback()
167 {
168 std::lock_guard<std::mutex> guard(mutex_);
169 return resultCallback_;
170 }
171
GetAcquireCallback()172 std::shared_ptr<JsRefHolder> UserAuthCallbackV9::GetAcquireCallback()
173 {
174 std::lock_guard<std::mutex> guard(mutex_);
175 return acquireCallback_;
176 }
177
DoResultCallback(int32_t result,const std::vector<uint8_t> & token,std::optional<int32_t> & remainTimes,std::optional<int32_t> & freezingTime)178 napi_status UserAuthCallbackV9::DoResultCallback(int32_t result, const std::vector<uint8_t> &token,
179 std::optional<int32_t> &remainTimes, std::optional<int32_t> &freezingTime)
180 {
181 auto resultCallback = GetResultCallback();
182 if (resultCallback == nullptr) {
183 return napi_ok;
184 }
185 IAM_LOGI("start");
186 napi_value eventInfo;
187 napi_status ret = napi_create_object(env_, &eventInfo);
188 if (ret != napi_ok) {
189 IAM_LOGE("napi_create_object failed %{public}d", ret);
190 return ret;
191 }
192 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "result", result);
193 if (ret != napi_ok) {
194 IAM_LOGE("napi_create_int32 failed %{public}d", ret);
195 return ret;
196 }
197 ret = UserAuthNapiHelper::SetUint8ArrayProperty(env_, eventInfo, "token", token);
198 if (ret != napi_ok) {
199 IAM_LOGE("SetUint8ArrayProperty failed %{public}d", ret);
200 return ret;
201 }
202
203 if (remainTimes.has_value()) {
204 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "remainAttempts", remainTimes.value());
205 if (ret != napi_ok) {
206 IAM_LOGE("SetInt32Property failed %{public}d", ret);
207 return ret;
208 }
209 }
210
211 if (freezingTime.has_value()) {
212 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "lockoutDuration", freezingTime.value());
213 if (ret != napi_ok) {
214 IAM_LOGE("SetInt32Property failed %{public}d", ret);
215 return ret;
216 }
217 }
218
219 return UserAuthNapiHelper::CallVoidNapiFunc(env_, resultCallback->Get(), ARGS_ONE, &eventInfo);
220 }
221
DoAcquireCallback(int32_t module,uint32_t acquireInfo)222 napi_status UserAuthCallbackV9::DoAcquireCallback(int32_t module, uint32_t acquireInfo)
223 {
224 auto acquireCallback = GetAcquireCallback();
225 if (acquireCallback == nullptr) {
226 return napi_ok;
227 }
228 IAM_LOGI("start");
229 napi_value eventInfo;
230 napi_status ret = napi_create_object(env_, &eventInfo);
231 if (ret != napi_ok) {
232 IAM_LOGE("napi_create_object failed %{public}d", ret);
233 return ret;
234 }
235 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "module", module);
236 if (ret != napi_ok) {
237 IAM_LOGE("napi_create_int32 failed %{public}d", ret);
238 return ret;
239 }
240 ret = UserAuthNapiHelper::SetUint32Property(env_, eventInfo, "tip", acquireInfo);
241 if (ret != napi_ok) {
242 IAM_LOGE("SetUint32Property failed %{public}d", ret);
243 return ret;
244 }
245 return UserAuthNapiHelper::CallVoidNapiFunc(env_, acquireCallback->Get(), ARGS_ONE, &eventInfo);
246 }
247
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const UserIam::UserAuth::Attributes & extraInfo)248 void UserAuthCallbackV9::OnAcquireInfo(int32_t module, uint32_t acquireInfo,
249 const UserIam::UserAuth::Attributes &extraInfo)
250 {
251 IAM_LOGI("start module:%{public}d acquireInfo:%{public}u", module, acquireInfo);
252 uv_loop_s *loop;
253 napi_status napiStatus = napi_get_uv_event_loop(env_, &loop);
254 if (napiStatus != napi_ok || loop == nullptr) {
255 IAM_LOGE("napi_get_uv_event_loop fail");
256 return;
257 }
258 uv_work_t *work = new (std::nothrow) uv_work_t;
259 if (work == nullptr) {
260 IAM_LOGE("work is null");
261 return;
262 }
263 AcquireCallbackV9Holder *acquireHolder = new (std::nothrow) AcquireCallbackV9Holder();
264 if (acquireHolder == nullptr) {
265 IAM_LOGE("acquireHolder is null");
266 delete work;
267 return;
268 }
269 acquireHolder->callback = shared_from_this();
270 acquireHolder->module = module;
271 acquireHolder->acquireInfo = acquireInfo;
272 acquireHolder->env = env_;
273 work->data = reinterpret_cast<void *>(acquireHolder);
274 if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, OnAcquireV9Work, uv_qos_user_initiated) != 0) {
275 IAM_LOGE("uv_qos_user_initiated fail");
276 DestoryAcquireWork(work);
277 }
278 }
279
OnResult(int32_t result,const Attributes & extraInfo)280 void UserAuthCallbackV9::OnResult(int32_t result, const Attributes &extraInfo)
281 {
282 IAM_LOGI("start, result:%{public}d", result);
283 uv_loop_s *loop;
284 napi_status napiStatus = napi_get_uv_event_loop(env_, &loop);
285 if (napiStatus != napi_ok || loop == nullptr) {
286 IAM_LOGE("napi_get_uv_event_loop fail");
287 return;
288 }
289 uv_work_t *work = new (std::nothrow) uv_work_t;
290 if (work == nullptr) {
291 IAM_LOGE("work is null");
292 return;
293 }
294 ResultCallbackV9Holder *resultHolder = new (std::nothrow) ResultCallbackV9Holder();
295 if (resultHolder == nullptr) {
296 IAM_LOGE("resultHolder is null");
297 delete work;
298 return;
299 }
300 resultHolder->callback = shared_from_this();
301 resultHolder->result = UserAuthNapiHelper::GetResultCodeV9(result);
302 resultHolder->env = env_;
303 if (!extraInfo.GetUint8ArrayValue(Attributes::ATTR_SIGNATURE, resultHolder->token)) {
304 IAM_LOGE("ATTR_SIGNATURE is null");
305 }
306
307 int32_t remainTimes = 0;
308 if (extraInfo.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, remainTimes)) {
309 resultHolder->remainTimes = remainTimes;
310 } else {
311 IAM_LOGE("ATTR_REMAIN_TIMES is null");
312 }
313
314 int32_t freezingTime = INT32_MAX;
315 if (extraInfo.GetInt32Value(Attributes::ATTR_FREEZING_TIME, freezingTime)) {
316 resultHolder->freezingTime = freezingTime;
317 } else {
318 IAM_LOGE("ATTR_FREEZING_TIME is null");
319 }
320
321 work->data = reinterpret_cast<void *>(resultHolder);
322 if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, OnResultV9Work, uv_qos_user_initiated) != 0) {
323 IAM_LOGE("uv_queue_work_with_qos fail");
324 DestoryResultWork(work);
325 }
326 }
327 } // namespace UserAuth
328 } // namespace UserIam
329 } // namespace OHOS
330