1 /*
2 * Copyright (c) 2021-2022 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 "form_db_cache.h"
17
18 #include <cinttypes>
19
20 #include "fms_log_wrapper.h"
21 #include "form_bms_helper.h"
22 #include "form_data_mgr.h"
23 #include "form_db_info.h"
24 #include "form_mgr_errors.h"
25 #include "form_provider_mgr.h"
26
27 namespace OHOS {
28 namespace AppExecFwk {
FormDbCache()29 FormDbCache::FormDbCache()
30 {
31 HILOG_INFO("create");
32 }
33
~FormDbCache()34 FormDbCache::~FormDbCache()
35 {
36 HILOG_INFO("destroy");
37 }
38
39 /**
40 * @brief Load form data from DB to DbCache when starting.
41 * @return Void.
42 */
Start()43 void FormDbCache::Start()
44 {
45 HILOG_INFO("call");
46 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
47 std::vector<InnerFormInfo> innerFormInfos;
48 innerFormInfos.clear();
49 if (FormInfoRdbStorageMgr::GetInstance().LoadFormData(innerFormInfos) != ERR_OK) {
50 HILOG_ERROR("LoadFormData failed");
51 return;
52 }
53
54 for (unsigned int i = 0; i < innerFormInfos.size(); i++) {
55 FormDBInfo formDBInfo = innerFormInfos.at(i).GetFormDBInfo();
56 formDBInfos_.emplace_back(formDBInfo);
57 }
58 }
59
60 /**
61 * @brief Save or update form data to DbCache and DB.
62 * @param formDBInfo Form data.
63 * @return Returns ERR_OK on success, others on failure.
64 */
SaveFormInfo(const FormDBInfo &formDBInfo)65 ErrCode FormDbCache::SaveFormInfo(const FormDBInfo &formDBInfo)
66 {
67 HILOG_INFO("formId:%{public}" PRId64, formDBInfo.formId);
68 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
69 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), formDBInfo);
70 if (iter != formDBInfos_.end()) {
71 if (iter->Compare(formDBInfo) == false) {
72 HILOG_WARN("need update, formId[%{public}" PRId64 "]", formDBInfo.formId);
73 *iter = formDBInfo;
74 InnerFormInfo innerFormInfo(formDBInfo);
75 return FormInfoRdbStorageMgr::GetInstance().ModifyStorageFormData(innerFormInfo);
76 } else {
77 HILOG_WARN("already exist, formId[%{public}" PRId64 "].", formDBInfo.formId);
78 return ERR_OK;
79 }
80 } else {
81 formDBInfos_.emplace_back(formDBInfo);
82 InnerFormInfo innerFormInfo(formDBInfo);
83 return FormInfoRdbStorageMgr::GetInstance().SaveStorageFormData(innerFormInfo);
84 }
85 }
86
87 /**
88 * @brief Save or update form data to DbCache and DB.
89 * @param formDBInfo Form data.
90 * @return Returns ERR_OK on success, others on failure.(NoLock)
91 */
SaveFormInfoNolock(const FormDBInfo &formDBInfo)92 ErrCode FormDbCache::SaveFormInfoNolock(const FormDBInfo &formDBInfo)
93 {
94 HILOG_INFO("formId:%{public}" PRId64, formDBInfo.formId);
95 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), formDBInfo);
96 if (iter != formDBInfos_.end()) {
97 if (iter->Compare(formDBInfo) == false) {
98 HILOG_WARN("need update, formId[%{public}" PRId64 "].", formDBInfo.formId);
99 *iter = formDBInfo;
100 InnerFormInfo innerFormInfo(formDBInfo);
101 return FormInfoRdbStorageMgr::GetInstance().ModifyStorageFormData(innerFormInfo);
102 } else {
103 HILOG_WARN("already exist, formId[%{public}" PRId64 "].", formDBInfo.formId);
104 return ERR_OK;
105 }
106 } else {
107 formDBInfos_.emplace_back(formDBInfo);
108 InnerFormInfo innerFormInfo(formDBInfo);
109 return FormInfoRdbStorageMgr::GetInstance().SaveStorageFormData(innerFormInfo);
110 }
111 }
112
113 /**
114 * @brief Delete form data in DbCache and DB with formId.
115 * @param formId form data Id.
116 * @return Returns ERR_OK on success, others on failure.
117 */
DeleteFormInfo(int64_t formId)118 ErrCode FormDbCache::DeleteFormInfo(int64_t formId)
119 {
120 HILOG_INFO("call");
121 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
122 FormDBInfo tmpForm;
123 tmpForm.formId = formId;
124 auto iter = find(formDBInfos_.begin(), formDBInfos_.end(), tmpForm);
125 if (iter == formDBInfos_.end()) {
126 HILOG_WARN("not find formId[%{public}" PRId64 "]", formId);
127 } else {
128 formDBInfos_.erase(iter);
129 }
130 if (FormInfoRdbStorageMgr::GetInstance().DeleteStorageFormData(std::to_string(formId)) == ERR_OK) {
131 return ERR_OK;
132 } else {
133 return ERR_APPEXECFWK_FORM_COMMON_CODE;
134 }
135 }
136 /**
137 * @brief Delete form data in DbCache and DB with formId.
138 * @param formId form data Id.
139 * @param removedDBForms Removed db form infos
140 * @return Returns ERR_OK on success, others on failure.
141 */
DeleteFormInfoByBundleName(const std::string &bundleName, const int32_t userId, std::vector<FormDBInfo> &removedDBForms)142 ErrCode FormDbCache::DeleteFormInfoByBundleName(const std::string &bundleName, const int32_t userId,
143 std::vector<FormDBInfo> &removedDBForms)
144 {
145 HILOG_DEBUG("call");
146 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
147 std::vector<FormDBInfo>::iterator itRecord;
148 for (itRecord = formDBInfos_.begin(); itRecord != formDBInfos_.end();) {
149 if ((bundleName == itRecord->bundleName) && (userId == itRecord->providerUserId)) {
150 int64_t formId = itRecord->formId;
151 if (FormInfoRdbStorageMgr::GetInstance().DeleteStorageFormData(std::to_string(formId)) == ERR_OK) {
152 removedDBForms.emplace_back(*itRecord);
153 itRecord = formDBInfos_.erase(itRecord);
154 } else {
155 itRecord++;
156 }
157 } else {
158 itRecord++;
159 }
160 }
161 return ERR_OK;
162 }
163
164 /**
165 * @brief Get all form data from DbCache.
166 * @param formDBInfos Storage all DbCache.
167 * @return Void.
168 */
GetAllFormInfo(std::vector<FormDBInfo> &formDBInfos)169 void FormDbCache::GetAllFormInfo(std::vector<FormDBInfo> &formDBInfos)
170 {
171 HILOG_INFO("call");
172 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
173 formDBInfos = formDBInfos_;
174 }
175
176 /**
177 * @brief Get record from DB cache with formId
178 * @param formId Form data Id
179 * @param record Form data
180 * @return Returns ERR_OK on success, others on failure.
181 */
GetDBRecord(const int64_t formId, FormRecord &record) const182 ErrCode FormDbCache::GetDBRecord(const int64_t formId, FormRecord &record) const
183 {
184 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
185 for (const FormDBInfo &dbInfo : formDBInfos_) {
186 if (dbInfo.formId == formId) {
187 record.userId = dbInfo.userId;
188 record.providerUserId= dbInfo.providerUserId;
189 record.formName = dbInfo.formName;
190 record.bundleName = dbInfo.bundleName;
191 record.moduleName = dbInfo.moduleName;
192 record.abilityName = dbInfo.abilityName;
193 record.formUserUids = dbInfo.formUserUids;
194 record.formLocation = dbInfo.formLocation;
195 record.enableForm = dbInfo.enableForm;
196 return ERR_OK;
197 }
198 }
199 HILOG_ERROR("not find formId[%{public}" PRId64 "]", formId);
200 return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
201 }
202 /**
203 * @brief Get record from DB cache with formId
204 * @param formId Form data Id
205 * @param record Form db data
206 * @return Returns ERR_OK on success, others on failure.
207 */
GetDBRecord(const int64_t formId, FormDBInfo &record) const208 ErrCode FormDbCache::GetDBRecord(const int64_t formId, FormDBInfo &record) const
209 {
210 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
211 for (const FormDBInfo &dbInfo : formDBInfos_) {
212 if (dbInfo.formId == formId) {
213 record = dbInfo;
214 return ERR_OK;
215 }
216 }
217 HILOG_ERROR("not find formId[%{public}" PRId64 "]", formId);
218 return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
219 }
220 /**
221 * @brief Use record save or update DB data and DB cache with formId
222 * @param formId Form data Id
223 * @param record Form data
224 * @return Returns ERR_OK on success, others on failure.
225 */
UpdateDBRecord(const int64_t formId, const FormRecord &record) const226 ErrCode FormDbCache::UpdateDBRecord(const int64_t formId, const FormRecord &record) const
227 {
228 FormDBInfo formDBInfo(formId, record);
229 return FormDbCache::GetInstance().SaveFormInfo(formDBInfo);
230 }
231 /**
232 * @brief Get no host db record.
233 * @param uid The caller uid.
234 * @param noHostFormDBList no host db record list.
235 * @param foundFormsMap Form Id list.
236 * @return Returns ERR_OK on success, others on failure.
237 */
GetNoHostDBForms(const int uid, std::map<FormIdKey, std::set<int64_t>> &noHostFormDBList, std::map<int64_t, bool> &foundFormsMap)238 ErrCode FormDbCache::GetNoHostDBForms(const int uid, std::map<FormIdKey,
239 std::set<int64_t>> &noHostFormDBList, std::map<int64_t, bool> &foundFormsMap)
240 {
241 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
242 for (FormDBInfo& dbInfo : formDBInfos_) {
243 if (dbInfo.Contains(uid)) {
244 dbInfo.Remove(uid);
245 if (dbInfo.formUserUids.empty()) {
246 FormIdKey formIdKey(dbInfo.bundleName, dbInfo.abilityName);
247 auto itIdsSet = noHostFormDBList.find(formIdKey);
248 if (itIdsSet == noHostFormDBList.end()) {
249 std::set<int64_t> formIdsSet;
250 formIdsSet.emplace(dbInfo.formId);
251 noHostFormDBList.emplace(formIdKey, formIdsSet);
252 } else {
253 itIdsSet->second.emplace(dbInfo.formId);
254 }
255 } else {
256 foundFormsMap.emplace(dbInfo.formId, false);
257 SaveFormInfoNolock(dbInfo);
258 FormBmsHelper::GetInstance().NotifyModuleNotRemovable(dbInfo.bundleName, dbInfo.moduleName);
259 }
260 }
261 }
262 return ERR_OK;
263 }
264 /**
265 * @brief Get match count by bundleName and moduleName.
266 * @param bundleName BundleName.
267 * @param moduleName ModuleName.
268 * @return Returns match count.
269 */
GetMatchCount(const std::string &bundleName, const std::string &moduleName)270 int FormDbCache::GetMatchCount(const std::string &bundleName, const std::string &moduleName)
271 {
272 int32_t matchCount = 0;
273 std::vector<FormDBInfo> formDBInfos;
274 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
275 for (const FormDBInfo &dbInfo : formDBInfos_) {
276 if (dbInfo.bundleName == bundleName && dbInfo.moduleName == moduleName) {
277 ++matchCount;
278 }
279 }
280 return matchCount;
281 }
282 /**
283 * @brief delete forms bu userId.
284 *
285 * @param userId user ID.
286 */
DeleteDBFormsByUserId(const int32_t userId)287 void FormDbCache::DeleteDBFormsByUserId(const int32_t userId)
288 {
289 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
290 std::vector<FormDBInfo>::iterator itRecord;
291 for (itRecord = formDBInfos_.begin(); itRecord != formDBInfos_.end();) {
292 if (userId == itRecord->providerUserId) {
293 int64_t formId = itRecord->formId;
294 if (FormInfoRdbStorageMgr::GetInstance().DeleteStorageFormData(std::to_string(formId)) == ERR_OK) {
295 itRecord = formDBInfos_.erase(itRecord);
296 } else {
297 HILOG_ERROR("fail delete form, formId[%{public}" PRId64 "]", formId);
298 itRecord++;
299 }
300 } else {
301 itRecord++;
302 }
303 }
304 }
305
306 /**
307 * @brief handle get no host invalid DB forms.
308 * @param userId User ID.
309 * @param callingUid The UID of the proxy.
310 * @param matchedFormIds The set of the valid forms.
311 * @param noHostDBFormsMap The map of the no host forms.
312 * @param foundFormsMap The map of the found forms.
313 */
GetNoHostInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds, std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap, std::map<int64_t, bool> &foundFormsMap)314 void FormDbCache::GetNoHostInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds,
315 std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap,
316 std::map<int64_t, bool> &foundFormsMap)
317 {
318 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
319 for (auto &formRecord: formDBInfos_) {
320 int64_t formId = formRecord.formId;
321 // check UID
322 auto iter = std::find(formRecord.formUserUids.begin(), formRecord.formUserUids.end(), callingUid);
323 if (iter == formRecord.formUserUids.end()) {
324 continue;
325 }
326 // check valid form set
327 if (matchedFormIds.find(formId) != matchedFormIds.end()) {
328 continue;
329 }
330 // checks if the form provider is the currently active user.
331 if (formRecord.providerUserId != userId) {
332 continue;
333 }
334
335 HILOG_DEBUG("found invalid form:%{public}" PRId64 "", formId);
336 formRecord.formUserUids.erase(iter);
337 if (formRecord.formUserUids.empty()) {
338 FormIdKey formIdKey(formRecord.bundleName, formRecord.abilityName);
339 auto itIdsSet = noHostDBFormsMap.find(formIdKey);
340 if (itIdsSet == noHostDBFormsMap.end()) {
341 std::set<int64_t> formIdsSet;
342 formIdsSet.emplace(formId);
343 noHostDBFormsMap.emplace(formIdKey, formIdsSet);
344 } else {
345 itIdsSet->second.emplace(formId);
346 }
347 } else {
348 foundFormsMap.emplace(formId, false);
349 SaveFormInfoNolock(formRecord);
350 FormBmsHelper::GetInstance().NotifyModuleNotRemovable(formRecord.bundleName, formRecord.moduleName);
351 }
352 }
353 }
354
355 /**
356 * @brief handle delete no host DB forms.
357 * @param callingUid The UID of the proxy.
358 * @param noHostFormDbMap The map of the no host forms.
359 * @param foundFormsMap The map of the found forms.
360 */
BatchDeleteNoHostDBForms(int32_t callingUid, std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap, std::map<int64_t, bool> &foundFormsMap)361 void FormDbCache::BatchDeleteNoHostDBForms(int32_t callingUid, std::map<FormIdKey, std::set<int64_t>> &noHostDBFormsMap,
362 std::map<int64_t, bool> &foundFormsMap)
363 {
364 std::set<FormIdKey> removableModuleSet;
365 for (auto &element : noHostDBFormsMap) {
366 std::set<int64_t> &formIds = element.second;
367 FormIdKey formIdKey = element.first;
368 std::string bundleName = formIdKey.bundleName;
369 std::string abilityName = formIdKey.abilityName;
370 FormProviderMgr::GetInstance().NotifyProviderFormsBatchDelete(bundleName, abilityName, formIds);
371 for (const int64_t formId : formIds) {
372 foundFormsMap.emplace(formId, true);
373 FormDBInfo dbInfo;
374 int errCode = GetDBRecord(formId, dbInfo);
375 if (errCode == ERR_OK) {
376 FormIdKey removableModuleFormIdKey(dbInfo.bundleName, dbInfo.moduleName);
377 removableModuleSet.emplace(removableModuleFormIdKey);
378 DeleteFormInfo(formId);
379 }
380 FormDataMgr::GetInstance().StopRenderingForm(formId);
381 FormDataMgr::GetInstance().DeleteFormRecord(formId);
382 }
383 }
384
385 for (const FormIdKey &item : removableModuleSet) {
386 int32_t matchCount = GetMatchCount(item.bundleName, item.moduleName);
387 if (matchCount == 0) {
388 FormBmsHelper::GetInstance().NotifyModuleRemovable(item.bundleName, item.moduleName);
389 }
390 }
391 }
392
393 /**
394 * @brief handle delete invalid DB forms.
395 * @param userId User ID.
396 * @param callingUid The UID of the proxy.
397 * @param matchedFormIds The set of the valid forms.
398 * @param removedFormsMap The map of the removed invalid forms.
399 * @return Returns ERR_OK on success, others on failure.
400 */
DeleteInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds, std::map<int64_t, bool> &removedFormsMap)401 ErrCode FormDbCache::DeleteInvalidDBForms(int32_t userId, int32_t callingUid, std::set<int64_t> &matchedFormIds,
402 std::map<int64_t, bool> &removedFormsMap)
403 {
404 HILOG_INFO("userId:%{public}d, callingUid:%{public}d", userId, callingUid);
405 std::map<int64_t, bool> foundFormsMap {};
406 std::map<FormIdKey, std::set<int64_t>> noHostDBFormsMap {};
407
408 GetNoHostInvalidDBForms(userId, callingUid, matchedFormIds, noHostDBFormsMap, foundFormsMap);
409
410 if (!foundFormsMap.empty()) {
411 for (const auto &element : foundFormsMap) {
412 FormDataMgr::GetInstance().DeleteFormUserUid(element.first, callingUid);
413 }
414 }
415
416 BatchDeleteNoHostDBForms(callingUid, noHostDBFormsMap, foundFormsMap);
417 HILOG_DEBUG("foundFormsMap size:%{public}zu", foundFormsMap.size());
418 HILOG_DEBUG("noHostDBFormsMap size:%{public}zu", noHostDBFormsMap.size());
419
420 if (!foundFormsMap.empty()) {
421 removedFormsMap.insert(foundFormsMap.begin(), foundFormsMap.end());
422 #ifdef THEME_MGR_ENABLE
423 DeleteThemeForms(removedFormsMap);
424 #endif
425 }
426
427 HILOG_INFO("done");
428 return ERR_OK;
429 }
430
431 #ifdef THEME_MGR_ENABLE
DeleteThemeForms(std::map<int64_t, bool> &removedFormsMap)432 void FormDbCache::DeleteThemeForms(std::map<int64_t, bool> &removedFormsMap)
433 {
434 HILOG_INFO("call");
435 std::vector<int64_t> removeList;
436 for (const auto &element : removedFormsMap) {
437 removeList.emplace_back(element.first);
438 }
439 ThemeManager::ThemeManagerClient::GetInstance().DeleteForm(removeList);
440 }
441 #endif
442
IsHostOwner(int64_t formId, int32_t hostUid)443 bool FormDbCache::IsHostOwner(int64_t formId, int32_t hostUid)
444 {
445 FormDBInfo dbInfo;
446 if (GetDBRecord(formId, dbInfo) != ERR_OK) {
447 HILOG_ERROR("get db record failed. formId:%{public}s", std::to_string(formId).c_str());
448 return false;
449 }
450
451 auto iter = std::find(dbInfo.formUserUids.begin(), dbInfo.formUserUids.end(), hostUid);
452 if (iter != dbInfo.formUserUids.end()) {
453 return true;
454 }
455
456 return false;
457 }
458
UpdateFormLocation(const int64_t formId, const int32_t formLocation)459 ErrCode FormDbCache::UpdateFormLocation(const int64_t formId, const int32_t formLocation)
460 {
461 std::lock_guard<std::mutex> lock(formDBInfosMutex_);
462 std::vector<FormDBInfo>::iterator itRecord;
463 for (itRecord = formDBInfos_.begin(); itRecord != formDBInfos_.end();) {
464 if (itRecord->formId == formId) {
465 itRecord->formLocation = (Constants::FormLocation)formLocation;
466 InnerFormInfo innerFormInfo(*itRecord);
467 return FormInfoRdbStorageMgr::GetInstance().ModifyStorageFormData(innerFormInfo);
468 }
469 ++itRecord;
470 }
471 return ERR_APPEXECFWK_FORM_INVALID_FORM_ID;
472 }
473
474 } // namespace AppExecFwk
475 } // namespace OHOS
476