diff --git a/frameworks/ets/ani/accesstoken/BUILD.gn b/frameworks/ets/ani/accesstoken/BUILD.gn index cd5ebb4008a9c9690e87b44e03908908b9e73273..7a91bdadbe8fb120a7c0300ff077ee8af85852b4 100644 --- a/frameworks/ets/ani/accesstoken/BUILD.gn +++ b/frameworks/ets/ani/accesstoken/BUILD.gn @@ -34,6 +34,7 @@ ohos_shared_library("accesstoken_ani") { sources = [ "src/ani_ability_access_ctrl.cpp", "src/ani_common.cpp", + "src/ani_request_base.cpp", "src/ani_request_global_switch_on_setting.cpp", "src/ani_request_permission.cpp", "src/ani_request_permission_on_setting.cpp", diff --git a/frameworks/ets/ani/accesstoken/include/ani_common.h b/frameworks/ets/ani/accesstoken/include/ani_common.h index e419b3516ec44c71956ec81d106fab504631a176..d83378d2b8ce848cfcc2c5d608d92a002fffa776 100644 --- a/frameworks/ets/ani/accesstoken/include/ani_common.h +++ b/frameworks/ets/ani/accesstoken/include/ani_common.h @@ -19,6 +19,7 @@ #include "ability_context.h" #include "ani.h" #include "ani_base_context.h" +#include "ani_request_base.h" #include "ui_content.h" #include "ui_extension_context.h" @@ -26,8 +27,16 @@ namespace OHOS { namespace Security { namespace AccessToken { 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); +OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr stageContext); +void CreateUIExtensionMainThread(std::shared_ptr asyncContext, + const OHOS::AAFwk::Want& want, const OHOS::Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, + const std::shared_ptr uiExtCallback); +void CloseModalUIExtensionMainThread(std::shared_ptr asyncContext, int32_t sessionId); +void CreateUIExtension( + const OHOS::AAFwk::Want& want, + std::shared_ptr asyncContext, + std::shared_ptr controller +); } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/frameworks/ets/ani/accesstoken/include/ani_request_base.h b/frameworks/ets/ani/accesstoken/include/ani_request_base.h new file mode 100644 index 0000000000000000000000000000000000000000..97dc0697afde2c7f8b6b8bf8ee0de76c03cf7cb5 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/include/ani_request_base.h @@ -0,0 +1,117 @@ +/* + * 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_BASE_H +#define ANI_REQUEST_BASE_H + +#include "ability_context.h" +#include "access_token.h" +#include "ani.h" +#include "ani_error.h" +#include "ani_utils.h" +#ifdef EVENTHANDLER_ENABLE +#include "event_handler.h" +#include "event_queue.h" +#endif +#include "permission_grant_info.h" +#include "ui_content.h" +#include "ui_extension_context.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { +enum AniRequestType { + REQUEST_PERMISSIONS_FROM_USER, + REQUEST_PERMISSION_ON_SETTING, + REQUEST_GLOBAL_SWITCH_ON_SETTING +}; + +struct RequestAsyncContextBase { + AccessTokenID tokenId = 0; + std::string bundleName; + AtmResult result; + PermissionGrantInfo info; + int32_t instanceId = -1; + std::shared_ptr stageContext_ = nullptr; + bool uiExtensionFlag = false; + bool releaseFlag = false; + bool uiContentFlag = false; + std::mutex lockReleaseFlag; + +#ifdef EVENTHANDLER_ENABLE + std::shared_ptr handler_ = nullptr; +#endif + std::thread::id threadId_; + ani_vm* vm_ = nullptr; + ani_env* env_ = nullptr; + ani_ref callbackRef = nullptr; + AniRequestType contextType_; + + RequestAsyncContextBase(ani_vm* vm, ani_env* env, AniRequestType type); + virtual ~RequestAsyncContextBase() = default; + bool FillInfoFromContext(const ani_object& aniContext); + void FinishCallback(); + void GetInstanceId(); + void Clear(); + AniRequestType GetType(); + + virtual bool IsSameRequest(const std::shared_ptr other); + virtual void CopyResult(const std::shared_ptr other); + virtual void ProcessFailResult(int32_t code); + + virtual bool NoNeedUpdate() = 0; + virtual int32_t ConvertErrorCode(int32_t code) = 0; + virtual void ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) = 0; + virtual ani_object WrapResult(ani_env* env) = 0; + virtual void StartExtensionAbility(std::shared_ptr asyncContext) = 0; + virtual bool CheckDynamicRequest() = 0; +}; + +class RequestInstanceControl { +public: + void AddCallbackByInstanceId(std::shared_ptr asyncContext); + void ExecCallback(int32_t id); + void UpdateQueueData(const std::shared_ptr asyncContext); +private: + std::map>> instanceIdMap_; + std::mutex instanceIdMutex_; +}; + +class UIExtensionCallback { +public: + explicit UIExtensionCallback(const std::shared_ptr reqContext); + ~UIExtensionCallback(); + + void SetSessionId(int32_t sessionId); + void SetRequestInstanceControl(std::shared_ptr controllerInstance); + void ReleaseHandler(int32_t code); + void OnRelease(int32_t releaseCode); + 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(); + void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); + +protected: + std::shared_ptr controllerInstance_ = nullptr; + std::shared_ptr reqContext_ = nullptr; + +private: + int32_t sessionId_ = 0; +}; + +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif /* ANI_REQUEST_BASE_H */ diff --git a/frameworks/ets/ani/accesstoken/include/ani_request_global_switch_on_setting.h b/frameworks/ets/ani/accesstoken/include/ani_request_global_switch_on_setting.h index f04f9f4c1750798faa3374d61f76a6e86f40fd4b..4ae216cf62776d37eedd3c686cf7f522e9c032c4 100644 --- a/frameworks/ets/ani/accesstoken/include/ani_request_global_switch_on_setting.h +++ b/frameworks/ets/ani/accesstoken/include/ani_request_global_switch_on_setting.h @@ -17,14 +17,16 @@ #include "access_token.h" #include "ani.h" -#include "ani_common.h" #include "ani_error.h" +#include "ani_request_base.h" #include "ani_utils.h" #ifdef EVENTHANDLER_ENABLE #include "event_handler.h" #include "event_queue.h" #endif #include "permission_grant_info.h" +#include "ui_content.h" +#include "ui_extension_context.h" namespace OHOS { namespace Security { @@ -35,62 +37,21 @@ typedef enum { LOCATION = 2, } SwitchType; -struct RequestGlobalSwitchAsyncContext { - virtual ~RequestGlobalSwitchAsyncContext(); - AccessTokenID tokenId = 0; - AtmResult result; - PermissionGrantInfo info; - - int32_t instanceId = -1; +struct RequestGlobalSwitchAsyncContext : public RequestAsyncContextBase { bool isDynamic = true; bool switchStatus = false; int32_t switchType = -1; - - std::shared_ptr abilityContext = nullptr; - std::shared_ptr uiExtensionContext = nullptr; - bool uiAbilityFlag = false; - bool releaseFlag = false; - std::mutex lockReleaseFlag; - -#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 RequestGlobalSwitchAsyncInstanceControl { - 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 SwitchOnSettingUICallback { -public: - explicit SwitchOnSettingUICallback(const std::shared_ptr& reqContext); - ~SwitchOnSettingUICallback(); - 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; + RequestGlobalSwitchAsyncContext(ani_vm* vm, ani_env* env); + ~RequestGlobalSwitchAsyncContext() override; + int32_t ConvertErrorCode(int32_t errCode) override; + ani_object WrapResult(ani_env* env) override; + void ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) override; + void StartExtensionAbility(std::shared_ptr asyncContext) override; + bool IsSameRequest(const std::shared_ptr other) override; + void CopyResult(const std::shared_ptr other) override; + bool CheckDynamicRequest() override; + bool NoNeedUpdate() override; + void ProcessFailResult(int32_t code) override; }; void RequestGlobalSwitchExecute([[maybe_unused]] ani_env* env, diff --git a/frameworks/ets/ani/accesstoken/include/ani_request_permission.h b/frameworks/ets/ani/accesstoken/include/ani_request_permission.h index 7d4da55ac40438f0acb8f25ade817fb81c09eecc..ae8a192725090364048dc2aff368974e20b9cb5e 100644 --- a/frameworks/ets/ani/accesstoken/include/ani_request_permission.h +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission.h @@ -19,8 +19,8 @@ #include #include "access_token.h" #include "ani.h" -#include "ani_common.h" #include "ani_error.h" +#include "ani_request_base.h" #include "ani_utils.h" #ifdef EVENTHANDLER_ENABLE #include "event_handler.h" @@ -29,62 +29,36 @@ #include "permission_grant_info.h" #include "perm_state_change_callback_customize.h" #include "token_callback_stub.h" +#include "ui_content.h" +#include "ui_extension_context.h" namespace OHOS { namespace Security { namespace AccessToken { -struct RequestAsyncContext { - virtual ~RequestAsyncContext(); - AccessTokenID tokenId = 0; - std::string bundleName; +struct RequestAsyncContext : public RequestAsyncContextBase { + RequestAsyncContext(ani_vm* vm, ani_env* env); + ~RequestAsyncContext() override; + void StartExtensionAbility(std::shared_ptr asyncContext) override; + bool IsDynamicRequest(); + void ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) override; + int32_t ConvertErrorCode(int32_t code) override; + ani_object WrapResult(ani_env* env) override; + bool CheckDynamicRequest() override; + void HandleResult(const std::vector& permissionList, const std::vector& grantResults); + bool NoNeedUpdate() override; + bool needDynamicRequest = true; - AtmResult result; - int32_t instanceId = -1; std::vector permissionList; std::vector grantResults; std::vector permissionsState; std::vector dialogShownResults; - std::vector permissionQueryResults; std::vector errorReasons; - Security::AccessToken::PermissionGrantInfo info; - std::shared_ptr abilityContext = nullptr; - std::shared_ptr uiExtensionContext = nullptr; - bool uiAbilityFlag = false; - bool uiExtensionFlag = false; - bool uiContentFlag = false; - bool releaseFlag = false; -#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 { -public: - explicit UIExtensionCallback(const std::shared_ptr& reqContext); - ~UIExtensionCallback(); - void SetSessionId(int32_t sessionId); - 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(); - void ReleaseHandler(int32_t code); - -private: - int32_t sessionId_ = 0; - std::shared_ptr reqContext_ = nullptr; }; class AuthorizationResult : public Security::AccessToken::TokenCallbackStub { public: - AuthorizationResult(std::shared_ptr& data) : data_(data) {} - virtual ~AuthorizationResult() override = default; + AuthorizationResult(std::shared_ptr& data); + virtual ~AuthorizationResult() override; virtual void GrantResultsCallback( const std::vector& permissionList, const std::vector& grantResults) override; @@ -94,16 +68,6 @@ private: std::shared_ptr data_ = nullptr; }; -class RequestAsyncInstanceControl { -public: - static void AddCallbackByInstanceId(std::shared_ptr& asyncContext); - static void ExecCallback(int32_t id); - static void CheckDynamicRequest(std::shared_ptr& asyncContext, bool& isDynamic); - -private: - static std::map>> instanceIdMap_; - static std::mutex instanceIdMutex_; -}; struct ResultCallback { std::vector permissions; 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 index 5d73f58179d3378d0b2bff811cef19e706f70030..d64097bb516e0eb897afc461db88c8e920dfe58f 100644 --- a/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h +++ b/frameworks/ets/ani/accesstoken/include/ani_request_permission_on_setting.h @@ -17,75 +17,37 @@ #include "access_token.h" #include "ani.h" -#include "ani_common.h" #include "ani_error.h" +#include "ani_request_base.h" #include "ani_utils.h" #ifdef EVENTHANDLER_ENABLE #include "event_handler.h" #include "event_queue.h" #endif #include "permission_grant_info.h" +#include "ui_content.h" +#include "ui_extension_context.h" namespace OHOS { namespace Security { namespace AccessToken { -struct RequestPermOnSettingAsyncContext { - virtual ~RequestPermOnSettingAsyncContext(); - AccessTokenID tokenId = 0; - AtmResult result; - PermissionGrantInfo info; - - int32_t instanceId = -1; +struct RequestPermOnSettingAsyncContext: public RequestAsyncContextBase { bool isDynamic = true; std::vector permissionList; ani_object requestResult = nullptr; std::vector stateList; - std::shared_ptr abilityContext = nullptr; - std::shared_ptr uiExtensionContext = nullptr; - bool uiAbilityFlag = false; - bool releaseFlag = false; - std::mutex lockReleaseFlag; - -#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; + RequestPermOnSettingAsyncContext(ani_vm* vm_, ani_env* env_); + ~RequestPermOnSettingAsyncContext() override; + bool IsSameRequest(const std::shared_ptr other) override; + void CopyResult(const std::shared_ptr other) override; + void ProcessFailResult(int32_t code) override; + void ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) override; + int32_t ConvertErrorCode(int32_t code) override; + ani_object WrapResult(ani_env* env) override; + void StartExtensionAbility(std::shared_ptr asyncContext) override; + bool CheckDynamicRequest() override; + bool NoNeedUpdate() override; }; void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, diff --git a/frameworks/ets/ani/accesstoken/src/ani_common.cpp b/frameworks/ets/ani/accesstoken/src/ani_common.cpp index 8631bf74b5a3d3b8fa3e622e852d290546c6632a..cf221cffe448378eb00a6adf31f577e2ac3732bb 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_common.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_common.cpp @@ -51,23 +51,124 @@ bool ExecuteAsyncCallback(ani_env* env, ani_object callback, ani_object error, a return true; } -OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr& abilityContext, - std::shared_ptr& uiExtensionContext, bool uiAbilityFlag) +OHOS::Ace::UIContent* GetUIContent(const std::shared_ptr stageContext) { + if (stageContext == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "stageContext is nullptr"); + return nullptr; + } OHOS::Ace::UIContent* uiContent = nullptr; - if (uiAbilityFlag) { - if (abilityContext == nullptr) { - return nullptr; - } + auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo( + stageContext); + if (abilityContext != nullptr) { uiContent = abilityContext->GetUIContent(); } else { + auto uiExtensionContext = + OHOS::AbilityRuntime::Context::ConvertTo(stageContext); if (uiExtensionContext == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ConvertTo UIExtensionContext."); return nullptr; } uiContent = uiExtensionContext->GetUIContent(); } return uiContent; } + +void CreateUIExtensionMainThread(std::shared_ptr asyncContext, + const OHOS::AAFwk::Want& want, const OHOS::Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, + const std::shared_ptr uiExtCallback) +{ + if (asyncContext == nullptr || uiExtCallback == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "asyncContext or uiExtCallback is nullptr"); + return; + } + auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { + OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->stageContext_); + if (uiContent == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Get ui content failed!"); + asyncContext->result.errorCode = AccessToken::RET_FAILED; + asyncContext->uiExtensionFlag = false; + return; + } + + OHOS::Ace::ModalUIExtensionConfig config; + config.isProhibitBack = true; + int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); + LOGI(ATM_DOMAIN, ATM_TAG, "Create end, sessionId: %{public}d, tokenId: %{public}d.", + sessionId, asyncContext->tokenId); + if (sessionId <= 0) { + LOGE(ATM_DOMAIN, ATM_TAG, "Create component failed, sessionId is invalid"); + asyncContext->result.errorCode = AccessToken::RET_FAILED; + asyncContext->uiExtensionFlag = false; + return; + } + uiExtCallback->SetSessionId(sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +void CloseModalUIExtensionMainThread(std::shared_ptr asyncContext, int32_t sessionId) +{ + if (asyncContext == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "asyncContext is nullptr"); + return; + } + auto task = [asyncContext, sessionId]() { + Ace::UIContent* uiContent = GetUIContent(asyncContext->stageContext_); + if (uiContent == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Get ui content failed!"); + asyncContext->result.errorCode = RET_FAILED; + return; + } + uiContent->CloseModalUIExtension(sessionId); + LOGI(ATM_DOMAIN, ATM_TAG, "Close end, sessionId: %{public}d", sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif + LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", asyncContext->instanceId); +} + +void CreateUIExtension( + const OHOS::AAFwk::Want& want, + std::shared_ptr asyncContext, + std::shared_ptr controller) +{ + if (asyncContext == nullptr || controller == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "asyncContext or controller is nullptr"); + return; + } + auto uiExtCallback = std::make_shared(asyncContext); + uiExtCallback->SetRequestInstanceControl(controller); + OHOS::Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { + [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); }, + [uiExtCallback]( + int32_t resultCode, const OHOS::AAFwk::Want& result) { uiExtCallback->OnResult(resultCode, result); }, + [uiExtCallback](const OHOS::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(); }, + }; + CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/src/ani_request_base.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..143da38f176e48d7c0402d8c10daee87295a393b --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ani_request_base.cpp @@ -0,0 +1,315 @@ +/* + * 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_base.h" + +#include "accesstoken_common_log.h" +#include "accesstoken_kit.h" +#include "ani_common.h" +#include "token_setproc.h" +#include "want.h" + +namespace OHOS { +namespace Security { +namespace AccessToken { + +RequestAsyncContextBase::RequestAsyncContextBase(ani_vm* vm, ani_env* env, AniRequestType type) + : vm_(vm), env_(env), contextType_(type) +{ + threadId_ = std::this_thread::get_id(); +#ifdef EVENTHANDLER_ENABLE + handler_ = std::make_shared( + AppExecFwk::EventRunner::GetMainEventRunner()); +#endif +} + +bool RequestAsyncContextBase::FillInfoFromContext(const ani_object& aniContext) +{ + if (env_ == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "env_ is nullptr."); + return false; + } + auto context = OHOS::AbilityRuntime::GetStageModeContext(env_, aniContext); + if (context == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "GetStageModeContext failed"); + return false; + } + stageContext_ = context; + auto appInfo = context->GetApplicationInfo(); + if (appInfo == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "GetApplicationInfo failed"); + return false; + } + tokenId = appInfo->accessTokenId; + bundleName = appInfo->bundleName; + return true; +} + +void RequestAsyncContextBase::GetInstanceId() +{ + auto task = [this]() { + Ace::UIContent* uiContent = GetUIContent(this->stageContext_); + if (uiContent == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Get ui content failed!"); + return; + } + this->uiContentFlag = true; + this->instanceId = uiContent->GetInstanceId(); + }; +#ifdef EVENTHANDLER_ENABLE + if (this->handler_ != nullptr) { + this->handler_->PostSyncTask(task, "AT:GetInstanceId"); + } else { + task(); + } +#else + task(); +#endif + LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", this->instanceId); +} + + +bool RequestAsyncContextBase::IsSameRequest(const std::shared_ptr other) +{ + (void) other; + return false; +} + +void RequestAsyncContextBase::CopyResult(const std::shared_ptr other) +{ + (void) other; + return; +} + +void RequestAsyncContextBase::ProcessFailResult(int32_t code) +{ + result.errorCode = code; +} + +void RequestAsyncContextBase::FinishCallback() +{ + if (vm_ == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "vm_ is nullptr."); + return; + } + bool isSameThread = IsCurrentThread(threadId_); + ani_env* env = isSameThread ? env_ : GetCurrentEnv(vm_); + if (env == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "GetCurrentEnv failed."); + return; + } + + int32_t stsCode = ConvertErrorCode(result.errorCode); + ani_object error = BusinessErrorAni::CreateError(env, stsCode, GetErrorMessage(stsCode, result.errorMsg)); + ani_object result = WrapResult(env); + (void)ExecuteAsyncCallback(env, reinterpret_cast(callbackRef), error, result); + + if (!isSameThread && vm_->DetachCurrentThread() != ANI_OK) { + LOGE(ATM_DOMAIN, ATM_TAG, "DetachCurrentThread failed!"); + } +} + +void RequestAsyncContextBase::Clear() +{ + if (vm_ == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "VM is nullptr."); + return; + } + bool isSameThread = IsCurrentThread(threadId_); + ani_env* curEnv = isSameThread ? env_ : GetCurrentEnv(vm_); + if (curEnv == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "GetCurrentEnv failed."); + return; + } + + if (callbackRef != nullptr) { + curEnv->GlobalReference_Delete(callbackRef); + callbackRef = nullptr; + } +} + +AniRequestType RequestAsyncContextBase::GetType() +{ + return contextType_; +} + +UIExtensionCallback::UIExtensionCallback(const std::shared_ptr reqContext) + :reqContext_(reqContext) +{} + +UIExtensionCallback::~UIExtensionCallback() +{} + +void UIExtensionCallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +void UIExtensionCallback::ReleaseHandler(int32_t code) +{ + { + std::lock_guard lock(this->reqContext_->lockReleaseFlag); + if (this->reqContext_->releaseFlag) { + LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed."); + return; + } + this->reqContext_->releaseFlag = true; + } + CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_); + reqContext_->ProcessFailResult(code); + controllerInstance_->UpdateQueueData(this->reqContext_); + controllerInstance_->ExecCallback(this->reqContext_->instanceId); + reqContext_->FinishCallback(); +} + +void UIExtensionCallback::OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "ResultCode is %{public}d", resultCode); + reqContext_->ProcessUIExtensionCallback(result); + ReleaseHandler(0); +} + +/* + * when UIExtensionAbility send message to UIExtensionComponent + */ +void UIExtensionCallback::OnReceive(const AAFwk::WantParams& receive) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "Called!"); +} + +/* + * when UIExtensionAbility disconnect or use terminate or process die + * releaseCode is 0 when process normal exit + */ +void UIExtensionCallback::OnRelease(int32_t releaseCode) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "ReleaseCode is %{public}d", releaseCode); + + ReleaseHandler(-1); +} + +/* + * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error + */ +void UIExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "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 UIExtensionCallback::OnRemoteReady(const std::shared_ptr& uiProxy) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully."); +} + +/* + * when UIExtensionComponent destructed + */ +void UIExtensionCallback::OnDestroy() +{ + LOGI(ATM_DOMAIN, ATM_TAG, "UIExtensionAbility destructed."); + ReleaseHandler(-1); +} + +void UIExtensionCallback::SetRequestInstanceControl(std::shared_ptr controllerInstance) +{ + this->controllerInstance_ = controllerInstance; +} + +void RequestInstanceControl::AddCallbackByInstanceId( + std::shared_ptr asyncContext) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "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()) { + LOGI(ATM_DOMAIN, ATM_TAG, "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] = {}; + } + asyncContext->StartExtensionAbility(asyncContext); +} + +void RequestInstanceControl::UpdateQueueData( + const std::shared_ptr asyncContext) +{ + if (asyncContext->NoNeedUpdate()) { + LOGI(ATM_DOMAIN, ATM_TAG, "The queue data does not need to be updated."); + return; + } + + { + std::lock_guard lock(instanceIdMutex_); + int32_t id = asyncContext->instanceId; + auto iter = instanceIdMap_.find(id); + if (iter == instanceIdMap_.end()) { + LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); + return; + } + for (auto& curContext : iter->second) { + if (curContext != nullptr && curContext->IsSameRequest(asyncContext)) { + curContext->CopyResult(asyncContext); + } + } + } +} + +void RequestInstanceControl::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()) { + LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); + return; + } + while (!iter->second.empty()) { + LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size()); + asyncContext = iter->second[0]; + iter->second.erase(iter->second.begin()); + if (asyncContext == nullptr) { + LOGI(ATM_DOMAIN, ATM_TAG, "asyncContext is nullptr."); + continue; + } + isDynamic = asyncContext->CheckDynamicRequest(); + if (isDynamic) { + break; + } + } + if (iter->second.empty()) { + LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map is empty", id); + instanceIdMap_.erase(id); + } + } + if (isDynamic) { + asyncContext->StartExtensionAbility(asyncContext); + } +} + +} // namespace AccessToken +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/src/ani_request_global_switch_on_setting.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_global_switch_on_setting.cpp index b425935f9f69c4f28075031b049756c66e1ab8c4..93d8f2a6e93c96a9d496a65ecd5c5b60c6d2c460 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_request_global_switch_on_setting.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_global_switch_on_setting.cpp @@ -15,111 +15,47 @@ #include "ani_request_global_switch_on_setting.h" #include "accesstoken_kit.h" #include "accesstoken_common_log.h" +#include "ani_common.h" #include "token_setproc.h" #include "want.h" namespace OHOS { namespace Security { namespace AccessToken { -std::map>> - RequestGlobalSwitchAsyncInstanceControl::instanceIdMap_; -std::mutex RequestGlobalSwitchAsyncInstanceControl::instanceIdMutex_; namespace { const std::string GLOBAL_SWITCH_KEY = "ohos.user.setting.global_switch"; const std::string GLOBAL_SWITCH_RESULT_KEY = "ohos.user.setting.global_switch.result"; const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code"; const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; const std::string UI_EXTENSION_TYPE = "sys/commonUI"; +std::shared_ptr g_requestInstanceControl = nullptr; +std::mutex g_requestInstanceControlLock; // error code from dialog constexpr int32_t REQUEST_REALDY_EXIST = 1; constexpr int32_t GLOBAL_TYPE_IS_NOT_SUPPORT = 2; constexpr int32_t SWITCH_IS_ALREADY_OPEN = 3; } -RequestGlobalSwitchAsyncContext::~RequestGlobalSwitchAsyncContext() -{ - if (vm == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null."); - return; - } - bool isSameThread = IsCurrentThread(threadId); - ani_env* curEnv = isSameThread ? env : GetCurrentEnv(vm); - if (curEnv == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); - return; - } - if (callbackRef != nullptr) { - curEnv->GlobalReference_Delete(callbackRef); - callbackRef = nullptr; - } -} - -static ani_status GetContext( - ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) +static std::shared_ptr GetRequestInstanceControl() { - auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); - if (context == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetStageModeContext."); - return ANI_ERROR; - } - asyncContext->abilityContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->abilityContext != nullptr) { - auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); - if (abilityInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->uiAbilityFlag = true; - asyncContext->tokenId = abilityInfo->accessTokenId; - } else { - asyncContext->uiExtensionContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->uiExtensionContext == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ConvertTo UIExtensionContext."); - return ANI_ERROR; - } - auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); - if (uiExtensionInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->tokenId = uiExtensionInfo->accessTokenId; + std::lock_guard lock(g_requestInstanceControlLock); + if (g_requestInstanceControl == nullptr) { + g_requestInstanceControl = std::make_shared(); } - return ANI_OK; + return g_requestInstanceControl; } -static bool ParseRequestGlobalSwitch(ani_env* env, ani_object& aniContext, ani_int type, - ani_object callback, std::shared_ptr& asyncContext) -{ - ani_vm* vm; - ani_status status = env->GetVM(&vm); - if (status != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast(status)); - return false; - } - asyncContext->vm = vm; - asyncContext->env = env; - asyncContext->callback = callback; - asyncContext->threadId = std::this_thread::get_id(); - asyncContext->switchType = static_cast(type); +RequestGlobalSwitchAsyncContext::RequestGlobalSwitchAsyncContext(ani_vm* vm, ani_env* env) + : RequestAsyncContextBase(vm, env, REQUEST_GLOBAL_SWITCH_ON_SETTING) +{} - if (GetContext(env, aniContext, asyncContext) != ANI_OK) { - BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, - GetParamErrorMsg("context", "UIAbility or UIExtension Context")); - 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; +RequestGlobalSwitchAsyncContext::~RequestGlobalSwitchAsyncContext() +{ + Clear(); } -static int32_t TransferToStsErrorCode(int32_t errCode) +int32_t RequestGlobalSwitchAsyncContext::ConvertErrorCode(int32_t errCode) { int32_t stsCode = STS_OK; switch (errCode) { @@ -143,328 +79,88 @@ static int32_t TransferToStsErrorCode(int32_t errCode) return stsCode; } -SwitchOnSettingUICallback::SwitchOnSettingUICallback( - const std::shared_ptr& reqContext) -{ - this->reqContext_ = reqContext; -} - -SwitchOnSettingUICallback::~SwitchOnSettingUICallback() -{} - -void SwitchOnSettingUICallback::SetSessionId(int32_t sessionId) -{ - this->sessionId_ = sessionId; -} - -static void GlobalSwitchResultsCallbackUI(bool switchStatus, std::shared_ptr& data) -{ - bool isSameThread = IsCurrentThread(data->threadId); - ani_env* env = isSameThread ? data->env : GetCurrentEnv(data->vm); - if (env == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); - return; - } - - int32_t stsCode = TransferToStsErrorCode(data->result.errorCode); - ani_object error = BusinessErrorAni::CreateError(env, stsCode, GetErrorMessage(stsCode, data->result.errorMsg)); - ExecuteAsyncCallback( - env, reinterpret_cast(data->callbackRef), error, CreateBooleanObject(env, data->switchStatus)); - - if (!isSameThread && data->vm->DetachCurrentThread() != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to DetachCurrentThread!"); - } -} - -static void CloseModalUIExtensionMainThread(std::shared_ptr& asyncContext, - int32_t sessionId) -{ - auto task = [asyncContext, sessionId]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - asyncContext->result.errorCode = RET_FAILED; - return; - } - uiContent->CloseModalUIExtension(sessionId); - LOGI(ATM_DOMAIN, ATM_TAG, "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 SwitchOnSettingUICallback::ReleaseHandler(int32_t code) +ani_object RequestGlobalSwitchAsyncContext::WrapResult(ani_env* env) { - { - std::lock_guard lock(this->reqContext_->lockReleaseFlag); - if (this->reqContext_->releaseFlag) { - LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed."); - return; - } - this->reqContext_->releaseFlag = true; - } - CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_); - if (code == -1) { - this->reqContext_->result.errorCode = code; - } - RequestGlobalSwitchAsyncInstanceControl::UpdateQueueData(this->reqContext_); - RequestGlobalSwitchAsyncInstanceControl::ExecCallback(this->reqContext_->instanceId); - GlobalSwitchResultsCallbackUI(this->reqContext_->switchStatus, this->reqContext_); + return CreateBooleanObject(env, this->switchStatus); } -/* - * when UIExtensionAbility use terminateSelfWithResult - */ -void SwitchOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result) +void RequestGlobalSwitchAsyncContext::ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) { - this->reqContext_->result.errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); - this->reqContext_->switchStatus = result.GetBoolParam(GLOBAL_SWITCH_RESULT_KEY, 0); - LOGI(ATM_DOMAIN, ATM_TAG, "ResultCode is %{public}d, errorCodeis %{public}d, switchStatus=%{public}d.", - resultCode, this->reqContext_->result.errorCode, this->reqContext_->switchStatus); - ReleaseHandler(0); + this->result.errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); + this->switchStatus = result.GetBoolParam(GLOBAL_SWITCH_RESULT_KEY, 0); } -/* - * when UIExtensionAbility send message to UIExtensionComponent - */ -void SwitchOnSettingUICallback::OnReceive(const AAFwk::WantParams& receive) +void RequestGlobalSwitchAsyncContext::StartExtensionAbility(std::shared_ptr asyncContext) { - LOGI(ATM_DOMAIN, ATM_TAG, "Called!"); -} - -/* - * when UIExtensionAbility disconnect or use terminate or process die - * releaseCode is 0 when process normal exit - */ -void SwitchOnSettingUICallback::OnRelease(int32_t releaseCode) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "ReleaseCode is %{public}d", releaseCode); - - ReleaseHandler(-1); -} - -/* - * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error - */ -void SwitchOnSettingUICallback::OnError(int32_t code, const std::string& name, const std::string& message) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "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 SwitchOnSettingUICallback::OnRemoteReady(const std::shared_ptr& uiProxy) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully."); -} - -/* - * when UIExtensionComponent destructed - */ -void SwitchOnSettingUICallback::OnDestroy() -{ - LOGI(ATM_DOMAIN, ATM_TAG, "UIExtensionAbility destructed."); - ReleaseHandler(-1); -} - -static void CreateUIExtensionMainThread(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) { - LOGE(ATM_DOMAIN, ATM_TAG, "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); - LOGI(ATM_DOMAIN, ATM_TAG, "Create end, sessionId: %{public}d, tokenId: %{public}d.", - sessionId, asyncContext->tokenId); - if (sessionId == 0) { - LOGE(ATM_DOMAIN, ATM_TAG, "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(); - }, - }; - - CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); -} - -static void StartUIExtension(std::shared_ptr& asyncContext) -{ - AccessTokenKit::GetPermissionManagerInfo(asyncContext->info); + AccessTokenKit::GetPermissionManagerInfo(this->info); LOGI(ATM_DOMAIN, ATM_TAG, "BundleName: %{public}s, permStateAbilityName: %{public}s.", - asyncContext->info.grantBundleName.c_str(), asyncContext->info.permStateAbilityName.c_str()); + this->info.grantBundleName.c_str(), this->info.permStateAbilityName.c_str()); OHOS::AAFwk::Want want; - want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.globalSwitchAbilityName); - want.SetParam(GLOBAL_SWITCH_KEY, asyncContext->switchType); + want.SetElementName(this->info.grantBundleName, this->info.globalSwitchAbilityName); + want.SetParam(GLOBAL_SWITCH_KEY, this->switchType); want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); - CreateUIExtension(want, asyncContext); + CreateUIExtension(want, asyncContext, GetRequestInstanceControl()); } -static void GetInstanceId(std::shared_ptr& asyncContext) +bool RequestGlobalSwitchAsyncContext::IsSameRequest(const std::shared_ptr other) { - auto task = [asyncContext]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - return; - } - asyncContext->instanceId = uiContent->GetInstanceId(); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId"); - } else { - task(); + if (other == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr."); + return false; } -#else - task(); -#endif - LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", asyncContext->instanceId); + auto ptr = std::static_pointer_cast(other); + return switchType == ptr->switchType; } -void RequestGlobalSwitchAsyncInstanceControl::AddCallbackByInstanceId( - std::shared_ptr& asyncContext) +void RequestGlobalSwitchAsyncContext::CopyResult(const std::shared_ptr other) { - LOGI(ATM_DOMAIN, ATM_TAG, "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()) { - LOGI(ATM_DOMAIN, ATM_TAG, "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] = {}; + if (other == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr."); + return; } - StartUIExtension(asyncContext); + auto ptr = std::static_pointer_cast(other); + this->result.errorCode = ptr->result.errorCode; + this->switchStatus = ptr->switchStatus; + this->isDynamic = false; } -void RequestGlobalSwitchAsyncInstanceControl::UpdateQueueData( - const std::shared_ptr& reqContext) +bool RequestGlobalSwitchAsyncContext::CheckDynamicRequest() { - if ((reqContext->result.errorCode != RET_SUCCESS) || !(reqContext->switchStatus)) { - LOGI(ATM_DOMAIN, ATM_TAG, "The queue data does not need to be updated."); - return; + if (!this->isDynamic) { + LOGI(ATM_DOMAIN, ATM_TAG, "It does not need to request permission extension"); + FinishCallback(); + return false; } + return true; +} - { - std::lock_guard lock(instanceIdMutex_); - int32_t id = reqContext->instanceId; - auto iter = instanceIdMap_.find(id); - if (iter == instanceIdMap_.end()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); - return; - } - int32_t targetSwitchType = reqContext->switchType; - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size()); - for (auto& asyncContext : iter->second) { - if (targetSwitchType == asyncContext->switchType) { - asyncContext->result.errorCode = reqContext->result.errorCode; - asyncContext->switchStatus = reqContext->switchStatus; - asyncContext->isDynamic = false; - } - } - } +bool RequestGlobalSwitchAsyncContext::NoNeedUpdate() +{ + return result.errorCode != RET_SUCCESS || switchStatus == false; } -void RequestGlobalSwitchAsyncInstanceControl::ExecCallback(int32_t id) +void RequestGlobalSwitchAsyncContext::ProcessFailResult(int32_t code) { - std::shared_ptr asyncContext = nullptr; - bool isDynamic = false; - { - std::lock_guard lock(instanceIdMutex_); - auto iter = instanceIdMap_.find(id); - if (iter == instanceIdMap_.end()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); - return; - } - while (!iter->second.empty()) { - LOGI(ATM_DOMAIN, ATM_TAG, "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()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map is empty.", id); - instanceIdMap_.erase(id); - } - } - if (isDynamic) { - StartUIExtension(asyncContext); + if (code == -1) { + result.errorCode = code; } } -void RequestGlobalSwitchAsyncInstanceControl::CheckDynamicRequest( - std::shared_ptr& asyncContext, bool& isDynamic) +static bool ParseRequestGlobalSwitch(ani_env* env, ani_object& aniContext, ani_int type, + ani_object callback, std::shared_ptr& asyncContext) { - isDynamic = asyncContext->isDynamic; - if (!isDynamic) { - LOGI(ATM_DOMAIN, ATM_TAG, "It does not need to request permission exsion."); - GlobalSwitchResultsCallbackUI(asyncContext->switchStatus, asyncContext); - return; + asyncContext->switchType = static_cast(type); + + if (!asyncContext->FillInfoFromContext(aniContext) != ANI_OK) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("context", "UIAbility or UIExtension Context")); + return false; + } + if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { + return false; } + return true; } void RequestGlobalSwitchExecute([[maybe_unused]] ani_env* env, @@ -475,8 +171,14 @@ void RequestGlobalSwitchExecute([[maybe_unused]] ani_env* env, return; } + ani_vm* vm; + ani_status status = env->GetVM(&vm); + if (status != ANI_OK) { + LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast(status)); + return; + } std::shared_ptr asyncContext = - std::make_shared(); + std::make_shared(vm, env); if (!ParseRequestGlobalSwitch(env, aniContext, type, callback, asyncContext)) { return; } @@ -489,18 +191,15 @@ void RequestGlobalSwitchExecute([[maybe_unused]] ani_env* env, 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); + (void)ExecuteAsyncCallback(env, callback, error, result); return; } - GetInstanceId(asyncContext); - RequestGlobalSwitchAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + asyncContext->GetInstanceId(); + GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext); LOGI(ATM_DOMAIN, ATM_TAG, "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); + asyncContext->FinishCallback(); LOGW(ATM_DOMAIN, ATM_TAG, "Failed to pop uiextension dialog."); } } diff --git a/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp index 6e4ac4ca11cc19843625da849be0e3ccf4d20fc4..96ec8c3180d0dafdfac621f8b393002d3fc9d736 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission.cpp @@ -22,6 +22,7 @@ #include "ability_manager_client.h" #include "accesstoken_kit.h" #include "accesstoken_common_log.h" +#include "ani_common.h" #include "hisysevent.h" #include "token_setproc.h" #include "want.h" @@ -29,11 +30,8 @@ namespace OHOS { namespace Security { namespace AccessToken { -std::map>> RequestAsyncInstanceControl::instanceIdMap_; -std::mutex RequestAsyncInstanceControl::instanceIdMutex_; namespace { #define SETTER_METHOD_NAME(property) "" #property -std::mutex g_lockFlag; const std::string PERMISSION_KEY = "ohos.user.grant.permission"; const std::string STATE_KEY = "ohos.user.grant.permission.state"; const std::string RESULT_KEY = "ohos.user.grant.permission.result"; @@ -47,23 +45,86 @@ 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"; +std::shared_ptr g_requestInstanceControl = nullptr; +std::mutex g_requestInstanceControlLock; } + +static std::shared_ptr GetRequestInstanceControl() +{ + std::lock_guard lock(g_requestInstanceControlLock); + if (g_requestInstanceControl == nullptr) { + g_requestInstanceControl = std::make_shared(); + } + return g_requestInstanceControl; +} + +RequestAsyncContext::RequestAsyncContext(ani_vm* vm, ani_env* env) + : RequestAsyncContextBase(vm, env, REQUEST_PERMISSIONS_FROM_USER) +{} + RequestAsyncContext::~RequestAsyncContext() { - if (vm == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null."); + Clear(); +} + +static void CreateServiceExtension(std::shared_ptr asyncContext) +{ + auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo( + asyncContext->stageContext_); + if (abilityContext == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Convert to AbilityContext failed. " \ + "UIExtension ability can not pop service ablility window!"); + asyncContext->needDynamicRequest = false; + asyncContext->result.errorCode = RET_FAILED; return; } - bool isSameThread = IsCurrentThread(threadId); - ani_env* curEnv = isSameThread ? env : GetCurrentEnv(vm); - if (curEnv == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); + OHOS::sptr remoteObject = new (std::nothrow) AuthorizationResult(asyncContext); + if (remoteObject == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Create window failed!"); + asyncContext->needDynamicRequest = false; + asyncContext->result.errorCode = RET_FAILED; return; } + OHOS::AAFwk::Want want; + want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName); + want.SetParam(PERMISSION_KEY, asyncContext->permissionList); + want.SetParam(STATE_KEY, asyncContext->permissionsState); + want.SetParam(TOKEN_KEY, abilityContext->GetToken()); + want.SetParam(CALLBACK_KEY, remoteObject); + + int32_t left = 0; + int32_t top = 0; + int32_t width = 0; + int32_t height = 0; + abilityContext->GetWindowRect(left, top, width, height); + want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left); + want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top); + want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width); + want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height); + want.SetParam(REQUEST_TOKEN_KEY, abilityContext->GetToken()); + int32_t ret = OHOS::AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService( + want, abilityContext->GetToken()); + LOGI(ATM_DOMAIN, ATM_TAG, "Request end, ret: %{public}d, tokenId: %{public}d, permNum: %{public}zu", ret, + asyncContext->tokenId, asyncContext->permissionList.size()); +} - if (callbackRef != nullptr) { - curEnv->GlobalReference_Delete(callbackRef); - callbackRef = nullptr; +void RequestAsyncContext::StartExtensionAbility(std::shared_ptr asyncContext) +{ + if (asyncContext == nullptr) { + LOGI(ATM_DOMAIN, ATM_TAG, "asyncContext is nullptr."); + return; + } + if (uiExtensionFlag) { + OHOS::AAFwk::Want want; + want.SetElementName(this->info.grantBundleName, this->info.grantAbilityName); + want.SetParam(PERMISSION_KEY, this->permissionList); + want.SetParam(STATE_KEY, this->permissionsState); + want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); + CreateUIExtension(want, + std::static_pointer_cast(asyncContext), + GetRequestInstanceControl()); + } else { + CreateServiceExtension(std::static_pointer_cast(asyncContext)); } } @@ -73,45 +134,49 @@ static inline bool CallSetter(ani_env* env, ani_class cls, ani_object object, co ani_status status = ANI_ERROR; ani_field fieldValue; if (env->Class_FindField(cls, setterName, &fieldValue) != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Class_FindField %{public}d, name: %{public}s.", + LOGE(ATM_DOMAIN, ATM_TAG, "Class_FindField Fail %{public}d, name: %{public}s.", static_cast(status), setterName); return false; } if ((status = env->Object_SetField_Ref(object, fieldValue, value)) != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Object_SetField_Ref %{public}d, name: %{public}s.", + LOGE(ATM_DOMAIN, ATM_TAG, "Object_SetField_Ref Fail %{public}d, name: %{public}s.", static_cast(status), setterName); return false; } return true; } -static ani_object WrapResult(ani_env* env, std::shared_ptr& asyncContext) +ani_object RequestAsyncContext::WrapResult(ani_env* env) { ani_status status = ANI_ERROR; ani_class cls = nullptr; + if (env == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "env is nullptr"); + return nullptr; + } if ((status = env->FindClass("Lsecurity/PermissionRequestResult/PermissionRequestResult;", &cls)) != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "FindClass status %{public}d.", static_cast(status)); + LOGE(ATM_DOMAIN, ATM_TAG, "FindClass status %{public}d ", static_cast(status)); return nullptr; } if (cls == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Cls is null."); + LOGE(ATM_DOMAIN, ATM_TAG, "null cls"); return nullptr; } ani_method method = nullptr; if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Class_FindMethod status %{public}d.", static_cast(status)); + LOGE(ATM_DOMAIN, ATM_TAG, "Class_FindMethod status %{public}d ", static_cast(status)); return nullptr; } ani_object aObject = nullptr; if ((status = env->Object_New(cls, method, &aObject)) != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Object_New status %{public}d.", static_cast(status)); + LOGE(ATM_DOMAIN, ATM_TAG, "Object_New status %{public}d ", static_cast(status)); return nullptr; } - auto state = asyncContext->needDynamicRequest ? asyncContext->grantResults : asyncContext->permissionsState; - ani_ref aniPerms = CreateAniArrayString(env, asyncContext->permissionList); + auto state = this->needDynamicRequest ? this->grantResults : this->permissionsState; + ani_ref aniPerms = CreateAniArrayString(env, permissionList); ani_ref aniAuthRes = CreateAniArrayInt(env, state); - ani_ref aniDiasShownRes = CreateAniArrayBool(env, asyncContext->dialogShownResults); - ani_ref aniErrorReasons = CreateAniArrayInt(env, asyncContext->errorReasons); + ani_ref aniDiasShownRes = CreateAniArrayBool(env, dialogShownResults); + ani_ref aniErrorReasons = CreateAniArrayInt(env, errorReasons); if (aniPerms == nullptr || aniAuthRes == nullptr || aniDiasShownRes == nullptr || aniErrorReasons == nullptr || !CallSetter(env, cls, aObject, SETTER_METHOD_NAME(permissions), aniPerms) || !CallSetter(env, cls, aObject, SETTER_METHOD_NAME(authResults), aniAuthRes) || @@ -126,40 +191,42 @@ static ani_object WrapResult(ani_env* env, std::shared_ptr& return aObject; } -static void UpdateGrantPermissionResultOnly(const std::vector& permissions, - const std::vector& grantResults, - std::shared_ptr& data, - std::vector& newGrantResults) +void RequestAsyncContext::HandleResult(const std::vector& permissionList, + const std::vector& grantResults) { - size_t size = permissions.size(); + std::vector newGrantResults; + size_t size = permissionList.size(); for (size_t i = 0; i < size; 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; + int32_t result = static_cast(this->permissionsState[i]); + if (this->permissionsState[i] == AccessToken::DYNAMIC_OPER) { + result = this->result.errorCode == AccessToken::RET_SUCCESS ? + grantResults[i] : AccessToken::INVALID_OPER; } newGrantResults.emplace_back(result); } + + if (newGrantResults.empty()) { + LOGE(ATM_DOMAIN, ATM_TAG, "GrantResults empty"); + result.errorCode = RET_FAILED; + } + this->grantResults.assign(newGrantResults.begin(), newGrantResults.end()); } -static bool IsDynamicRequest(std::shared_ptr& asyncContext) +bool RequestAsyncContext::IsDynamicRequest() { - if (asyncContext == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "AsyncContext is null."); - return false; - } std::vector permList; - for (const auto& permission : asyncContext->permissionList) { + for (const auto& permission : this->permissionList) { AccessToken::PermissionListState permState; permState.permissionName = permission; permState.errorReason = SERVICE_ABNORMAL; permState.state = AccessToken::INVALID_OPER; permList.emplace_back(permState); } - auto ret = AccessToken::AccessTokenKit::GetSelfPermissionsState(permList, asyncContext->info); + auto ret = AccessToken::AccessTokenKit::GetSelfPermissionsState(permList, this->info); LOGI(ATM_DOMAIN, ATM_TAG, "TokenID: %{public}d, bundle: %{public}s, uiExAbility: %{public}s, serExAbility: %{public}s.", - asyncContext->tokenId, asyncContext->info.grantBundleName.c_str(), asyncContext->info.grantAbilityName.c_str(), - asyncContext->info.grantServiceAbilityName.c_str()); + this->tokenId, this->info.grantBundleName.c_str(), this->info.grantAbilityName.c_str(), + this->info.grantServiceAbilityName.c_str()); if (ret == AccessToken::FORBIDDEN_OPER) { LOGE(ATM_DOMAIN, ATM_TAG, "FORBIDDEN_OPER"); for (auto& perm : permList) { @@ -168,223 +235,67 @@ static bool IsDynamicRequest(std::shared_ptr& asyncContext) } } for (const auto& permState : permList) { - LOGI(ATM_DOMAIN, ATM_TAG, "Permission: %{public}s: state: %{public}d, errorReason: %{public}d.", + LOGI(ATM_DOMAIN, ATM_TAG, "Permission: %{public}s: state: %{public}d, errorReason: %{public}d", permState.permissionName.c_str(), permState.state, permState.errorReason); - asyncContext->permissionsState.emplace_back(permState.state); - asyncContext->dialogShownResults.emplace_back(permState.state == AccessToken::TypePermissionOper::DYNAMIC_OPER); - asyncContext->errorReasons.emplace_back(permState.errorReason); + this->permissionsState.emplace_back(permState.state); + this->dialogShownResults.emplace_back(permState.state == AccessToken::TypePermissionOper::DYNAMIC_OPER); + this->errorReasons.emplace_back(permState.errorReason); } - if (permList.size() != asyncContext->permissionList.size()) { - LOGE(ATM_DOMAIN, ATM_TAG, "PermList.size: %{public}zu, permissionList.size: %{public}zu.", permList.size(), - asyncContext->permissionList.size()); + if (permList.size() != this->permissionList.size()) { + LOGE(ATM_DOMAIN, ATM_TAG, "permList.size: %{public}zu, permissionList.size: %{public}zu", permList.size(), + this->permissionList.size()); return false; } return ret == AccessToken::TypePermissionOper::DYNAMIC_OPER; } -static void CreateUIExtensionMainThread(std::shared_ptr& asyncContext, - const OHOS::AAFwk::Want& want, const OHOS::Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks, - const std::shared_ptr& uiExtCallback) -{ - auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - asyncContext->result.errorCode = AccessToken::RET_FAILED; - asyncContext->uiExtensionFlag = false; - return; - } - - OHOS::Ace::ModalUIExtensionConfig config; - config.isProhibitBack = true; - int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); - if (sessionId == 0) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Create component, sessionId is 0"); - asyncContext->result.errorCode = AccessToken::RET_FAILED; - asyncContext->uiExtensionFlag = false; - return; - } - uiExtCallback->SetSessionId(sessionId); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); - } else { - task(); - } -#else - task(); -#endif -} - -static void CreateServiceExtension(std::shared_ptr& asyncContext) +bool RequestAsyncContext::CheckDynamicRequest() { - if (!asyncContext->uiAbilityFlag) { - LOGE(ATM_DOMAIN, ATM_TAG, "UIExtension ability can not pop service ablility window!"); - asyncContext->needDynamicRequest = false; - asyncContext->result.errorCode = RET_FAILED; - return; - } - OHOS::sptr remoteObject = new (std::nothrow) AuthorizationResult(asyncContext); - if (remoteObject == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Create window!"); - asyncContext->needDynamicRequest = false; - asyncContext->result.errorCode = RET_FAILED; - return; + permissionsState.clear(); + dialogShownResults.clear(); + if (!IsDynamicRequest()) { + HandleResult(this->permissionList, this->permissionsState); + FinishCallback(); + return false; } - OHOS::AAFwk::Want want; - want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName); - want.SetParam(PERMISSION_KEY, asyncContext->permissionList); - want.SetParam(STATE_KEY, asyncContext->permissionsState); - want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken()); - want.SetParam(CALLBACK_KEY, remoteObject); - - 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); - want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width); - want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height); - want.SetParam(REQUEST_TOKEN_KEY, asyncContext->abilityContext->GetToken()); - int32_t ret = OHOS::AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService( - want, asyncContext->abilityContext->GetToken()); - LOGI(ATM_DOMAIN, ATM_TAG, "Request end, ret: %{public}d, tokenId: %{public}d, permNum: %{public}zu。", ret, - asyncContext->tokenId, asyncContext->permissionList.size()); -} - -static void CreateUIExtension(std::shared_ptr& asyncContext) -{ - OHOS::AAFwk::Want want; - want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantAbilityName); - want.SetParam(PERMISSION_KEY, asyncContext->permissionList); - want.SetParam(STATE_KEY, asyncContext->permissionsState); - want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); - - auto uiExtCallback = std::make_shared(asyncContext); - OHOS::Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { - [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); }, - [uiExtCallback]( - int32_t resultCode, const OHOS::AAFwk::Want& result) { uiExtCallback->OnResult(resultCode, result); }, - [uiExtCallback](const OHOS::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(); }, - }; - CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); + return true; } -static void GetInstanceId(std::shared_ptr& asyncContext) +void RequestAsyncContext::ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) { - auto task = [asyncContext]() { - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content failed!"); - return; - } - asyncContext->uiContentFlag = true; - asyncContext->instanceId = uiContent->GetInstanceId(); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId"); - } else { - task(); - } -#else - task(); -#endif + this->permissionList = result.GetStringArrayParam(PERMISSION_KEY); + this->permissionsState = result.GetIntArrayParam(RESULT_KEY); + HandleResult(permissionList, permissionsState); } -static void RequestResultsHandler(const std::vector& permissionList, - const std::vector& permissionStates, std::shared_ptr& data) +int32_t RequestAsyncContext::ConvertErrorCode(int32_t code) { - std::vector newGrantResults; - UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults); - if (newGrantResults.empty()) { - LOGE(ATM_DOMAIN, ATM_TAG, "Empty grantResults."); - data->result.errorCode = RET_FAILED; - } - data->grantResults.assign(newGrantResults.begin(), newGrantResults.end()); - - bool isSameThread = IsCurrentThread(data->threadId); - ani_env* env = isSameThread ? data->env : GetCurrentEnv(data->vm); - if (env == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); - 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) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to DetachCurrentThread!"); - } + return BusinessErrorAni::GetStsErrorCode(result.errorCode); } -static ani_status ConvertContext( - ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) +bool RequestAsyncContext::NoNeedUpdate() { - auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); - if (context == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetStageModeContext."); - return ANI_ERROR; - } - asyncContext->abilityContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->abilityContext != nullptr) { - auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); - if (abilityInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->uiAbilityFlag = true; - asyncContext->tokenId = abilityInfo->accessTokenId; - asyncContext->bundleName = abilityInfo->bundleName; - } else { - asyncContext->uiExtensionContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->uiExtensionContext == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ConvertTo UIExtensionContext."); - return ANI_ERROR; - } - auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); - if (uiExtensionInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->tokenId = uiExtensionInfo->accessTokenId; - asyncContext->bundleName = uiExtensionInfo->bundleName; - } - return ANI_OK; + return true; } static void RequestPermissionsFromUserProcess(std::shared_ptr& asyncContext) { - if (!IsDynamicRequest(asyncContext)) { - LOGE(ATM_DOMAIN, ATM_TAG, "It does not need to request permission."); + if (!asyncContext->IsDynamicRequest()) { + LOGE(ATM_DOMAIN, ATM_TAG, "It does not need to request permission"); asyncContext->needDynamicRequest = false; if ((asyncContext->permissionsState.empty()) && (asyncContext->result.errorCode == RET_SUCCESS)) { - LOGE(ATM_DOMAIN, ATM_TAG, "Empty GrantResults."); + LOGE(ATM_DOMAIN, ATM_TAG, "GrantResults empty"); asyncContext->result.errorCode = RET_FAILED; } return; } - GetInstanceId(asyncContext); + asyncContext->GetInstanceId(); if (asyncContext->info.grantBundleName == ORI_PERMISSION_MANAGER_BUNDLE_NAME) { LOGI(ATM_DOMAIN, ATM_TAG, - "Pop service extension dialog, uiContentFlag=%{public}d.", asyncContext->uiContentFlag); + "Pop service extension dialog, uiContentFlag=%{public}d", asyncContext->uiContentFlag); if (asyncContext->uiContentFlag) { - RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext); } else { CreateServiceExtension(asyncContext); } @@ -395,36 +306,24 @@ static void RequestPermissionsFromUserProcess(std::shared_ptrbundleName.c_str(), "UIEXTENSION_FLAG", false); } else { - LOGI(ATM_DOMAIN, ATM_TAG, "Pop ui extension dialog."); + LOGI(ATM_DOMAIN, ATM_TAG, "Pop ui extension dialog"); asyncContext->uiExtensionFlag = true; - RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext); (void)HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER", HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "BUNDLENAME", asyncContext->bundleName, "UIEXTENSION_FLAG", false); if (!asyncContext->uiExtensionFlag) { LOGW(ATM_DOMAIN, ATM_TAG, "Pop uiextension dialog fail, start to pop service extension dialog."); - RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext); } } } -static bool ParseRequestPermissionFromUser(ani_env* env, ani_object aniContext, ani_array_ref aniPermissionList, +static bool ParseParameter(ani_env* env, ani_object aniContext, ani_array_ref aniPermissionList, ani_object callback, std::shared_ptr& asyncContext) { - ani_vm* vm; - ani_status status = env->GetVM(&vm); - if (status != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast(status)); - return false; - } - 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) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ConvertContext, error=%{public}d.", static_cast(status)); + if (!asyncContext->FillInfoFromContext(aniContext)) { + LOGE(ATM_DOMAIN, ATM_TAG, "FillInfoFromContext failed."); BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, GetParamErrorMsg("context", "UIAbility or UIExtension Context")); return false; @@ -433,9 +332,6 @@ static bool ParseRequestPermissionFromUser(ani_env* env, ani_object aniContext, if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { return false; } -#ifdef EVENTHANDLER_ENABLE - asyncContext->handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); -#endif return true; } @@ -443,11 +339,17 @@ void RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_un ani_object aniContext, ani_array_ref aniPermissionList, ani_object callback) { if (env == nullptr || aniPermissionList == nullptr || callback == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Env or aniPermissionList or callback is null."); + LOGE(ATM_DOMAIN, ATM_TAG, "env or aniPermissionList or callback is null."); return; } - std::shared_ptr asyncContext = std::make_shared(); - if (!ParseRequestPermissionFromUser(env, aniContext, aniPermissionList, callback, asyncContext)) { + ani_vm* vm; + ani_status status = env->GetVM(&vm); + if (status != ANI_OK) { + LOGE(ATM_DOMAIN, ATM_TAG, "GetVM failed, error=%{public}d.", static_cast(status)); + return; + } + std::shared_ptr asyncContext = std::make_shared(vm, env); + if (!ParseParameter(env, aniContext, aniPermissionList, callback, asyncContext)) { return; } @@ -461,179 +363,27 @@ void RequestPermissionsFromUserExecute([[maybe_unused]] ani_env* env, [[maybe_un 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); + (void)ExecuteAsyncCallback(env, callback, error, result); return; } 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); - LOGI(ATM_DOMAIN, ATM_TAG, "UiExtensionFlag: %{public}d, uiContentFlag: %{public}d, uiAbilityFlag: %{public}d.", - asyncContext->uiExtensionFlag, asyncContext->uiContentFlag, asyncContext->uiAbilityFlag); -} - -static void CloseModalUIExtensionMainThread(std::shared_ptr& asyncContext, int32_t sessionId) -{ - auto task = [asyncContext, sessionId]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - asyncContext->result.errorCode = RET_FAILED; - return; - } - uiContent->CloseModalUIExtension(sessionId); - LOGI(ATM_DOMAIN, ATM_TAG, "Close end, sessionId: %{public}d.", sessionId); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread"); - } else { - task(); - } -#else - task(); -#endif - LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", asyncContext->instanceId); + asyncContext->FinishCallback(); + LOGI(ATM_DOMAIN, ATM_TAG, "uiExtensionFlag: %{public}d, uiContentFlag: %{public}d", + asyncContext->uiExtensionFlag, asyncContext->uiContentFlag); } -void RequestAsyncInstanceControl::ExecCallback(int32_t id) -{ - std::shared_ptr asyncContext = nullptr; - bool isDynamic = false; - { - std::lock_guard lock(instanceIdMutex_); - auto iter = RequestAsyncInstanceControl::instanceIdMap_.find(id); - if (iter == RequestAsyncInstanceControl::instanceIdMap_.end()) { - LOGE(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); - return; - } - while (!iter->second.empty()) { - LOGI(ATM_DOMAIN, ATM_TAG, "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()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map is empty.", id); - RequestAsyncInstanceControl::instanceIdMap_.erase(id); - } - } - if (isDynamic) { - if (asyncContext->uiExtensionFlag) { - CreateUIExtension(asyncContext); - } else { - CreateServiceExtension(asyncContext); - } - } -} - -void RequestAsyncInstanceControl::CheckDynamicRequest( - std::shared_ptr& asyncContext, bool& isDynamic) -{ - asyncContext->permissionsState.clear(); - asyncContext->dialogShownResults.clear(); - if (!IsDynamicRequest(asyncContext)) { - RequestResultsHandler(asyncContext->permissionList, asyncContext->permissionsState, asyncContext); - return; - } - isDynamic = true; -} - -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; - } - RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId] = {}; - } - if (asyncContext->uiExtensionFlag) { - CreateUIExtension(asyncContext); - } else { - CreateServiceExtension(asyncContext); - } - return; -} - -UIExtensionCallback::UIExtensionCallback(const std::shared_ptr& reqContext) -{ - this->reqContext_ = reqContext; -} - -UIExtensionCallback::~UIExtensionCallback() {} - -void UIExtensionCallback::SetSessionId(int32_t sessionId) -{ - this->sessionId_ = sessionId; -} - -void UIExtensionCallback::ReleaseHandler(int32_t code) -{ - { - std::lock_guard lock(g_lockFlag); - if (this->reqContext_->releaseFlag) { - LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed."); - return; - } - this->reqContext_->releaseFlag = true; - } - CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_); - this->reqContext_->result.errorCode = code; - LOGE(ATM_DOMAIN, ATM_TAG, "ReleaseHandler errorCode: %{public}d.", - this->reqContext_->result.errorCode); - RequestAsyncInstanceControl::ExecCallback(this->reqContext_->instanceId); - RequestResultsHandler(this->reqContext_->permissionList, this->reqContext_->permissionsState, this->reqContext_); -} - -void UIExtensionCallback::OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "ResultCode is %{public}d.", resultCode); - this->reqContext_->permissionList = result.GetStringArrayParam(PERMISSION_KEY); - this->reqContext_->permissionsState = result.GetIntArrayParam(RESULT_KEY); - ReleaseHandler(0); -} - -void UIExtensionCallback::OnReceive(const OHOS::AAFwk::WantParams& receive) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "Called!"); -} - -void UIExtensionCallback::OnRelease(int32_t releaseCode) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "ReleaseCode is %{public}d.", releaseCode); - ReleaseHandler(-1); -} - -void UIExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message) -{ - LOGI(ATM_DOMAIN, ATM_TAG, - "Code is %{public}d, name is %{public}s, message is %{public}s.", code, name.c_str(), message.c_str()); - - ReleaseHandler(-1); -} -void UIExtensionCallback::OnRemoteReady(const std::shared_ptr& uiProxy) +AuthorizationResult::AuthorizationResult(std::shared_ptr& data) : data_(data) { - LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully."); + LOGI(ATM_DOMAIN, ATM_TAG, "AuthorizationResult"); } -void UIExtensionCallback::OnDestroy() +AuthorizationResult::~AuthorizationResult() { - LOGI(ATM_DOMAIN, ATM_TAG, "UIExtensionAbility destructed."); - ReleaseHandler(-1); + LOGI(ATM_DOMAIN, ATM_TAG, "~AuthorizationResult"); } void AuthorizationResult::GrantResultsCallback( @@ -643,8 +393,9 @@ void AuthorizationResult::GrantResultsCallback( if (asyncContext == nullptr) { return; } - LOGE(ATM_DOMAIN, ATM_TAG, "GrantResultsCallback."); - RequestResultsHandler(permissionList, grantResults, asyncContext); + LOGI(ATM_DOMAIN, ATM_TAG, "GrantResultsCallback"); + asyncContext->HandleResult(permissionList, grantResults); + asyncContext->FinishCallback(); } void AuthorizationResult::WindowShownCallback() @@ -653,12 +404,11 @@ void AuthorizationResult::WindowShownCallback() if (asyncContext == nullptr) { return; } - OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); + OHOS::Ace::UIContent* uiContent = GetUIContent(asyncContext->stageContext_); if ((uiContent == nullptr) || !(asyncContext->uiContentFlag)) { return; } - RequestAsyncInstanceControl::ExecCallback(asyncContext->instanceId); + GetRequestInstanceControl()->ExecCallback(asyncContext->instanceId); } } // namespace AccessToken } // namespace Security 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 index d10008ac038ab3701c41d375cd8c7b483261acc1..e1cfcb1baf7e068ffe9bba2d601ee5a943da96ff 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp @@ -15,15 +15,13 @@ #include "ani_request_permission_on_setting.h" #include "accesstoken_kit.h" #include "accesstoken_common_log.h" +#include "ani_common.h" #include "token_setproc.h" #include "want.h" namespace OHOS { namespace Security { namespace AccessToken { -std::map>> - RequestOnSettingAsyncInstanceControl::instanceIdMap_; -std::mutex RequestOnSettingAsyncInstanceControl::instanceIdMutex_; namespace { constexpr int32_t REQUEST_REALDY_EXIST = 1; constexpr int32_t PERM_NOT_BELONG_TO_SAME_GROUP = 2; @@ -35,88 +33,26 @@ 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"; +std::shared_ptr g_requestInstanceControl = nullptr; +std::mutex g_requestInstanceControlLock; } -RequestPermOnSettingAsyncContext::~RequestPermOnSettingAsyncContext() -{ - if (vm == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Vm is null."); - return; - } - bool isSameThread = IsCurrentThread(threadId); - ani_env* curEnv = isSameThread ? env : GetCurrentEnv(vm); - if (curEnv == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); - return; - } - if (callbackRef != nullptr) { - curEnv->GlobalReference_Delete(callbackRef); - callbackRef = nullptr; - } -} - -static ani_status GetContext( - ani_env* env, const ani_object& aniContext, std::shared_ptr& asyncContext) +static std::shared_ptr GetRequestInstanceControl() { - auto context = OHOS::AbilityRuntime::GetStageModeContext(env, aniContext); - if (context == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetStageModeContext"); - return ANI_ERROR; - } - asyncContext->abilityContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->abilityContext != nullptr) { - auto abilityInfo = asyncContext->abilityContext->GetApplicationInfo(); - if (abilityInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->uiAbilityFlag = true; - asyncContext->tokenId = abilityInfo->accessTokenId; - } else { - asyncContext->uiExtensionContext = - OHOS::AbilityRuntime::Context::ConvertTo(context); - if (asyncContext->uiExtensionContext == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to ConvertTo UIExtensionContext."); - return ANI_ERROR; - } - auto uiExtensionInfo = asyncContext->uiExtensionContext->GetApplicationInfo(); - if (uiExtensionInfo == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetApplicationInfo."); - return ANI_ERROR; - } - asyncContext->tokenId = uiExtensionInfo->accessTokenId; + std::lock_guard lock(g_requestInstanceControlLock); + if (g_requestInstanceControl == nullptr) { + g_requestInstanceControl = std::make_shared(); } - return ANI_OK; + return g_requestInstanceControl; } -static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext, ani_array_ref& aniPermissionList, - ani_object callback, std::shared_ptr& asyncContext) -{ - ani_vm* vm; - ani_status status = env->GetVM(&vm); - if (status != ANI_OK) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast(status)); - return false; - } - asyncContext->vm = vm; - asyncContext->env = env; - asyncContext->callback = callback; - asyncContext->threadId = std::this_thread::get_id(); +RequestPermOnSettingAsyncContext::RequestPermOnSettingAsyncContext(ani_vm* vm, ani_env* env) + : RequestAsyncContextBase(vm, env, REQUEST_PERMISSION_ON_SETTING) +{} - if (GetContext(env, aniContext, asyncContext) != ANI_OK) { - BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, - GetParamErrorMsg("context", "UIAbility or UIExtension Context")); - return false; - } - asyncContext->permissionList = ParseAniStringVector(env, aniPermissionList); - if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { - return false; - } -#ifdef EVENTHANDLER_ENABLE - asyncContext->handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); -#endif - return true; +RequestPermOnSettingAsyncContext::~RequestPermOnSettingAsyncContext() +{ + Clear(); } static void StateToEnumIndex(int32_t state, ani_size& enumIndex) @@ -128,7 +64,7 @@ static void StateToEnumIndex(int32_t state, ani_size& enumIndex) } } -static ani_object ReturnResult(ani_env* env, std::shared_ptr& asyncContext) +ani_object RequestPermOnSettingAsyncContext::WrapResult(ani_env* env) { ani_class arrayCls = nullptr; if (env->FindClass("Lescompat/Array;", &arrayCls) != ANI_OK) { @@ -143,7 +79,7 @@ static ani_object ReturnResult(ani_env* env, std::shared_ptrObject_New(arrayCls, arrayCtor, &arrayObj, asyncContext->stateList.size()) != ANI_OK) { + if (env->Object_New(arrayCls, arrayCtor, &arrayObj, this->stateList.size()) != ANI_OK) { LOGE(ATM_DOMAIN, ATM_TAG, "Object new failed!"); return nullptr; } @@ -156,7 +92,7 @@ static ani_object ReturnResult(ani_env* env, std::shared_ptrstateList) { + for (const auto& state: this->stateList) { ani_enum_item enumItem; ani_size enumIndex = 0; StateToEnumIndex(state, enumIndex); @@ -175,7 +111,7 @@ static ani_object ReturnResult(ani_env* env, std::shared_ptr& reqContext) -{ - this->reqContext_ = reqContext; -} - -PermissonOnSettingUICallback::~PermissonOnSettingUICallback() -{} - -void PermissonOnSettingUICallback::SetSessionId(int32_t sessionId) +void RequestPermOnSettingAsyncContext::ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result) { - this->sessionId_ = sessionId; + this->result.errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0); + this->stateList = result.GetIntArrayParam(PERMISSION_RESULT_KEY); } -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) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetCurrentEnv."); - 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) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to DetachCurrentThread!"); - } -} - -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) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - asyncContext->result.errorCode = RET_FAILED; - return; - } - uiContent->CloseModalUIExtension(sessionId); - LOGI(ATM_DOMAIN, ATM_TAG, "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->reqContext_->lockReleaseFlag); - if (this->reqContext_->releaseFlag) { - LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed."); - return; - } - this->reqContext_->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); - LOGI(ATM_DOMAIN, ATM_TAG, "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) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "Called!"); -} - -/* - * when UIExtensionAbility disconnect or use terminate or process die - * releaseCode is 0 when process normal exit - */ -void PermissonOnSettingUICallback::OnRelease(int32_t releaseCode) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "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) +void RequestPermOnSettingAsyncContext::StartExtensionAbility(std::shared_ptr asyncContext) { - LOGI(ATM_DOMAIN, ATM_TAG, "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) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully."); -} - -/* - * when UIExtensionComponent destructed - */ -void PermissonOnSettingUICallback::OnDestroy() -{ - LOGI(ATM_DOMAIN, ATM_TAG, "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) { - LOGE(ATM_DOMAIN, ATM_TAG, "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); - LOGI(ATM_DOMAIN, ATM_TAG, "Create end, sessionId: %{public}d, tokenId: %{public}d.", - sessionId, asyncContext->tokenId); - if (sessionId == 0) { - LOGE(ATM_DOMAIN, ATM_TAG, "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); + AccessTokenKit::GetPermissionManagerInfo(this->info); LOGI(ATM_DOMAIN, ATM_TAG, "BundleName: %{public}s, permStateAbilityName: %{public}s.", - asyncContext->info.grantBundleName.c_str(), asyncContext->info.permStateAbilityName.c_str()); + this->info.grantBundleName.c_str(), this->info.permStateAbilityName.c_str()); OHOS::AAFwk::Want want; - want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.permStateAbilityName); - want.SetParam(PERMISSION_SETTING_KEY, asyncContext->permissionList); + want.SetElementName(this->info.grantBundleName, this->info.permStateAbilityName); + want.SetParam(PERMISSION_SETTING_KEY, this->permissionList); want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); - CreateUIExtension(want, asyncContext); + CreateUIExtension(want, asyncContext, GetRequestInstanceControl()); } -static void GetInstanceId(std::shared_ptr& asyncContext) -{ - auto task = [asyncContext]() { - Ace::UIContent* uiContent = GetUIContent(asyncContext->abilityContext, - asyncContext->uiExtensionContext, asyncContext->uiAbilityFlag); - if (uiContent == nullptr) { - LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!"); - return; - } - asyncContext->instanceId = uiContent->GetInstanceId(); - }; -#ifdef EVENTHANDLER_ENABLE - if (asyncContext->handler_ != nullptr) { - asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId"); - } else { - task(); - } -#else - task(); -#endif - LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", asyncContext->instanceId); -} - -void RequestOnSettingAsyncInstanceControl::AddCallbackByInstanceId( - std::shared_ptr& asyncContext) -{ - LOGI(ATM_DOMAIN, ATM_TAG, "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()) { - LOGI(ATM_DOMAIN, ATM_TAG, "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) +static bool CheckPermList(std::vector permList, std::vector tmpPermList) { if (permList.size() != tmpPermList.size()) { LOGE(ATM_DOMAIN, ATM_TAG, "Perm list size not equal, CurrentPermList size: %{public}zu.", tmpPermList.size()); @@ -480,80 +178,71 @@ bool static CheckPermList(std::vector permList, std::vector& reqContext) +bool RequestPermOnSettingAsyncContext::IsSameRequest(const std::shared_ptr other) +{ + if (other == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr."); + return false; + } + auto ptr = std::static_pointer_cast(other); + return CheckPermList(permissionList, ptr->permissionList); +} + +void RequestPermOnSettingAsyncContext::CopyResult(const std::shared_ptr other) { - if (reqContext->result.errorCode != RET_SUCCESS) { - LOGI(ATM_DOMAIN, ATM_TAG, "The queue data does not need to be updated."); + if (other == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr."); return; } - for (const int32_t item : reqContext->stateList) { - if (item != PERMISSION_GRANTED) { - LOGI(ATM_DOMAIN, ATM_TAG, "The queue data does not need to be updated"); - return; - } + auto ptr = std::static_pointer_cast(other); + this->result.errorCode = ptr->result.errorCode; + this->stateList = ptr->stateList; + this->isDynamic = false; +} + +bool RequestPermOnSettingAsyncContext::CheckDynamicRequest() +{ + if (!this->isDynamic) { + LOGI(ATM_DOMAIN, ATM_TAG, "It does not need to request permission extension"); + FinishCallback(); + return false; } + return true; +} - { - std::lock_guard lock(instanceIdMutex_); - int32_t id = reqContext->instanceId; - auto iter = instanceIdMap_.find(id); - if (iter == instanceIdMap_.end()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); - return; - } - std::vector permList = reqContext->permissionList; - LOGI(ATM_DOMAIN, ATM_TAG, "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 RequestPermOnSettingAsyncContext::ProcessFailResult(int32_t code) +{ + if (code == -1) { + this->result.errorCode = code; } } -void RequestOnSettingAsyncInstanceControl::ExecCallback(int32_t id) +bool RequestPermOnSettingAsyncContext::NoNeedUpdate() { - std::shared_ptr asyncContext = nullptr; - bool isDynamic = false; - { - std::lock_guard lock(instanceIdMutex_); - auto iter = instanceIdMap_.find(id); - if (iter == instanceIdMap_.end()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id); - return; - } - while (!iter->second.empty()) { - LOGI(ATM_DOMAIN, ATM_TAG, "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()) { - LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map is empty", id); - instanceIdMap_.erase(id); - } + if (result.errorCode != RET_SUCCESS) { + return true; } - if (isDynamic) { - StartUIExtension(asyncContext); + for (int32_t item : this->stateList) { + if (item != PERMISSION_GRANTED) { + return true; + } } + return false; } -void RequestOnSettingAsyncInstanceControl::CheckDynamicRequest( - std::shared_ptr& asyncContext, bool& isDynamic) +static bool ParseRequestPermissionOnSetting(ani_env* env, ani_object& aniContext, ani_array_ref& aniPermissionList, + ani_object callback, std::shared_ptr& asyncContext) { - isDynamic = asyncContext->isDynamic; - if (!isDynamic) { - LOGI(ATM_DOMAIN, ATM_TAG, "It does not need to request permission exsion"); - PermissionResultsCallbackUI(asyncContext->stateList, asyncContext); - return; + if (!asyncContext->FillInfoFromContext(aniContext)) { + BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL, + GetParamErrorMsg("context", "UIAbility or UIExtension Context")); + return false; + } + asyncContext->permissionList = ParseAniStringVector(env, aniPermissionList); + if (!AniParseCallback(env, reinterpret_cast(callback), asyncContext->callbackRef)) { + return false; } + return true; } void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, @@ -564,12 +253,18 @@ void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, return; } + ani_vm* vm; + ani_status status = env->GetVM(&vm); + if (status != ANI_OK) { + LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast(status)); + return; + } + std::shared_ptr asyncContext = - std::make_shared(); + std::make_shared(vm, env); if (!ParseRequestPermissionOnSetting(env, aniContext, permissionList, callback, asyncContext)) { return; } - ani_ref nullRef = nullptr; env->GetNull(&nullRef); ani_object result = reinterpret_cast(nullRef); @@ -580,18 +275,15 @@ void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, 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); + (void)ExecuteAsyncCallback(env, callback, error, result); return; } - GetInstanceId(asyncContext); - RequestOnSettingAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + asyncContext->GetInstanceId(); + GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext); LOGI(ATM_DOMAIN, ATM_TAG, "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); + asyncContext->FinishCallback(); LOGW(ATM_DOMAIN, ATM_TAG, "Failed to pop uiextension dialog."); } }