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 "pre_install_exception_mgr.h"
17 
18 #include "bundle_mgr_service.h"
19 
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 constexpr const char* PREINSTALL_EXCEPTION = "PreInstallExceptionMgr";
24 constexpr const char* EXCEPTION_PATHS = "ExceptionPaths";
25 constexpr const char* EXCEPTION_BUNDLENAMES = "ExceptionBundleNames";
26 constexpr const char* EXCEPTION_APP_SERVICE_PATHS = "ExceptionAppServicePaths";
27 constexpr const char* EXCEPTION_APP_SERVICE_BUNDLENAMES = "ExceptionAppServiceBundleNames";
28 }
PreInstallExceptionMgr()29 PreInstallExceptionMgr::PreInstallExceptionMgr()
30 {}
31 
~PreInstallExceptionMgr()32 PreInstallExceptionMgr::~PreInstallExceptionMgr()
33 {
34     APP_LOGD("PreInstallExceptionMgr instance is destroyed");
35 }
36 
GetAllPreInstallExceptionInfo( std::set<std::string> &exceptionPaths, std::set<std::string> &exceptionBundleNames, std::set<std::string> &exceptionAppServicePaths, std::set<std::string> &exceptionAppServiceBundleNames)37 bool PreInstallExceptionMgr::GetAllPreInstallExceptionInfo(
38     std::set<std::string> &exceptionPaths, std::set<std::string> &exceptionBundleNames,
39     std::set<std::string> &exceptionAppServicePaths, std::set<std::string> &exceptionAppServiceBundleNames)
40 {
41     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
42     if (!hasInit_) {
43         APP_LOGI("LoadPreInstallExceptionInfosFromDb");
44         if (!LoadPreInstallExceptionInfosFromDb()) {
45             APP_LOGE("Load PreInstall Exception Infos FromDb error");
46             return false;
47         }
48     }
49 
50     exceptionPaths = exceptionPaths_;
51     exceptionBundleNames = exceptionBundleNames_;
52     exceptionAppServicePaths = exceptionAppServicePaths_;
53     exceptionAppServiceBundleNames = exceptionAppServiceBundleNames_;
54     return !exceptionPaths_.empty() || !exceptionBundleNames_.empty() ||
55         !exceptionAppServicePaths_.empty() || !exceptionAppServiceBundleNames_.empty();
56 }
57 
LoadPreInstallExceptionInfosFromDb()58 bool PreInstallExceptionMgr::LoadPreInstallExceptionInfosFromDb()
59 {
60     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
61     if (bmsPara == nullptr) {
62         APP_LOGE("bmsPara is nullptr");
63         return false;
64     }
65 
66     std::string preInstallExceptionStr;
67     bmsPara->GetBmsParam(PREINSTALL_EXCEPTION, preInstallExceptionStr);
68     if (preInstallExceptionStr.empty()) {
69         APP_LOGI("preInstallExceptionStr is empty");
70         return false;
71     }
72 
73     nlohmann::json jsonObject = nlohmann::json::parse(preInstallExceptionStr, nullptr, false);
74     if (jsonObject.is_discarded() || !jsonObject.is_object()) {
75         APP_LOGE("jsonObject is invalid");
76         return false;
77     }
78 
79     const auto &jsonObjectEnd = jsonObject.end();
80     int32_t parseResult = ERR_OK;
81     GetValueIfFindKey<std::set<std::string>>(jsonObject, jsonObjectEnd, EXCEPTION_PATHS, exceptionPaths_,
82         JsonType::ARRAY, false, parseResult, ArrayType::STRING);
83     GetValueIfFindKey<std::set<std::string>>(jsonObject, jsonObjectEnd, EXCEPTION_BUNDLENAMES, exceptionBundleNames_,
84         JsonType::ARRAY, false, parseResult, ArrayType::STRING);
85     GetValueIfFindKey<std::set<std::string>>(jsonObject, jsonObjectEnd, EXCEPTION_APP_SERVICE_PATHS,
86         exceptionAppServicePaths_, JsonType::ARRAY, false, parseResult, ArrayType::STRING);
87     GetValueIfFindKey<std::set<std::string>>(jsonObject, jsonObjectEnd, EXCEPTION_APP_SERVICE_BUNDLENAMES,
88         exceptionAppServiceBundleNames_, JsonType::ARRAY, false, parseResult, ArrayType::STRING);
89     if (parseResult != ERR_OK) {
90         APP_LOGE("from_json error code : %{public}d", parseResult);
91         exceptionPaths_.clear();
92         exceptionBundleNames_.clear();
93         exceptionAppServicePaths_.clear();
94         exceptionAppServiceBundleNames_.clear();
95         return false;
96     }
97     APP_LOGI("Successfully loaded pre-install exception information");
98 
99     hasInit_ = true;
100     return true;
101 }
102 
SavePreInstallExceptionInfosToDb()103 void PreInstallExceptionMgr::SavePreInstallExceptionInfosToDb()
104 {
105     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
106     if (bmsPara == nullptr) {
107         APP_LOGE("bmsPara is nullptr");
108         return;
109     }
110 
111     nlohmann::json jsonObject;
112     jsonObject[EXCEPTION_PATHS] = exceptionPaths_;
113     jsonObject[EXCEPTION_BUNDLENAMES] = exceptionBundleNames_;
114     jsonObject[EXCEPTION_APP_SERVICE_PATHS] = exceptionAppServicePaths_;
115     jsonObject[EXCEPTION_APP_SERVICE_BUNDLENAMES] = exceptionAppServiceBundleNames_;
116     bmsPara->SaveBmsParam(PREINSTALL_EXCEPTION, jsonObject.dump());
117 }
118 
DeletePreInstallExceptionInfosFromDb()119 void PreInstallExceptionMgr::DeletePreInstallExceptionInfosFromDb()
120 {
121     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
122     if (bmsPara == nullptr) {
123         APP_LOGE("bmsPara is nullptr");
124         return;
125     }
126 
127     nlohmann::json jsonObject;
128     if (!exceptionPaths_.empty()) {
129         jsonObject[EXCEPTION_PATHS] = exceptionPaths_;
130     }
131 
132     if (!exceptionBundleNames_.empty()) {
133         jsonObject[EXCEPTION_BUNDLENAMES] = exceptionBundleNames_;
134     }
135 
136     if (!exceptionAppServiceBundleNames_.empty()) {
137         jsonObject[EXCEPTION_APP_SERVICE_BUNDLENAMES] = exceptionAppServiceBundleNames_;
138     }
139 
140     if (!exceptionAppServicePaths_.empty()) {
141         jsonObject[EXCEPTION_APP_SERVICE_PATHS] = exceptionAppServicePaths_;
142     }
143 
144     if (jsonObject.empty()) {
145         APP_LOGI_NOFUNC("Exception information is empty, Deleting pre-install exception information from database");
146         bmsPara->DeleteBmsParam(PREINSTALL_EXCEPTION);
147     } else {
148         APP_LOGI_NOFUNC("Updating pre-install exception in database");
149         bmsPara->SaveBmsParam(PREINSTALL_EXCEPTION, jsonObject.dump());
150     }
151 }
152 
SavePreInstallExceptionPath( const std::string &bundleDir)153 void PreInstallExceptionMgr::SavePreInstallExceptionPath(
154     const std::string &bundleDir)
155 {
156     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
157     if (bundleDir.empty()) {
158         APP_LOGE("bundleDir is empty");
159         return;
160     }
161 
162     if (exceptionPaths_.find(bundleDir) != exceptionPaths_.end()) {
163         APP_LOGE("bundleDir %{public}s saved", bundleDir.c_str());
164         return;
165     }
166 
167     exceptionPaths_.insert(bundleDir);
168     SavePreInstallExceptionInfosToDb();
169     APP_LOGI_NOFUNC("Pre-install exception save success");
170 }
171 
DeletePreInstallExceptionPath(const std::string &bundleDir)172 void PreInstallExceptionMgr::DeletePreInstallExceptionPath(const std::string &bundleDir)
173 {
174     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
175     if (bundleDir.empty()) {
176         APP_LOGE("bundleDir is empty");
177         return;
178     }
179 
180     if (exceptionPaths_.find(bundleDir) == exceptionPaths_.end()) {
181         APP_LOGE("bundleDir %{public}s deleted", bundleDir.c_str());
182         return;
183     }
184 
185     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
186     if (bmsPara == nullptr) {
187         APP_LOGE("bmsPara is nullptr");
188         return;
189     }
190 
191     exceptionPaths_.erase(bundleDir);
192     DeletePreInstallExceptionInfosFromDb();
193     APP_LOGI_NOFUNC("Pre-install exception delete success bundleDir:%{public}s", bundleDir.c_str());
194 }
195 
SavePreInstallExceptionBundleName(const std::string &bundleName)196 void PreInstallExceptionMgr::SavePreInstallExceptionBundleName(const std::string &bundleName)
197 {
198     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
199     if (bundleName.empty()) {
200         APP_LOGE("bundleName is empty");
201         return;
202     }
203 
204     if (exceptionBundleNames_.find(bundleName) != exceptionBundleNames_.end()) {
205         APP_LOGE("bundleName %{public}s saved", bundleName.c_str());
206         return;
207     }
208 
209     exceptionBundleNames_.insert(bundleName);
210     SavePreInstallExceptionInfosToDb();
211     APP_LOGI_NOFUNC("Pre-install exception save success -n %{public}s", bundleName.c_str());
212 }
213 
DeletePreInstallExceptionBundleName(const std::string &bundleName)214 void PreInstallExceptionMgr::DeletePreInstallExceptionBundleName(const std::string &bundleName)
215 {
216     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
217     if (bundleName.empty()) {
218         APP_LOGE("bundleName is empty");
219         return;
220     }
221 
222     if (exceptionBundleNames_.find(bundleName) == exceptionBundleNames_.end()) {
223         APP_LOGE("bundleName %{public}s deleted", bundleName.c_str());
224         return;
225     }
226 
227     exceptionBundleNames_.erase(bundleName);
228     DeletePreInstallExceptionInfosFromDb();
229     APP_LOGI_NOFUNC("Pre-install exception delete success -n %{public}s", bundleName.c_str());
230 }
231 
SavePreInstallExceptionAppServiceBundleName(const std::string &bundleName)232 void PreInstallExceptionMgr::SavePreInstallExceptionAppServiceBundleName(const std::string &bundleName)
233 {
234     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
235     if (bundleName.empty()) {
236         APP_LOGE("bundleName is empty");
237         return;
238     }
239 
240     if (exceptionAppServiceBundleNames_.find(bundleName) != exceptionAppServiceBundleNames_.end()) {
241         APP_LOGE("bundleName %{public}s saved", bundleName.c_str());
242         return;
243     }
244 
245     exceptionAppServiceBundleNames_.insert(bundleName);
246     SavePreInstallExceptionInfosToDb();
247     APP_LOGI_NOFUNC("Pre-install exception app service save success -n %{public}s", bundleName.c_str());
248 }
249 
DeletePreInstallExceptionAppServiceBundleName(const std::string &bundleName)250 void PreInstallExceptionMgr::DeletePreInstallExceptionAppServiceBundleName(const std::string &bundleName)
251 {
252     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
253     if (bundleName.empty()) {
254         APP_LOGE("bundleName is empty");
255         return;
256     }
257 
258     if (exceptionAppServiceBundleNames_.find(bundleName) == exceptionAppServiceBundleNames_.end()) {
259         APP_LOGE("bundleName %{public}s deleted", bundleName.c_str());
260         return;
261     }
262 
263     exceptionAppServiceBundleNames_.erase(bundleName);
264     DeletePreInstallExceptionInfosFromDb();
265     APP_LOGI_NOFUNC("Pre-install exception app service delete success -n %{public}s", bundleName.c_str());
266 }
267 
SavePreInstallExceptionAppServicePath( const std::string &bundleDir)268 void PreInstallExceptionMgr::SavePreInstallExceptionAppServicePath(
269     const std::string &bundleDir)
270 {
271     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
272     if (bundleDir.empty()) {
273         APP_LOGE("bundleDir is empty");
274         return;
275     }
276 
277     if (exceptionAppServicePaths_.find(bundleDir) != exceptionAppServicePaths_.end()) {
278         APP_LOGE("bundleDir %{public}s saved", bundleDir.c_str());
279         return;
280     }
281 
282     exceptionAppServicePaths_.insert(bundleDir);
283     SavePreInstallExceptionInfosToDb();
284     APP_LOGI_NOFUNC("Pre-install exception app service save success");
285 }
286 
DeletePreInstallExceptionAppServicePath(const std::string &bundleDir)287 void PreInstallExceptionMgr::DeletePreInstallExceptionAppServicePath(const std::string &bundleDir)
288 {
289     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
290     if (bundleDir.empty()) {
291         APP_LOGE("bundleDir is empty");
292         return;
293     }
294 
295     if (exceptionAppServicePaths_.find(bundleDir) == exceptionAppServicePaths_.end()) {
296         APP_LOGE("bundleDir %{public}s deleted", bundleDir.c_str());
297         return;
298     }
299 
300     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
301     if (bmsPara == nullptr) {
302         APP_LOGE("bmsPara is nullptr");
303         return;
304     }
305 
306     exceptionAppServicePaths_.erase(bundleDir);
307     DeletePreInstallExceptionInfosFromDb();
308     APP_LOGI_NOFUNC("Pre-install exception app service delete success bundleDir:%{public}s", bundleDir.c_str());
309 }
310 
ClearAll()311 void PreInstallExceptionMgr::ClearAll()
312 {
313     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
314     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
315     if (bmsPara == nullptr) {
316         APP_LOGE("bmsPara is nullptr");
317         return;
318     }
319 
320     bmsPara->DeleteBmsParam(PREINSTALL_EXCEPTION);
321     exceptionPaths_.clear();
322     exceptionBundleNames_.clear();
323     exceptionAppServicePaths_.clear();
324     exceptionAppServiceBundleNames_.clear();
325     hasInit_ = false;
326     APP_LOGI_NOFUNC("Pre-install exception cleare success");
327 }
328 }  // namespace AppExecFwk
329 }  // namespace OHOS