From a8f03456038a4eed128bfa3d136acc398b0527d7 Mon Sep 17 00:00:00 2001 From: chennian Date: Wed, 4 Jun 2025 13:51:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9request=E4=B8=BA=E5=BC=82?= =?UTF-8?q?=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chennian Change-Id: I7e10712bf96f15c6c5cb083edafe0c508a352609 --- frameworks/ets/ani/accesstoken/BUILD.gn | 6 +- .../ets/@ohos.abilityAccessCtrl.ets | 30 +- .../include/ani_ability_access_ctrl.h | 54 ++ ...access_ctrl.h => ani_request_permission.h} | 120 +-- .../ani_request_permission_on_setting.h | 88 ++ .../src/ani_ability_access_ctrl.cpp | 340 +++++++ ...ss_ctrl.cpp => ani_request_permission.cpp} | 876 +----------------- .../src/ani_request_permission_on_setting.cpp | 453 +++++++++ frameworks/ets/ani/common/include/ani_utils.h | 6 + frameworks/ets/ani/common/src/ani_error.cpp | 2 +- frameworks/ets/ani/common/src/ani_utils.cpp | 118 +++ .../ani/privacy/ets/@ohos.privacyManager.ets | 12 +- 12 files changed, 1129 insertions(+), 976 deletions(-) create mode 100644 frameworks/ets/ani/accesstoken/include/ani_ability_access_ctrl.h rename frameworks/ets/ani/accesstoken/include/{ability_access_ctrl.h => ani_request_permission.h} (54%) create mode 100644 frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h create mode 100644 frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp rename frameworks/ets/ani/accesstoken/src/{ability_access_ctrl.cpp => ani_request_permission.cpp} (44%) create mode 100644 frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp diff --git a/frameworks/ets/ani/accesstoken/BUILD.gn b/frameworks/ets/ani/accesstoken/BUILD.gn index 6fe0a6561..30e910dc6 100644 --- a/frameworks/ets/ani/accesstoken/BUILD.gn +++ b/frameworks/ets/ani/accesstoken/BUILD.gn @@ -31,7 +31,11 @@ ohos_shared_library("accesstoken_ani") { "${access_token_path}/interfaces/innerkits/token_callback/include", "${access_token_path}/frameworks/ets/ani/common/include", ] - sources = [ "src/ability_access_ctrl.cpp" ] + sources = [ + "src/ani_ability_access_ctrl.cpp", + "src/ani_request_permission.cpp", + "src/ani_request_permission_on_setting.cpp", + ] deps = [ "${access_token_path}/frameworks/ets/ani/common:libani_common", diff --git a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets index 1e48fc2a9..0104c113d 100644 --- a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -16,7 +16,7 @@ import { AsyncCallback, Callback, BusinessError } from '@ohos.base'; import { Permissions } from 'permissions'; import type _PermissionRequestResult from 'security.PermissionRequestResult'; -import Context from 'application.Context' +import Context from 'application.Context'; import hilog from '@ohos.hilog'; function PARAM_ERROR_MSG(param: string, type: string): string { @@ -28,7 +28,6 @@ export { Permissions }; export type PermissionRequestResult = _PermissionRequestResult; export default namespace abilityAccessCtrl { - loadLibrary("accesstoken_ani.z"); export enum GrantStatus { PERMISSION_DENIED = -1, @@ -92,7 +91,9 @@ export default namespace abilityAccessCtrl { interface AtManager { checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; requestPermissionsFromUserExecute( - context: Context, permissionList: Array): PermissionRequestResult; + context: Context, permissionList: Array, + resolve: (v: PermissionRequestResult) => void, + reject: (error: BusinessError) => void): PermissionRequestResult; requestPermissionOnSettingExecute(context: Context, permissionList: Array): Array; revokeUserGrantedPermissionExecute(tokenID: int, permissionName: Permissions, permissionFlags: int): void; getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; @@ -127,7 +128,9 @@ export default namespace abilityAccessCtrl { class AtManagerInner implements AtManager { native checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; native requestPermissionsFromUserExecute( - context: Context, permissionList: Array): PermissionRequestResult; + context: Context, permissionList: Array, + resolve: (v: PermissionRequestResult) => void, + reject: (error: BusinessError) => void): PermissionRequestResult; native requestPermissionOnSettingExecute( context: Context, permissionList: Array): Array; native revokeUserGrantedPermissionExecute( @@ -176,7 +179,7 @@ export default namespace abilityAccessCtrl { } requestPermissionsFromUser(context: Context, permissionList: Array, - callback:AsyncCallback): void { + callback: AsyncCallback): void { validateRequestParams(context, permissionList); let fun = async() => { let work = new EAWorker(); @@ -200,24 +203,9 @@ export default namespace abilityAccessCtrl { requestPermissionsFromUser(context: Context, permissionList: Array): Promise { validateRequestParams(context, permissionList); - let p = new Promise(( resolve: (v: PermissionRequestResult) => void, reject: (error: BusinessError) => void) => { - let fun = async() => { - let work = new EAWorker(); - try { - 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); - } - }; - fun(); + new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList, resolve, reject); }); return p; } diff --git a/frameworks/ets/ani/accesstoken/include/ani_ability_access_ctrl.h b/frameworks/ets/ani/accesstoken/include/ani_ability_access_ctrl.h new file mode 100644 index 000000000..28ffbdcec --- /dev/null +++ b/frameworks/ets/ani/accesstoken/include/ani_ability_access_ctrl.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABILITY_ACCESS_CTRL_H +#define ABILITY_ACCESS_CTRL_H + +#include "access_token.h" +#include "ani.h" +#include "ani_error.h" +#include "ani_utils.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +const int32_t PARAM_DEFAULT_VALUE = -1; +struct AtManagerAsyncContext { + AccessTokenID tokenId = 0; + std::string permissionName; + union { + uint32_t flag = 0; + uint32_t status; + }; + int32_t grantStatus = PERMISSION_DENIED; + AtmResult result; +}; + +struct PermissionParamCache { + long long sysCommitIdCache = PARAM_DEFAULT_VALUE; + int32_t commitIdCache = PARAM_DEFAULT_VALUE; + int32_t handle = PARAM_DEFAULT_VALUE; + std::string sysParamCache; +}; + +struct PermissionStatusCache { + int32_t status; + std::string paramValue; +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +#endif // ABILITY_ACCESS_CTRL_H \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h b/frameworks/ets/ani/accesstoken/include/ani_request_permission.h similarity index 54% rename from frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h rename to frameworks/ets/ani/accesstoken/include/ani_request_permission.h index e3ac10ad3..c78c50a4c 100644 --- a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission.h @@ -12,20 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifndef ABILITY_ACCESS_CTRL_H -#define ABILITY_ACCESS_CTRL_H - -#include -#include -#include -#include +#ifndef ANI_REQUEST_PERMISSION_H +#define ANI_REQUEST_PERMISSION_H #include "ability.h" -#include "ability_manager_client.h" #include "access_token.h" #include "ani.h" #include "ani_error.h" +#include "ani_utils.h" +#ifdef EVENTHANDLER_ENABLE +#include "event_handler.h" +#include "event_queue.h" +#endif #include "permission_grant_info.h" #include "token_callback_stub.h" #include "ui_content.h" @@ -34,45 +32,13 @@ namespace OHOS { namespace Security { namespace AccessToken { -const int32_t PARAM_DEFAULT_VALUE = -1; -struct AtManagerAsyncContext { - AccessTokenID tokenId = 0; - std::string permissionName; - union { - uint32_t flag = 0; - uint32_t status; - }; - int32_t grantStatus = PERMISSION_DENIED; - AtmResult result; -}; - -class AniContextCommon { -public: - static constexpr int32_t MAX_PARAMS_ONE = 1; - static constexpr int32_t MAX_PARAMS_TWO = 2; - static constexpr int32_t MAX_PARAMS_THREE = 3; - static constexpr int32_t MAX_PARAMS_FOUR = 4; - static constexpr int32_t MAX_LENGTH = 256; - static constexpr int32_t MAX_WAIT_TIME = 1000; - static constexpr int32_t VALUE_MAX_LEN = 32; -}; - -struct PermissionParamCache { - long long sysCommitIdCache = PARAM_DEFAULT_VALUE; - int32_t commitIdCache = PARAM_DEFAULT_VALUE; - int32_t handle = PARAM_DEFAULT_VALUE; - std::string sysParamCache; -}; - -struct PermissionStatusCache { - int32_t status; - std::string paramValue; -}; - -static PermissionParamCache g_paramCache; -std::map g_cache; - struct RequestAsyncContext { + explicit RequestAsyncContext(ani_env* env, ani_fn_object resolve, ani_fn_object reject) + { + this->env = env; + this->resolve = resolve; + this->reject = reject; + } AccessTokenID tokenId = 0; std::string bundleName; bool needDynamicRequest = true; @@ -96,8 +62,10 @@ struct RequestAsyncContext { #ifdef EVENTHANDLER_ENABLE std::shared_ptr handler_ = nullptr; #endif + ani_env* env = nullptr; + ani_fn_object resolve; + ani_fn_object reject; }; - class UIExtensionCallback { public: explicit UIExtensionCallback(const std::shared_ptr& reqContext); @@ -147,59 +115,9 @@ struct ResultCallback { std::shared_ptr data = nullptr; }; -struct RequestPermOnSettingAsyncContext { - AccessTokenID tokenId = 0; - AtmResult result; - PermissionGrantInfo info; - - std::vector permissionList; - napi_value requestResult = nullptr; - std::vector stateList; - - std::shared_ptr abilityContext; - std::shared_ptr uiExtensionContext; - bool uiAbilityFlag = false; - std::mutex loadlock; - -#ifdef EVENTHANDLER_ENABLE - std::shared_ptr handler_ = - std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); -#endif -}; - -class PermissonOnSettingUICallback { -public: - explicit PermissonOnSettingUICallback(ani_env* env, - const std::shared_ptr& reqContext); - ~PermissonOnSettingUICallback(); - void SetSessionId(int32_t sessionId); - void ReleaseHandler(int32_t code); - void OnRelease(int32_t releaseCode); - void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); - void OnReceive(const OHOS::AAFwk::WantParams& request); - void OnError(int32_t code, const std::string& name, const std::string& message); - void OnRemoteReady(const std::shared_ptr& uiProxy); - void OnDestroy(); - -private: - ani_env* env_; - std::shared_ptr reqContext_ = nullptr; - int32_t sessionId_ = 0; - - std::mutex lockReleaseFlag; - bool releaseFlag = false; -}; - -struct PermissonOnSettingResultCallback { - int32_t jsCode; - std::vector stateList; - std::shared_ptr data = nullptr; -}; - -std::map>> RequestAsyncInstanceControl::instanceIdMap_; -std::mutex RequestAsyncInstanceControl::instanceIdMutex_; +ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_object aniContext, ani_array_ref permissionList, ani_fn_object resolve, ani_fn_object reject); } // namespace AccessToken } // namespace Security } // namespace OHOS - -#endif // ABILITY_ACCESS_CTRL_H \ No newline at end of file +#endif /* ANI_REQUEST_PERMISSION_H */ diff --git a/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h b/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h new file mode 100644 index 000000000..c332cc228 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANI_REQUEST_PERMISSION_ON_SETTING_H +#define ANI_REQUEST_PERMISSION_ON_SETTING_H + +#include "ability.h" +#include "access_token.h" +#include "ani.h" +#include "ani_error.h" +#include "ani_utils.h" +#ifdef EVENTHANDLER_ENABLE +#include "event_handler.h" +#include "event_queue.h" +#endif +#include "permission_grant_info.h" +#include "ui_content.h" +#include "ui_extension_context.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +struct RequestPermOnSettingAsyncContext { + AccessTokenID tokenId = 0; + AtmResult result; + PermissionGrantInfo info; + + std::vector permissionList; + napi_value requestResult = nullptr; + std::vector stateList; + + std::shared_ptr abilityContext; + std::shared_ptr uiExtensionContext; + bool uiAbilityFlag = false; + std::mutex loadlock; + +#ifdef EVENTHANDLER_ENABLE + std::shared_ptr handler_ = + std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); +#endif +}; + +class PermissonOnSettingUICallback { +public: + explicit PermissonOnSettingUICallback(ani_env* env, + const std::shared_ptr& reqContext); + ~PermissonOnSettingUICallback(); + void SetSessionId(int32_t sessionId); + void ReleaseHandler(int32_t code); + void OnRelease(int32_t releaseCode); + void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); + void OnReceive(const OHOS::AAFwk::WantParams& request); + void OnError(int32_t code, const std::string& name, const std::string& message); + void OnRemoteReady(const std::shared_ptr& uiProxy); + void OnDestroy(); + +private: + ani_env* env_; + std::shared_ptr reqContext_ = nullptr; + int32_t sessionId_ = 0; + + std::mutex lockReleaseFlag; + bool releaseFlag = false; +}; + +struct PermissonOnSettingResultCallback { + int32_t jsCode; + std::vector stateList; + std::shared_ptr data = nullptr; +}; + +ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList); +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif /* ANI_REQUEST_PERMISSION_ON_SETTING_H */ diff --git a/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp new file mode 100644 index 000000000..4bdcd38f6 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_ability_access_ctrl.h" + +#include +#include +#include + +#include "access_token_error.h" +#include "accesstoken_kit.h" +#include "accesstoken_log.h" +#include "ani_request_permission.h" +#include "ani_request_permission_on_setting.h" +#include "hisysevent.h" +#include "parameter.h" +#include "permission_list_state.h" +#include "permission_map.h" +#include "token_setproc.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniAbilityAccessCtrl" }; +constexpr int32_t MAX_LENGTH = 256; +constexpr int32_t VALUE_MAX_LEN = 32; +std::mutex g_lockCache; +static PermissionParamCache g_paramCache; +std::map g_cache; +static constexpr const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change"; +} + +static ani_object CreateAtManager([[maybe_unused]] ani_env* env) +{ + ani_object atManagerObj = {}; + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return atManagerObj; + } + + static const char* className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); + return atManagerObj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "get ctor Failed %{public}s", className); + return atManagerObj; + } + + if (ANI_OK != env->Object_New(cls, ctor, &atManagerObj)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Create Object Failed %{public}s", className); + return atManagerObj; + } + return atManagerObj; +} + +static std::string GetPermParamValue() +{ + long long sysCommitId = GetSystemCommitId(); + if (sysCommitId == g_paramCache.sysCommitIdCache) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "SysCommitId = %{public}lld", sysCommitId); + return g_paramCache.sysParamCache; + } + g_paramCache.sysCommitIdCache = sysCommitId; + if (g_paramCache.handle == PARAM_DEFAULT_VALUE) { + int32_t handle = static_cast(FindParameter(PERMISSION_STATUS_CHANGE_KEY)); + if (handle == PARAM_DEFAULT_VALUE) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindParameter failed"); + return "-1"; + } + g_paramCache.handle = handle; + } + + int32_t currCommitId = static_cast(GetParameterCommitId(g_paramCache.handle)); + if (currCommitId != g_paramCache.commitIdCache) { + char value[VALUE_MAX_LEN] = { 0 }; + auto ret = GetParameterValue(g_paramCache.handle, value, VALUE_MAX_LEN - 1); + if (ret < 0) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Return default value, ret=%{public}d", ret); + return "-1"; + } + std::string resStr(value); + g_paramCache.sysParamCache = resStr; + g_paramCache.commitIdCache = currCommitId; + } + return g_paramCache.sysParamCache; +} + +static void UpdatePermissionCache(AtManagerAsyncContext* asyncContext) +{ + std::lock_guard lock(g_lockCache); + auto iter = g_cache.find(asyncContext->permissionName); + if (iter != g_cache.end()) { + std::string currPara = GetPermParamValue(); + if (currPara != iter->second.paramValue) { + asyncContext->grantStatus = + AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); + iter->second.status = asyncContext->grantStatus; + iter->second.paramValue = currPara; + ACCESSTOKEN_LOG_DEBUG(LABEL, "Param changed currPara %{public}s", currPara.c_str()); + } else { + asyncContext->grantStatus = iter->second.status; + } + } else { + asyncContext->grantStatus = + AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); + 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()); + } +} + +static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_int tokenID, ani_string permissionName) +{ + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return AccessToken::PermissionState::PERMISSION_DENIED; + } + if (tokenID == 0) { + 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) { + 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(); + if (asyncContext == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail."); + return AccessToken::PermissionState::PERMISSION_DENIED; + } + std::unique_ptr context {asyncContext}; + asyncContext->tokenId = static_cast(tokenID); + asyncContext->permissionName = stdPermissionName; + static uint64_t selfTokenId = GetSelfTokenID(); + if (asyncContext->tokenId != static_cast(selfTokenId)) { + asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, stdPermissionName); + return static_cast(asyncContext->grantStatus); + } + UpdatePermissionCache(asyncContext); + ACCESSTOKEN_LOG_INFO(LABEL, "CheckAccessTokenSync result : %{public}d", asyncContext->grantStatus); + return static_cast(asyncContext->grantStatus); +} + +static bool IsPermissionFlagValid(uint32_t flag) +{ + return (flag == PermissionFlag::PERMISSION_USER_SET) || (flag == PermissionFlag::PERMISSION_USER_FIXED) || + (flag == PermissionFlag::PERMISSION_ALLOW_THIS_TIME); +}; + +static void RevokeUserGrantedPermissionExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_int tokenID, ani_string permissionName, ani_int permissionFlags) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "RevokeUserGrantedPermission begin."); + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "env null."); + return; + } + + std::string permissionNameString; + if (!AniParseString(env, permissionName, permissionNameString)) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("permissionName", "Permissions")); + return; + } + + if (!IsPermissionFlagValid(static_cast (permissionFlags))) { + std::string errMsg = GetErrorMessage(STS_ERROR_PARAM_INVALID, "The permissionFlags is invalid."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); + return; + } + + 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) { + 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; + } + + int32_t ret = AccessTokenKit::RevokePermission(tokenID, permissionNameString, permissionFlags); + if (ret != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(ret); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + } +} + +static ani_int GetVersionExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "getVersionExecute begin."); + uint32_t version = -1; + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "env null"); + return version; + } + + int32_t result = AccessTokenKit::GetVersion(version); + if (result != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + return version; + } + return version; +} + +static ani_ref GetPermissionsStatusExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_int tokenID, ani_array_ref permissionList) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "GetPermissionsStatusExecute begin."); + if ((env == nullptr) || (permissionList == nullptr)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null."); + return nullptr; + } + std::vector aniPermissionList; + if (!AniParseStringArray(env, permissionList, aniPermissionList)) { + BusinessErrorAni::ThrowParameterTypeError( + env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("permissionList", "Array")); + return nullptr; + } + + if (aniPermissionList.empty()) { + std::string errMsg = GetErrorMessage(STS_ERROR_INNER, "The permissionList is empty."); + BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STS_ERROR_INNER)); + return nullptr; + } + + std::vector permList; + for (const auto& permission : aniPermissionList) { + PermissionListState permState; + permState.permissionName = permission; + permState.state = INVALID_OPER; + permList.emplace_back(permState); + } + + int32_t result = RET_SUCCESS; + std::vector permissionQueryResults; + result = AccessTokenKit::GetPermissionsStatus(tokenID, permList); + if (result != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + return nullptr; + } + for (const auto& permState : permList) { + permissionQueryResults.emplace_back(permState.state); + } + + return ConvertAniArrayInt(env, permissionQueryResults); +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) +{ + if (vm == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm"); + return ANI_INVALID_ARGS; + } + ani_env* env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Unsupported ANI_VERSION_1"); + return ANI_OUT_OF_MEMORY; + } + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return ANI_NOT_FOUND; + } + const char* spaceName = "L@ohos/abilityAccessCtrl/abilityAccessCtrl;"; + ani_namespace spc; + if (ANI_OK != env->FindNamespace(spaceName, &spc)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", spaceName); + return ANI_NOT_FOUND; + } + std::array methods = { + ani_native_function { "createAtManager", nullptr, reinterpret_cast(CreateAtManager) }, + }; + if (ANI_OK != env->Namespace_BindNativeFunctions(spc, methods.data(), methods.size())) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", spaceName); + return ANI_ERROR; + }; + const char* className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); + return ANI_ERROR; + } + std::array claMethods = { + ani_native_function { + "checkAccessTokenExecute", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, + ani_native_function { "requestPermissionsFromUserExecute", + "Lapplication/Context/Context;Lescompat/Array;Lstd/core/Function1;Lstd/core/Function1:Lsecurity/PermissionRequestResult/PermissionRequestResult;", + reinterpret_cast(RequestPermissionsFromUserExecute) }, + ani_native_function { "requestPermissionOnSettingExecute", + "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) }, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, claMethods.data(), claMethods.size())) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className); + return ANI_ERROR; + }; + *result = ANI_VERSION_1; + return ANI_OK; +} +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp similarity index 44% rename from frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp rename to frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp index 0dcb952f1..12be0ff84 100644 --- a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,46 +12,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "ani_request_permission.h" -#include "ability_access_ctrl.h" +#include +#include +#include +#include -#include -#include - -#include "access_token.h" -#include "access_token_error.h" +#include "ability_manager_client.h" +#include "ani_base_context.h" #include "accesstoken_kit.h" #include "accesstoken_log.h" -#include "ani_base_context.h" -#include "ani_error.h" -#include "ani_utils.h" #include "hisysevent.h" -#include "parameter.h" -#include "permission_list_state.h" -#include "permission_map.h" #include "token_setproc.h" #include "want.h" namespace OHOS { namespace Security { namespace AccessToken { +std::map>> RequestAsyncInstanceControl::instanceIdMap_; +std::mutex RequestAsyncInstanceControl::instanceIdMutex_; +namespace { +#define SETTER_METHOD_NAME(property) "" #property +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = + { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniRequestPermissionOnSetting" }; std::mutex g_lockFlag; -std::mutex g_lockWindowFlag; -bool g_windowFlag = false; -static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniAbilityAccessCtrl" }; -constexpr int32_t MAX_LENGTH = 256; -constexpr int32_t REQUEST_REALDY_EXIST = 1; -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"; const std::string STATE_KEY = "ohos.user.grant.permission.state"; const std::string RESULT_KEY = "ohos.user.grant.permission.result"; const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; @@ -64,11 +51,7 @@ const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top"; const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height"; const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width"; const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token"; -const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code"; -const std::string PERMISSION_RESULT_KEY = "ohos.user.setting.permission.result"; - -#define SETTER_METHOD_NAME(property) "" #property - +} static void UpdateGrantPermissionResultOnly(const std::vector& permissions, const std::vector& grantResults, std::shared_ptr& data, std::vector& newGrantResults) { @@ -267,81 +250,8 @@ static void GetInstanceId(std::shared_ptr& asyncContext) #endif } -static ani_ref ConvertAniArrayString(ani_env* env, const std::vector& cArray) -{ - ani_size length = cArray.size(); - ani_array_ref aArrayRef = nullptr; - ani_class aStringcls = nullptr; - if (env->FindClass("Lstd/core/String;", &aStringcls) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString FindClass String failed"); - return nullptr; - } - ani_ref undefinedRef = nullptr; - if (ANI_OK != env->GetUndefined(&undefinedRef)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString GetUndefined failed"); - return nullptr; - } - if (env->Array_New_Ref(aStringcls, length, undefinedRef, &aArrayRef) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString Array_New_Ref failed "); - return nullptr; - } - ani_string aString = nullptr; - for (ani_size i = 0; i < length; ++i) { - env->String_NewUTF8(cArray[i].c_str(), cArray[i].size(), &aString); - env->Array_Set_Ref(aArrayRef, i, aString); - } - ani_ref aRef = nullptr; - if (env->GlobalReference_Create(aArrayRef, &aRef) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString GlobalReference_Create failed "); - return nullptr; - } - return aRef; -} - -static ani_ref ConvertAniArrayInt(ani_env* env, const std::vector& cArray) -{ - ani_size length = cArray.size(); - ani_array_int aArrayInt = nullptr; - if (env->Array_New_Int(length, &aArrayInt) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayInt Array_New_Int failed "); - return nullptr; - } - for (ani_size i = 0; i < length; ++i) { - env->Array_SetRegion_Int(aArrayInt, i, length, &cArray[i]); - } - ani_ref aRef = nullptr; - if (env->GlobalReference_Create(aArrayInt, &aRef) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayInt GlobalReference_Create failed "); - return nullptr; - } - return aRef; -} - -static ani_ref ConvertAniArrayBool(ani_env* env, const std::vector& cArray) -{ - ani_size length = cArray.size(); - ani_array_boolean aArrayBool = nullptr; - if (env->Array_New_Boolean(length, &aArrayBool) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayBool Array_New_Boolean failed "); - return nullptr; - } - std::vector boolArray(length); - for (ani_size i = 0; i < length; ++i) { - boolArray[i] = cArray[i]; - } - for (ani_size i = 0; i < length; ++i) { - env->Array_SetRegion_Boolean(aArrayBool, i, length, &boolArray[i]); - } - ani_ref aRef = nullptr; - if (env->GlobalReference_Create(aArrayBool, &aRef) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayBool GlobalReference_Create failed "); - return nullptr; - } - return aRef; -} - template -static inline bool CallSetter(ani_env* env, ani_class cls, ani_object object, const char* setterName, valueType value) +inline bool CallSetter(ani_env* env, ani_class cls, ani_object object, const char* setterName, valueType value) { ani_status status = ANI_ERROR; ani_field fieldValue; @@ -356,51 +266,6 @@ static inline bool CallSetter(ani_env* env, ani_class cls, ani_object object, co return true; } -std::string ANIUtils_ANIStringToStdString(ani_env* env, ani_string ani_str) -{ - ani_size strSize; - if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8Size error"); - return ""; - } - std::vector buffer(strSize + 1); - char* utf8_buffer = buffer.data(); - - ani_size bytes_written = 0; - if (env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8 error"); - return ""; - } - utf8_buffer[bytes_written] = '\0'; - std::string content = std::string(utf8_buffer); - return content; -} - -static bool ProcessArrayString([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, - ani_array_ref arrayObj, std::vector& permissionList) -{ - ani_size length; - if (ANI_OK != env->Array_GetLength(arrayObj, &length)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Array_GetLength FAILED"); - return false; - } - for (ani_size i = 0; i < length; i++) { - ani_ref stringEntryRef; - if (ANI_OK != env->Object_CallMethodByName_Ref( - arrayObj, "$_get", "I:Lstd/core/Object;", &stringEntryRef, static_cast(i))) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethodByName_Ref _get Failed"); - return false; - } - auto strEntryRef = ANIUtils_ANIStringToStdString(env, static_cast(stringEntryRef)); - if (strEntryRef.empty()) { - return false; - } else { - permissionList.emplace_back(strEntryRef); - } - } - return true; -} - static ani_object WrapResult(ani_env* env, std::shared_ptr& asyncContext) { ani_status status = ANI_ERROR; @@ -575,14 +440,14 @@ static bool RequestPermissionsFromUserProcess([[maybe_unused]] ani_env* env, return true; } -static ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, - ani_object aniContext, ani_array_ref permissionList) +ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_object aniContext, ani_array_ref permissionList, ani_fn_object resolve, ani_fn_object reject) { - if (env == nullptr || permissionList == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null"); + if (env == nullptr || permissionList == nullptr || resolve == nullptr || reject == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "env or permissionList or resolve or reject is null."); return nullptr; } - std::shared_ptr asyncContext = std::make_shared(); + std::shared_ptr asyncContext = std::make_shared(env, resolve, reject); if (!ParseRequestPermissionFromUser(env, aniContext, permissionList, asyncContext)) { return nullptr; } @@ -595,7 +460,11 @@ static ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* en LABEL, "The context tokenID: %{public}d, selfTokenID: %{public}d.", asyncContext->tokenId, selfTokenID); std::string errMsg = GetErrorMessage( STS_ERROR_INNER, "The specified context does not belong to the current application."); - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, errMsg); + std::vector vec; + ani_ref error = BusinessErrorAni::CreateError(env, STS_ERROR_INNER, errMsg); + vec.emplace_back(static_cast(error)); + ani_ref result; + AniFunctionalObjectCall(env, reject, vec.size(), vec.data(), result); return nullptr; } if (!RequestPermissionsFromUserProcess(env, asyncContext)) { @@ -789,693 +658,6 @@ void AuthorizationResult::WindowShownCallback() } RequestAsyncInstanceControl::ExecCallback(asyncContext->instanceId); } - -static ani_object CreateAtManager([[maybe_unused]] ani_env* env) -{ - ani_object atManagerObj = {}; - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); - return atManagerObj; - } - - static const char* className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; - ani_class cls; - if (ANI_OK != env->FindClass(className, &cls)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); - return atManagerObj; - } - - ani_method ctor; - if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "get ctor Failed %{public}s", className); - return atManagerObj; - } - - if (ANI_OK != env->Object_New(cls, ctor, &atManagerObj)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Create Object Failed %{public}s", className); - return atManagerObj; - } - return atManagerObj; -} - -static std::string GetPermParamValue() -{ - long long sysCommitId = GetSystemCommitId(); - if (sysCommitId == g_paramCache.sysCommitIdCache) { - ACCESSTOKEN_LOG_DEBUG(LABEL, "SysCommitId = %{public}lld", sysCommitId); - return g_paramCache.sysParamCache; - } - g_paramCache.sysCommitIdCache = sysCommitId; - if (g_paramCache.handle == PARAM_DEFAULT_VALUE) { - int32_t handle = static_cast(FindParameter(PERMISSION_STATUS_CHANGE_KEY)); - if (handle == PARAM_DEFAULT_VALUE) { - ACCESSTOKEN_LOG_ERROR(LABEL, "FindParameter failed"); - return "-1"; - } - g_paramCache.handle = handle; - } - - int32_t currCommitId = static_cast(GetParameterCommitId(g_paramCache.handle)); - if (currCommitId != g_paramCache.commitIdCache) { - char value[AniContextCommon::VALUE_MAX_LEN] = { 0 }; - auto ret = GetParameterValue(g_paramCache.handle, value, AniContextCommon::VALUE_MAX_LEN - 1); - if (ret < 0) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Return default value, ret=%{public}d", ret); - return "-1"; - } - std::string resStr(value); - g_paramCache.sysParamCache = resStr; - g_paramCache.commitIdCache = currCommitId; - } - return g_paramCache.sysParamCache; -} - -static void UpdatePermissionCache(AtManagerAsyncContext* asyncContext) -{ - std::lock_guard lock(g_lockCache); - auto iter = g_cache.find(asyncContext->permissionName); - if (iter != g_cache.end()) { - std::string currPara = GetPermParamValue(); - if (currPara != iter->second.paramValue) { - asyncContext->grantStatus = - AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); - iter->second.status = asyncContext->grantStatus; - iter->second.paramValue = currPara; - ACCESSTOKEN_LOG_DEBUG(LABEL, "Param changed currPara %{public}s", currPara.c_str()); - } else { - asyncContext->grantStatus = iter->second.status; - } - } else { - asyncContext->grantStatus = - AccessToken::AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName); - 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()); - } -} - -static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, - ani_int tokenID, ani_string permissionName) -{ - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); - return AccessToken::PermissionState::PERMISSION_DENIED; - } - if (tokenID == 0) { - 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) { - 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(); - if (asyncContext == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail."); - return AccessToken::PermissionState::PERMISSION_DENIED; - } - std::unique_ptr context {asyncContext}; - asyncContext->tokenId = static_cast(tokenID); - asyncContext->permissionName = stdPermissionName; - static uint64_t selfTokenId = GetSelfTokenID(); - if (asyncContext->tokenId != static_cast(selfTokenId)) { - asyncContext->grantStatus = AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, stdPermissionName); - return static_cast(asyncContext->grantStatus); - } - UpdatePermissionCache(asyncContext); - ACCESSTOKEN_LOG_INFO(LABEL, "CheckAccessTokenSync result : %{public}d", asyncContext->grantStatus); - return static_cast(asyncContext->grantStatus); -} - -static ani_status GetContext( - ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) -{ - auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); - if (context == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "GetStageModeContext failed"); - return ANI_ERROR; - } - asyncContext->abilityContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->abilityContext != nullptr) { - auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); - if (abilityInfo == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); - return ANI_ERROR; - } - asyncContext->uiAbilityFlag = true; - asyncContext->tokenId = abilityInfo->accessTokenId; - } else { - asyncContext->uiExtensionContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->uiExtensionContext == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertTo UIExtensionContext failed"); - return ANI_ERROR; - } - auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); - if (uiExtensionInfo == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); - return ANI_ERROR; - } - asyncContext->tokenId = uiExtensionInfo->accessTokenId; - } - return ANI_OK; -} - -static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext, ani_array_ref& permissionList, - std::shared_ptr& asyncContext) -{ - if (GetContext(env, aniContext, asyncContext) != ANI_OK) { - 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, STS_ERROR_PARAM_ILLEGAL, - GetParamErrorMsg("permissionList", "Array")); - return false; - } - return true; -} - -static void StateToEnumIndex(int32_t state, ani_size& enumIndex) -{ - if (state == 0) { - enumIndex = 1; - } else { - enumIndex = 0; - } -} - -static ani_ref ReturnResult(ani_env* env, std::shared_ptr& asyncContext) -{ - ani_class arrayCls = nullptr; - if (env->FindClass("Lescompat/Array;", &arrayCls) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name Lescompat/Array failed!"); - return nullptr; - } - - ani_method arrayCtor; - if (env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass failed!"); - return nullptr; - } - - ani_object arrayObj; - if (env->Object_New(arrayCls, arrayCtor, &arrayObj, asyncContext->stateList.size()) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Object new failed!"); - return nullptr; - } - - const char* enumDescriptor = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/GrantStatus;"; - ani_enum enumType; - if (env->FindEnum(enumDescriptor, &enumType) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name %{public}s failed!", enumDescriptor); - return nullptr; - } - - ani_size index = 0; - for (const auto& state: asyncContext->stateList) { - ani_enum_item enumItem; - ani_size enumIndex = 0; - StateToEnumIndex(state, enumIndex); - if (env->Enum_GetEnumItemByIndex(enumType, enumIndex, &enumItem) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "GetEnumItemByIndex value %{public}u failed!", state); - break; - } - - if (env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, enumItem) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethodByName_Void $_set failed!"); - break; - } - index++; - } - - return arrayObj; -} - -static int32_t TransferToStsErrorCode(int32_t errorCode) -{ - int32_t stsCode = STS_OK; - switch (errorCode) { - case RET_SUCCESS: - stsCode = STS_OK; - break; - case REQUEST_REALDY_EXIST: - stsCode = STS_ERROR_REQUEST_IS_ALREADY_EXIST; - break; - case PERM_NOT_BELONG_TO_SAME_GROUP: - stsCode = STS_ERROR_PARAM_INVALID; - break; - case PERM_IS_NOT_DECLARE: - stsCode = STS_ERROR_PARAM_INVALID; - break; - case ALL_PERM_GRANTED: - stsCode = STS_ERROR_ALL_PERM_GRANTED; - break; - case PERM_REVOKE_BY_USER: - stsCode = STS_ERROR_PERM_REVOKE_BY_USER; - break; - default: - stsCode = STS_ERROR_INNER; - break; - } - ACCESSTOKEN_LOG_ERROR(LABEL, "Dialog error(%{public}d) stsCode(%{public}d).", errorCode, stsCode); - return stsCode; -} - -static ani_ref RequestPermissionOnSettingComplete( - ani_env* env, std::shared_ptr& asyncContext) -{ - if (asyncContext->result.errorCode == RET_SUCCESS) { - ani_ref result = ReturnResult(env, asyncContext); - if (result != nullptr) { - return result; - } - asyncContext->result.errorCode = RET_FAILED; - } - - int32_t stsCode = TransferToStsErrorCode(asyncContext->result.errorCode); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); - return nullptr; -} - -PermissonOnSettingUICallback::PermissonOnSettingUICallback(ani_env* env, - const std::shared_ptr& reqContext) -{ - this->env_ = env; - this->reqContext_ = reqContext; -} - -PermissonOnSettingUICallback::~PermissonOnSettingUICallback() -{} - -void PermissonOnSettingUICallback::SetSessionId(int32_t sessionId) -{ - this->sessionId_ = sessionId; -} - -static void CloseSettingModalUIExtensionMainThread(std::shared_ptr& asyncContext, - int32_t sessionId) -{ - auto task = [asyncContext, sessionId]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); - asyncContext->result.errorCode = RET_FAILED; - return; - } - uiContent->CloseModalUIExtension(sessionId); - ACCESSTOKEN_LOG_INFO(LABEL, "Close end, sessionId: %{public}d", sessionId); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread"); - } else { - task(); - } -#else - task(); -#endif -} - -void PermissonOnSettingUICallback::ReleaseHandler(int32_t code) -{ - { - std::lock_guard lock(this->lockReleaseFlag); - if (this->releaseFlag) { - ACCESSTOKEN_LOG_WARN(LABEL, "Callback has executed."); - return; - } - this->releaseFlag = true; - } - CloseSettingModalUIExtensionMainThread(this->reqContext_, this->sessionId_); - if (code == -1) { - this->reqContext_->result.errorCode = code; - } - this->reqContext_->loadlock.unlock(); - std::lock_guard lock(g_lockWindowFlag); - g_windowFlag = false; -} - -/* - * when UIExtensionAbility use terminateSelfWithResult - */ -void PermissonOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result) -{ - 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, listSize=%{public}zu.", - resultCode, this->reqContext_->stateList.size()); - ReleaseHandler(0); -} - -/* - * when UIExtensionAbility send message to UIExtensionComponent - */ -void PermissonOnSettingUICallback::OnReceive(const AAFwk::WantParams& receive) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "Called!"); -} - -/* - * when UIExtensionAbility disconnect or use terminate or process die - * releaseCode is 0 when process normal exit - */ -void PermissonOnSettingUICallback::OnRelease(int32_t releaseCode) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "ReleaseCode is %{public}d", releaseCode); - - ReleaseHandler(-1); -} - -/* - * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error - */ -void PermissonOnSettingUICallback::OnError(int32_t code, const std::string& name, const std::string& message) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "Code is %{public}d, name is %{public}s, message is %{public}s", - code, name.c_str(), message.c_str()); - - ReleaseHandler(-1); -} - -/* - * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init, - * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy - */ -void PermissonOnSettingUICallback::OnRemoteReady(const std::shared_ptr& uiProxy) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "Connect to UIExtensionAbility successfully."); -} - -/* - * when UIExtensionComponent destructed - */ -void PermissonOnSettingUICallback::OnDestroy() -{ - ACCESSTOKEN_LOG_INFO(LABEL, "UIExtensionAbility destructed."); - ReleaseHandler(-1); -} - -static void CreateSettingUIExtensionMainThread(std::shared_ptr& asyncContext, - const AAFwk::Want& want, const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, - const std::shared_ptr& uiExtCallback) -{ - auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to get ui content!"); - asyncContext->result.errorCode = RET_FAILED; - return; - } - - Ace::ModalUIExtensionConfig config; - config.isProhibitBack = true; - int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); - ACCESSTOKEN_LOG_INFO(LABEL, "Create end, sessionId: %{public}d, tokenId: %{public}d.", - sessionId, asyncContext->tokenId); - if (sessionId == 0) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create component, sessionId is 0."); - asyncContext->result.errorCode = RET_FAILED; - return; - } - uiExtCallback->SetSessionId(sessionId); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); - } else { - task(); - } -#else - task(); -#endif -} - -static bool StartUIExtension(ani_env* env, std::shared_ptr& asyncContext) -{ - AccessTokenKit::GetPermissionManagerInfo(asyncContext->info); - - OHOS::AAFwk::Want want; - want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.permStateAbilityName); - want.SetParam(PERMISSION_SETTING_KEY, asyncContext->permissionList); - want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); - - auto uiExtCallback = std::make_shared(env, asyncContext); - Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { - [uiExtCallback](int32_t releaseCode) { - uiExtCallback->OnRelease(releaseCode); - }, - [uiExtCallback](int32_t resultCode, const AAFwk::Want& result) { - uiExtCallback->OnResult(resultCode, result); - }, - [uiExtCallback](const AAFwk::WantParams& receive) { - uiExtCallback->OnReceive(receive); - }, - [uiExtCallback](int32_t code, const std::string& name, [[maybe_unused]] const std::string& message) { - uiExtCallback->OnError(code, name, name); - }, - [uiExtCallback](const std::shared_ptr& uiProxy) { - uiExtCallback->OnRemoteReady(uiProxy); - }, - [uiExtCallback]() { - uiExtCallback->OnDestroy(); - }, - }; - - { - std::lock_guard lock(g_lockWindowFlag); - if (g_windowFlag) { - ACCESSTOKEN_LOG_WARN(LABEL, "The request already exists."); - 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.errorCode == RET_FAILED) { - { - std::lock_guard lock(g_lockWindowFlag); - g_windowFlag = false; - return false; - } - } - return true; -} - -static ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, - [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList) -{ - if (env == nullptr || permissionList == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null"); - return nullptr; - } - - std::shared_ptr asyncContext = - std::make_shared(); - if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, asyncContext)) { - return nullptr; - } - - static AccessTokenID selfTokenID = static_cast(GetSelfTokenID()); - if (selfTokenID != asyncContext->tokenId) { - ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID %{public}d is not same with selfTokenID %{public}d.", - asyncContext->tokenId, selfTokenID); - 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(); - bool flag = StartUIExtension(env, asyncContext); - if (!flag) { - asyncContext->loadlock.unlock(); - } - asyncContext->loadlock.lock(); - ani_ref result = RequestPermissionOnSettingComplete(env, asyncContext); - asyncContext->loadlock.unlock(); - return result; -} - -static bool IsPermissionFlagValid(uint32_t flag) -{ - return (flag == PermissionFlag::PERMISSION_USER_SET) || (flag == PermissionFlag::PERMISSION_USER_FIXED) || - (flag == PermissionFlag::PERMISSION_ALLOW_THIS_TIME); -}; - -static void RevokeUserGrantedPermissionExecute([[maybe_unused]] ani_env* env, - [[maybe_unused]] ani_object object, ani_int tokenID, ani_string permissionName, ani_int permissionFlags) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "RevokeUserGrantedPermission begin."); - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "env null."); - return; - } - - std::string permissionNameString; - if (!AniParseString(env, permissionName, permissionNameString)) { - BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, - GetParamErrorMsg("permissionName", "Permissions")); - return; - } - - if (!IsPermissionFlagValid(static_cast (permissionFlags))) { - std::string errMsg = GetErrorMessage(STS_ERROR_PARAM_INVALID, "The permissionFlags is invalid."); - BusinessErrorAni::ThrowError(env, STS_ERROR_PARAM_INVALID, errMsg); - return; - } - - 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) { - 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; - } - - int32_t ret = AccessTokenKit::RevokePermission(tokenID, permissionNameString, permissionFlags); - if (ret != RET_SUCCESS) { - int32_t stsCode = BusinessErrorAni::GetStsErrorCode(ret); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); - } -} - -static ani_int GetVersionExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "getVersionExecute begin."); - uint32_t version = -1; - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "env null"); - return version; - } - - int32_t result = AccessTokenKit::GetVersion(version); - if (result != RET_SUCCESS) { - int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); - return version; - } - return version; -} - -static ani_ref GetPermissionsStatusExecute([[maybe_unused]] ani_env* env, - [[maybe_unused]] ani_object object, ani_int tokenID, ani_array_ref permissionList) -{ - ACCESSTOKEN_LOG_INFO(LABEL, "GetPermissionsStatusExecute begin."); - if ((env == nullptr) || (permissionList == nullptr)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null."); - return nullptr; - } - std::vector aniPermissionList; - if (!AniParseStringArray(env, permissionList, aniPermissionList)) { - BusinessErrorAni::ThrowParameterTypeError( - env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("permissionList", "Array")); - return nullptr; - } - - if (aniPermissionList.empty()) { - std::string errMsg = GetErrorMessage(STS_ERROR_INNER, "The permissionList is empty."); - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STS_ERROR_INNER)); - return nullptr; - } - - std::vector permList; - for (const auto& permission : aniPermissionList) { - PermissionListState permState; - permState.permissionName = permission; - permState.state = INVALID_OPER; - permList.emplace_back(permState); - } - - int32_t result = RET_SUCCESS; - std::vector permissionQueryResults; - result = AccessTokenKit::GetPermissionsStatus(tokenID, permList); - if (result != RET_SUCCESS) { - int32_t stsCode = BusinessErrorAni::GetStsErrorCode(result); - BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); - return nullptr; - } - for (const auto& permState : permList) { - permissionQueryResults.emplace_back(permState.state); - } - - return ConvertAniArrayInt(env, permissionQueryResults); -} - -extern "C" { -ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) -{ - if (vm == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm"); - return ANI_INVALID_ARGS; - } - ani_env* env; - if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Unsupported ANI_VERSION_1"); - return ANI_OUT_OF_MEMORY; - } - if (env == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); - return ANI_NOT_FOUND; - } - const char* spaceName = "L@ohos/abilityAccessCtrl/abilityAccessCtrl;"; - ani_namespace spc; - if (ANI_OK != env->FindNamespace(spaceName, &spc)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", spaceName); - return ANI_NOT_FOUND; - } - std::array methods = { - ani_native_function { "createAtManager", nullptr, reinterpret_cast(CreateAtManager) }, - }; - if (ANI_OK != env->Namespace_BindNativeFunctions(spc, methods.data(), methods.size())) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", spaceName); - return ANI_ERROR; - }; - const char* className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; - ani_class cls; - if (ANI_OK != env->FindClass(className, &cls)) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); - return ANI_ERROR; - } - std::array claMethods = { - ani_native_function { - "checkAccessTokenExecute", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, - ani_native_function { "requestPermissionsFromUserExecute", - "Lapplication/Context/Context;Lescompat/Array;:Lsecurity/PermissionRequestResult/PermissionRequestResult;", - reinterpret_cast(RequestPermissionsFromUserExecute) }, - ani_native_function { "requestPermissionOnSettingExecute", - "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) }, - }; - if (ANI_OK != env->Class_BindNativeMethods(cls, claMethods.data(), claMethods.size())) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className); - return ANI_ERROR; - }; - *result = ANI_VERSION_1; - return ANI_OK; -} -} -} // namespace AccessToken -} // namespace Security -} // namespace OHOS \ No newline at end of file +} // namespace AccessToken +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp new file mode 100644 index 000000000..9e4241c21 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ani_request_permission_on_setting.h" +#include "ani_base_context.h" +#include "accesstoken_kit.h" +#include "accesstoken_log.h" +#include "token_setproc.h" +#include "want.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniRequestPermission" }; +std::mutex g_lockWindowFlag; +bool g_windowFlag = false; +constexpr int32_t REQUEST_REALDY_EXIST = 1; +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; +const std::string PERMISSION_SETTING_KEY = "ohos.user.setting.permission"; +const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; +const std::string UI_EXTENSION_TYPE = "sys/commonUI"; +const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code"; +const std::string PERMISSION_RESULT_KEY = "ohos.user.setting.permission.result"; +} +static ani_status GetContext( + ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) +{ + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); + if (context == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetStageModeContext failed"); + return ANI_ERROR; + } + asyncContext->abilityContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->abilityContext != nullptr) { + auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); + if (abilityInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); + return ANI_ERROR; + } + asyncContext->uiAbilityFlag = true; + asyncContext->tokenId = abilityInfo->accessTokenId; + } else { + asyncContext->uiExtensionContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->uiExtensionContext == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertTo UIExtensionContext failed"); + return ANI_ERROR; + } + auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); + if (uiExtensionInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetApplicationInfo failed"); + return ANI_ERROR; + } + asyncContext->tokenId = uiExtensionInfo->accessTokenId; + } + return ANI_OK; +} + +static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext, ani_array_ref& permissionList, + std::shared_ptr& asyncContext) +{ + if (GetContext(env, aniContext, asyncContext) != ANI_OK) { + 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, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("permissionList", "Array")); + return false; + } + return true; +} + +static void StateToEnumIndex(int32_t state, ani_size& enumIndex) +{ + if (state == 0) { + enumIndex = 1; + } else { + enumIndex = 0; + } +} + +static ani_ref ReturnResult(ani_env* env, std::shared_ptr& asyncContext) +{ + ani_class arrayCls = nullptr; + if (env->FindClass("Lescompat/Array;", &arrayCls) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name Lescompat/Array failed!"); + return nullptr; + } + + ani_method arrayCtor; + if (env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass failed!"); + return nullptr; + } + + ani_object arrayObj; + if (env->Object_New(arrayCls, arrayCtor, &arrayObj, asyncContext->stateList.size()) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object new failed!"); + return nullptr; + } + + const char* enumDescriptor = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/GrantStatus;"; + ani_enum enumType; + if (env->FindEnum(enumDescriptor, &enumType) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass name %{public}s failed!", enumDescriptor); + return nullptr; + } + + ani_size index = 0; + for (const auto& state: asyncContext->stateList) { + ani_enum_item enumItem; + ani_size enumIndex = 0; + StateToEnumIndex(state, enumIndex); + if (env->Enum_GetEnumItemByIndex(enumType, enumIndex, &enumItem) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetEnumItemByIndex value %{public}u failed!", state); + break; + } + + if (env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, enumItem) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethodByName_Void $_set failed!"); + break; + } + index++; + } + + return arrayObj; +} + +static int32_t TransferToStsErrorCode(int32_t errorCode) +{ + int32_t stsCode = STS_OK; + switch (errorCode) { + case RET_SUCCESS: + stsCode = STS_OK; + break; + case REQUEST_REALDY_EXIST: + stsCode = STS_ERROR_REQUEST_IS_ALREADY_EXIST; + break; + case PERM_NOT_BELONG_TO_SAME_GROUP: + stsCode = STS_ERROR_PARAM_INVALID; + break; + case PERM_IS_NOT_DECLARE: + stsCode = STS_ERROR_PARAM_INVALID; + break; + case ALL_PERM_GRANTED: + stsCode = STS_ERROR_ALL_PERM_GRANTED; + break; + case PERM_REVOKE_BY_USER: + stsCode = STS_ERROR_PERM_REVOKE_BY_USER; + break; + default: + stsCode = STS_ERROR_INNER; + break; + } + ACCESSTOKEN_LOG_ERROR(LABEL, "Dialog error(%{public}d) stsCode(%{public}d).", errorCode, stsCode); + return stsCode; +} + +static ani_ref RequestPermissionOnSettingComplete( + ani_env* env, std::shared_ptr& asyncContext) +{ + if (asyncContext->result.errorCode == RET_SUCCESS) { + ani_ref result = ReturnResult(env, asyncContext); + if (result != nullptr) { + return result; + } + asyncContext->result.errorCode = RET_FAILED; + } + + int32_t stsCode = TransferToStsErrorCode(asyncContext->result.errorCode); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + return nullptr; +} + +PermissonOnSettingUICallback::PermissonOnSettingUICallback(ani_env* env, + const std::shared_ptr& reqContext) +{ + this->env_ = env; + this->reqContext_ = reqContext; +} + +PermissonOnSettingUICallback::~PermissonOnSettingUICallback() +{} + +void PermissonOnSettingUICallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +static OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr& abilityContext, + std::shared_ptr& uiExtensionContext, bool uiAbilityFlag) +{ + OHOS::Ace::UIContent* uiContent = nullptr; + if (uiAbilityFlag) { + if (abilityContext == nullptr) { + return nullptr; + } + uiContent = abilityContext->GetUIContent(); + } else { + if (uiExtensionContext == nullptr) { + return nullptr; + } + uiContent = uiExtensionContext->GetUIContent(); + } + return uiContent; +} + +static void CloseSettingModalUIExtensionMainThread(std::shared_ptr& asyncContext, + int32_t sessionId) +{ + auto task = [asyncContext, sessionId]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + if (uiContent == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); + asyncContext->result.errorCode = RET_FAILED; + return; + } + uiContent->CloseModalUIExtension(sessionId); + ACCESSTOKEN_LOG_INFO(LABEL, "Close end, sessionId: %{public}d", sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +void PermissonOnSettingUICallback::ReleaseHandler(int32_t code) +{ + { + std::lock_guard lock(this->lockReleaseFlag); + if (this->releaseFlag) { + ACCESSTOKEN_LOG_WARN(LABEL, "Callback has executed."); + return; + } + this->releaseFlag = true; + } + CloseSettingModalUIExtensionMainThread(this->reqContext_, this->sessionId_); + if (code == -1) { + this->reqContext_->result.errorCode = code; + } + this->reqContext_->loadlock.unlock(); + std::lock_guard lock(g_lockWindowFlag); + g_windowFlag = false; +} + +/* + * when UIExtensionAbility use terminateSelfWithResult + */ +void PermissonOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result) +{ + 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, listSize=%{public}zu.", + resultCode, this->reqContext_->stateList.size()); + ReleaseHandler(0); +} + +/* + * when UIExtensionAbility send message to UIExtensionComponent + */ +void PermissonOnSettingUICallback::OnReceive(const AAFwk::WantParams& receive) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Called!"); +} + +/* + * when UIExtensionAbility disconnect or use terminate or process die + * releaseCode is 0 when process normal exit + */ +void PermissonOnSettingUICallback::OnRelease(int32_t releaseCode) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "ReleaseCode is %{public}d", releaseCode); + + ReleaseHandler(-1); +} + +/* + * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error + */ +void PermissonOnSettingUICallback::OnError(int32_t code, const std::string& name, const std::string& message) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Code is %{public}d, name is %{public}s, message is %{public}s", + code, name.c_str(), message.c_str()); + + ReleaseHandler(-1); +} + +/* + * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init, + * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy + */ +void PermissonOnSettingUICallback::OnRemoteReady(const std::shared_ptr& uiProxy) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "Connect to UIExtensionAbility successfully."); +} + +/* + * when UIExtensionComponent destructed + */ +void PermissonOnSettingUICallback::OnDestroy() +{ + ACCESSTOKEN_LOG_INFO(LABEL, "UIExtensionAbility destructed."); + ReleaseHandler(-1); +} + +static void CreateSettingUIExtensionMainThread(std::shared_ptr& asyncContext, + const AAFwk::Want& want, const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, + const std::shared_ptr& uiExtCallback) +{ + auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + if (uiContent == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to get ui content!"); + asyncContext->result.errorCode = RET_FAILED; + return; + } + + Ace::ModalUIExtensionConfig config; + config.isProhibitBack = true; + int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); + ACCESSTOKEN_LOG_INFO(LABEL, "Create end, sessionId: %{public}d, tokenId: %{public}d.", + sessionId, asyncContext->tokenId); + if (sessionId == 0) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create component, sessionId is 0."); + asyncContext->result.errorCode = RET_FAILED; + return; + } + uiExtCallback->SetSessionId(sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +static bool StartUIExtension(ani_env* env, std::shared_ptr& asyncContext) +{ + AccessTokenKit::GetPermissionManagerInfo(asyncContext->info); + + OHOS::AAFwk::Want want; + want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.permStateAbilityName); + want.SetParam(PERMISSION_SETTING_KEY, asyncContext->permissionList); + want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); + + auto uiExtCallback = std::make_shared(env, asyncContext); + Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { + [uiExtCallback](int32_t releaseCode) { + uiExtCallback->OnRelease(releaseCode); + }, + [uiExtCallback](int32_t resultCode, const AAFwk::Want& result) { + uiExtCallback->OnResult(resultCode, result); + }, + [uiExtCallback](const AAFwk::WantParams& receive) { + uiExtCallback->OnReceive(receive); + }, + [uiExtCallback](int32_t code, const std::string& name, [[maybe_unused]] const std::string& message) { + uiExtCallback->OnError(code, name, name); + }, + [uiExtCallback](const std::shared_ptr& uiProxy) { + uiExtCallback->OnRemoteReady(uiProxy); + }, + [uiExtCallback]() { + uiExtCallback->OnDestroy(); + }, + }; + + { + std::lock_guard lock(g_lockWindowFlag); + if (g_windowFlag) { + ACCESSTOKEN_LOG_WARN(LABEL, "The request already exists."); + 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.errorCode == RET_FAILED) { + { + std::lock_guard lock(g_lockWindowFlag); + g_windowFlag = false; + return false; + } + } + return true; +} + +ani_ref RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList) +{ + if (env == nullptr || permissionList == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null"); + return nullptr; + } + + std::shared_ptr asyncContext = + std::make_shared(); + if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, asyncContext)) { + return nullptr; + } + + static AccessTokenID selfTokenID = static_cast(GetSelfTokenID()); + if (selfTokenID != asyncContext->tokenId) { + ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID %{public}d is not same with selfTokenID %{public}d.", + asyncContext->tokenId, selfTokenID); + 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(); + bool flag = StartUIExtension(env, asyncContext); + if (!flag) { + asyncContext->loadlock.unlock(); + } + asyncContext->loadlock.lock(); + ani_ref result = RequestPermissionOnSettingComplete(env, asyncContext); + asyncContext->loadlock.unlock(); + return result; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/common/include/ani_utils.h b/frameworks/ets/ani/common/include/ani_utils.h index f86989e11..f7dbea07a 100644 --- a/frameworks/ets/ani/common/include/ani_utils.h +++ b/frameworks/ets/ani/common/include/ani_utils.h @@ -54,6 +54,12 @@ bool IsCurrentThread(std::thread::id threadId); bool AniIsCallbackRefEqual(ani_env* env, const ani_ref& compareRef, const ani_ref& targetRref, std::thread::id threadId, bool& isEqual); bool AniFunctionalObjectCall(ani_env *env, const ani_fn_object& fn, ani_size size, ani_ref* argv, ani_ref& result); +bool ProcessArrayString([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_array_ref arrayObj, std::vector& permissionList); +std::string ANIUtils_ANIStringToStdString(ani_env* env, ani_string ani_str); +ani_ref ConvertAniArrayBool(ani_env* env, const std::vector& cArray); +ani_ref ConvertAniArrayInt(ani_env* env, const std::vector& cArray); +ani_ref ConvertAniArrayString(ani_env* env, const std::vector& cArray); } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/frameworks/ets/ani/common/src/ani_error.cpp b/frameworks/ets/ani/common/src/ani_error.cpp index 29dfc88f2..d3c26b748 100644 --- a/frameworks/ets/ani/common/src/ani_error.cpp +++ b/frameworks/ets/ani/common/src/ani_error.cpp @@ -33,7 +33,7 @@ static const std::unordered_map g_errorStringMap = { { 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_TERMINATE_FAIL, "Ui extension terminate failed." }, + { STS_ERROR_TERMINATE_FAIL, "UI extension terminate failed." }, { 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." }, diff --git a/frameworks/ets/ani/common/src/ani_utils.cpp b/frameworks/ets/ani/common/src/ani_utils.cpp index 22200802f..ede5621da 100644 --- a/frameworks/ets/ani/common/src/ani_utils.cpp +++ b/frameworks/ets/ani/common/src/ani_utils.cpp @@ -264,6 +264,124 @@ bool AniFunctionalObjectCall(ani_env *env, const ani_fn_object& fn, ani_size siz } return true; } + +ani_ref ConvertAniArrayString(ani_env* env, const std::vector& cArray) +{ + ani_size length = cArray.size(); + ani_array_ref aArrayRef = nullptr; + ani_class aStringcls = nullptr; + if (env->FindClass("Lstd/core/String;", &aStringcls) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString FindClass String failed"); + return nullptr; + } + ani_ref undefinedRef = nullptr; + if (ANI_OK != env->GetUndefined(&undefinedRef)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString GetUndefined failed"); + return nullptr; + } + if (env->Array_New_Ref(aStringcls, length, undefinedRef, &aArrayRef) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString Array_New_Ref failed "); + return nullptr; + } + ani_string aString = nullptr; + for (ani_size i = 0; i < length; ++i) { + env->String_NewUTF8(cArray[i].c_str(), cArray[i].size(), &aString); + env->Array_Set_Ref(aArrayRef, i, aString); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayRef, &aRef) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayString GlobalReference_Create failed "); + return nullptr; + } + return aRef; +} + +ani_ref ConvertAniArrayInt(ani_env* env, const std::vector& cArray) +{ + ani_size length = cArray.size(); + ani_array_int aArrayInt = nullptr; + if (env->Array_New_Int(length, &aArrayInt) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayInt Array_New_Int failed "); + return nullptr; + } + for (ani_size i = 0; i < length; ++i) { + env->Array_SetRegion_Int(aArrayInt, i, length, &cArray[i]); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayInt, &aRef) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayInt GlobalReference_Create failed "); + return nullptr; + } + return aRef; +} + +ani_ref ConvertAniArrayBool(ani_env* env, const std::vector& cArray) +{ + ani_size length = cArray.size(); + ani_array_boolean aArrayBool = nullptr; + if (env->Array_New_Boolean(length, &aArrayBool) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayBool Array_New_Boolean failed "); + return nullptr; + } + std::vector boolArray(length); + for (ani_size i = 0; i < length; ++i) { + boolArray[i] = cArray[i]; + } + for (ani_size i = 0; i < length; ++i) { + env->Array_SetRegion_Boolean(aArrayBool, i, length, &boolArray[i]); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayBool, &aRef) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertAniArrayBool GlobalReference_Create failed "); + return nullptr; + } + return aRef; +} + +std::string ANIUtils_ANIStringToStdString(ani_env* env, ani_string ani_str) +{ + ani_size strSize; + if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8Size error"); + return ""; + } + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + if (env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8 error"); + return ""; + } + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +bool ProcessArrayString([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_array_ref arrayObj, std::vector& permissionList) +{ + ani_size length; + if (ANI_OK != env->Array_GetLength(arrayObj, &length)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Array_GetLength FAILED"); + return false; + } + for (ani_size i = 0; i < length; i++) { + ani_ref stringEntryRef; + if (ANI_OK != env->Object_CallMethodByName_Ref( + arrayObj, "$_get", "I:Lstd/core/Object;", &stringEntryRef, static_cast(i))) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethodByName_Ref _get Failed"); + return false; + } + auto strEntryRef = ANIUtils_ANIStringToStdString(env, static_cast(stringEntryRef)); + if (strEntryRef.empty()) { + return false; + } else { + permissionList.emplace_back(strEntryRef); + } + } + return true; +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets index b53beac77..397fb054a 100644 --- a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets +++ b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets @@ -29,13 +29,13 @@ export default namespace privacyManager { NORMAL_TYPE = 0, PICKER_TYPE = 1, SECURITY_COMPONENT_TYPE = 2 - } + }; enum PermissionActiveStatus { PERM_INACTIVE = 0, PERM_ACTIVE_IN_FOREGROUND = 1, PERM_ACTIVE_IN_BACKGROUND = 2 - } + }; enum STSErrorCode { STS_OK = 0, @@ -43,7 +43,7 @@ export default namespace privacyManager { STS_ERROR_NOT_SYSTEM_APP = 202, STS_ERROR_PARAM_ILLEGAL = 401, STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT = 801, - } ; + }; interface AddPermissionUsedRecordOptions { usedType?: PermissionUsedType; @@ -103,8 +103,10 @@ export default namespace privacyManager { let usedTypeTemp : PermissionUsedType|undefined = options ? options.usedType : PermissionUsedType.NORMAL_TYPE; let optionsLocal: AddPermissionUsedRecordOptionsInner = { usedType: usedTypeTemp }; let p = new Promise((resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { - let p1 = taskpool.execute((): void => { return new PrivacyManagerInner().addPermissionUsedRecordSync( - tokenID, permissionName, successCount, failCount, optionsLocal) }); + let p1 = taskpool.execute((): void => { + return new PrivacyManagerInner().addPermissionUsedRecordSync( + tokenID, permissionName, successCount, failCount, optionsLocal) + }); p1.then(() => { resolve(undefined); }).catch((err: BusinessError): void => { -- Gitee