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 const std::string PREINSTALL_EXCEPTION = "PreInstallExceptionMgr";
24 const std::string EXCEPTION_PATHS = "ExceptionPaths";
25 const std::string EXCEPTION_BUNDLENAMES = "ExceptionBundleNames";
26 }
PreInstallExceptionMgr()27 PreInstallExceptionMgr::PreInstallExceptionMgr()
28 {}
29 
~PreInstallExceptionMgr()30 PreInstallExceptionMgr::~PreInstallExceptionMgr()
31 {
32     APP_LOGD("PreInstallExceptionMgr instance is destroyed");
33 }
34 
GetAllPreInstallExceptionInfo(std::set<std::string> & exceptionPaths,std::set<std::string> & exceptionBundleNames)35 bool PreInstallExceptionMgr::GetAllPreInstallExceptionInfo(
36     std::set<std::string> &exceptionPaths, std::set<std::string> &exceptionBundleNames)
37 {
38     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
39     if (!hasInit_) {
40         APP_LOGI("LoadPreInstallExceptionInfosFromDb");
41         if (!LoadPreInstallExceptionInfosFromDb()) {
42             APP_LOGE("Load PreInstall Exception Infos FromDb error");
43             return false;
44         }
45     }
46 
47     exceptionPaths = exceptionPaths_;
48     exceptionBundleNames = exceptionBundleNames_;
49     return !exceptionPaths_.empty() || !exceptionBundleNames_.empty();
50 }
51 
LoadPreInstallExceptionInfosFromDb()52 bool PreInstallExceptionMgr::LoadPreInstallExceptionInfosFromDb()
53 {
54     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
55     if (bmsPara == nullptr) {
56         APP_LOGE("bmsPara is nullptr");
57         return false;
58     }
59 
60     std::string preInstallExceptionStr;
61     bmsPara->GetBmsParam(PREINSTALL_EXCEPTION, preInstallExceptionStr);
62     if (preInstallExceptionStr.empty()) {
63         APP_LOGI("preInstallExceptionStr is empty");
64         return false;
65     }
66 
67     nlohmann::json jsonObject = nlohmann::json::parse(preInstallExceptionStr, nullptr, false);
68     if (jsonObject.is_discarded() || !jsonObject.is_object()) {
69         APP_LOGE("jsonObject is invalid");
70         return false;
71     }
72 
73     const auto &jsonObjectEnd = jsonObject.end();
74     int32_t parseResult = ERR_OK;
75     GetValueIfFindKey<std::set<std::string>>(jsonObject,
76         jsonObjectEnd,
77         EXCEPTION_PATHS,
78         exceptionPaths_,
79         JsonType::ARRAY,
80         false,
81         parseResult,
82         ArrayType::STRING);
83     GetValueIfFindKey<std::set<std::string>>(jsonObject,
84         jsonObjectEnd,
85         EXCEPTION_BUNDLENAMES,
86         exceptionBundleNames_,
87         JsonType::ARRAY,
88         false,
89         parseResult,
90         ArrayType::STRING);
91     if (parseResult != ERR_OK) {
92         APP_LOGE("from_json error code : %{public}d", parseResult);
93         exceptionPaths_.clear();
94         exceptionBundleNames_.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     bmsPara->SaveBmsParam(PREINSTALL_EXCEPTION, jsonObject.dump());
115 }
116 
DeletePreInstallExceptionInfosFromDb()117 void PreInstallExceptionMgr::DeletePreInstallExceptionInfosFromDb()
118 {
119     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
120     if (bmsPara == nullptr) {
121         APP_LOGE("bmsPara is nullptr");
122         return;
123     }
124 
125     nlohmann::json jsonObject;
126     if (!exceptionPaths_.empty()) {
127         jsonObject[EXCEPTION_PATHS] = exceptionPaths_;
128     }
129 
130     if (!exceptionBundleNames_.empty()) {
131         jsonObject[EXCEPTION_BUNDLENAMES] = exceptionBundleNames_;
132     }
133 
134     if (jsonObject.empty()) {
135         APP_LOGI_NOFUNC("Exception information is empty, Deleting pre-install exception information from database");
136         bmsPara->DeleteBmsParam(PREINSTALL_EXCEPTION);
137     } else {
138         APP_LOGI_NOFUNC("Updating pre-install exception in database");
139         bmsPara->SaveBmsParam(PREINSTALL_EXCEPTION, jsonObject.dump());
140     }
141 }
142 
SavePreInstallExceptionPath(const std::string & bundleDir)143 void PreInstallExceptionMgr::SavePreInstallExceptionPath(
144     const std::string &bundleDir)
145 {
146     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
147     if (bundleDir.empty()) {
148         APP_LOGE("bundleDir is empty");
149         return;
150     }
151 
152     if (exceptionPaths_.find(bundleDir) != exceptionPaths_.end()) {
153         APP_LOGE("bundleDir %{public}s saved", bundleDir.c_str());
154         return;
155     }
156 
157     exceptionPaths_.insert(bundleDir);
158     SavePreInstallExceptionInfosToDb();
159     APP_LOGI_NOFUNC("Pre-install exception save success");
160 }
161 
DeletePreInstallExceptionPath(const std::string & bundleDir)162 void PreInstallExceptionMgr::DeletePreInstallExceptionPath(const std::string &bundleDir)
163 {
164     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
165     if (bundleDir.empty()) {
166         APP_LOGE("bundleDir is empty");
167         return;
168     }
169 
170     if (exceptionPaths_.find(bundleDir) == exceptionPaths_.end()) {
171         APP_LOGE("bundleDir %{public}s deleted", bundleDir.c_str());
172         return;
173     }
174 
175     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
176     if (bmsPara == nullptr) {
177         APP_LOGE("bmsPara is nullptr");
178         return;
179     }
180 
181     exceptionPaths_.erase(bundleDir);
182     APP_LOGI_NOFUNC("exceptionPaths erase dir:%{public}s", bundleDir.c_str());
183     DeletePreInstallExceptionInfosFromDb();
184 }
185 
SavePreInstallExceptionBundleName(const std::string & bundleName)186 void PreInstallExceptionMgr::SavePreInstallExceptionBundleName(const std::string &bundleName)
187 {
188     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
189     if (bundleName.empty()) {
190         APP_LOGE("bundleName is empty");
191         return;
192     }
193 
194     if (exceptionBundleNames_.find(bundleName) != exceptionBundleNames_.end()) {
195         APP_LOGE("bundleName %{public}s saved", bundleName.c_str());
196         return;
197     }
198 
199     exceptionBundleNames_.insert(bundleName);
200     SavePreInstallExceptionInfosToDb();
201     APP_LOGI_NOFUNC("Pre-install exception save success -n %{public}s", bundleName.c_str());
202 }
203 
DeletePreInstallExceptionBundleName(const std::string & bundleName)204 void PreInstallExceptionMgr::DeletePreInstallExceptionBundleName(const std::string &bundleName)
205 {
206     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
207     if (bundleName.empty()) {
208         APP_LOGE("bundleName is empty");
209         return;
210     }
211 
212     if (exceptionBundleNames_.find(bundleName) == exceptionBundleNames_.end()) {
213         APP_LOGE("bundleName %{public}s deleted", bundleName.c_str());
214         return;
215     }
216 
217     exceptionBundleNames_.erase(bundleName);
218     APP_LOGI_NOFUNC("exceptionBundleNames erase -n %{public}s", bundleName.c_str());
219     DeletePreInstallExceptionInfosFromDb();
220 }
221 
ClearAll()222 void PreInstallExceptionMgr::ClearAll()
223 {
224     std::lock_guard<std::mutex> lock(preInstallExceptionMutex_);
225     auto bmsPara = DelayedSingleton<BundleMgrService>::GetInstance()->GetBmsParam();
226     if (bmsPara == nullptr) {
227         APP_LOGE("bmsPara is nullptr");
228         return;
229     }
230 
231     bmsPara->DeleteBmsParam(PREINSTALL_EXCEPTION);
232     exceptionPaths_.clear();
233     exceptionBundleNames_.clear();
234     hasInit_ = false;
235     APP_LOGI_NOFUNC("Pre-install exception cleare success");
236 }
237 }  // namespace AppExecFwk
238 }  // namespace OHOS