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