1 /*
2 * Copyright (c) 2023-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 "user_auth_callback_v10.h"
17
18 #include <uv.h>
19
20 #include "iam_logger.h"
21 #include "user_auth_client_impl.h"
22
23 #define LOG_TAG "USER_AUTH_NAPI"
24
25 namespace OHOS {
26 namespace UserIam {
27 namespace UserAuth {
28 namespace {
29 struct ResultCallbackV10Holder {
30 std::shared_ptr<UserAuthCallbackV10> callback {nullptr};
31 int32_t result {0};
32 std::vector<uint8_t> token {};
33 int32_t authType {0};
34 EnrolledState enrolledState {};
35 napi_env env {nullptr};
36 };
37
DestoryResultWork(uv_work_t * work)38 void DestoryResultWork(uv_work_t *work)
39 {
40 if (work == nullptr) {
41 return;
42 }
43 if (work->data != nullptr) {
44 delete (reinterpret_cast<ResultCallbackV10Holder *>(work->data));
45 }
46 delete work;
47 }
48
OnResultV10Work(uv_work_t * work,int status)49 void OnResultV10Work(uv_work_t *work, int status)
50 {
51 IAM_LOGI("start");
52 if (work == nullptr) {
53 IAM_LOGE("work is null");
54 return;
55 }
56 ResultCallbackV10Holder *resultHolder = reinterpret_cast<ResultCallbackV10Holder *>(work->data);
57 if (resultHolder == nullptr || resultHolder->callback == nullptr) {
58 IAM_LOGE("resultHolder is invalid");
59 DestoryResultWork(work);
60 return;
61 }
62 napi_handle_scope scope = nullptr;
63 napi_open_handle_scope(resultHolder->env, &scope);
64 if (scope == nullptr) {
65 IAM_LOGE("scope is invalid");
66 DestoryResultWork(work);
67 return;
68 }
69 napi_status ret = resultHolder->callback->DoResultCallback(resultHolder->result, resultHolder->token,
70 resultHolder->authType, resultHolder->enrolledState);
71 IAM_LOGD("DoResultCallback ret = %{public}d", ret);
72 napi_close_handle_scope(resultHolder->env, scope);
73 DestoryResultWork(work);
74 }
75 }
76
UserAuthCallbackV10(napi_env env)77 UserAuthCallbackV10::UserAuthCallbackV10(napi_env env) : env_(env)
78 {
79 if (env_ == nullptr) {
80 IAM_LOGE("UserAuthCallbackV10 get null env");
81 }
82 }
83
~UserAuthCallbackV10()84 UserAuthCallbackV10::~UserAuthCallbackV10()
85 {
86 }
87
SetResultCallback(const std::shared_ptr<JsRefHolder> & resultCallback)88 void UserAuthCallbackV10::SetResultCallback(const std::shared_ptr<JsRefHolder> &resultCallback)
89 {
90 std::lock_guard<std::mutex> guard(mutex_);
91 resultCallback_ = resultCallback;
92 }
93
ClearResultCallback()94 void UserAuthCallbackV10::ClearResultCallback()
95 {
96 std::lock_guard<std::mutex> guard(mutex_);
97 resultCallback_ = nullptr;
98 }
99
GetResultCallback()100 std::shared_ptr<JsRefHolder> UserAuthCallbackV10::GetResultCallback()
101 {
102 std::lock_guard<std::mutex> guard(mutex_);
103 return resultCallback_;
104 }
105
HasResultCallback()106 bool UserAuthCallbackV10::HasResultCallback()
107 {
108 std::lock_guard<std::mutex> guard(mutex_);
109 return resultCallback_ != nullptr;
110 }
111
DoResultCallback(int32_t result,const std::vector<uint8_t> & token,int32_t authType,EnrolledState enrolledState)112 napi_status UserAuthCallbackV10::DoResultCallback(int32_t result,
113 const std::vector<uint8_t> &token, int32_t authType, EnrolledState enrolledState)
114 {
115 auto resultCallback = GetResultCallback();
116 if (resultCallback == nullptr) {
117 return napi_ok;
118 }
119 IAM_LOGI("start");
120 napi_value eventInfo;
121 napi_status ret = napi_create_object(env_, &eventInfo);
122 if (ret != napi_ok) {
123 IAM_LOGE("napi_create_object failed %{public}d", ret);
124 return ret;
125 }
126 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "result", result);
127 if (ret != napi_ok) {
128 IAM_LOGE("napi_create_int32 failed %{public}d", ret);
129 return ret;
130 }
131
132 if (!token.empty()) {
133 ret = UserAuthNapiHelper::SetUint8ArrayProperty(env_, eventInfo, "token", token);
134 if (ret != napi_ok) {
135 IAM_LOGE("SetUint8ArrayProperty failed %{public}d", ret);
136 return ret;
137 }
138 }
139
140 if (authType == AuthType::PIN ||
141 authType == AuthType::FACE ||
142 authType == AuthType::FINGERPRINT ||
143 authType == AuthType::PRIVATE_PIN) {
144 ret = UserAuthNapiHelper::SetInt32Property(env_, eventInfo, "authType", authType);
145 if (ret != napi_ok) {
146 IAM_LOGE("napi_create_int32 failed %{public}d", ret);
147 return ret;
148 }
149 }
150 if (UserAuthResultCode(result) == UserAuthResultCode::SUCCESS) {
151 ret = UserAuthNapiHelper::SetEnrolledStateProperty(env_, eventInfo, "enrolledState", enrolledState);
152 if (ret != napi_ok) {
153 IAM_LOGE("SetEnrolledStateProperty failed %{public}d", ret);
154 return ret;
155 }
156 }
157 return UserAuthNapiHelper::CallVoidNapiFunc(env_, resultCallback->Get(), ARGS_ONE, &eventInfo);
158 }
159
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const UserIam::UserAuth::Attributes & extraInfo)160 void UserAuthCallbackV10::OnAcquireInfo(int32_t module, uint32_t acquireInfo,
161 const UserIam::UserAuth::Attributes &extraInfo)
162 {
163 }
164
OnResult(int32_t result,const Attributes & extraInfo)165 void UserAuthCallbackV10::OnResult(int32_t result, const Attributes &extraInfo)
166 {
167 IAM_LOGI("start, result:%{public}d", result);
168 uv_loop_s *loop;
169 napi_status napiStatus = napi_get_uv_event_loop(env_, &loop);
170 if (napiStatus != napi_ok || loop == nullptr) {
171 IAM_LOGE("napi_get_uv_event_loop fail");
172 return;
173 }
174 uv_work_t *work = new (std::nothrow) uv_work_t;
175 if (work == nullptr) {
176 IAM_LOGE("work is null");
177 return;
178 }
179 ResultCallbackV10Holder *resultHolder = new (std::nothrow) ResultCallbackV10Holder();
180 if (resultHolder == nullptr) {
181 IAM_LOGE("resultHolder is null");
182 delete work;
183 return;
184 }
185 resultHolder->callback = shared_from_this();
186 resultHolder->result = UserAuthNapiHelper::GetResultCodeV10(result); // ResultCode -> UserAuthResultCode
187 resultHolder->env = env_;
188 if (!extraInfo.GetUint8ArrayValue(Attributes::ATTR_SIGNATURE, resultHolder->token)) {
189 IAM_LOGE("ATTR_SIGNATURE is null");
190 }
191 if (!extraInfo.GetInt32Value(Attributes::ATTR_AUTH_TYPE, resultHolder->authType)) {
192 IAM_LOGE("ATTR_AUTH_TYPE is null");
193 }
194 if (!extraInfo.GetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST, resultHolder->enrolledState.credentialDigest)) {
195 IAM_LOGE("ATTR_CREDENTIAL_DIGEST is null");
196 }
197 if (!extraInfo.GetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT, resultHolder->enrolledState.credentialCount)) {
198 IAM_LOGE("ATTR_CREDENTIAL_COUNT is null");
199 }
200 work->data = reinterpret_cast<void *>(resultHolder);
201 if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, OnResultV10Work, uv_qos_user_initiated) != 0) {
202 IAM_LOGE("uv_queue_work_with_qos fail");
203 DestoryResultWork(work);
204 }
205 }
206 } // namespace UserAuth
207 } // namespace UserIam
208 } // namespace OHOS
209