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 "page_url_checker_ohos.h"
17
18 #include <string>
19
20 #include "ability_runtime/context/context.h"
21 #include "app_mgr_client.h"
22 #include "atomic_service_status_callback.h"
23 #include "errors.h"
24 #include "iremote_broker.h"
25 #include "iremote_object.h"
26 #include "iremote_stub.h"
27 #include "iservice_registry.h"
28 #include "nocopyable.h"
29 #include "singleton.h"
30 #include "system_ability_definition.h"
31 #include "want.h"
32
33 namespace OHOS::Ace {
34 const char BUNDLE_TAG[] = "@bundle:";
35 constexpr size_t BUNDLE_START_POS = 8;
36 constexpr int32_t SILENT_INSTALL_SUCCESS = 0;
37
38 /**
39 * @class IAtomicServiceStatusCallback
40 * IAtomicServiceStatusCallback is used to notify caller ability that free install is complete.
41 */
42 class IAtomicServiceStatusCallback : public IRemoteBroker {
43 public:
44 DECLARE_INTERFACE_DESCRIPTOR(u"ohos.IAtomicServiceStatusCallback");
45
46 /**
47 * @brief OnActionEvent.
48 */
49 virtual int32_t OnActionEvent() = 0;
50 /**
51 * @brief OnError.
52 * @param code The code.
53 * @param msg The msg.
54 */
55 virtual int32_t OnError(int32_t code, const std::string& msg) = 0;
56 };
57
58 /**
59 * @class AtomicServiceStatusCallbackStub
60 * AtomicServiceStatusCallbackStub.
61 */
62 class AtomicServiceStatusCallbackStub : public IRemoteStub<IAtomicServiceStatusCallback> {
63 public:
AtomicServiceStatusCallbackStub()64 AtomicServiceStatusCallbackStub()
65 {
66 handleOnActionEventFunc_ = &AtomicServiceStatusCallbackStub::HandleOnActionEvent;
67 handleOnErrorFunc_ = &AtomicServiceStatusCallbackStub::HandleOnError;
68 }
~AtomicServiceStatusCallbackStub()69 ~AtomicServiceStatusCallbackStub() override
70 {
71 handleOnActionEventFunc_ = nullptr;
72 handleOnErrorFunc_ = nullptr;
73 }
74
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)75 int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override
76 {
77 LOGI("AtomicServiceStatusCallbackStub::OnReceived, code = %{public}u, flags= %{public}d.",
78 code, option.GetFlags());
79 std::u16string descriptor = AtomicServiceStatusCallbackStub::GetDescriptor();
80 std::u16string remoteDescriptor = data.ReadInterfaceToken();
81 if (descriptor != remoteDescriptor) {
82 LOGE("%{public}s failed, local descriptor is not equal to remote", __func__);
83 return ERR_INVALID_VALUE;
84 }
85
86 auto resultCode = data.ReadInt32();
87 if (resultCode == SILENT_INSTALL_SUCCESS) {
88 if (handleOnActionEventFunc_ != nullptr) {
89 return (this->*handleOnActionEventFunc_)();
90 }
91 }
92
93 if (resultCode < SILENT_INSTALL_SUCCESS) {
94 if (handleOnErrorFunc_ != nullptr) {
95 return (this->*handleOnErrorFunc_)(data);
96 }
97 }
98
99 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
100 }
101
102 private:
HandleOnActionEvent()103 int32_t HandleOnActionEvent()
104 {
105 return OnActionEvent();
106 }
HandleOnError(MessageParcel & data)107 int32_t HandleOnError(MessageParcel &data)
108 {
109 int32_t code = data.ReadInt32();
110 std::string msg = data.ReadString();
111 return OnError(code, msg);
112 }
113
114 using HandleOnActionEventFunc = int32_t (AtomicServiceStatusCallbackStub::*)();
115 HandleOnActionEventFunc handleOnActionEventFunc_;
116
117 using HandleOnErrorFunc = int32_t (AtomicServiceStatusCallbackStub::*)(MessageParcel &data);
118 HandleOnErrorFunc handleOnErrorFunc_;
119
120 DISALLOW_COPY_AND_MOVE(AtomicServiceStatusCallbackStub);
121 };
122
123 /**
124 * @class AtomicServiceStatusCallback
125 * AtomicServiceStatusCallback.
126 */
127 class AtomicServiceStatusCallback : public AtomicServiceStatusCallbackStub {
128 public:
129 AtomicServiceStatusCallback() = default;
130 ~AtomicServiceStatusCallback() override = default;
131
132 /**
133 * @brief OnActionEvent.
134 */
OnActionEvent()135 int32_t OnActionEvent() override
136 {
137 if (!actionEventHandler_) {
138 LOGE("actionEventHandler_ is null.");
139 return ERR_INVALID_VALUE;
140 }
141 actionEventHandler_();
142 return ERR_OK;
143 }
144 /**
145 * @brief OnError.
146 * @param code The code.
147 * @param msg The msg.
148 */
OnError(int32_t code,const std::string & msg)149 int32_t OnError(int32_t code, const std::string& msg) override
150 {
151 LOGE("OnError code: %{public}d, msg: %{public}s", code, msg.c_str());
152 if (!errorEventHandler_) {
153 LOGE("errorEventHandler_ is null");
154 return ERR_INVALID_VALUE;
155 }
156
157 errorEventHandler_(code, msg);
158 return ERR_OK;
159 }
160
SetActionEventHandler(const std::function<void ()> & listener)161 void SetActionEventHandler(const std::function<void()>& listener)
162 {
163 actionEventHandler_ = listener;
164 }
SetErrorEventHandler(const std::function<void (int32_t,const std::string &)> & listener)165 void SetErrorEventHandler(const std::function<void(int32_t, const std::string&)>& listener)
166 {
167 errorEventHandler_ = listener;
168 }
169
170 private:
171 std::function<void()> actionEventHandler_;
172 std::function<void(int32_t, const std::string&)> errorEventHandler_;
173 };
174
GetBundleManager()175 sptr<AppExecFwk::IBundleMgr> PageUrlCheckerOhos::GetBundleManager()
176 {
177 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
178 if (systemAbilityMgr == nullptr) {
179 LOGE("Failed to get SystemAbilityManager.");
180 return nullptr;
181 }
182
183 auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
184 if (bundleObj == nullptr) {
185 LOGE("Failed to get bundle manager service");
186 return nullptr;
187 }
188
189 return iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
190 }
191
LoadPageUrl(const std::string & url,const std::function<void ()> & callback,const std::function<void (int32_t,const std::string &)> & silentInstallErrorCallBack)192 void PageUrlCheckerOhos::LoadPageUrl(const std::string& url, const std::function<void()>& callback,
193 const std::function<void(int32_t, const std::string&)>& silentInstallErrorCallBack)
194 {
195 if (url.substr(0, strlen(BUNDLE_TAG)) != BUNDLE_TAG) {
196 return;
197 }
198
199 size_t bundleEndPos = url.find('/');
200 std::string bundleName = url.substr(BUNDLE_START_POS, bundleEndPos - BUNDLE_START_POS);
201 size_t moduleStartPos = bundleEndPos + 1;
202 size_t moduleEndPos = url.find('/', moduleStartPos);
203 std::string moduleName = url.substr(moduleStartPos, moduleEndPos - moduleStartPos);
204
205 auto appInfo = context_->GetApplicationInfo();
206 if (appInfo) {
207 std::vector<OHOS::AppExecFwk::ModuleInfo> moduleList = appInfo->moduleInfos;
208 auto res = std::any_of(moduleList.begin(), moduleList.end(), [moduleName](const auto &module) {
209 return module.moduleName == moduleName;
210 });
211 if (res) {
212 callback();
213 return;
214 }
215
216 auto bms = GetBundleManager();
217 CHECK_NULL_VOID(bms);
218 std::vector<AppExecFwk::BaseSharedBundleInfo> baseSharedBundleInfo;
219 if (bms->GetBaseSharedBundleInfos(bundleName, baseSharedBundleInfo) != 0 &&
220 baseSharedBundleInfo.size() != 0) {
221 callback();
222 return;
223 }
224
225 AppExecFwk::BundleInfo bundleInfo;
226 int32_t ret = bms->GetDependentBundleInfo(bundleName, bundleInfo,
227 AppExecFwk::GetDependentBundleInfoFlag::GET_APP_SERVICE_HSP_BUNDLE_INFO);
228 if (ret == ERR_OK && bundleInfo.hapModuleInfos.size() != 0) {
229 callback();
230 return;
231 }
232
233 AAFwk::Want want;
234 want.SetBundle(bundleName);
235 want.SetModuleName(moduleName);
236 sptr<AtomicServiceStatusCallback> routerCallback = new AtomicServiceStatusCallback();
237 routerCallback->SetActionEventHandler(callback);
238 routerCallback->SetErrorEventHandler(silentInstallErrorCallBack);
239 if (bms->SilentInstall(want, appInfo->uid / AppExecFwk::Constants::BASE_USER_RANGE, routerCallback)) {
240 LOGI("Begin to silent install");
241 }
242 }
243 }
244
CheckPreload(const std::string & url)245 void PageUrlCheckerOhos::CheckPreload(const std::string& url)
246 {
247 if (url.substr(0, strlen(BUNDLE_TAG)) != BUNDLE_TAG) {
248 return;
249 }
250
251 size_t bundleEndPos = url.find('/');
252 std::string bundleName = url.substr(BUNDLE_START_POS, bundleEndPos - BUNDLE_START_POS);
253 size_t moduleStartPos = bundleEndPos + 1;
254 size_t moduleEndPos = url.find('/', moduleStartPos);
255 std::string moduleName = url.substr(moduleStartPos, moduleEndPos - moduleStartPos);
256
257 auto appInfo = context_->GetApplicationInfo();
258 CHECK_NULL_VOID(appInfo);
259 if (appInfo->CheckNeedPreload(moduleName)) {
260 auto bms = GetBundleManager();
261 CHECK_NULL_VOID(bms);
262 AAFwk::Want want;
263 // only need to Transfer bundleName and moduleName
264 want.SetElementName("", bundleName, "", moduleName);
265 want.SetParam("uid", appInfo->uid);
266 bms->ProcessPreload(want);
267 }
268 }
269
NotifyPageShow(const std::string & pageName)270 void PageUrlCheckerOhos::NotifyPageShow(const std::string& pageName)
271 {
272 std::string targetBundleName;
273 std::string targetModuleName;
274 GetTargetPageInfo(pageName, targetBundleName, targetModuleName);
275 AppExecFwk::PageStateData pageStateData;
276 pageStateData.bundleName = abilityInfo_->bundleName;
277 pageStateData.moduleName = abilityInfo_->moduleName;
278 pageStateData.abilityName = abilityInfo_->name;
279 pageStateData.pageName = pageName;
280 pageStateData.targetBundleName = targetBundleName;
281 pageStateData.targetModuleName = targetModuleName;
282 DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->
283 NotifyPageShow(context_->GetToken(), pageStateData);
284 }
285
NotifyPageHide(const std::string & pageName)286 void PageUrlCheckerOhos::NotifyPageHide(const std::string& pageName)
287 {
288 std::string targetBundleName;
289 std::string targetModuleName;
290 GetTargetPageInfo(pageName, targetBundleName, targetModuleName);
291 AppExecFwk::PageStateData pageStateData;
292 pageStateData.bundleName = abilityInfo_->bundleName;
293 pageStateData.moduleName = abilityInfo_->moduleName;
294 pageStateData.abilityName = abilityInfo_->name;
295 pageStateData.pageName = pageName;
296 pageStateData.targetBundleName = targetBundleName;
297 pageStateData.targetModuleName = targetModuleName;
298 DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->
299 NotifyPageHide(context_->GetToken(), pageStateData);
300 }
301
GetTargetPageInfo(const std::string & pageName,std::string & targetBundleName,std::string & targetModuleName) const302 void PageUrlCheckerOhos::GetTargetPageInfo(const std::string& pageName, std::string& targetBundleName,
303 std::string& targetModuleName) const
304 {
305 if (pageName.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
306 size_t bundleEndPos = pageName.find('/');
307 targetBundleName = pageName.substr(BUNDLE_START_POS, bundleEndPos - BUNDLE_START_POS);
308 size_t moduleStartPos = bundleEndPos + 1;
309 size_t moduleEndPos = pageName.find('/', moduleStartPos);
310 targetModuleName = pageName.substr(moduleStartPos, moduleEndPos - moduleStartPos);
311 } else {
312 targetBundleName = abilityInfo_->bundleName;
313 std::string moduleName = moduleNameCallback_(pageName);
314 if (moduleName == "") {
315 moduleName = abilityInfo_->moduleName;
316 }
317 targetModuleName = moduleName;
318 }
319 }
320
SetModuleNameCallback(std::function<std::string (const std::string &)> && callback)321 void PageUrlCheckerOhos::SetModuleNameCallback(std::function<std::string(const std::string&)>&& callback)
322 {
323 moduleNameCallback_ = std::move(callback);
324 }
325 } // namespace OHOS::Ace