1 /*
2 * Copyright (c) 2021-2023 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 "pre_bundle_profile.h"
17
18 #include "app_log_wrapper.h"
19 #include "string_ex.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 const int32_t COMMON_PRIORITY = 0;
25 const int32_t HIGH_PRIORITY = 1;
26 const std::string INSTALL_LIST = "install_list";
27 const std::string UNINSTALL_LIST = "uninstall_list";
28 const std::string EXTENSION_TYPE = "extensionType";
29 const std::string RECOVER_LIST = "recover_list";
30 const std::string INSTALL_ABILITY_CONFIGS = "install_ability_configs";
31 const std::string APP_DIR = "app_dir";
32 const std::string REMOVABLE = "removable";
33 const std::string PRIORITY = "priority";
34 const std::string BUNDLE_NAME = "bundleName";
35 const std::string TYPE_NAME = "name";
36 const std::string KEEP_ALIVE = "keepAlive";
37 const std::string SINGLETON = "singleton";
38 const std::string ALLOW_COMMON_EVENT = "allowCommonEvent";
39 const std::string RUNNING_RESOURCES_APPLY = "runningResourcesApply";
40 const std::string APP_SIGNATURE = "app_signature";
41 const std::string ASSOCIATED_WAKE_UP = "associatedWakeUp";
42 const std::string RESOURCES_PATH_1 = "/app/ohos.global.systemres";
43 const std::string RESOURCES_PATH_2 = "/app/SystemResources";
44 const std::string ALLOW_APP_DATA_NOT_CLEARED = "allowAppDataNotCleared";
45 const std::string ALLOW_APP_MULTI_PROCESS = "allowAppMultiProcess";
46 const std::string ALLOW_APP_DESKTOP_ICON_HIDE = "allowAppDesktopIconHide";
47 const std::string ALLOW_ABILITY_PRIORITY_QUERIED = "allowAbilityPriorityQueried";
48 const std::string ALLOW_ABILITY_EXCLUDE_FROM_MISSIONS = "allowAbilityExcludeFromMissions";
49 const std::string ALLOW_MISSION_NOT_CLEARED = "allowMissionNotCleared";
50 const std::string ALLOW_APP_USE_PRIVILEGE_EXTENSION = "allowAppUsePrivilegeExtension";
51 const std::string ALLOW_FORM_VISIBLE_NOTIFY = "allowFormVisibleNotify";
52 const std::string ALLOW_APP_SHARE_LIBRARY = "allowAppShareLibrary";
53 const std::string ALLOW_ENABLE_NOTIFICATION = "allowEnableNotification";
54 const std::string RESOURCES_APPLY = "resourcesApply";
55 }
56
TransformTo(const nlohmann::json & jsonBuf,std::set<PreScanInfo> & scanInfos) const57 ErrCode PreBundleProfile::TransformTo(
58 const nlohmann::json &jsonBuf,
59 std::set<PreScanInfo> &scanInfos) const
60 {
61 APP_LOGI("transform jsonBuf to PreScanInfos");
62 if (jsonBuf.is_discarded()) {
63 APP_LOGE("profile format error");
64 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
65 }
66
67 if (jsonBuf.find(INSTALL_LIST) == jsonBuf.end()) {
68 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
69 }
70
71 auto arrays = jsonBuf.at(INSTALL_LIST);
72 if (!arrays.is_array() || arrays.empty()) {
73 APP_LOGE("value is not array");
74 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
75 }
76
77 PreScanInfo preScanInfo;
78 for (const auto &array : arrays) {
79 if (!array.is_object()) {
80 APP_LOGE("array is not json object");
81 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
82 }
83
84 preScanInfo.Reset();
85 const auto &jsonObjectEnd = array.end();
86 int32_t parseResult = ERR_OK;
87 GetValueIfFindKey<std::string>(array,
88 jsonObjectEnd,
89 APP_DIR,
90 preScanInfo.bundleDir,
91 JsonType::STRING,
92 true,
93 parseResult,
94 ArrayType::NOT_ARRAY);
95 GetValueIfFindKey<bool>(array,
96 jsonObjectEnd,
97 REMOVABLE,
98 preScanInfo.removable,
99 JsonType::BOOLEAN,
100 false,
101 parseResult,
102 ArrayType::NOT_ARRAY);
103 bool isResourcesPath =
104 (preScanInfo.bundleDir.find(RESOURCES_PATH_1) != preScanInfo.bundleDir.npos) ||
105 (preScanInfo.bundleDir.find(RESOURCES_PATH_2) != preScanInfo.bundleDir.npos);
106 preScanInfo.priority = isResourcesPath ? HIGH_PRIORITY : COMMON_PRIORITY;
107 if (parseResult == ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP) {
108 APP_LOGE("bundleDir must exist, and it is empty here");
109 continue;
110 }
111
112 if (parseResult != ERR_OK) {
113 APP_LOGE("parse from json failed");
114 return parseResult;
115 }
116
117 APP_LOGD("preScanInfo(%{public}s)", preScanInfo.ToString().c_str());
118 auto iter = std::find(scanInfos.begin(), scanInfos.end(), preScanInfo);
119 if (iter != scanInfos.end()) {
120 APP_LOGD("Replace old preScanInfo(%{public}s)", preScanInfo.bundleDir.c_str());
121 scanInfos.erase(iter);
122 }
123
124 scanInfos.insert(preScanInfo);
125 }
126
127 return ERR_OK;
128 }
129
TransformTo(const nlohmann::json & jsonBuf,std::set<std::string> & uninstallList) const130 ErrCode PreBundleProfile::TransformTo(
131 const nlohmann::json &jsonBuf,
132 std::set<std::string> &uninstallList) const
133 {
134 APP_LOGD("transform jsonBuf to bundleNames");
135 if (jsonBuf.is_discarded()) {
136 APP_LOGE("profile format error");
137 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
138 }
139
140 const auto &jsonObjectEnd = jsonBuf.end();
141 int32_t parseResult = ERR_OK;
142 std::vector<std::string> names;
143 GetValueIfFindKey<std::vector<std::string>>(jsonBuf,
144 jsonObjectEnd,
145 UNINSTALL_LIST,
146 names,
147 JsonType::ARRAY,
148 false,
149 parseResult,
150 ArrayType::STRING);
151 for (const auto &name : names) {
152 APP_LOGD("uninstall bundleName %{public}s", name.c_str());
153 uninstallList.insert(name);
154 }
155
156 names.clear();
157 GetValueIfFindKey<std::vector<std::string>>(jsonBuf,
158 jsonObjectEnd,
159 RECOVER_LIST,
160 names,
161 JsonType::ARRAY,
162 false,
163 parseResult,
164 ArrayType::STRING);
165 for (const auto &name : names) {
166 APP_LOGD("recover bundleName %{public}s", name.c_str());
167 uninstallList.erase(name);
168 }
169
170 return parseResult;
171 }
172
TransformTo(const nlohmann::json & jsonBuf,std::set<PreBundleConfigInfo> & preBundleConfigInfos) const173 ErrCode PreBundleProfile::TransformTo(
174 const nlohmann::json &jsonBuf,
175 std::set<PreBundleConfigInfo> &preBundleConfigInfos) const
176 {
177 APP_LOGI("transform jsonBuf to preBundleConfigInfos");
178 if (jsonBuf.is_discarded()) {
179 APP_LOGE("profile format error");
180 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
181 }
182
183 if (jsonBuf.find(INSTALL_LIST) == jsonBuf.end()) {
184 APP_LOGE("installList no exist");
185 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
186 }
187
188 auto arrays = jsonBuf.at(INSTALL_LIST);
189 if (!arrays.is_array() || arrays.empty()) {
190 APP_LOGE("value is not array");
191 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
192 }
193
194 PreBundleConfigInfo preBundleConfigInfo;
195 for (const auto &array : arrays) {
196 if (!array.is_object()) {
197 APP_LOGE("array is not json object");
198 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
199 }
200
201 preBundleConfigInfo.Reset();
202 const auto &jsonObjectEnd = array.end();
203 int32_t parseResult = ERR_OK;
204 GetValueIfFindKey<std::string>(array,
205 jsonObjectEnd,
206 BUNDLE_NAME,
207 preBundleConfigInfo.bundleName,
208 JsonType::STRING,
209 true,
210 parseResult,
211 ArrayType::NOT_ARRAY);
212 GetValueIfFindKey<bool>(array,
213 jsonObjectEnd,
214 KEEP_ALIVE,
215 preBundleConfigInfo.keepAlive,
216 JsonType::BOOLEAN,
217 false,
218 parseResult,
219 ArrayType::NOT_ARRAY);
220 GetValueIfFindKey<bool>(array,
221 jsonObjectEnd,
222 SINGLETON,
223 preBundleConfigInfo.singleton,
224 JsonType::BOOLEAN,
225 false,
226 parseResult,
227 ArrayType::NOT_ARRAY);
228 GetValueIfFindKey<std::vector<std::string>>(array,
229 jsonObjectEnd,
230 ALLOW_COMMON_EVENT,
231 preBundleConfigInfo.allowCommonEvent,
232 JsonType::ARRAY,
233 false,
234 parseResult,
235 ArrayType::STRING);
236 GetValueIfFindKey<std::vector<std::string>>(array,
237 jsonObjectEnd,
238 APP_SIGNATURE,
239 preBundleConfigInfo.appSignature,
240 JsonType::ARRAY,
241 false,
242 parseResult,
243 ArrayType::STRING);
244 GetValueIfFindKey<bool>(array,
245 jsonObjectEnd,
246 RUNNING_RESOURCES_APPLY,
247 preBundleConfigInfo.runningResourcesApply,
248 JsonType::BOOLEAN,
249 false,
250 parseResult,
251 ArrayType::NOT_ARRAY);
252 GetValueIfFindKey<bool>(array,
253 jsonObjectEnd,
254 ASSOCIATED_WAKE_UP,
255 preBundleConfigInfo.associatedWakeUp,
256 JsonType::BOOLEAN,
257 false,
258 parseResult,
259 ArrayType::NOT_ARRAY);
260 GetValueIfFindKey<bool>(array,
261 jsonObjectEnd,
262 ALLOW_APP_DATA_NOT_CLEARED,
263 preBundleConfigInfo.userDataClearable,
264 JsonType::BOOLEAN,
265 false,
266 parseResult,
267 ArrayType::NOT_ARRAY);
268 GetValueIfFindKey<bool>(array,
269 jsonObjectEnd,
270 ALLOW_APP_MULTI_PROCESS,
271 preBundleConfigInfo.allowMultiProcess,
272 JsonType::BOOLEAN,
273 false,
274 parseResult,
275 ArrayType::NOT_ARRAY);
276 GetValueIfFindKey<bool>(array,
277 jsonObjectEnd,
278 ALLOW_APP_DESKTOP_ICON_HIDE,
279 preBundleConfigInfo.hideDesktopIcon,
280 JsonType::BOOLEAN,
281 false,
282 parseResult,
283 ArrayType::NOT_ARRAY);
284 GetValueIfFindKey<bool>(array,
285 jsonObjectEnd,
286 ALLOW_ABILITY_PRIORITY_QUERIED,
287 preBundleConfigInfo.allowQueryPriority,
288 JsonType::BOOLEAN,
289 false,
290 parseResult,
291 ArrayType::NOT_ARRAY);
292 GetValueIfFindKey<bool>(array,
293 jsonObjectEnd,
294 ALLOW_ABILITY_EXCLUDE_FROM_MISSIONS,
295 preBundleConfigInfo.allowExcludeFromMissions,
296 JsonType::BOOLEAN,
297 false,
298 parseResult,
299 ArrayType::NOT_ARRAY);
300 GetValueIfFindKey<bool>(array,
301 jsonObjectEnd,
302 ALLOW_MISSION_NOT_CLEARED,
303 preBundleConfigInfo.allowMissionNotCleared,
304 JsonType::BOOLEAN,
305 false,
306 parseResult,
307 ArrayType::NOT_ARRAY);
308 GetValueIfFindKey<bool>(array,
309 jsonObjectEnd,
310 ALLOW_APP_USE_PRIVILEGE_EXTENSION,
311 preBundleConfigInfo.allowUsePrivilegeExtension,
312 JsonType::BOOLEAN,
313 false,
314 parseResult,
315 ArrayType::NOT_ARRAY);
316 GetValueIfFindKey<bool>(array,
317 jsonObjectEnd,
318 ALLOW_FORM_VISIBLE_NOTIFY,
319 preBundleConfigInfo.formVisibleNotify,
320 JsonType::BOOLEAN,
321 false,
322 parseResult,
323 ArrayType::NOT_ARRAY);
324 GetValueIfFindKey<bool>(array,
325 jsonObjectEnd,
326 ALLOW_APP_SHARE_LIBRARY,
327 preBundleConfigInfo.appShareLibrary,
328 JsonType::BOOLEAN,
329 false,
330 parseResult,
331 ArrayType::NOT_ARRAY);
332 GetValueIfFindKey<bool>(array,
333 jsonObjectEnd,
334 ALLOW_ENABLE_NOTIFICATION,
335 preBundleConfigInfo.allowEnableNotification,
336 JsonType::BOOLEAN,
337 false,
338 parseResult,
339 ArrayType::NOT_ARRAY);
340 GetValueIfFindKey<std::vector<int32_t>>(array,
341 jsonObjectEnd,
342 RESOURCES_APPLY,
343 preBundleConfigInfo.resourcesApply,
344 JsonType::ARRAY,
345 false,
346 parseResult,
347 ArrayType::NUMBER);
348 if (array.find(ALLOW_APP_DATA_NOT_CLEARED) != jsonObjectEnd) {
349 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_APP_DATA_NOT_CLEARED);
350 preBundleConfigInfo.userDataClearable = !preBundleConfigInfo.userDataClearable;
351 }
352 if (array.find(ALLOW_APP_MULTI_PROCESS) != jsonObjectEnd) {
353 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_APP_MULTI_PROCESS);
354 }
355 if (array.find(ALLOW_APP_DESKTOP_ICON_HIDE) != jsonObjectEnd) {
356 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_APP_DESKTOP_ICON_HIDE);
357 }
358 if (array.find(ALLOW_ABILITY_PRIORITY_QUERIED) != jsonObjectEnd) {
359 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_ABILITY_PRIORITY_QUERIED);
360 }
361 if (array.find(ALLOW_ABILITY_EXCLUDE_FROM_MISSIONS) != jsonObjectEnd) {
362 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_ABILITY_EXCLUDE_FROM_MISSIONS);
363 }
364 if (array.find(ALLOW_MISSION_NOT_CLEARED) != jsonObjectEnd) {
365 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_MISSION_NOT_CLEARED);
366 }
367 if (array.find(ALLOW_APP_USE_PRIVILEGE_EXTENSION) != jsonObjectEnd) {
368 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_APP_USE_PRIVILEGE_EXTENSION);
369 }
370 if (array.find(ALLOW_FORM_VISIBLE_NOTIFY) != jsonObjectEnd) {
371 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_FORM_VISIBLE_NOTIFY);
372 }
373 if (array.find(ALLOW_APP_SHARE_LIBRARY) != jsonObjectEnd) {
374 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_APP_SHARE_LIBRARY);
375 }
376 if (array.find(ALLOW_ENABLE_NOTIFICATION) != jsonObjectEnd) {
377 preBundleConfigInfo.existInJsonFile.push_back(ALLOW_ENABLE_NOTIFICATION);
378 }
379 if (parseResult == ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP) {
380 APP_LOGE("bundlename must exist, and it is empty here");
381 continue;
382 }
383
384 if (parseResult != ERR_OK) {
385 APP_LOGE("parse from json failed");
386 return parseResult;
387 }
388
389 APP_LOGD("preBundleConfigInfo(%{public}s)", preBundleConfigInfo.ToString().c_str());
390 auto iter = preBundleConfigInfos.find(preBundleConfigInfo);
391 if (iter != preBundleConfigInfos.end()) {
392 APP_LOGD("Replace old preBundleConfigInfo(%{public}s)",
393 preBundleConfigInfo.bundleName.c_str());
394 preBundleConfigInfos.erase(iter);
395 }
396
397 preBundleConfigInfos.insert(preBundleConfigInfo);
398 }
399
400 return ERR_OK;
401 }
402
TransformJsonToExtensionTypeList(const nlohmann::json & jsonBuf,std::set<std::string> & extensionTypeList) const403 ErrCode PreBundleProfile::TransformJsonToExtensionTypeList(
404 const nlohmann::json &jsonBuf, std::set<std::string> &extensionTypeList) const
405 {
406 if (jsonBuf.is_discarded()) {
407 APP_LOGE("Profile format error");
408 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
409 }
410
411 if (jsonBuf.find(EXTENSION_TYPE) == jsonBuf.end()) {
412 APP_LOGE("Profile does not have 'extensionType'key");
413 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
414 }
415
416 auto arrays = jsonBuf.at(EXTENSION_TYPE);
417 if (!arrays.is_array() || arrays.empty()) {
418 APP_LOGE("Value is not array");
419 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
420 }
421
422 for (const auto &array : arrays) {
423 if (!array.is_object()) {
424 APP_LOGE("Array is not json object");
425 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_TYPE_ERROR;
426 }
427
428 std::string extensionAbilityType;
429 const auto &jsonObjectEnd = array.end();
430 int32_t parseResult = ERR_OK;
431 GetValueIfFindKey<std::string>(array,
432 jsonObjectEnd,
433 TYPE_NAME,
434 extensionAbilityType,
435 JsonType::STRING,
436 true,
437 parseResult,
438 ArrayType::NOT_ARRAY);
439 extensionTypeList.insert(extensionAbilityType);
440 }
441
442 return ERR_OK;
443 }
444 } // namespace AppExecFwk
445 } // namespace OHOS
446