1600cc4afSopenharmony_ci/*
2600cc4afSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3600cc4afSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4600cc4afSopenharmony_ci * you may not use this file except in compliance with the License.
5600cc4afSopenharmony_ci * You may obtain a copy of the License at
6600cc4afSopenharmony_ci *
7600cc4afSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8600cc4afSopenharmony_ci *
9600cc4afSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10600cc4afSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11600cc4afSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12600cc4afSopenharmony_ci * See the License for the specific language governing permissions and
13600cc4afSopenharmony_ci * limitations under the License.
14600cc4afSopenharmony_ci */
15600cc4afSopenharmony_ci#include "package.h"
16600cc4afSopenharmony_ci#include <string>
17600cc4afSopenharmony_ci
18600cc4afSopenharmony_ci#include "app_log_wrapper.h"
19600cc4afSopenharmony_ci#include "bundle_constants.h"
20600cc4afSopenharmony_ci#include "bundle_mgr_host.h"
21600cc4afSopenharmony_ci#include "bundle_mgr_interface.h"
22600cc4afSopenharmony_ci#include "if_system_ability_manager.h"
23600cc4afSopenharmony_ci#include "ipc_skeleton.h"
24600cc4afSopenharmony_ci#include "iservice_registry.h"
25600cc4afSopenharmony_ci#include "napi/native_api.h"
26600cc4afSopenharmony_ci#include "napi/native_node_api.h"
27600cc4afSopenharmony_ci
28600cc4afSopenharmony_ci#include "securec.h"
29600cc4afSopenharmony_ci#include "system_ability_definition.h"
30600cc4afSopenharmony_ci
31600cc4afSopenharmony_cinamespace OHOS {
32600cc4afSopenharmony_cinamespace AppExecFwk {
33600cc4afSopenharmony_ciusing namespace OHOS;
34600cc4afSopenharmony_ciusing namespace OHOS::AAFwk;
35600cc4afSopenharmony_ciusing namespace OHOS::AppExecFwk;
36600cc4afSopenharmony_cinamespace {
37600cc4afSopenharmony_ciconstexpr int32_t NAPI_RETURN_ZERO = 0;
38600cc4afSopenharmony_ciconstexpr size_t ARGS_SIZE_ONE = 1;
39600cc4afSopenharmony_ciconstexpr size_t ARGS_SIZE_TWO = 2;
40600cc4afSopenharmony_ciconstexpr int32_t PARAM0 = 0;
41600cc4afSopenharmony_ciconstexpr int32_t PARAM1 = 1;
42600cc4afSopenharmony_ciconstexpr int32_t NAPI_RETURN_ONE = 1;
43600cc4afSopenharmony_ciconstexpr int32_t INVALID_PARAM = 2;
44600cc4afSopenharmony_ciconstexpr int32_t INVALID_NUMBER = 202;
45600cc4afSopenharmony_ciconstexpr const char* BUNDLE_NAME = "bundleName";
46600cc4afSopenharmony_ciconstexpr const char* COMPLETE = "complete";
47600cc4afSopenharmony_ciconstexpr const char* FAIL = "fail";
48600cc4afSopenharmony_ciconstexpr const char* SUCCESS = "success";
49600cc4afSopenharmony_ci}
50600cc4afSopenharmony_ci
51600cc4afSopenharmony_ciCheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions()
52600cc4afSopenharmony_ci{
53600cc4afSopenharmony_ci    if (successRef) {
54600cc4afSopenharmony_ci        APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete successRef");
55600cc4afSopenharmony_ci        napi_delete_reference(env, successRef);
56600cc4afSopenharmony_ci        successRef = nullptr;
57600cc4afSopenharmony_ci    }
58600cc4afSopenharmony_ci    if (failRef) {
59600cc4afSopenharmony_ci        APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete failRef");
60600cc4afSopenharmony_ci        napi_delete_reference(env, failRef);
61600cc4afSopenharmony_ci        failRef = nullptr;
62600cc4afSopenharmony_ci    }
63600cc4afSopenharmony_ci    if (completeRef) {
64600cc4afSopenharmony_ci        APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete completeRef");
65600cc4afSopenharmony_ci        napi_delete_reference(env, completeRef);
66600cc4afSopenharmony_ci        completeRef = nullptr;
67600cc4afSopenharmony_ci    }
68600cc4afSopenharmony_ci    if (asyncWork) {
69600cc4afSopenharmony_ci        APP_LOGD("CheckPackageHasInstalledOptions::~CheckPackageHasInstalledOptions delete callbackRef");
70600cc4afSopenharmony_ci        napi_delete_async_work(env, asyncWork);
71600cc4afSopenharmony_ci        asyncWork = nullptr;
72600cc4afSopenharmony_ci    }
73600cc4afSopenharmony_ci}
74600cc4afSopenharmony_ci
75600cc4afSopenharmony_cistatic OHOS::sptr<OHOS::AppExecFwk::IBundleMgr> GetBundleMgr()
76600cc4afSopenharmony_ci{
77600cc4afSopenharmony_ci    auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
78600cc4afSopenharmony_ci    if (systemAbilityManager == nullptr) {
79600cc4afSopenharmony_ci        APP_LOGE("GetBundleMgr GetSystemAbilityManager is null");
80600cc4afSopenharmony_ci        return nullptr;
81600cc4afSopenharmony_ci    }
82600cc4afSopenharmony_ci    auto bundleMgrSa = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
83600cc4afSopenharmony_ci    if (bundleMgrSa == nullptr) {
84600cc4afSopenharmony_ci        APP_LOGE("GetBundleMgr GetSystemAbility is null");
85600cc4afSopenharmony_ci        return nullptr;
86600cc4afSopenharmony_ci    }
87600cc4afSopenharmony_ci    auto bundleMgr = OHOS::iface_cast<IBundleMgr>(bundleMgrSa);
88600cc4afSopenharmony_ci    if (bundleMgr == nullptr) {
89600cc4afSopenharmony_ci        APP_LOGE("GetBundleMgr iface_cast get null");
90600cc4afSopenharmony_ci    }
91600cc4afSopenharmony_ci    return bundleMgr;
92600cc4afSopenharmony_ci}
93600cc4afSopenharmony_ci
94600cc4afSopenharmony_cistatic std::string GetStringFromNAPI(napi_env env, napi_value value)
95600cc4afSopenharmony_ci{
96600cc4afSopenharmony_ci    std::string result;
97600cc4afSopenharmony_ci    size_t size = 0;
98600cc4afSopenharmony_ci
99600cc4afSopenharmony_ci    if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) {
100600cc4afSopenharmony_ci        APP_LOGE("can not get string size");
101600cc4afSopenharmony_ci        return "";
102600cc4afSopenharmony_ci    }
103600cc4afSopenharmony_ci    result.reserve(size + NAPI_RETURN_ONE);
104600cc4afSopenharmony_ci    result.resize(size);
105600cc4afSopenharmony_ci    if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) {
106600cc4afSopenharmony_ci        APP_LOGE("can not get string value");
107600cc4afSopenharmony_ci        return "";
108600cc4afSopenharmony_ci    }
109600cc4afSopenharmony_ci    return result;
110600cc4afSopenharmony_ci}
111600cc4afSopenharmony_ci
112600cc4afSopenharmony_cistatic void ParseCheckPackageHasInstalledOptions(napi_env env, napi_value param,
113600cc4afSopenharmony_ci    OHOS::AppExecFwk::CheckPackageHasInstalledOptions *hasInstalledOptions)
114600cc4afSopenharmony_ci{
115600cc4afSopenharmony_ci    if (hasInstalledOptions == nullptr) {
116600cc4afSopenharmony_ci        APP_LOGW("hasInstalledOptions is nullptr");
117600cc4afSopenharmony_ci        return;
118600cc4afSopenharmony_ci    }
119600cc4afSopenharmony_ci    napi_valuetype valueType;
120600cc4afSopenharmony_ci    napi_value prop = nullptr;
121600cc4afSopenharmony_ci    // parse bundleName
122600cc4afSopenharmony_ci    napi_get_named_property(env, param, BUNDLE_NAME, &prop);
123600cc4afSopenharmony_ci    napi_typeof(env, prop, &valueType);
124600cc4afSopenharmony_ci    hasInstalledOptions->isString = false;
125600cc4afSopenharmony_ci    if (valueType == napi_string) {
126600cc4afSopenharmony_ci        hasInstalledOptions->bundleName = GetStringFromNAPI(env, prop);
127600cc4afSopenharmony_ci        hasInstalledOptions->isString = true;
128600cc4afSopenharmony_ci    }
129600cc4afSopenharmony_ci    // parse success function
130600cc4afSopenharmony_ci    napi_value jsFunc = nullptr;
131600cc4afSopenharmony_ci    napi_ref jsFuncRef = nullptr;
132600cc4afSopenharmony_ci    napi_get_named_property(env, param, SUCCESS, &jsFunc);
133600cc4afSopenharmony_ci    napi_typeof(env, jsFunc, &valueType);
134600cc4afSopenharmony_ci    if (valueType == napi_function) {
135600cc4afSopenharmony_ci        napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef);
136600cc4afSopenharmony_ci        hasInstalledOptions->successRef = jsFuncRef;
137600cc4afSopenharmony_ci    }
138600cc4afSopenharmony_ci    // parse fail function
139600cc4afSopenharmony_ci    napi_get_named_property(env, param, FAIL, &jsFunc);
140600cc4afSopenharmony_ci    napi_typeof(env, jsFunc, &valueType);
141600cc4afSopenharmony_ci    if (valueType == napi_function) {
142600cc4afSopenharmony_ci        napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef);
143600cc4afSopenharmony_ci        hasInstalledOptions->failRef = jsFuncRef;
144600cc4afSopenharmony_ci    }
145600cc4afSopenharmony_ci    // parse complete function
146600cc4afSopenharmony_ci    napi_get_named_property(env, param, COMPLETE, &jsFunc);
147600cc4afSopenharmony_ci    napi_typeof(env, jsFunc, &valueType);
148600cc4afSopenharmony_ci    if (valueType == napi_function) {
149600cc4afSopenharmony_ci        napi_create_reference(env, jsFunc, NAPI_RETURN_ONE, &jsFuncRef);
150600cc4afSopenharmony_ci        hasInstalledOptions->completeRef = jsFuncRef;
151600cc4afSopenharmony_ci    }
152600cc4afSopenharmony_ci}
153600cc4afSopenharmony_ci
154600cc4afSopenharmony_cistatic bool InnerHasInstalled(std::string bundleName)
155600cc4afSopenharmony_ci{
156600cc4afSopenharmony_ci    if (bundleName.empty()) {
157600cc4afSopenharmony_ci        APP_LOGE("bundleName is invalid param");
158600cc4afSopenharmony_ci        return false;
159600cc4afSopenharmony_ci    }
160600cc4afSopenharmony_ci    auto iBundleMgr = GetBundleMgr();
161600cc4afSopenharmony_ci    if (iBundleMgr == nullptr) {
162600cc4afSopenharmony_ci        APP_LOGE("can not get iBundleMgr");
163600cc4afSopenharmony_ci        return false;
164600cc4afSopenharmony_ci    }
165600cc4afSopenharmony_ci    BundleInfo bundleInfo;
166600cc4afSopenharmony_ci    bool ret = iBundleMgr->GetBundleInfo(bundleName, 0, bundleInfo);
167600cc4afSopenharmony_ci    if (!ret) {
168600cc4afSopenharmony_ci        APP_LOGE("bundleInfo is not find, bundleName=%{public}s", bundleName.c_str());
169600cc4afSopenharmony_ci    }
170600cc4afSopenharmony_ci    return ret;
171600cc4afSopenharmony_ci}
172600cc4afSopenharmony_ci
173600cc4afSopenharmony_cistatic void ConvertCheckPackageHasInstalledResponse(napi_env env, napi_value hasInstalledResponseObj,
174600cc4afSopenharmony_ci    const OHOS::AppExecFwk::CheckPackageHasInstalledResponse &response)
175600cc4afSopenharmony_ci{
176600cc4afSopenharmony_ci    APP_LOGD("convert CheckPackageHasInstalledResponse start");
177600cc4afSopenharmony_ci    napi_value nResult;
178600cc4afSopenharmony_ci    NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, response.result, &nResult));
179600cc4afSopenharmony_ci    NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, hasInstalledResponseObj, "result", nResult));
180600cc4afSopenharmony_ci}
181600cc4afSopenharmony_ci
182600cc4afSopenharmony_cistatic void HasInstalledExecute(napi_env env, void *data)
183600cc4afSopenharmony_ci{
184600cc4afSopenharmony_ci    APP_LOGD("NAPI_HasInstalled, worker pool thread execute");
185600cc4afSopenharmony_ci    CheckPackageHasInstalledOptions *asyncCallbackInfo = static_cast<CheckPackageHasInstalledOptions *>(data);
186600cc4afSopenharmony_ci    if (asyncCallbackInfo == nullptr) {
187600cc4afSopenharmony_ci        APP_LOGW("NAPI_HasInstalled, asyncCallbackInfo == nullptr");
188600cc4afSopenharmony_ci        return;
189600cc4afSopenharmony_ci    }
190600cc4afSopenharmony_ci    if (!asyncCallbackInfo->errCode && asyncCallbackInfo->isString && asyncCallbackInfo->successRef) {
191600cc4afSopenharmony_ci        asyncCallbackInfo->response.result = InnerHasInstalled(asyncCallbackInfo->bundleName);
192600cc4afSopenharmony_ci    }
193600cc4afSopenharmony_ci    APP_LOGD("NAPI_HasInstalled, worker pool thread execute end");
194600cc4afSopenharmony_ci}
195600cc4afSopenharmony_ci
196600cc4afSopenharmony_cistatic void HasInstalledAsyncComplete(napi_env env, napi_status status, void *data)
197600cc4afSopenharmony_ci{
198600cc4afSopenharmony_ci    APP_LOGD("NAPI_HasInstalled, main event thread complete");
199600cc4afSopenharmony_ci    CheckPackageHasInstalledOptions *asyncCallbackInfo = static_cast<CheckPackageHasInstalledOptions *>(data);
200600cc4afSopenharmony_ci    std::unique_ptr<CheckPackageHasInstalledOptions> callbackPtr {asyncCallbackInfo};
201600cc4afSopenharmony_ci    if (asyncCallbackInfo == nullptr) {
202600cc4afSopenharmony_ci        APP_LOGW("NAPI_HasInstalled, asyncCallbackInfo == nullptr");
203600cc4afSopenharmony_ci        return;
204600cc4afSopenharmony_ci    }
205600cc4afSopenharmony_ci    napi_value callback = nullptr;
206600cc4afSopenharmony_ci    napi_value placeHolder = nullptr;
207600cc4afSopenharmony_ci    if (!asyncCallbackInfo->isString) {
208600cc4afSopenharmony_ci        if (asyncCallbackInfo->failRef) {
209600cc4afSopenharmony_ci            napi_value result[ARGS_SIZE_TWO] = { 0 };
210600cc4afSopenharmony_ci            NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "value is not an available number",
211600cc4afSopenharmony_ci                NAPI_AUTO_LENGTH, &result[PARAM0]));
212600cc4afSopenharmony_ci            NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, INVALID_NUMBER, &result[PARAM1]));
213600cc4afSopenharmony_ci            NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->failRef, &callback));
214600cc4afSopenharmony_ci            napi_call_function(env, nullptr, callback, ARGS_SIZE_TWO, result, &placeHolder);
215600cc4afSopenharmony_ci        }
216600cc4afSopenharmony_ci    } else {
217600cc4afSopenharmony_ci        if (asyncCallbackInfo->successRef) {
218600cc4afSopenharmony_ci            napi_value result[ARGS_SIZE_ONE] = { 0 };
219600cc4afSopenharmony_ci            NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[PARAM0]));
220600cc4afSopenharmony_ci            ConvertCheckPackageHasInstalledResponse(env, result[PARAM0], asyncCallbackInfo->response);
221600cc4afSopenharmony_ci            NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->successRef, &callback));
222600cc4afSopenharmony_ci            napi_call_function(env, nullptr, callback, ARGS_SIZE_ONE, result, &placeHolder);
223600cc4afSopenharmony_ci        }
224600cc4afSopenharmony_ci    }
225600cc4afSopenharmony_ci    if (asyncCallbackInfo->completeRef) {
226600cc4afSopenharmony_ci        NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->completeRef, &callback));
227600cc4afSopenharmony_ci        napi_call_function(env, nullptr, callback, 0, nullptr, &placeHolder);
228600cc4afSopenharmony_ci    }
229600cc4afSopenharmony_ci    APP_LOGD("NAPI_HasInstalled, main event thread complete end");
230600cc4afSopenharmony_ci}
231600cc4afSopenharmony_ci
232600cc4afSopenharmony_cinapi_value HasInstalled(napi_env env, napi_callback_info info)
233600cc4afSopenharmony_ci{
234600cc4afSopenharmony_ci    APP_LOGD("asyncCallback");
235600cc4afSopenharmony_ci    size_t requireArgc = ARGS_SIZE_ONE;
236600cc4afSopenharmony_ci    size_t argc = ARGS_SIZE_TWO;
237600cc4afSopenharmony_ci    napi_value argv[ARGS_SIZE_TWO] = { 0 };
238600cc4afSopenharmony_ci    napi_value thisArg = nullptr;
239600cc4afSopenharmony_ci    void *data = nullptr;
240600cc4afSopenharmony_ci
241600cc4afSopenharmony_ci    NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
242600cc4afSopenharmony_ci    if (argc != requireArgc) {
243600cc4afSopenharmony_ci        APP_LOGW("requires 1 parameter");
244600cc4afSopenharmony_ci        return nullptr;
245600cc4afSopenharmony_ci    }
246600cc4afSopenharmony_ci
247600cc4afSopenharmony_ci    CheckPackageHasInstalledOptions *asyncCallbackInfo = new (std::nothrow) CheckPackageHasInstalledOptions();
248600cc4afSopenharmony_ci    if (asyncCallbackInfo == nullptr) {
249600cc4afSopenharmony_ci        return nullptr;
250600cc4afSopenharmony_ci    }
251600cc4afSopenharmony_ci    std::unique_ptr<CheckPackageHasInstalledOptions> callbackPtr {asyncCallbackInfo};
252600cc4afSopenharmony_ci    asyncCallbackInfo->env = env;
253600cc4afSopenharmony_ci    napi_valuetype valueType = napi_undefined;
254600cc4afSopenharmony_ci    NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
255600cc4afSopenharmony_ci    if (valueType == napi_object) {
256600cc4afSopenharmony_ci        ParseCheckPackageHasInstalledOptions(env, argv[PARAM0], asyncCallbackInfo);
257600cc4afSopenharmony_ci    } else {
258600cc4afSopenharmony_ci        asyncCallbackInfo->errCode = INVALID_PARAM;
259600cc4afSopenharmony_ci    }
260600cc4afSopenharmony_ci
261600cc4afSopenharmony_ci    napi_value resource = nullptr;
262600cc4afSopenharmony_ci    NAPI_CALL(env, napi_create_string_utf8(env, "JSHasInstalled", NAPI_AUTO_LENGTH, &resource));
263600cc4afSopenharmony_ci    NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, HasInstalledExecute,
264600cc4afSopenharmony_ci                       HasInstalledAsyncComplete, (void *)asyncCallbackInfo, &asyncCallbackInfo->asyncWork));
265600cc4afSopenharmony_ci    NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
266600cc4afSopenharmony_ci    callbackPtr.release();
267600cc4afSopenharmony_ci    return nullptr;
268600cc4afSopenharmony_ci}
269600cc4afSopenharmony_ci}  // namespace AppExecFwk
270600cc4afSopenharmony_ci}  // namespace OHOS
271