1
2 /*
3 * Copyright (c) 2023 Huawei Device Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "js_form_observer.h"
18
19 #include "fms_log_wrapper.h"
20 #include "form_callback_interface.h"
21 #include "form_host_client.h"
22 #include "form_info.h"
23 #include "form_instance.h"
24 #include "form_instances_filter.h"
25 #include "form_mgr.h"
26 #include "form_mgr_errors.h"
27 #include "ipc_skeleton.h"
28 #include "js_form_state_observer.h"
29 #include "js_runtime.h"
30 #include "js_runtime_utils.h"
31 #include "napi/native_api.h"
32 #include "napi/native_node_api.h"
33 #include "napi_common_util.h"
34 #include "napi_common_want.h"
35 #include "napi_form_util.h"
36 #include "runtime.h"
37 #include "tokenid_kit.h"
38
39 namespace OHOS {
40 namespace AbilityRuntime {
41 using FormMgr = AppExecFwk::FormMgr;
42 namespace {
43 const std::string EMPTY_BUNDLE = "";
44 const std::string EMPTY_TYPE = "";
45 }
46 class JsFormObserver {
47 public:
48 JsFormObserver() = default;
49 ~JsFormObserver() = default;
50
Finalizer(napi_env env,void * data,void * hint)51 static void Finalizer(napi_env env, void *data, void *hint)
52 {
53 HILOG_DEBUG("call");
54 std::unique_ptr<JsFormObserver>(static_cast<JsFormObserver*>(data));
55 }
56
RegisterFormObserver(napi_env env,napi_callback_info info)57 static napi_value RegisterFormObserver(napi_env env, napi_callback_info info)
58 {
59 GET_CB_INFO_AND_CALL(env, info, JsFormObserver, OnRegisterFormObserver);
60 }
61
UnregisterFormObserver(napi_env env,napi_callback_info info)62 static napi_value UnregisterFormObserver(napi_env env, napi_callback_info info)
63 {
64 GET_CB_INFO_AND_CALL(env, info, JsFormObserver, OnUnregisterFormObserver);
65 }
66
GetRunningFormInfos(napi_env env,napi_callback_info info)67 static napi_value GetRunningFormInfos(napi_env env, napi_callback_info info)
68 {
69 GET_CB_INFO_AND_CALL(env, info, JsFormObserver, OnGetRunningFormInfos);
70 }
71
GetFormInstancesByFilter(napi_env env,napi_callback_info info)72 static napi_value GetFormInstancesByFilter(napi_env env, napi_callback_info info)
73 {
74 GET_CB_INFO_AND_CALL(env, info, JsFormObserver, OnGetFormInstancesByFilter);
75 }
76
GetFormInstanceById(napi_env env,napi_callback_info info)77 static napi_value GetFormInstanceById(napi_env env, napi_callback_info info)
78 {
79 GET_CB_INFO_AND_CALL(env, info, JsFormObserver, OnGetFormInstanceById);
80 }
81 private:
CheckCallerIsSystemApp()82 bool CheckCallerIsSystemApp()
83 {
84 auto selfToken = IPCSkeleton::GetSelfTokenID();
85 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken);
86 }
87
CheckParamNum(napi_env env,size_t argc,size_t minParamNum,size_t maxParamNum)88 bool CheckParamNum(napi_env env, size_t argc, size_t minParamNum, size_t maxParamNum)
89 {
90 HILOG_DEBUG("argc is %{public}zu,param range is [%{public}zu,%{public}zu]",
91 argc, minParamNum, maxParamNum);
92 if (argc > maxParamNum || argc < minParamNum) {
93 HILOG_ERROR("invalid param number %{public}zu", argc);
94 std::string errMsg = "[" + std::to_string(minParamNum) + ", " + std::to_string(maxParamNum) + "]";
95 NapiFormUtil::ThrowParamNumError(env, std::to_string(argc), errMsg);
96 return false;
97 }
98 return true;
99 }
100
ConvertFromId(napi_env env,napi_value jsValue,int64_t & formId)101 static bool ConvertFromId(napi_env env, napi_value jsValue, int64_t &formId)
102 {
103 std::string strFormId;
104 if (!ConvertFromJsValue(env, jsValue, strFormId)) {
105 HILOG_ERROR("Convert strFormId failed");
106 return false;
107 }
108
109 if (strFormId.empty()) {
110 HILOG_ERROR("empty strFormId");
111 return false;
112 }
113
114 if (!ConvertStringToInt64(strFormId, formId)) {
115 HILOG_ERROR("Convert string formId to int64 failed");
116 return false;
117 }
118 return true;
119 }
120
OnRegisterFormAddObserver(napi_env env,size_t argc,napi_value * argv)121 napi_value OnRegisterFormAddObserver(napi_env env, size_t argc, napi_value *argv)
122 {
123 HILOG_DEBUG("call");
124 if (CheckParamNum(env, argc, ARGS_TWO, ARGS_THREE) == false) {
125 return CreateJsUndefined(env);
126 }
127
128 std::string bundleName("");
129 if (argc == ARGS_THREE) {
130 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
131 HILOG_ERROR("Convert type failed");
132 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
133 return CreateJsUndefined(env);
134 }
135 } else {
136 bundleName = "all";
137 }
138
139 if (!AppExecFwk::IsTypeForNapiValue(env, argv[argc - 1], napi_function)) {
140 HILOG_ERROR("invalid lastParam");
141 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
142 return CreateJsUndefined(env);
143 }
144
145 // Check the size of the map.
146 if (!JsFormStateObserver::GetInstance()->CheckMapSize("formAdd", bundleName)) {
147 NapiFormUtil::ThrowParamError(env,
148 "The number of bundleNames registered to listen has exceeded the limit.");
149 return CreateJsUndefined(env);
150 }
151
152 if (!JsFormStateObserver::GetInstance()->RegisterFormAddCallback(env, bundleName, argv[argc - 1])) {
153 return CreateJsUndefined(env);
154 }
155 FormMgr::GetInstance().RegisterFormAddObserverByBundle(bundleName, JsFormStateObserver::GetInstance());
156 return CreateJsUndefined(env);
157 }
158
OnRegisterFormRemoveObserver(napi_env env,size_t argc,napi_value * argv)159 napi_value OnRegisterFormRemoveObserver(napi_env env, size_t argc, napi_value *argv)
160 {
161 HILOG_DEBUG("call");
162 if (CheckParamNum(env, argc, ARGS_TWO, ARGS_THREE) == false) {
163 return CreateJsUndefined(env);
164 }
165
166 std::string bundleName("");
167 if (argc == ARGS_THREE) {
168 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
169 HILOG_ERROR("Convert type failed");
170 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
171 return CreateJsUndefined(env);
172 }
173 } else {
174 bundleName = "all";
175 }
176
177 if (!AppExecFwk::IsTypeForNapiValue(env, argv[argc - 1], napi_function)) {
178 HILOG_ERROR("invalid lastParam");
179 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
180 return CreateJsUndefined(env);
181 }
182
183 // Check the size of the map.
184 if (!JsFormStateObserver::GetInstance()->CheckMapSize("formRemove", bundleName)) {
185 NapiFormUtil::ThrowParamError(env,
186 "The number of bundleNames registered to listen has exceeded the limit.");
187 return CreateJsUndefined(env);
188 }
189
190 if (!JsFormStateObserver::GetInstance()->RegisterFormRemoveCallback(env, bundleName, argv[argc - 1])) {
191 return CreateJsUndefined(env);
192 }
193
194 FormMgr::GetInstance().RegisterFormRemoveObserverByBundle(bundleName, JsFormStateObserver::GetInstance());
195 return CreateJsUndefined(env);
196 }
197
OnRegisterFormObserver(napi_env env,size_t argc,napi_value * argv)198 napi_value OnRegisterFormObserver(napi_env env, size_t argc, napi_value *argv)
199 {
200 HILOG_DEBUG("call");
201 if (!CheckCallerIsSystemApp()) {
202 HILOG_ERROR("The app not system-app,can't use system-api");
203 NapiFormUtil::ThrowByExternalErrorCode(env, AppExecFwk::ERR_FORM_EXTERNAL_NOT_SYSTEM_APP);
204 return CreateJsUndefined(env);
205 }
206
207 std::string type;
208 if (!ConvertFromJsValue(env, argv[PARAM0], type)) {
209 HILOG_ERROR("Convert type failed");
210 NapiFormUtil::ThrowParamTypeError(env, "type",
211 "formAdd, formRemove, notifyVisible, notifyInvisible, router, message, call.");
212 return CreateJsUndefined(env);
213 }
214
215 if (type == "formAdd") {
216 return OnRegisterFormAddObserver(env, argc, argv);
217 } else if (type == "formRemove") {
218 return OnRegisterFormRemoveObserver(env, argc, argv);
219 } else if (type == "notifyVisible") {
220 return OnRegisterFormIsVisibleObserver(env, argc, argv, true);
221 } else if (type == "notifyInvisible") {
222 return OnRegisterFormIsVisibleObserver(env, argc, argv, false);
223 } else if (type == "router" || type == "message" || type == "call") {
224 return OnRegisterClickEventCallback(env, argc, argv, type);
225 } else {
226 HILOG_ERROR("args[0] not formAdd,formRemove,notifyVisible,notifyInvisible,router,message,call");
227 NapiFormUtil::ThrowParamTypeError(env, "type",
228 "formAdd, formRemove, notifyVisible, notifyInvisible, router, message, call.");
229 return CreateJsUndefined(env);
230 }
231 }
232
OnRegisterFormIsVisibleObserver(napi_env env,size_t argc,napi_value * argv,bool isVisibility)233 napi_value OnRegisterFormIsVisibleObserver(napi_env env, size_t argc, napi_value *argv, bool isVisibility)
234 {
235 HILOG_DEBUG("call");
236 if (CheckParamNum(env, argc, ARGS_TWO, ARGS_THREE) == false) {
237 return CreateJsUndefined(env);
238 }
239
240 int32_t funcPos = 0;
241 std::string bundleName(EMPTY_BUNDLE);
242 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
243 // There are two or more arguments, and the type of argument2 is function.
244 funcPos = PARAM1;
245 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
246 // There are three or more arguments, and the type of argument2 is string.
247 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
248 HILOG_ERROR("invalid secondParam");
249 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
250 return CreateJsUndefined(env);
251 }
252 if (bundleName.empty()) {
253 HILOG_ERROR("empty bundleName");
254 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
255 return CreateJsUndefined(env);
256 }
257 funcPos = PARAM2;
258 } else {
259 HILOG_ERROR("invalid secondParam");
260 NapiFormUtil::ThrowParamTypeError(env, "param 2", "type");
261 return CreateJsUndefined(env);
262 }
263
264 if (!AppExecFwk::IsTypeForNapiValue(env, argv[funcPos], napi_function)) {
265 HILOG_ERROR("invalid lastParam");
266 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<Array<RunningFormInfo>>");
267 return CreateJsUndefined(env);
268 }
269
270 if (formObserver_ == nullptr) {
271 HILOG_ERROR("null formObserver_");
272 formObserver_ = JsFormStateObserver::GetInstance();
273 }
274 JsFormStateObserver::GetInstance()->
275 RegisterFormInstanceCallback(env, argv[funcPos], isVisibility, bundleName, formObserver_);
276 return CreateJsUndefined(env);
277 }
278
OnUnregisterFormIsVisibleObserver(napi_env env,size_t argc,napi_value * argv,bool isVisibility)279 napi_value OnUnregisterFormIsVisibleObserver(napi_env env, size_t argc, napi_value *argv, bool isVisibility)
280 {
281 HILOG_DEBUG("argc is %{public}zu, isVisibility is %{public}d", argc, isVisibility);
282 int32_t funcPos = 0;
283 int32_t bundlePos = 0;
284 if (CheckParamNum(env, argc, ARGS_ONE, ARGS_THREE) == false) {
285 return CreateJsUndefined(env);
286 }
287 std::string bundleName(EMPTY_BUNDLE);
288 if (argc == ARGS_TWO) {
289 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
290 HILOG_DEBUG("The second param is function");
291 funcPos = PARAM1;
292 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
293 bundlePos = PARAM1;
294 } else {
295 NapiFormUtil::ThrowParamTypeError(env, "param 2", "type");
296 return CreateJsUndefined(env);
297 }
298 }
299
300 if (argc == ARGS_THREE) {
301 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)
302 && AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
303 bundlePos = PARAM1;
304 funcPos = PARAM2;
305 } else {
306 NapiFormUtil::ThrowParamTypeError(env, "param 2 or 3", "type");
307 return CreateJsUndefined(env);
308 }
309 }
310
311 if (bundlePos != 0) {
312 if (!ConvertFromJsValue(env, argv[bundlePos], bundleName) || bundleName.empty()) {
313 HILOG_ERROR("Convert bundleName failed.bundleName is %{public}s", bundleName.c_str());
314 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
315 return CreateJsUndefined(env);
316 }
317 }
318
319 if (funcPos != 0) {
320 JsFormStateObserver::GetInstance()->
321 DelFormNotifyVisibleCallbackByBundle(bundleName, isVisibility, argv[funcPos], formObserver_);
322 return CreateJsUndefined(env);
323 }
324 // If there is only one argument.
325 JsFormStateObserver::GetInstance()->
326 ClearFormNotifyVisibleCallbackByBundle(bundleName, isVisibility, formObserver_);
327 return CreateJsUndefined(env);
328 }
329
OnUnregisterFormRemoveObserverWithTwoParams(napi_env env,size_t argc,napi_value * argv)330 napi_value OnUnregisterFormRemoveObserverWithTwoParams(napi_env env, size_t argc, napi_value *argv)
331 {
332 if (argc != ARGS_TWO) {
333 return CreateJsUndefined(env);
334 }
335 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
336 JsFormStateObserver::GetInstance()->DelFormRemoveCallbackByBundle(
337 reinterpret_cast<napi_value>(argv[PARAM1]), "all");
338 return CreateJsUndefined(env);
339 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
340 std::string bundleName;
341 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
342 HILOG_ERROR("Convert bundleName error");
343 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
344 return CreateJsUndefined(env);
345 }
346 JsFormStateObserver::GetInstance()->ClearFormRemoveCallbackByBundle(bundleName);
347 return CreateJsUndefined(env);
348 } else {
349 HILOG_ERROR("The second param is ineffective");
350 NapiFormUtil::ThrowParamTypeError(env, "callback or bundleName",
351 "Callback<formInfo.RunningFormInfo> or string");
352 return CreateJsUndefined(env);
353 }
354 return CreateJsUndefined(env);
355 }
356
OnUnregisterFormRemoveObserverWithThreeParams(napi_env env,size_t argc,napi_value * argv)357 napi_value OnUnregisterFormRemoveObserverWithThreeParams(napi_env env, size_t argc, napi_value *argv)
358 {
359 if (argc != ARGS_THREE) {
360 return CreateJsUndefined(env);
361 }
362 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
363 HILOG_ERROR("The second param is ineffective");
364 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
365 return CreateJsUndefined(env);
366 }
367 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
368 HILOG_ERROR("The third param is ineffective");
369 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
370 return CreateJsUndefined(env);
371 }
372 std::string bundleName;
373 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
374 HILOG_ERROR("Convert bundleName failed");
375 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
376 return CreateJsUndefined(env);
377 }
378 JsFormStateObserver::GetInstance()->DelFormRemoveCallbackByBundle(argv[PARAM2], bundleName);
379 return CreateJsUndefined(env);
380 }
381
OnUnregisterFormRemoveObserver(napi_env env,size_t argc,napi_value * argv)382 napi_value OnUnregisterFormRemoveObserver(napi_env env, size_t argc, napi_value *argv)
383 {
384 HILOG_DEBUG("call");
385 if (CheckParamNum(env, argc, ARGS_ONE, ARGS_THREE) == false) {
386 return CreateJsUndefined(env);
387 }
388
389 if (argc == ARGS_ONE) {
390 // If there is only one argument, all listening will be cancelled.
391 JsFormStateObserver::GetInstance()->ClearFormRemoveCallbackByBundle("all");
392 return CreateJsUndefined(env);
393 } else if (argc == ARGS_TWO) {
394 return OnUnregisterFormRemoveObserverWithTwoParams(env, argc, argv);
395 } else {
396 return OnUnregisterFormRemoveObserverWithThreeParams(env, argc, argv);
397 }
398 return CreateJsUndefined(env);
399 }
400
OnUnregisterFormAddObserverWithTwoParams(napi_env env,size_t argc,napi_value * argv)401 napi_value OnUnregisterFormAddObserverWithTwoParams(napi_env env, size_t argc, napi_value *argv)
402 {
403 if (argc != ARGS_TWO) {
404 return CreateJsUndefined(env);
405 }
406 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
407 JsFormStateObserver::GetInstance()->DelFormAddCallbackByBundle(argv[PARAM1], "all");
408 return CreateJsUndefined(env);
409 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
410 std::string bundleName;
411 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
412 HILOG_ERROR("Convert bundleName failed");
413 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
414 return CreateJsUndefined(env);
415 }
416 JsFormStateObserver::GetInstance()->ClearFormAddCallbackByBundle(bundleName);
417 return CreateJsUndefined(env);
418 } else {
419 HILOG_ERROR("invalid secondParam");
420 NapiFormUtil::ThrowParamTypeError(env, "callback or bundleName",
421 "Callback<formInfo.RunningFormInfo> or string");
422 return CreateJsUndefined(env);
423 }
424 return CreateJsUndefined(env);
425 }
426
OnUnregisterFormAddObserverWithThreeParams(napi_env env,size_t argc,napi_value * argv)427 napi_value OnUnregisterFormAddObserverWithThreeParams(napi_env env, size_t argc, napi_value *argv)
428 {
429 if (argc != ARGS_THREE) {
430 return CreateJsUndefined(env);
431 }
432 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
433 HILOG_ERROR("invalid secondParam");
434 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
435 return CreateJsUndefined(env);
436 }
437 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
438 HILOG_ERROR("invalid thirdParam");
439 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
440 return CreateJsUndefined(env);
441 }
442 std::string bundleName;
443 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
444 HILOG_ERROR("Convert bundleName failed");
445 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
446 return CreateJsUndefined(env);
447 }
448 JsFormStateObserver::GetInstance()->DelFormAddCallbackByBundle(argv[PARAM2], bundleName);
449 return CreateJsUndefined(env);
450 }
451
OnUnregisterFormAddObserver(napi_env env,size_t argc,napi_value * argv)452 napi_value OnUnregisterFormAddObserver(napi_env env, size_t argc, napi_value *argv)
453 {
454 HILOG_DEBUG("call");
455 if (CheckParamNum(env, argc, ARGS_ONE, ARGS_THREE) == false) {
456 return CreateJsUndefined(env);
457 }
458
459 if (argc == ARGS_ONE) {
460 // If there is only one argument, full listening will be cancelled.
461 JsFormStateObserver::GetInstance()->ClearFormAddCallbackByBundle("all");
462 return CreateJsUndefined(env);
463 } else if (argc == ARGS_TWO) {
464 return OnUnregisterFormAddObserverWithTwoParams(env, argc, argv);
465 } else if (argc == ARGS_THREE) {
466 return OnUnregisterFormAddObserverWithThreeParams(env, argc, argv);
467 }
468 return CreateJsUndefined(env);
469 }
470
OnUnregisterFormObserver(napi_env env,size_t argc,napi_value * argv)471 napi_value OnUnregisterFormObserver(napi_env env, size_t argc, napi_value *argv)
472 {
473 HILOG_DEBUG("call");
474 if (!CheckCallerIsSystemApp()) {
475 HILOG_ERROR("The application not system-app, can't use system-api");
476 NapiFormUtil::ThrowByExternalErrorCode(env, AppExecFwk::ERR_FORM_EXTERNAL_NOT_SYSTEM_APP);
477 return CreateJsUndefined(env);
478 }
479
480 // Check the type of the PARAM0 and convert it to string.
481 std::string type;
482 if (!ConvertFromJsValue(env, argv[PARAM0], type)) {
483 HILOG_ERROR("Convert type error");
484 NapiFormUtil::ThrowParamTypeError(env, "type",
485 "formAdd, formRemove, formUninstall, notifyVisible or notifyInvisible.");
486 return CreateJsUndefined(env);
487 }
488
489 if (type == "formAdd") {
490 return OnUnregisterFormAddObserver(env, argc, argv);
491 } else if (type == "formRemove") {
492 return OnUnregisterFormRemoveObserver(env, argc, argv);
493 } else if (type == "notifyVisible") {
494 return OnUnregisterFormIsVisibleObserver(env, argc, argv, true);
495 } else if (type == "notifyInvisible") {
496 return OnUnregisterFormIsVisibleObserver(env, argc, argv, false);
497 } else if (type == "router" || type == "message" || type == "call") {
498 return OnUnregisterClickEventCallback(env, argc, argv, type);
499 } else {
500 HILOG_ERROR("args[0] not formAdd,formRemove,notifyVisible,notifyInvisible,router,message,call");
501 NapiFormUtil::ThrowParamTypeError(env, "type",
502 "args[0] should be formAdd, formRemove,"
503 "notifyVisible, notifyInvisible, router, message, call");
504 return CreateJsUndefined(env);
505 }
506 }
507
ParseGetRunningFormInfosOneParam(const napi_env & env,const napi_value * argv,std::string & bundleName,bool & hasBundleName,bool & isUnusedIncluded)508 bool ParseGetRunningFormInfosOneParam(const napi_env &env, const napi_value *argv, std::string &bundleName,
509 bool &hasBundleName, bool &isUnusedIncluded)
510 {
511 HILOG_DEBUG("call");
512 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_string)) {
513 if (!ConvertFromJsValue(env, argv[PARAM0], bundleName)) {
514 HILOG_ERROR("Convert bundleName failed");
515 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
516 return false;
517 }
518 if (bundleName.empty()) {
519 HILOG_ERROR("empty bundleName");
520 NapiFormUtil::ThrowParamError(env, "bundleName is empty.");
521 return false;
522 }
523 hasBundleName = true;
524 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_boolean)) {
525 if (!ConvertFromJsValue(env, argv[PARAM0], isUnusedIncluded)) {
526 HILOG_ERROR("Convert isUnusedIncluded failed");
527 NapiFormUtil::ThrowParamTypeError(env, "isUnusedIncluded", "bool");
528 return false;
529 }
530 } else {
531 HILOG_ERROR("Input params not string or boolean");
532 NapiFormUtil::ThrowParamTypeError(env, "the first param", "string or boolean");
533 return false;
534 }
535 return true;
536 }
537
ParseGetRunningFormInfosParams(const napi_env & env,const napi_value * argv,std::string & bundleName,bool & isUnusedIncluded,int startPos)538 bool ParseGetRunningFormInfosParams(const napi_env &env, const napi_value *argv, std::string &bundleName,
539 bool &isUnusedIncluded, int startPos)
540 {
541 HILOG_DEBUG("call");
542 if (!ConvertFromJsValue(env, argv[startPos], isUnusedIncluded)) {
543 HILOG_ERROR("Convert isUnusedIncluded failed");
544 NapiFormUtil::ThrowParamTypeError(env, "isUnusedIncluded", "bool");
545 return false;
546 }
547 if (!ConvertFromJsValue(env, argv[startPos + 1], bundleName)) {
548 HILOG_ERROR("Convert bundleName failed");
549 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
550 return false;
551 }
552 return true;
553 }
554
ParseGetRunningFormInfosTwoParams(const napi_env & env,const napi_value * argv,std::string & bundleName,bool & hasBundleName,bool & isUnusedIncluded)555 bool ParseGetRunningFormInfosTwoParams(const napi_env &env, const napi_value *argv, std::string &bundleName,
556 bool &hasBundleName, bool &isUnusedIncluded)
557 {
558 HILOG_DEBUG("call");
559 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_function)) {
560 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
561 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
562 HILOG_ERROR("Convert bundleName failed");
563 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
564 return false;
565 }
566 hasBundleName = true;
567 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_boolean)) {
568 if (!ConvertFromJsValue(env, argv[PARAM1], isUnusedIncluded)) {
569 HILOG_ERROR("Convert isUnusedIncluded failed");
570 NapiFormUtil::ThrowParamTypeError(env, "isUnusedIncluded", "bool");
571 return false;
572 }
573 } else {
574 HILOG_ERROR("Input params not a string or boolean");
575 NapiFormUtil::ThrowParamTypeError(env, "the second param", "string or boolean");
576 return false;
577 }
578 } else {
579 if (!ParseGetRunningFormInfosParams(env, argv, bundleName, isUnusedIncluded, PARAM0)) {
580 return false;
581 }
582 hasBundleName = true;
583 }
584 return true;
585 }
586
OnGetRunningFormInfos(napi_env env,size_t argc,napi_value * argv)587 napi_value OnGetRunningFormInfos(napi_env env, size_t argc, napi_value *argv)
588 {
589 HILOG_DEBUG("call");
590 if (CheckParamNum(env, argc, ARGS_ZERO, ARGS_THREE) == false) {
591 return CreateJsUndefined(env);
592 }
593
594 std::string bundleName("");
595 bool hasBundleName = false;
596 bool isUnusedIncluded = false;
597 if (argc == ARGS_ONE && !AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_function)) {
598 if (!ParseGetRunningFormInfosOneParam(env, argv, bundleName, hasBundleName, isUnusedIncluded)) {
599 return CreateJsUndefined(env);
600 }
601 } else if (argc == ARGS_TWO) {
602 if (!ParseGetRunningFormInfosTwoParams(env, argv, bundleName, hasBundleName, isUnusedIncluded)) {
603 return CreateJsUndefined(env);
604 }
605 } else if (argc == ARGS_THREE) {
606 if (!ParseGetRunningFormInfosParams(env, argv, bundleName, isUnusedIncluded, PARAM1)) {
607 return CreateJsUndefined(env);
608 }
609 hasBundleName = true;
610 }
611
612 auto complete = [hostBundleName = bundleName, isUnusedIncluded, hasBundleName](
613 napi_env env, NapiAsyncTask &task, int32_t status) {
614 std::vector<AppExecFwk::RunningFormInfo> runningFormInfos;
615 auto ret = hasBundleName ? FormMgr::GetInstance().GetRunningFormInfosByBundleName(
616 hostBundleName, isUnusedIncluded, runningFormInfos)
617 : FormMgr::GetInstance().GetRunningFormInfos(isUnusedIncluded, runningFormInfos);
618 if (ret != ERR_OK) {
619 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, ret));
620 return;
621 }
622 task.ResolveWithNoError(env, CreateRunningFormInfos(env, runningFormInfos));
623 };
624 napi_value result = nullptr;
625 napi_value callbackParam =
626 (argc >= ARGS_ONE) &&
627 (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_function)) ? argv[PARAM0] : nullptr;
628 NapiAsyncTask::ScheduleWithDefaultQos("JsFormObserver::OnGetRunningFormInfos", env,
629 CreateAsyncTaskWithLastParam(env, callbackParam, nullptr, std::move(complete), &result));
630 return result;
631 }
632
OnGetFormInstancesByFilter(napi_env env,size_t argc,napi_value * argv)633 napi_value OnGetFormInstancesByFilter(napi_env env, size_t argc, napi_value *argv)
634 {
635 HILOG_DEBUG("call");
636 if (CheckParamNum(env, argc, ARGS_ONE, ARGS_THREE) == false) {
637 return CreateJsUndefined(env);
638 }
639
640 AppExecFwk::FormInstancesFilter filter;
641 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM0], napi_object)) {
642 HILOG_ERROR("Input params not object");
643 NapiFormUtil::ThrowParamTypeError(env, "formProviderFilter", "object");
644 return CreateJsUndefined(env);
645 }
646 if (!ParseParam(env, argv[PARAM0], filter)) {
647 HILOG_ERROR("Input params parse failed");
648 NapiFormUtil::ThrowParamTypeError(env, "formProviderFilter", "object");
649 return CreateJsUndefined(env);
650 }
651 if (argc == ARGS_TWO && !AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
652 HILOG_ERROR("invalid secondParam");
653 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<string>");
654 return CreateJsUndefined(env);
655 }
656 auto formInstances = std::make_shared<std::vector<AppExecFwk::FormInstance>>();
657 auto apiResult = std::make_shared<int32_t>();
658 auto execute = [filter, formInstances, ret = apiResult]() {
659 *ret = FormMgr::GetInstance().GetFormInstancesByFilter(filter, *formInstances);
660 };
661
662 auto complete =
663 [formInstances, ret = apiResult](napi_env env, NapiAsyncTask &task, int32_t status) {
664 if (*ret != ERR_OK) {
665 HILOG_ERROR("Get FormInstances by filter failed");
666 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, *ret));
667 } else {
668 task.ResolveWithNoError(env, CreateFormInstances(env, *formInstances));
669 }
670 };
671 napi_value lastParam = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
672 napi_value result = nullptr;
673 NapiAsyncTask::ScheduleWithDefaultQos("JsFormObserver::OnGetFormInstancesByFilter",
674 env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
675 return result;
676 }
677
OnGetFormInstanceById(napi_env env,size_t argc,napi_value * argv)678 napi_value OnGetFormInstanceById(napi_env env, size_t argc, napi_value *argv)
679 {
680 HILOG_DEBUG("call");
681 if (CheckParamNum(env, argc, ARGS_ONE, ARGS_THREE) == false) {
682 return CreateJsUndefined(env);
683 }
684 decltype(argc) convertArgc = 0;
685 int64_t formId;
686 if (!ConvertFromId(env, argv[PARAM0], formId)) {
687 HILOG_ERROR("Convert strFormIdList failed");
688 NapiFormUtil::ThrowParamTypeError(env, "formId", "string");
689 return CreateJsUndefined(env);
690 }
691 convertArgc++;
692 bool isUnusedIncluded = false;
693 if ((argc == ARGS_TWO || argc == ARGS_THREE) &&
694 !AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
695 if (!ConvertFromJsValue(env, argv[PARAM1], isUnusedIncluded)) {
696 HILOG_ERROR("Convert isUnusedIncluded failed");
697 NapiFormUtil::ThrowParamTypeError(env, "isUnusedIncluded", "bool");
698 return CreateJsUndefined(env);
699 }
700 convertArgc++;
701 }
702 if (argc == ARGS_THREE && !AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
703 HILOG_ERROR("invalid thirdParam");
704 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<string>");
705 return CreateJsUndefined(env);
706 }
707 std::shared_ptr<AppExecFwk::FormInstance> formInstance = std::make_shared<AppExecFwk::FormInstance>();
708 auto apiResult = std::make_shared<int32_t>();
709 auto execute = [formId, isUnusedIncluded, formInstance, ret = apiResult]() {
710 *ret = FormMgr::GetInstance().GetFormInstanceById(formId, isUnusedIncluded, *formInstance);
711 };
712
713 auto complete =
714 [formInstance, ret = apiResult](napi_env env, NapiAsyncTask &task, int32_t status) {
715 if (*ret != ERR_OK) {
716 HILOG_ERROR("Get formInstance by id failed");
717 task.Reject(env, NapiFormUtil::CreateErrorByInternalErrorCode(env, *ret));
718 } else {
719 task.ResolveWithNoError(env, CreateFormInstance(env, *formInstance));
720 }
721 };
722 napi_value lastParam = (argc == convertArgc) ? nullptr : argv[convertArgc];
723 napi_value result = nullptr;
724 NapiAsyncTask::ScheduleWithDefaultQos("JsFormObserver::OnGetFormInstanceById",
725 env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
726 return result;
727 }
728 sptr<JsFormStateObserver> formObserver_ = nullptr;
729
OnRegisterClickEventCallback(napi_env env,size_t argc,napi_value * argv,const std::string & type)730 napi_value OnRegisterClickEventCallback(
731 napi_env env, size_t argc, napi_value *argv, const std::string &type)
732 {
733 HILOG_DEBUG("call");
734 if (argc < ARGS_TWO) {
735 HILOG_ERROR("invalid argc");
736 NapiFormUtil::ThrowParamNumError(env, std::to_string(argc), "2");
737 return CreateJsUndefined(env);
738 }
739 std::string bundleName(EMPTY_BUNDLE);
740 napi_value callFunc = nullptr;
741 if (argc >= ARGS_THREE) {
742 if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
743 HILOG_ERROR("Convert bundleName from js fail");
744 NapiFormUtil::ThrowParamTypeError(env, "bundleName", "string");
745 return CreateJsUndefined(env);
746 }
747 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
748 HILOG_ERROR("invalid thirdParam");
749 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
750 return CreateJsUndefined(env);
751 }
752 callFunc = argv[PARAM2];
753 JsFormStateObserver::GetInstance()->RegisterClickEventCallback(env, bundleName, callFunc, type);
754 return CreateJsUndefined(env);
755 }
756 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
757 HILOG_ERROR("invalid secondParam");
758 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
759 return CreateJsUndefined(env);
760 }
761 callFunc = argv[PARAM1];
762 JsFormStateObserver::GetInstance()->RegisterClickEventCallback(env, bundleName, callFunc, type);
763 return CreateJsUndefined(env);
764 }
765
OnUnregisterClickEventCallback(napi_env env,size_t argc,napi_value * argv,const std::string & type)766 napi_value OnUnregisterClickEventCallback(
767 napi_env env, size_t argc, napi_value *argv, const std::string &type)
768 {
769 HILOG_DEBUG("call");
770 std::string bundleName(EMPTY_BUNDLE);
771 napi_value callback = nullptr;
772 if (argc < ARGS_ONE) {
773 HILOG_ERROR("invalid argc");
774 NapiFormUtil::ThrowParamNumError(env, std::to_string(argc), "1");
775 return CreateJsUndefined(env);
776 }
777 if (argc == ARGS_ONE) {
778 JsFormStateObserver::GetInstance()->ClearFormClickCallbackByBundleName(type, EMPTY_BUNDLE);
779 return CreateJsUndefined(env);
780 }
781 if (argc == ARGS_TWO) {
782 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
783 HILOG_DEBUG("secondParam bundlename not string");
784 JsFormStateObserver::GetInstance()->ClearFormClickCallbackByBundleName(type, EMPTY_BUNDLE);
785 return CreateJsUndefined(env);
786 } else if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
787 HILOG_ERROR("Convert bundleName failed");
788 return CreateJsUndefined(env);
789 }
790 JsFormStateObserver::GetInstance()->ClearFormClickCallbackByBundleName(type, bundleName);
791 return CreateJsUndefined(env);
792 }
793 if (!AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_string)) {
794 HILOG_DEBUG("secondParam bundlename not string");
795 } else if (!ConvertFromJsValue(env, argv[PARAM1], bundleName)) {
796 HILOG_ERROR("Convert bundleName failed");
797 return CreateJsUndefined(env);
798 }
799 if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_null) ||
800 AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_undefined)) {
801 HILOG_DEBUG("null or undefined thirdParam");
802 JsFormStateObserver::GetInstance()->ClearFormClickCallbackByBundleName(type, bundleName);
803 return CreateJsUndefined(env);
804 } else if (AppExecFwk::IsTypeForNapiValue(env, argv[PARAM2], napi_function)) {
805 HILOG_DEBUG("The third param is callback");
806 callback = argv[PARAM2];
807 JsFormStateObserver::GetInstance()->ClearFormClickCallback(type, bundleName, callback);
808 return CreateJsUndefined(env);
809 } else {
810 HILOG_ERROR("invalid thirdParam");
811 NapiFormUtil::ThrowParamTypeError(env, "callback", "Callback<formInfo.RunningFormInfo>");
812 return CreateJsUndefined(env);
813 }
814 return CreateJsUndefined(env);
815 }
816 };
817
JsFormObserverInit(napi_env env,napi_value exportObj)818 napi_value JsFormObserverInit(napi_env env, napi_value exportObj)
819 {
820 HILOG_DEBUG("call");
821 std::unique_ptr<JsFormObserver> jsFormObserver = std::make_unique<JsFormObserver>();
822 napi_wrap(env, exportObj, jsFormObserver.release(), JsFormObserver::Finalizer, nullptr, nullptr);
823
824 const char *moduleName = "JsFormObserver";
825 BindNativeFunction(env, exportObj, "on", moduleName, JsFormObserver::RegisterFormObserver);
826 BindNativeFunction(env, exportObj, "off", moduleName, JsFormObserver::UnregisterFormObserver);
827 BindNativeFunction(env, exportObj, "getRunningFormInfos", moduleName, JsFormObserver::GetRunningFormInfos);
828 BindNativeFunction(env, exportObj, "getRunningFormInfosByFilter", moduleName,
829 JsFormObserver::GetFormInstancesByFilter);
830 BindNativeFunction(env, exportObj, "getRunningFormInfoById", moduleName, JsFormObserver::GetFormInstanceById);
831
832 return CreateJsUndefined(env);
833 }
834 } // namespace AbilityRuntime
835 } // namespace OHOS
836