1/* 2 * Copyright (c) 2022-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#include "package.h" 16#include <string> 17 18#include "app_log_wrapper.h" 19#include "bundle_constants.h" 20#include "bundle_mgr_host.h" 21#include "bundle_mgr_interface.h" 22#include "if_system_ability_manager.h" 23#include "ipc_skeleton.h" 24#include "iservice_registry.h" 25#include "napi/native_api.h" 26#include "napi/native_node_api.h" 27 28#include "securec.h" 29#include "system_ability_definition.h" 30 31namespace OHOS { 32namespace AppExecFwk { 33using namespace OHOS; 34using namespace OHOS::AAFwk; 35using namespace OHOS::AppExecFwk; 36namespace { 37constexpr int32_t NAPI_RETURN_ZERO = 0; 38constexpr size_t ARGS_SIZE_ONE = 1; 39constexpr size_t ARGS_SIZE_TWO = 2; 40constexpr int32_t PARAM0 = 0; 41constexpr int32_t PARAM1 = 1; 42constexpr int32_t NAPI_RETURN_ONE = 1; 43constexpr int32_t INVALID_PARAM = 2; 44constexpr int32_t INVALID_NUMBER = 202; 45constexpr const char* BUNDLE_NAME = "bundleName"; 46constexpr const char* COMPLETE = "complete"; 47constexpr const char* FAIL = "fail"; 48constexpr const char* SUCCESS = "success"; 49} 50 51CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions() 52{ 53 if (successRef) { 54 APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete successRef"); 55 napi_delete_reference(env, successRef); 56 successRef = nullptr; 57 } 58 if (failRef) { 59 APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete failRef"); 60 napi_delete_reference(env, failRef); 61 failRef = nullptr; 62 } 63 if (completeRef) { 64 APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete completeRef"); 65 napi_delete_reference(env, completeRef); 66 completeRef = nullptr; 67 } 68 if (asyncWork) { 69 APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete callbackRef"); 70 napi_delete_async_work(env, asyncWork); 71 asyncWork = nullptr; 72 } 73} 74 75static OHOS::sptr<OHOS::AppExecFwk::IBundleMgr> GetBundleMgr() 76{ 77 auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 78 if (systemAbilityManager == nullptr) { 79 APP_LOGE("GetBundleMgr GetSystemAbilityManager is null"); 80 return nullptr; 81 } 82 auto bundleMgrSa = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 83 if (bundleMgrSa == nullptr) { 84 APP_LOGE("GetBundleMgr GetSystemAbility is null"); 85 return nullptr; 86 } 87 auto bundleMgr = OHOS::iface_cast<IBundleMgr>(bundleMgrSa); 88 if (bundleMgr == nullptr) { 89 APP_LOGE("GetBundleMgr iface_cast get null"); 90 } 91 return bundleMgr; 92} 93 94static std::string GetStringFromNAPI(napi_env env, napi_value value) 95{ 96 std::string result; 97 size_t size = 0; 98 99 if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) { 100 APP_LOGE("can not get string size"); 101 return ""; 102 } 103 result.reserve(size + NAPI_RETURN_ONE); 104 result.resize(size); 105 if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) { 106 APP_LOGE("can not get string value"); 107 return ""; 108 } 109 return result; 110} 111 112static void ParseCheckPackageHasInstalledOptions(napi_env env, napi_value param, 113 OHOS::AppExecFwk::CheckPackageHasInstalledOptions *hasInstalledOptions) 114{ 115 if (hasInstalledOptions == nullptr) { 116 APP_LOGW("hasInstalledOptions is nullptr"); 117 return; 118 } 119 napi_valuetype valueType; 120 napi_value prop = nullptr; 121 // parse bundleName 122 napi_get_named_property(env, param, BUNDLE_NAME, &prop); 123 napi_typeof(env, prop, &valueType); 124 hasInstalledOptions->isString = false; 125 if (valueType == napi_string) { 126 hasInstalledOptions->bundleName = GetStringFromNAPI(env, prop); 127 hasInstalledOptions->isString = true; 128 } 129 // parse success function 130 napi_value jsFunc = nullptr; 131 napi_ref jsFuncRef = nullptr; 132 napi_get_named_property(env, param, SUCCESS, &jsFunc); 133 napi_typeof(env, jsFunc, &valueType); 134 if (valueType == napi_function) { 135 napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef); 136 hasInstalledOptions->successRef = jsFuncRef; 137 } 138 // parse fail function 139 napi_get_named_property(env, param, FAIL, &jsFunc); 140 napi_typeof(env, jsFunc, &valueType); 141 if (valueType == napi_function) { 142 napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef); 143 hasInstalledOptions->failRef = jsFuncRef; 144 } 145 // parse complete function 146 napi_get_named_property(env, param, COMPLETE, &jsFunc); 147 napi_typeof(env, jsFunc, &valueType); 148 if (valueType == napi_function) { 149 napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef); 150 hasInstalledOptions->completeRef = jsFuncRef; 151 } 152} 153 154static bool InnerHasInstalled(std::string bundleName) 155{ 156 if (bundleName.empty()) { 157 APP_LOGE("bundleName is invalid param"); 158 return false; 159 } 160 auto iBundleMgr = GetBundleMgr(); 161 if (iBundleMgr == nullptr) { 162 APP_LOGE("can not get iBundleMgr"); 163 return false; 164 } 165 BundleInfo bundleInfo; 166 bool ret = iBundleMgr->GetBundleInfo(bundleName, 0, bundleInfo); 167 if (!ret) { 168 APP_LOGE("bundleInfo is not find, bundleName=%{public}s", bundleName.c_str()); 169 } 170 return ret; 171} 172 173static void ConvertCheckPackageHasInstalledResponse(napi_env env, napi_value hasInstalledResponseObj, 174 const OHOS::AppExecFwk::CheckPackageHasInstalledResponse &response) 175{ 176 APP_LOGD("convert CheckPackageHasInstalledResponse start"); 177 napi_value nResult; 178 NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, response.result, &nResult)); 179 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, hasInstalledResponseObj, "result", nResult)); 180} 181 182static void HasInstalledExecute(napi_env env, void *data) 183{ 184 APP_LOGD("NAPI_HasInstalled, worker pool thread execute"); 185 CheckPackageHasInstalledOptions *asyncCallbackInfo = static_cast<CheckPackageHasInstalledOptions *>(data); 186 if (asyncCallbackInfo == nullptr) { 187 APP_LOGW("NAPI_HasInstalled, asyncCallbackInfo == nullptr"); 188 return; 189 } 190 if (!asyncCallbackInfo->errCode && asyncCallbackInfo->isString && asyncCallbackInfo->successRef) { 191 asyncCallbackInfo->response.result = InnerHasInstalled(asyncCallbackInfo->bundleName); 192 } 193 APP_LOGD("NAPI_HasInstalled, worker pool thread execute end"); 194} 195 196static void HasInstalledAsyncComplete(napi_env env, napi_status status, void *data) 197{ 198 APP_LOGD("NAPI_HasInstalled, main event thread complete"); 199 CheckPackageHasInstalledOptions *asyncCallbackInfo = static_cast<CheckPackageHasInstalledOptions *>(data); 200 std::unique_ptr<CheckPackageHasInstalledOptions> callbackPtr {asyncCallbackInfo}; 201 if (asyncCallbackInfo == nullptr) { 202 APP_LOGW("NAPI_HasInstalled, asyncCallbackInfo == nullptr"); 203 return; 204 } 205 napi_value callback = nullptr; 206 napi_value placeHolder = nullptr; 207 if (!asyncCallbackInfo->isString) { 208 if (asyncCallbackInfo->failRef) { 209 napi_value result[ARGS_SIZE_TWO] = { 0 }; 210 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "value is not an available number", 211 NAPI_AUTO_LENGTH, &result[PARAM0])); 212 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, INVALID_NUMBER, &result[PARAM1])); 213 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->failRef, &callback)); 214 napi_call_function(env, nullptr, callback, ARGS_SIZE_TWO, result, &placeHolder); 215 } 216 } else { 217 if (asyncCallbackInfo->successRef) { 218 napi_value result[ARGS_SIZE_ONE] = { 0 }; 219 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[PARAM0])); 220 ConvertCheckPackageHasInstalledResponse(env, result[PARAM0], asyncCallbackInfo->response); 221 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->successRef, &callback)); 222 napi_call_function(env, nullptr, callback, ARGS_SIZE_ONE, result, &placeHolder); 223 } 224 } 225 if (asyncCallbackInfo->completeRef) { 226 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->completeRef, &callback)); 227 napi_call_function(env, nullptr, callback, 0, nullptr, &placeHolder); 228 } 229 APP_LOGD("NAPI_HasInstalled, main event thread complete end"); 230} 231 232napi_value HasInstalled(napi_env env, napi_callback_info info) 233{ 234 APP_LOGD("asyncCallback"); 235 size_t requireArgc = ARGS_SIZE_ONE; 236 size_t argc = ARGS_SIZE_TWO; 237 napi_value argv[ARGS_SIZE_TWO] = { 0 }; 238 napi_value thisArg = nullptr; 239 void *data = nullptr; 240 241 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data)); 242 if (argc != requireArgc) { 243 APP_LOGW("requires 1 parameter"); 244 return nullptr; 245 } 246 247 CheckPackageHasInstalledOptions *asyncCallbackInfo = new (std::nothrow) CheckPackageHasInstalledOptions(); 248 if (asyncCallbackInfo == nullptr) { 249 return nullptr; 250 } 251 std::unique_ptr<CheckPackageHasInstalledOptions> callbackPtr {asyncCallbackInfo}; 252 asyncCallbackInfo->env = env; 253 napi_valuetype valueType = napi_undefined; 254 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType)); 255 if (valueType == napi_object) { 256 ParseCheckPackageHasInstalledOptions(env, argv[PARAM0], asyncCallbackInfo); 257 } else { 258 asyncCallbackInfo->errCode = INVALID_PARAM; 259 } 260 261 napi_value resource = nullptr; 262 NAPI_CALL(env, napi_create_string_utf8(env, "JSHasInstalled", NAPI_AUTO_LENGTH, &resource)); 263 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, HasInstalledExecute, 264 HasInstalledAsyncComplete, (void *)asyncCallbackInfo, &asyncCallbackInfo->asyncWork)); 265 NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); 266 callbackPtr.release(); 267 return nullptr; 268} 269} // namespace AppExecFwk 270} // namespace OHOS 271