From 97621eaa3e74ef7a67862ca3485841439d89fcf1 Mon Sep 17 00:00:00 2001 From: chennian Date: Mon, 2 Jun 2025 16:19:38 +0800 Subject: [PATCH] Modify js error message Signed-off-by: chennian Change-Id: I45b5264a955a12a3d426eb8091b08850fd9b8b61 --- .../ets/@ohos.abilityAccessCtrl.ets | 199 +++++++----------- .../accesstoken/include/ability_access_ctrl.h | 20 +- .../accesstoken/src/ability_access_ctrl.cpp | 190 ++++++++--------- frameworks/ets/ani/common/include/ani_error.h | 12 +- frameworks/ets/ani/common/src/ani_error.cpp | 81 +------ .../ani/privacy/ets/@ohos.privacyManager.ets | 11 +- 6 files changed, 189 insertions(+), 324 deletions(-) diff --git a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets index 575731294..1e48fc2a9 100644 --- a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -31,69 +31,46 @@ export default namespace abilityAccessCtrl { loadLibrary("accesstoken_ani.z"); export enum GrantStatus { - PERMISSION_DENIED = -1, - PERMISSION_GRANTED = 0 } export enum PermissionRequestToggleStatus { - CLOSED = 0, - OPEN = 1, } export enum PermissionStatus { - DENIED = -1, - GRANTED = 0, - NOT_DETERMINED = 1, - INVALID = 2, - RESTRICTED = 3 } interface PermissionStateChangeInfo { - change: PermissionStateChangeType; - tokenID: int; - permissionName: Permissions; } export enum PermissionStateChangeType { - PERMISSION_REVOKED_OPER = 0, - PERMISSION_GRANTED_OPER = 1 } export enum SwitchType { - CAMERA = 0, - MICROPHONE = 1, - LOCATION = 2, } enum STSErrorCode { - STS_OK = 0, - STS_ERROR_PERMISSION_DENIED = 201, - STS_ERROR_NOT_SYSTEM_APP = 202, - STS_ERROR_PARAM_ILLEGAL = 401, - STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT = 801, - } ; function validateRequestParams(context: Context, permissionList: Array): void { if (typeof context === "undefined" || context == null) { @@ -111,102 +88,69 @@ export default namespace abilityAccessCtrl { } } - function validateTokenAndPermission(tokenID: int, permissionName: Permissions): void { - if (typeof permissionName !== "string") { - let err = new BusinessError(); - err.code = STSErrorCode.STS_ERROR_PARAM_ILLEGAL; - err.data = PARAM_ERROR_MSG("permissionName", "Permissions"); - throw err; - } - } native function createAtManager(): AtManager; - interface AtManager { - checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; - checkAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus; - checkAccessToken(tokenID: int, permissionName: Permissions): Promise + checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; + requestPermissionsFromUserExecute( + context: Context, permissionList: Array): PermissionRequestResult; + requestPermissionOnSettingExecute(context: Context, permissionList: Array): Array; + revokeUserGrantedPermissionExecute(tokenID: int, permissionName: Permissions, permissionFlags: int): void; + getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; + getVersionExecute(): int; + checkAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus; verifyAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus; - - requestPermissionsFromUserExecute( - context: Context, - permissionList: Array):PermissionRequestResult; + checkAccessToken(tokenID: int, permissionName: Permissions): Promise; + verifyAccessToken(tokenID: int, permissionName: Permissions): Promise; requestPermissionsFromUser( - context: Context, - permissionList: Array, - requestCallback: AsyncCallback - ): void; + context: Context, permissionList: Array, + requestCallback: AsyncCallback): void; requestPermissionsFromUser( - context: Context, - permissionList: Array): Promise; - - requestPermissionOnSettingExecute( - context: Context, - permissionList: Array): Array; + context: Context, permissionList: Array): Promise; requestPermissionOnSetting( context: Context, permissionList: Array): Promise>; - - revokeUserGrantedPermissionExecute( - tokenID: int, - permissionName: Permissions, - permissionFlags: int, - ): void; - revokeUserGrantedPermission( - tokenID: int, - permissionName: Permissions, - permissionFlags: int, - ): Promise; + revokeUserGrantedPermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise; revokeUserGrantedPermission( - tokenID: int, - permissionName: Permissions, - permissionFlags: int, - callback: AsyncCallback - ): void; - - getVersionExecute(): int; + tokenID: int, permissionName: Permissions, permissionFlags: int, callback: AsyncCallback): void; getVersion(): Promise; - getPermissionsStatusExecute( - tokenID: int, permissionList: Array): Array; - - getPermissionsStatus( - tokenID: int, permissionList: Array): Promise>; + getPermissionsStatus(tokenID: int, permissionList: Array): Promise>; } class AtManagerInner implements AtManager { - native checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; + native checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; + native requestPermissionsFromUserExecute( + context: Context, permissionList: Array): PermissionRequestResult; + native requestPermissionOnSettingExecute( + context: Context, permissionList: Array): Array; + native revokeUserGrantedPermissionExecute( + tokenID: int, permissionName: Permissions, permissionFlags: int): void; + native getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; + native getVersionExecute(): int; verifyAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus { - validateTokenAndPermission(tokenID, permissionName); - let result = this.checkAccessTokenANI(tokenID, permissionName); - if (result == 0) { - return GrantStatus.PERMISSION_GRANTED - } - return GrantStatus.PERMISSION_DENIED + let result = this.checkAccessTokenExecute(tokenID, permissionName); + return result as GrantStatus; } checkAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus { - validateTokenAndPermission(tokenID, permissionName); - let result = this.checkAccessTokenANI(tokenID, permissionName); - if (result == 0) { - return GrantStatus.PERMISSION_GRANTED - } - return GrantStatus.PERMISSION_DENIED + let result = this.checkAccessTokenExecute(tokenID, permissionName); + return result as GrantStatus; } checkAccessToken(tokenID: int, permissionName: Permissions): Promise { - validateTokenAndPermission(tokenID, permissionName); - let p = new Promise((resolve: (v: GrantStatus) - => void, reject: (error: BusinessError) => void) => { - let p1 = taskpool.execute((): GrantStatus => { return new AtManagerInner().checkAccessTokenANI(tokenID, - permissionName) as GrantStatus;}); + let p = new Promise(( + resolve: (v: GrantStatus) => void, reject: (error: BusinessError) => void) => { + let p1 = taskpool.execute((): GrantStatus => { + return new AtManagerInner().checkAccessTokenExecute(tokenID, permissionName) as GrantStatus; + }); p1.then((e: NullishType) => { resolve(e as GrantStatus); }).catch((err: BusinessError): void => { @@ -216,22 +160,36 @@ export default namespace abilityAccessCtrl { return p; } - native requestPermissionsFromUserExecute(context: Context, - permissionList: Array): PermissionRequestResult; + verifyAccessToken(tokenID: int, permissionName: Permissions): Promise { + let p = new Promise(( + resolve: (v: GrantStatus) => void, reject: (error: BusinessError) => void) => { + let p1 = taskpool.execute((): GrantStatus => { + return new AtManagerInner().checkAccessTokenExecute(tokenID, permissionName) as GrantStatus; + }); + p1.then((e: NullishType) => { + resolve(e as GrantStatus); + }).catch((err: BusinessError): void => { + resolve(GrantStatus.PERMISSION_DENIED); + }); + }); + return p; + } requestPermissionsFromUser(context: Context, permissionList: Array, callback:AsyncCallback): void { validateRequestParams(context, permissionList); let fun = async() => { + let work = new EAWorker(); try { - let work = new EAWorker(); let job = work.run(() : PermissionRequestResult => { return new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList); }) let result = job.Await(); + work.join(); let retError = new BusinessError(); callback(retError, result as PermissionRequestResult); } catch (err: BusinessError) { + work.join(); const defaultResult: PermissionRequestResult = {}; callback(err, defaultResult); } @@ -243,17 +201,19 @@ export default namespace abilityAccessCtrl { Promise { validateRequestParams(context, permissionList); - let p = new Promise((resolve: (v: PermissionRequestResult) => - void, reject: (error: BusinessError) => void) => { + let p = new Promise(( + resolve: (v: PermissionRequestResult) => void, reject: (error: BusinessError) => void) => { let fun = async() => { + let work = new EAWorker(); try { - let work = new EAWorker(); let job = work.run((): PermissionRequestResult => { return new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList); }); let result = job.Await(); + work.join(); resolve(result as PermissionRequestResult); } catch (err: BusinessError) { + work.join(); reject(err); } }; @@ -262,24 +222,21 @@ export default namespace abilityAccessCtrl { return p; } - native requestPermissionOnSettingExecute( - context: Context, - permissionList: Array): Array; - - requestPermissionOnSetting(context: Context, permissionList: Array): - Promise> { + requestPermissionOnSetting(context: Context, permissionList: Array): Promise> { validateRequestParams(context, permissionList); - let p = new Promise>((resolve: (v: Array) => - void, reject: (error: BusinessError) => void) => { + let p = new Promise>(( + resolve: (v: Array) => void, reject: (error: BusinessError) => void) => { let func = async() => { + let work = new EAWorker(); try { - let work = new EAWorker(); let job = work.run>((): Array => { return new AtManagerInner().requestPermissionOnSettingExecute(context, permissionList); }); let result = job.Await(); + work.join(); resolve(result as Array); } catch (err: BusinessError) { + work.join(); reject(err); } }; @@ -287,9 +244,6 @@ export default namespace abilityAccessCtrl { }); return p; } - - native revokeUserGrantedPermissionExecute(tokenID: int, permissionName: Permissions, - permissionFlags: int): void; revokeUserGrantedPermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise { return new Promise( @@ -315,15 +269,15 @@ export default namespace abilityAccessCtrl { callback(err, undefined); }, (err: BusinessError): void=> { callback(err, undefined); - }) + }) } - native getVersionExecute(): int; - - getVersion(): Promise{ - let p = new Promise((resolve: (v: int)=> void, reject: (error: BusinessError) - => void) =>{ - let p1 = taskpool.execute((): int => { return new AtManagerInner().getVersionExecute() as int;}); + getVersion(): Promise { + let p = new Promise(( + resolve: (v: int) => void, reject: (error: BusinessError) => void) =>{ + let p1 = taskpool.execute((): int => { + return new AtManagerInner().getVersionExecute() as int; + }); p1.then((e: NullishType) => { resolve(e as int); }).catch((err: BusinessError): void => { @@ -333,15 +287,14 @@ export default namespace abilityAccessCtrl { return p; } - native getPermissionsStatusExecute( - tokenID: int, permissionList: Array): Array; - getPermissionsStatus( tokenID: int, permissionList: Array): Promise> { - let p = new Promise>((resolve: (v: Array) - => void, reject: (error: BusinessError) => void) => { - let p1 = taskpool.execute((): Array => { return new AtManagerInner().getPermissionsStatusExecute(tokenID, - permissionList) as Array;}); + let p = new Promise>(( + resolve: (v: Array) => void, reject: (error: BusinessError) => void) => { + let p1 = taskpool.execute((): Array => { + return new AtManagerInner().getPermissionsStatusExecute( + tokenID, permissionList) as Array; + }); p1.then((e: NullishType) => { resolve(e as Array); }).catch((err: BusinessError): void => { @@ -350,5 +303,5 @@ export default namespace abilityAccessCtrl { }); return p; } - } + } } \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h b/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h index a59e24264..e3ac10ad3 100644 --- a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h +++ b/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h @@ -25,6 +25,7 @@ #include "ability_manager_client.h" #include "access_token.h" #include "ani.h" +#include "ani_error.h" #include "permission_grant_info.h" #include "token_callback_stub.h" #include "ui_content.h" @@ -33,16 +34,7 @@ namespace OHOS { namespace Security { namespace AccessToken { -std::condition_variable g_loadedCond; -std::mutex g_lockCache; -typedef unsigned int AccessTokenID; -static std::atomic g_cnt = 0; -constexpr uint32_t REPORT_CNT = 10; -constexpr uint32_t VERIFY_TOKENID_INCONSISTENCY = 0; const int32_t PARAM_DEFAULT_VALUE = -1; - -static constexpr const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change"; - struct AtManagerAsyncContext { AccessTokenID tokenId = 0; std::string permissionName; @@ -50,8 +42,8 @@ struct AtManagerAsyncContext { uint32_t flag = 0; uint32_t status; }; - int32_t result = RET_FAILED; - int32_t errorCode = 0; + int32_t grantStatus = PERMISSION_DENIED; + AtmResult result; }; class AniContextCommon { @@ -84,7 +76,7 @@ struct RequestAsyncContext { AccessTokenID tokenId = 0; std::string bundleName; bool needDynamicRequest = true; - int32_t result = RET_SUCCESS; + AtmResult result; int32_t instanceId = -1; std::vector permissionList; std::vector grantResults; @@ -157,13 +149,11 @@ struct ResultCallback { struct RequestPermOnSettingAsyncContext { AccessTokenID tokenId = 0; - int32_t result = RET_SUCCESS; + AtmResult result; PermissionGrantInfo info; - int32_t resultCode = -1; std::vector permissionList; napi_value requestResult = nullptr; - int32_t errorCode = -1; std::vector stateList; std::shared_ptr abilityContext; diff --git a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp index 53c129ad1..0dcb952f1 100644 --- a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp +++ b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp @@ -45,6 +45,10 @@ const int32_t PERM_NOT_BELONG_TO_SAME_GROUP = 2; const int32_t PERM_IS_NOT_DECLARE = 3; const int32_t ALL_PERM_GRANTED = 4; const int32_t PERM_REVOKE_BY_USER = 5; +std::condition_variable g_loadedCond; +std::mutex g_lockCache; + +static constexpr const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change"; const std::string PERMISSION_KEY = "ohos.user.grant.permission"; const std::string PERMISSION_SETTING_KEY = "ohos.user.setting.permission"; @@ -72,7 +76,7 @@ static void UpdateGrantPermissionResultOnly(const std::vector& perm for (size_t i = 0; i < size; i++) { int result = static_cast(data->permissionsState[i]); if (data->permissionsState[i] == AccessToken::DYNAMIC_OPER) { - result = data->result == AccessToken::RET_SUCCESS ? grantResults[i] : AccessToken::INVALID_OPER; + result = data->result.errorCode == AccessToken::RET_SUCCESS ? grantResults[i] : AccessToken::INVALID_OPER; } newGrantResults.emplace_back(result); } @@ -146,7 +150,7 @@ static void CreateUIExtensionMainThread(std::shared_ptr& as asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); - asyncContext->result = AccessToken::RET_FAILED; + asyncContext->result.errorCode = AccessToken::RET_FAILED; asyncContext->uiExtensionFlag = false; asyncContext->loadlock.unlock(); return; @@ -157,7 +161,7 @@ static void CreateUIExtensionMainThread(std::shared_ptr& as int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); if (sessionId == 0) { ACCESSTOKEN_LOG_ERROR(LABEL, "Create component failed, sessionId is 0"); - asyncContext->result = AccessToken::RET_FAILED; + asyncContext->result.errorCode = AccessToken::RET_FAILED; asyncContext->uiExtensionFlag = false; asyncContext->loadlock.unlock(); return; @@ -180,14 +184,14 @@ static bool CreateServiceExtension(std::shared_ptr& asyncCo if (!asyncContext->uiAbilityFlag) { ACCESSTOKEN_LOG_ERROR(LABEL, "UIExtension ability can not pop service ablility window!"); asyncContext->needDynamicRequest = false; - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return false; } OHOS::sptr remoteObject = new (std::nothrow) AuthorizationResult(asyncContext); if (remoteObject == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Create window failed!"); asyncContext->needDynamicRequest = false; - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return false; } OHOS::AAFwk::Want want; @@ -426,14 +430,14 @@ static ani_object WrapResult(ani_env* env, std::shared_ptr& ani_ref intPermissionQueryResults = ConvertAniArrayInt(env, asyncContext->permissionQueryResults); if (strPermissions == nullptr || intAuthResults == nullptr || boolDialogShownResults == nullptr || intPermissionQueryResults == nullptr) { - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return nullptr; } if (!CallSetter(env, cls, aObject, SETTER_METHOD_NAME(permissions), strPermissions) || !CallSetter(env, cls, aObject, SETTER_METHOD_NAME(authResults), intAuthResults) || !CallSetter(env, cls, aObject, SETTER_METHOD_NAME(dialogShownResults), boolDialogShownResults) || !CallSetter(env, cls, aObject, SETTER_METHOD_NAME(errorReasons), intPermissionQueryResults)) { - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return nullptr; } return aObject; @@ -442,12 +446,12 @@ static ani_object WrapResult(ani_env* env, std::shared_ptr& static ani_object DealWithResult(ani_env* env, std::shared_ptr& asyncContext) { ani_object resultObj = nullptr; - if (asyncContext->result == RET_SUCCESS) { + if (asyncContext->result.errorCode == RET_SUCCESS) { resultObj = WrapResult(env, asyncContext); } - if (asyncContext->result != RET_SUCCESS) { - int32_t stsCode = BusinessErrorAni::GetStsErrorCode(asyncContext->result); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + if (asyncContext->result.errorCode != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(asyncContext->result.errorCode); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode, asyncContext->result.errorMsg)); return nullptr; } return resultObj; @@ -456,16 +460,15 @@ static ani_object DealWithResult(ani_env* env, std::shared_ptr& permissionList, const std::vector& permissionStates, std::shared_ptr& data) { - int32_t result; - if (data->result != RET_SUCCESS) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Result is: %{public}d", data->result); - result = RET_FAILED; + if (data->result.errorCode != RET_SUCCESS) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Result is: %{public}d", data->result.errorCode); + data->result.errorCode = RET_FAILED; } std::vector newGrantResults; UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults); if (newGrantResults.empty()) { ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty"); - result = RET_FAILED; + data->result.errorCode = RET_FAILED; } data->grantResults.assign(newGrantResults.begin(), newGrantResults.end()); data->loadlock.unlock(); @@ -513,12 +516,12 @@ static bool ParseRequestPermissionFromUser(ani_env* env, ani_object aniContext, std::shared_ptr& asyncContext) { if (ConvertContext(env, aniContext, asyncContext) != ANI_OK) { - BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("context", "UIAbility or UIExtension Context")); return false; } if (!ProcessArrayString(env, nullptr, permissionList, asyncContext->permissionList)) { - BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("permissionList", "Array")); return false; } @@ -531,9 +534,9 @@ static bool RequestPermissionsFromUserProcess([[maybe_unused]] ani_env* env, if (!IsDynamicRequest(asyncContext)) { ACCESSTOKEN_LOG_ERROR(LABEL, "It does not need to request permission"); asyncContext->needDynamicRequest = false; - if ((asyncContext->permissionsState.empty()) && (asyncContext->result == STSErrorCode::STS_OK)) { + if ((asyncContext->permissionsState.empty()) && (asyncContext->result.errorCode == RET_SUCCESS)) { ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty"); - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; } return false; } @@ -586,15 +589,16 @@ static ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* en #ifdef EVENTHANDLER_ENABLE asyncContext->handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); #endif - bool errTokenID = true; static AccessTokenID selfTokenID = static_cast(GetSelfTokenID()); if (selfTokenID != asyncContext->tokenId) { ACCESSTOKEN_LOG_ERROR( LABEL, "The context tokenID: %{public}d, selfTokenID: %{public}d.", asyncContext->tokenId, selfTokenID); - asyncContext->result = RET_FAILED; - errTokenID = false; + std::string errMsg = GetErrorMessage( + STS_ERROR_INNER, "The specified context does not belong to the current application."); + BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, errMsg); + return nullptr; } - if (!RequestPermissionsFromUserProcess(env, asyncContext) || !errTokenID) { + if (!RequestPermissionsFromUserProcess(env, asyncContext)) { return DealWithResult(env, asyncContext); } ACCESSTOKEN_LOG_INFO(LABEL, "uiExtensionFlag: %{public}d, uiContentFlag: %{public}d, uiAbilityFlag: %{public}d ", @@ -612,7 +616,7 @@ static void CloseModalUIExtensionMainThread(std::shared_ptr asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return; } uiContent->CloseModalUIExtension(sessionId); @@ -719,7 +723,7 @@ void UIExtensionCallback::ReleaseHandler(int32_t code) this->reqContext_->releaseFlag = true; } CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_); - this->reqContext_->result = code; + this->reqContext_->result.errorCode = code; RequestAsyncInstanceControl::ExecCallback(this->reqContext_->instanceId); RequestResultsHandler(this->reqContext_->permissionList, this->reqContext_->permissionsState, this->reqContext_); } @@ -853,18 +857,18 @@ static void UpdatePermissionCache(AtManagerAsyncContext* asyncContext) if (iter != g_cache.end()) { std::string currPara = GetPermParamValue(); if (currPara != iter->second.paramValue) { - asyncContext->result = + asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); - iter->second.status = asyncContext->result; + iter->second.status = asyncContext->grantStatus; iter->second.paramValue = currPara; ACCESSTOKEN_LOG_DEBUG(LABEL, "Param changed currPara %{public}s", currPara.c_str()); } else { - asyncContext->result = iter->second.status; + asyncContext->grantStatus = iter->second.status; } } else { - asyncContext->result = + asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); - g_cache[asyncContext->permissionName].status = asyncContext->result; + g_cache[asyncContext->permissionName].status = asyncContext->grantStatus; g_cache[asyncContext->permissionName].paramValue = GetPermParamValue(); ACCESSTOKEN_LOG_DEBUG( LABEL, "G_cacheParam set %{public}s", g_cache[asyncContext->permissionName].paramValue.c_str()); @@ -879,14 +883,15 @@ static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env* env, [[maybe_unuse return AccessToken::PermissionState::PERMISSION_DENIED; } if (tokenID == 0) { - BusinessErrorAni::ThrowError( - env, STSErrorCode::STS_ERROR_PARAM_INVALID, GetErrorMessage(STSErrorCode::STS_ERROR_PARAM_INVALID)); + std::string errMsg = GetErrorMessage(STS_ERROR_PARAM_INVALID, "The tokenID is 0."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); return AccessToken::PermissionState::PERMISSION_DENIED; } std::string stdPermissionName = ANIUtils_ANIStringToStdString(env, static_cast(permissionName)); if (stdPermissionName.empty() || stdPermissionName.length() > MAX_LENGTH) { - BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_PARAM_INVALID, - GetParamErrorMsg("permissionName", "Permissions")); + std::string errMsg = GetErrorMessage( + STS_ERROR_PARAM_INVALID, "The permissionName is empty or exceeds 256 characters."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); return AccessToken::PermissionState::PERMISSION_DENIED; } auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(); @@ -899,12 +904,12 @@ static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env* env, [[maybe_unuse asyncContext->permissionName = stdPermissionName; static uint64_t selfTokenId = GetSelfTokenID(); if (asyncContext->tokenId != static_cast(selfTokenId)) { - asyncContext->result = AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, stdPermissionName); - return static_cast(asyncContext->result); + asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, stdPermissionName); + return static_cast(asyncContext->grantStatus); } UpdatePermissionCache(asyncContext); - ACCESSTOKEN_LOG_INFO(LABEL, "CheckAccessTokenSync result : %{public}d", asyncContext->result); - return static_cast(asyncContext->result); + ACCESSTOKEN_LOG_INFO(LABEL, "CheckAccessTokenSync result : %{public}d", asyncContext->grantStatus); + return static_cast(asyncContext->grantStatus); } static ani_status GetContext( @@ -946,25 +951,18 @@ static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext std::shared_ptr& asyncContext) { if (GetContext(env, aniContext, asyncContext) != ANI_OK) { - BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("context", "UIAbility or UIExtension Context")); return false; } if (!ProcessArrayString(env, nullptr, permissionList, asyncContext->permissionList)) { - BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("permissionList", "Array")); return false; } return true; } -static void ThrowError(ani_env* env, int32_t errCode) -{ - int32_t stsCode = BusinessErrorAni::GetStsErrorCode(errCode); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); -} - - static void StateToEnumIndex(int32_t state, ani_size& enumIndex) { if (state == 0) { @@ -1021,48 +1019,48 @@ static ani_ref ReturnResult(ani_env* env, std::shared_ptr& asyncContext) { - if (asyncContext->result == RET_SUCCESS) { + if (asyncContext->result.errorCode == RET_SUCCESS) { ani_ref result = ReturnResult(env, asyncContext); if (result != nullptr) { return result; } - asyncContext->errorCode = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; } - int32_t stsCode = TransferToStsErrorCode(asyncContext->errorCode); + int32_t stsCode = TransferToStsErrorCode(asyncContext->result.errorCode); BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); return nullptr; } @@ -1090,7 +1088,7 @@ static void CloseSettingModalUIExtensionMainThread(std::shared_ptruiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return; } uiContent->CloseModalUIExtension(sessionId); @@ -1119,11 +1117,7 @@ void PermissonOnSettingUICallback::ReleaseHandler(int32_t code) } CloseSettingModalUIExtensionMainThread(this->reqContext_, this->sessionId_); if (code == -1) { - this->reqContext_->errorCode = code; - } - int32_t stsCode = TransferToStsErrorCode(this->reqContext_->errorCode); - if (stsCode != STSErrorCode::STS_OK) { - this->reqContext_->result = RET_FAILED; + this->reqContext_->result.errorCode = code; } this->reqContext_->loadlock.unlock(); std::lock_guard lock(g_lockWindowFlag); @@ -1135,10 +1129,10 @@ void PermissonOnSettingUICallback::ReleaseHandler(int32_t code) */ void PermissonOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result) { - this->reqContext_->errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); + this->reqContext_->result.errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); this->reqContext_->stateList = result.GetIntArrayParam(PERMISSION_RESULT_KEY); - ACCESSTOKEN_LOG_INFO(LABEL, "ResultCode is %{public}d, errorCode=%{public}d, listSize=%{public}zu.", - resultCode, this->reqContext_->errorCode, this->reqContext_->stateList.size()); + ACCESSTOKEN_LOG_INFO(LABEL, "ResultCode is %{public}d, listSize=%{public}zu.", + resultCode, this->reqContext_->stateList.size()); ReleaseHandler(0); } @@ -1199,7 +1193,7 @@ static void CreateSettingUIExtensionMainThread(std::shared_ptruiExtensionContext, asyncContext->uiAbilityFlag); if (uiContent == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to get ui content!"); - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return; } @@ -1210,7 +1204,7 @@ static void CreateSettingUIExtensionMainThread(std::shared_ptrtokenId); if (sessionId == 0) { ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create component, sessionId is 0."); - asyncContext->result = RET_FAILED; + asyncContext->result.errorCode = RET_FAILED; return; } uiExtCallback->SetSessionId(sessionId); @@ -1261,14 +1255,14 @@ static bool StartUIExtension(ani_env* env, std::shared_ptr lock(g_lockWindowFlag); if (g_windowFlag) { ACCESSTOKEN_LOG_WARN(LABEL, "The request already exists."); - asyncContext->result = RET_FAILED; - asyncContext->errorCode = REQUEST_REALDY_EXIST; + asyncContext->result.errorCode = REQUEST_REALDY_EXIST; + asyncContext->result.errorMsg = "The specified context does not belong to the current application."; return false; } g_windowFlag = true; } CreateSettingUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); - if (asyncContext->result == RET_FAILED) { + if (asyncContext->result.errorCode == RET_FAILED) { { std::lock_guard lock(g_lockWindowFlag); g_windowFlag = false; @@ -1288,7 +1282,6 @@ static ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, std::shared_ptr asyncContext = std::make_shared(); - if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, asyncContext)) { return nullptr; } @@ -1297,7 +1290,9 @@ static ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, if (selfTokenID != asyncContext->tokenId) { ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID %{public}d is not same with selfTokenID %{public}d.", asyncContext->tokenId, selfTokenID); - ThrowError(env, RET_FAILED); + std::string errMsg = GetErrorMessage( + STS_ERROR_INNER, "The specified context does not belong to the current application."); + BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, errMsg); return nullptr; } asyncContext->loadlock.lock(); @@ -1334,19 +1329,23 @@ static void RevokeUserGrantedPermissionExecute([[maybe_unused]] ani_env* env, } if (!IsPermissionFlagValid(static_cast (permissionFlags))) { - BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_PARAM_INVALID, - GetErrorMessage(STSErrorCode::STS_ERROR_PARAM_INVALID)); + std::string errMsg = GetErrorMessage(STS_ERROR_PARAM_INVALID, "The permissionFlags is invalid."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); return; } - if (permissionNameString.size() > MAX_LENGTH || permissionNameString.empty()) { - BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_PARAM_INVALID, - GetErrorMessage(STSErrorCode::STS_ERROR_PARAM_INVALID)); + if (permissionNameString.empty() || permissionNameString.size() > MAX_LENGTH) { + std::string errMsg = GetErrorMessage( + STS_ERROR_PARAM_INVALID, "The permissionName is empty or exceeds 256 characters."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); return; } PermissionBriefDef def; if (!GetPermissionBriefDef(permissionNameString, def) || def.grantMode != USER_GRANT) { - BusinessErrorAni::ThrowError(env, STSErrorCode::STS_ERROR_PERMISSION_NOT_EXIST, GetErrorMessage(STSErrorCode::STS_ERROR_PERMISSION_NOT_EXIST)); + std::string errMsg = GetErrorMessage(STS_ERROR_PERMISSION_NOT_EXIST, + "The specified permission does not exist or is not a user_grant permission."); + BusinessErrorAni::ThrowError( + env, STS_ERROR_PERMISSION_NOT_EXIST, GetErrorMessage(STS_ERROR_PERMISSION_NOT_EXIST)); return; } @@ -1385,13 +1384,14 @@ static ani_ref GetPermissionsStatusExecute([[maybe_unused]] ani_env* env, } std::vector aniPermissionList; if (!AniParseStringArray(env, permissionList, aniPermissionList)) { - BusinessErrorAni::ThrowParameterTypeError(env, STSErrorCode::STS_ERROR_PARAM_ILLEGAL, - GetParamErrorMsg("permissionList", "Array")); + BusinessErrorAni::ThrowParameterTypeError( + env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("permissionList", "Array")); return nullptr; } - + if (aniPermissionList.empty()) { - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STS_ERROR_INNER)); + std::string errMsg = GetErrorMessage(STS_ERROR_INNER, "The permissionList is empty."); + BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STS_ERROR_INNER)); return nullptr; } @@ -1455,7 +1455,7 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) } std::array claMethods = { ani_native_function { - "checkAccessTokenANI", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, + "checkAccessTokenExecute", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, ani_native_function { "requestPermissionsFromUserExecute", "Lapplication/Context/Context;Lescompat/Array;:Lsecurity/PermissionRequestResult/PermissionRequestResult;", reinterpret_cast(RequestPermissionsFromUserExecute) }, @@ -1463,14 +1463,10 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) "Lapplication/Context/Context;Lescompat/Array;:Lescompat/Array;", reinterpret_cast(RequestPermissionOnSettingExecute) }, ani_native_function { "revokeUserGrantedPermissionExecute", - nullptr, - reinterpret_cast(RevokeUserGrantedPermissionExecute) }, - ani_native_function { "getVersionExecute", - nullptr, - reinterpret_cast(GetVersionExecute) }, - ani_native_function { "getPermissionsStatusExecute", - nullptr, - reinterpret_cast(GetPermissionsStatusExecute) }, + nullptr, reinterpret_cast(RevokeUserGrantedPermissionExecute) }, + ani_native_function { "getVersionExecute", nullptr, reinterpret_cast(GetVersionExecute) }, + ani_native_function { "getPermissionsStatusExecute", + nullptr, reinterpret_cast(GetPermissionsStatusExecute) }, }; if (ANI_OK != env->Class_BindNativeMethods(cls, claMethods.data(), claMethods.size())) { ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className); diff --git a/frameworks/ets/ani/common/include/ani_error.h b/frameworks/ets/ani/common/include/ani_error.h index d698fd7bf..d8fc49028 100644 --- a/frameworks/ets/ani/common/include/ani_error.h +++ b/frameworks/ets/ani/common/include/ani_error.h @@ -45,16 +45,18 @@ typedef enum { STS_ERROR_PERM_REVOKE_BY_USER = 12100012, STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN = 12100013, } STSErrorCode; + +struct AtmResult { + int32_t errorCode = 0; + std::string errorMsg = ""; +}; + std::string GetParamErrorMsg(const std::string& param, const std::string& errMsg); -std::string GetErrorMessage(uint32_t errCode); +std::string GetErrorMessage(uint32_t errCode, const std::string& extendMsg = ""); class BusinessErrorAni { public: static ani_object CreateError(ani_env* env, ani_int code, const std::string& msg); - static ani_object CreateCommonError(ani_env* env, int32_t err, const std::string& errMsg = ""); - static ani_object CreateEnumError(ani_env* env, const std::string& parameter, const std::string& enumClass); - static void ThrowTooFewParametersError(ani_env* env, int32_t err); static void ThrowParameterTypeError(ani_env* env, int32_t err, const std::string& errMsg); - static void ThrowEnumError(ani_env* env, const std::string& parameter, const std::string& errMsg); static void ThrowError(ani_env* env, int32_t err, const std::string& errMsg = ""); static int32_t GetStsErrorCode(int32_t errCode); diff --git a/frameworks/ets/ani/common/src/ani_error.cpp b/frameworks/ets/ani/common/src/ani_error.cpp index 0f8d42f6b..29dfc88f2 100644 --- a/frameworks/ets/ani/common/src/ani_error.cpp +++ b/frameworks/ets/ani/common/src/ani_error.cpp @@ -27,19 +27,14 @@ static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN } // namespace constexpr const int32_t RET_SUCCESS = 0; constexpr const char* BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;"; -constexpr const char* ERR_MSG_PARAM_NUMBER_ERROR = - "BusinessError 401: Parameter error. The number of parameters is incorrect."; -constexpr const char* ERR_MSG_ENUM_EROOR = "Parameter error. The value of $ is not a valid enum $."; -constexpr const char* ERR_MSG_BUSINESS_ERROR = "BusinessError $: "; -constexpr const char* ERR_MSG_PARAM_TYPE_ERROR = "Parameter error. The errMsg of $ must be $."; static const std::unordered_map g_errorStringMap = { { STS_ERROR_PERMISSION_DENIED, "Permission denied." }, { STS_ERROR_NOT_SYSTEM_APP, "Not system app." }, { STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT, "Not support system capability." }, { STS_ERROR_START_ABILITY_FAIL, "Start grant ability failed." }, - { STS_ERROR_BACKGROUND_FAIL, "Ui extension turn background failed." }, + { STS_ERROR_BACKGROUND_FAIL, "UI extension turn background failed." }, { STS_ERROR_TERMINATE_FAIL, "Ui extension terminate failed." }, - { STS_ERROR_PARAM_INVALID, "Invalid parameter $." }, + { STS_ERROR_PARAM_INVALID, "Invalid parameter." }, { STS_ERROR_TOKENID_NOT_EXIST, "The specified token id does not exist." }, { STS_ERROR_PERMISSION_NOT_EXIST, "The specified permission does not exist." }, { STS_ERROR_NOT_USE_TOGETHER, "The API is not used in pair with others." }, @@ -53,7 +48,6 @@ static const std::unordered_map g_errorStringMap = { { STS_ERROR_PERM_REVOKE_BY_USER, "The permission list contains the permission that has not been revoked by the user." }, { STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN, "The specific global switch is already open." }, - { STS_ERROR_PARAM_ILLEGAL, ERR_MSG_PARAM_TYPE_ERROR }, }; void BusinessErrorAni::ThrowError(ani_env* env, int32_t err, const std::string& errMsg) @@ -122,13 +116,13 @@ std::string GetParamErrorMsg(const std::string& param, const std::string& errMsg return msg; } -std::string GetErrorMessage(uint32_t errCode) +std::string GetErrorMessage(uint32_t errCode, const std::string& extendMsg) { auto iter = g_errorStringMap.find(errCode); if (iter != g_errorStringMap.end()) { - return iter->second; + return iter->second + (extendMsg.empty() ? "" : ("" + extendMsg)); } - std::string errMsg = "Unknown error, errCode + " + std::to_string(errCode) + "."; + std::string errMsg = "Unknown error, errCode " + std::to_string(errCode) + "."; return errMsg; } @@ -137,73 +131,10 @@ void BusinessErrorAni::ThrowParameterTypeError(ani_env* env, int32_t err, const if (env == nullptr) { return; } - ani_object error = CreateCommonError(env, err, errMsg); - ThrowError(env, error); -} - -void BusinessErrorAni::ThrowTooFewParametersError(ani_env* env, int32_t err) -{ - if (env == nullptr) { - return; - } - ThrowError(env, err, ERR_MSG_PARAM_NUMBER_ERROR); -} - -ani_object BusinessErrorAni::CreateCommonError(ani_env* env, int32_t err, const std::string& errMsg) -{ - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "env is nullptr"); - return nullptr; - } - std::string errMessage = ERR_MSG_BUSINESS_ERROR; - auto iter = errMessage.find("$"); - if (iter != std::string::npos) { - errMessage = errMessage.replace(iter, 1, std::to_string(err)); - } - if (g_errorStringMap.find(err) != g_errorStringMap.end()) { - errMessage += g_errorStringMap.at(err); - } - iter = errMessage.find("$"); - if (iter != std::string::npos) { - iter = errMessage.find("$"); - if (iter != std::string::npos) { - errMessage = errMessage.replace(iter, 1, errMsg); - } - } - return CreateError(env, err, errMessage); -} - -void BusinessErrorAni::ThrowEnumError(ani_env* env, const std::string& parameter, const std::string& errMsg) -{ - if (env == nullptr) { - return; - } - ani_object error = CreateEnumError(env, parameter, errMsg); + ani_object error = CreateError(env, err, errMsg); ThrowError(env, error); } -ani_object BusinessErrorAni::CreateEnumError(ani_env* env, const std::string& parameter, const std::string& enumClass) -{ - if (env == nullptr) { - return nullptr; - } - std::string errMessage = ERR_MSG_BUSINESS_ERROR; - auto iter = errMessage.find("$"); - if (iter != std::string::npos) { - errMessage = errMessage.replace(iter, 1, std::to_string(STS_ERROR_PARAM_ILLEGAL)); - } - errMessage += ERR_MSG_ENUM_EROOR; - iter = errMessage.find("$"); - if (iter != std::string::npos) { - errMessage = errMessage.replace(iter, 1, parameter); - iter = errMessage.find("$"); - if (iter != std::string::npos) { - errMessage = errMessage.replace(iter, 1, enumClass); - } - } - return CreateError(env, STS_ERROR_PARAM_ILLEGAL, errMessage); -} - void BusinessErrorAni::ThrowError(ani_env* env, ani_object err) { if (err == nullptr) { diff --git a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets index f91c45fe6..b53beac77 100644 --- a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets +++ b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets @@ -23,7 +23,6 @@ function PARAM_ERROR_MSG(param: string, type: string): string { export { Permissions } export default namespace privacyManager { - loadLibrary("privacy_ani.z"); enum PermissionUsedType { @@ -39,17 +38,11 @@ export default namespace privacyManager { } enum STSErrorCode { - STS_OK = 0, - STS_ERROR_PERMISSION_DENIED = 201, - STS_ERROR_NOT_SYSTEM_APP = 202, - STS_ERROR_PARAM_ILLEGAL = 401, - STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT = 801, - } ; interface AddPermissionUsedRecordOptions { @@ -103,7 +96,7 @@ export default namespace privacyManager { if (typeof permissionName !== "string") { let err = new BusinessError(); err.code = STSErrorCode.STS_ERROR_PARAM_ILLEGAL; - err.data = PARAM_ERROR_MSG("permissionName", "string"); + err.data = PARAM_ERROR_MSG("permissionName", "Permissions"); throw err; } @@ -126,7 +119,7 @@ export default namespace privacyManager { if (typeof permissionName !== "string") { let err = new BusinessError(); err.code = STSErrorCode.STS_ERROR_PARAM_ILLEGAL; - err.data = PARAM_ERROR_MSG("permissionName", "string"); + err.data = PARAM_ERROR_MSG("permissionName", "Permissions"); throw err; } let optionsLocal: AddPermissionUsedRecordOptionsInner = { usedType: PermissionUsedType.NORMAL_TYPE }; -- Gitee