1 /*
2 * Copyright (c) 2023-2024 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_ability_auto_startup_manager.h"
16
17 #include "ability_business_error.h"
18 #include "ability_manager_client.h"
19 #include "ability_manager_interface.h"
20 #include "auto_startup_info.h"
21 #include "hilog_tag_wrapper.h"
22 #include "ipc_skeleton.h"
23 #include "js_ability_auto_startup_manager_utils.h"
24 #include "js_error_utils.h"
25 #include "js_runtime_utils.h"
26 #include "permission_constants.h"
27 #include "tokenid_kit.h"
28
29 namespace OHOS {
30 namespace AbilityRuntime {
31 using namespace OHOS::AAFwk;
32 namespace {
33 constexpr size_t ARGC_ONE = 1;
34 constexpr size_t ARGC_TWO = 2;
35 constexpr int32_t INDEX_ZERO = 0;
36 constexpr int32_t INDEX_ONE = 1;
37 constexpr int32_t INVALID_PARAM = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
38 constexpr const char *ON_OFF_TYPE_SYSTEM = "systemAutoStartup";
39 } // namespace
40
Finalizer(napi_env env,void * data,void * hint)41 void JsAbilityAutoStartupManager::Finalizer(napi_env env, void *data, void *hint)
42 {
43 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
44 std::unique_ptr<JsAbilityAutoStartupManager>(static_cast<JsAbilityAutoStartupManager *>(data));
45 }
46
RegisterAutoStartupCallback(napi_env env,napi_callback_info info)47 napi_value JsAbilityAutoStartupManager::RegisterAutoStartupCallback(napi_env env, napi_callback_info info)
48 {
49 GET_NAPI_INFO_AND_CALL(env, info, JsAbilityAutoStartupManager, OnRegisterAutoStartupCallback);
50 }
51
UnregisterAutoStartupCallback(napi_env env,napi_callback_info info)52 napi_value JsAbilityAutoStartupManager::UnregisterAutoStartupCallback(napi_env env, napi_callback_info info)
53 {
54 GET_NAPI_INFO_AND_CALL(env, info, JsAbilityAutoStartupManager, OnUnregisterAutoStartupCallback);
55 }
56
SetApplicationAutoStartup(napi_env env,napi_callback_info info)57 napi_value JsAbilityAutoStartupManager::SetApplicationAutoStartup(napi_env env, napi_callback_info info)
58 {
59 GET_NAPI_INFO_AND_CALL(env, info, JsAbilityAutoStartupManager, OnSetApplicationAutoStartup);
60 }
61
CancelApplicationAutoStartup(napi_env env,napi_callback_info info)62 napi_value JsAbilityAutoStartupManager::CancelApplicationAutoStartup(napi_env env, napi_callback_info info)
63 {
64 GET_NAPI_INFO_AND_CALL(env, info, JsAbilityAutoStartupManager, OnCancelApplicationAutoStartup);
65 }
66
QueryAllAutoStartupApplications(napi_env env,napi_callback_info info)67 napi_value JsAbilityAutoStartupManager::QueryAllAutoStartupApplications(napi_env env, napi_callback_info info)
68 {
69 GET_NAPI_INFO_AND_CALL(env, info, JsAbilityAutoStartupManager, OnQueryAllAutoStartupApplications);
70 }
71
CheckCallerIsSystemApp()72 bool JsAbilityAutoStartupManager::CheckCallerIsSystemApp()
73 {
74 auto selfToken = IPCSkeleton::GetSelfTokenID();
75 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
76 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "not system app");
77 return false;
78 }
79 return true;
80 }
81
OnRegisterAutoStartupCallback(napi_env env,NapiCallbackInfo & info)82 napi_value JsAbilityAutoStartupManager::OnRegisterAutoStartupCallback(napi_env env, NapiCallbackInfo &info)
83 {
84 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
85 if (info.argc < ARGC_TWO) {
86 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "invalid argc");
87 ThrowTooFewParametersError(env);
88 return CreateJsUndefined(env);
89 }
90
91 std::string type;
92 if (!ConvertFromJsValue(env, info.argv[INDEX_ZERO], type) || type != ON_OFF_TYPE_SYSTEM) {
93 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "invalid param");
94 ThrowError(env, INVALID_PARAM, "Parameter error. Convert type fail.");
95 return CreateJsUndefined(env);
96 }
97
98 if (!CheckCallerIsSystemApp()) {
99 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "not system app");
100 ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP);
101 return CreateJsUndefined(env);
102 }
103
104 if (jsAutoStartupCallback_ == nullptr) {
105 jsAutoStartupCallback_ = new (std::nothrow) JsAbilityAutoStartupCallBack(env);
106 if (jsAutoStartupCallback_ == nullptr) {
107 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null jsAutoStartupCallback_");
108 ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER);
109 return CreateJsUndefined(env);
110 }
111
112 auto ret =
113 AbilityManagerClient::GetInstance()->RegisterAutoStartupSystemCallback(jsAutoStartupCallback_->AsObject());
114 if (ret != ERR_OK) {
115 jsAutoStartupCallback_ = nullptr;
116 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "reg callback failed[%{public}d]", ret);
117 if (ret == CHECK_PERMISSION_FAILED) {
118 ThrowNoPermissionError(env, PermissionConstants::PERMISSION_MANAGE_APP_BOOT);
119 } else {
120 ThrowError(env, GetJsErrorCodeByNativeError(ret));
121 }
122 return CreateJsUndefined(env);
123 }
124 }
125
126 jsAutoStartupCallback_->Register(info.argv[INDEX_ONE]);
127 return CreateJsUndefined(env);
128 }
129
OnUnregisterAutoStartupCallback(napi_env env,NapiCallbackInfo & info)130 napi_value JsAbilityAutoStartupManager::OnUnregisterAutoStartupCallback(napi_env env, NapiCallbackInfo &info)
131 {
132 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
133 if (info.argc < ARGC_ONE) {
134 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "invalid argc");
135 ThrowTooFewParametersError(env);
136 return CreateJsUndefined(env);
137 }
138
139 std::string type;
140 if (!ConvertFromJsValue(env, info.argv[INDEX_ZERO], type) || type != ON_OFF_TYPE_SYSTEM) {
141 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "parse type failed");
142 ThrowError(env, INVALID_PARAM, "Parameter error. Convert type fail.");
143 return CreateJsUndefined(env);
144 }
145
146 if (!CheckCallerIsSystemApp()) {
147 ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP);
148 return CreateJsUndefined(env);
149 }
150
151 if (jsAutoStartupCallback_ == nullptr) {
152 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null jsAutoStartupCallback_");
153 ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER);
154 return CreateJsUndefined(env);
155 }
156
157 auto callback = info.argc > ARGC_ONE ? info.argv[INDEX_ONE] : CreateJsUndefined(env);
158 jsAutoStartupCallback_->UnRegister(callback);
159 if (jsAutoStartupCallback_->IsCallbacksEmpty()) {
160 auto ret = AbilityManagerClient::GetInstance()->UnregisterAutoStartupSystemCallback(
161 jsAutoStartupCallback_->AsObject());
162 if (ret != ERR_OK) {
163 if (ret == CHECK_PERMISSION_FAILED) {
164 ThrowNoPermissionError(env, PermissionConstants::PERMISSION_MANAGE_APP_BOOT);
165 } else {
166 ThrowError(env, GetJsErrorCodeByNativeError(ret));
167 }
168 }
169 jsAutoStartupCallback_ = nullptr;
170 }
171
172 return CreateJsUndefined(env);
173 }
174
OnSetApplicationAutoStartup(napi_env env,NapiCallbackInfo & info)175 napi_value JsAbilityAutoStartupManager::OnSetApplicationAutoStartup(napi_env env, NapiCallbackInfo &info)
176 {
177 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
178 if (info.argc < ARGC_ONE) {
179 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "invalid argc");
180 ThrowTooFewParametersError(env);
181 return CreateJsUndefined(env);
182 }
183
184 if (!CheckCallerIsSystemApp()) {
185 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "not system app");
186 ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP);
187 return CreateJsUndefined(env);
188 }
189
190 AutoStartupInfo autoStartupInfo;
191 if (!UnwrapAutoStartupInfo(env, info.argv[INDEX_ZERO], autoStartupInfo)) {
192 ThrowError(env, INVALID_PARAM, "unwrap AutoStartupInfo failed");
193 return CreateJsUndefined(env);
194 }
195
196 auto retVal = std::make_shared<int32_t>(0);
197 NapiAsyncTask::ExecuteCallback execute = [autoStartupInfo, ret = retVal] () {
198 if (ret == nullptr) {
199 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret");
200 return;
201 }
202 *ret = AbilityManagerClient::GetInstance()->SetApplicationAutoStartup(autoStartupInfo);
203 };
204 NapiAsyncTask::CompleteCallback complete = [ret = retVal](napi_env env, NapiAsyncTask &task, int32_t status) {
205 if (ret == nullptr) {
206 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret");
207 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(INNER_ERR)));
208 return;
209 }
210 if (*ret != ERR_OK) {
211 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "error:%{public}d", *ret);
212 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(*ret)));
213 return;
214 }
215 task.ResolveWithNoError(env, CreateJsUndefined(env));
216 };
217
218 napi_value lastParam = (info.argc >= ARGC_TWO) ? info.argv[INDEX_ONE] : nullptr;
219 napi_value result = nullptr;
220 NapiAsyncTask::ScheduleHighQos("JsAbilityAutoStartupManager::OnSetApplicationAutoStartup", env,
221 CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
222 return result;
223 }
224
OnCancelApplicationAutoStartup(napi_env env,NapiCallbackInfo & info)225 napi_value JsAbilityAutoStartupManager::OnCancelApplicationAutoStartup(napi_env env, NapiCallbackInfo &info)
226 {
227 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
228 if (info.argc < ARGC_ONE) {
229 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "invalid argc");
230 ThrowTooFewParametersError(env);
231 return CreateJsUndefined(env);
232 }
233
234 if (!CheckCallerIsSystemApp()) {
235 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "not system app");
236 ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP);
237 return CreateJsUndefined(env);
238 }
239
240 AutoStartupInfo autoStartupInfo;
241 if (!UnwrapAutoStartupInfo(env, info.argv[INDEX_ZERO], autoStartupInfo)) {
242 ThrowError(env, INVALID_PARAM, "Parameter error. Convert autoStartupInfo fail.");
243 return CreateJsUndefined(env);
244 }
245
246 auto retVal = std::make_shared<int32_t>(0);
247 NapiAsyncTask::ExecuteCallback execute = [autoStartupInfo, ret = retVal] () {
248 if (ret == nullptr) {
249 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret");
250 return;
251 }
252 *ret = AbilityManagerClient::GetInstance()->CancelApplicationAutoStartup(autoStartupInfo);
253 };
254
255 NapiAsyncTask::CompleteCallback complete = [ret = retVal](napi_env env, NapiAsyncTask &task, int32_t status) {
256 if (ret == nullptr) {
257 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret");
258 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(INNER_ERR)));
259 return;
260 }
261 if (*ret != ERR_OK) {
262 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "error:%{public}d", *ret);
263 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(*ret)));
264 return;
265 }
266 task.ResolveWithNoError(env, CreateJsUndefined(env));
267 };
268
269 napi_value lastParam = (info.argc >= ARGC_TWO) ? info.argv[INDEX_ONE] : nullptr;
270 napi_value result = nullptr;
271 NapiAsyncTask::Schedule("JsAbilityAutoStartupManager::OnCancelApplicationAutoStartup", env,
272 CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
273 return result;
274 }
275
OnQueryAllAutoStartupApplications(napi_env env,const NapiCallbackInfo & info)276 napi_value JsAbilityAutoStartupManager::OnQueryAllAutoStartupApplications(napi_env env, const NapiCallbackInfo &info)
277 {
278 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
279 if (!CheckCallerIsSystemApp()) {
280 ThrowError(env, AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP);
281 return CreateJsUndefined(env);
282 }
283
284 auto retVal = std::make_shared<int32_t>(0);
285 auto infoList = std::make_shared<std::vector<AutoStartupInfo>>();
286 NapiAsyncTask::ExecuteCallback execute = [infos = infoList, ret = retVal] () {
287 if (ret == nullptr || infos == nullptr) {
288 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret or infos");
289 return;
290 }
291 *ret = AbilityManagerClient::GetInstance()->QueryAllAutoStartupApplications(*infos);
292 };
293
294 NapiAsyncTask::CompleteCallback complete = [infos = infoList, ret = retVal](
295 napi_env env, NapiAsyncTask &task, int32_t status) {
296 if (ret == nullptr || infos == nullptr) {
297 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null ret or infos");
298 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(INNER_ERR)));
299 return;
300 }
301 if (*ret != ERR_OK) {
302 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "error:%{public}d", *ret);
303 task.Reject(env, CreateJsError(env, GetJsErrorCodeByNativeError(*ret)));
304 return;
305 }
306 task.ResolveWithNoError(env, CreateJsAutoStartupInfoArray(env, *infos));
307 };
308
309 napi_value lastParam = (info.argc >= ARGC_ONE) ? info.argv[INDEX_ZERO] : nullptr;
310 napi_value result = nullptr;
311 NapiAsyncTask::Schedule("JsAbilityAutoStartupManager::OnQueryAllAutoStartupApplications", env,
312 CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
313 return result;
314 }
315
JsAbilityAutoStartupManagerInit(napi_env env,napi_value exportObj)316 napi_value JsAbilityAutoStartupManagerInit(napi_env env, napi_value exportObj)
317 {
318 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "called");
319 if (env == nullptr || exportObj == nullptr) {
320 TAG_LOGE(AAFwkTag::AUTO_STARTUP, "null env or exportObj");
321 return nullptr;
322 }
323
324 auto jsAbilityAutoStartupManager = std::make_unique<JsAbilityAutoStartupManager>();
325 napi_wrap(env, exportObj, jsAbilityAutoStartupManager.release(),
326 JsAbilityAutoStartupManager::Finalizer, nullptr, nullptr);
327
328 const char *moduleName = "JsAbilityAutoStartupManager";
329 BindNativeFunction(env, exportObj, "on", moduleName, JsAbilityAutoStartupManager::RegisterAutoStartupCallback);
330 BindNativeFunction(env, exportObj, "off", moduleName, JsAbilityAutoStartupManager::UnregisterAutoStartupCallback);
331 BindNativeFunction(env, exportObj, "setApplicationAutoStartup", moduleName,
332 JsAbilityAutoStartupManager::SetApplicationAutoStartup);
333 BindNativeFunction(env, exportObj, "cancelApplicationAutoStartup", moduleName,
334 JsAbilityAutoStartupManager::CancelApplicationAutoStartup);
335 BindNativeFunction(env, exportObj, "queryAllAutoStartupApplications", moduleName,
336 JsAbilityAutoStartupManager::QueryAllAutoStartupApplications);
337 TAG_LOGD(AAFwkTag::AUTO_STARTUP, "end");
338 return CreateJsUndefined(env);
339 }
340 } // namespace AbilityRuntime
341 } // namespace OHOS