• 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_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