1 /*
2 * Copyright (c) 2024 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 "app_details_rdb_data_manager.h"
17 #include "app_details_base_item.h"
18 #include "app_details_meta_item.h"
19 #include "app_details_rdb_data_define.h"
20 #include "app_details_rdb_item.h"
21 #include "app_details_rdb_open_callback.h"
22 #include "app_domain_verify_hilog.h"
23 #include "cpp/mutex.h"
24 #include "rdb_errno.h"
25 #include "rdb_store.h"
26 #include "values_bucket.h"
27 #include "rdb_helper.h"
28 #include <functional>
29 #include <string>
30 #include <variant>
31 #include <vector>
32 #include "app_details_rdb_const_define.h"
33 #include "utils/critial_utils.h"
34
35 namespace OHOS {
36 namespace AppDomainVerify {
AppDetailsRdbDataMgr(bool isCreated)37 AppDetailsRdbDataMgr::AppDetailsRdbDataMgr(bool isCreated)
38 {
39 conf_.rdbName = APP_DETAILS_RDB_NAME;
40 conf_.rdbPath = APP_DETAILS_RDB_PATH;
41 conf_.version = APP_DETAILS_RDB_VERSION;
42 conf_.fileCreated = isCreated;
43 };
44
AppDetailsRdbDataMgr(const RdbConfigInfo & info)45 AppDetailsRdbDataMgr::AppDetailsRdbDataMgr(const RdbConfigInfo& info)
46 {
47 conf_ = info;
48 };
49
~AppDetailsRdbDataMgr()50 AppDetailsRdbDataMgr::~AppDetailsRdbDataMgr()
51 {
52 if (closeHandler_ != nullptr) {
53 closeHandler_->RemoveTask(CLOSE_TASK_ID);
54 }
55 };
56
ExecWithTrans(TransCallback cb)57 bool AppDetailsRdbDataMgr::ExecWithTrans(TransCallback cb)
58 {
59 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call");
60 auto rdbStore = GetRdbStore();
61 if (!rdbStore) {
62 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
63 return false;
64 }
65 CriticalLock criticalLock;
66 auto ret = rdbStore->BeginTransaction();
67 if (ret != NativeRdb::E_OK) {
68 return false;
69 }
70 if (cb()) {
71 ret = rdbStore->Commit();
72 if (ret != NativeRdb::E_OK) {
73 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "commit err:%{public}d", ret);
74 return false;
75 }
76 return true;
77 }
78 ret = rdbStore->RollBack();
79 if (ret != NativeRdb::E_OK) {
80 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "roll err:%{public}d.", ret);
81 }
82 return false;
83 }
84
QueryDataByDomain(const std::string & tableName,const std::string & domain,std::vector<AppDetailsRdbItem> & itemVec)85 bool AppDetailsRdbDataMgr::QueryDataByDomain(
86 const std::string& tableName, const std::string &domain, std::vector<AppDetailsRdbItem> &itemVec)
87 {
88 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");
89 NativeRdb::AbsRdbPredicates absRdbPred(tableName);
90 absRdbPred.EqualTo(DETAILS_DOMAIN, domain);
91 std::vector<std::string> columns = {};
92 RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet)->bool {
93 AppDetailsRdbItem item;
94 if (!item.GetRdbItem(retSet)) {
95 return false;
96 }
97 itemVec.emplace_back(item);
98 return true;
99 };
100 return Query(absRdbPred, columns, eachCb);
101 }
102
PostDelayCloseTask(int32_t delayTime)103 void AppDetailsRdbDataMgr::PostDelayCloseTask(int32_t delayTime)
104 {
105 if (runner_ == nullptr) {
106 runner_ = AppExecFwk::EventRunner::Create("closeRdb", AppExecFwk::ThreadMode::FFRT);
107 }
108 if (closeHandler_ == nullptr) {
109 closeHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
110 }
111 if (closeHandler_ == nullptr) {
112 return;
113 }
114 std::weak_ptr<AppDetailsRdbDataMgr> weakPtr = shared_from_this();
115 auto task = [weakPtr]() {
116 auto appDetailsRdbMgr = weakPtr.lock();
117 if (appDetailsRdbMgr != nullptr) {
118 std::lock_guard<ffrt::mutex> lock(appDetailsRdbMgr->mtx_);
119 appDetailsRdbMgr->rdbStore_ = nullptr;
120 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb close");
121 }
122 return;
123 };
124 closeHandler_->RemoveTask(CLOSE_TASK_ID);
125 closeHandler_->PostTask(task, CLOSE_TASK_ID, delayTime);
126 return;
127 }
128
InsertDataBatch(const std::string & tableName,std::vector<AppDetailsRdbItem> & infoVec)129 bool AppDetailsRdbDataMgr::InsertDataBatch(const std::string& tableName, std::vector<AppDetailsRdbItem>& infoVec)
130 {
131 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
132 auto rdbStore = GetRdbStore();
133 if (!rdbStore) {
134 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
135 return false;
136 }
137 std::vector<NativeRdb::ValuesBucket> rows;
138 for (auto& info : infoVec) {
139 NativeRdb::ValuesBucket valuesBucket;
140 info.AddRdbItemToBucket(valuesBucket);
141 rows.emplace_back(valuesBucket);
142 }
143 int64_t num = 0;
144 CriticalLock criticalLock;
145 return CheckRdbReturnIfOk(rdbStore_->BatchInsert(num, tableName, rows));
146 };
147
CreateMetaData()148 bool AppDetailsRdbDataMgr::CreateMetaData()
149 {
150 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
151 auto rdbStore = GetRdbStore();
152 if (!rdbStore) {
153 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
154 return false;
155 }
156 std::string sql = "CREATE TABLE IF NOT EXISTS " + META_DATA +
157 "("
158 "TABLE_NAME TEXT NOT NULL PRIMARY KEY,"
159 "TABLE_VERSION TEXT,"
160 "TABLE_EXT_INFO TEXT,"
161 "UPDATE_TIME TEXT"
162 ");";
163 CriticalLock lock;
164 auto ret = rdbStore->ExecuteSql(sql);
165 if (ret != NativeRdb::E_OK) {
166 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "exec sql fail. ret:%{public}d", ret);
167 return false;
168 }
169 return true;
170 };
171
UpdateMetaData(std::vector<MetaItem> & itemVec)172 bool AppDetailsRdbDataMgr::UpdateMetaData(std::vector<MetaItem> &itemVec)
173 {
174 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
175 auto rdbStore = GetRdbStore();
176 if (!rdbStore) {
177 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
178 return false;
179 }
180 CriticalLock lock;
181 for (auto& item : itemVec) {
182 NativeRdb::ValuesBucket valuesBucket;
183 item.AddRdbItemToBucket(valuesBucket);
184 int64_t rowId = 0;
185 auto ret = rdbStore->InsertWithConflictResolution(rowId, META_DATA, valuesBucket,
186 NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
187 if (ret != NativeRdb::E_OK) {
188 return CheckRdbReturnIfOk(ret);
189 }
190 }
191 return true;
192 };
193
QueryMetaData(const std::string & tableName,MetaItem & info)194 bool AppDetailsRdbDataMgr::QueryMetaData(const std::string &tableName, MetaItem &info)
195 {
196 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call.");
197 NativeRdb::AbsRdbPredicates absRdbPred(META_DATA);
198 absRdbPred.EqualTo(META_TABLE_NAME, tableName);
199 std::vector<std::string> columns = {};
200 auto rdbStore = GetRdbStore();
201 if (!rdbStore) {
202 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
203 return false;
204 }
205 std::vector<MetaItem> itemVec;
206 RdbForEachRetCb eachCb = [&itemVec](std::shared_ptr<AbsSharedResultSet> retSet)->bool {
207 MetaItem item;
208 if (!item.GetRdbItem(retSet)) {
209 return false;
210 }
211 itemVec.emplace_back(item);
212 return true;
213 };
214 if (Query(absRdbPred, columns, eachCb)) {
215 info = itemVec.front();
216 return true;
217 };
218 return false;
219 };
220
CreateTable(const std::string & tableName)221 bool AppDetailsRdbDataMgr::CreateTable(const std::string &tableName)
222 {
223 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
224 std::string sql = "CREATE TABLE IF NOT EXISTS " + tableName
225 + " ("
226 "ID TEXT NOT NULL PRIMARY KEY,"
227 "SCHEME TEXT,"
228 "DOMAIN TEXT,"
229 "PATH_TYPE TEXT,"
230 "PATH TEXT,"
231 "BUNDLE_NAME TEXT"
232 + " );";
233 auto rdbStore = GetRdbStore();
234 if (!rdbStore) {
235 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
236 return false;
237 }
238 CriticalLock lock;
239 auto ret = rdbStore->ExecuteSql(sql);
240 if (ret != NativeRdb::E_OK) {
241 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "exec sql fail. ret:%{public}d", ret);
242 return false;
243 }
244 return true;
245 };
246
CreateRegularIndex(const std::string & tableName,const std::string & colName)247 bool AppDetailsRdbDataMgr::CreateRegularIndex(const std::string& tableName, const std::string& colName)
248 {
249 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
250 std::string sql = "CREATE INDEX IF NOT EXISTS " + colName + "_INDEX " + "ON " + tableName + " (" + colName + ");";
251 auto rdbStore = GetRdbStore();
252 if (!rdbStore) {
253 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
254 return false;
255 }
256 CriticalLock lock;
257 auto ret = rdbStore->ExecuteSql(sql);
258 if (ret != NativeRdb::E_OK) {
259 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "exec sql fail. ret:%{public}d", ret);
260 return false;
261 }
262 return true;
263 };
264
DeleteTable(const std::string & tableName)265 bool AppDetailsRdbDataMgr::DeleteTable(const std::string &tableName)
266 {
267 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "Called");
268 std::string sql = "DROP TABLE IF EXISTS " + tableName + ";";
269 auto rdbStore = GetRdbStore();
270 if (!rdbStore) {
271 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "Get rdbStore fail.");
272 return false;
273 }
274 CriticalLock lock;
275 auto ret = rdbStore->ExecuteSql(sql);
276 if (ret != NativeRdb::E_OK) {
277 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "Exec sql fail. ret:%{public}d", ret);
278 return false;
279 }
280 return true;
281 };
282
GetDbVersion()283 std::string AppDetailsRdbDataMgr::GetDbVersion()
284 {
285 auto rdbStore = GetRdbStore();
286 if (!rdbStore) {
287 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
288 return "";
289 }
290 int version = -1;
291 rdbStore->GetVersion(version);
292 if (version != -1) {
293 return std::to_string(version);
294 }
295 return "";
296 };
297
RenameTable(const std::string & oldName,const std::string & newName)298 bool AppDetailsRdbDataMgr::RenameTable(const std::string &oldName, const std::string &newName)
299 {
300 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
301 std::string sql = "ALTER TABLE " + oldName + " RENAME TO " + newName + ";";
302 auto rdbStore = GetRdbStore();
303 if (!rdbStore) {
304 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail.");
305 return false;
306 }
307 CriticalLock lock;
308 auto ret = rdbStore->ExecuteSql(sql);
309 if (ret != NativeRdb::E_OK) {
310 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "exec sql fail. ret:%{public}d", ret);
311 return false;
312 }
313 return true;
314 };
315
GetRdbStore()316 std::shared_ptr<NativeRdb::RdbStore> AppDetailsRdbDataMgr::GetRdbStore()
317 {
318 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
319 std::lock_guard<ffrt::mutex> lock(mtx_);
320 if (rdbStore_ != nullptr) {
321 return rdbStore_;
322 }
323 NativeRdb::RdbStoreConfig rdbStoreConfig(conf_.rdbPath + conf_.rdbName);
324 rdbStoreConfig.SetCreateNecessary(conf_.fileCreated);
325 rdbStoreConfig.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
326 int32_t errCode = NativeRdb::E_OK;
327 AppDetailsRdbOpenCallback appDomainVerifyRdbOpenCallback(conf_);
328 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(
329 rdbStoreConfig, conf_.version, appDomainVerifyRdbOpenCallback, errCode);
330 if (errCode == NativeRdb::E_OK) {
331 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore success.");
332 PostDelayCloseTask(CLOSE_DELAY_TIME_S);
333 } else {
334 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get rdbStore fail, err:%{public}d", errCode);
335 }
336 return rdbStore_;
337 };
338
CheckRdbReturnIfOk(int errcode)339 bool AppDetailsRdbDataMgr::CheckRdbReturnIfOk(int errcode)
340 {
341 if (errcode != NativeRdb::E_OK) {
342 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb failed, ret: %{public}d", errcode);
343 return false;
344 }
345 return true;
346 }
347
Query(const NativeRdb::AbsRdbPredicates & predicates,const std::vector<std::string> & columns,RdbForEachRetCb cb)348 bool AppDetailsRdbDataMgr::Query(const NativeRdb::AbsRdbPredicates& predicates,
349 const std::vector<std::string>& columns, RdbForEachRetCb cb)
350 {
351 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
352 auto rdbStore = GetRdbStore();
353 if (!rdbStore) {
354 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb store is null");
355 return false;
356 }
357 auto absSharedResultSet = rdbStore->Query(predicates, columns);
358 if (absSharedResultSet == nullptr) {
359 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore query absSharedResultSet failed");
360 return false;
361 }
362 auto guard = std::unique_ptr<void, std::function<void(void*)>>(nullptr,
363 [&](void*) {
364 absSharedResultSet->Close();
365 });
366 if (!absSharedResultSet->HasBlock()) {
367 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "absSharedResultSet has no block");
368 return false;
369 }
370 if (CheckRdbReturnIfOk(absSharedResultSet->GoToFirstRow())) {
371 do {
372 if (!cb(absSharedResultSet)) {
373 return false;
374 }
375 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
376 } else {
377 APP_DOMAIN_VERIFY_HILOGW(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "GoToFirstRow fail, seems rdb table empty");
378 return false;
379 }
380 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "call end");
381 return true;
382 };
383
384 }
385 }
386