1 /*
2 * Copyright (c) 2022-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_event_target.h"
17
18 #include "devicestatus_define.h"
19 #include "devicestatus_errors.h"
20 #include "interaction_manager.h"
21 #include "napi_constants.h"
22 #include "util_napi_error.h"
23 #include "utility.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "JsEventTarget"
27
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace {
32 std::recursive_mutex mutex_;
33 inline constexpr std::string_view CREATE_PROMISE { "napi_create_promise" };
34 inline constexpr std::string_view GET_UNDEFINED { "napi_get_undefined" };
35 inline constexpr std::string_view RESOLVE_DEFERRED { "napi_resolve_deferred" };
36 inline constexpr std::string_view REJECT_DEFERRED { "napi_reject_deferred" };
37 } // namespace
38
JsEventTarget()39 JsEventTarget::JsEventTarget()
40 {
41 CALL_DEBUG_ENTER;
42 auto ret = coordinationListeners_.insert({ COOPERATE_NAME, std::vector<sptr<JsUtil::CallbackInfo>>() });
43 if (!ret.second) {
44 FI_HILOGW("Failed to insert, errCode:%{public}d", static_cast<int32_t>(DeviceStatus::VAL_NOT_EXP));
45 }
46 }
47
EmitJsPrepare(sptr<JsUtil::CallbackInfo> cb,const std::string & networkId,const CoordinationMsgInfo & msgInfo)48 void JsEventTarget::EmitJsPrepare(sptr<JsUtil::CallbackInfo> cb, const std::string &networkId,
49 const CoordinationMsgInfo &msgInfo)
50 {
51 CALL_INFO_TRACE;
52 CHKPV(cb);
53 CHKPV(cb->env);
54 cb->data.prepareResult = (msgInfo.msg == CoordinationMessage::PREPARE ||
55 msgInfo.msg == CoordinationMessage::UNPREPARE);
56 cb->data.msgInfo = msgInfo;
57
58 auto task = [cb]() {
59 FI_HILOGI("Execute lambda");
60 if (cb->ref == nullptr) {
61 CallPreparePromiseWork(cb);
62 } else {
63 CallPrepareAsyncWork(cb);
64 }
65 };
66 if (napi_status::napi_ok != napi_send_event(cb->env, task, napi_eprio_immediate)) {
67 FI_HILOGE("Failed to SendEvent");
68 }
69 }
70
EmitJsActivate(sptr<JsUtil::CallbackInfo> cb,const std::string & remoteNetworkId,const CoordinationMsgInfo & msgInfo)71 void JsEventTarget::EmitJsActivate(sptr<JsUtil::CallbackInfo> cb, const std::string &remoteNetworkId,
72 const CoordinationMsgInfo &msgInfo)
73 {
74 CALL_INFO_TRACE;
75 CHKPV(cb);
76 CHKPV(cb->env);
77 cb->data.activateResult = (msgInfo.msg == CoordinationMessage::ACTIVATE_SUCCESS);
78 cb->data.msgInfo = msgInfo;
79
80 auto task = [cb]() {
81 FI_HILOGI("Execute lambda");
82 if (cb->ref == nullptr) {
83 CallActivatePromiseWork(cb);
84 } else {
85 CallActivateAsyncWork(cb);
86 }
87 };
88 if (napi_status::napi_ok != napi_send_event(cb->env, task, napi_eprio_immediate)) {
89 FI_HILOGE("Failed to SendEvent");
90 }
91 }
92
EmitJsDeactivate(sptr<JsUtil::CallbackInfo> cb,const std::string & networkId,const CoordinationMsgInfo & msgInfo)93 void JsEventTarget::EmitJsDeactivate(sptr<JsUtil::CallbackInfo> cb, const std::string &networkId,
94 const CoordinationMsgInfo &msgInfo)
95 {
96 CALL_INFO_TRACE;
97 CHKPV(cb);
98 CHKPV(cb->env);
99 cb->data.deactivateResult = (msgInfo.msg == CoordinationMessage::DEACTIVATE_SUCCESS);
100 cb->data.msgInfo = msgInfo;
101
102 auto task = [cb]() {
103 FI_HILOGI("Execute lambda");
104 if (cb->ref == nullptr) {
105 CallDeactivatePromiseWork(cb);
106 } else {
107 CallDeactivateAsyncWork(cb);
108 }
109 };
110 if (napi_status::napi_ok != napi_send_event(cb->env, task, napi_eprio_immediate)) {
111 FI_HILOGE("Failed to SendEvent");
112 }
113 }
114
EmitJsGetCrossingSwitchState(sptr<JsUtil::CallbackInfo> cb,bool state)115 void JsEventTarget::EmitJsGetCrossingSwitchState(sptr<JsUtil::CallbackInfo> cb, bool state)
116 {
117 CALL_INFO_TRACE;
118 CHKPV(cb);
119 CHKPV(cb->env);
120 cb->data.coordinationOpened = state;
121
122 auto task = [cb]() {
123 FI_HILOGI("Execute lambda");
124 if (cb->ref == nullptr) {
125 CallGetCrossingSwitchStatePromiseWork(cb);
126 } else {
127 CallGetCrossingSwitchStateAsyncWork(cb);
128 }
129 };
130 if (napi_status::napi_ok != napi_send_event(cb->env, task, napi_eprio_immediate)) {
131 FI_HILOGE("Failed to SendEvent");
132 }
133 }
134
AddListener(napi_env env,const std::string & type,napi_value handle)135 void JsEventTarget::AddListener(napi_env env, const std::string &type, napi_value handle)
136 {
137 CALL_INFO_TRACE;
138 std::string listenerType = type;
139 bool isCompatible = false;
140 if (type == COOPERATE_MESSAGE_NAME) {
141 isCompatible = true;
142 listenerType = COOPERATE_NAME;
143 }
144 napi_ref ref = nullptr;
145 {
146 std::lock_guard<std::recursive_mutex> guard(mutex_);
147 auto iter = coordinationListeners_.find(listenerType);
148 if (iter == coordinationListeners_.end()) {
149 FI_HILOGE("Not exist %{public}s", listenerType.c_str());
150 return;
151 }
152 for (const auto &item : iter->second) {
153 CHKPC(item);
154 if (JsUtil::IsSameHandle(env, handle, item->ref)) {
155 FI_HILOGE("The handle already exists");
156 return;
157 }
158 }
159 CHKRV(napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
160 sptr<JsUtil::CallbackInfo> monitor = new (std::nothrow) JsUtil::CallbackInfo();
161 if (monitor == nullptr) {
162 FI_HILOGE("Null monitor, release callback");
163 RELEASE_CALLBACKINFO(env, ref);
164 return;
165 }
166 monitor->env = env;
167 monitor->ref = ref;
168 monitor->data.type = type;
169 iter->second.push_back(monitor);
170 }
171 if (!isListeningProcess_) {
172 if (int32_t errCode = INTERACTION_MGR->RegisterCoordinationListener(shared_from_this(), isCompatible);
173 errCode != RET_OK) {
174 FI_HILOGE("RegisterEventListener failed, ret:%{public}d", errCode);
175 {
176 std::lock_guard<std::recursive_mutex> guard(mutex_);
177 if (auto iter = coordinationListeners_.find(listenerType); iter != coordinationListeners_.end()) {
178 iter->second.pop_back();
179 }
180 }
181 RELEASE_CALLBACKINFO(env, ref);
182 UtilNapiError::HandleExecuteResult(env, errCode, "on", COOPERATE_PERMISSION);
183 } else {
184 isListeningProcess_ = true;
185 }
186 }
187 }
188
RemoveListener(napi_env env,const std::string & type,napi_value handle)189 void JsEventTarget::RemoveListener(napi_env env, const std::string &type, napi_value handle)
190 {
191 CALL_INFO_TRACE;
192 std::string listenerType = type;
193 bool isCompatible = false;
194 bool shouldUnregister = false;
195 if (type == COOPERATE_MESSAGE_NAME) {
196 isCompatible = true;
197 listenerType = COOPERATE_NAME;
198 }
199 {
200 std::lock_guard<std::recursive_mutex> guard(mutex_);
201 auto iter = coordinationListeners_.find(listenerType);
202 if (iter == coordinationListeners_.end()) {
203 FI_HILOGE("Not exist %{public}s", listenerType.c_str());
204 return;
205 }
206 if (handle == nullptr) {
207 iter->second.clear();
208 shouldUnregister = true;
209 } else {
210 for (auto it = iter->second.begin(); it != iter->second.end();) {
211 if (!JsUtil::IsSameHandle(env, handle, (*it)->ref)) {
212 ++it;
213 continue;
214 }
215 it = iter->second.erase(it);
216 if (iter->second.empty()) {
217 shouldUnregister = true;
218 }
219 break;
220 }
221 }
222 }
223 if (shouldUnregister && isListeningProcess_) {
224 int32_t errCode = INTERACTION_MGR->UnregisterCoordinationListener(shared_from_this(), isCompatible);
225 if (errCode == RET_OK) {
226 isListeningProcess_ = false;
227 } else {
228 UtilNapiError::HandleExecuteResult(env, errCode, "off", COOPERATE_PERMISSION);
229 }
230 }
231 }
232
AddListener(napi_env env,const std::string & type,const std::string & networkId,napi_value handle)233 void JsEventTarget::AddListener(napi_env env, const std::string &type, const std::string &networkId, napi_value handle)
234 {
235 CALL_INFO_TRACE;
236 napi_ref ref = nullptr;
237 {
238 std::lock_guard<std::recursive_mutex> guard(mutex_);
239 if (IsHandleExist(env, networkId, handle)) {
240 FI_HILOGE("Current handle for networkId:%{public}s already exists", Utility::Anonymize(networkId).c_str());
241 return;
242 }
243 CHKRV(napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
244 sptr<JsUtil::MouseCallbackInfo> monitor = new (std::nothrow) JsUtil::MouseCallbackInfo();
245 if (monitor == nullptr) {
246 FI_HILOGE("Null monitor, release callback");
247 RELEASE_CALLBACKINFO(env, ref);
248 return;
249 }
250 monitor->env = env;
251 monitor->ref = ref;
252 monitor->data.networkId = networkId;
253 mouseLocationListeners_[networkId].push_back(monitor);
254 }
255 if (int32_t errCode = INTERACTION_MGR->RegisterEventListener(networkId, shared_from_this());
256 errCode != RET_OK) {
257 FI_HILOGE("RegisterEventListener for networkId:%{public}s failed, ret:%{public}d",
258 Utility::Anonymize(networkId).c_str(), errCode);
259 {
260 std::lock_guard<std::recursive_mutex> guard(mutex_);
261 if (auto iter = mouseLocationListeners_.find(networkId); iter != mouseLocationListeners_.end()) {
262 iter->second.pop_back();
263 }
264 }
265 RELEASE_CALLBACKINFO(env, ref);
266 UtilNapiError::HandleExecuteResult(env, errCode, "on", COOPERATE_PERMISSION);
267 }
268 }
269
RemoveListener(napi_env env,const std::string & type,const std::string & networkId,napi_value handle)270 void JsEventTarget::RemoveListener(napi_env env, const std::string &type, const std::string &networkId,
271 napi_value handle)
272 {
273 {
274 std::lock_guard<std::recursive_mutex> guard(mutex_);
275 if (mouseLocationListeners_.find(networkId) == mouseLocationListeners_.end()) {
276 FI_HILOGE("Not listener for networkId:%{public}s exists", Utility::Anonymize(networkId).c_str());
277 return;
278 }
279 if (handle == nullptr) {
280 FI_HILOGI("Remove all listener for networkId:%{public}s", Utility::Anonymize(networkId).c_str());
281 mouseLocationListeners_.erase(networkId);
282 } else {
283 for (auto iter = mouseLocationListeners_[networkId].begin();
284 iter != mouseLocationListeners_[networkId].end();) {
285 if (JsUtil::IsSameHandle(env, handle, (*iter)->ref)) {
286 iter = mouseLocationListeners_[networkId].erase(iter);
287 break;
288 } else {
289 ++iter;
290 }
291 }
292 }
293 if (mouseLocationListeners_.find(networkId) != mouseLocationListeners_.end() &&
294 mouseLocationListeners_[networkId].empty()) {
295 mouseLocationListeners_.erase(networkId);
296 }
297 }
298 if (int32_t errCode = INTERACTION_MGR->UnregisterEventListener(networkId, shared_from_this());
299 errCode != RET_OK) {
300 FI_HILOGE("UnregisterEventListener for networkId:%{public}s failed, ret:%{public}d",
301 Utility::Anonymize(networkId).c_str(), errCode);
302 UtilNapiError::HandleExecuteResult(env, errCode, "off", COOPERATE_PERMISSION);
303 }
304 }
305
CreateCallbackInfo(napi_env env,napi_value handle,sptr<JsUtil::CallbackInfo> callback)306 napi_value JsEventTarget::CreateCallbackInfo(napi_env env, napi_value handle, sptr<JsUtil::CallbackInfo> callback)
307 {
308 CALL_INFO_TRACE;
309 CHKPP(callback);
310 callback->env = env;
311 napi_value napiPromise = nullptr;
312 if (handle == nullptr) {
313 CHKRP(napi_create_promise(env, &callback->deferred, &napiPromise), CREATE_PROMISE);
314 } else {
315 CHKRP(napi_create_reference(env, handle, 1, &callback->ref), CREATE_REFERENCE);
316 }
317 return napiPromise;
318 }
319
CreateMouseCallbackInfo(napi_env env,napi_value handle,sptr<JsUtil::MouseCallbackInfo> callback)320 napi_value JsEventTarget::CreateMouseCallbackInfo(napi_env env, napi_value handle,
321 sptr<JsUtil::MouseCallbackInfo> callback)
322 {
323 CALL_INFO_TRACE;
324 CHKPP(callback);
325 callback->env = env;
326 napi_value napiPromise = nullptr;
327 if (handle == nullptr) {
328 CHKRP(napi_create_promise(env, &callback->deferred, &napiPromise), CREATE_PROMISE);
329 } else {
330 CHKRP(napi_create_reference(env, handle, 1, &callback->ref), CREATE_REFERENCE);
331 }
332 return napiPromise;
333 }
334
ResetEnv()335 void JsEventTarget::ResetEnv()
336 {
337 CALL_INFO_TRACE;
338 INTERACTION_MGR->UnregisterCoordinationListener(shared_from_this());
339 }
340
OnCoordinationMessage(const std::string & networkId,CoordinationMessage msg)341 void JsEventTarget::OnCoordinationMessage(const std::string &networkId, CoordinationMessage msg)
342 {
343 CALL_INFO_TRACE;
344 std::vector<sptr<JsUtil::CallbackInfo>> dumpedChangeEvent;
345 {
346 std::lock_guard<std::recursive_mutex> guard(mutex_);
347 auto changeEvent = coordinationListeners_.find(COOPERATE_NAME);
348 if (changeEvent == coordinationListeners_.end()) {
349 FI_HILOGE("Find %{public}s failed", std::string(COOPERATE_NAME).c_str());
350 return;
351 }
352 dumpedChangeEvent = changeEvent->second;
353 }
354
355 for (auto &item : dumpedChangeEvent) {
356 CHKPC(item);
357 CHKPC(item->env);
358 CoordinationEvent ev {
359 .networkId = networkId,
360 .msg = msg
361 };
362 eventQueue_.push(ev);
363
364 auto task = [item]() {
365 FI_HILOGI("Execute lamdba");
366 EmitCoordinationMessageEvent(item);
367 };
368 if (napi_status::napi_ok != napi_send_event(item->env, task, napi_eprio_immediate)) {
369 FI_HILOGE("Failed to SendEvent");
370 eventQueue_.pop();
371 }
372 }
373 }
374
OnMouseLocationEvent(const std::string & networkId,const Event & event)375 void JsEventTarget::OnMouseLocationEvent(const std::string &networkId, const Event &event)
376 {
377 CALL_DEBUG_ENTER;
378 std::vector<sptr<JsUtil::MouseCallbackInfo>> dumpedMouseListeners;
379 {
380 std::lock_guard<std::recursive_mutex> guard(mutex_);
381 if (mouseLocationListeners_.find(networkId) == mouseLocationListeners_.end()) {
382 FI_HILOGE("Find listener for %{public}s failed", Utility::Anonymize(networkId).c_str());
383 return;
384 }
385 dumpedMouseListeners = mouseLocationListeners_[networkId];
386 }
387
388 for (auto &item : dumpedMouseListeners) {
389 CHKPC(item);
390 CHKPC(item->env);
391 item->data.networkId = networkId;
392 item->data.displayX = event.displayX;
393 item->data.displayY = event.displayY;
394 item->data.displayWidth = event.displayWidth;
395 item->data.displayHeight = event.displayHeight;
396 auto task = [item]() {
397 FI_HILOGI("Execute lamdba");
398 EmitMouseLocationEvent(item);
399 };
400 if (napi_status::napi_ok != napi_send_event(item->env, task, napi_eprio_immediate)) {
401 FI_HILOGE("Failed to SendEvent");
402 }
403 }
404 }
405
CallPreparePromiseWork(sptr<JsUtil::CallbackInfo> cb)406 void JsEventTarget::CallPreparePromiseWork(sptr<JsUtil::CallbackInfo> cb)
407 {
408 CALL_INFO_TRACE;
409 if (cb == nullptr) {
410 FI_HILOGE("Prepare promise, check data is nullptr");
411 return;
412 }
413 CHKPV(cb->env);
414 napi_handle_scope handleScope = nullptr;
415 napi_open_handle_scope(cb->env, &handleScope);
416 if (handleScope == nullptr) {
417 FI_HILOGE("Prepare promise, handleScope is nullptr");
418 RELEASE_CALLBACKINFO(cb->env, cb->ref);
419 return;
420 }
421 napi_value object = JsUtil::GetPrepareInfo(cb);
422 if (object == nullptr) {
423 FI_HILOGE("Prepare promise, object is nullptr");
424 RELEASE_CALLBACKINFO(cb->env, cb->ref);
425 napi_close_handle_scope(cb->env, handleScope);
426 return;
427 }
428 napi_valuetype napiValueType = napi_undefined;
429 if (napi_typeof(cb->env, object, &napiValueType) != napi_ok) {
430 FI_HILOGE("Prepare promise, napi typeof failed");
431 RELEASE_CALLBACKINFO(cb->env, cb->ref);
432 napi_close_handle_scope(cb->env, handleScope);
433 return;
434 }
435 if (napiValueType != napi_undefined) {
436 CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, object), REJECT_DEFERRED, handleScope);
437 } else {
438 CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, handleScope);
439 }
440 RELEASE_CALLBACKINFO(cb->env, cb->ref);
441 napi_close_handle_scope(cb->env, handleScope);
442 }
443
CallPrepareAsyncWork(sptr<JsUtil::CallbackInfo> cb)444 void JsEventTarget::CallPrepareAsyncWork(sptr<JsUtil::CallbackInfo> cb)
445 {
446 CALL_INFO_TRACE;
447 if (cb == nullptr) {
448 FI_HILOGE("Prepare async, check data is nullptr");
449 return;
450 }
451 CHKPV(cb->env);
452 napi_handle_scope scope = nullptr;
453 napi_open_handle_scope(cb->env, &scope);
454 if (scope == nullptr) {
455 FI_HILOGE("Prepare async, scope is nullptr");
456 RELEASE_CALLBACKINFO(cb->env, cb->ref);
457 return;
458 }
459 napi_value object = JsUtil::GetPrepareInfo(cb);
460 if (object == nullptr) {
461 FI_HILOGE("Prepare async, object is nullptr");
462 RELEASE_CALLBACKINFO(cb->env, cb->ref);
463 napi_close_handle_scope(cb->env, scope);
464 return;
465 }
466 napi_value processor = nullptr;
467 CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &processor), GET_REFERENCE_VALUE, scope);
468 napi_value result = nullptr;
469 CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, processor, 1, &object, &result), CALL_FUNCTION, scope);
470 RELEASE_CALLBACKINFO(cb->env, cb->ref);
471 napi_close_handle_scope(cb->env, scope);
472 }
473
CallActivatePromiseWork(sptr<JsUtil::CallbackInfo> cb)474 void JsEventTarget::CallActivatePromiseWork(sptr<JsUtil::CallbackInfo> cb)
475 {
476 CALL_INFO_TRACE;
477 if (cb == nullptr) {
478 FI_HILOGE("Activate promise, check data is nullptr");
479 return;
480 }
481 CHKPV(cb->env);
482 napi_handle_scope handleScope = nullptr;
483 napi_open_handle_scope(cb->env, &handleScope);
484 if (handleScope == nullptr) {
485 FI_HILOGE("Activate promise, handleScope is nullptr");
486 RELEASE_CALLBACKINFO(cb->env, cb->ref);
487 return;
488 }
489 napi_value napiObject = JsUtil::GetActivateInfo(cb);
490 if (napiObject == nullptr) {
491 FI_HILOGE("Activate promise, napiObject is nullptr");
492 RELEASE_CALLBACKINFO(cb->env, cb->ref);
493 napi_close_handle_scope(cb->env, handleScope);
494 return;
495 }
496 napi_valuetype valueType = napi_undefined;
497 if (napi_typeof(cb->env, napiObject, &valueType) != napi_ok) {
498 FI_HILOGE("Activate promise, napi typeof failed");
499 RELEASE_CALLBACKINFO(cb->env, cb->ref);
500 napi_close_handle_scope(cb->env, handleScope);
501 return;
502 }
503 if (valueType != napi_undefined) {
504 CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, napiObject), REJECT_DEFERRED, handleScope);
505 } else {
506 CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, napiObject), RESOLVE_DEFERRED, handleScope);
507 }
508 RELEASE_CALLBACKINFO(cb->env, cb->ref);
509 napi_close_handle_scope(cb->env, handleScope);
510 }
511
CallActivateAsyncWork(sptr<JsUtil::CallbackInfo> cb)512 void JsEventTarget::CallActivateAsyncWork(sptr<JsUtil::CallbackInfo> cb)
513 {
514 CALL_INFO_TRACE;
515 if (cb == nullptr) {
516 FI_HILOGE("Activate async, check data is nullptr");
517 return;
518 }
519 CHKPV(cb->env);
520 napi_handle_scope scope = nullptr;
521 napi_open_handle_scope(cb->env, &scope);
522 if (scope == nullptr) {
523 FI_HILOGE("Activate async, scope is nullptr");
524 RELEASE_CALLBACKINFO(cb->env, cb->ref);
525 return;
526 }
527 napi_value object = JsUtil::GetActivateInfo(cb);
528 if (object == nullptr) {
529 FI_HILOGE("Activate async, object is nullptr");
530 RELEASE_CALLBACKINFO(cb->env, cb->ref);
531 napi_close_handle_scope(cb->env, scope);
532 return;
533 }
534 napi_value handler = nullptr;
535 CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
536 napi_value ret = nullptr;
537 CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 1, &object, &ret), CALL_FUNCTION, scope);
538 RELEASE_CALLBACKINFO(cb->env, cb->ref);
539 napi_close_handle_scope(cb->env, scope);
540 }
541
CallDeactivatePromiseWork(sptr<JsUtil::CallbackInfo> cb)542 void JsEventTarget::CallDeactivatePromiseWork(sptr<JsUtil::CallbackInfo> cb)
543 {
544 CALL_INFO_TRACE;
545 if (cb == nullptr) {
546 FI_HILOGE("Deactivate promise, check data is nullptr");
547 return;
548 }
549 CHKPV(cb->env);
550 napi_handle_scope handleScope = nullptr;
551 napi_open_handle_scope(cb->env, &handleScope);
552 if (handleScope == nullptr) {
553 FI_HILOGE("Deactivate promise, handleScope is nullptr");
554 RELEASE_CALLBACKINFO(cb->env, cb->ref);
555 return;
556 }
557 napi_value object = JsUtil::GetDeactivateInfo(cb);
558 if (object == nullptr) {
559 FI_HILOGE("Deactivate promise, object is nullptr");
560 RELEASE_CALLBACKINFO(cb->env, cb->ref);
561 napi_close_handle_scope(cb->env, handleScope);
562 return;
563 }
564
565 napi_valuetype valueType = napi_undefined;
566 if (napi_typeof(cb->env, object, &valueType) != napi_ok) {
567 FI_HILOGE("Deactivate promise, napi typeof failed");
568 RELEASE_CALLBACKINFO(cb->env, cb->ref);
569 napi_close_handle_scope(cb->env, handleScope);
570 return;
571 }
572 if (valueType != napi_undefined) {
573 CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, object), REJECT_DEFERRED, handleScope);
574 } else {
575 CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, handleScope);
576 }
577 RELEASE_CALLBACKINFO(cb->env, cb->ref);
578 napi_close_handle_scope(cb->env, handleScope);
579 }
580
CallDeactivateAsyncWork(sptr<JsUtil::CallbackInfo> cb)581 void JsEventTarget::CallDeactivateAsyncWork(sptr<JsUtil::CallbackInfo> cb)
582 {
583 CALL_INFO_TRACE;
584 if (cb == nullptr) {
585 FI_HILOGE("Deactivate async, check data is nullptr");
586 return;
587 }
588 CHKPV(cb->env);
589 napi_handle_scope scope = nullptr;
590 napi_open_handle_scope(cb->env, &scope);
591 if (scope == nullptr) {
592 FI_HILOGE("Deactivate async, scope is nullptr");
593 RELEASE_CALLBACKINFO(cb->env, cb->ref);
594 return;
595 }
596 napi_value object = JsUtil::GetDeactivateInfo(cb);
597 if (object == nullptr) {
598 FI_HILOGE("Deactivate async, object is nullptr");
599 RELEASE_CALLBACKINFO(cb->env, cb->ref);
600 napi_close_handle_scope(cb->env, scope);
601 return;
602 }
603 napi_value handler = nullptr;
604 CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
605 napi_value result = nullptr;
606 CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 1, &object, &result), CALL_FUNCTION, scope);
607 RELEASE_CALLBACKINFO(cb->env, cb->ref);
608 napi_close_handle_scope(cb->env, scope);
609 }
610
CallGetCrossingSwitchStatePromiseWork(sptr<JsUtil::CallbackInfo> cb)611 void JsEventTarget::CallGetCrossingSwitchStatePromiseWork(sptr<JsUtil::CallbackInfo> cb)
612 {
613 CALL_INFO_TRACE;
614 if (cb == nullptr) {
615 FI_HILOGE("Switch state, check data is nullptr");
616 return;
617 }
618 CHKPV(cb->env);
619 napi_handle_scope scope = nullptr;
620 napi_open_handle_scope(cb->env, &scope);
621 if (scope == nullptr) {
622 FI_HILOGE("Switch state, scope is nullptr");
623 RELEASE_CALLBACKINFO(cb->env, cb->ref);
624 return;
625 }
626 napi_value state = JsUtil::GetCrossingSwitchStateInfo(cb);
627 if (state == nullptr) {
628 FI_HILOGE("Switch state, state is nullptr");
629 RELEASE_CALLBACKINFO(cb->env, cb->ref);
630 napi_close_handle_scope(cb->env, scope);
631 return;
632 }
633 CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, state), RESOLVE_DEFERRED, scope);
634 RELEASE_CALLBACKINFO(cb->env, cb->ref);
635 napi_close_handle_scope(cb->env, scope);
636 }
637
CallGetCrossingSwitchStateAsyncWork(sptr<JsUtil::CallbackInfo> cb)638 void JsEventTarget::CallGetCrossingSwitchStateAsyncWork(sptr<JsUtil::CallbackInfo> cb)
639 {
640 CALL_INFO_TRACE;
641 if (cb == nullptr) {
642 FI_HILOGE("Switch state asyn, check data is nullptr");
643 return;
644 }
645 CHKPV(cb->env);
646 napi_handle_scope scope = nullptr;
647 napi_open_handle_scope(cb->env, &scope);
648 if (scope == nullptr) {
649 FI_HILOGE("The scope is nullptr");
650 RELEASE_CALLBACKINFO(cb->env, cb->ref);
651 return;
652 }
653 napi_value resultObj[2];
654 CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &resultObj[0]), GET_UNDEFINED, scope);
655 resultObj[1] = JsUtil::GetCrossingSwitchStateInfo(cb);
656 if (resultObj[1] == nullptr) {
657 FI_HILOGE("The object is nullptr");
658 napi_close_handle_scope(cb->env, scope);
659 return;
660 }
661 napi_value handler = nullptr;
662 CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
663 napi_value result = nullptr;
664 size_t argc = TWO_PARAM;
665 CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, argc, resultObj, &result),
666 CALL_FUNCTION, scope);
667 RELEASE_CALLBACKINFO(cb->env, cb->ref);
668 napi_close_handle_scope(cb->env, scope);
669 }
670
EmitCoordinationMessageEvent(sptr<JsUtil::CallbackInfo> cb)671 void JsEventTarget::EmitCoordinationMessageEvent(sptr<JsUtil::CallbackInfo> cb)
672 {
673 CALL_INFO_TRACE;
674 if (cb == nullptr) {
675 FI_HILOGE("Emit coordination message event, check data is nullptr");
676 return;
677 }
678 std::vector<sptr<JsUtil::CallbackInfo>> dumpedMessageEvent;
679 {
680 std::lock_guard<std::recursive_mutex> guard(mutex_);
681 auto messageEvent = coordinationListeners_.find(COOPERATE_NAME);
682 if (messageEvent == coordinationListeners_.end()) {
683 FI_HILOGE("Not exist messageEvent");
684 return;
685 }
686 dumpedMessageEvent = messageEvent->second;
687 }
688 while (!eventQueue_.empty()) {
689 auto event = eventQueue_.front();
690 eventQueue_.pop();
691 for (const auto &item : dumpedMessageEvent) {
692 CHKPC(item->env);
693 if (item->ref != cb->ref) {
694 continue;
695 }
696 napi_handle_scope scope = nullptr;
697 napi_open_handle_scope(item->env, &scope);
698 napi_value deviceDescriptor = nullptr;
699 CHKRV_SCOPE(item->env, napi_create_string_utf8(item->env, event.networkId.c_str(),
700 NAPI_AUTO_LENGTH, &deviceDescriptor), CREATE_STRING_UTF8, scope);
701 napi_value eventMsg = nullptr;
702 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(event.msg), &eventMsg),
703 CREATE_INT32, scope);
704 napi_value object = nullptr;
705 CHKRV_SCOPE(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
706 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "networkId", deviceDescriptor),
707 SET_NAMED_PROPERTY, scope);
708 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object,
709 ((item->data.type == COOPERATE_MESSAGE_NAME) ? "state" : "msg"), eventMsg),
710 SET_NAMED_PROPERTY, scope);
711 napi_value handler = nullptr;
712 CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler),
713 GET_REFERENCE_VALUE, scope);
714 napi_value ret = nullptr;
715 CHKRV_SCOPE(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret),
716 CALL_FUNCTION, scope);
717 napi_close_handle_scope(item->env, scope);
718 }
719 }
720 }
721
EmitMouseLocationEvent(sptr<JsUtil::MouseCallbackInfo> cb)722 void JsEventTarget::EmitMouseLocationEvent(sptr<JsUtil::MouseCallbackInfo> cb)
723 {
724 CALL_DEBUG_ENTER;
725 if (cb == nullptr) {
726 FI_HILOGE("Emit mouse location event, check data is nullptr");
727 return;
728 }
729 std::vector<sptr<JsUtil::MouseCallbackInfo>> dumpedMouseListeners;
730 {
731 std::lock_guard<std::recursive_mutex> guard(mutex_);
732 auto mouseLocationEvent = mouseLocationListeners_.find(cb->data.networkId);
733 if (mouseLocationEvent == mouseLocationListeners_.end()) {
734 FI_HILOGE("Not exist mouseLocationEvent");
735 return;
736 }
737 dumpedMouseListeners = mouseLocationEvent->second;
738 }
739 for (const auto &item : dumpedMouseListeners) {
740 if (item->env == nullptr) {
741 FI_HILOGW("Item->env is nullptr, skip then continue");
742 continue;
743 }
744 if (item->ref != cb->ref) {
745 continue;
746 }
747 napi_handle_scope scope = nullptr;
748 napi_open_handle_scope(item->env, &scope);
749
750 napi_value displayX = nullptr;
751 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(item->data.displayX), &displayX),
752 CREATE_INT32, scope);
753 napi_value displayY = nullptr;
754 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(item->data.displayY), &displayY),
755 CREATE_INT32, scope);
756 napi_value displayWidth = nullptr;
757 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(item->data.displayWidth),
758 &displayWidth), CREATE_INT32, scope);
759 napi_value displayHeight = nullptr;
760 CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(item->data.displayHeight),
761 &displayHeight), CREATE_INT32, scope);
762
763 napi_value object = nullptr;
764 CHKRV_SCOPE(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
765 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "displayX", displayX),
766 SET_NAMED_PROPERTY, scope);
767 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "displayY", displayY),
768 SET_NAMED_PROPERTY, scope);
769 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "displayWidth", displayWidth),
770 SET_NAMED_PROPERTY, scope);
771 CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "displayHeight", displayHeight),
772 SET_NAMED_PROPERTY, scope);
773
774 napi_value handler = nullptr;
775 CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE_VALUE, scope);
776 napi_value ret = nullptr;
777 CHKRV_SCOPE(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret), CALL_FUNCTION, scope);
778 napi_close_handle_scope(item->env, scope);
779 }
780 }
781
IsHandleExist(napi_env env,const std::string & networkId,napi_value handle)782 bool JsEventTarget::IsHandleExist(napi_env env, const std::string &networkId, napi_value handle)
783 {
784 if (mouseLocationListeners_.find(networkId) == mouseLocationListeners_.end()) {
785 FI_HILOGW("No handle of networkId:%{public}s exists", Utility::Anonymize(networkId).c_str());
786 return false;
787 }
788 for (const auto &item : mouseLocationListeners_[networkId]) {
789 CHKPC(item);
790 if (JsUtil::IsSameHandle(env, handle, item->ref)) {
791 FI_HILOGE("The handle already exists");
792 return true;
793 }
794 }
795 return false;
796 }
797
798 } // namespace DeviceStatus
799 } // namespace Msdp
800 } // namespace OHOS
801