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