• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <uv.h>
19 #include "account_error_no.h"
20 #include "account_log_wrapper.h"
21 #include "napi_account_error.h"
22 #include "napi_account_common.h"
23 #include "securec.h"
24 
25 namespace OHOS {
26 namespace AccountJsKit {
27 using namespace OHOS::AccountSA;
28 
AccountIAMConvertOtherToJSErrCode(int32_t errCode)29 static int32_t AccountIAMConvertOtherToJSErrCode(int32_t errCode)
30 {
31     switch (errCode) {
32         case ERR_IAM_SUCCESS:
33             return ERR_JS_SUCCESS;
34         case ERR_IAM_FAIL:
35             return ERR_JS_AUTH_CREDENTIAL_WRONG_ERROR;
36         case ERR_IAM_TRUST_LEVEL_NOT_SUPPORT:
37             return ERR_JS_TRUST_LEVEL_NOT_SUPPORTED;
38         case ERR_IAM_TYPE_NOT_SUPPORT:
39             return ERR_JS_AUTH_TYPE_NOT_SUPPORTED;
40         case ERR_IAM_TIMEOUT:
41             return ERR_JS_AUTH_TIMEOUT;
42         case ERR_IAM_BUSY:
43             return ERR_JS_AUTH_SERVICE_BUSY;
44         case ERR_IAM_LOCKED:
45             return ERR_JS_AUTH_SERVICE_LOCKED;
46         case ERR_IAM_NOT_ENROLLED:
47             return ERR_JS_CREDENTIAL_NOT_EXIST;
48         case ERR_IAM_INVALID_CONTEXT_ID:
49             return ERR_JS_INVALID_CONTEXT_ID;
50         case ERR_ACCOUNT_COMMON_INVALID_PARAMTER:
51         case ERR_IAM_INVALID_PARAMETERS:
52             return ERR_JS_INVALID_PARAMETER;
53         case ERR_ACCOUNT_IAM_KIT_INPUTER_ALREADY_REGISTERED:
54             return ERR_JS_CREDENTIAL_INPUTER_ALREADY_EXIST;
55         case ERR_ACCOUNT_IAM_KIT_INPUTER_NOT_REGISTERED:
56             return ERR_JS_CREDENTIAL_INPUTER_NOT_EXIST;
57         case ERR_ACCOUNT_IAM_UNSUPPORTED_AUTH_TYPE:
58             return ERR_JS_AUTH_TYPE_NOT_SUPPORTED;
59         default:
60             return ERR_JS_SYSTEM_SERVICE_EXCEPTION;
61     }
62 }
63 
AccountIAMConvertToJSErrCode(int32_t errCode)64 int32_t AccountIAMConvertToJSErrCode(int32_t errCode)
65 {
66     if ((errCode >= ERR_ACCOUNT_IAM_KIT_SEND_REQUEST && errCode <= ERR_ACCOUNT_IAM_KIT_READ_PARCEL_FAIL) ||
67         (errCode >= ERR_ACCOUNT_IAM_SERVICE_GET_STORAGE_SYSTEM_ABILITY &&
68         errCode <= ERR_ACCOUNT_IAM_SERVICE_READ_PARCEL_FAIL)) {
69         return ERR_JS_SYSTEM_SERVICE_EXCEPTION;
70     } else if (errCode == ERR_ACCOUNT_IAM_SERVICE_PERMISSION_DENIED || errCode == ERR_IAM_CHECK_PERMISSION_FAILED) {
71         return ERR_JS_PERMISSION_DENIED;
72     } else if (errCode == ERR_ACCOUNT_IAM_SERVICE_PARAM_INVALID_ERROR ||
73         errCode == ERR_ACCOUNT_IAM_KIT_PARAM_INVALID_ERROR) {
74         return ERR_JS_INVALID_PARAMETER;
75     }
76     return AccountIAMConvertOtherToJSErrCode(errCode);
77 }
78 
IAMAsyncContext(napi_env napiEnv)79 IAMAsyncContext::IAMAsyncContext(napi_env napiEnv)
80     : CommonAsyncContext(napiEnv)
81 {}
82 
~IAMAsyncContext()83 IAMAsyncContext::~IAMAsyncContext()
84 {
85     if (env == nullptr) {
86         return;
87     }
88     if (work != nullptr) {
89         napi_delete_async_work(env, work);
90         work = nullptr;
91     }
92     if (callbackRef != nullptr) {
93         napi_delete_reference(env, callbackRef);
94         callbackRef = nullptr;
95     }
96 }
97 
98 #ifdef HAS_USER_AUTH_PART
NapiIDMCallback(napi_env env,const JsIAMCallback & callback)99 NapiIDMCallback::NapiIDMCallback(napi_env env, const JsIAMCallback &callback) : env_(env), callback_(callback)
100 {}
101 
~NapiIDMCallback()102 NapiIDMCallback::~NapiIDMCallback()
103 {
104     ReleaseNapiRefArray(env_, { callback_.onResult, callback_.onAcquireInfo });
105 }
106 
OnIDMResultWork(uv_work_t * work,int status)107 static void OnIDMResultWork(uv_work_t* work, int status)
108 {
109     std::unique_ptr<uv_work_t> workPtr(work);
110     napi_handle_scope scope = nullptr;
111     if (!InitUvWorkCallbackEnv(work, scope)) {
112         return;
113     }
114     std::unique_ptr<IDMCallbackParam> param(reinterpret_cast<IDMCallbackParam *>(work->data));
115     napi_value argv[ARG_SIZE_TWO] = {0};
116     napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->result), &argv[PARAM_ZERO]);
117     napi_create_object(param->env, &argv[PARAM_ONE]);
118     napi_value credentialId = CreateUint8Array(
119         param->env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
120     napi_set_named_property(param->env, argv[PARAM_ONE], "credentialId", credentialId);
121     NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback.onResult);
122     napi_close_handle_scope(param->env, scope);
123 }
124 
OnResult(int32_t result,const Attributes & extraInfo)125 void NapiIDMCallback::OnResult(int32_t result, const Attributes &extraInfo)
126 {
127     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
128     std::unique_ptr<IDMCallbackParam> param = std::make_unique<IDMCallbackParam>(env_);
129     uv_loop_s *loop = nullptr;
130     napi_get_uv_event_loop(env_, &loop);
131     if (loop == nullptr || work == nullptr || param == nullptr) {
132         ACCOUNT_LOGE("fail for nullptr");
133         return;
134     }
135     param->result = result;
136     extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param->credentialId);
137     param->callback = callback_;
138     work->data = reinterpret_cast<void *>(param.get());
139     NAPI_CALL_RETURN_VOID(env_, uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnIDMResultWork));
140     work.release();
141     param.release();
142 }
143 
OnAcquireInfoWork(uv_work_t * work,int status)144 static void OnAcquireInfoWork(uv_work_t* work, int status)
145 {
146     std::unique_ptr<uv_work_t> workPtr(work);
147     napi_handle_scope scope = nullptr;
148     if (!InitUvWorkCallbackEnv(work, scope)) {
149         return;
150     }
151     std::unique_ptr<IDMCallbackParam> param(reinterpret_cast<IDMCallbackParam *>(work->data));
152     napi_value argv[ARG_SIZE_THREE] = {0};
153     napi_env env = param->env;
154     napi_create_int32(env, param->module, &argv[PARAM_ZERO]);
155     napi_create_int32(env, param->acquire, &argv[PARAM_ONE]);
156     napi_value credentialId = CreateUint8Array(
157         env, reinterpret_cast<uint8_t *>(&param->credentialId), sizeof(uint64_t));
158     napi_create_object(env, &argv[PARAM_TWO]);
159     napi_set_named_property(env, argv[PARAM_TWO], "credentialId", credentialId);
160     NapiCallVoidFunction(env, argv, ARG_SIZE_THREE, param->callback.onAcquireInfo);
161     napi_close_handle_scope(env, scope);
162 }
163 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)164 void NapiIDMCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
165 {
166     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
167     std::unique_ptr<IDMCallbackParam> param = std::make_unique<IDMCallbackParam>(env_);
168     uv_loop_s *loop = nullptr;
169     napi_get_uv_event_loop(env_, &loop);
170     if (loop == nullptr || work == nullptr || param == nullptr) {
171         ACCOUNT_LOGE("fail for nullptr");
172         return;
173     }
174     param->callback = callback_;
175     param->module = module;
176     param->acquire = acquireInfo;
177     extraInfo.GetUint64Value(Attributes::AttributeKey::ATTR_CREDENTIAL_ID, param->credentialId);
178     work->data = reinterpret_cast<void *>(param.get());
179     NAPI_CALL_RETURN_VOID(env_, uv_queue_work(loop, work.get(), [] (uv_work_t *work) { }, OnAcquireInfoWork));
180     work.release();
181     param.release();
182 }
183 
ParseAddCredInfo(napi_env env,napi_value value,CredentialParameters & addCredInfo)184 napi_status ParseAddCredInfo(napi_env env, napi_value value, CredentialParameters &addCredInfo)
185 {
186     napi_valuetype valueType = napi_undefined;
187     napi_typeof(env, value, &valueType);
188     if (valueType != napi_object) {
189         ACCOUNT_LOGE("value is not an object");
190         return napi_invalid_arg;
191     }
192     napi_value result = nullptr;
193     napi_get_named_property(env, value, "credType", &result);
194     int32_t credType = -1;
195     napi_get_value_int32(env, result, &credType);
196     addCredInfo.authType = static_cast<AuthType>(credType);
197     napi_get_named_property(env, value, "credSubType", &result);
198     int32_t credSubType = -1;
199     napi_get_value_int32(env, result, &credSubType);
200     addCredInfo.pinType = static_cast<PinSubType>(credSubType);
201     napi_get_named_property(env, value, "token", &result);
202     return ParseUint8TypedArrayToVector(env, result, addCredInfo.token);
203 }
204 
ParseIAMCallback(napi_env env,napi_value object,JsIAMCallback & callback)205 napi_status ParseIAMCallback(napi_env env, napi_value object, JsIAMCallback &callback)
206 {
207     napi_valuetype valueType = napi_undefined;
208     napi_typeof(env, object, &valueType);
209     if (valueType != napi_object) {
210         ACCOUNT_LOGE("invalid object");
211         return napi_invalid_arg;
212     }
213     napi_value result = nullptr;
214     napi_get_named_property(env, object, "onResult", &result);
215     napi_typeof(env, result, &valueType);
216     if (valueType == napi_function) {
217         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback.onResult), napi_generic_failure);
218     } else {
219         ACCOUNT_LOGE("onResult is not a function");
220         return napi_invalid_arg;
221     }
222     bool hasOnAcquireInfo = false;
223     napi_has_named_property(env, object, "onAcquireInfo", &hasOnAcquireInfo);
224     if (!hasOnAcquireInfo) {
225         return napi_ok;
226     }
227     napi_get_named_property(env, object, "onAcquireInfo", &result);
228     napi_typeof(env, result, &valueType);
229     if (valueType == napi_function) {
230         NAPI_CALL_BASE(env, napi_create_reference(env, result, 1, &callback.onAcquireInfo), napi_generic_failure);
231     } else {
232         ACCOUNT_LOGE("onAcquireInfo is not a function");
233         return napi_invalid_arg;
234     }
235     return napi_ok;
236 }
237 
CreateCredInfoArray(napi_env env,const std::vector<CredentialInfo> & info)238 napi_value CreateCredInfoArray(napi_env env, const std::vector<CredentialInfo> &info)
239 {
240     napi_value arr = nullptr;
241     napi_create_array_with_length(env, info.size(), &arr);
242     uint32_t index = 0;
243     for (auto item : info) {
244         napi_value obj;
245         NAPI_CALL(env, napi_create_object(env, &obj));
246         napi_value credentialId = CreateUint8Array(
247             env, reinterpret_cast<uint8_t *>(&item.credentialId), sizeof(uint64_t));
248         napi_value authType;
249         NAPI_CALL(env, napi_create_uint32(env, item.authType, &authType));
250         napi_value napiPinType;
251         PinSubType pinType = item.pinType.value_or(PinSubType::PIN_MAX);
252         NAPI_CALL(env, napi_create_uint32(env, pinType, &napiPinType));
253         napi_value templateId = CreateUint8Array(
254             env, reinterpret_cast<uint8_t *>(&item.templateId), sizeof(uint64_t));
255         NAPI_CALL(env, napi_set_named_property(env, obj, "credentialId", credentialId));
256         NAPI_CALL(env, napi_set_named_property(env, obj, "authType", authType));
257         NAPI_CALL(env, napi_set_named_property(env, obj, "authSubType", napiPinType));
258         NAPI_CALL(env, napi_set_named_property(env, obj, "templateId", templateId));
259         NAPI_CALL(env, napi_set_element(env, arr, index, obj));
260         index++;
261     }
262     return arr;
263 }
264 
ParseGetPropRequest(napi_env env,napi_value object,GetPropertyRequest & request)265 napi_status ParseGetPropRequest(napi_env env, napi_value object, GetPropertyRequest &request)
266 {
267     napi_valuetype valueType = napi_undefined;
268     napi_typeof(env, object, &valueType);
269     if (valueType != napi_object) {
270         ACCOUNT_LOGE("invalid object");
271         return napi_invalid_arg;
272     }
273     napi_value napiAuthType = nullptr;
274     napi_get_named_property(env, object, "authType", &napiAuthType);
275     int32_t authType = -1;
276     napi_get_value_int32(env, napiAuthType, &authType);
277     request.authType = static_cast<AuthType>(authType);
278     napi_value napiKeys = nullptr;
279     napi_get_named_property(env, object, "keys", &napiKeys);
280     std::vector<uint32_t> keys;
281     ParseUInt32Array(env, napiKeys, keys);
282     for (const auto &item : keys) {
283         request.keys.push_back(static_cast<Attributes::AttributeKey>(item));
284     }
285     return napi_ok;
286 }
287 
ParseSetPropRequest(napi_env env,napi_value object,SetPropertyRequest & request)288 napi_status ParseSetPropRequest(napi_env env, napi_value object, SetPropertyRequest &request)
289 {
290     napi_valuetype valueType = napi_undefined;
291     napi_typeof(env, object, &valueType);
292     if (valueType != napi_object) {
293         ACCOUNT_LOGE("invalid object");
294         return napi_invalid_arg;
295     }
296     napi_value napiKey = nullptr;
297     napi_get_named_property(env, object, "key", &napiKey);
298     int32_t key = -1;
299     napi_get_value_int32(env, napiKey, &key);
300     request.mode = static_cast<PropertyMode>(key);
301     napi_value napiAuthType = nullptr;
302     napi_get_named_property(env, object, "authType", &napiAuthType);
303     int32_t authType = -1;
304     napi_get_value_int32(env, napiAuthType, &authType);
305     request.authType = static_cast<AuthType>(authType);
306     napi_value napiSetInfo = nullptr;
307     napi_get_named_property(env, object, "setInfo", &napiSetInfo);
308     std::vector<uint8_t> setInfo;
309     ParseUint8TypedArrayToVector(env, napiSetInfo, setInfo);
310     request.attrs.SetUint8ArrayValue(Attributes::AttributeKey(key), setInfo);
311     return napi_ok;
312 }
313 
GeneratePropertyJs(napi_env env,const GetPropertyContext & prop,napi_value & dataJs)314 static void GeneratePropertyJs(napi_env env, const GetPropertyContext &prop, napi_value &dataJs)
315 {
316     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &dataJs));
317     napi_value napiResult = 0;
318     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, prop.result, &napiResult));
319     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "result", napiResult));
320     napi_value napiAuthSubType = 0;
321     NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, prop.authSubType, &napiAuthSubType));
322     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "authSubType", napiAuthSubType));
323     napi_value napiRemainTimes = 0;
324     NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, prop.remainTimes, &napiRemainTimes));
325     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "remainTimes", napiRemainTimes));
326     napi_value napiFreezingTimes = 0;
327     NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, prop.freezingTime, &napiFreezingTimes));
328     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, dataJs, "freezingTime", napiFreezingTimes));
329 }
330 
CreateExecutorProperty(napi_env env,GetPropertyContext & prop,napi_value & errJs,napi_value & dataJs)331 static void CreateExecutorProperty(napi_env env, GetPropertyContext &prop, napi_value &errJs, napi_value &dataJs)
332 {
333     if (prop.result != ERR_OK && prop.result != ERR_IAM_NOT_ENROLLED) {
334         prop.errCode = prop.result;
335         int32_t jsErrCode = AccountIAMConvertToJSErrCode(prop.result);
336         errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
337         napi_get_null(env, &dataJs);
338     } else {
339         prop.errCode = 0;
340         napi_get_null(env, &errJs);
341         GeneratePropertyJs(env, prop, dataJs);
342     }
343 }
344 
CreateAuthResult(napi_env env,const std::vector<uint8_t> & token,int32_t remainTimes,int32_t freezingTime)345 napi_value CreateAuthResult(napi_env env, const std::vector<uint8_t> &token, int32_t remainTimes, int32_t freezingTime)
346 {
347     napi_value object = nullptr;
348     NAPI_CALL(env, napi_create_object(env, &object));
349     if (remainTimes >= 0) {
350         napi_value napiRemainTimes = 0;
351         napi_create_uint32(env, remainTimes, &napiRemainTimes);
352         napi_set_named_property(env, object, "remainTimes", napiRemainTimes);
353     }
354     if (remainTimes >= 0) {
355         napi_value napiFreezingTimes = 0;
356         napi_create_uint32(env, freezingTime, &napiFreezingTimes);
357         napi_set_named_property(env, object, "freezingTime", napiFreezingTimes);
358     }
359     if (token.size() > 0) {
360         napi_value napiToken = CreateUint8Array(env, token.data(), token.size());
361         napi_set_named_property(env, object, "token", napiToken);
362     }
363     return object;
364 }
365 
OnUserAuthResultWork(uv_work_t * work,int status)366 static void OnUserAuthResultWork(uv_work_t *work, int status)
367 {
368     std::unique_ptr<uv_work_t> workPtr(work);
369     napi_handle_scope scope = nullptr;
370     if (!InitUvWorkCallbackEnv(work, scope)) {
371         return;
372     }
373     std::unique_ptr<AuthCallbackParam> param(reinterpret_cast<AuthCallbackParam *>(work->data));
374     napi_value argv[ARG_SIZE_TWO] = {nullptr};
375     napi_create_int32(param->env, AccountIAMConvertToJSErrCode(param->resultCode), &argv[PARAM_ZERO]);
376     argv[PARAM_ONE] = CreateAuthResult(param->env, param->token, param->remainTimes, param->freezingTime);
377     NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->callback.onResult);
378     napi_close_handle_scope(param->env, scope);
379 }
380 
OnUserAuthAcquireInfoWork(uv_work_t * work,int status)381 static void OnUserAuthAcquireInfoWork(uv_work_t *work, int status)
382 {
383     std::unique_ptr<uv_work_t> workPtr(work);
384     napi_handle_scope scope = nullptr;
385     if (!InitUvWorkCallbackEnv(work, scope)) {
386         return;
387     }
388     std::unique_ptr<AuthCallbackParam> param(reinterpret_cast<AuthCallbackParam *>(work->data));
389     napi_value argv[ARG_SIZE_THREE] = {nullptr};
390     napi_create_int32(param->env, param->module, &argv[PARAM_ZERO]);
391     napi_create_uint32(param->env, param->acquireInfo, &argv[PARAM_ONE]);
392     napi_create_int32(param->env, param->extraInfo, &argv[PARAM_TWO]);
393     NapiCallVoidFunction(param->env, argv, ARG_SIZE_THREE, param->callback.onAcquireInfo);
394     napi_close_handle_scope(param->env, scope);
395 }
396 
NapiUserAuthCallback(napi_env env,JsIAMCallback callback)397 NapiUserAuthCallback::NapiUserAuthCallback(napi_env env, JsIAMCallback callback)
398     : env_(env), callback_(callback)
399 {}
400 
~NapiUserAuthCallback()401 NapiUserAuthCallback::~NapiUserAuthCallback()
402 {
403     ReleaseNapiRefArray(env_, { callback_.onResult, callback_.onAcquireInfo });
404 }
405 
OnResult(int32_t result,const Attributes & extraInfo)406 void NapiUserAuthCallback::OnResult(int32_t result, const Attributes &extraInfo)
407 {
408     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
409     std::unique_ptr<AuthCallbackParam> param = std::make_unique<AuthCallbackParam>(env_);
410     uv_loop_s *loop = nullptr;
411     napi_get_uv_event_loop(env_, &loop);
412     if (loop == nullptr || work == nullptr || param == nullptr) {
413         ACCOUNT_LOGE("fail for nullptr");
414         return;
415     }
416     param->resultCode = result;
417     extraInfo.GetUint8ArrayValue(Attributes::AttributeKey::ATTR_SIGNATURE, param->token);
418     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_REMAIN_TIMES, param->remainTimes);
419     extraInfo.GetInt32Value(Attributes::AttributeKey::ATTR_FREEZING_TIME, param->freezingTime);
420     param->callback = callback_;
421     work->data = reinterpret_cast<void *>(param.get());
422     NAPI_CALL_RETURN_VOID(env_, uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnUserAuthResultWork));
423     work.release();
424     param.release();
425 }
426 
OnAcquireInfo(int32_t module,uint32_t acquireInfo,const Attributes & extraInfo)427 void NapiUserAuthCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, const Attributes &extraInfo)
428 {
429     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
430     std::unique_ptr<AuthCallbackParam> param = std::make_unique<AuthCallbackParam>(env_);
431     uv_loop_s *loop = nullptr;
432     napi_get_uv_event_loop(env_, &loop);
433     if (loop == nullptr || work == nullptr || param == nullptr) {
434         ACCOUNT_LOGE("fail for nullptr");
435         return;
436     }
437     param->module = module;
438     param->acquireInfo = acquireInfo;
439     param->extraInfo = 0;
440     param->callback = callback_;
441     work->data = reinterpret_cast<void *>(param.get());
442     NAPI_CALL_RETURN_VOID(env_, uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnUserAuthAcquireInfoWork));
443     work.release();
444     param.release();
445 }
446 
447 
NapiGetInfoCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)448 NapiGetInfoCallback::NapiGetInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
449     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
450 {}
451 
~NapiGetInfoCallback()452 NapiGetInfoCallback::~NapiGetInfoCallback()
453 {}
454 
OnGetInfoWork(uv_work_t * work,int status)455 static void OnGetInfoWork(uv_work_t *work, int status)
456 {
457     std::unique_ptr<uv_work_t> workPtr(work);
458     napi_handle_scope scope = nullptr;
459     if (!InitUvWorkCallbackEnv(work, scope)) {
460         return;
461     }
462     std::unique_ptr<GetAuthInfoContext> context(reinterpret_cast<GetAuthInfoContext *>(work->data));
463     napi_env env = context->env;
464     napi_value errJs = nullptr;
465     napi_value dataJs = nullptr;
466     if (context->errCode != ERR_OK) {
467         int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
468         errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
469         napi_get_null(env, &dataJs);
470     } else {
471         napi_get_null(env, &errJs);
472         dataJs = CreateCredInfoArray(env, context->credInfo);
473     }
474     CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
475     napi_close_handle_scope(env, scope);
476 }
477 
OnCredentialInfo(int32_t result,const std::vector<AccountSA::CredentialInfo> & infoList)478 void NapiGetInfoCallback::OnCredentialInfo(int32_t result, const std::vector<AccountSA::CredentialInfo> &infoList)
479 {
480     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
481     std::unique_ptr<GetAuthInfoContext> context = std::make_unique<GetAuthInfoContext>(env_);
482     uv_loop_s *loop = nullptr;
483     napi_get_uv_event_loop(env_, &loop);
484     if (loop == nullptr || work == nullptr || context == nullptr) {
485         ACCOUNT_LOGE("fail for nullptr");
486         return;
487     }
488     context->callbackRef = callbackRef_;
489     context->deferred = deferred_;
490     context->errCode = result;
491     context->credInfo = infoList;
492     work->data = reinterpret_cast<void *>(context.get());
493     ErrCode ret = uv_queue_work(loop, work.get(), [](uv_work_t *work) {}, OnGetInfoWork);
494     if (ret != ERR_OK) {
495         ReleaseNapiRefAsync(env_, callbackRef_);
496         return;
497     }
498     work.release();
499     context.release();
500 }
501 
NapiGetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)502 NapiGetPropCallback::NapiGetPropCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
503     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
504 {}
505 
~NapiGetPropCallback()506 NapiGetPropCallback::~NapiGetPropCallback()
507 {}
508 
OnGetPropertyWork(uv_work_t * work,int status)509 static void OnGetPropertyWork(uv_work_t* work, int status)
510 {
511     std::unique_ptr<uv_work_t> workPtr(work);
512     napi_handle_scope scope = nullptr;
513     if (!InitUvWorkCallbackEnv(work, scope)) {
514         return;
515     }
516     std::unique_ptr<GetPropertyContext> context(reinterpret_cast<GetPropertyContext *>(work->data));
517     napi_value errJs = nullptr;
518     napi_value dataJs = nullptr;
519     CreateExecutorProperty(context->env, *context, errJs, dataJs);
520     CallbackAsyncOrPromise(context->env, context.get(), errJs, dataJs);
521     napi_close_handle_scope(context->env, scope);
522 }
523 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)524 void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
525 {
526     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
527     std::unique_ptr<GetPropertyContext> context = std::make_unique<GetPropertyContext>(env_);
528     uv_loop_s *loop = nullptr;
529     napi_get_uv_event_loop(env_, &loop);
530     if (loop == nullptr || work == nullptr || context == nullptr) {
531         ACCOUNT_LOGE("fail for nullptr");
532         return;
533     }
534     extraInfo.GetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, context->authSubType);
535     extraInfo.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, context->remainTimes);
536     extraInfo.GetInt32Value(Attributes::ATTR_FREEZING_TIME, context->freezingTime);
537     context->callbackRef = callbackRef_;
538     context->deferred = deferred_;
539     context->errCode = ERR_OK;
540     context->result = result;
541     work->data = reinterpret_cast<void *>(context.get());
542     ErrCode ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnGetPropertyWork);
543     if (ret != ERR_OK) {
544         ReleaseNapiRefAsync(env_, callbackRef_);
545         return;
546     }
547     work.release();
548     context.release();
549 }
550 
NapiSetPropCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)551 NapiSetPropCallback::NapiSetPropCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
552     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
553 {}
554 
~NapiSetPropCallback()555 NapiSetPropCallback::~NapiSetPropCallback()
556 {}
557 
OnSetPropertyWork(uv_work_t * work,int status)558 static void OnSetPropertyWork(uv_work_t* work, int status)
559 {
560     std::unique_ptr<uv_work_t> workPtr(work);
561     napi_handle_scope scope = nullptr;
562     if (!InitUvWorkCallbackEnv(work, scope)) {
563         return;
564     }
565     std::unique_ptr<SetPropertyContext> context(reinterpret_cast<SetPropertyContext *>(work->data));
566     napi_env env = context->env;
567     napi_value errJs = nullptr;
568     napi_value dataJs = nullptr;
569     context->errCode = context->result;
570     if (context->result != ERR_OK) {
571         int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
572         errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
573         napi_get_null(env, &dataJs);
574     } else {
575         napi_get_null(env, &errJs);
576         napi_get_null(env, &dataJs);
577     }
578     CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
579     napi_close_handle_scope(env, scope);
580 }
581 
OnResult(int32_t result,const UserIam::UserAuth::Attributes & extraInfo)582 void NapiSetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
583 {
584     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
585     std::unique_ptr<SetPropertyContext> context = std::make_unique<SetPropertyContext>(env_);
586     uv_loop_s *loop = nullptr;
587     napi_get_uv_event_loop(env_, &loop);
588     if (loop == nullptr || work == nullptr || context == nullptr) {
589         ACCOUNT_LOGE("fail for nullptr");
590         return;
591     }
592     context->callbackRef = callbackRef_;
593     context->deferred = deferred_;
594     context->errCode = ERR_OK;
595     context->result = result;
596     work->data = reinterpret_cast<void *>(context.get());
597     ErrCode ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnSetPropertyWork);
598     if (ret != ERR_OK) {
599         ReleaseNapiRefAsync(env_, callbackRef_);
600         return;
601     }
602     work.release();
603     context.release();
604 }
605 #endif  // HAS_USER_AUTH_PART
606 
607 #ifdef HAS_PIN_AUTH_PART
InputDataConstructor(napi_env env,napi_callback_info info)608 napi_value InputDataConstructor(napi_env env, napi_callback_info info)
609 {
610     napi_value thisVar;
611     void *data;
612     size_t argc = ARG_SIZE_ONE;
613     napi_value argv[ARG_SIZE_ONE] = {nullptr};
614     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
615     InputerContext *context = static_cast<InputerContext *>(data);
616     if (thisVar == nullptr) {
617         ACCOUNT_LOGE("thisVar is nullptr");
618         return nullptr;
619     }
620     if (context == nullptr) {
621         ACCOUNT_LOGE("inputerData is nullptr");
622         return nullptr;
623     }
624     NAPI_CALL(env, napi_wrap(env, thisVar, context,
625         [](napi_env env, void *data, void *hint) {
626             InputerContext *context = static_cast<InputerContext *>(data);
627             if (context != nullptr) {
628                 delete context;
629             }
630         },
631         nullptr, nullptr));
632     return thisVar;
633 }
634 
OnSetData(napi_env env,napi_callback_info info)635 napi_value OnSetData(napi_env env, napi_callback_info info)
636 {
637     size_t argc = ARG_SIZE_TWO;
638     napi_value thisVar = nullptr;
639     napi_value argv[ARG_SIZE_TWO] = {nullptr};
640     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
641     if (argc != ARG_SIZE_TWO) {
642         ACCOUNT_LOGE("failed to parse parameters, expect three parameters, but got %{public}zu", argc);
643         std::string errMsg = "The arg number must be at least 2 characters";
644         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
645         return nullptr;
646     }
647     InputerContext *context = nullptr;
648     NAPI_CALL(env, napi_unwrap(env, thisVar, (void **)&context));
649     if (context == nullptr || context->inputerData == nullptr) {
650         ACCOUNT_LOGE("context or inputerData is nullptr");
651         return nullptr;
652     }
653     int32_t authSubType;
654     if (!GetIntProperty(env, argv[PARAM_ZERO], authSubType)) {
655         ACCOUNT_LOGE("Get authSubType failed");
656         std::string errMsg = "The type of arg 1 must be number";
657         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
658         return nullptr;
659     }
660     std::vector<uint8_t> data;
661     if (ParseUint8TypedArrayToVector(env, argv[PARAM_ONE], data) != napi_ok) {
662         ACCOUNT_LOGE("Get data failed");
663         std::string errMsg = "The type of arg 2 must be int array";
664         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
665         return nullptr;
666     }
667     context->inputerData->OnSetData(authSubType, data);
668     context->inputerData = nullptr;
669     return nullptr;
670 }
671 
GetCtorIInputerData(napi_env env,const std::shared_ptr<AccountSA::IInputerData> & inputerData)672 napi_value GetCtorIInputerData(napi_env env, const std::shared_ptr<AccountSA::IInputerData> &inputerData)
673 {
674     if (inputerData == nullptr) {
675         ACCOUNT_LOGE("inputerData nullptr");
676         return nullptr;
677     }
678     InputerContext *context = new (std::nothrow) InputerContext();
679     if (context == nullptr) {
680         ACCOUNT_LOGE("inputer context is nullptr");
681         return nullptr;
682     }
683     napi_property_descriptor clzDes[] = {
684         DECLARE_NAPI_FUNCTION("onSetData", OnSetData),
685     };
686     context->inputerData = inputerData;
687     napi_value cons;
688     NAPI_CALL(env, napi_define_class(env, "InputerData", NAPI_AUTO_LENGTH,
689         InputDataConstructor, reinterpret_cast<void *>(context),
690         sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons));
691     return cons;
692 }
693 
GetInputerInstance(InputerContext * context,napi_value * inputerDataVarCtor)694 static napi_status GetInputerInstance(InputerContext *context, napi_value *inputerDataVarCtor)
695 {
696     napi_value cons = GetCtorIInputerData(context->env, context->inputerData);
697     if (cons == nullptr) {
698         ACCOUNT_LOGD("failed to GetCtorIInputerData");
699         return napi_generic_failure;
700     }
701     return napi_new_instance(context->env, cons, 0, nullptr, inputerDataVarCtor);
702 }
703 
OnGetDataWork(uv_work_t * work,int status)704 static void OnGetDataWork(uv_work_t* work, int status)
705 {
706     std::unique_ptr<uv_work_t> workPtr(work);
707     napi_handle_scope scope = nullptr;
708     if (!InitUvWorkCallbackEnv(work, scope)) {
709         return;
710     }
711     std::unique_ptr<InputerContext> context(reinterpret_cast<InputerContext *>(work->data));
712     napi_value argv[ARG_SIZE_TWO] = {0};
713     NAPI_CALL_RETURN_VOID(context->env, napi_create_int32(context->env, context->authSubType, &argv[PARAM_ZERO]));
714     NAPI_CALL_RETURN_VOID(context->env, GetInputerInstance(context.get(), &argv[PARAM_ONE]));
715     NapiCallVoidFunction(context->env, argv, ARG_SIZE_TWO, context->callbackRef);
716     std::unique_lock<std::mutex> lock(context->lockInfo->mutex);
717     context->lockInfo->count--;
718     context->lockInfo->condition.notify_all();
719 }
720 
NapiGetDataCallback(napi_env env,napi_ref callback)721 NapiGetDataCallback::NapiGetDataCallback(napi_env env, napi_ref callback) : env_(env), callback_(callback)
722 {}
723 
~NapiGetDataCallback()724 NapiGetDataCallback::~NapiGetDataCallback()
725 {
726     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
727     lockInfo_.condition.wait(lock, [this] { return this->lockInfo_.count == 0; });
728     lockInfo_.count--;
729     ReleaseNapiRefAsync(env_, callback_);
730     callback_ = nullptr;
731 }
732 
OnGetData(int32_t authSubType,const std::shared_ptr<AccountSA::IInputerData> inputerData)733 void NapiGetDataCallback::OnGetData(int32_t authSubType, const std::shared_ptr<AccountSA::IInputerData> inputerData)
734 {
735     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
736     if (lockInfo_.count < 0) {
737         ACCOUNT_LOGE("the inputer has been released");
738         return;
739     }
740     if (callback_ == nullptr) {
741         ACCOUNT_LOGE("the onGetData function is undefined");
742         return;
743     }
744     std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
745     std::unique_ptr<InputerContext> context = std::make_unique<InputerContext>();
746     uv_loop_s *loop = nullptr;
747     napi_get_uv_event_loop(env_, &loop);
748     if (loop == nullptr || work == nullptr || context == nullptr) {
749         ACCOUNT_LOGE("fail for nullptr");
750         return;
751     }
752     context->env = env_;
753     context->callbackRef = callback_;
754     context->authSubType = authSubType;
755     context->inputerData = inputerData;
756     context->lockInfo = &lockInfo_;
757     work->data = reinterpret_cast<void *>(context.get());
758     int errCode = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, OnGetDataWork);
759     ACCOUNT_LOGI("create get data work finish");
760     if (errCode != 0) {
761         ACCOUNT_LOGE("failed to uv_queue_work, errCode: %{public}d", errCode);
762         return;
763     }
764     lockInfo_.count++;
765     work.release();
766     context.release();
767 }
768 #endif  // HAS_PIN_AUTH_PART
769 
CallbackAsyncOrPromise(napi_env env,CommonAsyncContext * context,napi_value errJs,napi_value dataJs)770 void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs)
771 {
772     if (context->callbackRef) {
773         napi_value argv[ARG_SIZE_TWO] = {errJs, dataJs};
774         NapiCallVoidFunction(env, argv, ARG_SIZE_TWO, context->callbackRef);
775         napi_delete_reference(env, context->callbackRef);
776         context->callbackRef = nullptr;
777     } else {
778         if (context->errCode == ERR_OK) {
779             napi_resolve_deferred(env, context->deferred, dataJs);
780         } else {
781             napi_reject_deferred(env, context->deferred, errJs);
782         }
783     }
784 }
785 
ParseUInt32Array(napi_env env,napi_value value,std::vector<uint32_t> & data)786 napi_status ParseUInt32Array(napi_env env, napi_value value, std::vector<uint32_t> &data)
787 {
788     data.clear();
789     bool isArray = false;
790     napi_is_array(env, value, &isArray);
791     if (!isArray) {
792         ACCOUNT_LOGE("value is not an array");
793         return napi_invalid_arg;
794     }
795     uint32_t arrLen = 0;
796     napi_get_array_length(env, value, &arrLen);
797     for (uint32_t i = 0; i < arrLen; ++i) {
798         napi_value item = nullptr;
799         napi_get_element(env, value, i, &item);
800         uint32_t num = 0;
801         if (napi_get_value_uint32(env, item, &num) != napi_ok) {
802             data.clear();
803             return napi_number_expected;
804         }
805         data.push_back(num);
806     }
807     return napi_ok;
808 }
809 
CreateErrorObject(napi_env env,int32_t code)810 napi_value CreateErrorObject(napi_env env, int32_t code)
811 {
812     napi_value errObj = nullptr;
813     NAPI_CALL(env, napi_create_object(env, &errObj));
814     napi_value number = 0;
815     NAPI_CALL(env, napi_create_int32(env, code, &number));
816     NAPI_CALL(env, napi_set_named_property(env, errObj, "code", number));
817     return errObj;
818 }
819 }  // namespace AccountJsKit
820 }  // namespace OHOS
821