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