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