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