1 /*
2 * Copyright (c) 2025 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 "js_kiosk_manager.h"
17
18 #include <memory>
19 #include <regex>
20
21 #include "ability_manager_client.h"
22 #include "errors.h"
23 #include "hilog_tag_wrapper.h"
24 #include "js_error_utils.h"
25 #include "napi/native_api.h"
26 #include "napi_base_context.h"
27 #include "napi_common_configuration.h"
28 #include "napi_common_util.h"
29 #include "napi_common_want.h"
30 #include "kiosk_status.h"
31
32 namespace OHOS {
33 namespace AbilityRuntime {
34 using AbilityManagerClient = AAFwk::AbilityManagerClient;
35 namespace {
36 constexpr size_t ARGC_ZERO = 0;
37 constexpr size_t ARGC_ONE = 1;
38 constexpr size_t INDEX_ZERO = 0;
39
40 class JsKioskManager final {
41 public:
42 JsKioskManager() = default;
43 ~JsKioskManager() = default;
44
45 static napi_value UpdateKioskApplicationList(napi_env env, napi_callback_info info);
46 static napi_value EnterKioskMode(napi_env env, napi_callback_info info);
47 static napi_value ExitKioskMode(napi_env env, napi_callback_info info);
48 static napi_value GetKioskStatus(napi_env env, napi_callback_info info);
Finalizer(napi_env env,void * data,void * hint)49 static void Finalizer(napi_env env, void* data, void* hint)
50 {
51 TAG_LOGI(AAFwkTag::APPKIT, "finalizer called");
52 std::unique_ptr<JsKioskManager>(static_cast<JsKioskManager*>(data));
53 }
54
55 private:
56 static napi_value CreateJsKioskStatus(napi_env env,
57 std::shared_ptr<AAFwk::KioskStatus> kioskStatus);
58 napi_value OnUpdateKioskApplicationList(napi_env env, NapiCallbackInfo &info);
59 napi_value OnEnterKioskMode(napi_env env, NapiCallbackInfo &info);
60 napi_value OnExitKioskMode(napi_env env, NapiCallbackInfo &info);
61 napi_value OnGetKioskStatus(napi_env env, NapiCallbackInfo &info);
62 };
63 } // namespace
64
CreateJsKioskStatus(napi_env env,std::shared_ptr<AAFwk::KioskStatus> kioskStatus)65 napi_value JsKioskManager::CreateJsKioskStatus(napi_env env,
66 std::shared_ptr<AAFwk::KioskStatus> kioskStatus)
67 {
68 napi_value objValue = nullptr;
69 napi_create_object(env, &objValue);
70 if (objValue == nullptr) {
71 TAG_LOGE(AAFwkTag::APPKIT, "null ObjValue");
72 return nullptr;
73 }
74 if (kioskStatus == nullptr) {
75 TAG_LOGE(AAFwkTag::APPKIT, "null kioskStatus");
76 return nullptr;
77 }
78 napi_set_named_property(env, objValue, "isKioskMode",
79 CreateJsValue(env, kioskStatus->isKioskMode_));
80 napi_set_named_property(env, objValue, "kioskBundleName",
81 CreateJsValue(env, kioskStatus->kioskBundleName_));
82 napi_set_named_property(env, objValue, "kioskBundleUid", CreateJsValue(env, kioskStatus->kioskBundleUid_));
83 return objValue;
84 }
85
UpdateKioskApplicationList(napi_env env,napi_callback_info info)86 napi_value JsKioskManager::UpdateKioskApplicationList(napi_env env, napi_callback_info info)
87 {
88 GET_NAPI_INFO_AND_CALL(env, info, JsKioskManager, OnUpdateKioskApplicationList);
89 }
90
OnUpdateKioskApplicationList(napi_env env,NapiCallbackInfo & info)91 napi_value JsKioskManager::OnUpdateKioskApplicationList(napi_env env, NapiCallbackInfo &info)
92 {
93 TAG_LOGD(AAFwkTag::APPKIT, "On Update Kiosk AppList");
94 if (info.argc < ARGC_ONE) {
95 TAG_LOGE(AAFwkTag::APPKIT, "too few params");
96 ThrowTooFewParametersError(env);
97 return CreateJsUndefined(env);
98 }
99 auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
100
101 std::vector<std::string> appList;
102 if (!OHOS::AppExecFwk::UnwrapArrayStringFromJS(env, info.argv[ARGC_ZERO], appList)) {
103 TAG_LOGE(AAFwkTag::APPKIT, "app list is invalid");
104 ThrowInvalidParamError(env, "Failed to parse application list. Application list must be an Array<string>.");
105 return CreateJsUndefined(env);
106 }
107 NapiAsyncTask::ExecuteCallback execute = [innerErrCode, appList]() {
108 auto amsClient = AbilityManagerClient::GetInstance();
109 if (amsClient == nullptr) {
110 TAG_LOGE(AAFwkTag::APPKIT, "null amsClient");
111 *innerErrCode = static_cast<int32_t>(AAFwk::INNER_ERR);
112 return;
113 }
114 *innerErrCode = amsClient->UpdateKioskApplicationList(appList);
115 };
116
117 auto complete = [innerErrCode](napi_env env, NapiAsyncTask &task, int32_t status) {
118 if (*innerErrCode != ERR_OK) {
119 TAG_LOGE(AAFwkTag::APPKIT, "innerErrCode=%{public}d", *innerErrCode);
120 task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
121 return;
122 }
123 task.ResolveWithNoError(env, CreateJsUndefined(env));
124 };
125 napi_value result = nullptr;
126 NapiAsyncTask::Schedule("JsKioskManager::OnUpdateKioskApplicationList", env,
127 CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute),
128 std::move(complete), &result));
129 return result;
130 }
131
EnterKioskMode(napi_env env,napi_callback_info info)132 napi_value JsKioskManager::EnterKioskMode(napi_env env, napi_callback_info info)
133 {
134 GET_NAPI_INFO_AND_CALL(env, info, JsKioskManager, OnEnterKioskMode);
135 }
136
OnEnterKioskMode(napi_env env,NapiCallbackInfo & info)137 napi_value JsKioskManager::OnEnterKioskMode(napi_env env, NapiCallbackInfo &info)
138 {
139 TAG_LOGD(AAFwkTag::APPKIT, "On Enter KioskMode start");
140 if (info.argc < ARGC_ONE) {
141 TAG_LOGE(AAFwkTag::APPKIT, "too few params");
142 ThrowTooFewParametersError(env);
143 return CreateJsUndefined(env);
144 }
145
146 auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[INDEX_ZERO]);
147 if (context == nullptr) {
148 TAG_LOGE(AAFwkTag::APPKIT, "null context");
149 ThrowInvalidParamError(env, "Failed to get context. Context must not be nullptr.");
150 return CreateJsUndefined(env);
151 }
152 auto uiAbilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
153 if (uiAbilityContext == nullptr) {
154 TAG_LOGE(AAFwkTag::APPKIT, "null UIAbilityContext");
155 ThrowInvalidParamError(env, "Failed to get uiAbilityContext, uiAbilityContext must not be nullptr.");
156 return CreateJsUndefined(env);
157 }
158 auto token = uiAbilityContext->GetToken();
159 auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
160
161 NapiAsyncTask::ExecuteCallback execute = [innerErrCode, token]() {
162 auto amsClient = AbilityManagerClient::GetInstance();
163 if (amsClient == nullptr) {
164 TAG_LOGE(AAFwkTag::APPKIT, "null amsClient");
165 *innerErrCode = static_cast<int32_t>(AAFwk::INNER_ERR);
166 return;
167 }
168
169 *innerErrCode = amsClient->EnterKioskMode(token);
170 };
171
172 auto complete = [innerErrCode](napi_env env, NapiAsyncTask &task, int32_t status) {
173 if (*innerErrCode != ERR_OK) {
174 TAG_LOGE(AAFwkTag::APPKIT, "innerErrCode=%{public}d", *innerErrCode);
175 task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
176 return;
177 }
178 task.ResolveWithNoError(env, CreateJsUndefined(env));
179 };
180
181 napi_value result = nullptr;
182 NapiAsyncTask::Schedule("JsKioskManager::OnEnterKioskMode", env,
183 CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute),
184 std::move(complete), &result));
185 return result;
186 }
187
ExitKioskMode(napi_env env,napi_callback_info info)188 napi_value JsKioskManager::ExitKioskMode(napi_env env, napi_callback_info info)
189 {
190 GET_NAPI_INFO_AND_CALL(env, info, JsKioskManager, OnExitKioskMode);
191 }
192
OnExitKioskMode(napi_env env,NapiCallbackInfo & info)193 napi_value JsKioskManager::OnExitKioskMode(napi_env env, NapiCallbackInfo &info)
194 {
195 TAG_LOGD(AAFwkTag::APPKIT, "On Exit KioskMode");
196 if (info.argc < ARGC_ONE) {
197 TAG_LOGE(AAFwkTag::APPKIT, "too few params");
198 ThrowTooFewParametersError(env);
199 return CreateJsUndefined(env);
200 }
201
202 auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[INDEX_ZERO]);
203 if (context == nullptr) {
204 TAG_LOGE(AAFwkTag::APPKIT, "null context");
205 ThrowInvalidParamError(env, "Failed to get context. Context must not be nullptr.");
206 return CreateJsUndefined(env);
207 }
208 auto uiAbilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
209 if (uiAbilityContext == nullptr) {
210 TAG_LOGE(AAFwkTag::APPKIT, "null UIAbilityContext");
211 ThrowInvalidParamError(env, "Failed to get uIAbilityContext. Context must be uIAbilityContext.");
212 return CreateJsUndefined(env);
213 }
214 auto token = uiAbilityContext->GetToken();
215 auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
216
217 NapiAsyncTask::ExecuteCallback execute = [innerErrCode, token]() {
218 auto amsClient = AbilityManagerClient::GetInstance();
219 if (amsClient == nullptr) {
220 TAG_LOGE(AAFwkTag::APPKIT, "null amsClient");
221 *innerErrCode = static_cast<int32_t>(AAFwk::INNER_ERR);
222 return;
223 }
224 *innerErrCode = amsClient->ExitKioskMode(token);
225 };
226
227 auto complete = [innerErrCode](napi_env env, NapiAsyncTask &task, int32_t status) {
228 if (*innerErrCode != ERR_OK) {
229 TAG_LOGE(AAFwkTag::APPKIT, "innerErrCode=%{public}d", *innerErrCode);
230 task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
231 return;
232 }
233 task.ResolveWithNoError(env, CreateJsUndefined(env));
234 };
235 napi_value result = nullptr;
236 NapiAsyncTask::Schedule("JsKioskManager::OnExitKioskMode", env,
237 CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute),
238 std::move(complete), &result));
239 return result;
240 }
241
GetKioskStatus(napi_env env,napi_callback_info info)242 napi_value JsKioskManager::GetKioskStatus(napi_env env, napi_callback_info info)
243 {
244 GET_NAPI_INFO_AND_CALL(env, info, JsKioskManager, OnGetKioskStatus);
245 }
246
OnGetKioskStatus(napi_env env,NapiCallbackInfo & info)247 napi_value JsKioskManager::OnGetKioskStatus(napi_env env, NapiCallbackInfo &info)
248 {
249 TAG_LOGD(AAFwkTag::APPKIT, "Get KioskStatus");
250 auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
251 std::shared_ptr<AAFwk::KioskStatus> kioskStatus = std::make_shared<AAFwk::KioskStatus>();
252
253 NapiAsyncTask::ExecuteCallback execute = [innerErrCode, kioskStatus]() {
254 auto amsClient = AbilityManagerClient::GetInstance();
255 if (amsClient == nullptr) {
256 TAG_LOGE(AAFwkTag::APPKIT, "null amsClient");
257 *innerErrCode = static_cast<int32_t>(AAFwk::INNER_ERR);
258 return;
259 }
260 *innerErrCode = amsClient->GetKioskStatus(*kioskStatus);
261 };
262
263 auto complete = [innerErrCode, kioskStatus](napi_env env, NapiAsyncTask &task, int32_t status) {
264 if (*innerErrCode != ERR_OK) {
265 TAG_LOGE(AAFwkTag::APPKIT, "innerErrCode=%{public}d", *innerErrCode);
266 task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
267 return;
268 }
269 task.ResolveWithNoError(env, JsKioskManager::CreateJsKioskStatus(env, kioskStatus));
270 };
271 napi_value result = nullptr;
272 NapiAsyncTask::Schedule("JsKioskManager::OnGetKioskStatus", env,
273 CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute),
274 std::move(complete), &result));
275 return result;
276 }
277
JsKioskManagerInit(napi_env env,napi_value exportObj)278 napi_value JsKioskManagerInit(napi_env env, napi_value exportObj)
279 {
280 std::unique_ptr<JsKioskManager> jsKioskManager = std::make_unique<JsKioskManager>();
281 napi_wrap(env, exportObj, jsKioskManager.release(), JsKioskManager::Finalizer, nullptr,
282 nullptr);
283
284 const char *moduleName = "JsKioskManager";
285
286 BindNativeFunction(env, exportObj, "updateKioskAppList", moduleName,
287 JsKioskManager::UpdateKioskApplicationList);
288 BindNativeFunction(env, exportObj, "enterKioskMode", moduleName, JsKioskManager::EnterKioskMode);
289 BindNativeFunction(env, exportObj, "exitKioskMode", moduleName, JsKioskManager::ExitKioskMode);
290 BindNativeFunction(env, exportObj, "getKioskStatus", moduleName, JsKioskManager::GetKioskStatus);
291
292 TAG_LOGD(AAFwkTag::APPKIT, "end");
293 return CreateJsUndefined(env);
294 }
295 } // namespace AbilityRuntime
296 } // namespace OHOS
297