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_v6.h"
17 
18 #include <uv.h>
19 
20 #include "iam_logger.h"
21 
22 #include "user_auth_napi_helper.h"
23 
24 #define LOG_TAG "USER_AUTH_NAPI"
25 
26 namespace OHOS {
27 namespace UserIam {
28 namespace UserAuth {
29 namespace {
30 struct ResultCallbackV6Holder {
31     std::shared_ptr<UserAuthCallbackV6> callback {nullptr};
32     int32_t result {0};
33     napi_env env;
34 };
35 
36 const std::map<int32_t, AuthenticationResult> g_result2ExecuteResult = {
37     {ResultCode::SUCCESS, AuthenticationResult::SUCCESS},
38     {ResultCode::FAIL, AuthenticationResult::COMPARE_FAILURE},
39     {ResultCode::GENERAL_ERROR, AuthenticationResult::GENERAL_ERROR},
40     {ResultCode::CANCELED, AuthenticationResult::CANCELED},
41     {ResultCode::TIMEOUT, AuthenticationResult::TIMEOUT},
42     {ResultCode::TYPE_NOT_SUPPORT, AuthenticationResult::NO_SUPPORT},
43     {ResultCode::TRUST_LEVEL_NOT_SUPPORT, AuthenticationResult::NO_SUPPORT},
44     {ResultCode::BUSY, AuthenticationResult::BUSY},
45     {ResultCode::INVALID_PARAMETERS, AuthenticationResult::INVALID_PARAMETERS},
46     {ResultCode::LOCKED, AuthenticationResult::LOCKED},
47     {ResultCode::NOT_ENROLLED, AuthenticationResult::NOT_ENROLLED},
48     {ResultCode::IPC_ERROR, AuthenticationResult::GENERAL_ERROR},
49     {ResultCode::INVALID_CONTEXT_ID, AuthenticationResult::GENERAL_ERROR},
50     {ResultCode::WRITE_PARCEL_ERROR, AuthenticationResult::GENERAL_ERROR},
51     {ResultCode::READ_PARCEL_ERROR, AuthenticationResult::GENERAL_ERROR},
52     {ResultCode::CHECK_PERMISSION_FAILED, AuthenticationResult::GENERAL_ERROR},
53     {ResultCode::PIN_EXPIRED, AuthenticationResult::GENERAL_ERROR},
54 };
55 
DestoryWork(uv_work_t * work)56 void DestoryWork(uv_work_t *work)
57 {
58     if (work == nullptr) {
59         return;
60     }
61     if (work->data != nullptr) {
62         delete (reinterpret_cast<ResultCallbackV6Holder *>(work->data));
63     }
64     delete work;
65 }
66 
OnCallbackV6Work(uv_work_t * work,int status)67 void OnCallbackV6Work(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     ResultCallbackV6Holder *resultHolder = reinterpret_cast<ResultCallbackV6Holder *>(work->data);
75     if (resultHolder == nullptr || resultHolder->callback == nullptr) {
76         IAM_LOGE("resultHolder is invalid");
77         DestoryWork(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         DestoryWork(work);
85         return;
86     }
87     napi_status ret = resultHolder->callback->DoPromise(resultHolder->result);
88     if (ret != napi_ok) {
89         IAM_LOGE("DoPromise fail %{public}d", ret);
90         napi_close_handle_scope(resultHolder->env, scope);
91         DestoryWork(work);
92         return;
93     }
94     ret = resultHolder->callback->DoCallback(resultHolder->result);
95     if (ret != napi_ok) {
96         IAM_LOGE("DoCallback fail %{public}d", ret);
97         napi_close_handle_scope(resultHolder->env, scope);
98         DestoryWork(work);
99         return;
100     }
101     napi_close_handle_scope(resultHolder->env, scope);
102     DestoryWork(work);
103     return;
104 }
105 }
106 
UserAuthCallbackV6(napi_env env,const std::shared_ptr<JsRefHolder> & callback,napi_deferred promise)107 UserAuthCallbackV6::UserAuthCallbackV6(napi_env env,
108     const std::shared_ptr<JsRefHolder> &callback, napi_deferred promise)
109     : env_(env), callback_(callback), promise_(promise)
110 {
111     if (env_ == nullptr) {
112         IAM_LOGE("UserAuthCallbackV6 get null env");
113     }
114 }
115 
~UserAuthCallbackV6()116 UserAuthCallbackV6::~UserAuthCallbackV6()
117 {
118 }
119 
DoPromise(int32_t result)120 napi_status UserAuthCallbackV6::DoPromise(int32_t result)
121 {
122     if (promise_ == nullptr) {
123         return napi_ok;
124     }
125     IAM_LOGI("start");
126     napi_value resultVal;
127     napi_status ret = napi_create_int32(env_, result, &resultVal);
128     if (ret != napi_ok) {
129         IAM_LOGE("napi_create_int32 failed %{public}d", ret);
130         return ret;
131     }
132     if (result == ResultCode::SUCCESS) {
133         ret = napi_resolve_deferred(env_, promise_, resultVal);
134         if (ret != napi_ok) {
135             IAM_LOGE("napi_resolve_deferred failed %{public}d", ret);
136         }
137     } else {
138         ret = napi_reject_deferred(env_, promise_, resultVal);
139         if (ret != napi_ok) {
140             IAM_LOGE("napi_reject_deferred failed %{public}d", ret);
141         }
142     }
143     return ret;
144 }
145 
DoCallback(int32_t result)146 napi_status UserAuthCallbackV6::DoCallback(int32_t result)
147 {
148     if (callback_ == nullptr) {
149         return napi_ok;
150     }
151     IAM_LOGI("start");
152     napi_value resultVal;
153     napi_status ret = napi_create_int32(env_, result, &resultVal);
154     if (ret != napi_ok) {
155         IAM_LOGE("napi_create_int32 failed %{public}d", ret);
156         return ret;
157     }
158     return UserAuthNapiHelper::CallVoidNapiFunc(env_, callback_->Get(), ARGS_ONE, &resultVal);
159 }
160 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const UserIam::UserAuth::Attributes & extraInfo)161 void UserAuthCallbackV6::OnAcquireInfo(int32_t module, uint32_t acquireInfo,
162     const UserIam::UserAuth::Attributes &extraInfo)
163 {
164     IAM_LOGI("start module:%{public}d acquireInfo:%{public}u", module, acquireInfo);
165 }
166 
OnResult(int32_t result,const Attributes & extraInfo)167 void UserAuthCallbackV6::OnResult(int32_t result, const Attributes &extraInfo)
168 {
169     IAM_LOGI("start, result:%{public}d", result);
170     uv_loop_s *loop;
171     napi_status napiStatus = napi_get_uv_event_loop(env_, &loop);
172     if (napiStatus != napi_ok || loop == nullptr) {
173         IAM_LOGE("napi_get_uv_event_loop fail");
174         return;
175     }
176     uv_work_t *work = new (std::nothrow) uv_work_t;
177     if (work == nullptr) {
178         IAM_LOGE("work is null");
179         return;
180     }
181     ResultCallbackV6Holder *resultHolder = new (std::nothrow) ResultCallbackV6Holder();
182     if (resultHolder == nullptr) {
183         IAM_LOGE("resultHolder is null");
184         delete work;
185         return;
186     }
187     resultHolder->callback = shared_from_this();
188     auto res = g_result2ExecuteResult.find(result);
189     if (res == g_result2ExecuteResult.end()) {
190         resultHolder->result = static_cast<int32_t>(ResultCode::GENERAL_ERROR);
191         IAM_LOGE("result %{public}d not found, set execute result GENERAL_ERROR", result);
192     } else {
193         resultHolder->result = static_cast<int32_t>(res->second);
194         IAM_LOGI("convert result %{public}d to execute result %{public}d", result, resultHolder->result);
195     }
196     resultHolder->env = env_;
197     work->data = reinterpret_cast<void *>(resultHolder);
198     if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, OnCallbackV6Work, uv_qos_user_initiated) != 0) {
199         IAM_LOGE("uv_queue_work_with_qos fail");
200         DestoryWork(work);
201     }
202 }
203 } // namespace UserAuth
204 } // namespace UserIam
205 } // namespace OHOS
206