1 /*
2 * Copyright (c) 2021 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_info_mgr.h"
17
18 #include <utility>
19
20 #include "bundle_mgr_client.h"
21 #include "extension_form_profile.h"
22 #include "form_bms_helper.h"
23 #include "form_info_storage.h"
24 #include "form_info_storage_mgr.h"
25 #include "form_util.h"
26 #include "hilog_wrapper.h"
27 #include "in_process_call_wrapper.h"
28 #include "ipc_skeleton.h"
29 #include "json_serializer.h"
30 #include "permission_verification.h"
31
32 namespace OHOS {
33 namespace AppExecFwk {
34 namespace {
35 const std::string FORM_METADATA_NAME = "ohos.extension.form";
36 } // namespace
37
LoadFormConfigInfoByBundleName(const std::string & bundleName,std::vector<FormInfo> & formInfos,int32_t userId)38 ErrCode FormInfoHelper::LoadFormConfigInfoByBundleName(const std::string &bundleName, std::vector<FormInfo> &formInfos,
39 int32_t userId)
40 {
41 if (bundleName.empty()) {
42 HILOG_ERROR("bundleName is invalid");
43 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
44 }
45
46 sptr<IBundleMgr> iBundleMgr = FormBmsHelper::GetInstance().GetBundleMgr();
47 if (iBundleMgr == nullptr) {
48 HILOG_ERROR("GetBundleMgr, failed to get IBundleMgr.");
49 return ERR_APPEXECFWK_FORM_GET_BMS_FAILED;
50 }
51
52 BundleInfo bundleInfo;
53 if (!IN_PROCESS_CALL(iBundleMgr->GetBundleInfo(bundleName, GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId))) {
54 HILOG_ERROR("failed to get bundle info.");
55 return ERR_APPEXECFWK_FORM_GET_INFO_FAILED;
56 }
57
58 ErrCode errCode = LoadAbilityFormConfigInfo(bundleInfo, formInfos);
59 if (errCode != ERR_OK) {
60 HILOG_ERROR("failed to load FA form config info, error code=%{public}d.", errCode);
61 }
62
63 errCode = LoadStageFormConfigInfo(bundleInfo, formInfos);
64 if (errCode != ERR_OK) {
65 HILOG_ERROR("failed to load stage form config info, error code=%{public}d.", errCode);
66 }
67
68 return ERR_OK;
69 }
70
LoadStageFormConfigInfo(const BundleInfo & bundleInfo,std::vector<FormInfo> & formInfos)71 ErrCode FormInfoHelper::LoadStageFormConfigInfo(const BundleInfo &bundleInfo, std::vector<FormInfo> &formInfos)
72 {
73 std::shared_ptr<BundleMgrClient> client = DelayedSingleton<BundleMgrClient>::GetInstance();
74 if (client == nullptr) {
75 HILOG_ERROR("failed to get BundleMgrClient.");
76 return ERR_APPEXECFWK_FORM_GET_BMS_FAILED;
77 }
78
79 for (auto const &extensionInfo: bundleInfo.extensionInfos) {
80 if (extensionInfo.type != ExtensionAbilityType::FORM) {
81 continue;
82 }
83
84 std::vector<std::string> profileInfos {};
85 if (!client->GetResConfigFile(extensionInfo, FORM_METADATA_NAME, profileInfos)) {
86 HILOG_ERROR("failed to get form metadata.");
87 continue;
88 }
89
90 for (const auto &profileInfo: profileInfos) {
91 std::vector<ExtensionFormInfo> extensionFormInfos;
92 ErrCode errCode = ExtensionFormProfile::TransformTo(profileInfo, extensionFormInfos);
93 if (errCode != ERR_OK) {
94 HILOG_WARN("failed to transform profile to extension form info");
95 continue;
96 }
97 for (const auto &extensionFormInfo: extensionFormInfos) {
98 formInfos.emplace_back(extensionInfo, extensionFormInfo);
99 }
100 }
101 }
102 return ERR_OK;
103 }
104
LoadAbilityFormConfigInfo(const BundleInfo & bundleInfo,std::vector<FormInfo> & formInfos)105 ErrCode FormInfoHelper::LoadAbilityFormConfigInfo(const BundleInfo &bundleInfo, std::vector<FormInfo> &formInfos)
106 {
107 sptr<IBundleMgr> iBundleMgr = FormBmsHelper::GetInstance().GetBundleMgr();
108 if (iBundleMgr == nullptr) {
109 HILOG_ERROR("failed to get IBundleMgr.");
110 return ERR_APPEXECFWK_FORM_GET_BMS_FAILED;
111 }
112
113 const std::string &bundleName = bundleInfo.name;
114 for (const auto &modelInfo: bundleInfo.hapModuleInfos) {
115 const std::string &moduleName = modelInfo.moduleName;
116 std::vector<FormInfo> formInfoVec {};
117 if (!IN_PROCESS_CALL(iBundleMgr->GetFormsInfoByModule(bundleName, moduleName, formInfoVec))) {
118 continue;
119 }
120 for (const auto &formInfo: formInfoVec) {
121 // check form info
122 formInfos.push_back(formInfo);
123 }
124 }
125
126 return ERR_OK;
127 }
128
BundleFormInfo(std::string bundleName)129 BundleFormInfo::BundleFormInfo(std::string bundleName) : bundleName_(std::move(bundleName))
130 {
131 }
132
InitFromJson(const std::string & formInfoStoragesJson)133 ErrCode BundleFormInfo::InitFromJson(const std::string &formInfoStoragesJson)
134 {
135 nlohmann::json jsonObject = nlohmann::json::parse(formInfoStoragesJson, nullptr, false);
136 if (jsonObject.is_discarded()) {
137 HILOG_ERROR("bad profile");
138 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
139 }
140 std::unique_lock<std::shared_timed_mutex> guard(formInfosMutex_);
141 std::vector<AAFwk::FormInfoStorage> formInfoStorages = jsonObject.get<std::vector<AAFwk::FormInfoStorage>>();
142 for (const auto &item : formInfoStorages) {
143 formInfoStorages_.push_back(item);
144 }
145 return ERR_OK;
146 }
147
Update(int32_t userId)148 ErrCode BundleFormInfo::Update(int32_t userId)
149 {
150 HILOG_INFO("Update form infos, userId is %{public}d.", userId);
151 std::unique_lock<std::shared_timed_mutex> guard(formInfosMutex_);
152 std::vector<FormInfo> formInfos;
153 ErrCode errCode = FormInfoHelper::LoadFormConfigInfoByBundleName(bundleName_, formInfos, userId);
154 if (errCode != ERR_OK) {
155 return errCode;
156 }
157
158 for (auto item = formInfoStorages_.begin(); item != formInfoStorages_.end();) {
159 if (item->userId == userId) {
160 item = formInfoStorages_.erase(item);
161 } else {
162 ++item;
163 }
164 }
165
166 if (!formInfos.empty()) {
167 AAFwk::FormInfoStorage formInfoStorage(userId, formInfos);
168 formInfoStorages_.push_back(formInfoStorage);
169 }
170
171 if (formInfoStorages_.empty()) {
172 HILOG_INFO("form info Storages is empty.");
173 return ERR_OK;
174 }
175
176 nlohmann::json jsonObject = formInfoStorages_;
177 if (jsonObject.is_discarded()) {
178 HILOG_ERROR("bad form infos.");
179 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
180 }
181 std::string formInfoStoragesStr = jsonObject.dump(Constants::DUMP_INDENT);
182 errCode = FormInfoStorageMgr::GetInstance().UpdateBundleFormInfos(bundleName_, formInfoStoragesStr);
183 return errCode;
184 }
185
Remove(int32_t userId)186 ErrCode BundleFormInfo::Remove(int32_t userId)
187 {
188 HILOG_INFO("Remove form infos, userId is %{public}d.", userId);
189 std::unique_lock<std::shared_timed_mutex> guard(formInfosMutex_);
190 for (auto item = formInfoStorages_.begin(); item != formInfoStorages_.end();) {
191 if (item->userId == userId) {
192 item = formInfoStorages_.erase(item);
193 } else {
194 ++item;
195 }
196 }
197
198 ErrCode errCode;
199 if (formInfoStorages_.empty()) {
200 errCode = FormInfoStorageMgr::GetInstance().RemoveBundleFormInfos(bundleName_);
201 } else {
202 nlohmann::json jsonObject = formInfoStorages_;
203 if (jsonObject.is_discarded()) {
204 HILOG_ERROR("bad form infos.");
205 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
206 }
207 std::string formInfoStoragesStr = jsonObject.dump(Constants::DUMP_INDENT);
208 errCode = FormInfoStorageMgr::GetInstance().UpdateBundleFormInfos(bundleName_, formInfoStoragesStr);
209 }
210
211 return errCode;
212 }
213
Empty()214 bool BundleFormInfo::Empty()
215 {
216 std::shared_lock<std::shared_timed_mutex> guard(formInfosMutex_);
217 return formInfoStorages_.empty();
218 }
219
GetAllFormsInfo(std::vector<FormInfo> & formInfos)220 ErrCode BundleFormInfo::GetAllFormsInfo(std::vector<FormInfo> &formInfos)
221 {
222 HILOG_INFO("%{public}s begin.", __func__);
223 std::shared_lock<std::shared_timed_mutex> guard(formInfosMutex_);
224 int32_t userId = FormUtil::GetCurrentAccountId();
225 for (const auto &item : formInfoStorages_) {
226 item.GetAllFormsInfo(userId, formInfos);
227 }
228 return ERR_OK;
229 }
230
GetFormsInfoByModule(const std::string & moduleName,std::vector<FormInfo> & formInfos)231 ErrCode BundleFormInfo::GetFormsInfoByModule(const std::string &moduleName, std::vector<FormInfo> &formInfos)
232 {
233 std::shared_lock<std::shared_timed_mutex> guard(formInfosMutex_);
234 int32_t userId = FormUtil::GetCurrentAccountId();
235 for (const auto &item : formInfoStorages_) {
236 item.GetFormsInfoByModule(userId, moduleName, formInfos);
237 }
238 return ERR_OK;
239 }
240
FormInfoMgr()241 FormInfoMgr::FormInfoMgr()
242 {
243 HILOG_INFO("FormInfoMgr is created");
244 }
245
246 FormInfoMgr::~FormInfoMgr() = default;
247
Start()248 ErrCode FormInfoMgr::Start()
249 {
250 std::vector<std::pair<std::string, std::string>> formInfoStorages;
251 ErrCode errCode = FormInfoStorageMgr::GetInstance().LoadFormInfos(formInfoStorages);
252 if (errCode != ERR_OK) {
253 HILOG_ERROR("LoadFormData failed.");
254 return errCode;
255 }
256
257 std::unique_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
258 for (const auto &item: formInfoStorages) {
259 const std::string &bundleName = item.first;
260 const std::string &formInfoStoragesJson = item.second;
261 auto bundleFormInfoPtr = std::make_shared<BundleFormInfo>(bundleName);
262 errCode = bundleFormInfoPtr->InitFromJson(formInfoStoragesJson);
263 if (errCode != ERR_OK) {
264 continue;
265 }
266 HILOG_ERROR("load bundle %{public}s form infos success.", bundleName.c_str());
267 bundleFormInfoMap_[bundleName] = bundleFormInfoPtr;
268 }
269 HILOG_INFO("load bundle form infos from db done.");
270 return ERR_OK;
271 }
272
Update(const std::string & bundleName,int32_t userId)273 ErrCode FormInfoMgr::Update(const std::string &bundleName, int32_t userId)
274 {
275 if (bundleName.empty()) {
276 HILOG_ERROR("bundleName is empty.");
277 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
278 }
279
280 std::shared_ptr<BundleFormInfo> bundleFormInfoPtr;
281 auto search = bundleFormInfoMap_.find(bundleName);
282 if (search != bundleFormInfoMap_.end()) {
283 bundleFormInfoPtr = search->second;
284 } else {
285 bundleFormInfoPtr = std::make_shared<BundleFormInfo>(bundleName);
286 }
287
288 ErrCode errCode = bundleFormInfoPtr->Update(userId);
289 if (errCode != ERR_OK) {
290 return errCode;
291 }
292
293 if (bundleFormInfoPtr->Empty()) {
294 // no forms found, no need to be inserted into the map
295 return ERR_OK;
296 }
297
298 std::unique_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
299 bundleFormInfoMap_[bundleName] = bundleFormInfoPtr;
300 HILOG_ERROR("update forms info success, bundleName=%{public}s.", bundleName.c_str());
301 return ERR_OK;
302 }
303
Remove(const std::string & bundleName,int32_t userId)304 ErrCode FormInfoMgr::Remove(const std::string &bundleName, int32_t userId)
305 {
306 if (bundleName.empty()) {
307 HILOG_ERROR("bundleName is empty.");
308 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
309 }
310
311 std::unique_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
312 auto bundleFormInfoIter = bundleFormInfoMap_.find(bundleName);
313 if (bundleFormInfoIter == bundleFormInfoMap_.end()) {
314 // BundleFormInfo not found, no need to remove
315 return ERR_OK;
316 }
317
318 ErrCode errCode = ERR_OK;
319 if (bundleFormInfoIter->second != nullptr) {
320 errCode = bundleFormInfoIter->second->Remove(userId);
321 }
322
323 if (bundleFormInfoIter->second->Empty()) {
324 bundleFormInfoMap_.erase(bundleFormInfoIter);
325 }
326 HILOG_ERROR("remove forms info success, bundleName=%{public}s.", bundleName.c_str());
327 return errCode;
328 }
329
GetAllFormsInfo(std::vector<FormInfo> & formInfos)330 ErrCode FormInfoMgr::GetAllFormsInfo(std::vector<FormInfo> &formInfos)
331 {
332 bool hasPermission = CheckBundlePermission();
333 std::shared_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
334 if (hasPermission) {
335 for (const auto &bundleFormInfo: bundleFormInfoMap_) {
336 if (bundleFormInfo.second != nullptr) {
337 bundleFormInfo.second->GetAllFormsInfo(formInfos);
338 }
339 }
340 } else {
341 for (const auto &bundleFormInfo: bundleFormInfoMap_) {
342 if (IsCaller(bundleFormInfo.first)) {
343 if (bundleFormInfo.second != nullptr) {
344 bundleFormInfo.second->GetAllFormsInfo(formInfos);
345 }
346 return ERR_OK;
347 }
348 }
349 }
350 return ERR_OK;
351 }
352
GetFormsInfoByBundle(const std::string & bundleName,std::vector<FormInfo> & formInfos)353 ErrCode FormInfoMgr::GetFormsInfoByBundle(const std::string &bundleName, std::vector<FormInfo> &formInfos)
354 {
355 if (bundleName.empty()) {
356 HILOG_ERROR("bundleName is empty.");
357 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
358 }
359
360 if (!CheckBundlePermission() && !IsCaller(bundleName)) {
361 return ERR_APPEXECFWK_FORM_PERMISSION_DENY_BUNDLE;
362 }
363
364 std::shared_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
365 auto bundleFormInfoIter = bundleFormInfoMap_.find(bundleName);
366 if (bundleFormInfoIter == bundleFormInfoMap_.end()) {
367 HILOG_ERROR("no forms found.");
368 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
369 }
370
371 if (bundleFormInfoIter->second != nullptr) {
372 bundleFormInfoIter->second->GetAllFormsInfo(formInfos);
373 }
374 return ERR_OK;
375 }
376
GetFormsInfoByModule(const std::string & bundleName,const std::string & moduleName,std::vector<FormInfo> & formInfos)377 ErrCode FormInfoMgr::GetFormsInfoByModule(const std::string &bundleName, const std::string &moduleName,
378 std::vector<FormInfo> &formInfos)
379 {
380 if (bundleName.empty()) {
381 HILOG_ERROR("bundleName is empty.");
382 return ERR_APPEXECFWK_FORM_INVALID_PARAM;
383 }
384
385 if (!CheckBundlePermission() && !IsCaller(bundleName)) {
386 return ERR_APPEXECFWK_FORM_PERMISSION_DENY_BUNDLE;
387 }
388
389 std::shared_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
390 auto bundleFormInfoIter = bundleFormInfoMap_.find(bundleName);
391 if (bundleFormInfoIter == bundleFormInfoMap_.end()) {
392 HILOG_ERROR("no forms found for %{public}s.", bundleName.c_str());
393 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
394 }
395
396 if (bundleFormInfoIter->second != nullptr) {
397 bundleFormInfoIter->second->GetFormsInfoByModule(moduleName, formInfos);
398 }
399 return ERR_OK;
400 }
401
GetOrCreateBundleFromInfo(const std::string & bundleName)402 std::shared_ptr<BundleFormInfo> FormInfoMgr::GetOrCreateBundleFromInfo(const std::string &bundleName)
403 {
404 {
405 std::shared_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
406 auto bundleFormInfoIter = bundleFormInfoMap_.find(bundleName);
407 if (bundleFormInfoIter != bundleFormInfoMap_.end()) {
408 // found
409 return bundleFormInfoIter->second;
410 }
411 }
412
413 // not found
414 std::unique_lock<std::shared_timed_mutex> guard(bundleFormInfoMapMutex_);
415 auto bundleFormInfoIter = bundleFormInfoMap_.find(bundleName);
416 // try to find again
417 if (bundleFormInfoIter != bundleFormInfoMap_.end()) {
418 // found
419 return bundleFormInfoIter->second;
420 }
421 auto bundleFormInfoPtr = std::make_shared<BundleFormInfo>(bundleName);
422 bundleFormInfoMap_[bundleName] = bundleFormInfoPtr;
423 return bundleFormInfoPtr;
424 }
425
IsCaller(std::string bundleName)426 bool FormInfoMgr::IsCaller(std::string bundleName)
427 {
428 auto bms = FormBmsHelper::GetInstance().GetBundleMgr();
429 if (!bms) {
430 return false;
431 }
432 AppExecFwk::BundleInfo bundleInfo;
433 bool ret = IN_PROCESS_CALL(
434 bms->GetBundleInfo(bundleName, GET_BUNDLE_DEFAULT, bundleInfo, FormUtil::GetCurrentAccountId()));
435 if (!ret) {
436 HILOG_ERROR("Failed to get bundle info.");
437 return false;
438 }
439 auto callerToken = IPCSkeleton::GetCallingTokenID();
440 if (bundleInfo.applicationInfo.accessTokenId == callerToken) {
441 return true;
442 }
443 return false;
444 }
445
CheckBundlePermission()446 bool FormInfoMgr::CheckBundlePermission()
447 {
448 auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
449 if (isSaCall) {
450 return true;
451 }
452 auto isCallingPerm = AAFwk::PermissionVerification::GetInstance()->VerifyCallingPermission(
453 AppExecFwk::Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
454 if (isCallingPerm) {
455 return true;
456 }
457 HILOG_ERROR("Permission verification failed");
458 return false;
459 }
460 } // namespace AppExecFwk
461 } // namespace OHOS
462