1 /*
2  * Copyright (c) 2023 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 
16 #include "session_manager/include/extension_session_manager.h"
17 
18 #include <ability_manager_client.h>
19 #include <hitrace_meter.h>
20 
21 #include "session/host/include/extension_session.h"
22 
23 namespace OHOS::Rosen {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ExtensionSessionManager" };
26 const std::string EXTENSION_SESSION_MANAGER_THREAD = "OS_ExtensionSessionManager";
27 } // namespace
28 
ExtensionSessionManager()29 ExtensionSessionManager::ExtensionSessionManager()
30 {
31     taskScheduler_ = std::make_shared<TaskScheduler>(EXTENSION_SESSION_MANAGER_THREAD);
32 }
33 
WM_IMPLEMENT_SINGLE_INSTANCE(ExtensionSessionManager)34 WM_IMPLEMENT_SINGLE_INSTANCE(ExtensionSessionManager)
35 
36 sptr<AAFwk::SessionInfo> ExtensionSessionManager::SetAbilitySessionInfo(const sptr<ExtensionSession>& extSession)
37 {
38     sptr<AAFwk::SessionInfo> abilitySessionInfo = new (std::nothrow) AAFwk::SessionInfo();
39     if (!abilitySessionInfo) {
40         WLOGFE("abilitySessionInfo is nullptr");
41         return nullptr;
42     }
43     auto sessionInfo = extSession->GetSessionInfo();
44     sptr<ISession> iSession(extSession);
45     abilitySessionInfo->sessionToken = iSession->AsObject();
46     abilitySessionInfo->callerToken = sessionInfo.callerToken_;
47     abilitySessionInfo->parentToken = sessionInfo.rootToken_;
48     abilitySessionInfo->persistentId = extSession->GetPersistentId();
49     abilitySessionInfo->realHostWindowId = sessionInfo.realParentId_;
50     abilitySessionInfo->isAsyncModalBinding = sessionInfo.isAsyncModalBinding_;
51     abilitySessionInfo->uiExtensionUsage = static_cast<AAFwk::UIExtensionUsage>(sessionInfo.uiExtensionUsage_);
52     abilitySessionInfo->parentWindowType = sessionInfo.parentWindowType_;
53     if (sessionInfo.want != nullptr) {
54         abilitySessionInfo->want = *sessionInfo.want;
55     }
56     return abilitySessionInfo;
57 }
58 
RequestExtensionSession(const SessionInfo & sessionInfo)59 sptr<ExtensionSession> ExtensionSessionManager::RequestExtensionSession(const SessionInfo& sessionInfo)
60 {
61     auto task = [this, sessionInfo]() {
62         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "RequestExtensionSession");
63         sptr<ExtensionSession> extensionSession = new ExtensionSession(sessionInfo);
64         extensionSession->SetEventHandler(taskScheduler_->GetEventHandler(), nullptr);
65         auto persistentId = extensionSession->GetPersistentId();
66         WLOGFI("persistentId: %{public}d, bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s",
67             persistentId, sessionInfo.bundleName_.c_str(), sessionInfo.moduleName_.c_str(),
68             sessionInfo.abilityName_.c_str());
69         extensionSessionMap_.insert({ persistentId, extensionSession });
70         return extensionSession;
71     };
72 
73     return taskScheduler_->PostSyncTask(task, "RequestExtensionSession");
74 }
75 
RequestExtensionSessionActivation(const sptr<ExtensionSession> & extensionSession,uint32_t hostWindowId,const std::function<void (WSError)> && resultCallback)76 WSError ExtensionSessionManager::RequestExtensionSessionActivation(const sptr<ExtensionSession>& extensionSession,
77     uint32_t hostWindowId, const std::function<void(WSError)>&& resultCallback)
78 {
79     wptr<ExtensionSession> weakExtSession(extensionSession);
80     auto task = [this, weakExtSession, hostWindowId, callback = std::move(resultCallback)]() {
81         auto extSession = weakExtSession.promote();
82         if (extSession == nullptr) {
83             WLOGFE("session is nullptr");
84             return WSError::WS_ERROR_NULLPTR;
85         }
86         auto persistentId = extSession->GetPersistentId();
87         WLOGFI("Activate session with persistentId: %{public}d", persistentId);
88         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionActivation");
89         if (extensionSessionMap_.count(persistentId) == 0) {
90             WLOGFE("RequestExtensionSessionActivation Session is invalid! persistentId:%{public}d", persistentId);
91             return WSError::WS_ERROR_INVALID_SESSION;
92         }
93         auto extSessionInfo = SetAbilitySessionInfo(extSession);
94         if (extSessionInfo == nullptr) {
95             return WSError::WS_ERROR_NULLPTR;
96         }
97         extSessionInfo->hostWindowId = hostWindowId;
98         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->StartUIExtensionAbility(extSessionInfo,
99             AAFwk::DEFAULT_INVAL_VALUE);
100         if (callback) {
101             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_START_UI_EXTENSION_ABILITY_FAILED;
102             callback(ret);
103             return ret;
104         }
105         return WSError::WS_OK;
106     };
107     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionActivation");
108     return WSError::WS_OK;
109 }
110 
RequestExtensionSessionBackground(const sptr<ExtensionSession> & extensionSession,const std::function<void (WSError)> && resultCallback)111 WSError ExtensionSessionManager::RequestExtensionSessionBackground(const sptr<ExtensionSession>& extensionSession,
112     const std::function<void(WSError)>&& resultCallback)
113 {
114     wptr<ExtensionSession> weakExtSession(extensionSession);
115     auto task = [this, weakExtSession, callback = std::move(resultCallback)]() {
116         auto extSession = weakExtSession.promote();
117         if (extSession == nullptr) {
118             WLOGFE("session is nullptr");
119             return WSError::WS_ERROR_NULLPTR;
120         }
121         auto persistentId = extSession->GetPersistentId();
122         WLOGFI("Background session with persistentId: %{public}d", persistentId);
123         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionBackground");
124         extSession->SetActive(false);
125         extSession->Background();
126         if (extensionSessionMap_.count(persistentId) == 0) {
127             WLOGFE("RequestExtensionSessionBackground Session is invalid! persistentId:%{public}d", persistentId);
128             return WSError::WS_ERROR_INVALID_SESSION;
129         }
130         auto extSessionInfo = SetAbilitySessionInfo(extSession);
131         if (!extSessionInfo) {
132             return WSError::WS_ERROR_NULLPTR;
133         }
134         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->MinimizeUIExtensionAbility(extSessionInfo);
135         if (callback) {
136             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_MIN_UI_EXTENSION_ABILITY_FAILED;
137             callback(ret);
138             return ret;
139         }
140         return WSError::WS_OK;
141     };
142     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionBackground");
143     return WSError::WS_OK;
144 }
145 
RequestExtensionSessionDestruction(const sptr<ExtensionSession> & extensionSession,const std::function<void (WSError)> && resultCallback)146 WSError ExtensionSessionManager::RequestExtensionSessionDestruction(const sptr<ExtensionSession>& extensionSession,
147     const std::function<void(WSError)>&& resultCallback)
148 {
149     wptr<ExtensionSession> weakExtSession(extensionSession);
150     auto task = [this, weakExtSession, callback = std::move(resultCallback)]() {
151         auto extSession = weakExtSession.promote();
152         if (extSession == nullptr) {
153             WLOGFE("session is nullptr");
154             return WSError::WS_ERROR_NULLPTR;
155         }
156         auto persistentId = extSession->GetPersistentId();
157         WLOGFI("Destroy session with persistentId: %{public}d", persistentId);
158         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionDestruction");
159         extSession->Disconnect();
160         if (extensionSessionMap_.count(persistentId) == 0) {
161             WLOGFE("RequestExtensionSessionDestruction Session is invalid! persistentId:%{public}d", persistentId);
162             return WSError::WS_ERROR_INVALID_SESSION;
163         }
164         auto extSessionInfo = SetAbilitySessionInfo(extSession);
165         if (!extSessionInfo) {
166             return WSError::WS_ERROR_NULLPTR;
167         }
168         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(extSessionInfo);
169         extensionSessionMap_.erase(persistentId);
170         if (callback) {
171             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_TERMINATE_UI_EXTENSION_ABILITY_FAILED;
172             callback(ret);
173             return ret;
174         }
175         return WSError::WS_OK;
176     };
177     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionDestruction");
178     return WSError::WS_OK;
179 }
180 
RequestExtensionSessionDestructionDone(const sptr<ExtensionSession> & extensionSession)181 WSError ExtensionSessionManager::RequestExtensionSessionDestructionDone(const sptr<ExtensionSession>& extensionSession)
182 {
183     const char* const where = __func__;
184     auto task = [this, where, weakExtSession = wptr<ExtensionSession>(extensionSession)] {
185         auto extSession = weakExtSession.promote();
186         if (extSession == nullptr) {
187             TLOGNE(WmsLogTag::WMS_UIEXT, "%{public}s session is nullptr", where);
188             return;
189         }
190         auto persistentId = extSession->GetPersistentId();
191         TLOGNI(WmsLogTag::WMS_UIEXT, "Destroy session done with persistentId: %{public}d", persistentId);
192         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:%{public}s", where);
193         if (extensionSessionMap_.count(persistentId) == 0) {
194             TLOGNE(WmsLogTag::WMS_UIEXT, "%{public}s session is invalid! persistentId: %{public}d",
195                 where, persistentId);
196             return;
197         }
198         auto extSessionInfo = SetAbilitySessionInfo(extSession);
199         if (!extSessionInfo) {
200             return;
201         }
202         AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(extSessionInfo);
203         extensionSessionMap_.erase(persistentId);
204     };
205     taskScheduler_->PostAsyncTask(task, __func__);
206     return WSError::WS_OK;
207 }
208 } // namespace OHOS::Rosen
209