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