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