!2265 【账号iam】napi层callbackRef生命周期管理问题修复

Merge pull request !2265 from lichenchen/master
This commit is contained in:
openharmony_ci 2024-11-16 08:53:56 +00:00 committed by Gitee
commit 169d9c6d43
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 105 additions and 64 deletions

View File

@ -56,6 +56,16 @@ struct JsIAMCallback {
bool hasOnAcquireInfo = false;
};
struct CommonCallbackInfo {
CommonCallbackInfo(napi_env env) : env(env) {}
napi_env env;
napi_ref callbackRef = nullptr;
napi_deferred deferred = nullptr;
napi_value errJs = nullptr;
napi_value dataJs = nullptr;
int32_t errCode;
};
#ifdef HAS_USER_AUTH_PART
struct IDMCallbackParam : public CommonAsyncContext {
explicit IDMCallbackParam(napi_env napiEnv) : CommonAsyncContext(napiEnv) {};
@ -136,6 +146,7 @@ struct GetAuthInfoContext : public CommonAsyncContext {
bool parseHasAccountId = false;
AccountSA::AuthType authType {0};
std::vector<AccountSA::CredentialInfo> credInfo;
std::shared_ptr<NapiCallbackRef> callback;
};
struct GetEnrolledIdContext : public CommonAsyncContext {
@ -158,6 +169,7 @@ struct GetPropertyContext : public CommonAsyncContext {
int32_t accountId = -1;
bool parseHasAccountId = false;
int32_t nextPhaseFreezingTime = -1;
std::shared_ptr<NapiCallbackRef> callback;
};
struct SetPropertyContext : public CommonAsyncContext {
@ -165,6 +177,7 @@ struct SetPropertyContext : public CommonAsyncContext {
AccountSA::SetPropertyRequest request;
int32_t result = 0;
int32_t accountId = -1;
std::shared_ptr<NapiCallbackRef> callback;
};
class NapiIDMCallback : public AccountSA::IDMCallback {
@ -187,10 +200,13 @@ public:
virtual ~NapiGetInfoCallback();
void OnCredentialInfo(int32_t result, const std::vector<AccountSA::CredentialInfo> &infoList) override;
private:
napi_env env_;
napi_ref callbackRef_;
std::shared_ptr<NapiCallbackRef> callback_;
napi_deferred deferred_;
std::mutex mutex_;
bool onResultCalled_ = false;
};
class NapiGetEnrolledIdCallback : public AccountSA::GetEnrolledIdCallback {
@ -228,12 +244,14 @@ public:
virtual ~NapiGetPropCallback();
void GetContextParams(const UserIam::UserAuth::Attributes &extraInfo, GetPropertyContext &context);
void OnResult(int32_t result, const AccountSA::Attributes &extraInfo) override;
private:
napi_env env_ = nullptr;
napi_ref callbackRef_ = nullptr;
std::shared_ptr<NapiCallbackRef> callback_;
napi_deferred deferred_ = nullptr;
AccountSA::GetPropertyRequest request_;
std::mutex mutex_;
bool onResultCalled_ = false;
};
class NapiSetPropCallback : public AccountSA::GetSetPropCallback {
@ -245,9 +263,10 @@ public:
private:
napi_env env_ = nullptr;
napi_ref callbackRef_ = nullptr;
std::shared_ptr<NapiCallbackRef> callback_;
napi_deferred deferred_ = nullptr;
std::mutex mutex_;
bool onResultCalled_ = false;
};
#endif // HAS_USER_AUTH_PART
@ -274,6 +293,7 @@ private:
};
#endif // HAS_PIN_AUTH_PART
void CallbackAsyncOrPromise(const CommonCallbackInfo &callbackInfo);
void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs);
napi_value CreateErrorObject(napi_env env, int32_t code);
napi_status ParseUInt32Array(napi_env env, napi_value value, std::vector<uint32_t> &data);

View File

@ -557,30 +557,31 @@ void NapiUserAuthCallback::OnAcquireInfo(int32_t module, uint32_t acquireInfo, c
}
NapiGetInfoCallback::NapiGetInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
: env_(env), callbackRef_(callbackRef), deferred_(deferred)
{}
: env_(env), deferred_(deferred)
{
callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
}
NapiGetInfoCallback::~NapiGetInfoCallback()
{
if (callbackRef_ != nullptr) {
ReleaseNapiRefAsync(env_, callbackRef_);
callbackRef_ = nullptr;
}
deferred_ = nullptr;
}
{}
void NapiGetInfoCallback::OnCredentialInfo(int32_t result, const std::vector<AccountSA::CredentialInfo> &infoList)
{
std::lock_guard<std::mutex> lock(mutex_);
if (onResultCalled_) {
ACCOUNT_LOGE("Call twice is not allowed");
return;
}
onResultCalled_ = true;
std::shared_ptr<GetAuthInfoContext> context = std::make_shared<GetAuthInfoContext>(env_);
if (context == nullptr) {
ACCOUNT_LOGE("Failed for nullptr");
return;
}
context->callbackRef = callbackRef_;
context->callback = callback_;
context->deferred = deferred_;
context->errCode = result;
context->credInfo = infoList;
callbackRef_ = nullptr;
auto task = [context = std::move(context)]() {
ACCOUNT_LOGI("Enter NapiGetInfoCallback::OnCredentialInfo task");
napi_handle_scope scope = nullptr;
@ -590,17 +591,19 @@ void NapiGetInfoCallback::OnCredentialInfo(int32_t result, const std::vector<Acc
return;
}
napi_env env = context->env;
napi_value errJs = nullptr;
napi_value dataJs = nullptr;
CommonCallbackInfo callbackInfo(env);
callbackInfo.callbackRef = context->callback->callbackRef;
callbackInfo.deferred = context->deferred;
callbackInfo.errCode = context->errCode;
if (context->errCode != ERR_OK) {
int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->errCode);
errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
napi_get_null(env, &dataJs);
callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
napi_get_null(env, &callbackInfo.dataJs);
} else {
napi_get_null(env, &errJs);
dataJs = CreateCredInfoArray(env, context->credInfo);
napi_get_null(env, &callbackInfo.errJs);
callbackInfo.dataJs = CreateCredInfoArray(env, context->credInfo);
}
CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
CallbackAsyncOrPromise(callbackInfo);
napi_close_handle_scope(context->env, scope);
return;
};
@ -660,17 +663,13 @@ void NapiGetEnrolledIdCallback::OnEnrolledId(int32_t result, uint64_t enrolledId
NapiGetPropCallback::NapiGetPropCallback(
napi_env env, napi_ref callbackRef, napi_deferred deferred, const AccountSA::GetPropertyRequest &request)
: env_(env), callbackRef_(callbackRef), deferred_(deferred), request_(request)
{}
: env_(env), deferred_(deferred), request_(request)
{
callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
}
NapiGetPropCallback::~NapiGetPropCallback()
{
if (callbackRef_ != nullptr) {
ReleaseNapiRefAsync(env_, callbackRef_);
callbackRef_ = nullptr;
}
deferred_ = nullptr;
}
{}
void NapiGetPropCallback::GetContextParams(
const UserIam::UserAuth::Attributes &extraInfo, GetPropertyContext &context)
@ -726,9 +725,14 @@ void NapiGetPropCallback::GetContextParams(
void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
{
std::lock_guard<std::mutex> lock(mutex_);
if ((callbackRef_ == nullptr) && (deferred_ == nullptr)) {
if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
return;
}
if (onResultCalled_) {
ACCOUNT_LOGE("Call twice is not allowed");
return;
}
onResultCalled_ = true;
std::shared_ptr<GetPropertyContext> context = std::make_shared<GetPropertyContext>(env_);
if (context == nullptr) {
ACCOUNT_LOGE("Failed for nullptr");
@ -736,12 +740,11 @@ void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attr
}
// create context data
GetContextParams(extraInfo, *context);
context->callbackRef = callbackRef_;
context->callback = callback_;
context->deferred = deferred_;
context->errCode = ERR_OK;
context->result = result;
context->request = request_;
callbackRef_ = nullptr;
auto task = [context = std::move(context)]() {
ACCOUNT_LOGI("Enter NapiGetPropCallback::OnResult task");
napi_handle_scope scope = nullptr;
@ -750,10 +753,12 @@ void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attr
ACCOUNT_LOGE("Failed to open scope");
return;
}
napi_value errJs = nullptr;
napi_value dataJs = nullptr;
CreateExecutorProperty(context->env, *context, errJs, dataJs);
CallbackAsyncOrPromise(context->env, context.get(), errJs, dataJs);
CommonCallbackInfo callbackInfo(context->env);
callbackInfo.callbackRef = context->callback->callbackRef;
callbackInfo.deferred = context->deferred;
CreateExecutorProperty(context->env, *context, callbackInfo.errJs, callbackInfo.dataJs);
callbackInfo.errCode = context->errCode;
CallbackAsyncOrPromise(callbackInfo);
napi_close_handle_scope(context->env, scope);
return;
};
@ -765,17 +770,13 @@ void NapiGetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attr
}
NapiSetPropCallback::NapiSetPropCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
: env_(env), callbackRef_(callbackRef), deferred_(deferred)
{}
: env_(env), deferred_(deferred)
{
callback_ = std::make_shared<NapiCallbackRef>(env, callbackRef);
}
NapiSetPropCallback::~NapiSetPropCallback()
{
if (callbackRef_ != nullptr) {
ReleaseNapiRefAsync(env_, callbackRef_);
callbackRef_ = nullptr;
}
deferred_ = nullptr;
}
{}
NapiPrepareRemoteAuthCallback::NapiPrepareRemoteAuthCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
: env_(env), callbackRef_(callbackRef), deferred_(deferred)
@ -838,19 +839,23 @@ void NapiPrepareRemoteAuthCallback::OnResult(int32_t result)
void NapiSetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attributes &extraInfo)
{
std::lock_guard<std::mutex> lock(mutex_);
if ((callbackRef_ == nullptr) && (deferred_ == nullptr)) {
if ((callback_->callbackRef == nullptr) && (deferred_ == nullptr)) {
return;
}
if (onResultCalled_) {
ACCOUNT_LOGE("Call twice is not allowed");
return;
}
onResultCalled_ = true;
std::shared_ptr<SetPropertyContext> context = std::make_shared<SetPropertyContext>(env_);
if (context == nullptr) {
ACCOUNT_LOGE("Failed for nullptr");
return;
}
context->callbackRef = callbackRef_;
context->callback = callback_;
context->deferred = deferred_;
context->errCode = ERR_OK;
context->result = result;
callbackRef_ = nullptr;
auto task = [context = std::move(context)]() {
ACCOUNT_LOGI("Enter NapiSetPropCallback::OnResult task");
napi_handle_scope scope = nullptr;
@ -860,18 +865,19 @@ void NapiSetPropCallback::OnResult(int32_t result, const UserIam::UserAuth::Attr
return;
}
napi_env env = context->env;
napi_value errJs = nullptr;
napi_value dataJs = nullptr;
context->errCode = context->result;
CommonCallbackInfo callbackInfo(env);
callbackInfo.callbackRef = context->callback->callbackRef;
callbackInfo.deferred = context->deferred;
callbackInfo.errCode = context->result;
if (context->result != ERR_OK) {
int32_t jsErrCode = AccountIAMConvertToJSErrCode(context->result);
errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
napi_get_null(env, &dataJs);
callbackInfo.errJs = GenerateBusinessError(env, jsErrCode, ConvertToJsErrMsg(jsErrCode));
napi_get_null(env, &callbackInfo.dataJs);
} else {
napi_get_null(env, &errJs);
napi_get_null(env, &dataJs);
napi_get_null(env, &callbackInfo.errJs);
napi_get_null(env, &callbackInfo.dataJs);
}
CallbackAsyncOrPromise(env, context.get(), errJs, dataJs);
CallbackAsyncOrPromise(callbackInfo);
napi_close_handle_scope(env, scope);
return;
};
@ -1038,21 +1044,32 @@ void NapiGetDataCallback::OnGetData(int32_t authSubType, std::vector<uint8_t> ch
}
#endif // HAS_PIN_AUTH_PART
void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs)
void CallbackAsyncOrPromise(const CommonCallbackInfo &callbackInfo)
{
if (context->callbackRef) {
napi_value argv[ARG_SIZE_TWO] = {errJs, dataJs};
if (callbackInfo.callbackRef) {
napi_value argv[ARG_SIZE_TWO] = {callbackInfo.errJs, callbackInfo.dataJs};
ACCOUNT_LOGI("call js function");
NapiCallVoidFunction(env, argv, ARG_SIZE_TWO, context->callbackRef);
NapiCallVoidFunction(callbackInfo.env, argv, ARG_SIZE_TWO, callbackInfo.callbackRef);
} else {
if (context->errCode == ERR_OK) {
napi_resolve_deferred(env, context->deferred, dataJs);
if (callbackInfo.errCode == ERR_OK) {
napi_resolve_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.dataJs);
} else {
napi_reject_deferred(env, context->deferred, errJs);
napi_reject_deferred(callbackInfo.env, callbackInfo.deferred, callbackInfo.errJs);
}
}
}
void CallbackAsyncOrPromise(napi_env env, CommonAsyncContext *context, napi_value errJs, napi_value dataJs)
{
CommonCallbackInfo callbackInfo(env);
callbackInfo.callbackRef = context->callbackRef;
callbackInfo.deferred = context->deferred;
callbackInfo.errJs = errJs;
callbackInfo.dataJs = dataJs;
callbackInfo.errCode = context->errCode;
CallbackAsyncOrPromise(callbackInfo);
}
napi_status ParseUInt32Array(napi_env env, napi_value value, std::vector<uint32_t> &data)
{
data.clear();

View File

@ -546,7 +546,11 @@ void ReleaseNapiRefArray(napi_env env, const std::vector<napi_ref> &napiRefVec)
NapiCallbackRef::~NapiCallbackRef()
{
if (callbackRef == nullptr) {
return;
}
ReleaseNapiRefArray(env, {callbackRef});
callbackRef = nullptr;
}
bool InitUvWorkCallbackEnv(uv_work_t *work, napi_handle_scope &scope)