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_base.h"
16
17 #include "accesstoken_common_log.h"
18 #include "accesstoken_kit.h"
19 #include "ani_common.h"
20 #include "token_setproc.h"
21 #include "want.h"
22
23 namespace OHOS {
24 namespace Security {
25 namespace AccessToken {
26
RequestAsyncContextBase(ani_vm * vm,ani_env * env,AniRequestType type)27 RequestAsyncContextBase::RequestAsyncContextBase(ani_vm* vm, ani_env* env, AniRequestType type)
28 : vm_(vm), env_(env), contextType_(type)
29 {
30 threadId_ = std::this_thread::get_id();
31 #ifdef EVENTHANDLER_ENABLE
32 handler_ = std::make_shared<AppExecFwk::EventHandler>(
33 AppExecFwk::EventRunner::GetMainEventRunner());
34 #endif
35 }
36
FillInfoFromContext(const ani_object & aniContext)37 bool RequestAsyncContextBase::FillInfoFromContext(const ani_object& aniContext)
38 {
39 if (env_ == nullptr) {
40 LOGE(ATM_DOMAIN, ATM_TAG, "env_ is nullptr.");
41 return false;
42 }
43 auto context = OHOS::AbilityRuntime::GetStageModeContext(env_, aniContext);
44 if (context == nullptr) {
45 LOGE(ATM_DOMAIN, ATM_TAG, "GetStageModeContext failed");
46 return false;
47 }
48 stageContext_ = context;
49 auto appInfo = context->GetApplicationInfo();
50 if (appInfo == nullptr) {
51 LOGE(ATM_DOMAIN, ATM_TAG, "GetApplicationInfo failed");
52 return false;
53 }
54 tokenId = appInfo->accessTokenId;
55 bundleName = appInfo->bundleName;
56 return true;
57 }
58
GetInstanceId()59 void RequestAsyncContextBase::GetInstanceId()
60 {
61 auto task = [this]() {
62 Ace::UIContent* uiContent = GetUIContent(this->stageContext_);
63 if (uiContent == nullptr) {
64 LOGE(ATM_DOMAIN, ATM_TAG, "Get ui content failed!");
65 return;
66 }
67 this->uiContentFlag = true;
68 this->instanceId = uiContent->GetInstanceId();
69 };
70 #ifdef EVENTHANDLER_ENABLE
71 if (this->handler_ != nullptr) {
72 this->handler_->PostSyncTask(task, "AT:GetInstanceId");
73 } else {
74 task();
75 }
76 #else
77 task();
78 #endif
79 LOGI(ATM_DOMAIN, ATM_TAG, "Instance id: %{public}d", this->instanceId);
80 }
81
82
IsSameRequest(const std::shared_ptr<RequestAsyncContextBase> other)83 bool RequestAsyncContextBase::IsSameRequest(const std::shared_ptr<RequestAsyncContextBase> other)
84 {
85 (void) other;
86 return false;
87 }
88
CopyResult(const std::shared_ptr<RequestAsyncContextBase> other)89 void RequestAsyncContextBase::CopyResult(const std::shared_ptr<RequestAsyncContextBase> other)
90 {
91 (void) other;
92 return;
93 }
94
ProcessFailResult(int32_t code)95 void RequestAsyncContextBase::ProcessFailResult(int32_t code)
96 {
97 result.errorCode = code;
98 }
99
FinishCallback()100 void RequestAsyncContextBase::FinishCallback()
101 {
102 if (vm_ == nullptr) {
103 LOGE(ATM_DOMAIN, ATM_TAG, "vm_ is nullptr.");
104 return;
105 }
106 bool isSameThread = IsCurrentThread(threadId_);
107 ani_env* env = isSameThread ? env_ : GetCurrentEnv(vm_);
108 if (env == nullptr) {
109 LOGE(ATM_DOMAIN, ATM_TAG, "GetCurrentEnv failed.");
110 return;
111 }
112
113 int32_t stsCode = ConvertErrorCode(result.errorCode);
114 ani_object error = BusinessErrorAni::CreateError(env, stsCode, GetErrorMessage(stsCode, result.errorMsg));
115 ani_object result = WrapResult(env);
116 (void)ExecuteAsyncCallback(env, reinterpret_cast<ani_object>(callbackRef), error, result);
117
118 if (!isSameThread && vm_->DetachCurrentThread() != ANI_OK) {
119 LOGE(ATM_DOMAIN, ATM_TAG, "DetachCurrentThread failed!");
120 }
121 }
122
Clear()123 void RequestAsyncContextBase::Clear()
124 {
125 if (vm_ == nullptr) {
126 LOGE(ATM_DOMAIN, ATM_TAG, "VM is nullptr.");
127 return;
128 }
129 bool isSameThread = IsCurrentThread(threadId_);
130 ani_env* curEnv = isSameThread ? env_ : GetCurrentEnv(vm_);
131 if (curEnv == nullptr) {
132 LOGE(ATM_DOMAIN, ATM_TAG, "GetCurrentEnv failed.");
133 return;
134 }
135
136 if (callbackRef != nullptr) {
137 curEnv->GlobalReference_Delete(callbackRef);
138 callbackRef = nullptr;
139 }
140 }
141
GetType()142 AniRequestType RequestAsyncContextBase::GetType()
143 {
144 return contextType_;
145 }
146
UIExtensionCallback(const std::shared_ptr<RequestAsyncContextBase> reqContext)147 UIExtensionCallback::UIExtensionCallback(const std::shared_ptr<RequestAsyncContextBase> reqContext)
148 :reqContext_(reqContext)
149 {}
150
~UIExtensionCallback()151 UIExtensionCallback::~UIExtensionCallback()
152 {}
153
SetSessionId(int32_t sessionId)154 void UIExtensionCallback::SetSessionId(int32_t sessionId)
155 {
156 this->sessionId_ = sessionId;
157 }
158
ReleaseHandler(int32_t code)159 void UIExtensionCallback::ReleaseHandler(int32_t code)
160 {
161 {
162 std::lock_guard<std::mutex> lock(this->reqContext_->lockReleaseFlag);
163 if (this->reqContext_->releaseFlag) {
164 LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed.");
165 return;
166 }
167 this->reqContext_->releaseFlag = true;
168 }
169 CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_);
170 reqContext_->ProcessFailResult(code);
171 controllerInstance_->UpdateQueueData(this->reqContext_);
172 controllerInstance_->ExecCallback(this->reqContext_->instanceId);
173 reqContext_->FinishCallback();
174 }
175
OnResult(int32_t resultCode,const OHOS::AAFwk::Want & result)176 void UIExtensionCallback::OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result)
177 {
178 LOGI(ATM_DOMAIN, ATM_TAG, "ResultCode is %{public}d", resultCode);
179 reqContext_->ProcessUIExtensionCallback(result);
180 ReleaseHandler(0);
181 }
182
183 /*
184 * when UIExtensionAbility send message to UIExtensionComponent
185 */
OnReceive(const AAFwk::WantParams & receive)186 void UIExtensionCallback::OnReceive(const AAFwk::WantParams& receive)
187 {
188 LOGI(ATM_DOMAIN, ATM_TAG, "Called!");
189 }
190
191 /*
192 * when UIExtensionAbility disconnect or use terminate or process die
193 * releaseCode is 0 when process normal exit
194 */
OnRelease(int32_t releaseCode)195 void UIExtensionCallback::OnRelease(int32_t releaseCode)
196 {
197 LOGI(ATM_DOMAIN, ATM_TAG, "ReleaseCode is %{public}d", releaseCode);
198
199 ReleaseHandler(-1);
200 }
201
202 /*
203 * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error
204 */
OnError(int32_t code,const std::string & name,const std::string & message)205 void UIExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message)
206 {
207 LOGI(ATM_DOMAIN, ATM_TAG, "Code is %{public}d, name is %{public}s, message is %{public}s",
208 code, name.c_str(), message.c_str());
209
210 ReleaseHandler(-1);
211 }
212
213 /*
214 * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init,
215 * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy
216 */
OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & uiProxy)217 void UIExtensionCallback::OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy>& uiProxy)
218 {
219 LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully.");
220 }
221
222 /*
223 * when UIExtensionComponent destructed
224 */
OnDestroy()225 void UIExtensionCallback::OnDestroy()
226 {
227 LOGI(ATM_DOMAIN, ATM_TAG, "UIExtensionAbility destructed.");
228 ReleaseHandler(-1);
229 }
230
SetRequestInstanceControl(std::shared_ptr<RequestInstanceControl> controllerInstance)231 void UIExtensionCallback::SetRequestInstanceControl(std::shared_ptr<RequestInstanceControl> controllerInstance)
232 {
233 this->controllerInstance_ = controllerInstance;
234 }
235
AddCallbackByInstanceId(std::shared_ptr<RequestAsyncContextBase> asyncContext)236 void RequestInstanceControl::AddCallbackByInstanceId(
237 std::shared_ptr<RequestAsyncContextBase> asyncContext)
238 {
239 LOGI(ATM_DOMAIN, ATM_TAG, "InstanceId: %{public}d", asyncContext->instanceId);
240 {
241 std::lock_guard<std::mutex> lock(instanceIdMutex_);
242 auto iter = instanceIdMap_.find(asyncContext->instanceId);
243 // id is existed mean a pop window is showing, add context to waiting queue
244 if (iter != instanceIdMap_.end()) {
245 LOGI(ATM_DOMAIN, ATM_TAG, "InstanceId: %{public}d has existed.", asyncContext->instanceId);
246 instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext);
247 return;
248 }
249 // make sure id is in map to indicate a pop-up window is showing
250 instanceIdMap_[asyncContext->instanceId] = {};
251 }
252 asyncContext->StartExtensionAbility(asyncContext);
253 }
254
UpdateQueueData(const std::shared_ptr<RequestAsyncContextBase> asyncContext)255 void RequestInstanceControl::UpdateQueueData(
256 const std::shared_ptr<RequestAsyncContextBase> asyncContext)
257 {
258 if (asyncContext->NoNeedUpdate()) {
259 LOGI(ATM_DOMAIN, ATM_TAG, "The queue data does not need to be updated.");
260 return;
261 }
262
263 {
264 std::lock_guard<std::mutex> lock(instanceIdMutex_);
265 int32_t id = asyncContext->instanceId;
266 auto iter = instanceIdMap_.find(id);
267 if (iter == instanceIdMap_.end()) {
268 LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id);
269 return;
270 }
271 for (auto& curContext : iter->second) {
272 if (curContext != nullptr && curContext->IsSameRequest(asyncContext)) {
273 curContext->CopyResult(asyncContext);
274 }
275 }
276 }
277 }
278
ExecCallback(int32_t id)279 void RequestInstanceControl::ExecCallback(int32_t id)
280 {
281 std::shared_ptr<RequestAsyncContextBase> asyncContext = nullptr;
282 bool isDynamic = false;
283 {
284 std::lock_guard<std::mutex> lock(instanceIdMutex_);
285 auto iter = instanceIdMap_.find(id);
286 if (iter == instanceIdMap_.end()) {
287 LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d not existed.", id);
288 return;
289 }
290 while (!iter->second.empty()) {
291 LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size());
292 asyncContext = iter->second[0];
293 iter->second.erase(iter->second.begin());
294 if (asyncContext == nullptr) {
295 LOGI(ATM_DOMAIN, ATM_TAG, "asyncContext is nullptr.");
296 continue;
297 }
298 isDynamic = asyncContext->CheckDynamicRequest();
299 if (isDynamic) {
300 break;
301 }
302 }
303 if (iter->second.empty()) {
304 LOGI(ATM_DOMAIN, ATM_TAG, "Id: %{public}d, map is empty", id);
305 instanceIdMap_.erase(id);
306 }
307 }
308 if (isDynamic) {
309 asyncContext->StartExtensionAbility(asyncContext);
310 }
311 }
312
313 } // namespace AccessToken
314 } // namespace Security
315 } // namespace OHOS