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 "shared_bundle_installer.h"
17
18 #include "bundle_mgr_service.h"
19 #include "scope_guard.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
SharedBundleInstaller(const InstallParam & installParam,const Constants::AppType appType)23 SharedBundleInstaller::SharedBundleInstaller(const InstallParam &installParam, const Constants::AppType appType)
24 : installParam_(installParam), appType_(appType)
25 {
26 APP_LOGD("shared bundle installer instance is created");
27 }
28
~SharedBundleInstaller()29 SharedBundleInstaller::~SharedBundleInstaller()
30 {
31 APP_LOGD("shared bundle installer instance is destroyed");
32 }
33
ParseFiles()34 ErrCode SharedBundleInstaller::ParseFiles()
35 {
36 ErrCode result = ERR_OK;
37 if (installParam_.sharedBundleDirPaths.empty()) {
38 APP_LOGI_NOFUNC("sharedBundleDirPaths is empty");
39 return result;
40 }
41
42 InstallCheckParam checkParam;
43 checkParam.isPreInstallApp = installParam_.isPreInstallApp;
44 checkParam.crowdtestDeadline = installParam_.crowdtestDeadline;
45 checkParam.appType = appType_;
46 checkParam.removable = installParam_.removable;
47 checkParam.installBundlePermissionStatus = installParam_.installBundlePermissionStatus;
48 checkParam.installEnterpriseBundlePermissionStatus = installParam_.installEnterpriseBundlePermissionStatus;
49 checkParam.installEtpNormalBundlePermissionStatus = installParam_.installEtpNormalBundlePermissionStatus;
50 checkParam.installEtpMdmBundlePermissionStatus = installParam_.installEtpMdmBundlePermissionStatus;
51 checkParam.isCallByShell = installParam_.isCallByShell;
52
53 for (const auto &path : installParam_.sharedBundleDirPaths) {
54 auto installer = std::make_shared<InnerSharedBundleInstaller>(path);
55 result = installer->ParseFiles(checkParam);
56 CHECK_RESULT(result, "parse file failed %{public}d");
57 if (innerInstallers_.find(installer->GetBundleName()) != innerInstallers_.end()) {
58 APP_LOGW("sharedBundleDirPaths does not support that different paths contain hsp of same bundleName");
59 continue;
60 }
61 innerInstallers_.emplace(installer->GetBundleName(), installer);
62 }
63
64 APP_LOGI("parse shared bundles successfully");
65 return result;
66 }
67
CheckDependency(const InnerBundleInfo & innerBundleInfo) const68 bool SharedBundleInstaller::CheckDependency(const InnerBundleInfo &innerBundleInfo) const
69 {
70 if (innerBundleInfo.GetDependencies().empty()) {
71 APP_LOGD("dependencies of %{public}s is empty", innerBundleInfo.GetBundleName().c_str());
72 return true;
73 }
74
75 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
76 if (dataMgr == nullptr) {
77 APP_LOGE("Get dataMgr shared_ptr nullptr");
78 return false;
79 }
80
81 for (const auto &dependency : innerBundleInfo.GetDependencies()) {
82 if (dependency.bundleName.empty() || dependency.bundleName == innerBundleInfo.GetBundleName()) {
83 APP_LOGD("inner-app dependency: %{public}s", GetJsonStrFromInfo(dependency).c_str());
84 continue;
85 }
86
87 auto iter = innerInstallers_.find(dependency.bundleName);
88 if (iter != innerInstallers_.end() && iter->second->CheckDependency(dependency)) {
89 APP_LOGD("dependency found in installing shared bundles: %{public}s",
90 GetJsonStrFromInfo(dependency).c_str());
91 continue;
92 }
93
94 if (FindDependencyInInstalledBundles(dependency)) {
95 APP_LOGD("dependency found in installed shared bundles: %{public}s",
96 GetJsonStrFromInfo(dependency).c_str());
97 continue;
98 }
99
100 APP_LOGE("dependency not found: %{public}s", GetJsonStrFromInfo(dependency).c_str());
101 if (iter != innerInstallers_.end()) {
102 std::string checkResultMsg = "the dependent module: " + dependency.moduleName + " does not exist.";
103 iter->second->SetCheckResultMsg(checkResultMsg);
104 }
105 return false;
106 }
107
108 APP_LOGD("dependencies are satisfied");
109 return true;
110 }
111
Install(const EventInfo & eventTemplate)112 ErrCode SharedBundleInstaller::Install(const EventInfo &eventTemplate)
113 {
114 if (!NeedToInstall()) {
115 APP_LOGI("do not need to install");
116 return ERR_OK;
117 }
118
119 std::vector<std::string> processedBundles;
120 ScopeGuard installGuard([this, &processedBundles] {
121 APP_LOGE("install shared bundles failed, rollbacking:%{public}s", GetJsonStrFromInfo(processedBundles).c_str());
122 for (auto iter = processedBundles.crbegin(); iter != processedBundles.crend(); ++iter) {
123 auto installer = innerInstallers_.find(*iter);
124 if (installer != innerInstallers_.end()) {
125 installer->second->RollBack();
126 } else {
127 APP_LOGE("rollback failed : %{public}s", iter->c_str());
128 }
129 }
130 });
131
132 ErrCode result = ERR_OK;
133 for (auto installer : innerInstallers_) {
134 result = installer.second->Install(installParam_);
135 processedBundles.emplace_back(installer.first);
136 if (result != ERR_OK) {
137 APP_LOGE("install shared bundle failed %{public}d", result);
138 SendBundleSystemEvent(eventTemplate, result);
139 return result;
140 }
141 }
142
143 installGuard.Dismiss();
144 SendBundleSystemEvent(eventTemplate, result);
145 APP_LOGD("install shared bundles success");
146 return result;
147 }
148
FindDependencyInInstalledBundles(const Dependency & dependency) const149 bool SharedBundleInstaller::FindDependencyInInstalledBundles(const Dependency &dependency) const
150 {
151 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
152 if (dataMgr == nullptr) {
153 APP_LOGE("Get dataMgr shared_ptr nullptr");
154 return false;
155 }
156
157 InnerBundleInfo bundleInfo;
158 bool isBundleExist = dataMgr->FetchInnerBundleInfo(dependency.bundleName, bundleInfo);
159 if (!isBundleExist || bundleInfo.GetApplicationBundleType() != BundleType::SHARED) {
160 APP_LOGE("the shared bundle (%{public}s) is not installed", dependency.bundleName.c_str());
161 return false;
162 }
163
164 BaseSharedBundleInfo sharedBundle;
165 bool isModuleExist = bundleInfo.GetMaxVerBaseSharedBundleInfo(dependency.moduleName, sharedBundle);
166 if (isModuleExist && dependency.versionCode <= sharedBundle.versionCode) {
167 return true;
168 }
169
170 APP_LOGE("the module or version not satisfied : %{public}s", GetJsonStrFromInfo(dependency).c_str());
171 return false;
172 }
173
SendBundleSystemEvent(const EventInfo & eventTemplate,ErrCode errCode)174 void SharedBundleInstaller::SendBundleSystemEvent(const EventInfo &eventTemplate, ErrCode errCode)
175 {
176 EventInfo commonEventInfo = eventTemplate;
177 commonEventInfo.isPreInstallApp = installParam_.isPreInstallApp;
178 commonEventInfo.errCode = errCode;
179 commonEventInfo.isFreeInstallMode = (installParam_.installFlag == InstallFlag::FREE_INSTALL);
180 GetCallingEventInfo(commonEventInfo);
181
182 for (auto installer : innerInstallers_) {
183 installer.second->SendBundleSystemEvent(commonEventInfo);
184 }
185 }
186
GetCallingEventInfo(EventInfo & eventInfo)187 void SharedBundleInstaller::GetCallingEventInfo(EventInfo &eventInfo)
188 {
189 APP_LOGD("GetCallingEventInfo start, bundleName:%{public}s", eventInfo.callingBundleName.c_str());
190 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
191 if (dataMgr == nullptr) {
192 APP_LOGE("Get dataMgr shared_ptr nullptr");
193 return;
194 }
195 if (!dataMgr->GetBundleNameForUid(eventInfo.callingUid, eventInfo.callingBundleName)) {
196 APP_LOGW("CallingUid %{public}d is not hap, no bundleName", eventInfo.callingUid);
197 eventInfo.callingBundleName = Constants::EMPTY_STRING;
198 return;
199 }
200
201 BundleInfo bundleInfo;
202 if (!dataMgr->GetBundleInfo(eventInfo.callingBundleName, BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo,
203 eventInfo.callingUid / Constants::BASE_USER_RANGE)) {
204 APP_LOGE("GetBundleInfo failed, bundleName: %{public}s", eventInfo.callingBundleName.c_str());
205 return;
206 }
207 eventInfo.callingAppId = bundleInfo.appId;
208 }
209 } // namespace AppExecFwk
210 } // namespace OHOS
211