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