1 /*
2  * Copyright (c) 2022-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 "napi_account_iam_common.h"
17 
18 #include <map>
19 
20 #include <uv.h>
21 #include "account_error_no.h"
22 #include "account_iam_info.h"
23 #include "account_log_wrapper.h"
24 #include "napi_account_error.h"
25 #include "napi_account_common.h"
26 #include "napi_account_iam_constant.h"
27 #include "securec.h"
28 
29 namespace OHOS {
30 namespace AccountJsKit {
31 using namespace OHOS::AccountSA;
32 
AccountIAMConvertOtherToJSErrCode(int32_t errCode)33 static int32_t AccountIAMConvertOtherToJSErrCode(int32_t errCode)
34 {
35     switch (errCode) {
36         case ERR_IAM_SUCCESS:
37             return ERR_JS_SUCCESS;
38         case ERR_IAM_FAIL:
39         case ERR_IAM_TOKEN_TIMEOUT:
40         case ERR_IAM_TOKEN_AUTH_FAILED:
41             return ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR;
42         case ERR_IAM_TRUST_LEVEL_NOT_SUPPORT:
43             return ERR_JS_TRUST_LEVEL_NOT_SUPPORTED;
44         case ERR_IAM_TYPE_NOT_SUPPORT:
45             return ERR_JS_AUTH_TYPE_NOT_SUPPORTED;
46         case ERR_IAM_TIMEOUT:
47             return ERR_JS_AUTH_TIMEOUT;
48         case ERR_IAM_CANCELED:
49             return ERR_JS_AUTH_CANCELLED;
50         case ERR_IAM_BUSY:
51             return ERR_JS_AUTH_SERVICE_BUSY;
52         case ERR_IAM_LOCKED:
53             return ERR_JS_AUTH_SERVICE_LOCKED;
54         case ERR_IAM_NOT_ENROLLED:
55             return ERR_JS_CREDENTIAL_NOT_EXIST;
56         case ERR_IAM_PIN_IS_EXPIRED:
57             return ERR_JS_PIN_IS_EXPIRED;
58         case ERR_IAM_COMPLEXITY_CHECK_FAILED:
59             return ERR_JS_COMPLEXITY_CHECK_FAILED;
60         case ERR_IAM_INVALID_CONTEXT_ID:
61             return ERR_JS_INVALID_CONTEXT_ID;
62         case ERR_ACCOUNT_COMMON_INVALID_PARAMETER:
63         case ERR_IAM_INVALID_PARAMETERS:
64             return ERR_JS_INVALID_PARAMETER;
65         case ERR_ACCOUNT_IAM_KIT_INPUTER_ALREADY_REGISTERED:
66             return ERR_JS_CREDENTIAL_INPUTER_ALREADY_EXIST;
67         case ERR_ACCOUNT_IAM_KIT_INPUTER_NOT_REGISTERED:
68             return ERR_JS_CREDENTIAL_INPUTER_NOT_EXIST;
69         case ERR_ACCOUNT_IAM_UNSUPPORTED_AUTH_TYPE:
70         case ERR_DOMAIN_ACCOUNT_SERVICE_NOT_DOMAIN_ACCOUNT:
71             return ERR_JS_AUTH_TYPE_NOT_SUPPORTED;
72         case ERR_IAM_CREDENTIAL_NUMBER_REACH_LIMIT:
73             return ERR_JS_CREDENTIAL_NUMBER_REACH_LIMIT;
74         case ERR_IAM_SESSION_TIMEOUT:
75             return ERR_JS_SESSION_TIMEOUT;
76         default:
77             return ERR_JS_SYSTEM_SERVICE_EXCEPTION;
78     }
79 }
80 
AccountIAMConvertToJSErrCode(int32_t errCode)81 int32_t AccountIAMConvertToJSErrCode(int32_t errCode)
82 {
83     if (CheckJsErrorCode(errCode)) {
84         return errCode;
85     }
86     if (errCode == ERR_ACCOUNT_COMMON_NOT_SYSTEM_APP_ERROR) {
87         return ERR_JS_IS_NOT_SYSTEM_APP;
88     } else if (errCode == ERR_ACCOUNT_COMMON_PERMISSION_DENIED || errCode == ERR_IAM_CHECK_PERMISSION_FAILED) {
89         return ERR_JS_PERMISSION_DENIED;
90     } else if (errCode == ERR_ACCOUNT_COMMON_INVALID_PARAMETER) {
91         return ERR_JS_INVALID_PARAMETER;
92     } else if (errCode == ERR_ACCOUNT_COMMON_ACCOUNT_NOT_EXIST_ERROR) {
93         return ERR_JS_ACCOUNT_NOT_FOUND;
94     } else if (errCode == ERR_ACCOUNT_COMMON_ACCOUNT_IS_RESTRICTED) {
95         return ERR_JS_ACCOUNT_RESTRICTED;
96     }
97     return AccountIAMConvertOtherToJSErrCode(errCode);
98 }
99 
100 #ifdef HAS_USER_AUTH_PART
NapiIDMCallback(napi_env env,const std::shared_ptr<JsIAMCallback> & callback)101 NapiIDMCallback::NapiIDMCallback(napi_env env, const std::shared_ptr<JsIAMCallback> &callback)
102     : env_(env), callback_(callback)
103 {}
104 
~NapiIDMCallback()105 NapiIDMCallback::~NapiIDMCallback()
106 {}
107 
OnResult(int32_t result,const Attributes & extraInfo)108 void NapiIDMCallback::OnResult(int32_t result, const Attributes &extraInfo)
109 {
110     std::lock_guard<std::mutex> lock(mutex_);
111     if (callback_->onResultCalled) {
112         ACCOUNT_LOGE("Call twice is not allowed");
113         return;
114     }
115     callback_->onResultCalled = true;
116     std::shared_ptr<IDMCallbackParam> param = std::make_shared<IDMCallbackParam>(env_);
117     if (param == nullptr) {
118         ACCOUNT_LOGE("Failed for nullptr");
119         return;
120     }
121     param->result = result;
122     extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param->credentialId);
123     param->callback = callback_;
124     auto task = [param]() {
125         ACCOUNT_LOGI("Enter NapiIDMCallback::OnResult task");
126         napi_handle_scope scope = nullptr;
127         napi_open_handle_scope(param->env, &scope);
128         if (scope == nullptr) {
129             ACCOUNT_LOGE("Failed to open scope");
130             return;
131         }
132         napi_value argv[ARG_SIZE_TWO] = {0};
133         napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->result), &argv[PARAM_ZERO]);
134         napi_create_object(param->env, &argv[PARAM_ONE]);
135         napi_value credentialId =
136             CreateUint8Array(param->env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
137         napi_set_named_property(param->env, argv[PARAM_ONE], "credentialId", credentialId);
138         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback->onResult);
139         napi_close_handle_scope(param->env, scope);
140         return;
141     };
142     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
143         ACCOUNT_LOGE("Failed to send event for auth");
144         return;
145     }
146     ACCOUNT_LOGI("Post OnResult task finish");
147 }
148 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)149 void NapiIDMCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
150 {
151     std::lock_guard<std::mutex> lock(mutex_);
152     if (!callback_->hasOnAcquireInfo) {
153         ACCOUNT_LOGE("No 'OnAcquireInfo' callback need return");
154         return;
155     }
156     if (callback_->onResultCalled) {
157         ACCOUNT_LOGE("Call after OnResult is not allowed");
158         return;
159     }
160     std::shared_ptr<IDMCallbackParam> param = std::make_shared<IDMCallbackParam>(env_);
161     if (param == nullptr) {
162         ACCOUNT_LOGE("Failed for nullptr");
163         return;
164     }
165     param->callback = callback_;
166     param->module = module;
167     param->acquire = acquireInfo;
168     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_EXTRA_INFO, param->extraInfo);
169     auto task = [param]() {
170         ACCOUNT_LOGI("Enter NapiIDMCallback::OnAcquireInfo task");
171         napi_handle_scope scope = nullptr;
172         napi_open_handle_scope(param->env, &scope);
173         if (scope == nullptr) {
174             ACCOUNT_LOGE("Fail to open scope");
175             return;
176         }
177         napi_value argv[ARG_SIZE_THREE] = {0};
178         napi_env env = param->env;
179         napi_create_int32(env, param->module, &argv[PARAM_ZERO]);
180         napi_create_int32(env, param->acquire, &argv[PARAM_ONE]);
181         argv[PARAM_TWO] = CreateUint8Array(env, param->extraInfo.data(), param->extraInfo.size());
182         NapiCallVoidFunction(env, argv, ARG_SIZE_THREE, param->callback->onAcquireInfo);
183         napi_close_handle_scope(param->env, scope);
184         return;
185     };
186     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
187         ACCOUNT_LOGE("Failed to send event for auth");
188         return;
189     }
190     ACCOUNT_LOGI("Post OnAcquireInfo task finish");
191 }
192 
ParseAddCredInfo(napi_env env,napi_value value,IDMContext & context)193 napi_status ParseAddCredInfo(napi_env env, napi_value value, IDMContext &context)
194 {
195     napi_valuetype valueType = napi_undefined;
196     napi_typeof(env, value, &valueType);
197     if (valueType != napi_object) {
198         ACCOUNT_LOGE("value is not an object");
199         return napi_invalid_arg;
200     }
201     napi_value result = nullptr;
202     napi_get_named_property(env, value, "credType", &result);
203     int32_t credType = -1;
204     napi_get_value_int32(env, result, &credType);
205     context.addCredInfo.authType = static_cast<AuthType>(credType);
206     napi_get_named_property(env, value, "credSubType", &result);
207     int32_t credSubType = -1;
208     napi_get_value_int32(env, result, &credSubType);
209     context.addCredInfo.pinType = static_cast<PinSubType>(credSubType);
210     napi_get_named_property(env, value, "token", &result);
211     if (ParseUint8TypedArrayToVector(env, result, context.addCredInfo.token) != napi_ok) {
212         ACCOUNT_LOGE("Get Uint8Array data failed");
213         return napi_invalid_arg;
214     }
215     if (!GetOptionalNumberPropertyByKey(env, value, "accountId", context.accountId, context.parseHasAccountId)) {
216         ACCOUNT_LOGE("Get accountId data failed");
217         return napi_invalid_arg;
218     }
219     return napi_ok;
220 }
221 
ParseIAMCallback(napi_env env,napi_value object,std::shared_ptr<JsIAMCallback> & callback)222 napi_status ParseIAMCallback(napi_env env, napi_value object, std::shared_ptr<JsIAMCallback> &callback)
223 {
224     napi_valuetype valueType = napi_undefined;
225     napi_typeof(env, object, &valueType);
226     if (valueType != napi_object) {
227         ACCOUNT_LOGE("invalid object");
228         return napi_invalid_arg;
229     }
230     napi_value result = nullptr;
231     napi_get_named_property(env, object, "onResult", &result);
232     napi_typeof(env, result, &valueType);
233     if (valueType == napi_function) {
234         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback->onResult), napi_generic_failure);
235     } else {
236         ACCOUNT_LOGE("onResult is not a function");
237         return napi_invalid_arg;
238     }
239     napi_has_named_property(env, object, "onAcquireInfo", &callback->hasOnAcquireInfo);
240     if (!callback->hasOnAcquireInfo) {
241         return napi_ok;
242     }
243     napi_get_named_property(env, object, "onAcquireInfo", &result);
244     napi_typeof(env, result, &valueType);
245     if (valueType == napi_function) {
246         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback->onAcquireInfo), napi_generic_failure);
247     } else if ((valueType == napi_undefined) || (valueType == napi_null)) {
248         ACCOUNT_LOGI("onAcquireInfo is undefined or null");
249     } else {
250         ACCOUNT_LOGE("onAcquireInfo is not a function");
251         return napi_invalid_arg;
252     }
253     return napi_ok;
254 }
255 
CreateCredInfoArray(napi_env env,const std::vector<CredentialInfo> & info)256 napi_value CreateCredInfoArray(napi_env env, const std::vector<CredentialInfo> &info)
257 {
258     napi_value arr = nullptr;
259     napi_create_array_with_length(env, info.size(), &arr);
260     uint32_t index = 0;
261     for (auto item : info) {
262         napi_value obj;
263         NAPI_CALL(env, napi_create_object(env, &obj));
264         napi_value credentialId = CreateUint8Array(
265             env, reinterpret_cast<uint8_t *>(&item.credentialId), sizeof(uint64_t));
266         napi_value authType;
267         NAPI_CALL(env, napi_create_uint32(env, item.authType, &authType));
268         napi_value napiPinType;
269         PinSubType pinType = item.pinType.value_or(PinSubType::PIN_MAX);
270         NAPI_CALL(env, napi_create_uint32(env, pinType, &napiPinType));
271         napi_value templateId = CreateUint8Array(
272             env, reinterpret_cast<uint8_t *>(&item.templateId), sizeof(uint64_t));
273         NAPI_CALL(env, napi_set_named_property(env, obj, "credentialId", credentialId));
274         NAPI_CALL(env, napi_set_named_property(env, obj, "authType", authType));
275         NAPI_CALL(env, napi_set_named_property(env, obj, "authSubType", napiPinType));
276         NAPI_CALL(env, napi_set_named_property(env, obj, "templateId", templateId));
277         NAPI_CALL(env, napi_set_element(env, arr, index, obj));
278         index++;
279     }
280     return arr;
281 }
282 
ConvertGetPropertyTypeToAttributeKey(GetPropertyType in,Attributes::AttributeKey & out)283 napi_status ConvertGetPropertyTypeToAttributeKey(GetPropertyType in,
284     Attributes::AttributeKey &out)
285 {
286     static const std::map<GetPropertyType, Attributes::AttributeKey> type2Key = {
287         { AUTH_SUB_TYPE, Attributes::AttributeKey::ATTR_PIN_SUB_TYPE },
288         { REMAIN_TIMES, Attributes::AttributeKey::ATTR_REMAIN_TIMES },
289         { FREEZING_TIME, Attributes::AttributeKey::ATTR_FREEZING_TIME },
290         { ENROLLMENT_PROGRESS, Attributes::AttributeKey::ATTR_ENROLL_PROGRESS },
291         { SENSOR_INFO, Attributes::AttributeKey::ATTR_SENSOR_INFO },
292         { NEXT_PHASE_FREEZING_TIME, Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION },
293     };
294 
295     auto iter = type2Key.find(in);
296     if (iter == type2Key.end()) {
297         ACCOUNT_LOGE("GetPropertyType %{public}d is invalid", in);
298         return napi_invalid_arg;
299     } else {
300         out = iter->second;
301     }
302     return napi_ok;
303 }
304 
ParseGetPropKeys(napi_env env,napi_value napiKeys,std::vector<Attributes::AttributeKey> & keys)305 napi_status ParseGetPropKeys(napi_env env, napi_value napiKeys, std::vector<Attributes::AttributeKey> &keys)
306 {
307     std::vector<uint32_t> tempKeys;
308     if (ParseUInt32Array(env, napiKeys, tempKeys) != napi_ok) {
309         ACCOUNT_LOGE("Parameter error. The type of \"keys\" must be GetPropertyType's array");
310         return napi_invalid_arg;
311     }
312     for (const auto &item : tempKeys) {
313         Attributes::AttributeKey key;
314         napi_status status = ConvertGetPropertyTypeToAttributeKey(static_cast<GetPropertyType>(item), key);
315         if (status != napi_ok) {
316             ACCOUNT_LOGE("Parameter error. The type of \"key\" must be 'GetPropertyType'");
317             return napi_invalid_arg;
318         }
319         keys.push_back(key);
320     }
321     return napi_ok;
322 }
323 
ParseGetPropRequest(napi_env env,napi_value object,GetPropertyContext & context)324 napi_status ParseGetPropRequest(napi_env env, napi_value object, GetPropertyContext &context)
325 {
326     napi_valuetype valueType = napi_undefined;
327     napi_typeof(env, object, &valueType);
328     if (valueType != napi_object) {
329         ACCOUNT_LOGE("invalid object");
330         return napi_invalid_arg;
331     }
332     napi_value napiAuthType = nullptr;
333     napi_get_named_property(env, object, "authType", &napiAuthType);
334     int32_t authType = -1;
335     napi_get_value_int32(env, napiAuthType, &authType);
336     context.request.authType = static_cast<AuthType>(authType);
337     napi_value napiKeys = nullptr;
338     NAPI_CALL_BASE(env, napi_get_named_property(env, object, "keys", &napiKeys), napi_generic_failure);
339     if (ParseGetPropKeys(env, napiKeys, context.request.keys) != napi_ok) {
340         ACCOUNT_LOGE("Get getPropRequest's keys failed");
341         return napi_invalid_arg;
342     }
343     if (!GetOptionalNumberPropertyByKey(env, object, "accountId", context.accountId, context.parseHasAccountId)) {
344         ACCOUNT_LOGE("Get getPropRequest's accountId failed");
345         return napi_invalid_arg;
346     }
347     return napi_ok;
348 }
349 
ParseSetPropRequest(napi_env env,napi_value object,SetPropertyRequest & request)350 napi_status ParseSetPropRequest(napi_env env, napi_value object, SetPropertyRequest &request)
351 {
352     napi_valuetype valueType = napi_undefined;
353     napi_typeof(env, object, &valueType);
354     if (valueType != napi_object) {
355         ACCOUNT_LOGE("invalid object");
356         return napi_invalid_arg;
357     }
358     napi_value napiKey = nullptr;
359     napi_get_named_property(env, object, "key", &napiKey);
360     int32_t key = -1;
361     napi_get_value_int32(env, napiKey, &key);
362     request.mode = static_cast<PropertyMode>(key);
363     napi_value napiAuthType = nullptr;
364     napi_get_named_property(env, object, "authType", &napiAuthType);
365     int32_t authType = -1;
366     napi_get_value_int32(env, napiAuthType, &authType);
367     request.authType = static_cast<AuthType>(authType);
368     napi_value napiSetInfo = nullptr;
369     napi_get_named_property(env, object, "setInfo", &napiSetInfo);
370     std::vector<uint8_t> setInfo;
371     ParseUint8TypedArrayToVector(env, napiSetInfo, setInfo);
372     request.attrs.SetUint8ArrayValue(Attributes::AttributeKey(key), setInfo);
373     return napi_ok;
374 }
375 
GeneratePropertyJs(napi_env env,const GetPropertyCommonContext & context,napi_value & dataJs)376 static void GeneratePropertyJs(napi_env env, const GetPropertyCommonContext &context, napi_value &dataJs)
377 {
378     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &dataJs));
379     napi_value napiResult = nullptr;
380     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, context.propertyInfo.result, &napiResult));
381     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "result", napiResult));
382     for (const auto &key : context.keys) {
383         switch (key) {
384             case Attributes::AttributeKey::ATTR_PIN_SUB_TYPE: {
385                 SetInt32ToJsProperty(env, context.propertyInfo.authSubType, "authSubType", dataJs);
386                 break;
387             }
388             case Attributes::AttributeKey::ATTR_REMAIN_TIMES: {
389                 SetInt32ToJsProperty(env, context.propertyInfo.remainTimes, "remainTimes", dataJs);
390                 break;
391             }
392             case Attributes::AttributeKey::ATTR_FREEZING_TIME: {
393                 SetInt32ToJsProperty(env, context.propertyInfo.freezingTime, "freezingTime", dataJs);
394                 break;
395             }
396             case Attributes::AttributeKey::ATTR_ENROLL_PROGRESS: {
397                 napi_value napiEnrollmentProgress = nullptr;
398                 napi_create_string_utf8(
399                     env, context.propertyInfo.enrollmentProgress.c_str(), NAPI_AUTO_LENGTH, &napiEnrollmentProgress);
400                 napi_set_named_property(env, dataJs, "enrollmentProgress", napiEnrollmentProgress);
401                 break;
402             }
403             case Attributes::AttributeKey::ATTR_SENSOR_INFO: {
404                 napi_value napiSensorInfo = nullptr;
405                 napi_create_string_utf8(env,
406                     context.propertyInfo.sensorInfo.c_str(), NAPI_AUTO_LENGTH, &napiSensorInfo);
407                 napi_set_named_property(env, dataJs, "sensorInfo", napiSensorInfo);
408                 break;
409             }
410             case Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION: {
411                 SetInt32ToJsProperty(env, context.propertyInfo.nextPhaseFreezingTime, "nextPhaseFreezingTime", dataJs);
412                 break;
413             }
414             default:
415                 break;
416         }
417     }
418 }
419 
CreateExecutorProperty(napi_env env,GetPropertyCommonContext & context,napi_value & errJs,napi_value & dataJs)420 static void CreateExecutorProperty(
421     napi_env env, GetPropertyCommonContext &context, napi_value &errJs, napi_value &dataJs)
422 {
423     context.errCode = context.propertyInfo.result;
424     if (!context.isGetById && context.errCode == ERR_IAM_NOT_ENROLLED) {
425         context.errCode = ERR_OK;
426     }
427     if (context.errCode != ERR_OK) {
428         int32_t jsErrCode = AccountIAMConvertToJSErrCode(context.propertyInfo.result);
429         errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
430         napi_get_null(env, &dataJs);
431         return;
432     }
433     context.errCode = ERR_OK;
434     napi_get_null(env, &errJs);
435     GeneratePropertyJs(env, context, dataJs);
436 }
437 
GenerateAuthResult(napi_env env,AuthCallbackParam * param)438 static napi_value GenerateAuthResult(napi_env env, AuthCallbackParam *param)
439 {
440     napi_value object = CreateAuthResult(param->env, param->token, param->remainTimes, param->freezingTime);
441     if (param->hasNextPhaseFreezingTime) {
442         SetInt32ToJsProperty(env, param->nextPhaseFreezingTime, "nextPhaseFreezingTime", object);
443     }
444     if (param->hasCredentialId) {
445         napi_value napiCredentialId =
446             CreateUint8Array(env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
447         NAPI_CALL(env, napi_set_named_property(env, object, "credentialId", napiCredentialId));
448     }
449     if (param->hasAccountId) {
450         SetInt32ToJsProperty(env, param->accountId, "accountId", object);
451     }
452     if (param->hasPinValidityPeriod) {
453         napi_value napiPinValidityPeriod = nullptr;
454         NAPI_CALL(env, napi_create_int64(env, param->pinValidityPeriod, &napiPinValidityPeriod));
455         NAPI_CALL(env, napi_set_named_property(env, object, "pinValidityPeriod", napiPinValidityPeriod));
456     }
457     return object;
458 }
459 
NapiUserAuthCallback(napi_env env,const std::shared_ptr<JsIAMCallback> & callback)460 NapiUserAuthCallback::NapiUserAuthCallback(napi_env env, const std::shared_ptr<JsIAMCallback> &callback)
461     : env_(env), callback_(callback)
462 {}
463 
~NapiUserAuthCallback()464 NapiUserAuthCallback::~NapiUserAuthCallback()
465 {}
466 
PrepareAuthResult(int32_t result,const Attributes & extraInfo,AuthCallbackParam & param)467 void NapiUserAuthCallback::PrepareAuthResult(int32_t result, const Attributes &extraInfo, AuthCallbackParam &param)
468 {
469     param.resultCode = result;
470     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_SIGNATURE, param.token);
471     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_REMAIN_TIMES, param.remainTimes);
472     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_FREEZING_TIME, param.freezingTime);
473     if (extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
474                                 param.nextPhaseFreezingTime)) {
475         param.hasNextPhaseFreezingTime = true;
476     }
477     if (extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param.credentialId)) {
478         param.hasCredentialId = true;
479     }
480     if (extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_USER_ID, param.accountId)) {
481         param.hasAccountId = true;
482     }
483     if (extraInfo.GetInt64Value(Attributes::AttributeKey::ATTR_PIN_EXPIRED_INFO, param.pinValidityPeriod)) {
484         param.hasPinValidityPeriod = true;
485     }
486     param.callback = callback_;
487 }
488 
OnResult(int32_t result,const Attributes & extraInfo)489 void NapiUserAuthCallback::OnResult(int32_t result, const Attributes &extraInfo)
490 {
491     std::lock_guard<std::mutex> lock(mutex_);
492     if (callback_->onResultCalled) {
493         ACCOUNT_LOGE("call twice is not allowed");
494         return;
495     }
496     callback_->onResultCalled = true;
497     AuthCallbackParam *param = new (std::nothrow) AuthCallbackParam(env_);
498     if (param == nullptr) {
499         ACCOUNT_LOGE("fail for nullptr");
500         return;
501     }
502     PrepareAuthResult(result, extraInfo, *param);
503     auto task = [param = std::move(param)]() {
504         ACCOUNT_LOGI("Enter NapiUserAuthCallback::OnResult task");
505         napi_handle_scope scope = nullptr;
506         napi_open_handle_scope(param->env, &scope);
507         if (scope == nullptr) {
508             ACCOUNT_LOGE("Fail to open scope");
509             delete param;
510             return;
511         }
512         napi_value argv[ARG_SIZE_TWO] = {nullptr};
513         napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->resultCode), &argv[PARAM_ZERO]);
514         argv[PARAM_ONE] = GenerateAuthResult(param->env, param);
515         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback->onResult);
516         napi_close_handle_scope(param->env, scope);
517         delete param;
518         return;
519     };
520     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
521         delete param;
522         return;
523     }
524     ACCOUNT_LOGI("Post NapiUserAuthCallback::OnResult task finish");
525 }
526 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)527 void NapiUserAuthCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
528 {
529     std::lock_guard<std::mutex> lock(mutex_);
530     if (!callback_->hasOnAcquireInfo) {
531         ACCOUNT_LOGE("no 'OnAcquireInfo' callback need return");
532         return;
533     }
534     if (callback_->onResultCalled) {
535         ACCOUNT_LOGE("call after OnResult is not allowed");
536         return;
537     }
538     AuthCallbackParam *param = new (std::nothrow) AuthCallbackParam(env_);
539     if (param == nullptr) {
540         ACCOUNT_LOGE("Failed for nullptr");
541         return;
542     }
543     param->module = module;
544     param->acquireInfo = acquireInfo;
545     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_EXTRA_INFO, param->extraInfo);
546     param->callback = callback_;
547     auto task = [param = std::move(param)]() {
548         ACCOUNT_LOGI("Enter NapiUserAuthCallback::OnAcquireInfo task");
549         napi_handle_scope scope = nullptr;
550         napi_open_handle_scope(param->env, &scope);
551         if (scope == nullptr) {
552             ACCOUNT_LOGE("Fail to open scope");
553             delete param;
554             return;
555         }
556         napi_value argv[ARG_SIZE_THREE] = {nullptr};
557         napi_create_int32(param->env, param->module, &argv[PARAM_ZERO]);
558         napi_create_uint32(param->env, param->acquireInfo, &argv[PARAM_ONE]);
559         argv[PARAM_TWO] = CreateUint8Array(param->env, param->extraInfo.data(), param->extraInfo.size());
560         NapiCallVoidFunction(param->env, argv, ARG_SIZE_THREE, param->callback->onAcquireInfo);
561         napi_close_handle_scope(param->env, scope);
562         delete param;
563         return;
564     };
565     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
566         ACCOUNT_LOGE("Failed to send event for auth");
567         delete param;
568         return;
569     }
570     ACCOUNT_LOGI("Post NapiUserAuthCallback::OnAcquireInfo task finish");
571 }
572 
NapiGetInfoCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)573 NapiGetInfoCallback::NapiGetInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
574     : env_(env), deferred_(deferred)
575 {
576     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
577 }
578 
~NapiGetInfoCallback()579 NapiGetInfoCallback::~NapiGetInfoCallback()
580 {}
581 
OnCredentialInfo(int32_t result,const std::vector<AccountSA::CredentialInfo> & infoList)582 void NapiGetInfoCallback::OnCredentialInfo(int32_t result, const std::vector<AccountSA::CredentialInfo> &infoList)
583 {
584     std::lock_guard<std::mutex> lock(mutex_);
585     if (onResultCalled_) {
586         ACCOUNT_LOGE("Call twice is not allowed");
587         return;
588     }
589     onResultCalled_ = true;
590     std::shared_ptr<GetAuthInfoContext> context = std::make_shared<GetAuthInfoContext>(env_);
591     if (context == nullptr) {
592         ACCOUNT_LOGE("Failed for nullptr");
593         return;
594     }
595     context->callback = callback_;
596     context->deferred = deferred_;
597     context->errCode = result;
598     context->credInfo = infoList;
599     auto task = [context = std::move(context)]() {
600         ACCOUNT_LOGI("Enter NapiGetInfoCallback::OnCredentialInfo task");
601         napi_handle_scope scope = nullptr;
602         napi_open_handle_scope(context->env, &scope);
603         if (scope == nullptr) {
604             ACCOUNT_LOGE("Failed to open scope");
605             return;
606         }
607         napi_env env = context->env;
608         CommonCallbackInfo callbackInfo(env);
609         callbackInfo.callbackRef = context->callback->callbackRef;
610         callbackInfo.deferred = context->deferred;
611         callbackInfo.errCode = context->errCode;
612         if (context->errCode != ERR_OK) {
613             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
614             callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
615             napi_get_null(env, &callbackInfo.dataJs);
616         } else {
617             napi_get_null(env, &callbackInfo.errJs);
618             callbackInfo.dataJs = CreateCredInfoArray(env, context->credInfo);
619         }
620         CallbackAsyncOrPromise(callbackInfo);
621         napi_close_handle_scope(context->env, scope);
622         return;
623     };
624     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
625         ACCOUNT_LOGE("Failed to send event for auth");
626         return;
627     }
628     ACCOUNT_LOGI("Post OnCredentialInfo task finish");
629 }
630 
NapiGetEnrolledIdCallback(napi_env env,napi_deferred deferred)631 NapiGetEnrolledIdCallback::NapiGetEnrolledIdCallback(napi_env env, napi_deferred deferred)
632     : env_(env), deferred_(deferred)
633 {}
634 
~NapiGetEnrolledIdCallback()635 NapiGetEnrolledIdCallback::~NapiGetEnrolledIdCallback()
636 {}
637 
OnEnrolledId(int32_t result,uint64_t enrolledId)638 void NapiGetEnrolledIdCallback::OnEnrolledId(int32_t result, uint64_t enrolledId)
639 {
640     std::shared_ptr<GetEnrolledIdContext> context = std::make_shared<GetEnrolledIdContext>(env_);
641     if (context == nullptr) {
642         ACCOUNT_LOGE("Failed for nullptr");
643         return;
644     }
645     context->deferred = deferred_;
646     context->errCode = result;
647     context->enrolledId = enrolledId;
648     auto task = [context]() {
649         ACCOUNT_LOGI("Enter NapiGetEnrolledIdCallback::OnEnrolledId task");
650         napi_handle_scope scope = nullptr;
651         napi_open_handle_scope(context->env, &scope);
652         if (scope == nullptr) {
653             ACCOUNT_LOGE("Failed to open scope");
654             return;
655         }
656         napi_env env = context->env;
657         napi_value errJs = nullptr;
658         napi_value dataJs = nullptr;
659         if (context->errCode != ERR_OK) {
660             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
661             errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
662             napi_get_null(env, &dataJs);
663         } else {
664             napi_get_null(env, &errJs);
665             dataJs = CreateUint8Array(env, reinterpret_cast<uint8_t *>(&context->enrolledId), sizeof(uint64_t));
666         }
667         CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
668         napi_close_handle_scope(env, scope);
669         return;
670     };
671     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
672         ACCOUNT_LOGE("Failed to send event for auth");
673         return;
674     }
675     ACCOUNT_LOGI("Post OnEnrolledId task finish");
676 }
677 
NapiGetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred,const std::vector<Attributes::AttributeKey> & keys)678 NapiGetPropCallback::NapiGetPropCallback(
679     napi_env env, napi_ref callbackRef, napi_deferred deferred, const std::vector<Attributes::AttributeKey> &keys)
680     : env_(env), deferred_(deferred), keys_(keys)
681 {
682     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
683 }
684 
~NapiGetPropCallback()685 NapiGetPropCallback::~NapiGetPropCallback()
686 {}
687 
GetExecutorPropertys(const UserIam::UserAuth::Attributes & extraInfo,ExecutorProperty & propertyInfo)688 void NapiGetPropCallback::GetExecutorPropertys(
689     const UserIam::UserAuth::Attributes &extraInfo, ExecutorProperty &propertyInfo)
690 {
691     for (const auto &key : keys_) {
692         switch (key) {
693             case Attributes::AttributeKey::ATTR_PIN_SUB_TYPE: {
694                 if (!extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_PIN_SUB_TYPE, propertyInfo.authSubType)) {
695                     ACCOUNT_LOGE("get authSubType failed");
696                 }
697                 break;
698             }
699             case Attributes::AttributeKey::ATTR_REMAIN_TIMES: {
700                 if (!extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_REMAIN_TIMES, propertyInfo.remainTimes)) {
701                     ACCOUNT_LOGE("get remainTimes failed");
702                 }
703                 break;
704             }
705             case Attributes::AttributeKey::ATTR_FREEZING_TIME: {
706                 if (!extraInfo.GetInt32Value(
707                     Attributes::AttributeKey::ATTR_FREEZING_TIME, propertyInfo.freezingTime)) {
708                     ACCOUNT_LOGE("get freezingTime failed");
709                 }
710                 break;
711             }
712             case Attributes::AttributeKey::ATTR_ENROLL_PROGRESS: {
713                 if (!extraInfo.GetStringValue(
714                     Attributes::AttributeKey::ATTR_ENROLL_PROGRESS, propertyInfo.enrollmentProgress)) {
715                     ACCOUNT_LOGE("get enrollmentProgress failed");
716                 }
717                 break;
718             }
719             case Attributes::AttributeKey::ATTR_SENSOR_INFO: {
720                 if (!extraInfo.GetStringValue(Attributes::AttributeKey::ATTR_SENSOR_INFO, propertyInfo.sensorInfo)) {
721                     ACCOUNT_LOGE("get sensorInfo failed");
722                 }
723                 break;
724             }
725             case Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION: {
726                 if (!extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
727                     propertyInfo.nextPhaseFreezingTime)) {
728                     ACCOUNT_LOGE("get nextPhaseFreezingTime failed");
729                 }
730                 break;
731             }
732             default:
733                 ACCOUNT_LOGE("get invalid key");
734                 break;
735         }
736     }
737     return;
738 }
739 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)740 void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
741 {
742     std::lock_guard<std::mutex> lock(mutex_);
743     if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
744         ACCOUNT_LOGE("Return for nullptr");
745         return;
746     }
747     if (onResultCalled_) {
748         ACCOUNT_LOGE("Call twice is not allowed");
749         return;
750     }
751     onResultCalled_ = true;
752     std::shared_ptr<GetPropertyCommonContext> context = std::make_shared<GetPropertyCommonContext>(env_);
753     if (context == nullptr) {
754         ACCOUNT_LOGE("Failed for nullptr");
755         return;
756     }
757     // create context data
758     GetExecutorPropertys(extraInfo, context->propertyInfo);
759     context->isGetById = isGetById_;
760     context->callback = callback_;
761     context->deferred = deferred_;
762     context->errCode = ERR_OK;
763     context->propertyInfo.result = result;
764     context->keys = keys_;
765     auto task = [context = std::move(context)]() {
766         ACCOUNT_LOGI("Enter NapiGetPropCallback::OnResult task");
767         napi_handle_scope scope = nullptr;
768         napi_open_handle_scope(context->env, &scope);
769         if (scope == nullptr) {
770             ACCOUNT_LOGE("Failed to open scope");
771             return;
772         }
773         CommonCallbackInfo callbackInfo(context->env);
774         callbackInfo.callbackRef = context->callback->callbackRef;
775         callbackInfo.deferred = context->deferred;
776         CreateExecutorProperty(context->env, *context, callbackInfo.errJs, callbackInfo.dataJs);
777         callbackInfo.errCode = context->errCode;
778         CallbackAsyncOrPromise(callbackInfo);
779         napi_close_handle_scope(context->env, scope);
780         return;
781     };
782     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
783         ACCOUNT_LOGE("Failed to send event for auth");
784         return;
785     }
786     ACCOUNT_LOGI("Post OnResult task finish");
787 }
788 
NapiSetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)789 NapiSetPropCallback::NapiSetPropCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
790     : env_(env), deferred_(deferred)
791 {
792     callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
793 }
794 
~NapiSetPropCallback()795 NapiSetPropCallback::~NapiSetPropCallback()
796 {}
797 
NapiPrepareRemoteAuthCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)798 NapiPrepareRemoteAuthCallback::NapiPrepareRemoteAuthCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
799     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
800 {}
801 
~NapiPrepareRemoteAuthCallback()802 NapiPrepareRemoteAuthCallback::~NapiPrepareRemoteAuthCallback()
803 {
804     if (callbackRef_ != nullptr) {
805         ReleaseNapiRefAsync(env_, callbackRef_);
806         callbackRef_ = nullptr;
807     }
808     deferred_ = nullptr;
809 }
810 
OnResult(int32_t result)811 void NapiPrepareRemoteAuthCallback::OnResult(int32_t result)
812 {
813     std::lock_guard<std::mutex> lock(mutex_);
814     if ((callbackRef_ == nullptr) && (deferred_ == nullptr)) {
815         return;
816     }
817     std::shared_ptr<PrepareRemoteAuthContext> context = std::make_shared<PrepareRemoteAuthContext>(env_);
818     if (context == nullptr) {
819         ACCOUNT_LOGE("Nullptr fail.");
820         return;
821     }
822     context->deferred = deferred_;
823     context->errCode = ERR_OK;
824     context->result = result;
825     auto task = [context]() {
826         ACCOUNT_LOGI("Enter NapiPrepareRemoteAuthCallback::OnResult task");
827         napi_handle_scope scope = nullptr;
828         napi_open_handle_scope(context->env, &scope);
829         if (scope == nullptr) {
830             ACCOUNT_LOGE("Failed to open scope");
831             return;
832         }
833         napi_env env = context->env;
834         napi_value errJs = nullptr;
835         napi_value dataJs = nullptr;
836         context->errCode = context->result;
837         if (context->result != ERR_OK) {
838             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
839             errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
840             napi_get_null(env, &dataJs);
841         } else {
842             napi_get_null(env, &errJs);
843             napi_get_null(env, &dataJs);
844         }
845         CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
846         napi_close_handle_scope(context->env, scope);
847         return;
848     };
849     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
850         ACCOUNT_LOGE("Failed to send event for auth");
851         return;
852     }
853     ACCOUNT_LOGI("Post OnResult task finish");
854 }
855 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)856 void NapiSetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
857 {
858     std::lock_guard<std::mutex> lock(mutex_);
859     if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
860         return;
861     }
862     if (onResultCalled_) {
863         ACCOUNT_LOGE("Call twice is not allowed");
864         return;
865     }
866     onResultCalled_ = true;
867     std::shared_ptr<SetPropertyContext> context = std::make_shared<SetPropertyContext>(env_);
868     if (context == nullptr) {
869         ACCOUNT_LOGE("Failed for nullptr");
870         return;
871     }
872     context->callback = callback_;
873     context->deferred = deferred_;
874     context->errCode = ERR_OK;
875     context->result = result;
876     auto task = [context = std::move(context)]() {
877         ACCOUNT_LOGI("Enter NapiSetPropCallback::OnResult task");
878         napi_handle_scope scope = nullptr;
879         napi_open_handle_scope(context->env, &scope);
880         if (scope == nullptr) {
881             ACCOUNT_LOGE("Failed to open scope");
882             return;
883         }
884         napi_env env = context->env;
885         CommonCallbackInfo callbackInfo(env);
886         callbackInfo.callbackRef = context->callback->callbackRef;
887         callbackInfo.deferred = context->deferred;
888         callbackInfo.errCode = context->result;
889         if (context->result != ERR_OK) {
890             int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
891             callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
892             napi_get_null(env, &callbackInfo.dataJs);
893         } else {
894             napi_get_null(env, &callbackInfo.errJs);
895             napi_get_null(env, &callbackInfo.dataJs);
896         }
897         CallbackAsyncOrPromise(callbackInfo);
898         napi_close_handle_scope(env, scope);
899         return;
900     };
901     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
902         ACCOUNT_LOGE("Failed to send event for auth");
903         return;
904     }
905     ACCOUNT_LOGI("Post OnResult task finish");
906 }
907 #endif  // HAS_USER_AUTH_PART
908 
909 #ifdef HAS_PIN_AUTH_PART
InputDataConstructor(napi_env env,napi_callback_info info)910 napi_value InputDataConstructor(napi_env env, napi_callback_info info)
911 {
912     napi_value thisVar;
913     void *data;
914     size_t argc = ARG_SIZE_ONE;
915     napi_value argv[ARG_SIZE_ONE] = {nullptr};
916     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
917     InputerContext *context = static_cast<InputerContext *>(data);
918     if (thisVar == nullptr) {
919         ACCOUNT_LOGE("thisVar is nullptr");
920         return nullptr;
921     }
922     if (context == nullptr) {
923         ACCOUNT_LOGE("inputerData is nullptr");
924         return nullptr;
925     }
926     NAPI_CALL(env, napi_wrap(env, thisVar, context,
927         [](napi_env env, void *data, void *hint) {
928             InputerContext *context = static_cast<InputerContext *>(data);
929             if (context != nullptr) {
930                 delete context;
931             }
932         },
933         nullptr, nullptr));
934     return thisVar;
935 }
936 
OnSetData(napi_env env,napi_callback_info info)937 napi_value OnSetData(napi_env env, napi_callback_info info)
938 {
939     if (!IsSystemApp(env)) {
940         return nullptr;
941     }
942     size_t argc = ARG_SIZE_TWO;
943     napi_value thisVar = nullptr;
944     napi_value argv[ARG_SIZE_TWO] = {nullptr};
945     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
946     if (argc != ARG_SIZE_TWO) {
947         ACCOUNT_LOGE("failed to parse parameters, expect three parameters, but got %{public}zu", argc);
948         std::string errMsg = "Parameter error. The number of parameters should be 2";
949         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
950         return nullptr;
951     }
952     InputerContext *context = nullptr;
953     NAPI_CALL(env, napi_unwrap(env, thisVar, (void **)&context));
954     if (context == nullptr || context->inputerData == nullptr) {
955         ACCOUNT_LOGE("context or inputerData is nullptr");
956         return nullptr;
957     }
958     int32_t authSubType;
959     if (!GetIntProperty(env, argv[PARAM_ZERO], authSubType)) {
960         ACCOUNT_LOGE("Get authSubType failed");
961         std::string errMsg = "Parameter error. The type of \"authSubType\" must be AuthSubType";
962         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
963         return nullptr;
964     }
965     std::vector<uint8_t> data;
966     if (ParseUint8TypedArrayToVector(env, argv[PARAM_ONE], data) != napi_ok) {
967         ACCOUNT_LOGE("Get data failed");
968         std::string errMsg = "Parameter error. The type of \"data\" must be Uint8Array";
969         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
970         return nullptr;
971     }
972     ACCOUNT_LOGI("Call OnSetData, authSubType: %{public}d", authSubType);
973     context->inputerData->OnSetData(authSubType, data);
974     context->inputerData = nullptr;
975     return nullptr;
976 }
977 
GetCtorIInputerData(napi_env env,const std::shared_ptr<AccountSA::IInputerData> & inputerData)978 napi_value GetCtorIInputerData(napi_env env, const std::shared_ptr<AccountSA::IInputerData> &inputerData)
979 {
980     if (inputerData == nullptr) {
981         ACCOUNT_LOGE("inputerData nullptr");
982         return nullptr;
983     }
984     InputerContext *context = new (std::nothrow) InputerContext();
985     if (context == nullptr) {
986         ACCOUNT_LOGE("inputer context is nullptr");
987         return nullptr;
988     }
989     napi_property_descriptor clzDes[] = {
990         DECLARE_NAPI_FUNCTION("onSetData", OnSetData),
991     };
992     context->inputerData = inputerData;
993     napi_value cons;
994     NAPI_CALL(env, napi_define_class(env, "InputerData", NAPI_AUTO_LENGTH,
995         InputDataConstructor, reinterpret_cast<void *>(context),
996         sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
997     return cons;
998 }
999 
GetInputerInstance(InputerContext * context,napi_value * inputerDataVarCtor)1000 static napi_status GetInputerInstance(InputerContext *context, napi_value *inputerDataVarCtor)
1001 {
1002     napi_value cons = GetCtorIInputerData(context->env, context->inputerData);
1003     if (cons == nullptr) {
1004         ACCOUNT_LOGD("failed to GetCtorIInputerData");
1005         return napi_generic_failure;
1006     }
1007     return napi_new_instance(context->env, cons, 0, nullptr, inputerDataVarCtor);
1008 }
1009 
NapiGetDataCallback(napi_env env,const std::shared_ptr<NapiCallbackRef> & callback)1010 NapiGetDataCallback::NapiGetDataCallback(napi_env env, const std::shared_ptr<NapiCallbackRef> &callback)
1011     : env_(env), callback_(callback)
1012 {}
1013 
~NapiGetDataCallback()1014 NapiGetDataCallback::~NapiGetDataCallback()
1015 {}
1016 
OnGetData(int32_t authSubType,std::vector<uint8_t> challenge,const std::shared_ptr<AccountSA::IInputerData> inputerData)1017 void NapiGetDataCallback::OnGetData(int32_t authSubType, std::vector<uint8_t> challenge,
1018     const std::shared_ptr<AccountSA::IInputerData> inputerData)
1019 {
1020     if (callback_ == nullptr) {
1021         ACCOUNT_LOGE("The onGetData function is undefined");
1022         return;
1023     }
1024     std::shared_ptr<InputerContext> context = std::make_shared<InputerContext>();
1025     if (context == nullptr) {
1026         ACCOUNT_LOGE("Failed for nullptr");
1027         return;
1028     }
1029     context->env = env_;
1030     context->callback = callback_;
1031     context->authSubType = authSubType;
1032     context->challenge = challenge;
1033     context->inputerData = inputerData;
1034     auto task = [context]() {
1035         ACCOUNT_LOGI("Enter NapiGetDataCallback::OnGetData task");
1036         napi_env env = context->env;
1037         napi_handle_scope scope = nullptr;
1038         napi_open_handle_scope(env, &scope);
1039         if (scope == nullptr) {
1040             ACCOUNT_LOGE("Failed to open scope");
1041             return;
1042         }
1043         napi_value argv[ARG_SIZE_THREE] = {0};
1044         napi_create_int32(env, context->authSubType, &argv[PARAM_ZERO]);
1045         GetInputerInstance(context.get(), &argv[PARAM_ONE]);
1046         napi_create_object(env, &argv[PARAM_TWO]);
1047         if (!(context->challenge.empty())) {
1048             napi_value dataJs = nullptr;
1049             dataJs = CreateUint8Array(env, context->challenge.data(), context->challenge.size());
1050             napi_set_named_property(env, argv[PARAM_TWO], "challenge", dataJs);
1051         }
1052         NapiCallVoidFunction(env, argv, ARG_SIZE_THREE, context->callback->callbackRef);
1053         napi_close_handle_scope(env, scope);
1054         return;
1055     };
1056     if (napi_status::napi_ok !=  napi_send_event(env_, task, napi_eprio_vip)) {
1057         ACCOUNT_LOGE("Failed to send event for auth");
1058         return;
1059     }
1060     ACCOUNT_LOGI("Post OnGetData task finish");
1061 }
1062 #endif  // HAS_PIN_AUTH_PART
1063 
CallbackAsyncOrPromise(const CommonCallbackInfo & callbackInfo)1064 void CallbackAsyncOrPromise(const CommonCallbackInfo &callbackInfo)
1065 {
1066     if (callbackInfo.callbackRef) {
1067         napi_value argv[ARG_SIZE_TWO] = {callbackInfo.errJs, callbackInfo.dataJs};
1068         ACCOUNT_LOGI("call js function");
1069         NapiCallVoidFunction(callbackInfo.env, argv, ARG_SIZE_TWO, callbackInfo.callbackRef);
1070     } else {
1071         if (callbackInfo.errCode == ERR_OK) {
1072             napi_resolve_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.dataJs);
1073         } else {
1074             napi_reject_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.errJs);
1075         }
1076     }
1077 }
1078 
CallbackAsyncOrPromise(napi_env env,CommonAsyncContext * context,napi_value errJs,napi_value dataJs)1079 void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs)
1080 {
1081     CommonCallbackInfo callbackInfo(env);
1082     callbackInfo.callbackRef = context->callbackRef;
1083     callbackInfo.deferred = context->deferred;
1084     callbackInfo.errJs = errJs;
1085     callbackInfo.dataJs = dataJs;
1086     callbackInfo.errCode = context->errCode;
1087     CallbackAsyncOrPromise(callbackInfo);
1088 }
1089 
ParseUInt32Array(napi_env env,napi_value value,std::vector<uint32_t> & data)1090 napi_status ParseUInt32Array(napi_env env, napi_value value, std::vector<uint32_t> &data)
1091 {
1092     data.clear();
1093     bool isArray = false;
1094     napi_is_array(env, value, &isArray);
1095     if (!isArray) {
1096         ACCOUNT_LOGE("value is not an array");
1097         return napi_invalid_arg;
1098     }
1099     uint32_t arrLen = 0;
1100     napi_get_array_length(env, value, &arrLen);
1101     for (uint32_t i = 0; i < arrLen; ++i) {
1102         napi_value item = nullptr;
1103         napi_get_element(env, value, i, &item);
1104         uint32_t num = 0;
1105         if (napi_get_value_uint32(env, item, &num) != napi_ok) {
1106             data.clear();
1107             return napi_number_expected;
1108         }
1109         data.push_back(num);
1110     }
1111     return napi_ok;
1112 }
1113 
CreateErrorObject(napi_env env,int32_t code)1114 napi_value CreateErrorObject(napi_env env, int32_t code)
1115 {
1116     napi_value errObj = nullptr;
1117     NAPI_CALL(env, napi_create_object(env, &errObj));
1118     napi_value number = 0;
1119     NAPI_CALL(env, napi_create_int32(env, code, &number));
1120     NAPI_CALL(env, napi_set_named_property(env, errObj, "code", number));
1121     return errObj;
1122 }
1123 
IsAccountIdValid(int32_t accountId)1124 bool IsAccountIdValid(int32_t accountId)
1125 {
1126     if (accountId < 0) {
1127         ACCOUNT_LOGI("The account id is invalid");
1128         return false;
1129     }
1130     return true;
1131 }
1132 }  // namespace AccountJsKit
1133 }  // namespace OHOS
1134