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