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 #include "js_app_control.h"
16
17 #include <string>
18
19 #include "app_log_wrapper.h"
20 #include "app_control_interface.h"
21 #include "bundle_mgr_interface.h"
22 #include "bundle_mgr_proxy.h"
23 #include "bundle_errors.h"
24 #include "business_error.h"
25 #include "common_func.h"
26 #include "ipc_skeleton.h"
27 #include "napi_arg.h"
28 #include "napi_constants.h"
29
30 namespace OHOS {
31 namespace AppExecFwk {
32 using namespace OHOS::AAFwk;
33 namespace {
34 const std::string PARAM_TYPE_CHECK_ERROR = "param type check error";
35 const std::string TYPE_WANT = "want";
36 const std::string PERMISSION_DISPOSED_STATUS = "ohos.permission.MANAGE_DISPOSED_APP_STATUS";
37 const std::string SET_DISPOSED_STATUS = "SetDisposedStatus";
38 const std::string GET_DISPOSED_STATUS = "GetDisposedStatus";
39 const std::string DELETE_DISPOSED_STATUS = "DeleteDisposedStatus";
40 const std::string APP_ID = "appId";
41 const std::string DISPOSED_WANT = "disposedWant";
42 }
GetAppControlProxy()43 static OHOS::sptr<OHOS::AppExecFwk::IAppControlMgr> GetAppControlProxy()
44 {
45 auto bundleMgr = CommonFunc::GetBundleMgr();
46 if (bundleMgr == nullptr) {
47 APP_LOGE("CommonFunc::GetBundleMgr failed.");
48 return nullptr;
49 }
50 auto appControlProxy = bundleMgr->GetAppControlProxy();
51 if (appControlProxy == nullptr) {
52 APP_LOGE("GetAppControlProxy failed.");
53 return nullptr;
54 }
55 return appControlProxy;
56 }
57
InnerGetDisposedStatus(napi_env,const std::string & appId,Want & disposedWant)58 static ErrCode InnerGetDisposedStatus(napi_env, const std::string& appId, Want& disposedWant)
59 {
60 auto appControlProxy = GetAppControlProxy();
61 if (appControlProxy == nullptr) {
62 APP_LOGE("AppControlProxy is null.");
63 return ERROR_SYSTEM_ABILITY_NOT_FOUND;
64 }
65 ErrCode ret = appControlProxy->GetDisposedStatus(appId, disposedWant);
66 return CommonFunc::ConvertErrCode(ret);
67 }
68
InnerSetDisposedStatus(napi_env,const std::string & appId,Want & disposedWant)69 static ErrCode InnerSetDisposedStatus(napi_env, const std::string& appId, Want& disposedWant)
70 {
71 auto appControlProxy = GetAppControlProxy();
72 if (appControlProxy == nullptr) {
73 APP_LOGE("AppControlProxy is null.");
74 return ERROR_SYSTEM_ABILITY_NOT_FOUND;
75 }
76 ErrCode ret = appControlProxy->SetDisposedStatus(appId, disposedWant);
77 return CommonFunc::ConvertErrCode(ret);
78 }
79
InnerDeleteDisposedStatus(napi_env,const std::string & appId)80 static ErrCode InnerDeleteDisposedStatus(napi_env, const std::string& appId)
81 {
82 auto appControlProxy = GetAppControlProxy();
83 if (appControlProxy == nullptr) {
84 APP_LOGE("AppControlProxy is null.");
85 return ERROR_SYSTEM_ABILITY_NOT_FOUND;
86 }
87 ErrCode ret = appControlProxy->DeleteDisposedStatus(appId);
88 return CommonFunc::ConvertErrCode(ret);
89 }
90
SetDisposedStatusExec(napi_env env,void * data)91 void SetDisposedStatusExec(napi_env env, void *data)
92 {
93 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
94 if (asyncCallbackInfo == nullptr) {
95 APP_LOGE("%{public}s, asyncCallbackInfo == nullptr.", __func__);
96 return;
97 }
98 if (asyncCallbackInfo->err == NO_ERROR) {
99 asyncCallbackInfo->err = InnerSetDisposedStatus(env, asyncCallbackInfo->appId,
100 asyncCallbackInfo->want);
101 }
102 }
103
SetDisposedStatusComplete(napi_env env,napi_status status,void * data)104 void SetDisposedStatusComplete(napi_env env, napi_status status, void *data)
105 {
106 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
107 if (asyncCallbackInfo == nullptr) {
108 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
109 return;
110 }
111 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
112 napi_value result[1] = {0};
113 if (asyncCallbackInfo->err == NO_ERROR) {
114 NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &result[0]));
115 } else {
116 APP_LOGE("SetDisposedStatus err = %{public}d", asyncCallbackInfo->err);
117 result[0] = BusinessError::CreateCommonError(
118 env, asyncCallbackInfo->err, SET_DISPOSED_STATUS, PERMISSION_DISPOSED_STATUS);
119 }
120 if (asyncCallbackInfo->deferred) {
121 if (asyncCallbackInfo->err == NO_ERROR) {
122 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[0]));
123 } else {
124 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
125 }
126 } else {
127 napi_value callback = nullptr;
128 napi_value placeHolder = nullptr;
129 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
130 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
131 sizeof(result) / sizeof(result[0]), result, &placeHolder));
132 }
133 }
134
SetDisposedStatus(napi_env env,napi_callback_info info)135 napi_value SetDisposedStatus(napi_env env, napi_callback_info info)
136 {
137 APP_LOGD("begin to SetDisposedStatus");
138 NapiArg args(env, info);
139 DisposedStatus *asyncCallbackInfo = new (std::nothrow) DisposedStatus(env);
140 if (asyncCallbackInfo == nullptr) {
141 APP_LOGE("asyncCallbackInfo is null.");
142 return nullptr;
143 }
144 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
145 if (!args.Init(ARGS_SIZE_TWO, ARGS_SIZE_THREE)) {
146 APP_LOGE("Napi func init failed");
147 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
148 return nullptr;
149 }
150 for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
151 napi_valuetype valueType = napi_undefined;
152 napi_typeof(env, args[i], &valueType);
153 if (i == ARGS_POS_ZERO) {
154 if (!CommonFunc::ParseString(env, args[i], asyncCallbackInfo->appId)) {
155 APP_LOGE("appId invalid!");
156 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, APP_ID, TYPE_STRING);
157 return nullptr;
158 }
159 asyncCallbackInfo->err = asyncCallbackInfo->appId.size() == 0 ? ERROR_INVALID_APPID : NO_ERROR;
160 } else if (i == ARGS_POS_ONE) {
161 if (!CommonFunc::ParseWantWithoutVerification(env, args[i], asyncCallbackInfo->want)) {
162 APP_LOGE("disposed want invalid!");
163 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, DISPOSED_WANT, TYPE_WANT);
164 return nullptr;
165 }
166 } else if (i == ARGS_POS_TWO) {
167 if (valueType == napi_function) {
168 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callback));
169 } else {
170 APP_LOGD("SetDisposedStatus extra arg ignored");
171 }
172 } else {
173 APP_LOGE("SetDisposedStatus arg err!");
174 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_TYPE_CHECK_ERROR);
175 return nullptr;
176 }
177 }
178 auto promise = CommonFunc::AsyncCallNativeMethod<DisposedStatus>(
179 env, asyncCallbackInfo, "SetDisposedStatus", SetDisposedStatusExec, SetDisposedStatusComplete);
180 callbackPtr.release();
181 APP_LOGD("call SetDisposedStatus done.");
182 return promise;
183 }
184
DeleteDisposedStatusExec(napi_env env,void * data)185 void DeleteDisposedStatusExec(napi_env env, void *data)
186 {
187 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
188 if (asyncCallbackInfo == nullptr) {
189 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
190 return;
191 }
192 if (asyncCallbackInfo->err == NO_ERROR) {
193 asyncCallbackInfo->err = InnerDeleteDisposedStatus(env, asyncCallbackInfo->appId);
194 }
195 }
196
DeleteDisposedStatusComplete(napi_env env,napi_status,void * data)197 void DeleteDisposedStatusComplete(napi_env env, napi_status, void *data)
198 {
199 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
200 if (asyncCallbackInfo == nullptr) {
201 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
202 return;
203 }
204 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
205 napi_value result[1] = {0};
206 if (asyncCallbackInfo->err == NO_ERROR) {
207 NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &result[0]));
208 } else {
209 APP_LOGE("DeleteDisposedStatus err = %{public}d", asyncCallbackInfo->err);
210 result[0] = BusinessError::CreateCommonError(
211 env, asyncCallbackInfo->err, DELETE_DISPOSED_STATUS, PERMISSION_DISPOSED_STATUS);
212 }
213 if (asyncCallbackInfo->deferred) {
214 if (asyncCallbackInfo->err == NO_ERROR) {
215 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[0]));
216 } else {
217 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
218 }
219 } else {
220 napi_value callback = nullptr;
221 napi_value placeHolder = nullptr;
222 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
223 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
224 sizeof(result) / sizeof(result[0]), result, &placeHolder));
225 }
226 }
227
DeleteDisposedStatus(napi_env env,napi_callback_info info)228 napi_value DeleteDisposedStatus(napi_env env, napi_callback_info info)
229 {
230 APP_LOGD("begin to DeleteDisposedStatus.");
231 NapiArg args(env, info);
232 DisposedStatus *asyncCallbackInfo = new (std::nothrow) DisposedStatus(env);
233 if (asyncCallbackInfo == nullptr) {
234 APP_LOGE("asyncCallbackInfo is null.");
235 return nullptr;
236 }
237 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
238 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_TWO)) {
239 APP_LOGE("param count invalid.");
240 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
241 return nullptr;
242 }
243 for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
244 napi_valuetype valueType = napi_undefined;
245 napi_typeof(env, args[i], &valueType);
246 if (i == ARGS_POS_ZERO) {
247 if (!CommonFunc::ParseString(env, args[i], asyncCallbackInfo->appId)) {
248 APP_LOGE("appId invalid!");
249 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, APP_ID, TYPE_STRING);
250 return nullptr;
251 }
252 if (asyncCallbackInfo->appId.size() == 0) {
253 asyncCallbackInfo->err = ERROR_INVALID_APPID;
254 }
255 } else if (i == ARGS_POS_ONE) {
256 if (valueType == napi_function) {
257 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callback));
258 } else {
259 APP_LOGD("DeleteDisposedStatus extra arg ignored");
260 }
261 } else {
262 APP_LOGE("DeleteDisposedStatus arg err!");
263 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_TYPE_CHECK_ERROR);
264 return nullptr;
265 }
266 }
267 auto promise = CommonFunc::AsyncCallNativeMethod<DisposedStatus>(
268 env, asyncCallbackInfo, "DeleteDisposedStatus", DeleteDisposedStatusExec, DeleteDisposedStatusComplete);
269 callbackPtr.release();
270 APP_LOGD("call DeleteDisposedStatus done.");
271 return promise;
272 }
273
GetDisposedStatusExec(napi_env env,void * data)274 void GetDisposedStatusExec(napi_env env, void *data)
275 {
276 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
277 if (asyncCallbackInfo == nullptr) {
278 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
279 return;
280 }
281 if (asyncCallbackInfo->err == NO_ERROR) {
282 asyncCallbackInfo->err = InnerGetDisposedStatus(env, asyncCallbackInfo->appId,
283 asyncCallbackInfo->want);
284 }
285 }
286
GetDisposedStatusComplete(napi_env env,napi_status status,void * data)287 void GetDisposedStatusComplete(napi_env env, napi_status status, void *data)
288 {
289 DisposedStatus *asyncCallbackInfo = reinterpret_cast<DisposedStatus *>(data);
290 if (asyncCallbackInfo == nullptr) {
291 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
292 return;
293 }
294 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
295 napi_value result[2] = {0};
296 if (asyncCallbackInfo->err == NO_ERROR) {
297 NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &result[0]));
298 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[1]));
299 CommonFunc::ConvertWantInfo(env, result[1], asyncCallbackInfo->want);
300 } else {
301 APP_LOGE("GetDisposedStatus err = %{public}d", asyncCallbackInfo->err);
302 result[0] = BusinessError::CreateCommonError(
303 env, asyncCallbackInfo->err, GET_DISPOSED_STATUS, PERMISSION_DISPOSED_STATUS);
304 }
305 if (asyncCallbackInfo->deferred) {
306 if (asyncCallbackInfo->err == NO_ERROR) {
307 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]));
308 } else {
309 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
310 }
311 } else {
312 napi_value callback = nullptr;
313 napi_value placeHolder = nullptr;
314 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
315 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
316 sizeof(result) / sizeof(result[0]), result, &placeHolder));
317 }
318 }
319
GetDisposedStatus(napi_env env,napi_callback_info info)320 napi_value GetDisposedStatus(napi_env env, napi_callback_info info)
321 {
322 APP_LOGD("NAPI GetDisposedStatus called");
323 NapiArg args(env, info);
324 DisposedStatus *asyncCallbackInfo = new (std::nothrow) DisposedStatus(env);
325 if (asyncCallbackInfo == nullptr) {
326 APP_LOGE("asyncCallbackInfo is null.");
327 return nullptr;
328 }
329 std::unique_ptr<DisposedStatus> callbackPtr {asyncCallbackInfo};
330 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_TWO)) {
331 APP_LOGE("param count invalid.");
332 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
333 return nullptr;
334 }
335 for (size_t i = 0; i < args.GetMaxArgc(); i++) {
336 napi_valuetype valueType = napi_undefined;
337 napi_typeof(env, args[i], &valueType);
338 if (i == ARGS_POS_ZERO) {
339 if (!CommonFunc::ParseString(env, args[i], asyncCallbackInfo->appId)) {
340 APP_LOGE("appId %{public}s invalid!", asyncCallbackInfo->appId.c_str());
341 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, APP_ID, TYPE_STRING);
342 return nullptr;
343 }
344 if (asyncCallbackInfo->appId.size() == 0) {
345 asyncCallbackInfo->err = ERROR_INVALID_APPID;
346 }
347 } else if (i == ARGS_POS_ONE) {
348 if (valueType == napi_function) {
349 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callback));
350 } else {
351 APP_LOGD("GetDisposedStatus extra arg ignored");
352 }
353 } else {
354 APP_LOGE("GetDisposedStatus arg err!");
355 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_TYPE_CHECK_ERROR);
356 return nullptr;
357 }
358 }
359 auto promise = CommonFunc::AsyncCallNativeMethod<DisposedStatus>(
360 env, asyncCallbackInfo, "GetDisposedStatus", GetDisposedStatusExec, GetDisposedStatusComplete);
361 callbackPtr.release();
362 APP_LOGD("call GetDisposedStatus done.");
363 return promise;
364 }
365 }
366 }