1 /*
2 * Copyright (c) 2023 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_form_state_observer.h"
17
18 #include <regex>
19
20 #include "fms_log_wrapper.h"
21 #include "form_mgr_errors.h"
22 #include "js_runtime_utils.h"
23 #include "napi_common_util.h"
24 #include "napi_form_util.h"
25 #include "napi/native_api.h"
26 #include "napi/native_node_api.h"
27 #include "running_form_info.h"
28
29 namespace OHOS {
30 namespace AbilityRuntime {
31 namespace {
32 constexpr int REF_COUNT = 1;
33 constexpr uint KEY_LIMIT = 16;
34 }
35
36 sptr<JsFormStateObserver> JsFormStateObserver::instance_ = nullptr;
37 std::mutex JsFormStateObserver::mutex_;
38
FormAddCallbackClient(napi_env env,napi_ref callbackRef)39 FormAddCallbackClient::FormAddCallbackClient(napi_env env, napi_ref callbackRef)
40 {
41 env_ = env;
42 callbackRef_ = callbackRef;
43 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
44 }
45
~FormAddCallbackClient()46 FormAddCallbackClient::~FormAddCallbackClient()
47 {
48 napi_delete_reference(env_, callbackRef_);
49 }
50
ProcessFormAdd(const std::string & bundleName,const AppExecFwk::RunningFormInfo & runningFormInfo)51 void FormAddCallbackClient::ProcessFormAdd(const std::string &bundleName,
52 const AppExecFwk::RunningFormInfo &runningFormInfo)
53 {
54 if (handler_ == nullptr) {
55 HILOG_INFO("null handler");
56 return;
57 }
58 handler_->PostSyncTask([thisWeakPtr = weak_from_this(), bundleName, runningFormInfo]() {
59 auto sharedThis = thisWeakPtr.lock();
60 if (sharedThis == nullptr) {
61 HILOG_ERROR("null sharedThis");
62 return;
63 }
64 napi_value callbackValues = nullptr;
65 napi_create_object(sharedThis->env_, &callbackValues);
66 ParseRunningFormInfoIntoNapi(sharedThis->env_, runningFormInfo, callbackValues);
67 napi_value callResult;
68 napi_value myCallback = nullptr;
69 napi_get_reference_value(sharedThis->env_, sharedThis->callbackRef_, &myCallback);
70 if (myCallback != nullptr) {
71 napi_call_function(sharedThis->env_, nullptr, myCallback, ARGS_ONE, &callbackValues, &callResult);
72 }
73 });
74 }
75
IsStrictEqual(napi_value callback)76 bool FormAddCallbackClient::IsStrictEqual(napi_value callback)
77 {
78 bool isEqual = false;
79 napi_value myCallback = nullptr;
80 napi_get_reference_value(env_, callbackRef_, &myCallback);
81 napi_strict_equals(env_, myCallback, callback, &isEqual);
82 HILOG_INFO("isStrictEqual:%{public}d", isEqual);
83 return isEqual;
84 }
85
FormRemoveCallbackClient(napi_env env,napi_ref callbackRef)86 FormRemoveCallbackClient::FormRemoveCallbackClient(napi_env env, napi_ref callbackRef)
87 {
88 env_ = env;
89 callbackRef_ = callbackRef;
90 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
91 }
92
~FormRemoveCallbackClient()93 FormRemoveCallbackClient::~FormRemoveCallbackClient()
94 {
95 napi_delete_reference(env_, callbackRef_);
96 }
97
ProcessFormRemove(const std::string & bundleName,const AppExecFwk::RunningFormInfo & runningFormInfo)98 void FormRemoveCallbackClient::ProcessFormRemove(const std::string &bundleName,
99 const AppExecFwk::RunningFormInfo &runningFormInfo)
100 {
101 if (handler_ == nullptr) {
102 HILOG_INFO("null handler");
103 return;
104 }
105 handler_->PostSyncTask([thisWeakPtr = weak_from_this(), bundleName, runningFormInfo]() {
106 auto sharedThis = thisWeakPtr.lock();
107 if (sharedThis == nullptr) {
108 HILOG_ERROR("null sharedThis");
109 return;
110 }
111 napi_value callbackValues = nullptr;
112 napi_create_object(sharedThis->env_, &callbackValues);
113 ParseRunningFormInfoIntoNapi(sharedThis->env_, runningFormInfo, callbackValues);
114 napi_value callResult;
115 napi_value myCallback = nullptr;
116 napi_get_reference_value(sharedThis->env_, sharedThis->callbackRef_, &myCallback);
117 if (myCallback != nullptr) {
118 napi_call_function(sharedThis->env_, nullptr, myCallback, ARGS_ONE, &callbackValues, &callResult);
119 }
120 });
121 }
122
IsStrictEqual(napi_value callback)123 bool FormRemoveCallbackClient::IsStrictEqual(napi_value callback)
124 {
125 bool isEqual = false;
126 napi_value myCallback = nullptr;
127 napi_get_reference_value(env_, callbackRef_, &myCallback);
128 napi_strict_equals(env_, myCallback, callback, &isEqual);
129 HILOG_INFO("isStrictEqual:%{public}d", isEqual);
130 return isEqual;
131 }
132
GetInstance()133 sptr<JsFormStateObserver> JsFormStateObserver::GetInstance()
134 {
135 if (instance_ == nullptr) {
136 std::lock_guard<std::mutex> lock(mutex_);
137 if (instance_ == nullptr) {
138 instance_ = new (std::nothrow) JsFormStateObserver();
139 if (instance_ == nullptr) {
140 HILOG_ERROR("create JsFormStateObserver failed");
141 }
142 }
143 }
144 return instance_;
145 }
146
CheckMapSize(const std::string & type,const std::string & bundleName)147 bool JsFormStateObserver::CheckMapSize(const std::string &type, const std::string &bundleName)
148 {
149 HILOG_DEBUG("start");
150 if (type == "formAdd") {
151 std::lock_guard<std::mutex> lock(addFormCallbackMutex_);
152 if (formAddCallbackMap_.find(bundleName) == formAddCallbackMap_.end()) {
153 if (formAddCallbackMap_.size() >= KEY_LIMIT) {
154 HILOG_ERROR("the number of the bundleName exceeds the limit");
155 return false;
156 }
157 }
158 } else if (type == "formRemove") {
159 std::lock_guard<std::mutex> lock(removeFormCallbackMutex_);
160 if (formRemoveCallbackMap_.find(bundleName) == formRemoveCallbackMap_.end()) {
161 if (formRemoveCallbackMap_.size() >= KEY_LIMIT) {
162 HILOG_ERROR("the number of the bundleName exceeds the limit");
163 return false;
164 }
165 }
166 } else {
167 return false;
168 }
169 return true;
170 }
171
RegisterFormAddCallback(const napi_env env,const std::string & bundleName,const napi_value callback)172 bool JsFormStateObserver::RegisterFormAddCallback(const napi_env env,
173 const std::string &bundleName, const napi_value callback)
174 {
175 HILOG_DEBUG("start");
176 napi_ref callbackRef;
177 napi_create_reference(env, callback, REF_COUNT, &callbackRef);
178 std::shared_ptr<FormAddCallbackClient> callbackClient = std::make_shared<FormAddCallbackClient>(env,
179 callbackRef);
180
181 std::lock_guard<std::mutex> lock(addFormCallbackMutex_);
182 auto formAddCallbacks = formAddCallbackMap_.find(bundleName);
183 if (formAddCallbacks == formAddCallbackMap_.end()) {
184 std::vector<std::shared_ptr<FormAddCallbackClient>> callbacks;
185 callbacks.emplace_back(callbackClient);
186 formAddCallbackMap_.emplace(bundleName, callbacks);
187 return true;
188 } else {
189 auto &callbacks = formAddCallbacks->second;
190 for (auto &iter : callbacks) {
191 if (iter->IsStrictEqual(callback)) {
192 HILOG_ERROR("found equal callback");
193 return false;
194 }
195 }
196 formAddCallbacks->second.emplace_back(callbackClient);
197 return true;
198 }
199 }
200
RegisterFormRemoveCallback(const napi_env env,const std::string & bundleName,const napi_value callback)201 bool JsFormStateObserver::RegisterFormRemoveCallback(const napi_env env,
202 const std::string &bundleName, const napi_value callback)
203 {
204 HILOG_DEBUG("start");
205 napi_ref callbackRef;
206 napi_create_reference(env, callback, REF_COUNT, &callbackRef);
207 std::shared_ptr<FormRemoveCallbackClient> callbackClient =
208 std::make_shared<FormRemoveCallbackClient>(env, callbackRef);
209
210 std::lock_guard<std::mutex> lock(removeFormCallbackMutex_);
211 auto formRemoveCallbacks = formRemoveCallbackMap_.find(bundleName);
212 if (formRemoveCallbacks == formRemoveCallbackMap_.end()) {
213 std::vector<std::shared_ptr<FormRemoveCallbackClient>> callbacks;
214 callbacks.emplace_back(callbackClient);
215 formRemoveCallbackMap_.emplace(bundleName, callbacks);
216 return true;
217 } else {
218 auto &callbacks = formRemoveCallbacks->second;
219 for (auto &iter : callbacks) {
220 if (iter->IsStrictEqual(callback)) {
221 HILOG_ERROR("found equal callback");
222 return false;
223 }
224 }
225 formRemoveCallbacks->second.emplace_back(callbackClient);
226 return true;
227 }
228 }
229
ClearFormAddCallbackByBundle(const std::string & bundleName)230 void JsFormStateObserver::ClearFormAddCallbackByBundle(const std::string &bundleName)
231 {
232 HILOG_DEBUG("start");
233 std::lock_guard<std::mutex> lock(addFormCallbackMutex_);
234 auto formAddCallbacks = formAddCallbackMap_.find(bundleName);
235 if (formAddCallbacks == formAddCallbackMap_.end()) {
236 HILOG_INFO("No formAddCallback register");
237 } else {
238 auto &callbacks = formAddCallbacks->second;
239 callbacks.clear();
240 formAddCallbackMap_.erase(formAddCallbacks);
241 }
242 }
243
DelFormAddCallbackByBundle(const napi_value callback,const std::string & bundleName)244 void JsFormStateObserver::DelFormAddCallbackByBundle(const napi_value callback, const std::string &bundleName)
245 {
246 HILOG_DEBUG("start");
247
248 std::lock_guard<std::mutex> lock(addFormCallbackMutex_);
249 auto formAddCallbacks = formAddCallbackMap_.find(bundleName);
250 if (formAddCallbacks == formAddCallbackMap_.end()) {
251 HILOG_INFO("no formAddCallback registered with this bundleName");
252 } else {
253 auto &callbacks = formAddCallbacks->second;
254 auto iter = std::find_if(callbacks.begin(), callbacks.end(), [&](const auto &cb) {
255 return cb->IsStrictEqual(callback);
256 });
257 if (iter != callbacks.end()) {
258 HILOG_INFO("equal callback");
259 callbacks.erase(iter);
260 } else {
261 HILOG_INFO("no formAddCallback");
262 }
263 }
264 }
265
OnAddForm(const std::string & bundleName,const AppExecFwk::RunningFormInfo & runningFormInfo)266 int32_t JsFormStateObserver::OnAddForm(const std::string &bundleName,
267 const AppExecFwk::RunningFormInfo &runningFormInfo)
268 {
269 HILOG_DEBUG("call");
270
271 std::lock_guard<std::mutex> lock(addFormCallbackMutex_);
272 auto callbackClient = formAddCallbackMap_.find(bundleName);
273 if (callbackClient != formAddCallbackMap_.end()) {
274 for (auto iter : callbackClient->second) {
275 iter->ProcessFormAdd(bundleName, runningFormInfo);
276 }
277 }
278 return ERR_OK;
279 }
280
ClearFormRemoveCallbackByBundle(const std::string & bundleName)281 void JsFormStateObserver::ClearFormRemoveCallbackByBundle(const std::string &bundleName)
282 {
283 HILOG_DEBUG("start");
284 std::lock_guard<std::mutex> lock(removeFormCallbackMutex_);
285 auto formRemoveCallbacks = formRemoveCallbackMap_.find(bundleName);
286 if (formRemoveCallbacks == formRemoveCallbackMap_.end()) {
287 HILOG_INFO("no formRemoveCallback register");
288 } else {
289 auto &callbacks = formRemoveCallbacks->second;
290 callbacks.clear();
291 formRemoveCallbackMap_.erase(formRemoveCallbacks);
292 }
293 }
294
DelFormRemoveCallbackByBundle(const napi_value callback,const std::string & bundleName)295 void JsFormStateObserver::DelFormRemoveCallbackByBundle(const napi_value callback, const std::string &bundleName)
296 {
297 HILOG_DEBUG("start");
298
299 std::lock_guard<std::mutex> lock(removeFormCallbackMutex_);
300 auto formRemoveCallbacks = formRemoveCallbackMap_.find(bundleName);
301 if (formRemoveCallbacks == formRemoveCallbackMap_.end()) {
302 HILOG_INFO("no formRemoveCallback registered with this bundleName");
303 } else {
304 auto &callbacks = formRemoveCallbacks->second;
305 auto iter = std::find_if(callbacks.begin(), callbacks.end(), [&](const auto &cb) {
306 return cb->IsStrictEqual(callback);
307 });
308 if (iter != callbacks.end()) {
309 HILOG_INFO("equal callback");
310 callbacks.erase(iter);
311 } else {
312 HILOG_INFO("no formRemoveCallback");
313 }
314 }
315 }
316
OnRemoveForm(const std::string & bundleName,const AppExecFwk::RunningFormInfo & runningFormInfo)317 int32_t JsFormStateObserver::OnRemoveForm(const std::string &bundleName,
318 const AppExecFwk::RunningFormInfo &runningFormInfo)
319 {
320 HILOG_DEBUG("call");
321
322 std::lock_guard<std::mutex> lock(removeFormCallbackMutex_);
323 auto callbackClient = formRemoveCallbackMap_.find(bundleName);
324 if (callbackClient != formRemoveCallbackMap_.end()) {
325 for (auto iter : callbackClient->second) {
326 iter->ProcessFormRemove(bundleName, runningFormInfo);
327 }
328 }
329 return ERR_OK;
330 }
331
RegisterFormInstanceCallback(napi_env env,napi_value jsObserverObject,bool isVisibility,std::string & bundleName,sptr<JsFormStateObserver> & formObserver)332 int JsFormStateObserver::RegisterFormInstanceCallback(napi_env env, napi_value jsObserverObject,
333 bool isVisibility, std::string &bundleName, sptr<JsFormStateObserver> &formObserver)
334 {
335 HILOG_DEBUG("call");
336 if (env_ == nullptr) {
337 env_ = env;
338 }
339 std::string specialFlag = "#";
340 std::lock_guard<std::mutex> lock(formIsvisibleCallbackMutex_);
341 napi_ref ref = nullptr;
342 if (isVisibility) {
343 auto visibleCallback = formVisibleCallbackMap_.find(bundleName);
344 if (visibleCallback != formVisibleCallbackMap_.end()) {
345 HILOG_ERROR("bundleName is already in the map,bundleName id %{public}s", bundleName.c_str());
346 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
347 }
348 napi_create_reference(env, jsObserverObject, 1, &ref);
349 formVisibleCallbackMap_.emplace(
350 bundleName, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
351 } else {
352 auto invisibleCallback = formInvisibleCallbackMap_.find(bundleName);
353 if (invisibleCallback != formInvisibleCallbackMap_.end()) {
354 HILOG_ERROR("bundleName is already in the map,bundleName id %{public}s", bundleName.c_str());
355 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
356 }
357 napi_create_reference(env, jsObserverObject, 1, &ref);
358 formInvisibleCallbackMap_.emplace(
359 bundleName, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference *>(ref)));
360 }
361 AppExecFwk::FormMgr::GetInstance().RegisterAddObserver(bundleName + specialFlag + std::to_string(isVisibility),
362 formObserver);
363 return ERR_OK;
364 }
365
ClearFormNotifyVisibleCallbackByBundle(const std::string bundleName,bool isVisibility,sptr<JsFormStateObserver> & formObserver)366 ErrCode JsFormStateObserver::ClearFormNotifyVisibleCallbackByBundle(const std::string bundleName,
367 bool isVisibility, sptr<JsFormStateObserver> &formObserver)
368 {
369 HILOG_DEBUG("call");
370 std::lock_guard<std::mutex> lock(formIsvisibleCallbackMutex_);
371 std::string specialFlag = "#";
372 if (isVisibility) {
373 auto visibleCallback = formVisibleCallbackMap_.find(bundleName);
374 if (visibleCallback != formVisibleCallbackMap_.end()) {
375 AppExecFwk::FormMgr::GetInstance().RegisterRemoveObserver(
376 bundleName + specialFlag + std::to_string(isVisibility), formObserver);
377 formVisibleCallbackMap_.erase(visibleCallback);
378 return ERR_OK;
379 } else {
380 HILOG_ERROR("There is no formVisibleCallbackMap_ has been register");
381 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
382 }
383 } else {
384 auto invisibleCallback = formInvisibleCallbackMap_.find(bundleName);
385 if (invisibleCallback != formInvisibleCallbackMap_.end()) {
386 AppExecFwk::FormMgr::GetInstance().RegisterRemoveObserver(
387 bundleName + specialFlag + std::to_string(isVisibility), formObserver);
388 formInvisibleCallbackMap_.erase(invisibleCallback);
389 return ERR_OK;
390 } else {
391 HILOG_ERROR("There is no formInvisibleCallbackMap_ has been register");
392 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
393 }
394 }
395 }
396
DelFormNotifyVisibleCallbackByBundle(const std::string bundleName,bool isVisibility,napi_value jsObserverObject,sptr<JsFormStateObserver> & formObserver)397 ErrCode JsFormStateObserver::DelFormNotifyVisibleCallbackByBundle(const std::string bundleName,
398 bool isVisibility, napi_value jsObserverObject, sptr<JsFormStateObserver> &formObserver)
399 {
400 HILOG_DEBUG("call");
401 std::lock_guard<std::mutex> lock(formIsvisibleCallbackMutex_);
402 std::string specialFlag = "#";
403 if (isVisibility) {
404 auto visibleCallback = formVisibleCallbackMap_.find(bundleName);
405 if (visibleCallback != formVisibleCallbackMap_.end()) {
406 napi_value value = visibleCallback->second->GetNapiValue();
407 bool isEqual = false;
408 napi_strict_equals(env_, value, jsObserverObject, &isEqual);
409 if (isEqual) {
410 AppExecFwk::FormMgr::GetInstance().RegisterRemoveObserver(
411 bundleName + specialFlag + std::to_string(isVisibility), formObserver);
412 formVisibleCallbackMap_.erase(visibleCallback);
413 return ERR_OK;
414 } else {
415 HILOG_ERROR("There is no formVisibleCallbackMap_ has been register");
416 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
417 }
418 } else {
419 HILOG_ERROR("There is no formVisibleCallbackMap_ has been register");
420 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
421 }
422 } else {
423 auto invisibleCallback = formInvisibleCallbackMap_.find(bundleName);
424 if (invisibleCallback != formInvisibleCallbackMap_.end()) {
425 napi_value value = invisibleCallback->second->GetNapiValue();
426 bool isEqual = false;
427 napi_strict_equals(env_, value, jsObserverObject, &isEqual);
428 if (isEqual) {
429 AppExecFwk::FormMgr::GetInstance().RegisterRemoveObserver(
430 bundleName + specialFlag + std::to_string(isVisibility), formObserver);
431 formInvisibleCallbackMap_.erase(invisibleCallback);
432 return ERR_OK;
433 } else {
434 HILOG_ERROR("There is no formInvisibleCallbackMap_ has been register");
435 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
436 }
437 } else {
438 HILOG_ERROR("There is no formInvisibleCallbackMap_ has been register");
439 return ERR_APPEXECFWK_FORM_GET_BUNDLE_FAILED;
440 }
441 }
442 }
443
NotifyWhetherFormsVisible(const AppExecFwk::FormVisibilityType visibleType,const std::string & bundleName,std::vector<AppExecFwk::FormInstance> & formInstances)444 int32_t JsFormStateObserver::NotifyWhetherFormsVisible(const AppExecFwk::FormVisibilityType visibleType,
445 const std::string &bundleName, std::vector<AppExecFwk::FormInstance> &formInstances)
446 {
447 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
448 HILOG_DEBUG("call");
449 std::lock_guard<std::mutex> lock(formIsvisibleCallbackMutex_);
450 if (handler_) {
451 wptr<JsFormStateObserver> weakObserver = this;
452 handler_->PostSyncTask([weakObserver, visibleType, formInstances, bundleName]() {
453 std::string specialFlag = "#";
454 bool isVisibleTypeFlag = false;
455 auto sharedThis = weakObserver.promote();
456 if (sharedThis == nullptr) {
457 HILOG_ERROR("null sharedThis");
458 return;
459 }
460 napi_handle_scope scope = nullptr;
461 napi_open_handle_scope(sharedThis->env_, &scope);
462 if (scope == nullptr) {
463 HILOG_ERROR("null scope");
464 return;
465 }
466 if (visibleType == AppExecFwk::FormVisibilityType::VISIBLE) {
467 isVisibleTypeFlag = true;
468 if (bundleName.find((specialFlag + std::to_string(isVisibleTypeFlag))) != std::string::npos) {
469 std::string bundleNameNew =
470 std::regex_replace(bundleName, std::regex(specialFlag + std::to_string(isVisibleTypeFlag)), "");
471 auto visibleCallback = sharedThis->formVisibleCallbackMap_.find(bundleNameNew);
472 if (visibleCallback != sharedThis->formVisibleCallbackMap_.end()) {
473 napi_value res = visibleCallback->second->GetNapiValue();
474 napi_value argv[] = { CreateFormInstances(sharedThis->env_, formInstances) };
475 napi_call_function(sharedThis->env_, res, res, sizeof(argv) / sizeof(argv[0]), argv, nullptr);
476 }
477 }
478 } else {
479 isVisibleTypeFlag = false;
480 if (bundleName.find((specialFlag + std::to_string(isVisibleTypeFlag))) != std::string::npos) {
481 std::string bundleNameNew =
482 std::regex_replace(bundleName, std::regex(specialFlag + std::to_string(isVisibleTypeFlag)), "");
483 auto invisibleCallback = sharedThis->formInvisibleCallbackMap_.find(bundleNameNew);
484 if (invisibleCallback != sharedThis->formInvisibleCallbackMap_.end()) {
485 napi_value res = invisibleCallback->second->GetNapiValue();
486 napi_value argv[] = { CreateFormInstances(sharedThis->env_, formInstances) };
487 napi_call_function(sharedThis->env_, res, res, sizeof(argv) / sizeof(argv[0]), argv, nullptr);
488 }
489 }
490 }
491 napi_close_handle_scope(sharedThis->env_, scope);
492 });
493 }
494 return ERR_OK;
495 }
496
OnFormClickEvent(const std::string & bundleName,const std::string & callType,const AppExecFwk::RunningFormInfo & runningFormInfo)497 ErrCode JsFormStateObserver::OnFormClickEvent(
498 const std::string &bundleName, const std::string &callType, const AppExecFwk::RunningFormInfo &runningFormInfo)
499 {
500 HILOG_DEBUG("call");
501 if (callType.empty()) {
502 HILOG_ERROR("empty Calltype");
503 return ERR_INVALID_VALUE;
504 }
505 if (handler_ == nullptr) {
506 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
507 if (handler_ == nullptr) {
508 HILOG_ERROR("null Handler");
509 return ERR_INVALID_VALUE;
510 }
511 }
512
513 wptr<JsFormStateObserver> weakObserver = this;
514 auto notify = [bundleName, callType, runningFormInfo, weakObserver]() {
515 auto self = weakObserver.promote();
516 if (self == nullptr) {
517 HILOG_ERROR("null Self");
518 return;
519 }
520 std::unique_lock<std::mutex> lock(self->formEventMapMutex_);
521 auto formEventCallbackListIter = self->formEventMap_.find(bundleName);
522 if (formEventCallbackListIter != self->formEventMap_.end()) {
523 auto &callbackListVec = formEventCallbackListIter->second;
524 auto callBackListIter = std::find_if(callbackListVec.begin(), callbackListVec.end(),
525 [bundleName, callType](auto &iter) {
526 return iter != nullptr &&
527 iter->BindFormEventType() == callType &&
528 iter->BindHostBundleName() == bundleName;
529 });
530 if (callBackListIter != callbackListVec.end() && (*callBackListIter) != nullptr) {
531 (*callBackListIter)->HandleFormEvent(runningFormInfo);
532 }
533 }
534 };
535
536 handler_->PostSyncTask(notify);
537 return ERR_OK;
538 }
539
RegisterClickEventCallback(const napi_env env,const std::string & bundleName,const napi_value callback,const std::string & type)540 ErrCode JsFormStateObserver::RegisterClickEventCallback(
541 const napi_env env, const std::string &bundleName, const napi_value callback, const std::string &type)
542 {
543 HILOG_DEBUG("call");
544 auto record = std::make_shared<FormEventCallbackList>(bundleName, type, env);
545 if (record == nullptr) {
546 HILOG_ERROR("New obj error");
547 return ERR_INVALID_VALUE;
548 }
549 record->PushCallback(callback);
550
551 std::unique_lock<std::mutex> lock(formEventMapMutex_);
552
553 auto formEventCallbackListIter = formEventMap_.find(bundleName);
554 if (formEventCallbackListIter == formEventMap_.end()) {
555 std::vector<std::shared_ptr<FormEventCallbackList>> formEventCallbackListVector {record};
556 formEventMap_.emplace(bundleName, formEventCallbackListVector);
557 AppExecFwk::FormMgr::GetInstance().RegisterClickEventObserver(
558 bundleName, type, JsFormStateObserver::GetInstance());
559 return ERR_OK;
560 }
561
562 auto &callbackListVec = formEventCallbackListIter->second;
563 auto callBackListIter = std::find_if(
564 callbackListVec.begin(), callbackListVec.end(), [bundleName, type](auto &iter) {
565 return iter != nullptr && iter->BindFormEventType() == type && iter->BindHostBundleName() == bundleName;
566 });
567 if (callBackListIter != callbackListVec.end() && (*callBackListIter) != nullptr) {
568 (*callBackListIter)->PushCallback(callback);
569 return ERR_OK;
570 }
571
572 formEventCallbackListIter->second.emplace_back(record);
573 AppExecFwk::FormMgr::GetInstance().RegisterClickEventObserver(bundleName, type, JsFormStateObserver::GetInstance());
574 return ERR_OK;
575 }
576
ClearFormClickCallbackByBundleName(const std::string & type,const std::string & bundleName)577 ErrCode JsFormStateObserver::ClearFormClickCallbackByBundleName(const std::string &type, const std::string &bundleName)
578 {
579 HILOG_DEBUG("call");
580 std::unique_lock<std::mutex> lock(formEventMapMutex_);
581 auto formEventCallbackListIter = formEventMap_.find(bundleName);
582 if (formEventCallbackListIter == formEventMap_.end()) {
583 HILOG_ERROR("Invalid bundleName");
584 return ERR_INVALID_VALUE;
585 }
586
587 auto &callbackListVec = formEventCallbackListIter->second;
588 auto callBackListIter = std::find_if(
589 callbackListVec.begin(), callbackListVec.end(), [bundleName, type](auto &iter) {
590 return iter != nullptr && iter->BindFormEventType() == type && iter->BindHostBundleName() == bundleName;
591 });
592 if (callBackListIter == callbackListVec.end()) {
593 HILOG_ERROR("This bundle hasn't registered any callback of this type");
594 return ERR_INVALID_VALUE;
595 }
596 callbackListVec.erase(callBackListIter);
597 AppExecFwk::FormMgr::GetInstance().UnregisterClickEventObserver(
598 bundleName, type, JsFormStateObserver::GetInstance());
599 return ERR_OK;
600 }
601
ClearFormClickCallback(const std::string & type,const std::string & bundleName,const napi_value & callback)602 ErrCode JsFormStateObserver::ClearFormClickCallback(
603 const std::string &type, const std::string &bundleName, const napi_value &callback)
604 {
605 HILOG_DEBUG("call");
606 std::unique_lock<std::mutex> lock(formEventMapMutex_);
607 auto formEventCallbackListIter = formEventMap_.find(bundleName);
608 if (formEventCallbackListIter == formEventMap_.end()) {
609 HILOG_ERROR("Invalid bundleName");
610 return ERR_INVALID_VALUE;
611 }
612
613 auto &callbackListVec = formEventCallbackListIter->second;
614 auto callBackListIter = std::find_if(
615 callbackListVec.begin(), callbackListVec.end(), [bundleName, type](auto &iter) {
616 return iter != nullptr && iter->BindFormEventType() == type && iter->BindHostBundleName() == bundleName;
617 });
618 if (callBackListIter == callbackListVec.end()) {
619 HILOG_ERROR("This bundle hasn't registered any callback of this type");
620 return ERR_INVALID_VALUE;
621 }
622
623 auto sharedItem = *callBackListIter;
624 if (sharedItem == nullptr) {
625 HILOG_ERROR("Holding empty objects");
626 return ERR_INVALID_VALUE;
627 }
628
629 sharedItem->RemoveCallback(callback);
630 if (sharedItem->IsEmpty()) {
631 callbackListVec.erase(callBackListIter);
632 // Need to notify fms
633 AppExecFwk::FormMgr::GetInstance().UnregisterClickEventObserver(
634 bundleName, type, JsFormStateObserver::GetInstance());
635 }
636 return ERR_OK;
637 }
638
~FormEventCallbackList()639 FormEventCallbackList::~FormEventCallbackList()
640 {
641 for (auto &iter : callbacks_) {
642 napi_delete_reference(env_, iter);
643 }
644 }
645
ContainEqualCallback(napi_value callback) const646 bool FormEventCallbackList::ContainEqualCallback(napi_value callback) const
647 {
648 HILOG_DEBUG("call");
649 if (env_ == nullptr) {
650 HILOG_ERROR("null env");
651 return false;
652 }
653 bool ref = false;
654 napi_value compareCallback = nullptr;
655 for (auto &call : callbacks_) {
656 napi_get_reference_value(env_, call, &compareCallback);
657 napi_strict_equals(env_, compareCallback, callback, &ref);
658 if (ref) {
659 return ref;
660 }
661 }
662 return ref;
663 }
664
PushCallback(napi_value call)665 void FormEventCallbackList::PushCallback(napi_value call)
666 {
667 HILOG_DEBUG("call");
668 if (env_ == nullptr) {
669 HILOG_ERROR("null env");
670 return;
671 }
672 if (!ContainEqualCallback(call)) {
673 napi_ref callbackRef;
674 napi_create_reference(env_, call, REF_COUNT, &callbackRef);
675 if (callbackRef != nullptr) {
676 callbacks_.emplace_back(callbackRef);
677 }
678 }
679 }
680
RemoveCallback(napi_value call)681 void FormEventCallbackList::RemoveCallback(napi_value call)
682 {
683 HILOG_DEBUG("call");
684 if (env_ == nullptr) {
685 HILOG_ERROR("null env");
686 return;
687 }
688 auto iter = std::find_if(callbacks_.begin(), callbacks_.end(), [env = env_, callback = call](auto &item) {
689 bool equal = false;
690 napi_value callbackFun = nullptr;
691 napi_get_reference_value(env, item, &callbackFun);
692 if (callbackFun != nullptr) {
693 napi_strict_equals(env, callbackFun, callback, &equal);
694 }
695 return equal;
696 });
697 if (iter != callbacks_.end()) {
698 napi_delete_reference(env_, *iter);
699 callbacks_.erase(iter);
700 }
701 }
702
HandleFormEvent(const AppExecFwk::RunningFormInfo & runningFormInfo) const703 void FormEventCallbackList::HandleFormEvent(const AppExecFwk::RunningFormInfo &runningFormInfo) const
704 {
705 HILOG_DEBUG("call");
706 if (env_ == nullptr) {
707 HILOG_ERROR("null env");
708 return;
709 }
710 napi_value formInfo = nullptr;
711 napi_create_object(env_, &formInfo);
712 ParseRunningFormInfoIntoNapi(env_, runningFormInfo, formInfo);
713 napi_value callResult;
714 napi_value callbackfun = nullptr;
715 for (auto &iter : callbacks_) {
716 napi_get_reference_value(env_, iter, &callbackfun);
717 if (callbackfun != nullptr) {
718 napi_call_function(env_, nullptr, callbackfun, ARGS_ONE, &formInfo, &callResult);
719 }
720 }
721 }
722 } // namespace AbilityRuntime
723 } // namespace OHOS
724