From adb37a70d92a5862d31796a34cad1b0f57b6f475 Mon Sep 17 00:00:00 2001 From: chennian Date: Wed, 4 Jun 2025 15:24:58 +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: I1fdd835b57690a81b5964baa2f1473d275492f4d --- frameworks/ets/ani/accesstoken/BUILD.gn | 7 +- .../ets/@ohos.abilityAccessCtrl.ets | 108 +- .../include/ani_ability_access_ctrl.h | 54 + .../ets/ani/accesstoken/include/ani_common.h | 35 + ...access_ctrl.h => ani_request_permission.h} | 130 +- .../ani_request_permission_on_setting.h | 103 ++ .../src/ani_ability_access_ctrl.cpp | 338 +++++ .../ets/ani/accesstoken/src/ani_common.cpp | 91 ++ ...ss_ctrl.cpp => ani_request_permission.cpp} | 1237 +++-------------- .../src/ani_request_permission_on_setting.cpp | 586 ++++++++ frameworks/ets/ani/common/BUILD.gn | 2 +- ...t.ets => PermissionRequestResult copy.ets} | 0 frameworks/ets/ani/common/include/ani_error.h | 4 +- frameworks/ets/ani/common/include/ani_utils.h | 6 + frameworks/ets/ani/common/src/ani_error.cpp | 8 +- frameworks/ets/ani/common/src/ani_utils.cpp | 141 +- frameworks/ets/ani/privacy/BUILD.gn | 1 + .../ani/privacy/ets/@ohos.privacyManager.ets | 14 +- .../ets/ani/privacy/src/privacy_manager.cpp | 8 +- .../napi_request_permission_on_setting.cpp | 2 +- tools/accesstoken/src/atm_command.cpp | 2 +- 21 files changed, 1648 insertions(+), 1229 deletions(-) create mode 100644 frameworks/ets/ani/accesstoken/include/ani_ability_access_ctrl.h create mode 100644 frameworks/ets/ani/accesstoken/include/ani_common.h rename frameworks/ets/ani/accesstoken/include/{ability_access_ctrl.h => ani_request_permission.h} (49%) 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 create mode 100644 frameworks/ets/ani/accesstoken/src/ani_common.cpp rename frameworks/ets/ani/accesstoken/src/{ability_access_ctrl.cpp => ani_request_permission.cpp} (36%) create mode 100644 frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp rename frameworks/ets/ani/common/ets/security/{PermissionRequestResult.ets => PermissionRequestResult copy.ets} (100%) diff --git a/frameworks/ets/ani/accesstoken/BUILD.gn b/frameworks/ets/ani/accesstoken/BUILD.gn index 6fe0a6561..663bff258 100644 --- a/frameworks/ets/ani/accesstoken/BUILD.gn +++ b/frameworks/ets/ani/accesstoken/BUILD.gn @@ -31,7 +31,12 @@ 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_common.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..695c7fbdf 100644 --- a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -16,19 +16,28 @@ import { AsyncCallback, Callback, BusinessError } from '@ohos.base'; import { Permissions } from 'permissions'; import type _PermissionRequestResult from 'security.PermissionRequestResult'; -import Context from 'application.Context' -import hilog from '@ohos.hilog'; +import Context from 'application.Context'; function PARAM_ERROR_MSG(param: string, type: string): string { return `Parameter Error. The type of "${param}" must be ${type}.`; } export { Permissions }; - export type PermissionRequestResult = _PermissionRequestResult; -export default namespace abilityAccessCtrl { +class AsyncCallbackWrapper { + private myFun_: AsyncCallback = (err: BusinessError, data: T) => {} + constructor(myFun: AsyncCallback) { + this.myFun_ = myFun; + } + + invoke(err: BusinessError, data: T) : void { + this.myFun_(err, data); + } +} + +export default namespace abilityAccessCtrl { loadLibrary("accesstoken_ani.z"); export enum GrantStatus { PERMISSION_DENIED = -1, @@ -71,7 +80,7 @@ export default namespace abilityAccessCtrl { 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) { let err = new BusinessError(); @@ -91,9 +100,10 @@ export default namespace abilityAccessCtrl { native function createAtManager(): AtManager; interface AtManager { checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; - requestPermissionsFromUserExecute( - context: Context, permissionList: Array): PermissionRequestResult; - requestPermissionOnSettingExecute(context: Context, permissionList: Array): Array; + requestPermissionsFromUserExecute(context: Context, permissionList: Array, + callback: AsyncCallbackWrapper): void; + requestPermissionOnSettingExecute( + context: Context, permissionList: Array, callback: AsyncCallbackWrapper>): void; revokeUserGrantedPermissionExecute(tokenID: int, permissionName: Permissions, permissionFlags: int): void; getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; getVersionExecute(): int; @@ -126,10 +136,10 @@ export default namespace abilityAccessCtrl { class AtManagerInner implements AtManager { native checkAccessTokenExecute(tokenID: int, permissionName: Permissions): int; - native requestPermissionsFromUserExecute( - context: Context, permissionList: Array): PermissionRequestResult; - native requestPermissionOnSettingExecute( - context: Context, permissionList: Array): Array; + native requestPermissionsFromUserExecute(context: Context, permissionList: Array, + callback: AsyncCallbackWrapper): void; + native requestPermissionOnSettingExecute(context: Context, permissionList: Array, + callback: AsyncCallbackWrapper>): void; native revokeUserGrantedPermissionExecute( tokenID: int, permissionName: Permissions, permissionFlags: int): void; native getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; @@ -169,78 +179,56 @@ export default namespace abilityAccessCtrl { p1.then((e: NullishType) => { resolve(e as GrantStatus); }).catch((err: BusinessError): void => { - resolve(GrantStatus.PERMISSION_DENIED); + reject(err); }); }); return p; } requestPermissionsFromUser(context: Context, permissionList: Array, - callback:AsyncCallback): void { + requestCallback: AsyncCallback): void { validateRequestParams(context, permissionList); - 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(); - let retError = new BusinessError(); - callback(retError, result as PermissionRequestResult); - } catch (err: BusinessError) { - work.join(); - const defaultResult: PermissionRequestResult = {}; - callback(err, defaultResult); - } - }; - fun(); + let callbackWrap = new AsyncCallbackWrapper(requestCallback); + taskpool.execute((): void => { + new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList, callbackWrap); + }) } requestPermissionsFromUser(context: Context, permissionList: Array): Promise { validateRequestParams(context, permissionList); - - let p = new Promise(( + let p: Promise = 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(); + let callbackWrap = new AsyncCallbackWrapper(( + err: BusinessError, data: PermissionRequestResult)=>{ + if (err.code == 0) { + resolve(data); + } else { reject(err); } - }; - fun(); + }); + taskpool.execute((): void => { + new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList, callbackWrap); + }); }); return p; } requestPermissionOnSetting(context: Context, permissionList: Array): Promise> { validateRequestParams(context, permissionList); - let p = new Promise>(( + let p: Promise> = new Promise>(( resolve: (v: Array) => void, reject: (error: BusinessError) => void) => { - let func = async() => { - let work = new EAWorker(); - try { - 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(); + let callbackWrap = new AsyncCallbackWrapper>(( + err: BusinessError, data: Array)=>{ + if (err.code == 0) { + resolve(data); + } else { reject(err); } - }; - func(); + }); + taskpool.execute((): void => { + new AtManagerInner().requestPermissionOnSettingExecute(context, permissionList, callbackWrap); + }); }); 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/ani_common.h b/frameworks/ets/ani/accesstoken/include/ani_common.h new file mode 100644 index 000000000..0404544b1 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/include/ani_common.h @@ -0,0 +1,35 @@ +/* + * 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 INTERFACES_ETS_ANI_COMMON_H +#define INTERFACES_ETS_ANI_COMMON_H + +#include "ability_context.h" +#include "ani.h" +#include "ani_base_context.h" +#include "ui_content.h" +#include "ui_extension_context.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +ani_env* GetCurrentEnv(ani_vm* vm); +bool ExecuteAsyncCallback(ani_env* env, ani_object callback, ani_object error, ani_object result); +OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr& abilityContext, + std::shared_ptr& uiExtensionContext, bool uiAbilityFlag); +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif /* INTERFACES_ETS_ANI_COMMON_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 49% rename from frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h rename to frameworks/ets/ani/accesstoken/include/ani_request_permission.h index e3ac10ad3..c6c406499 100644 --- a/frameworks/ets/ani/accesstoken/include/ability_access_ctrl.h +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission.h @@ -12,67 +12,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef ANI_REQUEST_PERMISSION_H +#define ANI_REQUEST_PERMISSION_H -#ifndef ABILITY_ACCESS_CTRL_H -#define ABILITY_ACCESS_CTRL_H - -#include -#include -#include -#include - -#include "ability.h" -#include "ability_manager_client.h" +#include #include "access_token.h" #include "ani.h" +#include "ani_common.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" -#include "ui_extension_context.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; -}; - -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 { + virtual ~RequestAsyncContext(); AccessTokenID tokenId = 0; std::string bundleName; bool needDynamicRequest = true; @@ -81,13 +41,12 @@ struct RequestAsyncContext { std::vector permissionList; std::vector grantResults; std::vector permissionsState; - ani_object requestResult = nullptr; std::vector dialogShownResults; std::vector permissionQueryResults; std::vector errorReasons; Security::AccessToken::PermissionGrantInfo info; - std::shared_ptr abilityContext; - std::shared_ptr uiExtensionContext; + std::shared_ptr abilityContext; + std::shared_ptr uiExtensionContext; bool uiAbilityFlag = false; bool uiExtensionFlag = false; bool uiContentFlag = false; @@ -96,6 +55,11 @@ struct RequestAsyncContext { #ifdef EVENTHANDLER_ENABLE std::shared_ptr handler_ = nullptr; #endif + std::thread::id threadId; + ani_vm* vm = nullptr; + ani_env* env = nullptr; + ani_object callback = nullptr; + ani_ref callbackRef = nullptr; }; class UIExtensionCallback { @@ -122,7 +86,7 @@ public: virtual ~AuthorizationResult() override = default; virtual void GrantResultsCallback( - const std::vector& permissionList, const std::vector& grantResults) override; + const std::vector& permissionList, const std::vector& grantResults) override; virtual void WindowShownCallback() override; private: @@ -131,7 +95,7 @@ private: class RequestAsyncInstanceControl { public: - static bool AddCallbackByInstanceId(std::shared_ptr& asyncContext); + static void AddCallbackByInstanceId(std::shared_ptr& asyncContext); static void ExecCallback(int32_t id); static void CheckDynamicRequest(std::shared_ptr& asyncContext, bool& isDynamic); @@ -147,59 +111,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_; +void RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_object aniContext, ani_array_ref permissionList, ani_object callback); } // 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..42ff56551 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h @@ -0,0 +1,103 @@ +/* + * 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 "access_token.h" +#include "ani.h" +#include "ani_common.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" + +namespace OHOS { +namespace Security { +namespace AccessToken { +struct RequestPermOnSettingAsyncContext { + AccessTokenID tokenId = 0; + AtmResult result; + PermissionGrantInfo info; + + int32_t instanceId = -1; + bool isDynamic = true; + std::vector permissionList; + ani_object 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 + std::thread::id threadId; + ani_vm* vm = nullptr; + ani_env* env = nullptr; + ani_object callback = nullptr; + ani_ref callbackRef = nullptr; +}; + +class RequestOnSettingAsyncInstanceControl { + public: + static void AddCallbackByInstanceId(std::shared_ptr& asyncContext); + static void ExecCallback(int32_t id); + static void CheckDynamicRequest( + std::shared_ptr& asyncContext, bool& isDynamic); + static void UpdateQueueData(const std::shared_ptr& asyncContext); + private: + static std::map>> instanceIdMap_; + static std::mutex instanceIdMutex_; +}; + +class PermissonOnSettingUICallback { +public: + explicit PermissonOnSettingUICallback(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: + 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; +}; + +void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList, ani_object callback); +} // 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..2d4a72413 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp @@ -0,0 +1,338 @@ +/* + * 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 CheckAccessTokenExecute([[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, "CheckAccessTokenExecute 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 = 0; + 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(CheckAccessTokenExecute) }, + ani_native_function { "requestPermissionsFromUserExecute", + nullptr, reinterpret_cast(RequestPermissionsFromUserExecute) }, + ani_native_function { "requestPermissionOnSettingExecute", + nullptr, 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/ani_common.cpp b/frameworks/ets/ani/accesstoken/src/ani_common.cpp new file mode 100644 index 000000000..b0abb92a1 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_common.cpp @@ -0,0 +1,91 @@ +/* + * 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_common.h" +#include "accesstoken_log.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniAccessTokenCommon" }; +constexpr const char* WRAPPER_CLASS_NAME = "L@ohos/abilityAccessCtrl/AsyncCallbackWrapper;"; +constexpr const char* INVOKE_METHOD_NAME = "invoke"; +} // namespace +ani_env* GetCurrentEnv(ani_vm* vm) +{ + if (vm == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Vm is nullptr."); + return nullptr; + } + ani_env* env = nullptr; + ani_option interopEnabled {"--interop=enable", nullptr}; + ani_options aniArgs {1, &interopEnabled}; + if (vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env) != ANI_OK) { + if (vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) { + return nullptr; + } + } + return env; +} + +bool ExecuteAsyncCallback(ani_env* env, ani_object callback, ani_object error, ani_object result) +{ + if (env == nullptr || callback == nullptr || error == nullptr || result == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Invalid paramter."); + return false; + } + ani_status status = ANI_ERROR; + ani_class clsCall {}; + + if ((status = env->FindClass(WRAPPER_CLASS_NAME, &clsCall)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass failed, error=%{public}d.", static_cast(status)); + return false; + } + ani_method method = {}; + if ((status = env->Class_FindMethod( + clsCall, INVOKE_METHOD_NAME, "L@ohos/base/BusinessError;Lstd/core/Object;:V", &method)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindMethod failed, error=%{public}d.", static_cast(status)); + return false; + } + + status = env->Object_CallMethod_Void(static_cast(callback), method, error, result); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_CallMethod_Void failed, error=%{public}d.", static_cast(status)); + return false; + } + return true; +} + + +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; +} +} // 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 36% rename from frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp rename to frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp index 0dcb952f1..901f1250a 100644 --- a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp @@ -12,69 +12,127 @@ * 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 "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, "AniRequestPermissionFromUser" }; 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; +constexpr const char* PERMISSION_KEY = "ohos.user.grant.permission"; +constexpr const char* STATE_KEY = "ohos.user.grant.permission.state"; +constexpr const char* RESULT_KEY = "ohos.user.grant.permission.result"; +constexpr const char* EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; +constexpr const char* UI_EXTENSION_TYPE = "sys/commonUI"; +constexpr const char* ORI_PERMISSION_MANAGER_BUNDLE_NAME = "com.ohos.permissionmanager"; +constexpr const char* TOKEN_KEY = "ohos.ability.params.token"; +constexpr const char* CALLBACK_KEY = "ohos.ability.params.callback"; +constexpr const char* WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left"; +constexpr const char* WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top"; +constexpr const char* WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height"; +constexpr const char* WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width"; +constexpr const char* REQUEST_TOKEN_KEY = "ohos.ability.params.request.token"; +} +RequestAsyncContext::~RequestAsyncContext() +{ + if (vm == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "VM is nullptr."); + return; + } + bool isSameThread = IsCurrentThread(threadId); + ani_env* curEnv = isSameThread ? env : GetCurrentEnv(vm); + if (curEnv == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetCurrentEnv failed."); + return; + } -static constexpr const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change"; + if (callbackRef != nullptr) { + curEnv->GlobalReference_Delete(callbackRef); + callbackRef = nullptr; + } +} -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"; -const std::string UI_EXTENSION_TYPE = "sys/commonUI"; -const std::string ORI_PERMISSION_MANAGER_BUNDLE_NAME = "com.ohos.permissionmanager"; -const std::string TOKEN_KEY = "ohos.ability.params.token"; -const std::string CALLBACK_KEY = "ohos.ability.params.callback"; -const std::string WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left"; -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"; +template +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; + if (env->Class_FindField(cls, setterName, &fieldValue) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindField Fail %{public}d ", static_cast(status)); + return false; + } + if ((status = env->Object_SetField_Ref(object, fieldValue, value)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_SetField_Ref Fail %{public}d ", static_cast(status)); + return false; + } + return true; +} -#define SETTER_METHOD_NAME(property) "" #property +static ani_object WrapResult(ani_env* env, const std::shared_ptr& asyncContext) +{ + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass("Lsecurity/PermissionRequestResult/PermissionRequestResult;", &cls)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass status %{public}d ", static_cast(status)); + return nullptr; + } + if (cls == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "null cls"); + return nullptr; + } + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindMethod status %{public}d ", static_cast(status)); + return nullptr; + } + ani_object aObject = nullptr; + if ((status = env->Object_New(cls, method, &aObject)) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_New status %{public}d ", static_cast(status)); + return nullptr; + } + auto state = asyncContext->needDynamicRequest ? asyncContext->grantResults : asyncContext->permissionsState; + ani_ref strPermissions = ConvertAniArrayString(env, asyncContext->permissionList); + ani_ref intAuthResults = ConvertAniArrayInt(env, state); + ani_ref boolDialogShownResults = ConvertAniArrayBool(env, asyncContext->dialogShownResults); + ani_ref intPermissionQueryResults = ConvertAniArrayInt(env, asyncContext->permissionQueryResults); + if (strPermissions == nullptr || intAuthResults == nullptr || boolDialogShownResults == nullptr || + intPermissionQueryResults == nullptr) { + 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)) { + return nullptr; + } + return aObject; +} static void UpdateGrantPermissionResultOnly(const std::vector& permissions, - const std::vector& grantResults, std::shared_ptr& data, std::vector& newGrantResults) + const std::vector& grantResults, + std::shared_ptr& data, + std::vector& newGrantResults) { size_t size = permissions.size(); for (size_t i = 0; i < size; i++) { - int result = static_cast(data->permissionsState[i]); + int32_t result = static_cast(data->permissionsState[i]); if (data->permissionsState[i] == AccessToken::DYNAMIC_OPER) { result = data->result.errorCode == AccessToken::RET_SUCCESS ? grantResults[i] : AccessToken::INVALID_OPER; } @@ -123,24 +181,6 @@ static bool IsDynamicRequest(std::shared_ptr& asyncContext) return ret == AccessToken::TypePermissionOper::DYNAMIC_OPER; } -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 CreateUIExtensionMainThread(std::shared_ptr& asyncContext, const OHOS::AAFwk::Want& want, const OHOS::Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, const std::shared_ptr& uiExtCallback) @@ -179,20 +219,20 @@ static void CreateUIExtensionMainThread(std::shared_ptr& as #endif } -static bool CreateServiceExtension(std::shared_ptr& asyncContext) +static void CreateServiceExtension(std::shared_ptr& asyncContext) { if (!asyncContext->uiAbilityFlag) { ACCESSTOKEN_LOG_ERROR(LABEL, "UIExtension ability can not pop service ablility window!"); asyncContext->needDynamicRequest = false; asyncContext->result.errorCode = RET_FAILED; - return false; + return; } OHOS::sptr remoteObject = new (std::nothrow) AuthorizationResult(asyncContext); if (remoteObject == nullptr) { ACCESSTOKEN_LOG_ERROR(LABEL, "Create window failed!"); asyncContext->needDynamicRequest = false; asyncContext->result.errorCode = RET_FAILED; - return false; + return; } OHOS::AAFwk::Want want; want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName); @@ -201,10 +241,10 @@ static bool CreateServiceExtension(std::shared_ptr& asyncCo want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken()); want.SetParam(CALLBACK_KEY, remoteObject); - int32_t left; - int32_t top; - int32_t width; - int32_t height; + int32_t left = 0; + int32_t top = 0; + int32_t width = 0; + int32_t height = 0; asyncContext->abilityContext->GetWindowRect(left, top, width, height); want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left); want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top); @@ -215,10 +255,9 @@ static bool CreateServiceExtension(std::shared_ptr& asyncCo want, asyncContext->abilityContext->GetToken()); ACCESSTOKEN_LOG_INFO(LABEL, "Request end, ret: %{public}d, tokenId: %{public}d, permNum: %{public}zu", ret, asyncContext->tokenId, asyncContext->permissionList.size()); - return true; } -static bool CreateUIExtension(std::shared_ptr& asyncContext) +static void CreateUIExtension(std::shared_ptr& asyncContext) { OHOS::AAFwk::Want want; want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantAbilityName); @@ -241,7 +280,6 @@ static bool CreateUIExtension(std::shared_ptr& asyncContext [uiExtCallback]() { uiExtCallback->OnDestroy(); }, }; CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); - return true; } static void GetInstanceId(std::shared_ptr& asyncContext) @@ -267,212 +305,31 @@ 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) -{ - ani_status status = ANI_ERROR; - ani_field fieldValue; - if (env->Class_FindField(cls, setterName, &fieldValue) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindField Fail %{public}d ", status); - return false; - } - if ((status = env->Object_SetField_Ref(object, fieldValue, value)) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Object_SetField_Ref Fail %{public}d ", status); - return false; - } - 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; - ani_class cls = nullptr; - if ((status = env->FindClass("Lsecurity/PermissionRequestResult/PermissionRequestResult;", &cls)) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass status %{public}d ", static_cast(status)); - return nullptr; - } - if (cls == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "null cls"); - return nullptr; - } - ani_method method = nullptr; - if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindMethod status %{public}d ", static_cast(status)); - return nullptr; - } - ani_object aObject = nullptr; - if ((status = env->Object_New(cls, method, &aObject)) != ANI_OK) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Object_New status %{public}d ", static_cast(status)); - return nullptr; - } - auto state = asyncContext->needDynamicRequest ? asyncContext->grantResults : asyncContext->permissionsState; - ani_ref strPermissions = ConvertAniArrayString(env, asyncContext->permissionList); - ani_ref intAuthResults = ConvertAniArrayInt(env, state); - ani_ref boolDialogShownResults = ConvertAniArrayBool(env, asyncContext->dialogShownResults); - ani_ref intPermissionQueryResults = ConvertAniArrayInt(env, asyncContext->permissionQueryResults); - if (strPermissions == nullptr || intAuthResults == nullptr || boolDialogShownResults == nullptr || - intPermissionQueryResults == nullptr) { - 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.errorCode = RET_FAILED; - return nullptr; - } - return aObject; -} - -static ani_object DealWithResult(ani_env* env, std::shared_ptr& asyncContext) -{ - ani_object resultObj = nullptr; - if (asyncContext->result.errorCode == RET_SUCCESS) { - resultObj = WrapResult(env, asyncContext); - } - 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; -} - static void RequestResultsHandler(const std::vector& permissionList, const std::vector& permissionStates, std::shared_ptr& data) { - 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; + std::vector newGrantResults; UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults); if (newGrantResults.empty()) { ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty"); data->result.errorCode = RET_FAILED; } data->grantResults.assign(newGrantResults.begin(), newGrantResults.end()); - data->loadlock.unlock(); - g_loadedCond.notify_all(); + + bool isSameThread = IsCurrentThread(data->threadId); + ani_env* env = isSameThread ? data->env : GetCurrentEnv(data->vm); + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetCurrentEnv failed."); + return; + } + + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(data->result.errorCode); + ani_object error = BusinessErrorAni::CreateError(env, stsCode, GetErrorMessage(stsCode, data->result.errorMsg)); + ani_object result = WrapResult(env, data); + ExecuteAsyncCallback(env, reinterpret_cast(data->callbackRef), error, result); + if (!isSameThread && data->vm->DetachCurrentThread() != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "DetachCurrentThread failed!"); + } } static ani_status ConvertContext( @@ -512,24 +369,7 @@ static ani_status ConvertContext( return ANI_OK; } -static bool ParseRequestPermissionFromUser(ani_env* env, ani_object aniContext, ani_array_ref permissionList, - std::shared_ptr& asyncContext) -{ - if (ConvertContext(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 bool RequestPermissionsFromUserProcess([[maybe_unused]] ani_env* env, - std::shared_ptr& asyncContext) +static void RequestPermissionsFromUserProcess(std::shared_ptr& asyncContext) { if (!IsDynamicRequest(asyncContext)) { ACCESSTOKEN_LOG_ERROR(LABEL, "It does not need to request permission"); @@ -538,75 +378,110 @@ static bool RequestPermissionsFromUserProcess([[maybe_unused]] ani_env* env, ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty"); asyncContext->result.errorCode = RET_FAILED; } - return false; + return; } + GetInstanceId(asyncContext); - asyncContext->loadlock.lock(); - bool lockFlag = false; if (asyncContext->info.grantBundleName == ORI_PERMISSION_MANAGER_BUNDLE_NAME) { ACCESSTOKEN_LOG_INFO( LABEL, "Pop service extension dialog, uiContentFlag=%{public}d", asyncContext->uiContentFlag); if (asyncContext->uiContentFlag) { - lockFlag = RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); } else { - lockFlag = CreateServiceExtension(asyncContext); + CreateServiceExtension(asyncContext); } } else if (asyncContext->instanceId == -1) { ACCESSTOKEN_LOG_ERROR(LABEL, "Pop service extension dialog, instanceId is -1."); - lockFlag = CreateServiceExtension(asyncContext); + CreateServiceExtension(asyncContext); HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER", HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "BUNDLENAME", asyncContext->bundleName.c_str(), "UIEXTENSION_FLAG", false); } else { ACCESSTOKEN_LOG_INFO(LABEL, "Pop ui extension dialog"); asyncContext->uiExtensionFlag = true; - lockFlag = RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER", HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "BUNDLENAME", asyncContext->bundleName, "UIEXTENSION_FLAG", false); if (!asyncContext->uiExtensionFlag) { ACCESSTOKEN_LOG_WARN(LABEL, "Pop uiextension dialog fail, start to pop service extension dialog."); - lockFlag = RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); } } - if (!lockFlag) { - asyncContext->loadlock.unlock(); - } - return true; } -static ani_object RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, - ani_object aniContext, ani_array_ref permissionList) +static bool ParseRequestPermissionFromUser(ani_env* env, ani_object aniContext, ani_array_ref permissionList, + ani_object callback, std::shared_ptr& asyncContext) { - if (env == nullptr || permissionList == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "permissionList or env null"); - return nullptr; + ani_vm* vm; + ani_status status = env->GetVM(&vm); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetVM failed, error=%{public}d.", static_cast(status)); + return false; } - std::shared_ptr asyncContext = std::make_shared(); - if (!ParseRequestPermissionFromUser(env, aniContext, permissionList, asyncContext)) { - return nullptr; + asyncContext->vm = vm; + asyncContext->env = env; + asyncContext->callback = callback; + asyncContext->threadId = std::this_thread::get_id(); + + status = ConvertContext(env, aniContext, asyncContext); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertContext failed, error=%{public}d.", static_cast(status)); + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("context", "UIAbility or UIExtension Context")); + return false; + } + if (!AniParaseArrayString(env, nullptr, permissionList, asyncContext->permissionList)) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("permissionList", "Array")); + return false; + } + if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { + return false; } #ifdef EVENTHANDLER_ENABLE asyncContext->handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); #endif + return true; +} + +void RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, + ani_object aniContext, ani_array_ref permissionList, ani_object callback) +{ + if (env == nullptr || permissionList == nullptr || callback == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Parenv or permissionList or callback is null."); + return; + } + std::shared_ptr asyncContext = std::make_shared(); + if (!ParseRequestPermissionFromUser(env, aniContext, permissionList, callback, asyncContext)) { + return; + } + 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); - 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; + + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + ani_object result = reinterpret_cast(nullRef); + ani_object error = BusinessErrorAni::CreateError(env, STS_ERROR_INNER, GetErrorMessage(STS_ERROR_INNER, + "The specified context does not belong to the current application.")); + ExecuteAsyncCallback(env, callback, error, result); + return; } - if (!RequestPermissionsFromUserProcess(env, asyncContext)) { - return DealWithResult(env, asyncContext); + RequestPermissionsFromUserProcess(asyncContext); + if (asyncContext->needDynamicRequest) { + return; } + + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(asyncContext->result.errorCode); + ani_object error = BusinessErrorAni::CreateError( + env, stsCode, GetErrorMessage(stsCode, asyncContext->result.errorMsg)); + ani_object result = WrapResult(env, asyncContext); + ExecuteAsyncCallback(env, callback, error, result); ACCESSTOKEN_LOG_INFO(LABEL, "uiExtensionFlag: %{public}d, uiContentFlag: %{public}d, uiAbilityFlag: %{public}d ", asyncContext->uiExtensionFlag, asyncContext->uiContentFlag, asyncContext->uiAbilityFlag); - asyncContext->loadlock.lock(); - auto resultObj = DealWithResult(env, asyncContext); - asyncContext->loadlock.unlock(); - return resultObj; } static void CloseModalUIExtensionMainThread(std::shared_ptr& asyncContext, int32_t sessionId) @@ -642,10 +517,11 @@ void RequestAsyncInstanceControl::ExecCallback(int32_t id) std::lock_guard lock(instanceIdMutex_); auto iter = RequestAsyncInstanceControl::instanceIdMap_.find(id); if (iter == RequestAsyncInstanceControl::instanceIdMap_.end()) { - ACCESSTOKEN_LOG_ERROR(LABEL, "instanceIdMap_ empty"); + ACCESSTOKEN_LOG_ERROR(LABEL, "Id: %{public}d not existed.", id); return; } while (!iter->second.empty()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size()); asyncContext = iter->second[0]; iter->second.erase(iter->second.begin()); CheckDynamicRequest(asyncContext, isDynamic); @@ -654,20 +530,17 @@ void RequestAsyncInstanceControl::ExecCallback(int32_t id) } } if (iter->second.empty()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map is empty", id); RequestAsyncInstanceControl::instanceIdMap_.erase(id); } } - bool lockFlag = true; if (isDynamic) { if (asyncContext->uiExtensionFlag) { - lockFlag = CreateUIExtension(asyncContext); + CreateUIExtension(asyncContext); } else { - lockFlag = CreateServiceExtension(asyncContext); + CreateServiceExtension(asyncContext); } } - if (!lockFlag) { - asyncContext->loadlock.unlock(); - } } void RequestAsyncInstanceControl::CheckDynamicRequest( @@ -682,22 +555,23 @@ void RequestAsyncInstanceControl::CheckDynamicRequest( isDynamic = true; } -bool RequestAsyncInstanceControl::AddCallbackByInstanceId(std::shared_ptr& asyncContext) +void RequestAsyncInstanceControl::AddCallbackByInstanceId(std::shared_ptr& asyncContext) { - std::lock_guard lock(instanceIdMutex_); - auto iter = RequestAsyncInstanceControl::instanceIdMap_.find(asyncContext->instanceId); - if (iter != RequestAsyncInstanceControl::instanceIdMap_.end()) { - RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext); - return true; + { + std::lock_guard lock(instanceIdMutex_); + auto iter = RequestAsyncInstanceControl::instanceIdMap_.find(asyncContext->instanceId); + if (iter != RequestAsyncInstanceControl::instanceIdMap_.end()) { + RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext); + return; + } + RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId] = {}; } - RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId] = {}; - bool lockFlag = true; if (asyncContext->uiExtensionFlag) { - lockFlag = CreateUIExtension(asyncContext); + CreateUIExtension(asyncContext); } else { - lockFlag = CreateServiceExtension(asyncContext); + CreateServiceExtension(asyncContext); } - return lockFlag; + return; } UIExtensionCallback::UIExtensionCallback(const std::shared_ptr& reqContext) @@ -767,7 +641,7 @@ void UIExtensionCallback::OnDestroy() } void AuthorizationResult::GrantResultsCallback( - const std::vector& permissionList, const std::vector& grantResults) + const std::vector& permissionList, const std::vector& grantResults) { std::shared_ptr asyncContext = data_; if (asyncContext == nullptr) { @@ -789,693 +663,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..2aa9b2859 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp @@ -0,0 +1,586 @@ +/* + * 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_request_permission_on_setting.h" +#include "accesstoken_kit.h" +#include "accesstoken_log.h" +#include "token_setproc.h" +#include "want.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +std::map>> + RequestOnSettingAsyncInstanceControl::instanceIdMap_; +std::mutex RequestOnSettingAsyncInstanceControl::instanceIdMutex_; +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniRequestPermission" }; +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_NOT_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, + ani_object callback, std::shared_ptr& asyncContext) +{ + ani_vm* vm; + ani_status status = env->GetVM(&vm); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetVM failed, error=%{public}d.", static_cast(status)); + return false; + } + asyncContext->vm = vm; + asyncContext->env = env; + asyncContext->callback = callback; + asyncContext->threadId = std::this_thread::get_id(); + + if (GetContext(env, aniContext, asyncContext) != ANI_OK) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("context", "UIAbility or UIExtension Context")); + return false; + } + if (!AniParaseArrayString(env, nullptr, permissionList, asyncContext->permissionList)) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("permissionList", "Array")); + return false; + } + if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { + return false; + } +#ifdef EVENTHANDLER_ENABLE + asyncContext->handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); +#endif + return true; +} + +static void StateToEnumIndex(int32_t state, ani_size& enumIndex) +{ + if (state == 0) { + enumIndex = 1; + } else { + enumIndex = 0; + } +} + +static ani_object 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_NOT_REVOKE_BY_USER: + stsCode = STS_ERROR_PERM_NOT_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; +} + +PermissonOnSettingUICallback::PermissonOnSettingUICallback( + const std::shared_ptr& reqContext) +{ + this->reqContext_ = reqContext; +} + +PermissonOnSettingUICallback::~PermissonOnSettingUICallback() +{} + +void PermissonOnSettingUICallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +static void PermissionResultsCallbackUI( + const std::vector stateList, std::shared_ptr& data) +{ + bool isSameThread = IsCurrentThread(data->threadId); + ani_env* env = isSameThread ? data->env : GetCurrentEnv(data->vm); + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "GetCurrentEnv failed."); + return; + } + + int32_t stsCode = TransferToStsErrorCode(data->result.errorCode); + ani_object error = BusinessErrorAni::CreateError(env, stsCode, GetErrorMessage(stsCode, data->result.errorMsg)); + ani_object result = ReturnResult(env, data); + ExecuteAsyncCallback(env, reinterpret_cast(data->callbackRef), error, result); + + if (!isSameThread && data->vm->DetachCurrentThread() != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "DetachCurrentThread failed!"); + } +} + +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; + } + RequestOnSettingAsyncInstanceControl::UpdateQueueData(this->reqContext_); + RequestOnSettingAsyncInstanceControl::ExecCallback(this->reqContext_->instanceId); + PermissionResultsCallbackUI(this->reqContext_->stateList, this->reqContext_); +} + +/* + * 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, errorCodeis %{public}d, listSize=%{public}zu.", + resultCode, this->reqContext_->result.errorCode, 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 void CreateUIExtension(const OHOS::AAFwk::Want &want, std::shared_ptr asyncContext) +{ + auto uiExtCallback = std::make_shared(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(); + }, + }; + + CreateSettingUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); +} + +static void StartUIExtension(std::shared_ptr& asyncContext) +{ + AccessTokenKit::GetPermissionManagerInfo(asyncContext->info); + ACCESSTOKEN_LOG_INFO(LABEL, "bundleName: %{public}s, permStateAbilityName: %{public}s.", + asyncContext->info.grantBundleName.c_str(), asyncContext->info.permStateAbilityName.c_str()); + 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); + CreateUIExtension(want, asyncContext); +} + +static void GetInstanceId(std::shared_ptr& asyncContext) +{ + auto task = [asyncContext]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, + asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + if (uiContent == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!"); + return; + } + asyncContext->instanceId = uiContent->GetInstanceId(); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId"); + } else { + task(); + } +#else + task(); +#endif + ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId); +} + +void RequestOnSettingAsyncInstanceControl::AddCallbackByInstanceId( + std::shared_ptr& asyncContext) +{ + ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d", asyncContext->instanceId); + { + std::lock_guard lock(instanceIdMutex_); + auto iter = instanceIdMap_.find(asyncContext->instanceId); + // id is existed mean a pop window is showing, add context to waiting queue + if (iter != instanceIdMap_.end()) { + ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d has existed.", asyncContext->instanceId); + instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext); + return; + } + // make sure id is in map to indicate a pop-up window is showing + instanceIdMap_[asyncContext->instanceId] = {}; + } + StartUIExtension(asyncContext); +} + +bool static CheckPermList(std::vector permList, std::vector tmpPermList) +{ + if (permList.size() != tmpPermList.size()) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Perm list size not equal, CurrentPermList size: %{public}zu.", tmpPermList.size()); + return false; + } + + for (const auto& item : permList) { + auto iter = std::find_if(tmpPermList.begin(), tmpPermList.end(), [item](const std::string& perm) { + return item == perm; + }); + if (iter == tmpPermList.end()) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Different permission lists."); + return false; + } + } + return true; +} + +void RequestOnSettingAsyncInstanceControl::UpdateQueueData( + const std::shared_ptr& reqContext) +{ + if (reqContext->result.errorCode != RET_SUCCESS) { + ACCESSTOKEN_LOG_INFO(LABEL, "The queue data does not need to be updated."); + return; + } + for (const int32_t item : reqContext->stateList) { + if (item != PERMISSION_GRANTED) { + ACCESSTOKEN_LOG_INFO(LABEL, "The queue data does not need to be updated"); + return; + } + } + + { + std::lock_guard lock(instanceIdMutex_); + int32_t id = reqContext->instanceId; + auto iter = instanceIdMap_.find(id); + if (iter == instanceIdMap_.end()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d not existed.", id); + return; + } + std::vector permList = reqContext->permissionList; + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size()); + for (auto& asyncContext : iter->second) { + std::vector tmpPermList = asyncContext->permissionList; + + if (CheckPermList(permList, tmpPermList)) { + asyncContext->result.errorCode = reqContext->result.errorCode; + asyncContext->stateList = reqContext->stateList; + asyncContext->isDynamic = false; + } + } + } +} + +void RequestOnSettingAsyncInstanceControl::ExecCallback(int32_t id) +{ + std::shared_ptr asyncContext = nullptr; + bool isDynamic = false; + { + std::lock_guard lock(instanceIdMutex_); + auto iter = instanceIdMap_.find(id); + if (iter == instanceIdMap_.end()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d not existed.", id); + return; + } + while (!iter->second.empty()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size()); + asyncContext = iter->second[0]; + iter->second.erase(iter->second.begin()); + CheckDynamicRequest(asyncContext, isDynamic); + if (isDynamic) { + break; + } + } + if (iter->second.empty()) { + ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map is empty", id); + instanceIdMap_.erase(id); + } + } + if (isDynamic) { + StartUIExtension(asyncContext); + } +} + +void RequestOnSettingAsyncInstanceControl::CheckDynamicRequest( + std::shared_ptr& asyncContext, bool& isDynamic) +{ + isDynamic = asyncContext->isDynamic; + if (!isDynamic) { + ACCESSTOKEN_LOG_INFO(LABEL, "It does not need to request permission exsion"); + PermissionResultsCallbackUI(asyncContext->stateList, asyncContext); + return; + } +} + +void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList, ani_object callback) +{ + if (env == nullptr || permissionList == nullptr || callback == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "env or permissionList or callback is null."); + return; + } + + std::shared_ptr asyncContext = + std::make_shared(); + if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, callback, asyncContext)) { + return; + } + + ani_ref nullRef = nullptr; + env->GetNull(&nullRef); + ani_object result = reinterpret_cast(nullRef); + 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); + ani_object error = + BusinessErrorAni::CreateError(env, STS_ERROR_PARAM_INVALID, GetErrorMessage(STS_ERROR_PARAM_INVALID, + "The specified context does not belong to the current application.")); + ExecuteAsyncCallback(env, callback, error, result); + return; + } + GetInstanceId(asyncContext); + RequestOnSettingAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + ACCESSTOKEN_LOG_INFO(LABEL, "Start to pop ui extension dialog"); + + if (asyncContext->result.errorCode != RET_SUCCESS) { + int32_t stsCode = TransferToStsErrorCode(asyncContext->result.errorCode); + ani_object error = BusinessErrorAni::CreateError( + env, stsCode, GetErrorMessage(stsCode, asyncContext->result.errorMsg)); + ExecuteAsyncCallback(env, callback, error, result); + ACCESSTOKEN_LOG_WARN(LABEL, "Failed to pop uiextension dialog."); + } +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/common/BUILD.gn b/frameworks/ets/ani/common/BUILD.gn index 66cbbd3ab..6ebcfa514 100644 --- a/frameworks/ets/ani/common/BUILD.gn +++ b/frameworks/ets/ani/common/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# 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 diff --git a/frameworks/ets/ani/common/ets/security/PermissionRequestResult.ets b/frameworks/ets/ani/common/ets/security/PermissionRequestResult copy.ets similarity index 100% rename from frameworks/ets/ani/common/ets/security/PermissionRequestResult.ets rename to frameworks/ets/ani/common/ets/security/PermissionRequestResult copy.ets diff --git a/frameworks/ets/ani/common/include/ani_error.h b/frameworks/ets/ani/common/include/ani_error.h index d8fc49028..646254ce0 100644 --- a/frameworks/ets/ani/common/include/ani_error.h +++ b/frameworks/ets/ani/common/include/ani_error.h @@ -42,7 +42,7 @@ typedef enum { STS_ERROR_INNER, STS_ERROR_REQUEST_IS_ALREADY_EXIST = 12100010, STS_ERROR_ALL_PERM_GRANTED = 12100011, - STS_ERROR_PERM_REVOKE_BY_USER = 12100012, + STS_ERROR_PERM_NOT_REVOKE_BY_USER = 12100012, STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN = 12100013, } STSErrorCode; @@ -52,7 +52,7 @@ struct AtmResult { }; std::string GetParamErrorMsg(const std::string& param, const std::string& errMsg); -std::string GetErrorMessage(uint32_t errCode, const std::string& extendMsg = ""); +std::string GetErrorMessage(int32_t errCode, const std::string& extendMsg = ""); class BusinessErrorAni { public: static ani_object CreateError(ani_env* env, ani_int code, const std::string& msg); diff --git a/frameworks/ets/ani/common/include/ani_utils.h b/frameworks/ets/ani/common/include/ani_utils.h index f86989e11..4ca5812b9 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 AniParaseArrayString([[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..8891fb097 100644 --- a/frameworks/ets/ani/common/src/ani_error.cpp +++ b/frameworks/ets/ani/common/src/ani_error.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -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." }, @@ -45,7 +45,7 @@ static const std::unordered_map g_errorStringMap = { { STS_ERROR_INNER, "Common inner error." }, { STS_ERROR_REQUEST_IS_ALREADY_EXIST, "The request already exists." }, { STS_ERROR_ALL_PERM_GRANTED, "All permissions in the permission list have been granted." }, - { STS_ERROR_PERM_REVOKE_BY_USER, + { STS_ERROR_PERM_NOT_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." }, }; @@ -116,7 +116,7 @@ std::string GetParamErrorMsg(const std::string& param, const std::string& errMsg return msg; } -std::string GetErrorMessage(uint32_t errCode, const std::string& extendMsg) +std::string GetErrorMessage(int32_t errCode, const std::string& extendMsg) { auto iter = g_errorStringMap.find(errCode); if (iter != g_errorStringMap.end()) { diff --git a/frameworks/ets/ani/common/src/ani_utils.cpp b/frameworks/ets/ani/common/src/ani_utils.cpp index 22200802f..d872de498 100644 --- a/frameworks/ets/ani/common/src/ani_utils.cpp +++ b/frameworks/ets/ani/common/src/ani_utils.cpp @@ -79,10 +79,10 @@ bool AniGetEnumItemByIndex(ani_env* env, const ani_enum& aniEnum, ani_size index } -bool AniParseString(ani_env* env, const ani_string& ani_str, std::string& out) +bool AniParseString(ani_env* env, const ani_string& anistr, std::string& out) { ani_size strSize; - if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) { + if (env->String_GetUTF8Size(anistr, &strSize) != ANI_OK) { ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8Size failed!"); return false; } @@ -90,7 +90,7 @@ bool AniParseString(ani_env* env, const ani_string& ani_str, std::string& out) std::vector buffer(strSize + 1); // +1 for null terminator char* utf8Buffer = buffer.data(); ani_size bytesWritten = 0; - if (env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten) != ANI_OK) { + if (env->String_GetUTF8(anistr, utf8Buffer, strSize + 1, &bytesWritten) != ANI_OK) { ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8 failed!"); return false; } @@ -104,17 +104,17 @@ bool AniParseString(ani_env* env, const ani_string& ani_str, std::string& out) return true; } -bool AniParseStringArray(ani_env* env, const ani_array_ref& ani_str_arr, std::vector& out) +bool AniParseStringArray(ani_env* env, const ani_array_ref& aniStrArr, std::vector& out) { ani_size size = 0; - if (env->Array_GetLength(ani_str_arr, &size) != ANI_OK) { + if (env->Array_GetLength(aniStrArr, &size) != ANI_OK) { ACCESSTOKEN_LOG_ERROR(LABEL, "Array_GetLength failed!"); return false; } for (ani_size i = 0; i < size; ++i) { ani_ref aniRef; - if (env->Array_Get_Ref(ani_str_arr, i, &aniRef) != ANI_OK) { + if (env->Array_Get_Ref(aniStrArr, i, &aniRef) != ANI_OK) { ACCESSTOKEN_LOG_ERROR(LABEL, "Array_Get_Ref failed!"); return false; } @@ -129,9 +129,9 @@ bool AniParseStringArray(ani_env* env, const ani_array_ref& ani_str_arr, std::ve return true; } -bool AniParseCallback(ani_env* env, const ani_ref& ani_callback, ani_ref& out) +bool AniParseCallback(ani_env* env, const ani_ref& aniCallback, ani_ref& out) { - if (env->GlobalReference_Create(ani_callback, &out) != ANI_OK) { + if (env->GlobalReference_Create(aniCallback, &out) != ANI_OK) { ACCESSTOKEN_LOG_ERROR(LABEL, "GlobalReference_Create failed!"); return false; } @@ -232,12 +232,7 @@ bool AniObjectSetPropertyByNameRef(ani_env* env, ani_object& object, const char bool IsCurrentThread(std::thread::id threadId) { - std::thread::id currentThread = std::this_thread::get_id(); - if (threadId != currentThread) { - ACCESSTOKEN_LOG_ERROR(LABEL, "Ani_ref can not be compared, different threadId."); - return false; - } - return true; + return threadId == std::this_thread::get_id(); } bool AniIsCallbackRefEqual(ani_env* env, const ani_ref& compareRef, const ani_ref& targetRref, std::thread::id threadId, @@ -264,6 +259,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 aniStr) +{ + ani_size strSize; + if (env->String_GetUTF8Size(aniStr, &strSize) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8Size error"); + return ""; + } + std::vector buffer(strSize + 1); + char* utf8Buffer = buffer.data(); + + ani_size bytesWritten = 0; + if (env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytesWritten) != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8 error"); + return ""; + } + utf8Buffer[bytesWritten] = '\0'; + std::string content = std::string(utf8Buffer); + return content; +} + +bool AniParaseArrayString([[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/BUILD.gn b/frameworks/ets/ani/privacy/BUILD.gn index cb1ddd502..d7bdac39f 100644 --- a/frameworks/ets/ani/privacy/BUILD.gn +++ b/frameworks/ets/ani/privacy/BUILD.gn @@ -40,6 +40,7 @@ ohos_shared_library("privacy_ani") { external_deps = [ "hilog:libhilog", + "ipc:ipc_single", "runtime_core:ani", "runtime_core:libarkruntime", ] diff --git a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets index b53beac77..cd065400a 100644 --- a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets +++ b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import { AsyncCallback, Callback, BusinessError} from '@ohos.base'; +import { AsyncCallback, Callback, BusinessError} from '@ohos.base'; import { Permissions } from 'permissions'; function PARAM_ERROR_MSG(param: string, type: string): string { @@ -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 => { diff --git a/frameworks/ets/ani/privacy/src/privacy_manager.cpp b/frameworks/ets/ani/privacy/src/privacy_manager.cpp index 3528b7caa..8f59067c2 100644 --- a/frameworks/ets/ani/privacy/src/privacy_manager.cpp +++ b/frameworks/ets/ani/privacy/src/privacy_manager.cpp @@ -109,14 +109,13 @@ static void AddPermissionUsedRecord([[maybe_unused]] ani_env* env, [[maybe_unuse ani_int tokenID, ani_string permissionName, ani_int successCount, ani_int failCount, ani_object options) { if (env == nullptr) { - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); return; } ani_size strSize; ani_status status = ANI_ERROR; if (ANI_OK != (status = env->String_GetUTF8Size(permissionName, &strSize))) { ACCESSTOKEN_LOG_ERROR(LABEL, "String_GetUTF8Size_Faild status : %{public}d", status); - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); return; } std::vector buffer(strSize + 1); @@ -124,14 +123,12 @@ static void AddPermissionUsedRecord([[maybe_unused]] ani_env* env, [[maybe_unuse ani_size bytesWritten = 0; if (ANI_OK != (status = env->String_GetUTF8(permissionName, utf8Buffer, strSize + 1, &bytesWritten))) { ACCESSTOKEN_LOG_ERROR(LABEL, "get String_GetUTF8 Faild status : %{public}d", status); - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); return; } utf8Buffer[bytesWritten] = '\0'; std::string outputPermissionName = std::string(utf8Buffer); ani_ref usedTypeRef; if (ANI_OK != (status = env->Object_GetPropertyByName_Ref(options, "usedType", &usedTypeRef))) { - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); ACCESSTOKEN_LOG_ERROR(LABEL, "Object_GetFieldByName_Ref Faild status : %{public}d", status); return; } @@ -139,13 +136,12 @@ static void AddPermissionUsedRecord([[maybe_unused]] ani_env* env, [[maybe_unuse ani_boolean isUndefined = true; if (ANI_OK != (status = env->Reference_IsUndefined(usedTypeRef, &isUndefined))) { ACCESSTOKEN_LOG_ERROR(LABEL, "status : %{public}d", status); - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); return; } if (!isUndefined) { ani_enum_item usedTypeEnum = static_cast(usedTypeRef); if (ANI_OK != env->EnumItem_GetValue_Int(usedTypeEnum, &usedType)) { - BusinessErrorAni::ThrowError(env, STS_ERROR_INNER, GetErrorMessage(STSErrorCode::STS_ERROR_INNER)); + ACCESSTOKEN_LOG_ERROR(LABEL, "EnumItem_GetValue_Int Faild"); return; } } diff --git a/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp b/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp index 8bc4516dc..56d4c31f1 100644 --- a/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp +++ b/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp @@ -58,7 +58,7 @@ static napi_value WrapVoidToJS(napi_env env) return result; } -static Ace::UIContent* GetUIContent(std::shared_ptr asyncContext) +static Ace::UIContent* GetUIContent(const std::shared_ptr asyncContext) { if (asyncContext == nullptr) { return nullptr; diff --git a/tools/accesstoken/src/atm_command.cpp b/tools/accesstoken/src/atm_command.cpp index d00dc6fcf..666a526a9 100644 --- a/tools/accesstoken/src/atm_command.cpp +++ b/tools/accesstoken/src/atm_command.cpp @@ -139,7 +139,7 @@ AtmCommand::AtmCommand(int32_t argc, char *argv[]) : argc_(argc), argv_(argv), n opterr = 0; commandMap_ = { - {"help", [this](){return RunAsHelpCommand();}}, + {"help", [this]() {return RunAsHelpCommand();}}, {"dump", [this]() {return RunAsCommonCommand();}}, {"perm", [this]() {return RunAsCommonCommand();}}, {"toggle", [this]() {return RunAsCommonCommand();}}, -- Gitee