1 /*
2 * Copyright (c) 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 <unordered_map>
17
18 #include "installer.h"
19
20 #include "appexecfwk_errors.h"
21 #include "app_log_wrapper.h"
22 #include "bundle_errors.h"
23 #include "bundle_death_recipient.h"
24 #include "bundle_mgr_interface.h"
25 #include "bundle_mgr_proxy.h"
26 #include "business_error.h"
27 #include "common_func.h"
28 #include "if_system_ability_manager.h"
29 #include "installer_callback.h"
30 #include "napi_arg.h"
31 #include "napi_constants.h"
32 #include "system_ability_definition.h"
33
34 namespace OHOS {
35 namespace AppExecFwk {
36 namespace {
37 // resource name
38 const std::string RESOURCE_NAME_OF_GET_BUNDLE_INSTALLER = "GetBundleInstaller";
39 const std::string RESOURCE_NAME_OF_INSTALL = "Install";
40 const std::string RESOURCE_NAME_OF_UNINSTALL = "Uninstall";
41 const std::string RESOURCE_NAME_OF_RECOVER = "Recover";
42 const std::string EMPTY_STRING = "";
43 // install message
44 constexpr const char* INSTALL_PERMISSION = "ohos.permission.INSTALL_BUNDLE";
45 constexpr const char* PARAMETERS = "parameters";
46 constexpr const char* CORRESPONDING_TYPE = "corresponding type";
47 constexpr const char* FUNCTION_TYPE = "napi_function";
48 constexpr const char* CALLBACK = "callback";
49 // property name
50 const std::string USER_ID = "userId";
51 const std::string INSTALL_FLAG = "installFlag";
52 const std::string IS_KEEP_DATA = "isKeepData";
53 const std::string CROWD_TEST_DEADLINE = "crowdtestDeadline";
54 const std::string MODULE_NAME = "moduleName";
55 const std::string HASH_VALUE = "hashValue";
56 const std::string HASH_PARAMS = "hashParams";
57
58 constexpr int32_t FIRST_PARAM = 0;
59 constexpr int32_t SECOND_PARAM = 1;
60 } // namespace
61 napi_ref thread_local g_classBundleInstaller;
62
~AsyncInstallCallbackInfo()63 AsyncInstallCallbackInfo::~AsyncInstallCallbackInfo()
64 {
65 if (callback) {
66 napi_delete_reference(env, callback);
67 callback = nullptr;
68 }
69 if (asyncWork) {
70 napi_delete_async_work(env, asyncWork);
71 asyncWork = nullptr;
72 }
73 }
74
~AsyncGetBundleInstallerCallbackInfo()75 AsyncGetBundleInstallerCallbackInfo::~AsyncGetBundleInstallerCallbackInfo()
76 {
77 if (callback) {
78 napi_delete_reference(env, callback);
79 callback = nullptr;
80 }
81 if (asyncWork) {
82 napi_delete_async_work(env, asyncWork);
83 asyncWork = nullptr;
84 }
85 }
86
GetBundleInstallerCompleted(napi_env env,napi_status status,void * data)87 void GetBundleInstallerCompleted(napi_env env, napi_status status, void *data)
88 {
89 AsyncGetBundleInstallerCallbackInfo *asyncCallbackInfo =
90 reinterpret_cast<AsyncGetBundleInstallerCallbackInfo *>(data);
91 std::unique_ptr<AsyncGetBundleInstallerCallbackInfo> callbackPtr {asyncCallbackInfo};
92
93 napi_value m_classBundleInstaller = nullptr;
94 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, g_classBundleInstaller,
95 &m_classBundleInstaller));
96 napi_value result[CALLBACK_PARAM_SIZE] = {0};
97 auto iBundleMgr = CommonFunc::GetBundleMgr();
98 if (iBundleMgr == nullptr) {
99 APP_LOGE("can not get iBundleMgr");
100 return;
101 }
102 if (!iBundleMgr->VerifySystemApi(Constants::INVALID_API_VERSION)) {
103 APP_LOGE("non-system app calling system api");
104 result[0] = BusinessError::CreateCommonError(
105 env, ERROR_NOT_SYSTEM_APP, RESOURCE_NAME_OF_GET_BUNDLE_INSTALLER, INSTALL_PERMISSION);
106 if (callbackPtr->deferred) {
107 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
108 } else {
109 napi_value callback = nullptr;
110 napi_value placeHolder = nullptr;
111 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
112 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
113 sizeof(result) / sizeof(result[0]), result, &placeHolder));
114 }
115 return;
116 }
117 NAPI_CALL_RETURN_VOID(env, napi_new_instance(env, m_classBundleInstaller, 0, nullptr, &result[SECOND_PARAM]));
118
119 if (callbackPtr->deferred) {
120 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, callbackPtr->deferred, result[SECOND_PARAM]));
121 } else {
122 napi_value callback = CommonFunc::WrapVoidToJS(env);
123 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callbackPtr->callback, &callback));
124 napi_value undefined = CommonFunc::WrapVoidToJS(env);
125 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
126 napi_value callResult = CommonFunc::WrapVoidToJS(env);
127 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, CALLBACK_PARAM_SIZE,
128 &result[FIRST_PARAM], &callResult));
129 }
130 }
131
132 /**
133 * Promise and async callback
134 */
GetBundleInstaller(napi_env env,napi_callback_info info)135 napi_value GetBundleInstaller(napi_env env, napi_callback_info info)
136 {
137 APP_LOGD("GetBundleInstaller called");
138 NapiArg args(env, info);
139 if (!args.Init(FIRST_PARAM, SECOND_PARAM)) {
140 APP_LOGE("GetBundleInstaller args init failed");
141 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
142 return nullptr;
143 }
144 std::unique_ptr<AsyncGetBundleInstallerCallbackInfo> callbackPtr =
145 std::make_unique<AsyncGetBundleInstallerCallbackInfo>(env);
146
147 auto argc = args.GetMaxArgc();
148 APP_LOGD("GetBundleInstaller argc = [%{public}zu]", argc);
149 // check param
150 if (argc == SECOND_PARAM) {
151 napi_value arg = args.GetArgv(argc - SECOND_PARAM);
152 if (arg == nullptr) {
153 APP_LOGE("the param is nullptr");
154 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
155 return nullptr;
156 }
157 napi_valuetype valuetype = napi_undefined;
158 NAPI_CALL(env, napi_typeof(env, arg, &valuetype));
159 if (valuetype != napi_function) {
160 APP_LOGE("the param type is invalid");
161 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, CALLBACK, FUNCTION_TYPE);
162 return nullptr;
163 }
164 NAPI_CALL(env, napi_create_reference(env, arg, NAPI_RETURN_ONE, &callbackPtr->callback));
165 }
166
167 auto executeFunc = [](napi_env env, void *data) {};
168 napi_value promise = CommonFunc::AsyncCallNativeMethod(
169 env,
170 callbackPtr.get(),
171 RESOURCE_NAME_OF_GET_BUNDLE_INSTALLER,
172 executeFunc,
173 GetBundleInstallerCompleted);
174 callbackPtr.release();
175 return promise;
176 }
177
CreateErrCodeMap(std::unordered_map<int32_t,int32_t> & errCodeMap)178 static void CreateErrCodeMap(std::unordered_map<int32_t, int32_t> &errCodeMap)
179 {
180 errCodeMap = {
181 { IStatusReceiver::SUCCESS, SUCCESS},
182 { IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
183 { IStatusReceiver::ERR_INSTALL_HOST_INSTALLER_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
184 { IStatusReceiver::ERR_INSTALLD_PARAM_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
185 { IStatusReceiver::ERR_INSTALLD_GET_PROXY_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
186 { IStatusReceiver::ERR_INSTALL_INSTALLD_SERVICE_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
187 { IStatusReceiver::ERR_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
188 { IStatusReceiver::ERR_FAILED_SERVICE_DIED, ERROR_BUNDLE_SERVICE_EXCEPTION },
189 { IStatusReceiver::ERR_FAILED_GET_INSTALLER_PROXY, ERROR_BUNDLE_SERVICE_EXCEPTION },
190 { IStatusReceiver::ERR_USER_CREATE_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
191 { IStatusReceiver::ERR_USER_REMOVE_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
192 { IStatusReceiver::ERR_UNINSTALL_KILLING_APP_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
193 { IStatusReceiver::ERR_INSTALL_GENERATE_UID_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
194 { IStatusReceiver::ERR_INSTALL_STATE_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
195 { IStatusReceiver::ERR_RECOVER_NOT_ALLOWED, ERROR_BUNDLE_SERVICE_EXCEPTION },
196 { IStatusReceiver::ERR_RECOVER_GET_BUNDLEPATH_ERROR, ERROR_BUNDLE_SERVICE_EXCEPTION },
197 { IStatusReceiver::ERR_UNINSTALL_SYSTEM_APP_ERROR, ERROR_UNINSTALL_PREINSTALL_APP_FAILED },
198 { IStatusReceiver::ERR_INSTALL_PARSE_FAILED, ERROR_INSTALL_PARSE_FAILED },
199 { IStatusReceiver::ERR_INSTALL_PARSE_UNEXPECTED, ERROR_INSTALL_PARSE_FAILED },
200 { IStatusReceiver::ERR_INSTALL_PARSE_MISSING_BUNDLE, ERROR_INSTALL_PARSE_FAILED },
201 { IStatusReceiver::ERR_INSTALL_PARSE_NO_PROFILE, ERROR_INSTALL_PARSE_FAILED },
202 { IStatusReceiver::ERR_INSTALL_PARSE_BAD_PROFILE, ERROR_INSTALL_PARSE_FAILED },
203 { IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_PROP_TYPE_ERROR, ERROR_INSTALL_PARSE_FAILED },
204 { IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_MISSING_PROP, ERROR_INSTALL_PARSE_FAILED },
205 { IStatusReceiver::ERR_INSTALL_PARSE_PERMISSION_ERROR, ERROR_INSTALL_PARSE_FAILED },
206 { IStatusReceiver::ERR_INSTALL_PARSE_RPCID_FAILED, ERROR_INSTALL_PARSE_FAILED },
207 { IStatusReceiver::ERR_INSTALL_PARSE_NATIVE_SO_FAILED, ERROR_INSTALL_PARSE_FAILED },
208 { IStatusReceiver::ERR_INSTALL_PARSE_AN_FAILED, ERROR_INSTALL_PARSE_FAILED },
209 { IStatusReceiver::ERR_INSTALL_PARSE_MISSING_ABILITY, ERROR_INSTALL_PARSE_FAILED },
210 { IStatusReceiver::ERR_INSTALL_FAILED_PROFILE_PARSE_FAIL, ERROR_INSTALL_PARSE_FAILED },
211 { IStatusReceiver::ERR_INSTALL_VERIFICATION_FAILED, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
212 { IStatusReceiver::ERR_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
213 { IStatusReceiver::ERR_INSTALL_FAILED_INVALID_SIGNATURE_FILE_PATH, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
214 { IStatusReceiver::ERR_INSTALL_FAILED_BAD_BUNDLE_SIGNATURE_FILE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
215 { IStatusReceiver::ERR_INSTALL_FAILED_NO_BUNDLE_SIGNATURE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
216 { IStatusReceiver::ERR_INSTALL_FAILED_VERIFY_APP_PKCS7_FAIL, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
217 { IStatusReceiver::ERR_INSTALL_FAILED_APP_SOURCE_NOT_TRUESTED, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
218 { IStatusReceiver::ERR_INSTALL_FAILED_BAD_DIGEST, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
219 { IStatusReceiver::ERR_INSTALL_FAILED_BUNDLE_INTEGRITY_VERIFICATION_FAILURE,
220 ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
221 { IStatusReceiver::ERR_INSTALL_FAILED_BAD_PUBLICKEY, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
222 { IStatusReceiver::ERR_INSTALL_FAILED_BAD_BUNDLE_SIGNATURE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
223 { IStatusReceiver::ERR_INSTALL_FAILED_NO_PROFILE_BLOCK_FAIL, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
224 { IStatusReceiver::ERR_INSTALL_FAILED_BUNDLE_SIGNATURE_VERIFICATION_FAILURE,
225 ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
226 { IStatusReceiver::ERR_INSTALL_FAILED_VERIFY_SOURCE_INIT_FAIL, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
227 { IStatusReceiver::ERR_INSTALL_SINGLETON_INCOMPATIBLE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
228 { IStatusReceiver::ERR_INSTALL_FAILED_INCONSISTENT_SIGNATURE, ERROR_INSTALL_VERIFY_SIGNATURE_FAILED },
229 { IStatusReceiver::ERR_INSTALL_PARAM_ERROR, ERROR_BUNDLE_NOT_EXIST },
230 { IStatusReceiver::ERR_UNINSTALL_PARAM_ERROR, ERROR_BUNDLE_NOT_EXIST },
231 { IStatusReceiver::ERR_RECOVER_INVALID_BUNDLE_NAME, ERROR_BUNDLE_NOT_EXIST },
232 { IStatusReceiver::ERR_UNINSTALL_INVALID_NAME, ERROR_BUNDLE_NOT_EXIST },
233 { IStatusReceiver::ERR_INSTALL_INVALID_BUNDLE_FILE, ERROR_INSTALL_HAP_FILEPATH_INVALID },
234 { IStatusReceiver::ERR_INSTALL_FAILED_MODULE_NAME_EMPTY, ERROR_MODULE_NOT_EXIST },
235 { IStatusReceiver::ERR_INSTALL_FAILED_MODULE_NAME_DUPLICATE, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
236 { IStatusReceiver::ERR_INSTALL_FAILED_CHECK_HAP_HASH_PARAM, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
237 { IStatusReceiver::ERR_UNINSTALL_MISSING_INSTALLED_BUNDLE, ERROR_BUNDLE_NOT_EXIST },
238 { IStatusReceiver::ERR_UNINSTALL_MISSING_INSTALLED_MODULE, ERROR_MODULE_NOT_EXIST },
239 { IStatusReceiver::ERR_USER_NOT_INSTALL_HAP, ERROR_BUNDLE_NOT_EXIST },
240 { IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID, ERROR_INSTALL_HAP_FILEPATH_INVALID },
241 { IStatusReceiver::ERR_INSTALL_INVALID_HAP_SIZE, ERROR_INSTALL_HAP_SIZE_TOO_LARGE },
242 { IStatusReceiver::ERR_INSTALL_FAILED_FILE_SIZE_TOO_LARGE, ERROR_INSTALL_HAP_SIZE_TOO_LARGE },
243 { IStatusReceiver::ERR_INSTALL_INVALID_HAP_NAME, ERROR_INSTALL_INCORRECT_SUFFIX },
244 { IStatusReceiver::ERR_INSTALL_PERMISSION_DENIED, ERROR_PERMISSION_DENIED_ERROR },
245 { IStatusReceiver::ERR_UNINSTALL_PERMISSION_DENIED, ERROR_PERMISSION_DENIED_ERROR },
246 { IStatusReceiver::ERR_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED, ERROR_PERMISSION_DENIED_ERROR },
247 { IStatusReceiver::ERR_INSTALL_UPDATE_HAP_TOKEN_FAILED, ERROR_PERMISSION_DENIED_ERROR },
248 { IStatusReceiver::ERR_INSTALLD_CREATE_DIR_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
249 { IStatusReceiver::ERR_INSTALLD_CHOWN_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
250 { IStatusReceiver::ERR_INSTALLD_CREATE_DIR_EXIST, ERROR_BUNDLE_SERVICE_EXCEPTION },
251 { IStatusReceiver::ERR_INSTALLD_REMOVE_DIR_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
252 { IStatusReceiver::ERR_INSTALLD_EXTRACT_FILES_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
253 { IStatusReceiver::ERR_INSTALLD_RNAME_DIR_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
254 { IStatusReceiver::ERR_INSTALLD_CLEAN_DIR_FAILED, ERROR_BUNDLE_SERVICE_EXCEPTION },
255 { IStatusReceiver::ERR_INSTALL_ENTRY_ALREADY_EXIST, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
256 { IStatusReceiver::ERR_INSTALL_ALREADY_EXIST, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
257 { IStatusReceiver::ERR_INSTALL_BUNDLENAME_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
258 { IStatusReceiver::ERR_INSTALL_VERSIONCODE_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
259 { IStatusReceiver::ERR_INSTALL_VERSIONNAME_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
260 { IStatusReceiver::ERR_INSTALL_MINCOMPATIBLE_VERSIONCODE_NOT_SAME,
261 ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
262 { IStatusReceiver::ERR_INSTALL_VENDOR_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
263 { IStatusReceiver::ERR_INSTALL_RELEASETYPE_TARGET_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
264 { IStatusReceiver::ERR_INSTALL_RELEASETYPE_COMPATIBLE_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
265 { IStatusReceiver::ERR_INSTALL_SINGLETON_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
266 { IStatusReceiver::ERR_INSTALL_ZERO_USER_WITH_NO_SINGLETON, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
267 { IStatusReceiver::ERR_INSTALL_CHECK_SYSCAP_FAILED, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
268 { IStatusReceiver::ERR_INSTALL_APPTYPE_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
269 { IStatusReceiver::ERR_INSTALL_URI_DUPLICATE, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
270 { IStatusReceiver::ERR_INSTALL_VERSION_NOT_COMPATIBLE, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
271 { IStatusReceiver::ERR_INSTALL_APP_DISTRIBUTION_TYPE_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
272 { IStatusReceiver::ERR_INSTALL_APP_PROVISION_TYPE_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
273 { IStatusReceiver::ERR_INSTALL_SO_INCOMPATIBLE, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
274 { IStatusReceiver::ERR_INSTALL_AN_INCOMPATIBLE, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
275 { IStatusReceiver::ERR_INSTALL_TYPE_ERROR, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
276 { IStatusReceiver::ERR_INSTALL_TYPE_ERROR, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
277 { IStatusReceiver::ERR_INSTALL_NOT_UNIQUE_DISTRO_MODULE_NAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
278 { IStatusReceiver::ERR_INSTALL_INCONSISTENT_MODULE_NAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
279 { IStatusReceiver::ERR_INSTALL_INVALID_NUMBER_OF_ENTRY_HAP, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
280 { IStatusReceiver::ERR_INSTALL_ASAN_ENABLED_NOT_SAME, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT },
281 { IStatusReceiver::ERR_INSTALL_ASAN_ENABLED_NOT_SUPPORT, ERROR_INSTALL_MULTIPLE_HAP_INFO_INCONSISTENT},
282 { IStatusReceiver::ERR_INSTALL_BUNDLE_TYPE_NOT_SAME, ERROR_INSTALL_PARSE_FAILED},
283 { IStatusReceiver::ERR_INSTALL_DISK_MEM_INSUFFICIENT, ERROR_INSTALL_NO_DISK_SPACE_LEFT },
284 { IStatusReceiver::ERR_USER_NOT_EXIST, ERROR_INVALID_USER_ID },
285 { IStatusReceiver::ERR_INSTALL_VERSION_DOWNGRADE, ERROR_INSTALL_VERSION_DOWNGRADE },
286 { IStatusReceiver::ERR_INSTALL_DEVICE_TYPE_NOT_SUPPORTED, ERROR_INSTALL_PARSE_FAILED },
287 { IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_PROP_SIZE_CHECK_ERROR, ERROR_INSTALL_PARSE_FAILED },
288 { IStatusReceiver::ERR_INSTALL_DEPENDENT_MODULE_NOT_EXIST, ERROR_INSTALL_DEPENDENT_MODULE_NOT_EXIST },
289 };
290 }
291
ConvertInstallResult(InstallResult & installResult)292 static void ConvertInstallResult(InstallResult &installResult)
293 {
294 APP_LOGD("ConvertInstallResult msg %{public}s, errCode is %{public}d.", installResult.resultMsg.c_str(),
295 installResult.resultCode);
296 std::unordered_map<int32_t, int32_t> errCodeMap;
297 CreateErrCodeMap(errCodeMap);
298 auto iter = errCodeMap.find(installResult.resultCode);
299 if (iter != errCodeMap.end()) {
300 installResult.resultCode = iter->second;
301 return;
302 }
303 installResult.resultCode = ERROR_BUNDLE_SERVICE_EXCEPTION;
304 }
305
ParseHashParam(napi_env env,napi_value args,std::string & key,std::string & value)306 static bool ParseHashParam(napi_env env, napi_value args, std::string &key, std::string &value)
307 {
308 APP_LOGD("start to parse moduleName");
309 bool ret = CommonFunc::ParseStringPropertyFromObject(env, args, MODULE_NAME, true, key);
310 if (!ret || key.empty()) {
311 APP_LOGE("param string moduleName is empty.");
312 return false;
313 }
314 APP_LOGD("ParseHashParam moduleName=%{public}s.", key.c_str());
315
316 APP_LOGD("start to parse hashValue");
317 ret = CommonFunc::ParseStringPropertyFromObject(env, args, HASH_VALUE, true, value);
318 if (!ret || value.empty()) {
319 APP_LOGE("param string hashValue is empty.");
320 return false;
321 }
322 APP_LOGD("ParseHashParam hashValue=%{public}s.", value.c_str());
323 return true;
324 }
325
ParseHashParams(napi_env env,napi_value args,std::map<std::string,std::string> & hashParams)326 static bool ParseHashParams(napi_env env, napi_value args, std::map<std::string, std::string> &hashParams)
327 {
328 APP_LOGD("start to parse hashParams");
329 std::vector<napi_value> valueVec;
330 bool res = CommonFunc::ParsePropertyArray(env, args, HASH_PARAMS, valueVec);
331 if (!res) {
332 APP_LOGE("parse hashParams failed");
333 return res;
334 }
335 if (valueVec.empty()) {
336 APP_LOGE("value vec is empty");
337 return true;
338 }
339 for (const auto &property : valueVec) {
340 std::string key;
341 std::string value;
342 if (!ParseHashParam(env, property, key, value)) {
343 APP_LOGE("parse hash param failed");
344 return false;
345 }
346 if (hashParams.find(key) != hashParams.end()) {
347 APP_LOGE("moduleName(%{public}s) is duplicate", key.c_str());
348 return false;
349 }
350 hashParams.emplace(key, value);
351 }
352 return true;
353 }
354
ParseUserId(napi_env env,napi_value args,int32_t & userId)355 static bool ParseUserId(napi_env env, napi_value args, int32_t &userId)
356 {
357 APP_LOGD("start to parse userId");
358 PropertyInfo propertyInfo = {
359 .propertyName = USER_ID,
360 .isNecessary = false,
361 .propertyType = napi_number
362 };
363 napi_value property = nullptr;
364 bool res = CommonFunc::ParsePropertyFromObject(env, args, propertyInfo, property);
365 if (!res) {
366 APP_LOGE("parse userId failed");
367 return res;
368 }
369 if (property != nullptr) {
370 PARSE_PROPERTY(env, property, int32, userId);
371 }
372 APP_LOGD("param userId is %{public}d", userId);
373 return true;
374 }
375
ParseInstallFlag(napi_env env,napi_value args,InstallFlag & installFlag)376 static bool ParseInstallFlag(napi_env env, napi_value args, InstallFlag &installFlag)
377 {
378 APP_LOGD("start to parse installFlag");
379 PropertyInfo propertyInfo = {
380 .propertyName = INSTALL_FLAG,
381 .isNecessary = false,
382 .propertyType = napi_number
383 };
384 napi_value property = nullptr;
385 bool res = CommonFunc::ParsePropertyFromObject(env, args, propertyInfo, property);
386 if (!res) {
387 APP_LOGE("parse installFlag failed");
388 return res;
389 }
390
391 if (property != nullptr) {
392 int32_t flag = 0;
393 PARSE_PROPERTY(env, property, int32, flag);
394 APP_LOGD("param installFlag is %{public}d", flag);
395 if ((flag != static_cast<int32_t>(OHOS::AppExecFwk::InstallFlag::NORMAL)) &&
396 (flag != static_cast<int32_t>(OHOS::AppExecFwk::InstallFlag::REPLACE_EXISTING)) &&
397 (flag != static_cast<int32_t>(OHOS::AppExecFwk::InstallFlag::FREE_INSTALL))) {
398 APP_LOGE("invalid installFlag param");
399 return false;
400 }
401 installFlag = static_cast<OHOS::AppExecFwk::InstallFlag>(flag);
402 }
403 return true;
404 }
405
ParseIsKeepData(napi_env env,napi_value args,bool & isKeepData)406 static bool ParseIsKeepData(napi_env env, napi_value args, bool &isKeepData)
407 {
408 APP_LOGD("start to parse isKeepData");
409 PropertyInfo propertyInfo = {
410 .propertyName = IS_KEEP_DATA,
411 .isNecessary = false,
412 .propertyType = napi_boolean
413 };
414 napi_value property = nullptr;
415 bool res = CommonFunc::ParsePropertyFromObject(env, args, propertyInfo, property);
416 if (!res) {
417 APP_LOGE("parse isKeepData failed");
418 return res;
419 }
420 if (property != nullptr) {
421 PARSE_PROPERTY(env, property, bool, isKeepData);
422 }
423 APP_LOGD("param isKeepData is %{public}d", isKeepData);
424 return true;
425 }
426
ParseCrowdtestDeadline(napi_env env,napi_value args,int64_t & crowdtestDeadline)427 static bool ParseCrowdtestDeadline(napi_env env, napi_value args, int64_t &crowdtestDeadline)
428 {
429 APP_LOGD("start to parse crowdtestDeadline");
430 PropertyInfo propertyInfo = {
431 .propertyName = CROWD_TEST_DEADLINE,
432 .isNecessary = false,
433 .propertyType = napi_number
434 };
435 napi_value property = nullptr;
436 bool res = CommonFunc::ParsePropertyFromObject(env, args, propertyInfo, property);
437 if (!res) {
438 APP_LOGE("parse crowdtestDeadline failed");
439 return res;
440 }
441 if (property != nullptr) {
442 PARSE_PROPERTY(env, property, int64, crowdtestDeadline);
443 }
444 return true;
445 }
446
ParseInstallParam(napi_env env,napi_value args,InstallParam & installParam)447 static bool ParseInstallParam(napi_env env, napi_value args, InstallParam &installParam)
448 {
449 if (!ParseUserId(env, args, installParam.userId) || !ParseInstallFlag(env, args, installParam.installFlag) ||
450 !ParseIsKeepData(env, args, installParam.isKeepData) ||
451 !ParseCrowdtestDeadline(env, args, installParam.crowdtestDeadline) ||
452 !ParseHashParams(env, args, installParam.hashParams)) {
453 APP_LOGE("ParseInstallParam failed");
454 return false;
455 }
456 return true;
457 }
458
CreateProxyErrCode(std::unordered_map<int32_t,int32_t> & errCodeMap)459 static void CreateProxyErrCode(std::unordered_map<int32_t, int32_t> &errCodeMap)
460 {
461 errCodeMap = {
462 { ERR_APPEXECFWK_INSTALL_PARAM_ERROR, IStatusReceiver::ERR_INSTALL_PARAM_ERROR },
463 { ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR },
464 { ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID, IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID },
465 { ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT, IStatusReceiver::ERR_INSTALL_DISK_MEM_INSUFFICIENT }
466 };
467 }
468
InstallExecuter(napi_env env,void * data)469 void InstallExecuter(napi_env env, void *data)
470 {
471 AsyncInstallCallbackInfo *asyncCallbackInfo = reinterpret_cast<AsyncInstallCallbackInfo *>(data);
472 if (asyncCallbackInfo == nullptr) {
473 APP_LOGE("asyncCallbackInfo is nullptr");
474 return;
475 }
476 const std::vector<std::string> bundleFilePath = asyncCallbackInfo->hapFiles;
477 InstallResult &installResult = asyncCallbackInfo->installResult;
478 if (bundleFilePath.empty()) {
479 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID);
480 return;
481 }
482 auto iBundleInstaller = CommonFunc::GetBundleInstaller();
483 if ((iBundleInstaller == nullptr) || (iBundleInstaller->AsObject() == nullptr)) {
484 APP_LOGE("can not get iBundleInstaller");
485 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR);
486 return;
487 }
488
489 sptr<InstallerCallback> callback = new (std::nothrow) InstallerCallback();
490 sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(callback));
491 if (callback == nullptr || recipient == nullptr) {
492 APP_LOGE("callback or death recipient is nullptr");
493 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR);
494 return;
495 }
496 iBundleInstaller->AsObject()->AddDeathRecipient(recipient);
497
498 if (asyncCallbackInfo->installParam.installFlag == InstallFlag::NORMAL) {
499 asyncCallbackInfo->installParam.installFlag = InstallFlag::REPLACE_EXISTING;
500 }
501 ErrCode res = iBundleInstaller->StreamInstall(bundleFilePath, asyncCallbackInfo->installParam, callback);
502 if (res == ERR_OK) {
503 installResult.resultCode = callback->GetResultCode();
504 APP_LOGD("InnerInstall resultCode %{public}d", installResult.resultCode);
505 installResult.resultMsg = callback->GetResultMsg();
506 APP_LOGD("InnerInstall resultMsg %{public}s", installResult.resultMsg.c_str());
507 return;
508 }
509 APP_LOGE("install failed due to %{public}d", res);
510 std::unordered_map<int32_t, int32_t> proxyErrCodeMap;
511 CreateProxyErrCode(proxyErrCodeMap);
512 if (proxyErrCodeMap.find(res) != proxyErrCodeMap.end()) {
513 installResult.resultCode = proxyErrCodeMap.at(res);
514 } else {
515 installResult.resultCode = IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR;
516 }
517 }
518
GetFunctionName(const InstallOption & option)519 static std::string GetFunctionName(const InstallOption &option)
520 {
521 if (option == InstallOption::INSTALL) {
522 return RESOURCE_NAME_OF_INSTALL;
523 } else if (option == InstallOption::RECOVER) {
524 return RESOURCE_NAME_OF_RECOVER;
525 } else if (option == InstallOption::UNINSTALL) {
526 return RESOURCE_NAME_OF_UNINSTALL;
527 }
528 return EMPTY_STRING;
529 }
530
OperationCompleted(napi_env env,napi_status status,void * data)531 void OperationCompleted(napi_env env, napi_status status, void *data)
532 {
533 AsyncInstallCallbackInfo *asyncCallbackInfo = reinterpret_cast<AsyncInstallCallbackInfo *>(data);
534 std::unique_ptr<AsyncInstallCallbackInfo> callbackPtr {asyncCallbackInfo};
535 napi_value result[CALLBACK_PARAM_SIZE] = {0};
536 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[SECOND_PARAM]));
537 ConvertInstallResult(callbackPtr->installResult);
538 if (callbackPtr->installResult.resultCode != SUCCESS) {
539 result[FIRST_PARAM] = BusinessError::CreateCommonError(env, callbackPtr->installResult.resultCode,
540 GetFunctionName(callbackPtr->option), INSTALL_PERMISSION);
541 }
542
543 if (callbackPtr->deferred) {
544 if (callbackPtr->installResult.resultCode == SUCCESS) {
545 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, callbackPtr->deferred, result[SECOND_PARAM]));
546 } else {
547 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, callbackPtr->deferred, result[FIRST_PARAM]));
548 }
549 } else {
550 napi_value callback = CommonFunc::WrapVoidToJS(env);
551 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callbackPtr->callback, &callback));
552
553 napi_value undefined = CommonFunc::WrapVoidToJS(env);
554 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
555
556 napi_value callResult = CommonFunc::WrapVoidToJS(env);
557 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, CALLBACK_PARAM_SIZE,
558 &result[FIRST_PARAM], &callResult));
559 }
560 }
561
562 /**
563 * Promise and async callback
564 */
Install(napi_env env,napi_callback_info info)565 napi_value Install(napi_env env, napi_callback_info info)
566 {
567 APP_LOGD("Install called");
568 // obtain arguments of install interface
569 NapiArg args(env, info);
570 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_THREE)) {
571 APP_LOGE("init param failed");
572 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
573 return nullptr;
574 }
575
576 auto argc = args.GetMaxArgc();
577 APP_LOGD("the number of argc is %{public}zu", argc);
578 if (argc < ARGS_SIZE_ONE) {
579 APP_LOGE("the params number is incorrect");
580 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
581 return nullptr;
582 }
583
584 std::unique_ptr<AsyncInstallCallbackInfo> callbackPtr = std::make_unique<AsyncInstallCallbackInfo>(env);
585 callbackPtr->option = InstallOption::INSTALL;
586 for (size_t i = 0; i < argc; ++i) {
587 napi_valuetype valueType = napi_undefined;
588 napi_typeof(env, args[i], &valueType);
589 if (i == ARGS_POS_ZERO) {
590 if (!CommonFunc::ParseStringArray(env, callbackPtr->hapFiles, args[i])) {
591 APP_LOGE("Flags %{public}s invalid!", callbackPtr->bundleName.c_str());
592 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
593 return nullptr;
594 }
595 } else if (i == ARGS_POS_ONE) {
596 if (valueType == napi_function) {
597 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &callbackPtr->callback));
598 break;
599 }
600
601 if (!ParseInstallParam(env, args[i], callbackPtr->installParam)) {
602 APP_LOGE("userId %{public}d invalid!", callbackPtr->installParam.userId);
603 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
604 return nullptr;
605 }
606 } else if ((i == ARGS_POS_TWO) && (valueType == napi_function)) {
607 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &callbackPtr->callback));
608 break;
609 } else {
610 APP_LOGE("param check error");
611 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
612 return nullptr;
613 }
614 }
615
616 auto promise = CommonFunc::AsyncCallNativeMethod(env, callbackPtr.get(), RESOURCE_NAME_OF_INSTALL, InstallExecuter,
617 OperationCompleted);
618 callbackPtr.release();
619 return promise;
620 }
621
UninstallOrRecoverExecuter(napi_env env,void * data)622 void UninstallOrRecoverExecuter(napi_env env, void *data)
623 {
624 AsyncInstallCallbackInfo *asyncCallbackInfo = reinterpret_cast<AsyncInstallCallbackInfo *>(data);
625 if (asyncCallbackInfo == nullptr) {
626 APP_LOGE("asyncCallbackInfo is nullptr");
627 return;
628 }
629 const std::string bundleName = asyncCallbackInfo->bundleName;
630 InstallResult &installResult = asyncCallbackInfo->installResult;
631 if (bundleName.empty()) {
632 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_RECOVER_INVALID_BUNDLE_NAME);
633 return;
634 }
635 auto iBundleInstaller = CommonFunc::GetBundleInstaller();
636 if ((iBundleInstaller == nullptr) || (iBundleInstaller->AsObject() == nullptr)) {
637 APP_LOGE("can not get iBundleInstaller");
638 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR);
639 return;
640 }
641
642 sptr<InstallerCallback> callback = new (std::nothrow) InstallerCallback();
643 sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(callback));
644 if (callback == nullptr || recipient == nullptr) {
645 APP_LOGE("callback or death recipient is nullptr");
646 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR);
647 return;
648 }
649 iBundleInstaller->AsObject()->AddDeathRecipient(recipient);
650 if (asyncCallbackInfo->option == InstallOption::RECOVER) {
651 iBundleInstaller->Recover(bundleName, asyncCallbackInfo->installParam, callback);
652 } else if (asyncCallbackInfo->option == InstallOption::UNINSTALL) {
653 iBundleInstaller->Uninstall(bundleName, asyncCallbackInfo->installParam, callback);
654 } else {
655 APP_LOGE("error install option");
656 installResult.resultCode = static_cast<int32_t>(IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR);
657 return;
658 }
659 installResult.resultMsg = callback->GetResultMsg();
660 APP_LOGD("InnerRecover resultMsg %{public}s.", installResult.resultMsg.c_str());
661 installResult.resultCode = callback->GetResultCode();
662 APP_LOGD("InnerRecover resultCode %{public}d.", installResult.resultCode);
663 }
664
UninstallOrRecover(napi_env env,napi_callback_info info,std::unique_ptr<AsyncInstallCallbackInfo> & callbackPtr)665 napi_value UninstallOrRecover(napi_env env, napi_callback_info info,
666 std::unique_ptr<AsyncInstallCallbackInfo> &callbackPtr)
667 {
668 APP_LOGD("UninstallOrRecover by bundleName called");
669 // obtain arguments of install interface
670 NapiArg args(env, info);
671 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_THREE)) {
672 APP_LOGE("init param failed");
673 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
674 return nullptr;
675 }
676
677 auto argc = args.GetMaxArgc();
678 APP_LOGD("the number of argc is %{public}zu", argc);
679 if (argc < ARGS_SIZE_ONE) {
680 APP_LOGE("the params number is incorrect");
681 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
682 return nullptr;
683 }
684
685 for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
686 napi_valuetype valueType = napi_undefined;
687 napi_typeof(env, args[i], &valueType);
688 if (i == ARGS_POS_ZERO) {
689 if (!CommonFunc::ParseString(env, args[i], callbackPtr->bundleName)) {
690 APP_LOGE("Flags %{public}s invalid!", callbackPtr->bundleName.c_str());
691 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
692 return nullptr;
693 }
694 } else if (i == ARGS_POS_ONE) {
695 if (valueType == napi_function) {
696 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &callbackPtr->callback));
697 break;
698 }
699
700 if (!ParseInstallParam(env, args[i], callbackPtr->installParam)) {
701 APP_LOGE("userId %{public}d invalid!", callbackPtr->installParam.userId);
702 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
703 return nullptr;
704 }
705 } else if ((i == ARGS_POS_TWO) && (valueType == napi_function)) {
706 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &callbackPtr->callback));
707 break;
708 } else {
709 APP_LOGE("param check error");
710 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETERS, CORRESPONDING_TYPE);
711 return nullptr;
712 }
713 }
714
715 auto promise = CommonFunc::AsyncCallNativeMethod(env, callbackPtr.get(), GetFunctionName(callbackPtr->option),
716 UninstallOrRecoverExecuter, OperationCompleted);
717 callbackPtr.release();
718 return promise;
719 }
720
Recover(napi_env env,napi_callback_info info)721 napi_value Recover(napi_env env, napi_callback_info info)
722 {
723 APP_LOGD("Recover called");
724 std::unique_ptr<AsyncInstallCallbackInfo> callbackPtr = std::make_unique<AsyncInstallCallbackInfo>(env);
725 callbackPtr->option = InstallOption::RECOVER;
726 return UninstallOrRecover(env, info, callbackPtr);
727 }
728
Uninstall(napi_env env,napi_callback_info info)729 napi_value Uninstall(napi_env env, napi_callback_info info)
730 {
731 APP_LOGD("Uninstall called");
732 std::unique_ptr<AsyncInstallCallbackInfo> callbackPtr = std::make_unique<AsyncInstallCallbackInfo>(env);
733 callbackPtr->option = InstallOption::UNINSTALL;
734 return UninstallOrRecover(env, info, callbackPtr);
735 }
736
BundleInstallerConstructor(napi_env env,napi_callback_info info)737 napi_value BundleInstallerConstructor(napi_env env, napi_callback_info info)
738 {
739 napi_value jsthis = nullptr;
740 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr));
741 return jsthis;
742 }
743 } // AppExecFwk
744 } // OHOS