• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "ani_request_global_switch_on_setting.h"
16 #include "accesstoken_kit.h"
17 #include "accesstoken_common_log.h"
18 #include "ani_common.h"
19 #include "token_setproc.h"
20 #include "want.h"
21 
22 namespace OHOS {
23 namespace Security {
24 namespace AccessToken {
25 namespace {
26 const std::string GLOBAL_SWITCH_KEY = "ohos.user.setting.global_switch";
27 const std::string GLOBAL_SWITCH_RESULT_KEY = "ohos.user.setting.global_switch.result";
28 const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code";
29 const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
30 const std::string UI_EXTENSION_TYPE = "sys/commonUI";
31 std::shared_ptr<RequestInstanceControl> g_requestInstanceControl = nullptr;
32 std::mutex g_requestInstanceControlLock;
33 
34 // error code from dialog
35 constexpr int32_t REQUEST_ALREADY_EXIST = 1;
36 constexpr int32_t GLOBAL_TYPE_IS_NOT_SUPPORT = 2;
37 constexpr int32_t SWITCH_IS_ALREADY_OPEN = 3;
38 }
39 
GetRequestInstanceControl()40 static std::shared_ptr<RequestInstanceControl> GetRequestInstanceControl()
41 {
42     std::lock_guard<std::mutex> lock(g_requestInstanceControlLock);
43     if (g_requestInstanceControl == nullptr) {
44         g_requestInstanceControl = std::make_shared<RequestInstanceControl>();
45     }
46     return g_requestInstanceControl;
47 }
48 
RequestGlobalSwitchAsyncContext(ani_vm * vm,ani_env * env)49 RequestGlobalSwitchAsyncContext::RequestGlobalSwitchAsyncContext(ani_vm* vm, ani_env* env)
50     : RequestAsyncContextBase(vm, env, REQUEST_GLOBAL_SWITCH_ON_SETTING)
51 {}
52 
~RequestGlobalSwitchAsyncContext()53 RequestGlobalSwitchAsyncContext::~RequestGlobalSwitchAsyncContext()
54 {
55     Clear();
56 }
57 
ConvertErrorCode(int32_t errCode)58 int32_t RequestGlobalSwitchAsyncContext::ConvertErrorCode(int32_t errCode)
59 {
60     int32_t stsCode = STS_OK;
61     switch (errCode) {
62         case RET_SUCCESS:
63             stsCode = STS_OK;
64             break;
65         case REQUEST_ALREADY_EXIST:
66             stsCode = STS_ERROR_REQUEST_IS_ALREADY_EXIST;
67             break;
68         case GLOBAL_TYPE_IS_NOT_SUPPORT:
69             stsCode = STS_ERROR_PARAM_INVALID;
70             break;
71         case SWITCH_IS_ALREADY_OPEN:
72             stsCode = STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN;
73             break;
74         default:
75             stsCode = STS_ERROR_INNER;
76             break;
77     }
78     LOGI(ATM_DOMAIN, ATM_TAG, "Dialog error(%{public}d) stsCode(%{public}d).", errCode, stsCode);
79     return stsCode;
80 }
81 
82 
WrapResult(ani_env * env)83 ani_object RequestGlobalSwitchAsyncContext::WrapResult(ani_env* env)
84 {
85     return CreateBooleanObject(env, this->switchStatus);
86 }
87 
ProcessUIExtensionCallback(const OHOS::AAFwk::Want & result)88 void RequestGlobalSwitchAsyncContext::ProcessUIExtensionCallback(const OHOS::AAFwk::Want& result)
89 {
90     this->result.errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0);
91     this->switchStatus = result.GetBoolParam(GLOBAL_SWITCH_RESULT_KEY, 0);
92 }
93 
StartExtensionAbility(std::shared_ptr<RequestAsyncContextBase> asyncContext)94 void RequestGlobalSwitchAsyncContext::StartExtensionAbility(std::shared_ptr<RequestAsyncContextBase> asyncContext)
95 {
96     AccessTokenKit::GetPermissionManagerInfo(this->info);
97     LOGI(ATM_DOMAIN, ATM_TAG, "BundleName: %{public}s, permStateAbilityName: %{public}s.",
98         this->info.grantBundleName.c_str(), this->info.permStateAbilityName.c_str());
99     OHOS::AAFwk::Want want;
100     want.SetElementName(this->info.grantBundleName, this->info.globalSwitchAbilityName);
101     want.SetParam(GLOBAL_SWITCH_KEY, this->switchType);
102     want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE);
103     CreateUIExtension(want, asyncContext, GetRequestInstanceControl());
104 }
105 
IsSameRequest(const std::shared_ptr<RequestAsyncContextBase> other)106 bool RequestGlobalSwitchAsyncContext::IsSameRequest(const std::shared_ptr<RequestAsyncContextBase> other)
107 {
108     if (other == nullptr) {
109         LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr.");
110         return false;
111     }
112     auto ptr = std::static_pointer_cast<RequestGlobalSwitchAsyncContext>(other);
113     return switchType == ptr->switchType;
114 }
115 
CopyResult(const std::shared_ptr<RequestAsyncContextBase> other)116 void RequestGlobalSwitchAsyncContext::CopyResult(const std::shared_ptr<RequestAsyncContextBase> other)
117 {
118     if (other == nullptr) {
119         LOGE(ATM_DOMAIN, ATM_TAG, "other is nullptr.");
120         return;
121     }
122     auto ptr = std::static_pointer_cast<RequestGlobalSwitchAsyncContext>(other);
123     this->result.errorCode = ptr->result.errorCode;
124     this->switchStatus = ptr->switchStatus;
125     this->isDynamic = false;
126 }
127 
CheckDynamicRequest()128 bool RequestGlobalSwitchAsyncContext::CheckDynamicRequest()
129 {
130     if (!this->isDynamic) {
131         LOGI(ATM_DOMAIN, ATM_TAG, "It does not need to request permission extension");
132         FinishCallback();
133         return false;
134     }
135     return true;
136 }
137 
NoNeedUpdate()138 bool RequestGlobalSwitchAsyncContext::NoNeedUpdate()
139 {
140     return result.errorCode != RET_SUCCESS || switchStatus == false;
141 }
142 
ProcessFailResult(int32_t code)143 void RequestGlobalSwitchAsyncContext::ProcessFailResult(int32_t code)
144 {
145     if (code == -1) {
146         result.errorCode = code;
147     }
148 }
149 
ParseRequestGlobalSwitch(ani_env * env,ani_object & aniContext,ani_int type,ani_object callback,std::shared_ptr<RequestGlobalSwitchAsyncContext> & asyncContext)150 static bool ParseRequestGlobalSwitch(ani_env* env, ani_object& aniContext, ani_int type,
151     ani_object callback, std::shared_ptr<RequestGlobalSwitchAsyncContext>& asyncContext)
152 {
153     asyncContext->switchType = static_cast<SwitchType>(type);
154 
155     if (!asyncContext->FillInfoFromContext(aniContext) != ANI_OK) {
156         BusinessErrorAni::ThrowParameterTypeError(env, STS_ERROR_PARAM_ILLEGAL,
157             GetParamErrorMsg("context", "UIAbility or UIExtension Context"));
158         return false;
159     }
160     if (!AniParseCallback(env, reinterpret_cast<ani_ref>(callback), asyncContext->callbackRef)) {
161         return false;
162     }
163     return true;
164 }
165 
RequestGlobalSwitchExecute(ani_env * env,ani_object object,ani_object aniContext,ani_int type,ani_object callback)166 void RequestGlobalSwitchExecute([[maybe_unused]] ani_env* env,
167     [[maybe_unused]] ani_object object, ani_object aniContext, ani_int type, ani_object callback)
168 {
169     if (env == nullptr || callback == nullptr) {
170         LOGE(ATM_DOMAIN, ATM_TAG, "Env or permissionList or callback is null.");
171         return;
172     }
173 
174     ani_vm* vm;
175     ani_status status = env->GetVM(&vm);
176     if (status != ANI_OK) {
177         LOGE(ATM_DOMAIN, ATM_TAG, "Failed to GetVM, error=%{public}d.", static_cast<int32_t>(status));
178         return;
179     }
180     std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext =
181         std::make_shared<RequestGlobalSwitchAsyncContext>(vm, env);
182     if (!ParseRequestGlobalSwitch(env, aniContext, type, callback, asyncContext)) {
183         return;
184     }
185 
186     ani_object result = CreateBooleanObject(env, false);
187     static AccessTokenID selfTokenID = static_cast<AccessTokenID>(GetSelfTokenID());
188     if (selfTokenID != asyncContext->tokenId) {
189         LOGE(ATM_DOMAIN, ATM_TAG, "The context tokenID %{public}d is not same with selfTokenID %{public}d.",
190             asyncContext->tokenId, selfTokenID);
191         ani_object error =
192             BusinessErrorAni::CreateError(env, STS_ERROR_PARAM_INVALID, GetErrorMessage(STS_ERROR_PARAM_INVALID,
193             "The specified context does not belong to the current application."));
194         (void)ExecuteAsyncCallback(env, callback, error, result);
195         return;
196     }
197     asyncContext->GetInstanceId();
198     GetRequestInstanceControl()->AddCallbackByInstanceId(asyncContext);
199     LOGI(ATM_DOMAIN, ATM_TAG, "Start to pop ui extension dialog");
200 
201     if (asyncContext->result.errorCode != RET_SUCCESS) {
202         asyncContext->FinishCallback();
203         LOGW(ATM_DOMAIN, ATM_TAG, "Failed to pop uiextension dialog.");
204     }
205 }
206 }  // namespace AccessToken
207 }  // namespace Security
208 }  // namespace OHOS