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 *>(¶m->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 *>(¶m->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