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