• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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