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